spectral_connectivity.transforms.SpectralTransform#
- class SpectralTransform(*args, **kwargs)[source]#
Bases:
ProtocolInterface a transform needs for
Connectivity.from_transform().Any object with an
fft()method andfrequenciesandtimeattributes (plain attributes or properties) satisfies it; no subclassing or registration is needed.Multitaper,ShortTimeFourierTransform,Welch, andMorletWaveletall satisfy it.- frequencies#
Frequency of each bin of the
fft()output, in Hz. A two-sided transform lists them in standard FFT order (numpy.fft.fftfreq); a one-sided transform lists non-negative, strictly increasing values.NonemakesConnectivityuse normalized frequencies in cycles per sample:numpy.fft.fftfreq(n_fft_samples)for a two-sided transform,numpy.linspace(0, 0.5, n_fft_samples)for a one-sided one.- Type:
ndarray, shape (n_fft_samples,), or None
- time#
Time of each time window, in seconds.
NonemakesConnectivityuse the window indices.- Type:
ndarray, shape (n_time_windows,), or None
Notes
fft()must return the Fourier coefficients with shape(n_time_windows, n_trials, n_tapers, n_fft_samples, n_signals).fft()must return fresh, unshared storage on each call. Neither the transform nor its caller may subsequently mutate that storage through any alias.Connectivitykeeps it without copying and marks it read-only where the backend supports this. The flag is only a safeguard: existing writable NumPy views remain writable, and CuPy has no read-only flag. Mutating the storage would silently change the coefficients while cached results keep the old values.The coefficients’ scale sets the units of
Connectivity.power(); normalized measures such as coherence and the phase-lag indices do not depend on it, so an unscaled FFT is enough for those. Forpower()to be a power spectral density (signal² / Hz),|coefficient|²must be a density:a two-sided transform returns
fft(window * x) / sqrt(sampling_frequency)for a unit-energy window (sum(window**2) == 1), asMultitaperdoes;power()then folds it onto the non-negative frequencies, doubling every bin but DC and, for an even FFT length, Nyquist;a one-sided transform (
is_one_sided = True) must fold in the negative frequencies itself, multiplying every bin but 0 Hz and Nyquist bysqrt(2), becausepower()uses one-sided coefficients as given.MorletWavelet, whose frequencies all lie strictly between 0 Hz and Nyquist, scales every coefficient of a unit-energy wavelet bysqrt(2 / sampling_frequency).
Connectivity.from_transform()also reads the following optional attributes. A transform that lacks one gets the default, which describes a plain two-sided FFT of independent observations, so only a transform whose output differs needs to define it:is_one_sidedbool, default FalseWhether the coefficients hold only non-negative frequencies (as for a wavelet transform). One-sided coefficients are used as given, without taking the half spectrum or doubling power, and cannot be used by the Wilson-factorized directed measures.
observation_weightsndarray, shape (n_time_windows, n_trials, n_tapers, n_fft_samples, 1), default NoneFinite, non-negative weights applied to every expectation over the coefficients and shared across signals, e.g. a smoothing kernel or a mask for invalid edge estimates.
Noneweights all observations equally.observations_are_independentbool, default TrueWhether the trial and taper observations are statistically independent. Set it
Falsewhen that axis holds correlated estimates; measures whose corrections count observations then warn, and the jackknife refuses to leave out tapers.time_bins_are_independentbool, default TrueWhether successive time windows are independent (e.g.
Falsefor windows overlapping by more than half). It affects only expectations that average over time.
isinstancechecks only thatfft,frequencies, andtimeexist (on Python 3.11 and earlier it also evaluates the two properties).Connectivity.from_transform()checks the coefficients’ shape and complex dtype, the coordinate lengths, the frequency order, and that the flags are bools (NumPy bools included), not methods.Examples
Wrap Fourier coefficients computed elsewhere:
>>> import numpy as np >>> from spectral_connectivity import Connectivity, SpectralTransform >>> class PrecomputedTransform: ... def __init__(self, coefficients, frequencies, time): ... self._coefficients = coefficients ... self.frequencies = frequencies ... self.time = time ... ... def fft(self): ... return self._coefficients.copy() >>> rng = np.random.default_rng(0) >>> shape = (1, 10, 1, 16, 2) # (time windows, trials, tapers, FFT bins, signals) >>> coefficients = rng.standard_normal(shape) + 1j * rng.standard_normal(shape) >>> transform = PrecomputedTransform( ... coefficients, np.fft.fftfreq(16, d=1 / 500), time=np.array([0.0]) ... ) >>> isinstance(transform, SpectralTransform) True >>> connectivity = Connectivity.from_transform(transform) >>> connectivity.coherence_magnitude().shape # (time, frequency, signal, signal) (1, 9, 2, 2)
- Attributes:
frequenciesFrequency of each FFT bin, in Hz.
timeTime of each time window, in seconds.
Methods
fft()Return the coefficients,
(n_time_windows, n_trials, n_tapers, n_fft_samples, n_signals).Methods
Return the coefficients,
(n_time_windows, n_trials, n_tapers, n_fft_samples, n_signals).Attributes
Frequency of each FFT bin, in Hz.
Time of each time window, in seconds.
- fft() ndarray[tuple[int, ...], dtype[complexfloating]][source]#
Return the coefficients,
(n_time_windows, n_trials, n_tapers, n_fft_samples, n_signals).