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.

SymbolMeaningUnit
ttimes
ffrequencyHz
S(f)one-sided power spectral densitysignal^2/Hz
alphapower-law spectral index, S ~ f^alpha-
f_breakfrequency separating two power-law regimesHz
S_xy(f)one-sided cross-spectral density of x and yx*y/Hz
gamma^2magnitude-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_spectrumRun the spectral chain on one signal: density, then whatever else was asked for. Convention
coherent_componentsDecompose PSD-normalized matrices into coherent spectral components. Convention
compute_band_powerIntegrate spectral power over named frequency bands, and optionally their ratios. Convention
compute_psdOne-sided power spectral density by Welch’s method. Convention
compute_spectrogramShort-time Fourier magnitude map of a fluctuation signal. Convention
cross_spectral_matrixEstimate an arbitrary-N time-resolved cross-spectral matrix. Convention
cross_spectrogramTime-resolved cross-spectrum, coherence and y-relative-to-x phase. Convention
cross_spectrumCross-spectral density, coherence and relative phase of two fluctuation records. Convention
find_spectral_breakFit a two-regime power law, below and above a break frequency. Convention
fit_power_law_spectrumFit a power law to a spectrum over an explicitly chosen band. Convention
track_dominant_frequencyFollow the dominant spectral ridge of a time-frequency map, window by window. Convention

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.

NameTypeUnitDescription
timearray_likes

Uniformly sampled time axis.

dataarray_likeany

Signal samples.

fit_rangessequence, optionalHz

Bands to fit a power law over, each (f_low, f_high).

bandsmapping, optionalHz

Named bands whose power to integrate.

ratiosmapping, optional-

Named band-power ratios to report.

break_frequencyfloat, optionalHz

An imposed two-regime boundary.

search_rangesequence of float, optionalHz

Interval to scan for a break instead.

break_fit_rangesequence of float, optionalHz

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

  1. Estimate the power spectral density.
  2. Fit a power law over each requested band.
  3. Fit a two-regime break, if either mode argument was given.
  4. 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

  1. 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.

NameTypeUnitDescription
resultCrossSpectralMatrix-

Time-resolved matrix from cross_spectral_matrix.

referencestr-

Diagnostic whose phase is zero where its dominant loading is defined.

degeneracy_tolerancefloat, 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

  • ValueError Non-PSD normalization, unknown reference or invalid tolerance.
Processing steps · Defaults · Applicability · Limitations · Provenance

Processing steps

  1. Extract each jointly valid normalized submatrix without replacing missing diagnostic entries by zero.
  2. Hermitian-diagonalize it and sort the eigenpairs by descending power.
  3. 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

  1. 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 powers

Integrate spectral power over named frequency bands, and optionally their ratios.

NameTypeUnitDescription
frequencyarray_likeHz

Frequency axis.

psdarray_likeany

Power spectral density.

bandsmapping of str to sequence of floatHz

Named (f_low, f_high) pairs; the names are the caller’s.

ratiosmapping, 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

  1. 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.

NameTypeUnitDescription
timearray_likes

Strictly increasing, uniformly sampled time axis.

dataarray_likeany

Signal samples, same length.

sample_ratefloat, optionalHz

Overrides the rate derived from the time axis.

windowstr, optional-

Any window name SciPy accepts.

npersegint, optional-

Segment length in samples.

noverlapint, optional-

Overlap in samples.

detrendstr or bool, optional-

Passed through to the underlying estimator.

unitsstr, 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

  • ValueError The 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

  1. 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.

NameTypeUnitDescription
timearray_likes

Uniformly sampled time axis.

dataarray_likeany

Signal samples.

sample_ratefloat, optionalHz

Overrides the rate derived from the time axis.

npersegint, optional-

Window length in samples.

window_durationfloat, optionals

Window length as a duration, converted to samples.

overlapfloat, optional-

Fractional overlap between windows.

windowstr, optional-

Window name.

detrendstr 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

  1. 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.

NameTypeUnitDescription
recordssequence of FluctuationRecord-

Named scalar records, each with its own time, units and usable band.

sample_ratefloat, optionalHz

Common-grid rate; defaults to the slowest native rate, as cross_spectrogram does, so no record is upsampled.

frequency_rangetuple of float, optionalHz

Inclusive output band; defaults to all usable bins.

npersegint, optional-

Samples in each inner Welch segment.

segments_per_windowint, optional-

Non-overlapping inner segments per output time; defaults to the larger of four and one more than the selected diagnostic count.

window_step_samplesint, optional-

Output-window advance, defaulting to half an outer window.

normalization{"none", "variance", "psd", "user"}, optional-

Explicit scaling policy; "psd" gives a dimensionless matrix.

user_scalesmapping, optionalrecord units

Positive per-record amplitude scales, required for "user".

windowstr, optional-

SciPy window name.

detrendstr or bool, optional-

"constant", "linear" or False for each inner segment.

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

  • ValueError Invalid records, bands, normalization or grid, or too few common samples.
Processing steps · Defaults · Applicability · Limitations · Provenance

Processing steps

  1. Align every record on the overlapping interval, with anti-aliasing for rate reductions and mask propagation for missing/short filtered spans.
  2. Compute identically windowed one-sided FFTs in non-overlapping segments.
  3. 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.
  4. 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

  1. Welch’s one-sided density scaling as in scipy.signal.csd.
  2. vaft.process.signal_processing.resample_to_time provides 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.

