Conditions, switching matrix, and path corrections¶
Path corrections connect transmission paths represented by a DOT graph to the quantities that were actually measured. A frequency-dependent setup must coordinate three steps:
select active graph branches;
set real instruments and the switching matrix to the frequency;
read and apply the correction of the active path.
The DOT reference fully documents nodes,
edges, conditions, and the dev/what attributes.
Correction values are commonly supplied through an INI channel and a DAT file. Syntax, units, complex values, and uncertainty are documented in the INI and DAT reference.
Evaluating conditions¶
EvaluateConditions activates nodes and edges using the explicit context:
mg.EvaluateConditions(context={"frequency": frequency})
With doAction=False, it computes graph state only. This is important for
preflight, scan planning, and path validation because those operations must
not switch hardware.
An active element may additionally provide an action attribute. Only a
direct method call on an object from the context with literal arguments is
executed. Arbitrary Python code is not permitted. Actions are suitable for
small explicitly configured state changes; prefer the driver for
instrument-specific switching logic.
A small matrix may alternatively be switched directly through actions:
SwitchLF [condition="FREQUENCY <= 1e9"
action="switch.switch_to(0)"]
SwitchHF [condition="FREQUENCY > 1e9"
action="switch.switch_to(1)"]
mg.EvaluateConditions(context={
"frequency": frequency,
"switch": switch_instance,
})
This approach and a frequency-dependent SetFreq implementation in the
switch driver are alternatives. Do not set the same relay state through both
paths at once.
Switching matrix through SetFreq¶
A switching matrix is a regular MGraph instrument. Its driver implements
SetFreq(frequency) and selects the required relay state from its INI
configuration. SetFreq_Devices invokes this method together with the
other frequency-dependent instruments:
mg.EvaluateConditions(context={"frequency": frequency})
mg.SetFreq_Devices(frequency)
Conditions and the driver’s switching threshold must use the same range
boundaries. For example, the graph selects the LF branch up to and including
1 GHz while the switch driver chooses the same relay state for f <= 1e9.
Before switching, reset a signal generator to a safe initial level or disable RF. This is particularly important when changing frequency activates a different amplifier with a different input limit.
More complex TEM example¶
digraph {
Switch [ini="sw_gtem.ini"]
Sg [ini="sg.ini"]
AmpLF [ini="amp-lf.ini"
condition="FREQUENCY <= 1e9"]
AmpHF [ini="amp-hf.ini"
condition="FREQUENCY > 1e9"]
PathSgLF [ini="sg-lf.ini"]
PathSgHF [ini="sg-hf.ini"]
PathLFCell [ini="lf-cell.ini"]
PathHFCell [ini="hf-cell.ini"]
Sg -> SgLF [condition="FREQUENCY <= 1e9"]
Sg -> SgHF [condition="FREQUENCY > 1e9"]
SgLF -> AmpInLF [dev=PathSgLF what="S21"]
SgHF -> AmpInHF [dev=PathSgHF what="S21"]
AmpInLF -> AmpOutLF [dev=AmpLF what="S21"]
AmpInHF -> AmpOutHF [dev=AmpHF what="S21"]
AmpOutLF -> GTEM [dev=PathLFCell what="S21"]
AmpOutHF -> GTEM [dev=PathHFCell what="S21"]
}
The condition context selects the red or blue correction path. In
parallel, SetFreq_Devices sets the switching matrix and all active
instruments to the same frequency.¶
This simplified example shows the forward path only. A real TEM verification adds branches to forward and reverse power meters, including their coupler and cable corrections.
Reading the total correction¶
get_path_correction returns the total correction between two measurement
positions:
from mpylab.tools.aunits import POWERRATIO
correction = mg.get_path_correction(
names["sg"],
names["port"],
POWERRATIO,
)
Without unit, it returns AMPLITUDERATIO. Converting a complex
amplitude ratio to a power ratio uses abs(S21) ** 2. Units and uncertainty
are preserved.
get_path_corrections additionally returns the individual correction
elements. Its "total" key contains the combined result:
details = mg.get_path_corrections("Sg", "GTEM")
total = details["total"]
This detailed form is useful for diagnostics and reports. Application logic
should normally use get_path_correction for the total correction.
Coherent series and parallel paths¶
All active paths are combined as complex amplitude ratios, regardless of the requested output unit:
POWERRATIO is formed only after this sum (and any reference-path division).
For two unit-amplitude contributions, phase differences of 0, 90 and 180 degrees
therefore give power ratios of 4, 2 and 0. A series path multiplies complex
amplitudes; phases add. Shared segments retain the same uncertain inputs.
An S-parameter magnitude d in dB corresponds to amplitude
10**(d/20). Polar DAT values retain their phase. The historical DAT
representation POWERRATIO encodes |S21|**2 * exp(1j*phase); it is
converted back to amplitude before composition. It must not be interpreted
as a physical complex power. A scalar magnitude-only input implicitly assumes
zero phase and cannot establish the interference of an actual parallel setup.
The model assumes coherent contributions of one source with consistent wave normalization and negligible or already included reflection effects. Splitting and combining coefficients must be included in the configured transfer paths. The factor of four above is relative to one unit contribution at the summation point; it does not imply passive power gain from splitting one source. Full S-matrix networks, mismatch, and incoherent power addition are outside this model. For the wave conventions, see F. Caspers, RF engineering basic concepts: S-parameters.
get_path_correction(end, start) returns the inverse correction, not S12.
A zero denominator raises ZeroDivisionError; missing connectivity raises
ValueError. get_path_corrections retains zero for an absent forward
path and unity for an empty path from a node to itself. Its device entries
remain the original quantities; only "total" follows the requested unit.
Each device/channel is read once per query, including common-parent reference
ratios. A subsequent query reads it again, so frequency changes cannot reuse
stale values.
Uncertainty at cancellation¶
The result retains SCUQ expression dependencies instead of replacing each path
with an independent uncertainty input. Mixed real and complex expressions keep
shared scalar inputs, too. Complex power uses the Cartesian squared magnitude
with Jacobian (2*Re(H), 2*Im(H)); this avoids differentiating abs(H)
at zero.
SCUQ still propagates uncertainty to first order. At nominal cancellation that Jacobian is zero even when independent amplitude errors produce nonzero power in realizations. Thus a zero first-order power uncertainty is not evidence of exact cancellation. Retain the amplitude covariance and use a suitable higher-order or Monte Carlo evaluation for such cases. The regression tests include analytic interference, shared-input cancellation, and reproducible Monte Carlo comparisons illustrating this limit.
Compatibility¶
The INI/DAT format and diagnostic dictionary keys are unchanged. Previously,
requesting POWERRATIO added path powers or retained an encoded transfer
phase; corrected results can therefore differ for parallel or phased paths.
Stored measurement values are not rewritten automatically. Re-evaluation uses
the corrected calculation. Returned corrections retain SCUQ expressions;
new pickles containing these expressions require an mpylab version providing
the transfer-expression helpers.
Applying a correction¶
Select the direction explicitly according to the physical calculation:
corrected = mg.apply_path_correction(
measured,
correction,
operation="divide",
magnitude=True,
output_unit=VOLT,
)
operation is "multiply" or "divide". magnitude=False
preserves phase; magnitude=True produces a real magnitude quantity with
uncertainty.
Fast repeated application¶
When processing many values with the same correction, prepare it once:
prepared = mg.prepare_path_correction(
correction,
operation="divide",
magnitude=True,
output_unit=VOLT,
)
corrected = [
mg.apply_path_correction(value, prepared)
for value in measured_values
]
An exactly known constant correction can then use a fast scaling path. Uncertain and unsupported cases automatically fall back to the complete SCUQ calculation.
Reuse the prepared object only while frequency, active graph path, and
underlying calibration data remain unchanged. Read and, where appropriate,
prepare the correction again after every EvaluateConditions call or
frequency change.
Validation rules¶
Evaluate conditions before reading a correction.
Configure switching matrix and graph with identical range boundaries.
Test boundary frequencies for missing or duplicate paths.
Keep corrections as SCUQ quantities.
State multiplication or division and phase removal explicitly.
Do not reuse prepared corrections across a graph-state change.