Process reference: magnetics
Generated from the docstrings of vaft.process.magnetics:
16 public functions. Each entry is what
vaft.process.describe("magnetics.<name>") prints.
All process categories
Overview
Three groups, with different provenance and different applicability.
Sensor geometry is pure arithmetic on a layout: where the array’s centre is and what poloidal angle each sensor sits at.
The legacy VEST equilibrium chain is the ported workflow that turns raw
magnetic diagnostic records into the currents and fluxes an equilibrium
reconstruction consumes. Its functions are named vest_*, are
VEST-specific, and carry shot-era acquisition policy: which samples the
output window covers, and which samples the baseline is fitted over, both
depend on the shot number. Those policies live in vest.yaml and reach
these functions through a configuration record.
Mode analysis conditions Mirnov coil signals and extracts a toroidal mode number, either from the cross-spectral phase of a pair or from a wrapped-phase fit across an array.
| Symbol | Meaning | Unit |
|---|---|---|
| V | coil terminal voltage | V |
| Phi | poloidal flux through a loop | Wb |
| B_p | poloidal field at a probe | T |
| I_p | plasma current | A |
| n | toroidal mode number | - |
| f | frequency | Hz |
Integration carries Faraday’s minus sign, applied before the baseline is removed. A flux loop’s flux is the negative time integral of its voltage, and a poloidal probe’s field likewise; the constant of integration is absorbed into the fitted baseline rather than chosen separately. Flux is stored per radian, which the ODS mapper multiplies back by two pi.
The two generic integrating routines hedge their sign and the VEST ones
state it. flux_loop_flux and b_field_pol_probe_field say the minus
applies “if that is the convention”, because they take whatever a caller hands
them; the vest_* functions know their own diagnostics and assert it. That
difference is deliberate and is preserved rather than harmonized.
Plasma-current polarity is inferred from the data, not asserted.
rogowski_coil_ip flips the sign when the negative excursion dominates,
which is the one place in the module where a convention is decided by the
signal rather than declared.
Toroidal mode numbers adhere to standard right-handed cylindrical coordinates.
Coordinates (R, phi, Z) are oriented such that phi increases counter-clockwise
when viewed from above. A positive toroidal mode number (n > 0) denotes a
perturbation propagating in the positive phi direction (co-current / toroidal
direction). Across toroidally separated sensors, the signal phase varies as
theta(phi) = theta_0 - n * phi (negative phase slope d(theta)/d(phi) = -n). For
two coils separated by toroidal angle Delta_phi = phase_geometry > 0, the
cross-spectral phase of the downstream coil relative to the upstream coil is
Delta_theta = -n * Delta_phi, so the mode number is n = -Delta_theta / Delta_phi.
Both toroidal_mode_analysis and toroidal_phase_fit_at_time
share this convention.
Functions
b_field_pol_probe_field | Poloidal field from raw probe records, filtered before integration. Convention |
flux_loop_flux | Poloidal flux from raw flux-loop records, with a two-sided baseline. Convention |
magnetics_sensor_centre | Geometric centre of a magnetic sensor layout. Convention |
magnetics_sensor_poloidal_angle | Poloidal angle of each sensor about the layout centre. Convention |
mirnov_preprocess_signal | Condition a Mirnov coil signal for mode analysis. Convention |
mirnov_spectrogram | Sliding-window amplitude spectrogram of a Mirnov signal. Convention |
rogowski_coil_ip | Plasma current from a Rogowski coil, compensated by a flux-loop reference. Convention |
toroidal_mode_analysis | Toroidal mode number from the cross-spectral phase of two coils. Convention |
toroidal_phase_fit_at_time | Toroidal mode numbers from a wrapped-phase fit across an array, at one time. Convention |
vest_b_field_pol_probe_legacy | Poloidal field at a VEST probe, from its raw record. Convention |
vest_equilibrium_magnetics_detailed | Process every magnetic channel of one VEST shot onto the output window. Convention |
vest_equilibrium_magnetics_signals | The processed magnetics of one VEST shot, as the three-array legacy view. Convention |
vest_flux_loop_flux_from_voltage | Poloidal flux through a VEST flux loop, from its calibrated voltage. Convention |
vest_flux_loop_legacy | Poloidal flux through a VEST flux loop, from its raw record. Convention |
vest_flux_loop_voltage | Calibrated flux-loop terminal voltage, before integration. Convention |
vest_magnetics_time_window | The output time window a VEST shot’s magnetics are resampled onto. Convention |
No function matches.
b_field_pol_probe_field
Machine-independentConvention-sensitive
source
b_field_pol_probe_field(time, raw, gain, lowpass_param, baseline_onset=0.27, baseline_offset=0.28, baseline_type='linear', baseline_onset_window=500, baseline_offset_window=100)
Poloidal field from raw probe records, filtered before integration.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Time base. |
raw | array_like | V | Raw records, one column per probe. |
gain | array_like | - | Gain per probe. |
lowpass_param | Any | - | Low-pass specification applied before integration. |
baseline_onset | float, optional | s | Time at which the signals begin to deviate. |
baseline_offset | float, optional | s | Time by which they have returned. |
baseline_type | str, optional | - | Which model to fit as the baseline. |
baseline_onset_window | int, optional | - | Samples before the onset to include in the fit. |
baseline_offset_window | int, optional | - | Samples after the offset to include. |
| Returns | |||
| — | tuple of np.ndarray | - | The field per probe in tesla, together with the intermediate stages the caller may want to inspect. |
Convention
Gain first, then filter, which is the order this routine is named for and differs from the VEST chain’s. The leading minus is Faraday’s, applied as the caller’s system defines it rather than asserted; see this module’s conventions.
Filtering before integration matters: integrating first would accumulate the noise the filter is there to remove.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Apply the per-probe gain.
- Low-pass each column.
- Integrate in time, carrying the minus sign.
- Fit and subtract the two-sided baseline per column.
Defaults
The onset, offset and window lengths are machine-specific VEST values.
Applicability
Machine-independent. Every machine number is an argument.
Limitations
Assumes the record is quiet either side of the baseline window. This is the routine the fluctuation module points at as the canonical path from pickup voltage to field, and a spectrum taken before this step is a derivative spectrum, not a field one.
Provenance
- The legacy VEST probe chain, kept here in a machine-independent form;
vaft.process.fluctuationfor why the integration must precede a spectral index.
flux_loop_flux
Machine-independentConvention-sensitive
source
flux_loop_flux(time, raw, gain, baseline_onset=0.27, baseline_offset=0.28, baseline_type='linear', baseline_onset_window=500, baseline_offset_window=100)
Poloidal flux from raw flux-loop records, with a two-sided baseline.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Time base. |
raw | array_like | V | Raw records, one column per loop. |
gain | array_like | - | Gain per loop. |
baseline_onset | float, optional | s | Time at which the signals begin to deviate. |
baseline_offset | float, optional | s | Time by which they have returned. |
baseline_type | str, optional | - | Which model to fit as the baseline. |
baseline_onset_window | int, optional | - | Samples before the onset to include in the fit. |
baseline_offset_window | int, optional | - | Samples after the offset to include. |
| Returns | |||
| — | np.ndarray | Wb/rad | Flux through each loop, per radian. |
Convention
Per radian, and the leading minus is Faraday’s – but this is the generic routine, so it applies the sign the caller’s system uses rather than asserting one. The VEST chain asserts it instead; see this module’s conventions for why the two differ deliberately.
The baseline is fitted on both sides of the discharge, before the onset and after the offset, which anchors a drifting integration at both ends rather than extrapolating from one.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Apply the per-loop gain.
- Integrate in time and divide by two pi.
- Fit a baseline over the quiet samples either side of the discharge and subtract it per loop.
Defaults
The onset, offset and window lengths are machine-specific VEST values, mirroring the discharge timing of that machine. A caller on another machine passes its own.
Applicability
Machine-independent. Every machine number is an argument.
Limitations
Assumes the record is genuinely quiet either side of the window given. A discharge that has not returned to baseline by the offset biases the fit.
Provenance
- The two-sided baseline convention of the legacy VEST workflow, kept here in a machine-independent form.
magnetics_sensor_centre
Machine-independentConvention-sensitive
source
magnetics_sensor_centre(r, z)
Show source vaft/process/magnetics.py, lines 131–197
def magnetics_sensor_centre(r, z):
"""Geometric centre of a magnetic sensor layout.
Parameters
----------
r : array_like
Major radius of each sensor [m].
z : array_like
Height of each sensor [m].
Returns
-------
tuple of float
The centre as major radius and height [m].
Convention
----------
A layout counts as **two clusters** -- an inboard and an outboard array --
when the widest gap in major radius spans at least a set fraction of the
radial extent; a ring of sensors around the plasma has gaps far smaller than
that. The two cases need different centres: a ring's centre is the median of
its sensors, while two clusters take the midpoint between them, because the
median of a two-cluster layout lands inside whichever cluster has more
sensors rather than between them.
The median is used rather than the mean so that an unevenly populated ring
does not drag the centre toward its dense side.
Defaults
--------
The cluster gap fraction is a numerical convenience separating the two
layouts; a real ring and a real two-cluster array sit far either side of it.
Applicability
-------------
Machine-independent. The VEST case is an example: an inboard array against a
wall array further out is the two-cluster geometry this distinguishes.
Limitations
-----------
Two cases only. Three or more clusters, or a layout that is neither, gets
whichever branch its widest gap selects.
Provenance
----------
.. [1] Issue #486, which established this definition of the layout centre.
"""
from vaft.plot.selection import classify_regions, radial_divider
r = np.asarray(r, dtype=float).ravel()
z = np.asarray(z, dtype=float).ravel()
finite = np.isfinite(r) & np.isfinite(z)
if not np.any(finite):
raise ValueError("a sensor centre needs at least one finite (r, z) position")
r, z = r[finite], z[finite]
r0 = float(np.mean(r))
split = radial_divider(r)
extent = float(r.max() - r.min())
if split and extent > 0.0:
regions = np.asarray(classify_regions(r, split=split))
inboard = r[regions == "inboard"]
outboard = r[regions == "outboard"]
if inboard.size and outboard.size:
gap = float(outboard.min() - inboard.max())
if gap >= MAGNETICS_CLUSTER_GAP_FRACTION * extent:
r0 = 0.5 * (float(np.median(inboard)) + float(np.median(outboard)))
return r0, float(np.median(z))Geometric centre of a magnetic sensor layout.
| Name | Type | Unit | Description |
|---|---|---|---|
r | array_like | m | Major radius of each sensor. |
z | array_like | m | Height of each sensor. |
| Returns | |||
| — | tuple of float | m | The centre as major radius and height. |
Convention
A layout counts as two clusters – an inboard and an outboard array – when the widest gap in major radius spans at least a set fraction of the radial extent; a ring of sensors around the plasma has gaps far smaller than that. The two cases need different centres: a ring’s centre is the median of its sensors, while two clusters take the midpoint between them, because the median of a two-cluster layout lands inside whichever cluster has more sensors rather than between them.
The median is used rather than the mean so that an unevenly populated ring does not drag the centre toward its dense side.
Defaults · Applicability · Limitations · Provenance
Defaults
The cluster gap fraction is a numerical convenience separating the two layouts; a real ring and a real two-cluster array sit far either side of it.
Applicability
Machine-independent. The VEST case is an example: an inboard array against a wall array further out is the two-cluster geometry this distinguishes.
Limitations
Two cases only. Three or more clusters, or a layout that is neither, gets whichever branch its widest gap selects.
Provenance
- Issue #486, which established this definition of the layout centre.
magnetics_sensor_poloidal_angle
Machine-independentConvention-sensitive
source
magnetics_sensor_poloidal_angle(r, z, centre=None)
Show source vaft/process/magnetics.py, lines 200–251
def magnetics_sensor_poloidal_angle(r, z, centre=None):
"""Poloidal angle of each sensor about the layout centre.
Parameters
----------
r : array_like
Major radius of each sensor [m].
z : array_like
Height of each sensor [m].
centre : tuple of float, optional
The centre to measure about; computed from the layout when omitted [m].
Returns
-------
np.ndarray
Poloidal angle of each sensor, on the interval from zero to a full turn
[rad].
Convention
----------
Measured from the layout centre, counter-clockwise from the outboard
midplane, and wrapped to a single positive turn rather than centred on zero.
**This is not the IMAS poloidal angle of a probe**, which describes the
orientation of the probe's sensitive axis rather than its position; on VEST
every vertical-field probe has the same IMAS angle wherever it sits. Confusing
the two puts every probe at the same place.
Applicability
-------------
Machine-independent.
Limitations
-----------
Inherits the two-case centre rule of :func:`magnetics_sensor_centre` when the
centre is not supplied, so a layout that fits neither case gets angles about a
centre that may not be where the caller expects.
Provenance
----------
.. [1] The IMAS data dictionary's own poloidal-angle definition, which this
deliberately differs from.
"""
r = np.asarray(r, dtype=float)
z = np.asarray(z, dtype=float)
if centre is None:
centre = magnetics_sensor_centre(r, z)
r0, z0 = float(centre[0]), float(centre[1])
angle = np.mod(np.arctan2(z - z0, r - r0), 2.0 * np.pi)
# A sensor on the outboard midplane a rounding error below Z = 0 wraps to
# 2*pi; it belongs at 0.
return np.where(np.isclose(angle, 2.0 * np.pi), 0.0, angle)Poloidal angle of each sensor about the layout centre.
| Name | Type | Unit | Description |
|---|---|---|---|
r | array_like | m | Major radius of each sensor. |
z | array_like | m | Height of each sensor. |
centre | tuple of float, optional | m | The centre to measure about; computed from the layout when omitted. |
| Returns | |||
| — | np.ndarray | rad | Poloidal angle of each sensor, on the interval from zero to a full turn |
Convention
Measured from the layout centre, counter-clockwise from the outboard midplane, and wrapped to a single positive turn rather than centred on zero.
This is not the IMAS poloidal angle of a probe, which describes the orientation of the probe’s sensitive axis rather than its position; on VEST every vertical-field probe has the same IMAS angle wherever it sits. Confusing the two puts every probe at the same place.
Applicability · Limitations · Provenance
Applicability
Machine-independent.
Limitations
Inherits the two-case centre rule of magnetics_sensor_centre when the
centre is not supplied, so a layout that fits neither case gets angles about a
centre that may not be where the caller expects.
Provenance
- The IMAS data dictionary’s own poloidal-angle definition, which this deliberately differs from.
mirnov_preprocess_signal
Machine-independentConvention-sensitive
source
mirnov_preprocess_signal(data, *, sample_rate=250000.0, high_pass_cutoff=2000.0, low_pass_cutoff=90000.0, amplifier_gain=1.0, filter_order=None)
Condition a Mirnov coil signal for mode analysis.
| Name | Type | Unit | Description |
|---|---|---|---|
data | array_like | V | Raw coil record. |
sample_rate | float, optional | Hz | Sample rate. |
high_pass_cutoff | float, optional | Hz | Lower edge of the passband. |
low_pass_cutoff | float, optional | Hz | Upper edge. |
amplifier_gain | float, optional | - | Gain divided out of the record. |
filter_order | int, optional | - | Filter order; derived from the sample rate when omitted. |
| Returns | |||
| — | np.ndarray | V | The conditioned record. |
Convention
Band-passed rather than low-passed, because mode analysis wants neither the slow equilibrium evolution below the band nor the noise above it. The output is still a time derivative: nothing here integrates, so a spectral index taken from this is a derivative index, not a field one.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Remove the record’s mean.
- Band-pass it with a windowed filter.
- Divide out the amplifier gain.
Defaults
The sample rate and the two band edges are acquisition-era values, the VEST Mirnov amplifier chain’s own. The order is derived from the sample rate, one tap per millisecond, and forced odd, which is a numerical convenience keeping the filter symmetric.
Applicability
Machine-independent. The defaults are VEST’s chain; every one is an argument.
Limitations
The derived order scales with the sample rate, so a very high rate gives a long filter and a correspondingly long transient at each end.
Provenance
- The legacy
vest_oscMirnov preprocessing chain, whose stage order and band edges this reproduces.
mirnov_spectrogram
Machine-independentConvention-sensitive
source
mirnov_spectrogram(time, data, *, sample_rate=None, window_size=500, time_resolution=1, time_range=None)
Sliding-window amplitude spectrogram of a Mirnov signal.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Time base. |
data | array_like | V | Conditioned coil record. |
sample_rate | float, optional | Hz | Sample rate; derived from the time base when omitted. |
window_size | int, optional | - | Window length in samples. |
time_resolution | int, optional | - | Step between windows, in samples. |
time_range | sequence of float, optional | s | Analysis window as a start and end time. |
| Returns | |||
| — | MirnovSpectrogramResult | - | The time and frequency axes and the amplitude map. |
Convention
Amplitude, not power: the transform is normalized so a sinusoid appears at its own amplitude, which is the single-sided convention that makes a mode’s size directly readable. That differs from the power spectral density in the fluctuation module, which is squared and per hertz.
The field names match that module’s own spectrogram result, so the plotting layer accepts either.
Defaults · Applicability · Limitations · Provenance
Defaults
The window and step are validated-workflow defaults from the legacy Mirnov routine.
Applicability
Machine-independent.
Limitations
Fixed window, so the time and frequency resolution trade off once for the
whole map. Expects a conditioned input; run
mirnov_preprocess_signal first.
Provenance
- The legacy
vest_mirnovroutine, whose window and normalization this reproduces.
rogowski_coil_ip
Machine-independentConvention-sensitive
source
rogowski_coil_ip(time, rogowski_raw, flux_loop_raw, flux_loop_gain=11, effective_vessel_res=0.00058, baseline_onset=0.27, baseline_offset=0.28, baseline_type='linear', baseline_onset_window=500, baseline_offset_window=100, smooth_window=10)
Plasma current from a Rogowski coil, compensated by a flux-loop reference.
A Rogowski coil encircles both the plasma and the vessel current, so its signal is not the plasma current alone. A flux loop supplies the reference that removes the vessel’s share.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Time base. |
rogowski_raw | array_like | A | Raw Rogowski record, already a current-like signal. |
flux_loop_raw | array_like | V | Raw flux-loop record used as the vessel reference. |
flux_loop_gain | float, optional | A/V | Scales the reference into current units. |
effective_vessel_res | float, optional | ohm | Effective vessel resistance. Accepted but not used. |
baseline_onset | float, optional | s | Time at which the signals begin to deviate. |
baseline_offset | float, optional | s | Time by which they have returned. |
baseline_type | str, optional | - | Which model to fit as the baseline. |
baseline_onset_window | int, optional | - | Samples before the onset to include in the fit. |
baseline_offset_window | int, optional | - | Samples after the offset to include. |
smooth_window | int, optional | - | Smoothing width applied to the reference, odd. |
| Returns | |||
| — | np.ndarray | A | The plasma current. |
Convention
Polarity is inferred from the data, not asserted. If the result’s negative peak exceeds its positive one the whole trace is flipped, on the assumption that a discharge is a single-signed excursion. This is the one place in the module where a sign convention is decided by the signal rather than declared, and it is wrong for any record whose largest excursion is not the plasma current.
No integration happens here: the Rogowski input is already current-like.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Fit a baseline over the quiet samples either side of the discharge and subtract it from both records.
- Scale the flux-loop record into a current reference.
- Smooth that reference.
- Subtract it from the Rogowski record.
- Flip the sign if the negative excursion dominates.
Defaults
The gain and the two baseline times are machine-specific VEST values. The smoothing width and the two window lengths are numerical conveniences. The vessel resistance is hard-coded and unused: it is accepted for compatibility, the dimensional argument for it being a resistance rather than an inductance is recorded in issue #214, and no code path reads it.
Applicability
Machine-independent. Every machine number is an argument, and the defaults are VEST’s.
Limitations
The compensation is a scaled subtraction, not a circuit model, so it removes the vessel’s share only to the extent that share is proportional to the flux loop’s signal. The sign inference above can invert a correct trace. Assumes the record is quiet either side of the baseline window.
Provenance
- Issue #214, which records the dimensional argument for the unused vessel resistance and the flux-loop compensation it belongs to.
toroidal_mode_analysis
Machine-independentConvention-sensitive
source
toroidal_mode_analysis(signal_a, signal_b, *, sample_rate=250000.0, phase_geometry=0.5235987755982988, peak_threshold=0.1, sensor_count=4, nperseg=None)
Toroidal mode number from the cross-spectral phase of two coils.
| Name | Type | Unit | Description |
|---|---|---|---|
signal_a | array_like | V | Conditioned record from the first coil. |
signal_b | array_like | V | Conditioned record from the second. |
sample_rate | float, optional | Hz | Sample rate. |
phase_geometry | float, optional | rad | Toroidal angle of the second coil minus the first coil, phi_b - phi_a. |
peak_threshold | float, optional | - | Fraction of the maximum a peak must reach to be reported. |
sensor_count | int, optional | - | Number of sensors averaged, which sets the coherence significance. |
nperseg | int, optional | - | Segment length of the cross-spectral estimate. |
| Returns | |||
| — | ToroidalModeResult | - | The coherent peaks with their frequency, phase and mode number. |
Convention
The mode number carries a minus sign: n_raw = -phase / phase_geometry.
Under standard right-handed cylindrical coordinates (R, phi, Z) with phi
counter-clockwise from above, a mode propagating in the co-current (+phi)
direction has phase decreasing with increasing phi (theta(phi) = theta_0 -
n * phi, so d(theta)/d(phi) = -n). A sensor at Delta_phi > 0 lags the
reference sensor by Delta_theta = -n * Delta_phi, so n = -Delta_theta /
Delta_phi. This agrees with the model fitted by
toroidal_phase_fit_at_time.
The coherence threshold is the 95 percent significance level for a magnitude-squared coherence averaged over the given number of sensors, so it tightens as more are averaged rather than being a fixed number.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Estimate the cross-spectral density and the coherence of the pair.
- Keep frequencies whose coherence exceeds the significance level.
- Find the peaks among them above the threshold.
- Divide the negative of each peak’s phase by the toroidal separation to get its mode number.
Defaults
The sample rate, the toroidal separation and the sensor count are machine-specific: they are the VEST array’s spacing and size. The peak threshold is hard-coded with no recorded derivation.
Applicability
Machine-independent. The array geometry is an argument.
Limitations
Two coils cannot resolve aliasing: a mode and one differing by a full turn over the separation give the same phase. Nothing here reports the degeneracy, unlike the soft X-ray equivalent, which returns every candidate.
Provenance
- The magnitude-squared coherence significance level for an averaged estimate, which sets the threshold.
toroidal_phase_fit_at_time
Machine-independentConvention-sensitive
source
toroidal_phase_fit_at_time(time, signals, toroidal_angle, *, center_time, sample_rate=None, window_size=500, frequencies=None, num_modes=2, candidate_n=(-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6), peak_threshold=0.1)
Toroidal mode numbers from a wrapped-phase fit across an array, at one time.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Time base. |
signals | array_like | V | Conditioned records, one row per coil. |
toroidal_angle | array_like | rad | Toroidal angle of each coil. |
center_time | float | s | Centre of the analysis window. |
sample_rate | float, optional | Hz | Sample rate; derived from the time base when omitted. |
window_size | int, optional | - | Window length in samples. |
frequencies | array_like, optional | Hz | Frequencies to fit; the strongest peaks when omitted. |
num_modes | int, optional | - | How many mode lines to fit. |
candidate_n | sequence of int, optional | - | Mode numbers to consider. |
peak_threshold | float, optional | - | Fraction of the maximum a peak must reach. |
| Returns | |||
| — | ToroidalPhaseFitResult | - | The fitted mode number, intercept and residual for each mode line. |
Convention
The model carries a minus sign: the fitted phase decreases with increasing
toroidal angle for a positive mode number (fitted = intercept - n * toroidal_angle).
Under standard right-handed cylindrical coordinates (R, phi, Z), this
corresponds to a perturbation propagating in the positive phi (co-current)
direction, in agreement with toroidal_mode_analysis.
Phases are wrapped to a single turn and the intercept is a circular mean, so the fit is insensitive to where the branch cut falls, which a plain average would not be.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Take the window centred on the requested time.
- Choose the frequencies to fit, from the caller or from the strongest peaks.
- For each, measure the phase at every coil.
- Score each candidate mode number by its wrapped residual against the measured phases and keep the best.
Defaults
The window length and the candidate range are validated-workflow defaults from the legacy array analysis. The peak threshold is hard-coded with no recorded derivation.
Applicability
Machine-independent. The array’s angles are an argument.
Limitations
Fits at one time only, so a mode whose number changes through the shot needs repeated calls. Resolving a mode number needs enough coils spread over enough angle; a small or clustered array leaves candidates degenerate, and the fit returns the best-scoring one without reporting that.
Provenance
- The wrapped-phase array fit of the legacy VEST Mirnov analysis.
vest_b_field_pol_probe_legacy
VEST-specificConvention-sensitive
source
vest_b_field_pol_probe_legacy(time, raw, calibration, *, shot, config=None, allow_zero_fallback=None, channel=None)
Poloidal field at a VEST probe, from its raw record.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Time base. |
raw | array_like | V | Raw digitizer record. |
calibration | float | - | Calibration factor for the probe. |
shot | int | - | Shot number, which selects the baseline era. |
config | VestMagneticsProcessingConfig, optional | - | Processing settings. |
allow_zero_fallback | bool, optional | - | Whether to fall back to zero baseline with a warning when the baseline window is degenerate (fewer than 2 valid samples). Defaults to config.allow_zero_fallback. |
channel | str or int, optional | - | Channel identifier for diagnostic error reporting. |
| Returns | |||
| — | np.ndarray | T | Poloidal field at the probe. |
Convention
The low pass comes before the integration and is an anti-alias step: the record is conditioned on the fast acquisition grid below the output window’s Nyquist frequency, so resampling onto that window afterwards does not fold high-frequency content into the result.
The baseline is the era’s leading samples, a count rather than a physical window, so it means a different interval at a different rate.
The window and baseline indices are legacy acquisition-era policy, not a
signal-quality decision: which samples apply depends on the shot number,
and the eras are recorded in vest.yaml rather than inferred from the
data.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Low-pass the raw record on its native fast grid.
- Calibrate it.
- Integrate in time, carrying Faraday’s minus sign.
- Fit a linear baseline over the era’s leading samples and subtract it.
Defaults
The cut-off, the tap count and the baseline length are acquisition-era values tied to the VEST fast grid and its output window.
Applicability
VEST-specific. Written for the VEST poloidal probe chain, its digitizer rates and its shot eras.
Limitations
Assumes the leading samples precede the discharge. Raises DegenerateBaselineWindowError
if fewer than two valid baseline samples are available (issue #639), unless
allow_zero_fallback=True is opted into.
Provenance
- The legacy VEST magnetics workflow, whose stage order and baseline indices are preserved;
vest.yamlmagneticsfor the era table.
vest_equilibrium_magnetics_detailed
VEST-specificConvention-sensitive
source
vest_equilibrium_magnetics_detailed(shot, channels, loader, *, indices=None, config=None, allow_missing=False, allow_zero_fallback=None)
Process every magnetic channel of one VEST shot onto the output window.
| Name | Type | Unit | Description |
|---|---|---|---|
shot | int | - | Shot number, which selects the acquisition era. |
channels | sequence | - | The channels to process, each naming its kind and calibration. |
loader | callable | - | Returns the raw record and its time base for a channel. |
indices | sequence of int, optional | - | Which channels to process; all of them when omitted. |
config | VestMagneticsProcessingConfig, optional | - | Processing settings. |
allow_missing | bool, optional | - | Whether a channel the loader cannot supply is tolerated. |
allow_zero_fallback | bool, optional | - | Whether to fall back to zero baseline with a warning when a channel encounters a degenerate baseline window. Defaults to config.allow_zero_fallback. |
| Returns | |||
| — | VestEquilibriumMagneticsResult | - | The processed flux in weber per radian and field in tesla on the output window, the calibrated voltages at their native rate, and the window itself. |
Convention
Index alignment is an invariant. An unavailable channel contributes an empty array rather than being dropped, so channel positions never shift and a caller can index the result by the same number it indexed the input by. That is why a missing channel is not simply skipped.
Voltages are kept at the native acquisition rate while fluxes and fields are resampled, because the resampling is what the equilibrium chain needs and the voltage is what a diagnostic comparison needs.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Resolve the shot’s output window from its era.
- For each channel, load the raw record and dispatch on its kind, probe or flux loop, to the matching processing chain.
- Resample the result onto the output window.
- Keep the calibrated voltages at their native rate alongside.
Applicability
VEST-specific. Orchestrates the VEST legacy chain, its channel kinds, its calibrations and its acquisition eras.
Limitations
Inherits every limitation of the per-channel chains. Raises DegenerateBaselineWindowError
if any channel has a degenerate baseline window (issue #639), unless
allow_zero_fallback=True is opted into. With missing channels tolerated, an empty entry
is indistinguishable from a genuinely zero record without checking its length.
Provenance
- The legacy
vfit_equilibrium_magneticsworkflow this reproduces;vest.yamlmagneticsfor the era policy.
vest_equilibrium_magnetics_signals
VEST-specificConvention-sensitive
source
vest_equilibrium_magnetics_signals(shot, channels, loader, *, indices=None, config=None, allow_missing=False, allow_zero_fallback=None)
Show source vaft/process/magnetics.py, lines 1058–1122
def vest_equilibrium_magnetics_signals(
shot: int,
channels: Sequence[dict],
loader: Callable[[int, int], tuple[np.ndarray, np.ndarray] | None],
*,
indices: Sequence[int] | None = None,
config: VestMagneticsProcessingConfig | None = None,
allow_missing: bool = False,
allow_zero_fallback: bool | None = None,
) -> tuple[np.ndarray, list[np.ndarray], list[np.ndarray]]:
"""The processed magnetics of one VEST shot, as the three-array legacy view.
Parameters
----------
shot : int
Shot number [-].
channels : sequence
The channels to process [-].
loader : callable
Returns the raw record and its time base for a channel [-].
indices : sequence of int, optional
Which channels to process [-].
config : VestMagneticsProcessingConfig, optional
Processing settings [-].
allow_missing : bool, optional
Whether an unavailable channel is tolerated [-].
allow_zero_fallback : bool, optional
Whether to fall back to zero baseline with a warning when a channel encounters
a degenerate baseline window. Defaults to config.allow_zero_fallback [-].
Returns
-------
tuple of np.ndarray
The output window in seconds, the fluxes in weber per radian and the
fields in tesla [-].
Convention
----------
A backward-compatible view of :func:`vest_equilibrium_magnetics_detailed`,
returning the three arrays the older callers expect and discarding the native-
rate voltages. New code should call the detailed form, which keeps them.
Applicability
-------------
VEST-specific. The same chain and eras as the function it wraps.
Limitations
-----------
Inherits everything from that function, and additionally discards the
native-rate voltages, which cannot then be recovered.
Provenance
----------
.. [1] :func:`vest_equilibrium_magnetics_detailed`, which does the work.
"""
result = vest_equilibrium_magnetics_detailed(
shot,
channels,
loader,
indices=indices,
config=config,
allow_missing=allow_missing,
allow_zero_fallback=allow_zero_fallback,
)
return result.time, result.flux_loops, result.probesAlso exported as vest_md_signals.
The processed magnetics of one VEST shot, as the three-array legacy view.
| Name | Type | Unit | Description |
|---|---|---|---|
shot | int | - | Shot number. |
channels | sequence | - | The channels to process. |
loader | callable | - | Returns the raw record and its time base for a channel. |
indices | sequence of int, optional | - | Which channels to process. |
config | VestMagneticsProcessingConfig, optional | - | Processing settings. |
allow_missing | bool, optional | - | Whether an unavailable channel is tolerated. |
allow_zero_fallback | bool, optional | - | Whether to fall back to zero baseline with a warning when a channel encounters a degenerate baseline window. Defaults to config.allow_zero_fallback. |
| Returns | |||
| — | tuple of np.ndarray | - | The output window in seconds, the fluxes in weber per radian and the fields in tesla. |
Convention
A backward-compatible view of vest_equilibrium_magnetics_detailed,
returning the three arrays the older callers expect and discarding the native-
rate voltages. New code should call the detailed form, which keeps them.
Applicability · Limitations · Provenance
Applicability
VEST-specific. The same chain and eras as the function it wraps.
Limitations
Inherits everything from that function, and additionally discards the native-rate voltages, which cannot then be recovered.
Provenance
vest_equilibrium_magnetics_detailed, which does the work.
vest_flux_loop_flux_from_voltage
VEST-specificConvention-sensitive
source
vest_flux_loop_flux_from_voltage(time, voltage, *, flux_loop_number, config=None, allow_zero_fallback=None, shot=None, channel=None)
Poloidal flux through a VEST flux loop, from its calibrated voltage.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Time base of the voltage record. |
voltage | array_like | V | Calibrated terminal voltage. |
flux_loop_number | int | - | Which loop, since some take their own baseline window. |
config | VestMagneticsProcessingConfig, optional | - | Processing settings; the shipped defaults when omitted. |
allow_zero_fallback | bool, optional | - | Whether to fall back to zero baseline with a warning when the baseline window is degenerate (fewer than 2 valid samples). Defaults to config.allow_zero_fallback. |
shot | int, optional | - | Shot number for diagnostic error reporting. |
channel | str or int, optional | - | Channel identifier for diagnostic error reporting. |
| Returns | |||
| — | np.ndarray | Wb/rad | Flux through the loop, per radian. |
Convention
Per radian, which is what the ODS mapper expects and multiplies back by two pi. The minus sign is Faraday’s and is applied before the baseline, so the constant of integration is absorbed into the fitted line rather than chosen.
The window and baseline indices are legacy acquisition-era policy, not a
signal-quality decision: which samples apply depends on the shot number,
and the eras are recorded in vest.yaml rather than inferred from the
data.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Integrate the voltage in time, carrying Faraday’s minus sign.
- Divide by two pi to get flux per radian.
- Fit a linear baseline over the era’s indices and subtract it.
Defaults
The baseline indices are acquisition-era values in a four-way ladder: an explicit sample count for the native-DAQ era, then a physical time window, then a per-loop exception for three specific loops, then the two-segment default. The native-DAQ and later slow-DAQ windows are legacy compatibility values reproducing the donor’s own indices.
Applicability
VEST-specific. Carries VEST’s acquisition eras, its per-loop baseline exceptions, and its digitizer timebase.
Limitations
Raises DegenerateBaselineWindowError when fewer than two valid baseline samples
are available in the configured window (issue #639), unless allow_zero_fallback=True
is explicitly specified. The per-loop exception is by loop number, so a rewiring that
changes which loop is which invalidates it.
Provenance
VEST_MagneticSignalProcessing2.mfor the native-DAQ era, whose leading-sample baseline indices are reproduced; and the slow-DAQ era’s own window, expressed in physical seconds here so it stays correct at any sample rate.vest.yamlmagneticsfor the era table (issue #195).
vest_flux_loop_legacy
VEST-specificConvention-sensitive
source
vest_flux_loop_legacy(time, raw, calibration, *, flux_loop_number, config=None, allow_zero_fallback=None, shot=None, channel=None)
Show source vaft/process/magnetics.py, lines 798–876
def vest_flux_loop_legacy(
time: np.ndarray,
raw: np.ndarray,
calibration: float,
*,
flux_loop_number: int,
config: VestMagneticsProcessingConfig | None = None,
allow_zero_fallback: bool | None = None,
shot: int | None = None,
channel: str | int | None = None,
) -> np.ndarray:
"""Poloidal flux through a VEST flux loop, from its raw record.
Parameters
----------
time : array_like
Time base [s].
raw : array_like
Raw digitizer record [V].
calibration : float
Calibration factor for the loop [-].
flux_loop_number : int
Which loop [-].
config : VestMagneticsProcessingConfig, optional
Processing settings [-].
allow_zero_fallback : bool, optional
Whether to fall back to zero baseline with a warning when the baseline window
is degenerate (fewer than 2 valid samples). Defaults to config.allow_zero_fallback [-].
shot : int, optional
Shot number for diagnostic error reporting [-].
channel : str or int, optional
Channel identifier for diagnostic error reporting [-].
Returns
-------
np.ndarray
Flux through the loop, per radian [Wb/rad].
Processing steps
----------------
1. Calibrate the raw record into a terminal voltage.
2. Integrate, normalize per radian and subtract the era's baseline.
Convention
----------
The composition of :func:`vest_flux_loop_voltage` and
:func:`vest_flux_loop_flux_from_voltage`, kept as a single call because the
donor workflow had one. Same per-radian output and same era policy as those.
Applicability
-------------
VEST-specific. Inherits the calibration convention and the acquisition eras
of the two functions it composes.
Limitations
-----------
Inherits both. Raises `DegenerateBaselineWindowError` on degenerate baseline
windows (issue #639) unless `allow_zero_fallback=True`.
Provenance
----------
.. [1] The legacy VEST magnetics workflow; see the two functions this
composes for the donor indices.
"""
time = np.asarray(time, dtype=float)
raw = np.asarray(raw, dtype=float)
if time.size <= 1 or raw.size <= 1:
raise ValueError("VEST flux-loop processing requires at least two samples")
voltage = vest_flux_loop_voltage(raw, calibration, config=config)
return vest_flux_loop_flux_from_voltage(
time,
voltage,
flux_loop_number=flux_loop_number,
config=config,
allow_zero_fallback=allow_zero_fallback,
shot=shot,
channel=channel,
)Poloidal flux through a VEST flux loop, from its raw record.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Time base. |
raw | array_like | V | Raw digitizer record. |
calibration | float | - | Calibration factor for the loop. |
flux_loop_number | int | - | Which loop. |
config | VestMagneticsProcessingConfig, optional | - | Processing settings. |
allow_zero_fallback | bool, optional | - | Whether to fall back to zero baseline with a warning when the baseline window is degenerate (fewer than 2 valid samples). Defaults to config.allow_zero_fallback. |
shot | int, optional | - | Shot number for diagnostic error reporting. |
channel | str or int, optional | - | Channel identifier for diagnostic error reporting. |
| Returns | |||
| — | np.ndarray | Wb/rad | Flux through the loop, per radian. |
Convention
The composition of vest_flux_loop_voltage and
vest_flux_loop_flux_from_voltage, kept as a single call because the
donor workflow had one. Same per-radian output and same era policy as those.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Calibrate the raw record into a terminal voltage.
- Integrate, normalize per radian and subtract the era’s baseline.
Applicability
VEST-specific. Inherits the calibration convention and the acquisition eras of the two functions it composes.
Limitations
Inherits both. Raises DegenerateBaselineWindowError on degenerate baseline
windows (issue #639) unless allow_zero_fallback=True.
Provenance
- The legacy VEST magnetics workflow; see the two functions this composes for the donor indices.
vest_flux_loop_voltage
VEST-specificConvention-sensitive
source
vest_flux_loop_voltage(raw, calibration, *, config=None)
Show source vaft/process/magnetics.py, lines 616–663
def vest_flux_loop_voltage(
raw: np.ndarray,
calibration: float,
*,
config: VestMagneticsProcessingConfig | None = None,
) -> np.ndarray:
"""Calibrated flux-loop terminal voltage, before integration.
Parameters
----------
raw : array_like
Raw digitizer record [V].
calibration : float
Calibration factor for the loop [-].
config : VestMagneticsProcessingConfig, optional
Processing settings; the shipped defaults when omitted [-].
Returns
-------
np.ndarray
The calibrated terminal voltage [V].
Convention
----------
Calibration divides by default rather than multiplying, which is the donor's
convention and the opposite of what a gain usually means; the mode is
configurable and any other value is refused.
This is the single definition of a calibrated flux-loop voltage, shared by
:func:`vest_flux_loop_legacy` and the voltage the ODS mapper stores, so the
two cannot drift apart.
Applicability
-------------
VEST-specific. The calibration convention is that of the VEST flux-loop
digitizer chain.
Limitations
-----------
Voltage only. Nothing is integrated and no baseline is removed here.
Provenance
----------
.. [1] Issue #209, which established this as the single definition shared with
the ODS mapping.
"""
cfg = config or DEFAULT_VEST_MAGNETICS_PROCESSING
return _calibrated_signal(raw, float(calibration), cfg.calibration_mode)Calibrated flux-loop terminal voltage, before integration.
| Name | Type | Unit | Description |
|---|---|---|---|
raw | array_like | V | Raw digitizer record. |
calibration | float | - | Calibration factor for the loop. |
config | VestMagneticsProcessingConfig, optional | - | Processing settings; the shipped defaults when omitted. |
| Returns | |||
| — | np.ndarray | V | The calibrated terminal voltage. |
Convention
Calibration divides by default rather than multiplying, which is the donor’s convention and the opposite of what a gain usually means; the mode is configurable and any other value is refused.
This is the single definition of a calibrated flux-loop voltage, shared by
vest_flux_loop_legacy and the voltage the ODS mapper stores, so the
two cannot drift apart.
Applicability · Limitations · Provenance
Applicability
VEST-specific. The calibration convention is that of the VEST flux-loop digitizer chain.
Limitations
Voltage only. Nothing is integrated and no baseline is removed here.
Provenance
- Issue #209, which established this as the single definition shared with the ODS mapping.
vest_magnetics_time_window
VEST-specificConvention-sensitive
source
vest_magnetics_time_window(shot, config=None)
Show source vaft/process/magnetics.py, lines 456–505
def vest_magnetics_time_window(shot: int, config: VestMagneticsProcessingConfig | None = None) -> np.ndarray:
"""The output time window a VEST shot's magnetics are resampled onto.
Parameters
----------
shot : int
Shot number, which selects the acquisition era [-].
config : VestMagneticsProcessingConfig, optional
Processing settings; the shipped defaults when omitted [-].
Returns
-------
np.ndarray
The sample times of the output window [s].
Convention
----------
A slice of the shot's own timebase, chosen by era rather than by inspecting
the record. The window and baseline indices are legacy acquisition-era policy, not a
signal-quality decision: which samples apply depends on the shot number,
and the eras are recorded in ``vest.yaml`` rather than inferred from the
data.
Defaults
--------
Every index is an acquisition-era value. Two eras exist: a transient block of
six shots and everything from a later shot onward share one window, and
earlier shots take another. A configured override from ``vest.yaml``
supersedes both; a directly constructed record keeps the historical thresholds
so old behaviour is reproducible.
Applicability
-------------
VEST-specific. The windows are VEST acquisition policy, tied to that
machine's digitizer timebase and its shot-numbering eras.
Limitations
-----------
Selects by shot number alone. A shot whose acquisition differed from its era's
policy gets that era's window regardless.
Provenance
----------
.. [1] ``vest.yaml`` ``magnetics.equilibrium_magnetics.processing.window``
(issue #195), which carries the era table and supersedes the hard-coded
thresholds.
"""
cfg = config or DEFAULT_VEST_MAGNETICS_PROCESSING
index_start, index_end, _ = cfg.window_for_shot(int(shot))
return cfg.timebase()[index_start : index_end + 1]The output time window a VEST shot’s magnetics are resampled onto.
| Name | Type | Unit | Description |
|---|---|---|---|
shot | int | - | Shot number, which selects the acquisition era. |
config | VestMagneticsProcessingConfig, optional | - | Processing settings; the shipped defaults when omitted. |
| Returns | |||
| — | np.ndarray | s | The sample times of the output window. |
Convention
A slice of the shot’s own timebase, chosen by era rather than by inspecting
the record. The window and baseline indices are legacy acquisition-era policy, not a
signal-quality decision: which samples apply depends on the shot number,
and the eras are recorded in vest.yaml rather than inferred from the
data.
Defaults · Applicability · Limitations · Provenance
Defaults
Every index is an acquisition-era value. Two eras exist: a transient block of
six shots and everything from a later shot onward share one window, and
earlier shots take another. A configured override from vest.yaml
supersedes both; a directly constructed record keeps the historical thresholds
so old behaviour is reproducible.
Applicability
VEST-specific. The windows are VEST acquisition policy, tied to that machine’s digitizer timebase and its shot-numbering eras.
Limitations
Selects by shot number alone. A shot whose acquisition differed from its era’s policy gets that era’s window regardless.
Provenance
vest.yamlmagnetics.equilibrium_magnetics.processing.window(issue #195), which carries the era table and supersedes the hard-coded thresholds.