NameTypeUnitDescription
time_xarray_likes

Uniform time axis of the phase-reference record.

xarray_likeunits_x

First scalar signal.

time_yarray_likes

Uniform time axis of the second record.

yarray_likeunits_y

Second scalar signal.

sample_ratefloat, optionalHz

Rate of a common grid over the overlapping interval.

common_timearray_like, optionals

Explicit uniform common grid, overriding sample_rate.

bandwidth_x_hzfloat, optionalHz

Physically usable upper bandwidth of x; defaults to its Nyquist.

bandwidth_y_hzfloat, optionalHz

Physically usable upper bandwidth of y; defaults to its Nyquist.

frequency_rangetuple of float, optionalHz

Inclusive output band, defaulting to the full common usable band.

npersegint, optional-

Samples in one Welch segment.

segments_per_windowint, optional-

Non-overlapping Welch segments averaged in each output window.

window_step_samplesint, optional-

Output-window advance, defaulting to half an outer window.

windowstr, optional-

SciPy spectral window name.

detrendstr or bool, optional-

Detrending passed to SciPy Welch and CSD.

units_xstr, optional-

Caller-supplied physical unit label for x.

units_ystr, 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

  • ValueError Invalid axes, bandwidth or averaging parameters; non-overlapping or too-short records; or incomplete anti-alias filtering.
Processing steps · Defaults · Applicability · Limitations · Provenance

Processing steps

  1. Validate both records and align their overlapping time interval.
  2. Filter before rate reduction, refusing incomplete filter coverage.
  3. For each complete output window, average non-overlapping Welch segments before deriving coherence and phase from the averaged densities.
  4. 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

  1. scipy.signal.welch and scipy.signal.csd provide the one-sided Welch density scaling for every output window.
  2. vaft.process.signal_processing.resample_to_time provides 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.

NameTypeUnitDescription
time_xarray_likes

Uniformly sampled time axis of x.

xarray_likeany

First record, the phase reference.

time_yarray_likes

Uniformly sampled time axis of y.

yarray_likeany

Second record.

sample_ratefloat, optionalHz

Rate of a uniform common grid laid over the overlap; both records are resampled onto it.

npersegint, optional-

Welch segment length on the common grid.

noverlapint, optional-

Segment overlap on the common grid.

windowstr, optional-

Any window name SciPy accepts.

detrendstr or bool, optional-

Passed through to the underlying estimator.

common_timearray_like, optionals

An explicit uniform grid to compare on, overriding sample_rate.

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

  • ValueError Either axis is not uniform, or the two records do not overlap in time.
Processing steps · Defaults · Applicability · Limitations · Provenance

Processing steps

  1. Validate both time axes as uniform and increasing.
  2. Choose the common grid: the shared axis when the two are identical; otherwise common_time, else a uniform grid at sample_rate over the overlap, else the slower record’s own samples inside the overlap.
  3. 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.
  4. 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.
  5. 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

  1. Welch’s method for auto- and cross-spectra as implemented by scipy.signal.welch and scipy.signal.csd.
  2. 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.

NameTypeUnitDescription
frequencyarray_likeHz

Frequency axis.

psdarray_likeany

Power spectral density.

fit_rangesequence of floatHz

Outer band spanning both regimes.

break_frequencyfloat, optionalHz

An imposed boundary, for the physics-informed mode.

search_rangesequence of float, optionalHz

Interval to scan, for the data-driven mode.

n_candidatesint, 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

  • ValueError Neither 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

  1. 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.

NameTypeUnitDescription
frequencyarray_likeHz

Frequency axis.

psdarray_likeany

Power spectral density on that axis.

f_rangesequence of floatHz

The band to fit over, as (f_low, f_high).

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

  • ValueError Fewer 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

  1. 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.

NameTypeUnitDescription
spectrogramAny-

An object with time, frequency and a (frequency, time) magnitude – FluctuationSpectrogram or a magnetics spectrogram result – or the triple (time, frequency, magnitude).

search_rangesequence of floatHz

Lowest and highest frequency the ridge may be found at.

max_jumpfloat, optionalHz

Largest frequency change allowed between neighbouring windows; None takes each window’s own maximum independently.

floor_ratiofloat, optional-

Fraction of the map’s in-range peak a window’s ridge must exceed.

Returns
—FrequencyTrack-

(time, frequency, power): the window times in seconds, the ridge frequency in hertz and its magnitude in the map’s own unit, each NaN in a window where no ridge clears the floor.

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

  • ValueError The magnitude does not match its axes, search_range is not increasing, or an argument is negative.
Processing steps · Defaults · Applicability · Limitations · Provenance

Processing steps

  1. Keep the frequency bins inside search_range.
  2. Set the floor at floor_ratio times the largest in-range magnitude of the whole map; a window whose in-range maximum does not exceed it has no ridge.
  3. Split the remaining windows into runs of consecutive windows.
  4. Within each run, choose one bin per window: the window’s own maximum when max_jump is None, otherwise the path of largest summed magnitude whose step between neighbouring windows never exceeds max_jump.
  5. 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

  1. 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.
  2. The single-argmax reference-frequency tracker of the legacy FAST-camera analysis, which vaft.process.camera_fluctuation.track_reference_frequency now calls with floor_ratio=0.

results matching ""

    No results matching ""