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. TDResult is what the general time-domain analysis returns — the recorded signals of one march — and what Project.result(name) rebuilds for any stored run.

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.

  • AnalysisTD — one time-domain march under any set of simultaneous excitations; returns a TDResult.

  • AnalysisScatteringTD — S-parameters of a multi-port network, one channel per time-domain run.

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, t_end=None, excitations=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)

  • t_end (float | None)

  • excitations (tuple | 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.

Further accessors come from ScatteringResultMixin and are shared verbatim rather than reimplemented: plot_s, deembed (reference-plane shift) 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 elapsed: float | None#

Wall time of the marching [s] — setup excluded, resumes summed.

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 finished#

Wall-clock end (UTC datetime) of the last march, or None.

property settings: RunSettings#

The RunSettings this result was produced with.

property started#

Wall-clock start (UTC datetime) of the first march, or None.

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, port_source_used=None, reference_signals=None, settings=None, port_dispersion=None, port_reference_scale=None, extrapolation=None, started=None, finished=None, elapsed=None, energy_traces=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)

  • port_source_used (str | None)

  • reference_signals (dict | None)

  • settings (RunSettings | None)

  • port_dispersion (dict | None)

  • port_reference_scale (dict | None)

  • extrapolation (dict | None)

  • started (object | None)

  • finished (object | None)

  • elapsed (float | None)

  • energy_traces (dict | 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_source_used#

"dispersive" when the ports launched a rank-r family. The decomposition then runs per frequency against the port records, as it does for a band run: a dispersive source repairs the launch error, and reading it through the frequency-flat split would leave the two halves of the same defect mismatched — and the reported number worse than with neither repaired.

Type:

str 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

started, finished

Wall-clock stamps (UTC): the start of the first march and the end of the last one.

Type:

datetime or None

elapsed#

Wall time of the marches [s], summed over the excitations.

Type:

float or None

energy_traces#

The stored-energy trace of every excitation’s march, keyed by the excited (port_name, mode_idx) pair — the same structured array energy_trace holds.

Type:

dict 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

deembed(distances)#

Shift port reference planes; return the de-embedded S-matrix.

Removes the feed-line propagation between a port plane and its new reference plane: result.deembed({"port1": d}) moves port1’s reference plane the distance d [m] from the port plane into the domain, and every S-parameter touching that port is multiplied by the inverse line propagation factor over d — reflections twice, transmissions once per shifted end. A negative distance moves the plane outward (adds line length); ports not named keep their plane.

The shift uses the discrete dispersion of the port’s uniform feed chain — the same grid propagation the solver applied — so de-embedding a uniform feed line removes its phase down to the accuracy floor of the run itself, including the grid-dispersion part that an analytic exp(-jβd) would leave behind on coarse meshes. It assumes the cross-section stays that of the port over the shifted length. A quasi-TEM channel (microstrip, CPW — an inhomogeneous cross-section on modal Mur) carries no certified line parameters; the run keeps the port’s dispersion record instead, and the shift uses the true discrete modes of the feed solved at every frequency of the axis, so the line’s physical dispersion is removed as well (the first call on such a result spends a few seconds on that solve). Only a channel with neither — a feed section that is not a uniform chain behind the port — falls back to the mode’s continuum γ(f), for a quasi-TEM mode the frequency-flat quasi-static one.

Below its cut-off a channel’s factor grows exponentially with distance, so de-embedded values there keep the diagnostic character the raw ones have. Lumped ports carry no feed-line dispersion; naming one raises.

Parameters:

distances (dict[str, float]) – Per-port shift distance [m], positive into the domain.

Returns:

A new result referenced at the shifted planes — the original is untouched. It answers S / db / phase / plot_s and the Touchstone / scikit-rf exports.

Return type:

SParameterResult

extrapolate(*, order=None, tol=0.0001, decay_db=80.0, max_factor=100.0, fit_start=None)#

S-parameters as if the march had run until the fields died away.

A run has to stop somewhere, and on a high-Q structure what it leaves behind is a record still ringing at the last step. The DFT reads that edge as content and lays truncation ripple over every S-parameter. Past the excitation, though, the record is the structure’s own free decay — a sum of damped exponentials whose poles are its resonances — so a pole model fitted to what was recorded continues it for as long as one likes, and the S-parameters follow from the continued records through the same pipeline as before.

This is a model, not a measurement. It is trustworthy exactly as far as the record really is a free decay of a few resonances: read extrapolation, whose residual is the model fitted on the first half of the fit window and measured against the recorded second half. Below about 1e-2 the poles are the structure’s; approaching one, the fit is describing noise and the result should be thrown away in favour of a longer run. Nothing here is applied automatically — an extrapolated resonance mistaken for a measured one is exactly what the truncation warning exists to prevent.

Parameters:
  • order (int, optional) – Model order (poles, two per resonance). Default: from the singular-value decay of the record’s Hankel matrix.

  • tol (float, default 1e-4) – Relative singular-value threshold for that choice. Raise it on a noisy record to keep fewer poles.

  • decay_db (float, default 80.0) – Continue every record until the model has fallen this far below its peak.

  • max_factor (float, default 100.0) – Cap on the continuation, in multiples of the recorded length — a pole a hair inside the unit circle would otherwise ask for an unbounded record. The report says when the cap bit before the model had decayed.

  • fit_start (float, optional) – Time [s] the fit window opens. Default: when the excitation waveform has fallen 60 dB below its peak, since only past the source is the record a free decay.

Returns:

A new result whose records are the continued ones and whose S-matrix was recomputed from them; the original is untouched. Its extrapolation maps every excitation to an ExtrapolationReport.

Return type:

ScatteringTDResult

Examples

>>> long = result.extrapolate()
>>> long.extrapolation[("port1", 0)]
>>> long.plot_s(("port1", "port1"))
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, on hosts whose S() can recompute the spectrum (run results); a plain SParameterResult holds one fixed axis and rejects it.

  • mode_out (int)

  • mode_in (int)

Returns:

Phase per frequency point.

Return type:

np.ndarray

plot_balance(*excitations, deficit=False, ax=None)#

Plot the power balance of every excitation.

For each excited channel j the sum of the squared magnitudes over the observed channels, Σ_i |S_ij|² — the share of the incident power that comes back out of the ports. On a lossless, fully exported network it is one; what is missing is what left the ports: ohmic and dielectric loss, and radiation.

The reading depends on two things the plot cannot check. Only channels present in the result are summed, so a network whose higher modes or whose ports were not all exported reads short and the deficit looks like loss (is_complete says whether every observed channel was also excited). And a channel that carries no propagating mode at a frequency is NaN there; an evanescent channel transports no active power, so it counts as zero rather than poisoning the sum.

Parameters:
  • *excitations (str or tuple) – Excited channels to plot, each port or (port, mode). Without arguments every excitation is plotted.

  • deficit (bool, default False) – Plot 10·log10(1 − Σ) — the power that left the ports, in dB — instead of the sum itself. The useful form when the balance is close to one, where the interesting number is how far from it.

  • ax (matplotlib.axes.Axes, optional)

Returns:

  • fig (matplotlib.figure.Figure)

  • ax (matplotlib.axes.Axes)

plot_energy(*, x='time', floor_db=None, ax=None)#

Plot every excitation’s stored energy in dB below its peak.

One curve per excited channel, labelled port:mode, with the energy criterion as a dashed line when the runs had one. x is "time" (nanoseconds) or "step"; the axis runs from ten dB below the criterion (floor_db pins it) to +5 dB; ax draws into existing axes. Returns (fig, ax).

Parameters:
  • x (str)

  • floor_db (float | None)

plot_polar(*pairs, mark=None, r_max=None, ax=None)#

Plot channels in the complex plane, magnitude over phase.

The polar counterpart of plot_smith() for channels the Smith chart does not describe — transmission above all, whose magnitude is not bounded by one in a network with gain and which has no impedance reading.

Parameters:
  • *pairs (tuple) – As plot_smith(); without arguments every recorded channel of every excitation.

  • mark (array_like, optional) – Frequencies [Hz] to mark on every trace.

  • r_max (float, optional) – Radial limit; default the peak magnitude, at least one.

  • ax (matplotlib.axes.Axes, optional) – Must be a polar axes; one is created otherwise.

Returns:

  • fig (matplotlib.figure.Figure)

  • ax (matplotlib.axes.Axes)

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)

