magnelio.analysis#

ScatteringTDResult and the store-backed Project reader satisfy the same contract, ScatteringResult — a script works unchanged against either. Four of its accessors (phase, plot_s, to_touchstone, to_skrf) are shared verbatim between the two and are listed on each class below through inheritance.

Analysis workflows — the high-level problem-class API.

Each Analysis* class solves a specific physical question in one run() call:

  • AnalysisEigenmode — resonant eigenmodes of a closed cavity.

  • AnalysisScatteringTD — S-parameters of a multi-port network via FIT time-domain simulation.

resume() continues a time-domain run persisted in a project store

from its last checkpoint — see the function docstring.

class magnelio.analysis.RunSettings(f_max=None, f_min=None, n_freq=None, dt=None, n_actual_steps=None, accuracy=None, energy_stop_db=None, port_signal_stop_db=None, taper_signals=None, stop_reason=None, final_port_signal_db=None, precision=None, backend=None, port_model_used=None)#

Settings a finished run was produced with, readable off the result.

All fields are optional: the in-RAM result fills what the analysis knew at run time; the store-backed reader fills what the project recorded (older stores may lack individual entries).

Parameters:
  • f_max (float | None)

  • f_min (float | None)

  • n_freq (int | None)

  • dt (float | None)

  • n_actual_steps (int | None)

  • accuracy (str | None)

  • energy_stop_db (float | None)

  • port_signal_stop_db (float | None)

  • taper_signals (bool | None)

  • stop_reason (str | None)

  • final_port_signal_db (float | None)

  • precision (str | None)

  • backend (str | None)

  • port_model_used (str | None)

class magnelio.analysis.ScatteringResult(*args, **kwargs)#

Everything a scattering result guarantees, RAM- or store-backed.

A script written against this protocol runs unchanged whether AnalysisScatteringTD.run() returned an in-RAM ScatteringTDResult (no project) or a Project reader (with one). The protocol is runtime_checkable(), so isinstance(res, ScatteringResult) holds for both.

The members below are what both implementations provide; each implementation documents its own behaviour, and the two are cross-checked by running one shared set of assertions over both.

Three further accessors come from ScatteringResultMixin and are shared verbatim rather than reimplemented: plot_s and the to_touchstone / to_skrf exports.

S(out_port, in_port, *, mode_out=0, mode_in=0, f_axis=None)#

One complex S-parameter over the frequency axis.

Return type:

ndarray

a(port, mode=0, *, excited=None, f_ref=None, destagger=True)#

Incident power-wave time series a(t) at one channel.

b(port, mode=0, *, excited=None, f_ref=None, destagger=True)#

Outgoing power-wave time series b(t) at one channel.

db(out_port, in_port, *, mode_out=0, mode_in=0, floor_db=-200.0, f_axis=None)#

One S-parameter in decibels, floored at floor_db.

Return type:

ndarray

phase(out_port, in_port, *, mode_out=0, mode_in=0, deg=True, unwrap=True, f_axis=None)#

Phase of one S-parameter over the frequency axis.

Return type:

ndarray

property channels: tuple#

Observed (port_name, mode_idx) pairs, in S-matrix order.

property excitations: tuple#

Excited (port_name, mode_idx) pairs — the S-matrix columns present.

property f_axis: ndarray#

Frequency axis of the S-matrix [Hz], ascending.

property settings: RunSettings#

The RunSettings this result was produced with.

class magnelio.analysis.ScatteringTDResult(s_params, signals, reference_signal, dt, n_actual_steps, port_modes=None, port_normal_dx=None, port_line_params=None, port_model_used=None, reference_signals=None, settings=None)#

Result of one AnalysisScatteringTD.run() call.

Parameters:
  • s_params (SParameterResult)

  • signals (dict)

  • reference_signal (Signal1D)

  • dt (float)

  • n_actual_steps (int)

  • port_modes (dict | None)

  • port_normal_dx (dict | None)

  • port_line_params (dict | None)

  • port_model_used (str | None)

  • reference_signals (dict | None)

  • settings (RunSettings | None)

s_params#

