Matrix view concepts
A matrix view in the Syside VS Code Extension relates two sets of elements. Each row and each column is an element, and each cell says whether a relationship joins that pair, such as a requirement allocated to a component, a system requirement derived from a stakeholder requirement or two parts connected. The exact attributes are listed in Matrix view structure.
Three views, three selections
A matrix is made of three sub-views, and each one selects its elements on its own,
with its own expose, filter and include flags:
rowViewandcolumnViewselect the axes. Each works the way a flat table selects its rows, so the rows can come from one package and the columns from another, and be of different kinds. An element an axis reaches twice is still one row or column.cellViewselects the relationships that can mark a cell. Its filter decides which relationships count, but it does not prune (see Include flags in grid views). A relationship usually sits inside the part or definition that contains the parts it connects, so underexpose X::**withfilter hastype SysML::ConnectionUsagethe parts fail the filter, yet the connections among them still count.
Unlike the axes, the cell view includes reference usages by default. A usage
declared directly in a package is a reference usage, so connections written at
package level count without setting a flag. Ports are reference usages too, so the
cell view reads connections to ports without a flag. The ports themselves appear on
an axis only when that axis sets includeReferenceElements = true, and an editable
matrix with ports on its axes can then write connections to them.
How a relationship marks a cell
A relationship marks the cell where one of its ends is the row element and the other the column element. This exact match is a strong mark, as opposed to the weak marks described below. A connection between two usages strongly marks the cell between those usages, never the cell between the definitions typing them:
part def Powertrain {
part engine : Engine;
part transmission : Transmission;
connect engine to transmission;
}
With engine and transmission on the axes, the connection marks their cell. With
Engine and Transmission on the axes instead, it marks nothing, because neither
end is a definition. A relationship between definitions is a definition itself, and
this one marks the cell between Engine and Transmission:
connection def { end : Engine; end : Transmission; }
By default a matrix ignores which end of a relationship is which. Setting
direction makes the matrix count only relationships whose source is on one axis
and whose target is on the other. For a requirement derivation, the #original and
#derive tags decide which end is the source, not the order the ends are written
in.
Usage and definition traceability
Because the match is exact, a matrix traces one of two separate things:
Usage traceability |
Definition traceability |
|
|---|---|---|
Relates |
Features in one particular system: |
Definitions, wherever they are used: |
Rows and columns |
Usages |
Definitions |
A relationship is |
A usage, such as |
A definition, such as |
Holds |
In the context it is written in. The same two parts can be connected in one system and not in another. |
Everywhere the definitions are used |
Strong marks never cross between the two. A connection between engine and
transmission leaves the Engine × Transmission cell empty, and a connection
definition between Engine and Transmission leaves the engine × transmission
cell empty. A matrix with usages on one axis and definitions on the other therefore
shows no strong marks, and on matching axes only the relationships of the same side
count. With
weak marks on, a usage relationship can still
weakly mark the definitions its ends are declared in.
When a usage axis should read like a definition axis, representDefinition labels
each header with the definition typing the element, when exactly one does. The rows
are still the usages, so two usages typed by the same definition are two rows with
the same label.
Weak marks
A relationship can sit between elements nested inside the rows and columns rather than between the rows and columns themselves:
part def Drone {
part propulsion {
part motor;
}
part power {
part battery;
}
connect propulsion.motor to power.battery;
}
With propulsion and power on the axes, the connection marks nothing, because its
ends are motor and battery. Setting showWeakTraceability on the cell view adds
a weak mark to the propulsion × power cell: something inside the row is related
to something inside the column.
A relationship marks a cell weakly when each of its ends is the row or column element or lies inside it. An end lies inside an element in one of three ways:
It is declared inside the element, at any depth:
motoris declared insidepropulsion.It is reached through the element: the end
propulsion.motoris named throughpropulsion. This counts even whenmotoris declared in the definition typingpropulsionrather than inpropulsionitself.For relationships between definitions, its definition specializes the element. A connection definition with an end typed by
SportsCarweakly marks theCarrow whenSportsCar :> Car, but never the other way round.
When a cell has both a strong and a weak mark, the strong mark is shown. A weak cell is never editable: the relationship it reflects was made between other elements, so it cannot be added or removed from that cell.
Port transparency
Connections are often wired through ports, while the matrix is about the parts that own them:
part def System {
part sender {
port output;
}
part receiver {
port input;
}
connect sender.output to receiver.input;
}
With sender and receiver on the axes, the connection’s ends are the ports, so it
marks their cell only weakly, and only when weak marks are on. Setting
portsAreTransparent on the cell view treats a port end as the element the
connection reaches it through: sender.output counts as sender, and the cell gets
a strong mark. A port written without a path, inside the part that has it, counts as
the element the connection is declared in. The same applies to allocation and
derivation usages, but not to relationship definitions: their ends are definitions,
not ports.
What an editable matrix writes
An editable matrix creates one kind of relationship, and the view has to say which.
isEditable = true turns editing on, and the cell view’s filter picks the kind: it
must admit exactly one of the six relationship kinds, and every new cell becomes that
kind. The default cell view admits all six, so isEditable on its own leaves the
matrix read-only, as does a filter that admits several kinds. A banner explains why.
Where a new relationship goes depends on whether it is a usage or a definition:
A usage relationship is written into one context. A connection between usages only holds where it is written: the same two parts can be connected inside one system and not inside another. So the cell view names one context, and each new connection is written into it, with its ends as paths from the context to the row and column elements. A row or column element that does not appear exactly once inside the context has no single path, so its cells are disabled.
A definition relationship is written into a namespace. A connection definition holds wherever its definitions are used, so it only needs a place to live: a writable namespace the cell view exposes the members of, so that the new definition is read back.
The exact expose each side needs is listed in Relationship kinds.
A row or column that does not fit the kind, such as a usage in a matrix that writes definitions, has its cells disabled (see why a row or column is disabled). Relationships in libraries, or inherited from a supertype of the context, cannot be removed from the matrix either, since they are written outside the context.
Build a matrix view builds an editable derivation matrix step by step, and Make a matrix editable covers making an existing matrix editable.