plot_smith(*pairs, mark=None, labels=True, ax=None)#

Plot reflection channels on a Smith chart.

The complex reflection coefficient traced over frequency on the unit disc, with the circles of constant normalised resistance and reactance behind it. The chart is only readable against one normalisation: a channel whose reference impedance varies with frequency (a dispersive waveguide mode, DD-244) has no single set of circles, and its trace here is the power-wave coefficient against a moving reference. Call renormalize() first — renormalize(50) — when that matters; a warning names the case.

Parameters:
  • *pairs (tuple) – Channels to draw, each (out_port, in_port) or (out_port, in_port, mode_out, mode_in). Without arguments the reflection channel of every excitation.

  • mark (array_like, optional) – Frequencies [Hz] to mark and label on every trace.

  • labels (bool, default True) – Draw the resistance labels of the chart’s grid.

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

Returns:

  • fig (matplotlib.figure.Figure)

  • ax (matplotlib.axes.Axes)

reference_impedance(port, mode=0)#

Reference impedance [Ω] of one channel along the frequency axis.

The real impedance the channel’s power waves — and so its row and column of the S-matrix — are defined against: the line impedance of a TEM or quasi-TEM port mode as the grid carries it, the wave impedance of a hollow-pipe mode (which varies with frequency), the Thévenin impedance of a lumped port. Full-model values on ports cut by a symmetry plane. See renormalize() for moving to a common reference.