Frequency-domain S-matrix columns for every excited pair.

Type:

SParameterResult

signals#

Outer key: the excited (port_name, mode_idx) pair. Inner dict: every observed channel for that excitation, mapped to a (V_signal, I_signal) pair on the same time axis. Buffers are already trimmed to the actual leapfrog count via PortSignalRecorder.finalize().

Type:

dict[(str, int), dict[(str, int), (Signal1D, Signal1D)]]

reference_signal#

The excitation waveform sampled on the same time axis as the recorded signals. Useful for monitor renormalisation (MonitorFieldFrequency.renormalize) and for incident/reflected decomposition in time-domain plots. On multi-excitation runs with auto-derived waveforms this is the waveform of the longest run — per-mode waveforms can differ (cut-off-dependent band); the S-parameters are unaffected.

Type:

Signal1D

dt#

Solver time step [s].

Type:

float

n_actual_steps#

Number of leapfrog steps actually executed. Equals len(reference_signal.values); can be smaller than the configured total_time_steps when energy_stop_db triggered an early termination.

Type:

int

port_modes#

Per-port ordered Mode list (lumped ports carry a _LumpedModeStub), as used by the S-parameter post-processing. Backs the time-domain power-wave accessors a(...) / b(...).

Type:

dict[str, list] or None

port_normal_dx#

Per-port boundary cell size along the port normal, as passed to the S-parameter de-stagger. Backs the default (destagger=True) time-domain power waves.

Type:

dict[str, float] or None

port_line_params#

Per-channel certified discrete line parameters (PortOperatorModal.dtbc_line_params), as passed to the S-parameter de-stagger. Backs the default time-domain power waves; channels missing here use the continuum factors.

Type:

dict[(str, int), tuple] or None

port_model_used#

Which port pipeline produced this result: "modal" (the per-spec modal port operators) or "band" (the broadband band-subspace DTBC pipeline).

Type:

str or None

settings#

The settings this run was produced with — frequency range, time step, why the marching stopped, precision and backend.

Type:

RunSettings or None

Notes

The accessors S(), db() and f_axis delegate to s_params, so a script can write result.S("port2", "port1") without unpacking anything.

Use a() / b() — not V s(t) — for the incident/reflected split in time-domain plots: V is the total modal voltage and s(t) is the source waveform, not the launched wave, so the difference is not the reflected wave.

S(out_port, in_port, *, mode_out=0, mode_in=0, f_axis=None)#

One complex S-parameter over the frequency axis.

Parameters:
  • out_port (str) – Observed and excited port names. S("port2", "port1") is the transmission from port 1 to port 2; equal labels give a reflection.

  • in_port (str) – Observed and excited port names. S("port2", "port1") is the transmission from port 1 to port 2; equal labels give a reflection.

  • mode_out (int) – Mode index at the observed / excited port (default 0, the fundamental). Only needed on multi-mode ports.

  • mode_in (int) – Mode index at the observed / excited port (default 0, the fundamental). Only needed on multi-mode ports.

  • f_axis (array-like, optional) – Custom frequency axis [Hz]. The S-matrix is then recomputed from the recorded time signals on that axis instead of being read off the run’s own axis — use it to resolve a narrow feature without re-running the simulation. Frequencies outside the excitation’s band carry no usable signal.

Returns:

Complex S-parameter, one entry per frequency.

Return type:

numpy.ndarray

Raises:

KeyError – If the pair was never recorded — in_port must be among excitations and out_port among channels.

a(port, mode=0, *, excited=None, f_ref=None, destagger=True)#

Incident power-wave time series a(t) [√W].

With destagger=True (default) the decomposition runs on the rfft axis with the same per-frequency corrections as compute_s_parameters() — temporal Yee half-step rotation, spatial two-plane de-stagger (exact discrete λ^{1/2} factor on DTBC-certified channels, continuum e^{−γ·d/2} otherwise), and the exact discrete wave impedance where certified — then transforms back. b(t) then shows the true outgoing wave down to the port floor. destagger=False restores the historical co-located split (V/√Z ± √Z·I)/2 with midpoint-averaged I, which leaks β·dz/4 of the incident pulse into b (a derivative-of-pulse ghost, −22 dB at λ/20 meshes).

