Connection

class pathsim.connection.Connection(source, *targets)[source]

Bases: object

Class to handle input-output relations of blocks by connecting them (directed graph) and transfering data from the output port of the source block to the input port of the target block.

The default ports for connection are (0) -> (0), since these are the default inputs that are used in the SISO blocks.

Examples

Lets assume we have some generic blocks

from pathsim.blocks._block import Block

B1 = Block()
B2 = Block()
B3 = Block()

that we want to connect. We initialize a ‘Connection’ with the blocks directly as the arguments if we want to connect the default ports (0) -> (0)

from pathsim import Connection

C = Connection(B1, B2)

which is a connection from block ‘B1’ to ‘B2’. If we want to explicitly declare the input and output ports we can do that by utilizing the ‘__getitem__’ method of the blocks

C = Connection(B1[0], B2[0])

which is exactly the default port setup. Connecting output port (1) of ‘B1’ to the default input port (0) of ‘B2’ do

C = Connection(B1[1], B2[0])

or just

C = Connection(B1[1], B2).

The ‘Connection’ class also supports multiple targets for a single source. This is specified by just adding more blocks with their respective ports into the constructor like this:

C = Connection(B1, B2[0], B2[1], B3)

The port definitions follow the same structure as for single target connections.

‘self’-connections also work without a problem. This is useful for modeling direct feedback of a block to itself.

Port definitions support slicing. This enables direct MIMO connections. For example connecting ports 0, 1, 2 of ‘B1’ to ports 1, 2, 3 of ‘B2’ works like this:

C = Connection(B1[0:2], B2[1:3])

Port definitions also support lists and tuples of ‘int’. For example the slice above is identical to this:

C = Connection(B1[0, 1], B2[1, 2])

Or to be more programmatic about it, like this:

prts_1 = [0, 1]
prts_2 = [1, 2]

C = Connection(B1[prts_1], B2[prts_2])

Another way to define the ports is by using strings. Some blocks have internal aliases for the ports that can be used instead of the integer port indices to define the connections (or access the port data):

C = Connection(B1["out"], B2["in"])

Or mixed with integer port indices:

C = Connection(B1["out"], B2["in"])
Parameters:
_active

flag to set ‘Connection’ as active or inactive

Type:

bool

source
targets
get_blocks()[source]

Returns all the unique internal source and target blocks of the connection instance

Returns:

internal unique blocks of the connection

Return type:

list[Block]

on()[source]
off()[source]
update()[source]

Transfers data from the source block output port to the target block input port.

resolve_ports()[source]

Eagerly resolve source and target port indices, growing the underlying Register instances to their final size.

Normally registers grow lazily on the first connection.update() via PortReference._get_input_indices. In the DAG case that is fine: the source-side connection fires before the target block’s update, so by the time the block reads its inputs, the register has the right size. Inside an algebraic loop the order is reversed (block.update() first, then connection.update() in the same iteration), so the first iteration sees a register still at the Block.__init__ default size and any block that accesses inputs by position (e.g. Function splatting into a multi-arg callable) raises TypeError.

Calling resolve_ports once during graph assembly closes that gap. Idempotent. New register slots are zero-initialised through np.zeros in Register.resize.

class pathsim.connection.Duplex(source, target)[source]

Bases: Connection

Extension of the ‘Connection’ class, that defines bidirectional

Deprecated since version 1.0.0.

connections between two blocks by grouping together the inputs and outputs of the blocks into an IO-pair.

source
target
targets
update()[source]

Transfers data between the two target blocks and ports bidirectionally.