Parameters:
  • port (str)

  • mode (int)

Return type:

ndarray

renormalize(z_ref)#

Re-reference the S-matrix to new port impedances.

The raw S-matrix is measured against each port mode’s own impedance on the grid (reference_impedance()) — a uniform line is matched there whatever its impedance came out at. This returns the same network against z_ref instead, typically renormalize(50): what a network analyser with 50 Ω reference planes would read, and what a circuit simulator expects before it cascades this block with others. It acts on the square matrix over the excited channels: a channel that was observed but never excited stays matched to its own impedance and is left out, as the exports leave it out.

Whether the re-referenced mismatch is real is a modelling question: a 49 Ω grid line feeding a 50 Ω system does reflect, while a line meant to be the 50 Ω one shows a discretisation artefact — converge its impedance on the port plane first (refine_port_modes).

Parameters:

z_ref (float or dict) – New real reference impedance [Ω] for every channel, or a mapping {port_name: Z} / {(port, mode): Z}, each value a scalar or an array on the frequency axis.

Returns:

A new result on the same channels; the original is untouched. It answers S / db / phase / plot_s and the Touchstone / scikit-rf exports.

Return type:

SParameterResult

to_skrf(name='magnelio', *, channels=None, z_ref=None)#

Return the S-matrix as a skrf.Network.

Requires scikit-rf (extra magnelio[interop]). Same sub-matrix, channel selection and warning as to_touchstone(); the network’s z0 carries each channel’s reference impedance per frequency.

Parameters:
  • name (str, optional) – Network name.

  • channels (sequence of str or (str, int), optional) – Explicit channel selection, as in to_touchstone().

  • z_ref (float or dict, optional) – Renormalise first, as in renormalize().

Return type:

skrf.Network

to_touchstone(path, *, channels=None, z_ref=None)#

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

Exports the square sub-matrix over the excited channels — one Touchstone port per channel, so a multi-mode port occupies one port per mode. Channels that were observed but never excited are dropped from rows and columns alike; they carry a reflection-free boundary throughout the run, so the export is the network seen with them matched, the same quantity a network analyser measures with its unused ports terminated.

The option line’s R states the reference impedance the data refer to. Touchstone 1.x holds one constant value for all ports, so pass z_ref (typically z_ref=50) to renormalise first when the ports’ own references differ or vary with frequency; without it such a file is written with a nominal R 50, a warning, and each port’s actual reference in the header.

Warns when a port that is exported carries propagating modes that the export leaves out: the file then looks like a complete N-port while the mode conversion at that port is missing from it.

The .sNp extension must agree with the number of exported channels — Touchstone records the port count nowhere else — so a mismatch raises instead of writing an unreadable file. A path without an extension gets the matching one.

Parameters:
  • path (str or pathlib.Path) – Output file. <name>.s{N}p, or <name> to have the extension filled in.

  • channels (sequence of str or (str, int), optional) – Select the exported sub-network explicitly, e.g. ["port1", "port3"] to cut a two-port out of a fully excited three-port. A bare port name means mode 0. Every entry must have been excited.

  • z_ref (float or dict, optional) – Renormalise to this reference before writing, as in renormalize().

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.

class magnelio.analysis.TDResult(excitations, dt, n_steps, signals, excitation_signals, energy_trace=None, monitors=<factory>, port_modes=None, port_normal_dx=None, port_line_params=None, settings=None, name=None, started=None, finished=None, elapsed=None)#

