Diagram navigation#
This section presents navigation in an operator diagram, which means how to find the sources of an diagram block (the blocks that are connected to its inputs) and the targets (the blocks that are connected to its outputs).
The section starts giving the basic methods to move through a diagram and finishes by a simple navigation between two objects using these methods.
The QuadFlightControl
example is used. To setup the example see
QuadFlightControl example setup code.
The operator is first retrieved from the module:
def quad_fight_control_op_filter(obj: swan.GlobalDeclaration):
if isinstance(obj, swan.Operator):
return str(obj.id) == "QuadFlightControl"
return False
# Get the 'QuadFightControl' operator from model
quad_fight_control_op = cast(swan.Operator, model.find_declaration(quad_fight_control_op_filter))
Diagram block#
The operator’s diagram block can be accessed with the ansys.scadeone.core.swan.Operator.diagrams
property.
diag = next(quad_fight_control_op.diagrams, None)
From the MotorControl diagram block, one can get the list of diagram objects (blocks, wires, etc.) and the connections between them (sources or targets). The figure below presents those blocks for the example:

Diagram objects#
To get the source and target objects, one need to get the diagram objects using the
ansys.scadeone.core.swan.Diagram.objects
property. One can filter by ansys.scadeone.core.swan.Block
to get the blocks list.
blocks = list(filter(lambda obj: isinstance(obj, swan.Block), diag.objects))
Sources and targets#
Using the MotorControl diagram block, one can get the operator’s sources using the
ansys.scadeone.core.swan.DiagramObject.sources
property:
# Get the 'MotorControl' block
motor_control_block = next(
filter(lambda block: block.instance.path_id.as_string == "MotorControl", blocks)
)
# Get the 'MotorControl' sources ('FlightControl', 'motorStates')
sources = motor_control_block.sources
One can also get the operator’s targets using the
ansys.scadeone.core.swan.DiagramObject.targets
property:
# Get the 'MotorControl' targets ('motorHealthState', 'rotorCmd', 'byname' group)
targets = motor_control_block.targets
Navigate from Input to Output#
One can navigate inside the MotorControl operator selecting a starting and an ending point. One take attitudeCmd input as starting point and one navigate through the wires to get the blocks on the route until one arrive at the ending point, rotorCmd.

