PyMAD-NG Architecture Overview
This section explains the internal architecture of PyMAD-NG, outlining how Python interacts with MAD-NG.
Note
Understanding the architecture will help advanced users contribute to development, extend functionality, and debug issues more effectively.
High-Level Overview
PyMAD-NG is a Python wrapper for MAD-NG, using standard UNIX pipes to manage two-way communication between Python and the MAD-NG subprocess. It provides both:
A low-level string-based API (like scripting MAD-NG manually)
A high-level object-based API that emulates Pythonic behaviour
At the heart of PyMAD-NG is the MAD class, which:
Spawns the MAD-NG binary as a subprocess
Manages sending commands and receiving data
Handles variable binding, temporary variables, and object references
Communication Pipeline
The communication between Python and MAD-NG follows this pipeline:
+-----------+ send() +---------+
| Python | -------------------> | MAD-NG |
| Script | <------------------- | Process |
+-----------+ recv() +---------+
This is implemented using os.pipe() and select.select() to manage reads and writes asynchronously.
Communication Protocol
Commands are sent as strings to MAD-NG (e.g.,
mad.send("a = 1 + 2"))Responses are requested explicitly via
{func}MAD.recv`Data can be sent and received in binary or string formats, depending on the type
Core Components
MAD Class (madp_object)
Main interface for users
Automatically loads common MAD-NG modules (e.g.
twiss,element,sequence)Handles naming of Python process in MAD-NG via
py_nameConfigures subprocess behaviour (debug mode, stdout redirection)
madp_pymad.MadProcess
Manages low-level pipe setup and subprocess launch
Provides
send,recv, andclosemethodsSerialises and deserialises Python <-> MAD data
madp_classes
Wraps MAD-NG references returned to Python
Allows chained method calls like
mad.math.sin(1)Supports
.eval()to convert a MAD value into a native Python objectImplements
__getattr__,__getitem__,__call__to emulate Lua table behaviour
madp_last
Implements
_last[]variable management for symbolic return valuesEnsures unique temporary variable usage
Used in constructing expression chains
madp_strings
Contains helpers for quoting strings for MAD-NG consumption
Supports quote-conversion for use in file writing and table exporting
Data Types and Serialization
PyMAD-NG supports a wide range of Python-native and NumPy types, which are automatically serialised and mapped to MAD-NG equivalents.
Python Type |
MAD-NG Type |
Transport Format |
|---|---|---|
|
number, string |
text or binary |
|
bool |
text |
|
complex |
binary |
|
table |
serialised list |
|
matrix, cmatrix |
binary |
|
range types |
encoded structure |
Conversion is handled by MAD.send() and {func}MAD.recv, both methods on the {class}MAD` class.
Dynamic Attributes & Autocompletion
Because MAD-NG entities are only known at runtime, PyMAD-NG uses dynamic attribute access via __getattr__. This means:
Tab completion (
dir(mad)) only works for preloaded or cached attributesUse
MAD.globals()to list current MAD-NG global variablesmadp_classes.high_level_MadRefobjects will not show introspectable properties until evaluated
Protected Execution
All sends are “protected” by default:
If MAD-NG returns an error, PyMAD-NG raises a Python
RuntimeErrorThe return type
err_is automatically detected and escalatedThis avoids crashes and lets users handle exceptions gracefully
Summary
Component |
Role |
|---|---|
|
Main interface and environment for interacting with MAD-NG |
Launches and communicates with MAD-NG subprocess |
|
|
Wraps MAD objects for Pythonic access |
Tracks temporary intermediate results from MAD-NG |
|
Type dispatch |
Maps Python objects to MAD-NG-compatible messages |
This modular, pipe-based architecture ensures PyMAD-NG remains flexible, efficient, and closely integrated with MAD-NG’s scripting model.