Diagram Class

The Diagram class is the central object for creating and managing control system diagrams in Lynx.

Overview

A diagram contains:

  • Blocks: Computational units (Gain, TransferFunction, StateSpace, Sum, IOMarker)

  • Connections: Directed edges between block ports

  • Metadata: Labels, positions, and parameters

All modifications are performed in-place. Diagrams can be saved to and loaded from JSON files.

Creating Diagrams

import lynx

# Create empty diagram
diagram = lynx.Diagram()

# Load existing diagram
diagram = lynx.Diagram.load("diagram.json")

# Create new diagram from template
diagram = lynx.Diagram.from_template("feedforward_tf")

Adding Blocks

Use add_block() to add blocks to your diagram:

# Syntax: add_block(block_type, block_id, **parameters)

# Gain block
diagram.add_block('gain', 'controller', K=5.0, position={'x': 100, 'y': 50})

# Transfer function: G(s) = 2/(s+3)
diagram.add_block('transfer_function', 'plant',
                  num=[2.0],
                  den=[1.0, 3.0],
                  position={'x': 200, 'y': 50})

# State-space block with A, B, C, D matrices
import numpy as np
A = np.array([[-1, 0], [0, -2]])
B = np.array([[1], [1]])
C = np.array([[1, 0]])
D = np.array([[0]])
diagram.add_block('state_space', 'ss_system',
                  A=A, B=B, C=C, D=D,
                  position={'x': 300, 'y': 50})

# Sum block with configurable signs
diagram.add_block('sum', 'error_sum',
                  signs=['+', '-', '|'],  # top, left, bottom
                  position={'x': 50, 'y': 50})

# I/O markers for system boundaries
diagram.add_block('io_marker', 'r', marker_type='input', label='r', position={'x': 0, 'y': 50})
diagram.add_block('io_marker', 'y', marker_type='output', label='y', position={'x': 400, 'y': 50})

Adding Connections

Use add_connection() to connect block ports:

# Syntax: add_connection(connection_id, source_block, source_port, target_block, target_port)

# Basic connection
diagram.add_connection('c1', 'controller', 'out', 'plant', 'in')

# Connection with label (useful for export)
diagram.add_connection('c2', 'plant', 'out', 'y', 'in', label='output_signal')

# Feedback connection
diagram.add_connection('c3', 'plant', 'out', 'error_sum', 'in2')

Saving and Loading

# Save to JSON file
diagram.save('my_control_system.json')

# Load from JSON file
loaded_diagram = lynx.Diagram.load('my_control_system.json')

JSON format is human-readable and version-controlled friendly.

Exporting to Python-Control

Extract transfer functions or state-space representations:

import control as ct

# Export closed-loop transfer function
sys_tf = diagram.get_tf('r', 'y')  # From input 'r' to output 'y'

# Export state-space representation
sys_ss = diagram.get_ss('r', 'y')

# Analyze with python-control
bode = ct.bode_plot(sys_tf)
nyquist = ct.nyquist_plot(sys_tf)

See Python-Control Export for details on signal reference patterns.

Interactive Widget

Launch the interactive Jupyter widget:

# In Jupyter notebook
lynx.edit(diagram)

This opens a visual editor where you can:

  • Drag blocks to reposition

  • Edit parameters via properties panel

  • Add/remove connections

  • View block labels and LaTeX rendering

Changes in the widget sync back to the Python object.

API Reference

Diagram.add_block

Add a block to the diagram.

Diagram.add_connection

Add a connection between two block ports with validation.

Diagram.remove_block

Remove block from diagram and all connected edges.

Diagram.remove_connection

Remove connection from diagram.

Diagram.update_block_parameter

Update block parameter (with undo support).

Diagram.save

Save diagram to JSON file.

Diagram.load

Load diagram from JSON file with optional expression re-evaluation.

Diagram.get_tf

Extract transfer function from one signal to another.

Diagram.get_ss

Extract state-space model from one signal to another.

edit

Launch interactive widget to edit a diagram.

See Also