First, one get the attitudeCmd input with its fields.
def input_filter(obj: swan.DiagramObject):
if not isinstance(obj, swan.ExprBlock):
return False
if not isinstance(obj.expr, swan.StructProjection):
return False
return str(obj.expr.expr) == "attitudeCmd"
# Get the 'attitudeCmd' fields from the diagram (expression blocks)
attitude_cmd_fields = list(filter(lambda obj: input_filter(obj), diag.objects))
Once one have the input, one can move to the next object diagram using
the ansys.scadeone.core.swan.DiagramObject.targets
property.
For each object diagram target, one can move to the
next object, and so on until one arrive at the output. For each move, one can save the navigated object.
def contains_output(objs):
return next(filter(lambda obj: isinstance(obj, swan.DefBlock), objs), None) is not None
# Get the blocks following the flows from the 'attitudeCmd' input to the 'rotorCmd' output
blocks = set()
while not contains_output(attitude_cmd_fields):
targets = set()
for obj in attitude_cmd_fields:
for target in obj.targets:
targets.add(target[0])
if isinstance(target[0], swan.Block):
blocks.add(target[0])
attitude_cmd_fields = targets
Complete example#
This is the complete script for the diagram navigation section, with print of results.
# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from pathlib import Path
from typing import cast
from ansys.scadeone.core.scadeone import ScadeOne
import ansys.scadeone.core.swan as swan
# Update according to your installation
s_one_install = Path(r"C:\Scade One")
quad_flight_project = (
s_one_install / "examples/QuadFlightControl/QuadFlightControl" / "QuadFlightControl.sproj"
)
app = ScadeOne(install_dir=s_one_install)
model = app.load_project(quad_flight_project).model
def quad_fight_control_op_filter(obj: swan.GlobalDeclaration):
if isinstance(obj, swan.Operator):
return str(obj.id) == "QuadFlightControl"
return False
# Get the 'QuadFightControl' operator from model
quad_fight_control_op = cast(swan.Operator, model.find_declaration(quad_fight_control_op_filter))
# Get the diagram of the 'QuadFightControl' operator
diag = next(quad_fight_control_op.diagrams, None)
# Get the diagram blocks ('MotorControl', 'FlightControl')
blocks = list(filter(lambda obj: isinstance(obj, swan.Block), diag.objects))
# Get the 'MotorControl' block
motor_control_block = next(
filter(lambda block: block.instance.path_id.as_string == "MotorControl", blocks)
)
# Get the 'MotorControl' sources ('FlightControl', 'motorStates')
sources = motor_control_block.sources
# Get the 'MotorControl' targets ('motorHealthState', 'rotorCmd', 'byname' group)
targets = motor_control_block.targets
print("The object diagram sources of 'MotorControl' operator are:")
print("-----------------------------------")
message = "Operator name: {block}, Adaptation: {src} => {dst}"
for block, from_adapt, to_adapt_list in sources:
src = str(from_adapt)
dst = ", ".join(str(adapt) for adapt in to_adapt_list)
if isinstance(block, swan.ExprBlock):
print(message.format(block=str(block.expr), src=src, dst=dst))
elif isinstance(block, swan.Block):
print(message.format(block=str(block.instance.path_id), src=str(from_adapt), dst=dst))
print("-----------------------------------")
print("")
print("The object diagram targets of 'MotorControl' operator are:")
print("-----------------------------------")
for block, from_adapt, to_adapt in targets:
if isinstance(block, swan.DefBlock):
print(message.format(block=str(block.lhs), src=str(from_adapt), dst=str(to_adapt)))
elif isinstance(block, swan.Bar):
print(
message.format(block=str(block.operation.name), src=str(from_adapt), dst=str(to_adapt))
)
print("-----------------------------------")
def motor_control_op_filter(obj: swan.GlobalDeclaration):
if isinstance(obj, swan.Operator):
return str(obj.id) == "MotorControl"
return False
# Get the 'MotorControl' operator from model
motor_control_op = cast(swan.Operator, model.find_declaration(motor_control_op_filter))
# Get the diagram of the 'MotorControl' operator
diag = next(motor_control_op.diagrams, None)
def input_filter(obj: swan.DiagramObject):
if not isinstance(obj, swan.ExprBlock):
return False
if not isinstance(obj.expr, swan.StructProjection):
return False
return str(obj.expr.expr) == "attitudeCmd"
# Get the 'attitudeCmd' fields from the diagram (expression blocks)
attitude_cmd_fields = list(filter(lambda obj: input_filter(obj), diag.objects))
def contains_output(objs):
return next(filter(lambda obj: isinstance(obj, swan.DefBlock), objs), None) is not None
# Get the blocks following the flows from the 'attitudeCmd' input to the 'rotorCmd' output
blocks = set()
while not contains_output(attitude_cmd_fields):
targets = set()
for obj in attitude_cmd_fields:
for target in obj.targets:
targets.add(target[0])
if isinstance(target[0], swan.Block):
blocks.add(target[0])
attitude_cmd_fields = targets
print("")
print(
"In the 'MotorControl' operator, the 'attitudeCmd' input "
+ "passes through the following object diagrams:"
)
print("-----------------------------------")
for source in blocks:
if isinstance(source.instance, swan.PathIdOpCall):
print(f"Operator name: {source.instance.path_id}")
elif isinstance(source.instance, swan.PrefixOperatorExpression):
print(f"Operator name: {source.instance.op_expr.operator.path_id}")
print(f"Instance name: {source.luid}")
print("-----------------------------------")