Parameters:
  • port (str) – Observed port name.

  • mode (int, default 0) – Observed mode index.

  • excited (str or (str, int), optional) – Which excitation run to read. May be omitted when the result holds exactly one excitation.

  • f_ref (float, optional) – Frequency [Hz] at which the frozen reference impedance Z = z_modal(2π·f_ref) is evaluated. Defaults to the centre of the result’s frequency axis. With destagger=False this Z parameterises the whole decomposition; with destagger=True it only backs the out-of-band fallback bins (see destaggered_power_waves()). Raises if Z is not real at f_ref (mode evanescent there).

  • destagger (bool, default True) – Apply the exact frequency-domain de-stagger.

Returns:

On the same time axis as the recorded V.

Return type:

Signal1D

b(port, mode=0, *, excited=None, f_ref=None, destagger=True)#

Outgoing power-wave time series b(t) [√W].

See a() for conventions, stagger handling, and the f_ref / destagger semantics.

Parameters:
  • port (str)

  • mode (int)

  • excited (str | tuple[str, int] | None)

  • f_ref (float | None)

  • destagger (bool)

Return type:

Signal1D

db(out_port, in_port, *, mode_out=0, mode_in=0, floor_db=-200.0, f_axis=None)#

One S-parameter in decibels — 20 log10 |S|.

Parameters:
  • out_port (str) – Observed and excited port names, as in S().

  • in_port (str) – Observed and excited port names, as in S().

  • mode_out (int) – Mode indices at the observed / excited port (default 0).

  • mode_in (int) – Mode indices at the observed / excited port (default 0).

  • floor_db (float, default -200.0) – Values below this are clamped to it, so an exact zero (an unexcited channel, a perfect null) yields a finite number instead of -inf and stays plottable.

  • f_axis (array-like, optional) – Custom frequency axis; recomputed as in S().

Returns:

Magnitude in dB, one entry per frequency.

Return type:

numpy.ndarray

phase(out_port, in_port, *, mode_out=0, mode_in=0, deg=True, unwrap=True, f_axis=None)#

Phase of one S-parameter over the frequency axis.

Parameters:
  • out_port (str) – Observed / excited port names (modes via mode_out / mode_in), as in S().

  • in_port (str) – Observed / excited port names (modes via mode_out / mode_in), as in S().

  • deg (bool, default True) – Return degrees; False returns radians.

  • unwrap (bool, default True) – Unwrap 2π discontinuities along the frequency axis.

  • f_axis (array-like, optional) – Custom frequency axis; recomputed from the recorded signals like S().

  • mode_out (int)

  • mode_in (int)

Returns:

Phase per frequency point.

Return type:

np.ndarray

plot_s(*pairs, db=True, floor_db=-200.0, ax=None)#

Plot S-parameter magnitudes over frequency.

Parameters:
  • *pairs (tuple) – Channels to plot, each (out_port, in_port) or (out_port, in_port, mode_out, mode_in). Without arguments every recorded channel of every excitation is plotted.

  • db (bool, default True) – Magnitude in dB (with floor_db) instead of linear.

  • floor_db (float, default -200.0) – Clip floor for the dB display.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw into; a new figure is created otherwise.

Returns:

  • fig (matplotlib.figure.Figure)

  • ax (matplotlib.axes.Axes)

to_skrf(name='magnelio')#

Return the complete S-matrix as a skrf.Network.

Delegates to magnelio.post.SParameterResult.to_skrf(); requires scikit-rf and a complete square matrix.

Parameters:

name (str)

to_touchstone(path)#

Write the complete S-matrix as a Touchstone .sNp file.

Delegates to magnelio.post.SParameterResult.to_touchstone(); requires every channel to have been excited.

Return type:

None

property channels: tuple#

Observed (port_name, mode_idx) pairs, in S-matrix order.

property excitations: tuple#

Excited (port_name, mode_idx) pairs — the S-matrix columns present.

property f_axis: ndarray#

Frequency axis of the S-matrix [Hz], ascending.