Essentials
This section provides an overview of how models are structured in SysIDE Automator as well first step on importing model into Python.
Basic knowledge of SysML v2 is assumed. For those unfamiliar with the language, we recommend reviewing the SysML v2 specification.
Learn about:
Model Import: First step to start with Automator
Elements and Relationships: Understand elements and relationships
Element Types: Learn about the element types
Working with Elements: Basic example of reading elements
Model Import
Importing the model is the first step to working with it in Python.
The easiest way to import a SysML v2 model written in textual notation into Python is to
use syside.load_model
function. This function returns two
important objects:
Model
class instance containing all information from model defined by.sysml
files, including elements, relationships, and their properties. Each.sysml
file becomes an instance of classDocument
and is stored inModel.user_docs
attributeDiagnostics
class instance which contains any non-critical warnings that were found in the model
Example:
import syside
model, diagnostics = syside.load_model(["path_to_model.sysml"])
Note
Standard SysML v2 libraries are also imported when constructing a Model
, but they are stored in Model.all_docs
rather than Model.user_docs
since most users won’t need to access them directly.
Note
If the loaded model contains errors, load_model
function will raise an exception. If you need to be able to load a model with
errors, you can use try_load_model
function
instead. In that case, the diagnostics
will contain
the errors and warnings found in the model.
Elements and Relationships
In SysML v2, a Document
is constructed from
Element
(also known as nodes
). An Element
is a uniquely identified constituent of a model that can have
Relationships
with other Elements
.
Consider this example:
part wheel{
part wheel_rim;
part tyre;
}
Here, we have three unique elements: wheel
, wheel_rim
, and tyre
. In Python,
these elements are represented as objects with properties assigned via attributes, such
as .name
.
Elements can be identified in several ways:
.name
– basic element name.qualified_name
– includes hierarchy information.short_name
– SysML v2 short names, in textual notation defined between<
and>
characters.declared_name
– explicitly declared names
Note that the hierarchy is maintained through relationships. In the example, wheel
owns wheel_rim
and tyre
, representing that the wheel is composed of these parts.
Tip
For deeper exploration of Element
and other nodes
:
Refer to the SysML v2 Language Specification Document
Use a Python debugger (e.g., through Visual Studio Code)
Utilize
syside.sexp
to explore model nodes
Element Types
Elements can be of different types and have hierarchical relationships. For example:
part wheel{
attribute mass;
action rotate;
}
In this case:
wheel
is aPartUsage
mass
is aAttributeUsage
rotate
is aActionUsage
Working with Elements
Let’s explore how to work with elements using a basic example.
Example Model: copy this model into your .sysml
file locally.
part wheel{
part wheel_rim{
part metal;
attribute diameter;
attribute mass = 5;
}
part tyre{
part rubber;
attribute diameter;
attribute mass = 10;
}
attribute mass = wheel_rim.mass + tyre.mass;
}
Accessing Elements
To iterate over elements of a specific type, adjust the path and the name of the model, and run the code:
import syside
model, diagnostics = syside.load_model(["path_to_model.sysml"])
for element in model.elements(syside.PartUsage):
print(element.name)
Executing the code above will print the following:
wheel
wheel_rim
tyre
metal
rubber
Working with Values
When assigning something to an Element
, the structure will
depend on what data type was assigned. The most general way of dealing with this is to
use the Compiler
to evaluate the expression that was
assigned to element:
for attr_element in model.nodes(syside.AttributeUsage):
if attr_element.name == "mass":
expression = attr_element.feature_value_expression
assert expression is not None
evaluation = syside.Compiler().evaluate(expression)
if evaluation[1].fatal:
print(f"Error evaluating {attr_element.name}")
else:
value = evaluation[0]
assert attr_element.owner is not None
print(f"Mass of {attr_element.owner.name} = {value}")
Note that Compiler.evaluate
returns a tuple with
two elements: the first is the evaluation result, and the second is the evaluation
report. It is good practice to check if the evaluation succeeded before using the
result. Executing the code above will print the following:
Mass of wheel = 15
Mass of wheel_rim = 5
Mass of tyre = 10
Note
The Compiler
is the most general way of dealing with
expression evaluation, since the output is dependent on the expression – in above
example it returned a number, but in the case of item driver = John
it would
return the ReferenceUsage
instance of John
.
At the moment, Compiler
supports evaluation of model
level evaluable expressions, as defined in the specification.
Next Steps
Now that you understand the basics of SysIDE Automator’s model structure, you can proceed to the First Example section for hands-on example.