Result of one AnalysisTD.run() call — one leapfrog march.

Parameters:
  • excitations (tuple)

  • dt (float)

  • n_steps (int)

  • signals (dict)

  • excitation_signals (dict)

  • energy_trace (ndarray | None)

  • monitors (dict)

  • port_modes (dict | None)

  • port_normal_dx (dict | None)

  • port_line_params (dict | None)

  • settings (RunSettings | None)

  • name (str | None)

  • started (object | None)

  • finished (object | None)

  • elapsed (float | None)

excitations#

The excitations that drove the run, with the waveform each one resolved to (the per-mode default where none was given).

Type:

tuple of Excitation

dt#

Solver time step [s].

Type:

float

n_steps#

Number of leapfrog steps executed; every time series below has this many samples.

Type:

int

signals#

Recorded modal voltage and current (V, I) of every port channel, on the time axis t. V is the total modal voltage; use a() / b() for the incident/outgoing split.

Type:

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

excitation_signals#

The drive of every excitation sampled on the same axis — amplitude and delay included — keyed like excitations.

Type:

dict[(str, int), Signal1D]

energy_trace#

Stored electromagnetic energy at the solver’s check cadence, a structured array with step, time and energy fields.

Type:

np.ndarray or None

monitors#

The run’s monitors by name, holding their recorded data. Frequency-domain monitors keep the raw transient bins: with several waveforms in one run there is no single reference spectrum to divide out, so renormalize() is your call.

Type:

dict[str, Monitor]

port_modes, port_normal_dx, port_line_params

The port records behind a() / b().

Type:

dict or None

settings#

The settings this run was produced with, including why the marching stopped.

Type:

RunSettings or None

name#

The run’s name in a project store; None for an in-RAM run.

Type:

str or None

started, finished

Wall-clock stamps (UTC) of the march’s start and end.

Type:

datetime or None

elapsed#

Wall time of the march [s]; for a run read back from a project store the sum over every march of the run, resumes included.

Type:

float or None

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

Incident power wave a(t) [√W] of one port channel.

Parameters:
  • port (str) – The channel.

  • mode (int) – The channel.

  • f_ref (float, optional) – Frequency [Hz] at which the modal reference impedance is evaluated; default the centre of the excitations’ band.

  • destagger (bool, default True) – Use the port’s certified discrete line parameters for the V/I half-cell alignment (the S-parameter convention).

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

Outgoing power wave b(t) [√W] of one port channel (see a()).

Parameters:
  • port (str)

  • mode (int)

  • f_ref (float | None)

  • destagger (bool)

excitation_signal(name, mode=0)#

The sampled drive of the excitation naming name (and mode on a port).

Parameters:
  • name (str)

  • mode (int)

Return type:

Signal1D

plot_energy(*, x='time', floor_db=None, ax=None)#

Plot the stored energy in dB below its peak over the run.

The figure the progress line reports, over the whole run, with the energy criterion as a dashed line when the run had one. x is "time" (nanoseconds) or "step"; the axis runs from ten dB below the criterion (floor_db pins it) to +5 dB; ax draws into existing axes. Returns (fig, ax).

Parameters:
  • x (str)

  • floor_db (float | None)

plot_signals(ax=None, *, kind='V', **kwargs)#

Plot every recorded port signal of one kind over time.

Parameters:
  • ax (matplotlib.axes.Axes, optional) – Target axes; a new figure when omitted.

  • kind ({"V", "I"}, default "V") – Modal voltage or current.

  • **kwargs – Forwarded to ax.plot.

Returns:

The matplotlib (figure, axes) pair.

Return type:

tuple

renormalize(name, mode=0)#

Divide the frequency-domain monitors by one excitation’s spectrum.

Turns the raw transient bins of every MonitorFieldFrequency and MonitorFarFieldFrequency into the response per unit of the named excitation — fields per 1 √W incident on a port, per 1 V/m of an incident plane wave. Meaningful when that excitation is the only one, or the only one with energy at the monitor frequencies.

Parameters:
  • name (str)

  • mode (int)

Return type:

None

signal(port, mode=0, kind='V')#

A recorded port signal: modal voltage ("V") or current ("I").

Parameters:
  • port (str)

  • mode (int)

  • kind (str)

Return type:

Signal1D

property stop_reason: str | None#

Why the marching ended ("energy", "port_signal", "steps", …).

property t: ndarray#

Time axis of every recorded series [s].