Process reference: fluctuation
Generated from the docstrings of vaft.process.fluctuation:
11 public functions. Each entry is what
vaft.process.describe("fluctuation.<name>") prints.
All process categories
Overview
Every routine here takes a plain time-and-data pair and knows nothing about the diagnostic that produced it. The same functions serve magnetic pickup coils, interferometry, soft X-ray channels, Langmuir probes and optical intensity, so mapping modules must not grow their own spectral implementations.
| Symbol | Meaning | Unit |
|---|---|---|
| t | time | s |
| f | frequency | Hz |
| S(f) | one-sided power spectral density | signal^2/Hz |
| alpha | power-law spectral index, S ~ f^alpha | - |
| f_break | frequency separating two power-law regimes | Hz |
| S_xy(f) | one-sided cross-spectral density of x and y | x*y/Hz |
| gamma^2 | magnitude-squared coherence |S_xy|^2/(S_xx S_yy) | - |
Transfer functions stay outside this module. These routines analyse whatever quantity they are handed and never correct for a diagnostic’s transfer function. That matters most for a magnetic pickup coil, which measures a time derivative::
V(t) proportional to dB/dt => S_dBdt(f) = (2 pi f)**2 * S_B(f)
so a field spectrum going as f**alpha gives a derivative-signal spectrum
going as f**(alpha + 2). A spectral index fitted to raw pickup voltage
is not the magnetic-field spectral index. Integrate and calibrate first –
vaft.process.magnetics.b_field_pol_probe_field is the canonical VEST
path – and pass the resulting field in. Nothing here will do it for you, by
design.
No physical interpretation. Nothing classifies a fitted slope, names a spectral regime, or attaches meaning to a break frequency. Reference slopes and characteristic frequencies are the caller’s, supplied at the plotting layer; this module ships no slope constants of its own.
Nothing is inferred that the caller could state. A fit range is always explicit, so a reported index always belongs to a band someone chose; and the two-regime mode is selected by which argument is supplied, never guessed.
Functions
analyze_fluctuation_spectrum | Run the spectral chain on one signal: density, then whatever else was asked for. Convention |
coherent_components | Decompose PSD-normalized matrices into coherent spectral components. Convention |
compute_band_power | Integrate spectral power over named frequency bands, and optionally their ratios. Convention |
compute_psd | One-sided power spectral density by Welch’s method. Convention |
compute_spectrogram | Short-time Fourier magnitude map of a fluctuation signal. Convention |
cross_spectral_matrix | Estimate an arbitrary-N time-resolved cross-spectral matrix. Convention |
cross_spectrogram | Time-resolved cross-spectrum, coherence and y-relative-to-x phase. Convention |
cross_spectrum | Cross-spectral density, coherence and relative phase of two fluctuation records. Convention |
find_spectral_break | Fit a two-regime power law, below and above a break frequency. Convention |
fit_power_law_spectrum | Fit a power law to a spectrum over an explicitly chosen band. Convention |
track_dominant_frequency | Follow the dominant spectral ridge of a time-frequency map, window by window. Convention |
No function matches.
analyze_fluctuation_spectrum
Machine-independentConvention-sensitive
source
analyze_fluctuation_spectrum(time, data, *, fit_ranges=(), bands=None, ratios=None, break_frequency=None, search_range=None, break_fit_range=None, **psd_options)
Run the spectral chain on one signal: density, then whatever else was asked for.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Uniformly sampled time axis. |
data | array_like | any | Signal samples. |
fit_ranges | sequence, optional | Hz | Bands to fit a power law over, each |
bands | mapping, optional | Hz | Named bands whose power to integrate. |
ratios | mapping, optional | - | Named band-power ratios to report. |
break_frequency | float, optional | Hz | An imposed two-regime boundary. |
search_range | sequence of float, optional | Hz | Interval to scan for a break instead. |
break_fit_range | sequence of float, optional | Hz | Outer band for the two-regime fit. Further keyword arguments are passed through to the density estimate. |
| Returns | |||
| — | dict | - | The spectrum, and an entry for each optional analysis that was requested |
Convention
Everything past the density is opt-in. Nothing is computed because it might be interesting, so the returned mapping holds exactly what was asked for. The same rules apply as to the functions this calls: fit ranges are explicit, the break mode is never inferred, and no result is given a physical name.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Estimate the power spectral density.
- Fit a power law over each requested band.
- Fit a two-regime break, if either mode argument was given.
- Integrate the requested band powers and ratios.
Applicability
Machine-independent.
Limitations
A convenience wrapper only. It adds no analysis of its own and inherits every limitation of the steps it runs.
Provenance
- The functions it orchestrates, each documented on its own.
coherent_components
Machine-independentConvention-sensitive
source
coherent_components(result, *, reference, degeneracy_tolerance=1e-06)
Decompose PSD-normalized matrices into coherent spectral components.
| Name | Type | Unit | Description |
|---|---|---|---|
result | CrossSpectralMatrix | - | Time-resolved matrix from |
reference | str | - | Diagnostic whose phase is zero where its dominant loading is defined. |
degeneracy_tolerance | float, optional | - | Relative leading-eigenvalue gap below which the dominant direction is ambiguous. |
| Returns | |||
| — | CoherentComponents | - | Descending eigensystem, leading spectral power and fraction, diagnostic participation and reference-relative phase; invalid entries are NaN. |
Convention
The spectral matrix has S[i,j] = <X_i conj(X_j)>. The leading
eigenvector’s phase at i relative to the reference is
angle(u_i conj(u_ref)). Its squared magnitudes sum to one; they are
dimensionless loadings, not physical signal amplitudes. The fraction is
the leading eigenvalue divided by the trace. Finite-sample eigenvalue
spread raises this fraction above 1/N even for independent signals;
it needs an appropriate null model before physical interpretation.
Raises
ValueErrorNon-PSD normalization, unknown reference or invalid tolerance.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Extract each jointly valid normalized submatrix without replacing missing diagnostic entries by zero.
- Hermitian-diagonalize it and sort the eigenpairs by descending power.
- Calculate leading power fraction and, only for a distinct leading direction, normalized participation and reference-relative phase.
Defaults
The numerical convenience tolerance of 1e-6 only guards an ambiguous
eigenvector when the leading eigenvalues are effectively tied.
Applicability
Machine-independent. Inputs must already be selected scalar diagnostics; one diagnostic supplies no cross-diagnostic coherence claim. At least N+1 independent averaged segments are required for N valid diagnostics before leading-component metrics are reported.
Limitations
A large leading component alone does not identify a physical MHD mode. Relative phase is undefined when the reference is missing or its loading is numerically zero, or when an individual diagnostic’s loading vanishes. Distinct spectral components may exchange rank over time or frequency; no component tracking is inferred.
Provenance
- Hermitian eigendecomposition of the PSD-normalized cross-spectral matrix defined by
cross_spectral_matrix.
compute_band_power
Machine-independentConvention-sensitive
source
compute_band_power(frequency, psd, bands, *, ratios=None)
Show source vaft/process/fluctuation.py, lines 556–633
def compute_band_power(
frequency,
psd,
bands: Mapping[str, Sequence[float]],
*,
ratios: Mapping[str, Sequence[str]] | None = None,
) -> dict[str, float]:
"""Integrate spectral power over named frequency bands, and optionally their ratios.
Parameters
----------
frequency : array_like
Frequency axis [Hz].
psd : array_like
Power spectral density [any].
bands : mapping of str to sequence of float
Named ``(f_low, f_high)`` pairs; the names are the caller's [Hz].
ratios : mapping, optional
Named pairs of band names whose power ratio to report [-].
Returns
-------
dict
Power per named band, in the signal's own squared unit, and any requested
ratios, dimensionless [-].
Convention
----------
**Band edges are closed**, so two adjacent bands sharing an edge both include
the sample sitting on it. A band containing fewer than two samples integrates
to zero rather than raising, and a ratio with a zero denominator is NaN rather
than infinite, so a caller sweeping many channels gets a comparable result
from every one.
Applicability
-------------
Machine-independent.
Limitations
-----------
Integration is over the samples present, so a band narrower than the frequency
resolution reports zero rather than an error. Nothing normalizes by bandwidth;
these are powers, not densities.
Provenance
----------
.. [1] Numerical integration of the density returned by :func:`compute_psd`.
"""
frequency = np.asarray(frequency, dtype=float)
psd = np.asarray(psd, dtype=float)
if frequency.shape != psd.shape:
raise ValueError(
f"frequency and psd must have the same shape; got {frequency.shape} and {psd.shape}"
)
powers: dict[str, float] = {}
for name, edges in bands.items():
low, high = (float(edges[0]), float(edges[1]))
if low >= high:
raise ValueError(f"band {name!r} must be increasing; got ({low}, {high})")
mask = (frequency >= low) & (frequency <= high)
if np.count_nonzero(mask) < 2:
powers[str(name)] = 0.0
continue
powers[str(name)] = float(np.trapezoid(psd[mask], frequency[mask]))
for name, pair in (ratios or {}).items():
numerator, denominator = (str(pair[0]), str(pair[1]))
for key in (numerator, denominator):
if key not in powers:
raise KeyError(
f"ratio {name!r} refers to unknown band {key!r}; "
f"defined bands are {sorted(powers)}"
)
below = powers[denominator]
powers[str(name)] = powers[numerator] / below if below else float("nan")
return powersIntegrate spectral power over named frequency bands, and optionally their ratios.
| Name | Type | Unit | Description |
|---|---|---|---|
frequency | array_like | Hz | Frequency axis. |
psd | array_like | any | Power spectral density. |
bands | mapping of str to sequence of float | Hz | Named |
ratios | mapping, optional | - | Named pairs of band names whose power ratio to report. |
| Returns | |||
| — | dict | - | Power per named band, in the signal’s own squared unit, and any requested ratios, dimensionless. |
Convention
Band edges are closed, so two adjacent bands sharing an edge both include the sample sitting on it. A band containing fewer than two samples integrates to zero rather than raising, and a ratio with a zero denominator is NaN rather than infinite, so a caller sweeping many channels gets a comparable result from every one.
Applicability · Limitations · Provenance
Applicability
Machine-independent.
Limitations
Integration is over the samples present, so a band narrower than the frequency resolution reports zero rather than an error. Nothing normalizes by bandwidth; these are powers, not densities.
Provenance
- Numerical integration of the density returned by
compute_psd.
compute_psd
Machine-independentConvention-sensitive
source
compute_psd(time, data, *, sample_rate=None, window='hann', nperseg=None, noverlap=None, detrend='constant', units='signal**2/Hz')
One-sided power spectral density by Welch’s method.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Strictly increasing, uniformly sampled time axis. |
data | array_like | any | Signal samples, same length. |
sample_rate | float, optional | Hz | Overrides the rate derived from the time axis. |
window | str, optional | - | Any window name SciPy accepts. |
nperseg | int, optional | - | Segment length in samples. |
noverlap | int, optional | - | Overlap in samples. |
detrend | str or bool, optional | - | Passed through to the underlying estimator. |
units | str, optional | - | Free-text unit label recorded on the result. |
| Returns | |||
| — | FluctuationSpectrum | - | The frequency axis in hertz, the density in the signal’s own squared unit per hertz, and the parameters needed to reproduce them. |
Convention
One-sided, so the power at each frequency already accounts for its negative counterpart. The input is whatever quantity the caller wants a spectrum of and no transfer-function correction is applied; see the module’s conventions for what that means for a pickup coil.
Raises
ValueErrorThe time axis is not uniform within the module’s tolerance.
Defaults · Applicability · Limitations · Provenance
Defaults
The segment length and overlap are numerical conveniences, deferred to SciPy’s own choices rather than fixed here, so a caller who has not thought about resolution gets that library’s behaviour rather than one invented for VAFT.
Applicability
Machine-independent.
Limitations
Welch’s method assumes a uniformly sampled, stationary signal. A materially nonuniform time axis is rejected rather than interpolated, because interpolating one silently changes the spectrum it is being asked about.
Provenance
- Welch’s method as implemented by
scipy.signal.welch.
compute_spectrogram
Machine-independentConvention-sensitive
source
compute_spectrogram(time, data, *, sample_rate=None, nperseg=None, window_duration=None, overlap=0.5, window='hann', detrend='constant')
Short-time Fourier magnitude map of a fluctuation signal.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array_like | s | Uniformly sampled time axis. |
data | array_like | any | Signal samples. |
sample_rate | float, optional | Hz | Overrides the rate derived from the time axis. |
nperseg | int, optional | - | Window length in samples. |
window_duration | float, optional | s | Window length as a duration, converted to samples. |
overlap | float, optional | - | Fractional overlap between windows. |
window | str, optional | - | Window name. |
detrend | str or bool, optional | - | Passed through to the underlying transform. |
| Returns | |||
| — | FluctuationSpectrogram | - | The time and frequency axes and the magnitude map. |
Convention
The time axis is returned in the caller’s own absolute base, offset back from the transform’s window-relative one, so a feature can be read against the shot clock without correction.
The field names match the magnetics module’s own spectrogram result, so the plotting layer accepts either without knowing which produced it.
Defaults · Applicability · Limitations · Provenance
Defaults
The overlap is a numerical convenience. The window may be given in samples or as a duration; the duration form is the portable one, since it means the same thing at a different sample rate.
Applicability
Machine-independent.
Limitations
The window sets the trade-off between time and frequency resolution and nothing here chooses it for the caller. A window longer than the record returns an empty result rather than raising, so callers sweeping many channels get deterministic behaviour at the edges.
Provenance
- The short-time Fourier transform as implemented by
scipy.signal.spectrogram.
cross_spectral_matrix
Machine-independentConvention-sensitive
source
cross_spectral_matrix(records, *, sample_rate=None, frequency_range=None, nperseg=256, segments_per_window=None, window_step_samples=None, normalization='psd', user_scales=None, window='hann', detrend='constant')
Estimate an arbitrary-N time-resolved cross-spectral matrix.
| Name | Type | Unit | Description |
|---|---|---|---|
records | sequence of FluctuationRecord | - | Named scalar records, each with its own time, units and usable band. |
sample_rate | float, optional | Hz | Common-grid rate; defaults to the slowest native rate, as |
frequency_range | tuple of float, optional | Hz | Inclusive output band; defaults to all usable bins. |
nperseg | int, optional | - | Samples in each inner Welch segment. |
segments_per_window | int, optional | - | Non-overlapping inner segments per output time; defaults to the larger of four and one more than the selected diagnostic count. |
window_step_samples | int, optional | - | Output-window advance, defaulting to half an outer window. |
normalization | {"none", "variance", "psd", "user"}, optional | - | Explicit scaling policy; |
user_scales | mapping, optional | record units | Positive per-record amplitude scales, required for |
window | str, optional | - | SciPy window name. |
detrend | str or bool, optional | - |
|
| Returns | |||
| — | CrossSpectralMatrix | - | Raw and normalized matrices, validity masks, coordinates, units, averaging and resampling provenance. |
Convention
S[i,j] = mean(X_i * conj(X_j)) is Hermitian positive semidefinite.
Thus angle(S[i,reference]) matches cross_spectrum’s phase of
i relative to the reference. A record above its declared usable bandwidth,
or above native Nyquist when no physical band was declared, is unavailable
rather than zero. A single available record remains a 1x1 spectrum but
supplies no evidence of cross-diagnostic coherence.
Raises
ValueErrorInvalid records, bands, normalization or grid, or too few common samples.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Align every record on the overlapping interval, with anti-aliasing for rate reductions and mask propagation for missing/short filtered spans.
- Compute identically windowed one-sided FFTs in non-overlapping segments.
- At each frequency and output time, select the largest set of records sharing at least two finite segments and average only over that set’s jointly finite segments.
- Keep raw densities and apply the requested explicit normalization.
Defaults
The numerical convenience of at least four non-overlapping 256-sample
segments matches cross_spectrogram; for N diagnostics the default
uses at least N+1 segments so the sample matrix is not rank deficient by
construction. The default "psd" normalization
divides each entry by the geometric mean of its auto PSDs, giving a
dimensionless correlation matrix with unit diagonal where power is nonzero.
The raw physical-unit matrix is always retained separately.
Applicability
Machine-independent. Diagnostic selection and transfer functions belong upstream; no input gets extra weight merely for having more channels.
Limitations
Upsampling cannot recover frequencies above a record’s native bandwidth,
and a record linearly interpolated onto a faster requested grid carries
the interpolant’s sinc²(f/f_native) roll-off inside its own band: its
raw_csd auto-density is low by sinc⁴ (0.67 at a quarter of its native
rate) and its cross terms by sinc², while the "psd" matrix, in which
the factor cancels, is unaffected. That is why the default grid is the
slowest native rate; a faster sample_rate is the caller’s choice to
keep the fast records’ band at that price. A missing physical bandwidth
is reported as "nyquist_only" in the provenance. If the available records lack two jointly finite segments at
a bin, that bin is unavailable; it is not filled with zeros.
Provenance
- Welch’s one-sided density scaling as in
scipy.signal.csd. vaft.process.signal_processing.resample_to_timeprovides anti-aliased rate reduction and filter-coverage masks.
cross_spectrogram
Machine-independentConvention-sensitive
source
cross_spectrogram(time_x, x, time_y, y, *, sample_rate=None, common_time=None, bandwidth_x_hz=None, bandwidth_y_hz=None, frequency_range=None, nperseg=256, segments_per_window=4, window_step_samples=None, window='hann', detrend='constant', units_x='signal_x', units_y='signal_y')
Time-resolved cross-spectrum, coherence and y-relative-to-x phase.
| Name | Type | Unit | Description |
|---|---|---|---|
time_x | array_like | s | Uniform time axis of the phase-reference record. |
x | array_like | units_x | First scalar signal. |
time_y | array_like | s | Uniform time axis of the second record. |
y | array_like | units_y | Second scalar signal. |
sample_rate | float, optional | Hz | Rate of a common grid over the overlapping interval. |
common_time | array_like, optional | s | Explicit uniform common grid, overriding |
bandwidth_x_hz | float, optional | Hz | Physically usable upper bandwidth of x; defaults to its Nyquist. |
bandwidth_y_hz | float, optional | Hz | Physically usable upper bandwidth of y; defaults to its Nyquist. |
frequency_range | tuple of float, optional | Hz | Inclusive output band, defaulting to the full common usable band. |
nperseg | int, optional | - | Samples in one Welch segment. |
segments_per_window | int, optional | - | Non-overlapping Welch segments averaged in each output window. |
window_step_samples | int, optional | - | Output-window advance, defaulting to half an outer window. |
window | str, optional | - | SciPy spectral window name. |
detrend | str or bool, optional | - | Detrending passed to SciPy Welch and CSD. |
units_x | str, optional | - | Caller-supplied physical unit label for x. |
units_y | str, optional | - | Caller-supplied physical unit label for y. |
| Returns | |||
| — | CrossSpectrogram | - | One-sided auto and cross spectral densities, magnitude-squared coherence, relative phase and alignment/bandwidth provenance. |
Convention
The CSD uses conj(X) * Y as cross_spectrum does, so a delayed y
has negative phase. Coherence and phase are NaN at zero auto power. The
output time is the centre of each complete window in the input timebase.
An omitted bandwidth means only a Nyquist ceiling is known; the result
records "nyquist_only" and makes no diagnostic response claim.
Raises
ValueErrorInvalid axes, bandwidth or averaging parameters; non-overlapping or too-short records; or incomplete anti-alias filtering.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Validate both records and align their overlapping time interval.
- Filter before rate reduction, refusing incomplete filter coverage.
- For each complete output window, average non-overlapping Welch segments before deriving coherence and phase from the averaged densities.
- Restrict output to the common declared or sampling-limited bandwidth.
Defaults
A numerical convenience: four non-overlapping 256-sample inner segments provide a genuine average; outer windows advance by half their length. One STFT outer product alone would give coherence one even for unrelated noise. After rate reduction, the reported ceiling is conservatively 0.7 of target Nyquist, below the resampler’s FIR cutoff at 0.8 of target Nyquist.
Applicability
Machine-independent. Transfer functions and diagnostic selection remain the caller’s responsibility.
Limitations
Window duration trades time resolution for frequency resolution. Nyquist does not establish the sensor’s physical bandwidth; supply it when known. Adjacent output windows share data, so their estimates are correlated.
Provenance
scipy.signal.welchandscipy.signal.csdprovide the one-sided Welch density scaling for every output window.vaft.process.signal_processing.resample_to_timeprovides anti-aliased rate reduction and its filter-coverage mask.
cross_spectrum
Machine-independentConvention-sensitive
source
cross_spectrum(time_x, x, time_y, y, *, sample_rate=None, nperseg=None, noverlap=None, window='hann', detrend='constant', common_time=None)
Cross-spectral density, coherence and relative phase of two fluctuation records.
| Name | Type | Unit | Description |
|---|---|---|---|
time_x | array_like | s | Uniformly sampled time axis of |
x | array_like | any | First record, the phase reference. |
time_y | array_like | s | Uniformly sampled time axis of |
y | array_like | any | Second record. |
sample_rate | float, optional | Hz | Rate of a uniform common grid laid over the overlap; both records are resampled onto it. |
nperseg | int, optional | - | Welch segment length on the common grid. |
noverlap | int, optional | - | Segment overlap on the common grid. |
window | str, optional | - | Any window name SciPy accepts. |
detrend | str or bool, optional | - | Passed through to the underlying estimator. |
common_time | array_like, optional | s | An explicit uniform grid to compare on, overriding |
| Returns | |||
| — | CrossSpectrum | - | Frequency axis in hertz, the complex cross-spectral density in the product of the two signals’ units per hertz, the dimensionless coherence and its 95 % significance level, the phase in radians, and the grid used. |
Convention
The phase is that of y relative to x: phase = arg(S_xy) with
S_xy = conj(X) Y, SciPy’s convention, so y lagging x by dt
reads -2 pi f dt at frequency f. Swapping the arguments flips the
sign. The phase is wrapped to (-pi, pi].
Coherence is the magnitude-squared coherence |S_xy|^2 / (S_xx S_yy).
Its 95 % level for n averaged segments is 1 - 0.05**(1/(n-1)), the
level two independent Gaussian records exceed with probability 0.05 at any
one frequency.
Different timebases are never compared silently. The comparison is restricted to the overlap of the two records, and the grid, its rate, the overlap and which record was resampled are all returned with the result. Whenever the slower record keeps its own samples, only the faster one is changed, and it is anti-aliased before it is decimated.
Raises
ValueErrorEither axis is not uniform, or the two records do not overlap in time.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Validate both time axes as uniform and increasing.
- Choose the common grid: the shared axis when the two are identical;
otherwise
common_time, else a uniform grid atsample_rateover the overlap, else the slower record’s own samples inside the overlap. - Put each record that is not already on that grid onto it with
vaft.process.signal_processing.resample_to_time, which low-passes first when that is a rate reduction. - Estimate the two auto-spectra and the cross-spectrum by Welch’s method with one set of segments, and form coherence and phase from them.
- Count the segments and set the 95 % significance level of the coherence.
Defaults
A numerical convenience, SciPy’s own: without nperseg the segment is 256
samples, or the whole record when that is shorter, and the overlap half a
segment, stated here so the segment count can be reproduced.
Applicability
Machine-independent.
Limitations
The significance formula assumes independent segments; with the default half
overlap of a Hann window neighbouring segments are correlated, so the true
95 % level is somewhat higher than the one reported. A single segment has no
significance level and reports NaN. Coherence between two diagnostics with
different transfer functions is unaffected by either transfer function, but
the phase is not: a pickup coil’s derivative adds +pi/2 to its phase.
Provenance
- Welch’s method for auto- and cross-spectra as implemented by
scipy.signal.welchandscipy.signal.csd. - J. S. Bendat and A. G. Piersol, Random Data: Analysis and Measurement Procedures, 4th ed. (Wiley, 2010), section 9.2.3: the coherence significance level for averaged segments.
find_spectral_break
Machine-independentConvention-sensitive
source
find_spectral_break(frequency, psd, *, fit_range, break_frequency=None, search_range=None, n_candidates=64)
Fit a two-regime power law, below and above a break frequency.
| Name | Type | Unit | Description |
|---|---|---|---|
frequency | array_like | Hz | Frequency axis. |
psd | array_like | any | Power spectral density. |
fit_range | sequence of float | Hz | Outer band spanning both regimes. |
break_frequency | float, optional | Hz | An imposed boundary, for the physics-informed mode. |
search_range | sequence of float, optional | Hz | Interval to scan, for the data-driven mode. |
n_candidates | int, optional | - | Log-spaced candidates scanned in search mode. |
| Returns | |||
| — | SpectralBreak | - | The break, the two fits either side, the mode used, and the score. |
Convention
The mode is chosen by which argument is supplied, never inferred. Passing a break frequency imposes it and the caller owns the boundary; passing a search range scans for one. Supplying neither, or both, is an error rather than a default, because a break that looks physics-informed and was in fact fitted is the failure this refuses to permit.
Candidates are scored by total squared residual in log space, not by a point-weighted goodness of fit. The latter biases the score toward splits that hand most points to whichever segment fits best, and in practice pins the answer to the edge of the search range.
A break found this way is a numerical feature of the spectrum. It is not identified with any plasma scale here.
Raises
ValueErrorNeither or both of the two mode arguments were supplied, or the band holds too few points.
Defaults · Applicability · Limitations · Provenance
Defaults
The candidate count is a numerical convenience, dense enough that the scan’s resolution is not the limiting error.
Applicability
Machine-independent.
Limitations
Two straight lines are fitted to something that may not have two regimes; a best break is always returned in search mode, whether or not one exists. Inherits the log-space caveats of the single-regime fit.
Provenance
fit_power_law_spectrum, applied either side of the break.
fit_power_law_spectrum
Machine-independentConvention-sensitive
source
fit_power_law_spectrum(frequency, psd, *, f_range)
Fit a power law to a spectrum over an explicitly chosen band.
| Name | Type | Unit | Description |
|---|---|---|---|
frequency | array_like | Hz | Frequency axis. |
psd | array_like | any | Power spectral density on that axis. |
f_range | sequence of float | Hz | The band to fit over, as |
| Returns | |||
| — | SpectralFit | - | The index, the amplitude, the goodness of fit and the band used. |
Convention
Ordinary least squares in log-log space, so the fit is on the exponent directly. There is no default range and no automatic range selection: a reported index therefore always belongs to a band the caller chose deliberately, rather than to whatever the algorithm happened to like.
Nothing here names the regime that index belongs to.
Raises
ValueErrorFewer than the minimum number of usable points fall inside the band.
Defaults · Applicability · Limitations · Provenance
Defaults
The minimum point count is a numerical convenience: two points define a line, and the third is what makes the goodness of fit and the residuals mean anything.
Applicability
Machine-independent.
Limitations
Samples with a non-positive density are excluded, since their logarithm does not exist. A log-log fit weights decades equally, so a band spanning many decades is dominated by the sparse high-frequency end.
Provenance
- Ordinary least squares in log-log space; the module’s conventions on why the band is never chosen for the caller.
track_dominant_frequency
Machine-independentConvention-sensitive
source
track_dominant_frequency(spectrogram, *, search_range, max_jump=None, floor_ratio=0.05)
Follow the dominant spectral ridge of a time-frequency map, window by window.
| Name | Type | Unit | Description |
|---|---|---|---|
spectrogram | Any | - | An object with |
search_range | sequence of float | Hz | Lowest and highest frequency the ridge may be found at. |
max_jump | float, optional | Hz | Largest frequency change allowed between neighbouring windows; |
floor_ratio | float, optional | - | Fraction of the map’s in-range peak a window’s ridge must exceed. |
| Returns | |||
| — | FrequencyTrack | - |
|
Convention
A silent window is NaN, never its loudest noise bin. The floor is relative to the map, not absolute, so it means the same thing for a voltage, a brightness or a camera intensity. A gap breaks continuity: the run after it is found afresh rather than held to where the last run ended.
The continuity path maximises summed magnitude over the whole run rather than starting from the loudest pixel, so a brief loud burst far from the ridge cannot capture it.
Raises
ValueErrorThe magnitude does not match its axes,search_rangeis not increasing, or an argument is negative.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Keep the frequency bins inside
search_range. - Set the floor at
floor_ratiotimes the largest in-range magnitude of the whole map; a window whose in-range maximum does not exceed it has no ridge. - Split the remaining windows into runs of consecutive windows.
- Within each run, choose one bin per window: the window’s own maximum when
max_jumpisNone, otherwise the path of largest summed magnitude whose step between neighbouring windows never exceedsmax_jump. - Report NaN for a window whose chosen bin does not exceed the floor.
Defaults
floor_ratio = 0.05 is a numerical convenience: well above the tail of a
Hann window’s sidelobes relative to a clear mode, well below any mode worth
tracking. Set it to zero to report every window that has any content at all.
Applicability
Machine-independent.
Limitations
The ridge is resolved to one frequency bin; nothing interpolates between bins.
One ridge only: two comparable modes are not separated, and with no
max_jump the track may alternate between them. The floor is relative, so a
map that is noise throughout still reports its noise as a ridge.
Provenance
- Ridge extraction as a maximum-energy continuous path through the time-frequency plane, R. Carmona, W. L. Hwang and B. Torresani, “Characterization of signals by the ridges of their wavelet transforms”, IEEE Trans. Signal Process. 45 (1997) 2586, solved here by dynamic programming over discrete bins.
- The single-argmax reference-frequency tracker of the legacy FAST-camera analysis, which
vaft.process.camera_fluctuation.track_reference_frequencynow calls withfloor_ratio=0.