Communication with MAD-NG
Protocol Overview
PyMAD-NG communicates with MAD-NG using a pipe-based protocol, ensuring efficient, direct, two-way communication between the Python and MAD-NG processes.
Key points:
Data is sent through FIFO pipes (first-in, first-out).
Commands are sent as MAD-NG script strings (Lua-like).
Data is retrieved via
{func}MAD.recv()after explicit instruction to send it.MAD-NG stdout is redirected to Python, but not intercepted.
Important
You must always send instructions before sending data, and send a request before receiving data.
Example: Basic Communication
from pymadng import MAD
mad = MAD()
mad.send("a = py:recv()") # Tell MAD-NG to receive
mad.send(42) # Send the value
mad.send("py:send(a)") # Request it back
mad.recv() # Receive the value → 42
Both MAD.send() and MAD.recv() are the core communication methods.
See the pymadng.MAD reference for more details.
Supported Data Types
The following types can be sent from Python to MAD-NG:
Python Type |
MAD-NG Type |
Function to Use |
|---|---|---|
|
Various |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Complex structures (e.g., TPSA, CTPSA) |
|
|
For full compatibility, see the pymadng.MAD documentation.
Converting TFS Tables to DataFrames
If you use twiss() or survey(), MAD-NG returns an mtable, which can be converted to a Pandas or TFS-style DataFrame:
mtbl = mad.twiss(...)
df = mtbl.to_df() # Either DataFrame or TfsDataFrame
If the object is not an mtable, a TypeError will be raised.
Note
tfs-pandas (if installed) will enhance the output with headers and metadata.
See:
1 mad.ps.beam = mad.psbeam
2 )
3 )
4 )
5 # fmt: on
6 df = mad.mtbl.to_df()
7 try:
8 import tfs
9
10 assert type(df) is tfs.TfsDataFrame
11 print("tfs-pandas installed, so the header is stored in headers")
12 print(df.headers)
13 except ImportError:
14 print("tfs-pandas not installed, so the header is stored in attrs instead of headers")
Avoiding Deadlocks
Deadlocks can occur if Python and MAD-NG wait on each other to send/receive large data without syncing.
Example of a Deadlock
mad.send('arr = py:recv()')
mad.send(arr0) # Large matrix
mad.send('py:send(arr)') # Sends data to Python
mad.send('arr2 = py:recv()') # Asks for new data
mad.send(arr2) # DEADLOCK if previous data not yet received
Warning
Always ensure each MAD.send() has a matching MAD.recv() if data is expected back.
Scope: Local vs Global
MAD-NG uses Lua-style scoping:
Variables declared with
localare temporary.Variables without
localpersist acrossMAD.send()calls.
Example:
mad.send("""
a = 10
local b = 20
print(a + b)
""")
mad.send("print(a + (b or 5))") # b is nil → 10 + 5 = 15
Tip
Use local to avoid polluting the global MAD-NG namespace.
Customising the Environment
You can configure the MAD() instance with options to better suit your environment:
Change the Python alias used inside MAD-NG:
mad = MAD(py_name="python")
Specify a custom MAD-NG binary:
mad = MAD(mad_path="/custom/path/to/mad")
Enable debug mode:
mad = MAD(debug=True)
Increase the number of temporary variables:
mad = MAD(num_temp_vars=10)
See pymadng.MAD.__init__() for all configuration options.
Summary
Always match
MAD.send()withMAD.recv()when data is expected.Use
mad.to_df()for table conversion.Avoid deadlocks by receiving before sending again.
Manage scope using
localwisely.Use configuration flags to tailor behaviour.
For more, see the Advanced Features in PyMAD-NG, Debugging & Troubleshooting in PyMAD-NG, and Useful Functions & Objects in PyMAD-NG sections.