diff --git a/.buildinfo b/.buildinfo index 3bb78b8..0c18986 100644 --- a/.buildinfo +++ b/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 0e302fff034c73a1755494f52f6f5615 +config: 2a4b169f52f0af530d2c9204495e5109 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/_autoexamples/pyrasa.irasa.irasa.html b/_autoexamples/pyrasa.irasa.irasa.html new file mode 100644 index 0000000..27be343 --- /dev/null +++ b/_autoexamples/pyrasa.irasa.irasa.html @@ -0,0 +1,578 @@ + + + + + + + + + + + pyrasa.irasa.irasa — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +
+

pyrasa.irasa.irasa#

+
+
+pyrasa.irasa.irasa(data: ~numpy.ndarray, fs: int, band: tuple[float, float], psd_kwargs: dict, ch_names: ~numpy.ndarray | None = None, win_func: ~collections.abc.Callable = <function hann>, win_func_kwargs: dict | None = None, dpss_settings_time_bandwidth: float = 2.0, dpss_settings_low_bias: bool = True, dpss_eigenvalue_weighting: bool = True, filter_settings: tuple[float | None, float | None] = (None, None), hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05), hset_accuracy: int = 4) IrasaSpectrum[source]#
+

Computes the aperiodic and periodic components of the power spectrum from a time series using the +Irregular Resampling Autocorrelation (IRASA) algorithm.

+

The IRASA algorithm allows for the decomposition of neural signals into fractal (aperiodic) and +oscillatory (periodic) components, providing insight into the underlying dynamics of the data.

+
+
Parameters:
+
+
datanp.ndarray

Time series data, where the shape is expected to be either (Samples,) or (Channels, Samples).

+
+
fsint

Sampling frequency of the data in Hz.

+
+
bandtuple[float, float]

The frequency range (lower and upper bounds in Hz) over which to compute the spectra.

+
+
psd_kwargspython:dict

Keyword arguments to be passed to the scipy.signal.welch function for PSD estimation.

+
+
ch_namesnp.ndarray | python:None, optional

Channel names associated with the data, if available. Default is None.

+
+
win_funcCallable, optional

Window function to be used in Welch’s method. Default is dsp.windows.hann.

+
+
win_func_kwargspython:dict | python:None, optional

Additional keyword arguments for the window function. Default is None.

+
+
dpss_settings_time_bandwidthfloat, optional

Time-bandwidth product for the DPSS windows if used. Default is 2.0.

+
+
dpss_settings_low_biasbool, optional

Keep only tapers with eigenvalues > 0.9. Default is True.

+
+
dpss_eigenvalue_weightingbool, optional

Whether or not to apply eigenvalue weighting in DPSS. If True, spectral estimates weighted by +the concentration ratio of their respective tapers before combining. Default is True.

+
+
filter_settingstuple[float | python:None, float | python:None], optional

Cutoff frequencies for highpass and lowpass filtering to avoid artifacts in the evaluated frequency range. +Default is (None, None).

+
+
hset_infotuple[float, float, float], optional

Tuple specifying the range of the resampling factors as (min, max, step). Default is (1.05, 2.0, 0.05).

+
+
hset_accuracyint, optional

Decimal precision for the resampling factors. Default is 4.

+
+
+
+
Returns:
+
+
IrasaSpectrum
+
An object containing the following attributes:
    +
  • +
    freqs: np.ndarray

    Frequencies corresponding to the computed spectra.

    +
    +
    +
  • +
  • +
    raw_spectrum: np.ndarray

    The raw power spectrum.

    +
    +
    +
  • +
  • +
    aperiodic: np.ndarray

    The aperiodic (fractal) component of the spectrum.

    +
    +
    +
  • +
  • +
    periodic: np.ndarray

    The periodic (oscillatory) component of the spectrum.

    +
    +
    +
  • +
  • +
    ch_names: np.ndarray

    Channel names if provided.

    +
    +
    +
  • +
+
+
+
+
+
+
+

Notes

+

This function provides fine-grained control over the IRASA parameters. For users working with MNE-Python, +the irasa_raw and irasa_epochs functions from pyrasa.irasa_mne are recommended, as they handle +additional preprocessing steps.

+

References

+

Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum +of Neurophysiological Signal. Brain Topography, 29(1), 13–26. https://doi.org/10.1007/s10548-015-0448-0

+
+ +
+ + +
+ + + + + + + +
+ + + +
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autoexamples/pyrasa.irasa.irasa_sprint.html b/_autoexamples/pyrasa.irasa.irasa_sprint.html new file mode 100644 index 0000000..fc7b4da --- /dev/null +++ b/_autoexamples/pyrasa.irasa.irasa_sprint.html @@ -0,0 +1,585 @@ + + + + + + + + + + + pyrasa.irasa.irasa_sprint — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +
+

pyrasa.irasa.irasa_sprint#

+
+
+pyrasa.irasa.irasa_sprint(data: ~numpy.ndarray, fs: int, ch_names: ~numpy.ndarray | None = None, band: tuple[float, float] = (1.0, 100.0), win_duration: float = 0.4, overlap_fraction: float = 0.9, win_func: ~collections.abc.Callable = <function hann>, win_func_kwargs: dict | None = None, dpss_settings_time_bandwidth: float = 2.0, dpss_settings_low_bias: bool = True, dpss_eigenvalue_weighting: bool = True, filter_settings: tuple[float | None, float | None] = (None, None), hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05), hset_accuracy: int = 4) IrasaTfSpectrum[source]#
+

Computes time-resolved aperiodic and periodic components of the power spectrum from a time series +using the Irregular Resampling Autocorrelation (IRASA) algorithm.

+

This function is useful for analyzing how the aperiodic and periodic components of the power spectrum +change over time, providing a time-frequency decomposition of the signal.

+
+
Parameters:
+
+
datanp.ndarray

Time series data, where the shape is expected to be either (Samples,) or (Channels, Samples).

+
+
fsint

Sampling frequency of the data in Hz.

+
+
ch_namesnp.ndarray | python:None, optional

Channel names associated with the data, if available. Default is None.

+
+
bandtuple[float, float], optional

The frequency range (lower and upper bounds in Hz) over which to compute the spectra. Default is (1.0, 100.0).

+
+
win_durationfloat, optional

Duration of the window in seconds used for the short-time Fourier transforms (STFTs). Default is 0.4 seconds.

+
+
overlap_fractionint, optional

The overlap between the STFT sliding windows as fraction. Default is .99 of the windows.

+
+
win_funcCallable, optional

Window function to be used in computing the time frequency spectrum. Default is dsp.windows.hann.

+
+
win_func_kwargspython:dict | python:None, optional

Additional keyword arguments for the window function. Default is None.

+
+
dpss_settings_time_bandwidthfloat, optional

Time-bandwidth product for the DPSS windows if used. Default is 2.0.

+
+
dpss_settings_low_biasbool, optional

Keep only tapers with eigenvalues > 0.9. Default is True.

+
+
dpss_eigenvalue_weightingbool, optional

Whether or not to apply eigenvalue weighting in DPSS. If True, spectral estimates weighted by +the concentration ratio of their respective tapers before combining. Default is True.

+
+
filter_settingstuple[float | python:None, float | python:None], optional

Cutoff frequencies for highpass and lowpass filtering to avoid artifacts in the evaluated frequency range. +Default is (None, None).

+
+
hset_infotuple[float, float, float], optional

Tuple specifying the range of the resampling factors as (min, max, step). Default is (1.05, 2.0, 0.05).

+
+
hset_accuracyint, optional

Decimal precision for the resampling factors. Default is 4.

+
+
+
+
Returns:
+
+
IrasaTfSpectrum
+
An object containing the following attributes:
    +
  • +
    freqs: np.ndarray

    Frequencies corresponding to the computed spectra.

    +
    +
    +
  • +
  • +
    time: np.ndarray

    Time bins in seconds associated with the (a-)periodic spectra.

    +
    +
    +
  • +
  • +
    raw_spectrum: np.ndarray

    The raw time-frequency power spectrum.

    +
    +
    +
  • +
  • +
    aperiodic: np.ndarray

    The aperiodic (fractal) component of the spectrum.

    +
    +
    +
  • +
  • +
    periodic: np.ndarray

    The periodic (oscillatory) component of the spectrum.

    +
    +
    +
  • +
  • +
    ch_names: np.ndarray

    Channel names if provided.

    +
    +
    +
  • +
+
+
+
+
+
+
+

Notes

+

This function performs a time-frequency decomposition of the input data, allowing for a time-resolved analysis +of the periodic and aperiodic components of the signal. The STFT is computed for each time window, and IRASA +is applied to separate the spectral components.

+

References

+

Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum of +Neurophysiological Signal. Brain Topography, 29(1), 13–26. https://doi.org/10.1007/s10548-015-0448-0

+
+ +
+ + +
+ + + + + + + +
+ + + +
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autoexamples/pyrasa.irasa_mne.irasa_epochs.html b/_autoexamples/pyrasa.irasa_mne.irasa_epochs.html new file mode 100644 index 0000000..ec1b136 --- /dev/null +++ b/_autoexamples/pyrasa.irasa_mne.irasa_epochs.html @@ -0,0 +1,531 @@ + + + + + + + + + + + pyrasa.irasa_mne.irasa_epochs — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +
+

pyrasa.irasa_mne.irasa_epochs#

+
+
+pyrasa.irasa_mne.irasa_epochs(data: Epochs, band: tuple[float, float] = (1.0, 100.0), hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05)) IrasaEpoched[source]#
+

Separate aperiodic from periodic power spectra using the IRASA algorithm for Epochs data.

+

This function applies the Irregular Resampling Auto-Spectral Analysis (IRASA) algorithm +as described by Wen & Liu (2016) to decompose the power spectrum of neurophysiological +signals into aperiodic (fractal) and periodic (oscillatory) components. It is specifically +designed for time-series data in mne.Epochs format, making it suitable for event-related +EEG/MEG analyses.

+
+
Parameters:
+
+
datamne.Epochs

The time-series data used to extract aperiodic and periodic power spectra. +This should be an instance of mne.Epochs.

+
+
bandtuple of (float, float), optional, default: (1.0, 100.0)

A tuple specifying the lower and upper bounds of the frequency range (in Hz) used +for extracting the aperiodic and periodic spectra.

+
+
hset_infotuple of (float, float, float), optional, default: (1.05, 2.0, 0.05)

Contains the range of up/downsampling factors used in the IRASA algorithm. +This should be a tuple specifying the (min, max, step) values for the resampling.

+
+
+
+
Returns:
+
+
aperiodicAperiodicEpochsSpectrum

The aperiodic component of the data as an AperiodicEpochsSpectrum object.

+
+
periodicPeriodicEpochsSpectrum

The periodic component of the data as a PeriodicEpochsSpectrum object.

+
+
+
+
+

References

+

Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum +of Neurophysiological Signal. Brain Topography, 29(1), 13–26. +https://doi.org/10.1007/s10548-015-0448-0

+
+ +
+ + +
+ + + + + + + +
+ + + +
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autoexamples/pyrasa.irasa_mne.irasa_raw.html b/_autoexamples/pyrasa.irasa_mne.irasa_raw.html new file mode 100644 index 0000000..2f70fc1 --- /dev/null +++ b/_autoexamples/pyrasa.irasa_mne.irasa_raw.html @@ -0,0 +1,552 @@ + + + + + + + + + + + pyrasa.irasa_mne.irasa_raw — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +
+

pyrasa.irasa_mne.irasa_raw#

+
+
+pyrasa.irasa_mne.irasa_raw(data: Raw, band: tuple[float, float] = (1.0, 100.0), duration: float | None = None, overlap: float | int = 50, hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05)) IrasaRaw[source]#
+

Separate aperiodic from periodic power spectra using the IRASA algorithm.

+

This function applies the Irregular Resampling Auto-Spectral Analysis (IRASA) algorithm +as described by Wen & Liu (2016) to decompose the power spectrum of neurophysiological +signals into aperiodic (fractal) and periodic (oscillatory) components. This function is +essentially a wrapper function for pyrasa.irasa

+
+
Parameters:
+
+
datamne.io.Raw

The time-series data from which the aperiodic and periodic power spectra are extracted. +This should be an instance of mne.io.Raw. The function will automatically extract +relevant parameters such as sampling frequency (sfreq) and filtering settings from the mne object +to make sure the model is specified correctly.

+
+
bandtuple of (float, float), optional, default: (1.0, 100.0)

A tuple specifying the lower and upper bounds of the frequency range (in Hz) used +for extracting the aperiodic and periodic spectra.

+
+
durationfloat, required

The duration (in seconds) of each segment used to calculate the power spectral density (PSD). +This must be less than the total duration of the data.

+
+
overlapfloat or int, optional, default: 50

The overlap between segments, specified as a percentage (0-100).

+
+
hset_infotuple of (float, float, float), optional, default: (1.05, 2.0, 0.05)

Contains the range of up/downsampling factors used in the IRASA algorithm. +This should be a tuple specifying the (min, max, step) values for the resampling.

+
+
+
+
Returns:
+
+
IrasaRaw

A custom object containing the separated aperiodic and periodic components of the data: +- periodic: An instance of PeriodicSpectrumArray, which includes the periodic

+
+

(oscillatory) component of the power spectrum.

+
+
    +
  • aperiodic: An instance of AperiodicSpectrumArray, which includes the aperiodic +(fractal) component of the power spectrum.

  • +
+
+
+
+
+

Notes

+
    +
  • Ensure that data does not contain any bad channels (data.info[‘bads’] should be empty), +as this could affect the results.

  • +
  • The overlap percentage should be carefully chosen to balance between segment independence +and sufficient data for analysis. A value between 0 and 100% is valid.

  • +
  • The function will raise assertions if the input parameters are not consistent with the +expected formats or if the provided duration exceeds the length of the data.

  • +
+

References

+

Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum +of Neurophysiological Signal. Brain Topography, 29(1), 13–26. +https://doi.org/10.1007/s10548-015-0448-0

+
+ +
+ + +
+ + + + + + + +
+ + + +
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_autoexamples/pyrasa.utils.aperiodic_utils.compute_aperiodic_model.html b/_autoexamples/pyrasa.utils.aperiodic_utils.compute_aperiodic_model.html new file mode 100644 index 0000000..6424784 --- /dev/null +++ b/_autoexamples/pyrasa.utils.aperiodic_utils.compute_aperiodic_model.html @@ -0,0 +1,553 @@ + + + + + + + + + + + pyrasa.utils.aperiodic_utils.compute_aperiodic_model — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + +
+ + + + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +
+

pyrasa.utils.aperiodic_utils.compute_aperiodic_model#

+
+
+pyrasa.utils.aperiodic_utils.compute_aperiodic_model(aperiodic_spectrum: ndarray, freqs: ndarray, fit_func: str | type[AbstractFitFun] = 'fixed', ch_names: Iterable | None = None, scale: bool = False, fit_bounds: tuple[float, float] | None = None) AperiodicFit[source]#
+

Computes aperiodic parameters from the aperiodic spectrum using scipy’s curve fitting function.

+

This function can be used to model the aperiodic (1/f-like) component of the power spectrum. Per default, users can +choose between a fixed or knee model fit or specify their own fit method see examples custom_fit_functions.ipynb +for an example. The function returns the fitted parameters for each channel along with some +goodness of fit metrics.

+
+
Parameters:
+
+
aperiodic_spectrumnp.ndarray

A 1 or 2D array of power values for the aperiodic spectrum where the shape is +expected to be either (Samples,) or (Channels, Samples).

+
+
freqsnp.ndarray

A 1D array of frequency values corresponding to the aperiodic spectrum.

+
+
fit_funcpython:str or type[AbstractFitFun], optional

The fitting function to use. Can be “fixed” for a linear fit or “knee” for a fit that includes a +knee (bend) in the spectrum or a class that is inherited from AbstractFitFun. The default is ‘fixed’.

+
+
ch_namesIterable or python:None, optional

Channel names corresponding to the aperiodic spectrum. If None, channels will be named numerically +in ascending order. Default is None.

+
+
scalebool, optional

Whether to scale the data to improve fitting accuracy. This is useful in cases where +power values are very small (e.g., 1e-28), which may lead to numerical precision issues during fitting. +After fitting, the parameters are rescaled to match the original data scale. Default is False.

+
+
fit_boundstuple[float, float] or python:None, optional

Tuple specifying the lower and upper frequency bounds for the fit function. If None, the entire frequency +range is used. Otherwise, the spectrum is cropped to the specified bounds. Default is None.

+
+
+
+
Returns:
+
+
AperiodicFit
+
An object containing three pandas DataFrames:
    +
  • +
    aperiodic_paramspd.DataFrame

    A DataFrame containing the fitted aperiodic parameters for each channel.

    +
    +
    +
  • +
  • +
    gofpd.DataFrame

    A DataFrame containing the goodness of fit metrics for each channel.

    +
    +
    +
  • +
  • +
    modelpd.DataFrame

    A DataFrame containing the predicted aperiodic model for each channel.

    +
    +
    +
  • +
+
+
+
+
+
+
+

Notes

+

This function fits the aperiodic component of the power spectrum using scipy’s curve fitting function. +The fitting can be performed using either a simple linear model (‘fixed’) or a more complex model +that includes a “knee” point, where the spectrum bends. The resulting parameters can help in +understanding the underlying characteristics of the aperiodic component in the data.

+

If the fit_bounds parameter is used, it ensures that only the specified frequency range is considered +for fitting, which can be important to avoid fitting artifacts outside the region of interest.

+

The scale parameter can be crucial when dealing with data that have extremely small values, +as it helps to mitigate issues related to machine precision during the fitting process.

+

The function asserts that the input data are of the correct type and shape, and raises warnings +if the first frequency value is zero, as this can cause issues during model fitting.

+
+ +
+ + +
+ + + + + + + +
+ + + +
+ + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 0000000..11c94b8 --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,431 @@ + + + + + + + + + + Overview: module code — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + + + +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + + + + + + + +
+ +
+
+
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_modules/pyrasa/irasa.html b/_modules/pyrasa/irasa.html new file mode 100644 index 0000000..31a5aa6 --- /dev/null +++ b/_modules/pyrasa/irasa.html @@ -0,0 +1,780 @@ + + + + + + + + + + pyrasa.irasa — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + + + +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for pyrasa.irasa

+"""Functions to compute IRASA."""
+
+from collections.abc import Callable
+from typing import TYPE_CHECKING, Any
+
+import numpy as np
+import scipy.signal as dsp
+
+from pyrasa.utils.irasa_spectrum import IrasaSpectrum
+from pyrasa.utils.irasa_tf_spectrum import IrasaTfSpectrum
+
+# from scipy.stats.mstats import gmean
+from pyrasa.utils.irasa_utils import (
+    _check_irasa_settings,
+    _compute_psd_welch,
+    _compute_sgramm,
+    _crop_data,
+    _gen_irasa,
+)
+
+if TYPE_CHECKING:
+    from pyrasa.utils.types import IrasaSprintKwargsTyped
+
+
+# %% irasa
+
+[docs] +def irasa( + data: np.ndarray, + fs: int, + band: tuple[float, float], + psd_kwargs: dict, + ch_names: np.ndarray | None = None, + win_func: Callable = dsp.windows.hann, + win_func_kwargs: dict | None = None, + dpss_settings_time_bandwidth: float = 2.0, + dpss_settings_low_bias: bool = True, + dpss_eigenvalue_weighting: bool = True, + filter_settings: tuple[float | None, float | None] = (None, None), + hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05), + hset_accuracy: int = 4, +) -> IrasaSpectrum: + """ + Computes the aperiodic and periodic components of the power spectrum from a time series using the + Irregular Resampling Autocorrelation (IRASA) algorithm. + + The IRASA algorithm allows for the decomposition of neural signals into fractal (aperiodic) and + oscillatory (periodic) components, providing insight into the underlying dynamics of the data. + + Parameters + ---------- + data : np.ndarray + Time series data, where the shape is expected to be either (Samples,) or (Channels, Samples). + fs : int + Sampling frequency of the data in Hz. + band : tuple[float, float] + The frequency range (lower and upper bounds in Hz) over which to compute the spectra. + psd_kwargs : dict + Keyword arguments to be passed to the `scipy.signal.welch` function for PSD estimation. + ch_names : np.ndarray | None, optional + Channel names associated with the data, if available. Default is None. + win_func : Callable, optional + Window function to be used in Welch's method. Default is `dsp.windows.hann`. + win_func_kwargs : dict | None, optional + Additional keyword arguments for the window function. Default is None. + dpss_settings_time_bandwidth : float, optional + Time-bandwidth product for the DPSS windows if used. Default is 2.0. + dpss_settings_low_bias : bool, optional + Keep only tapers with eigenvalues > 0.9. Default is True. + dpss_eigenvalue_weighting : bool, optional + Whether or not to apply eigenvalue weighting in DPSS. If True, spectral estimates weighted by + the concentration ratio of their respective tapers before combining. Default is True. + filter_settings : tuple[float | None, float | None], optional + Cutoff frequencies for highpass and lowpass filtering to avoid artifacts in the evaluated frequency range. + Default is (None, None). + hset_info : tuple[float, float, float], optional + Tuple specifying the range of the resampling factors as (min, max, step). Default is (1.05, 2.0, 0.05). + hset_accuracy : int, optional + Decimal precision for the resampling factors. Default is 4. + + Returns + ------- + IrasaSpectrum + An object containing the following attributes: + - freqs: np.ndarray + Frequencies corresponding to the computed spectra. + - raw_spectrum: np.ndarray + The raw power spectrum. + - aperiodic: np.ndarray + The aperiodic (fractal) component of the spectrum. + - periodic: np.ndarray + The periodic (oscillatory) component of the spectrum. + - ch_names: np.ndarray + Channel names if provided. + + Notes + ----- + This function provides fine-grained control over the IRASA parameters. For users working with MNE-Python, + the `irasa_raw` and `irasa_epochs` functions from `pyrasa.irasa_mne` are recommended, as they handle + additional preprocessing steps. + + References + ---------- + Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum + of Neurophysiological Signal. Brain Topography, 29(1), 13–26. https://doi.org/10.1007/s10548-015-0448-0 + """ + + # set parameters + if win_func_kwargs is None: + win_func_kwargs = {} + + # Minimal safety checks + if data.ndim == 1: + data = data[np.newaxis, :] + assert data.ndim == 2, 'Data shape needs to be either of shape (Channels, Samples) or (Samples, ).' # noqa PLR2004 + + irasa_params = { + 'data': data, + 'fs': fs, + 'band': band, + 'filter_settings': filter_settings, + 'hset_accuracy': hset_accuracy, + } + + _check_irasa_settings(irasa_params=irasa_params, hset_info=hset_info) + + hset = np.round(np.arange(*hset_info), hset_accuracy) + hset = [h for h in hset if h % 1 != 0] # filter integers + + win_kwargs = {'win_func': win_func, 'win_func_kwargs': win_func_kwargs} + dpss_settings = { + 'time_bandwidth': dpss_settings_time_bandwidth, + 'low_bias': dpss_settings_low_bias, + 'eigenvalue_weighting': dpss_eigenvalue_weighting, + } + + def _local_irasa_fun( + data: np.ndarray, + fs: int, + *args: Any, + **kwargs: Any, + ) -> np.ndarray: + return _compute_psd_welch( + data, + fs=fs, + nperseg=psd_kwargs.get('nperseg'), + win_kwargs=win_kwargs, + dpss_settings=dpss_settings, + noverlap=psd_kwargs.get('noverlap'), + nfft=psd_kwargs.get('nfft'), + )[1] + + freq, psd = _compute_psd_welch( + data, + fs=fs, + nperseg=psd_kwargs.get('nperseg'), + win_kwargs=win_kwargs, + dpss_settings=dpss_settings, + noverlap=psd_kwargs.get('noverlap'), + nfft=psd_kwargs.get('nfft'), + ) + + psd, psd_aperiodic, psd_periodic = _gen_irasa( + data=np.squeeze(data), orig_spectrum=psd, fs=fs, irasa_fun=_local_irasa_fun, hset=hset + ) + + freq, psd_aperiodic, psd_periodic, psd = _crop_data(band, freq, psd_aperiodic, psd_periodic, psd, axis=-1) + + return IrasaSpectrum( + freqs=freq, + raw_spectrum=psd, + aperiodic=psd_aperiodic, + periodic=psd_periodic, + ch_names=ch_names, + )
+ + + +# irasa sprint +
+[docs] +def irasa_sprint( # noqa PLR0915 C901 + data: np.ndarray, + fs: int, + ch_names: np.ndarray | None = None, + band: tuple[float, float] = (1.0, 100.0), + win_duration: float = 0.4, + overlap_fraction: float = 0.90, + win_func: Callable = dsp.windows.hann, + win_func_kwargs: dict | None = None, + dpss_settings_time_bandwidth: float = 2.0, + dpss_settings_low_bias: bool = True, + dpss_eigenvalue_weighting: bool = True, + filter_settings: tuple[float | None, float | None] = (None, None), + hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05), + hset_accuracy: int = 4, +) -> IrasaTfSpectrum: + """ + Computes time-resolved aperiodic and periodic components of the power spectrum from a time series + using the Irregular Resampling Autocorrelation (IRASA) algorithm. + + This function is useful for analyzing how the aperiodic and periodic components of the power spectrum + change over time, providing a time-frequency decomposition of the signal. + + Parameters + ---------- + data : np.ndarray + Time series data, where the shape is expected to be either (Samples,) or (Channels, Samples). + fs : int + Sampling frequency of the data in Hz. + ch_names : np.ndarray | None, optional + Channel names associated with the data, if available. Default is None. + band : tuple[float, float], optional + The frequency range (lower and upper bounds in Hz) over which to compute the spectra. Default is (1.0, 100.0). + win_duration : float, optional + Duration of the window in seconds used for the short-time Fourier transforms (STFTs). Default is 0.4 seconds. + overlap_fraction : int, optional + The overlap between the STFT sliding windows as fraction. Default is .99 of the windows. + win_func : Callable, optional + Window function to be used in computing the time frequency spectrum. Default is `dsp.windows.hann`. + win_func_kwargs : dict | None, optional + Additional keyword arguments for the window function. Default is None. + dpss_settings_time_bandwidth : float, optional + Time-bandwidth product for the DPSS windows if used. Default is 2.0. + dpss_settings_low_bias : bool, optional + Keep only tapers with eigenvalues > 0.9. Default is True. + dpss_eigenvalue_weighting : bool, optional + Whether or not to apply eigenvalue weighting in DPSS. If True, spectral estimates weighted by + the concentration ratio of their respective tapers before combining. Default is True. + filter_settings : tuple[float | None, float | None], optional + Cutoff frequencies for highpass and lowpass filtering to avoid artifacts in the evaluated frequency range. + Default is (None, None). + hset_info : tuple[float, float, float], optional + Tuple specifying the range of the resampling factors as (min, max, step). Default is (1.05, 2.0, 0.05). + hset_accuracy : int, optional + Decimal precision for the resampling factors. Default is 4. + + Returns + ------- + IrasaTfSpectrum + An object containing the following attributes: + - freqs: np.ndarray + Frequencies corresponding to the computed spectra. + - time: np.ndarray + Time bins in seconds associated with the (a-)periodic spectra. + - raw_spectrum: np.ndarray + The raw time-frequency power spectrum. + - aperiodic: np.ndarray + The aperiodic (fractal) component of the spectrum. + - periodic: np.ndarray + The periodic (oscillatory) component of the spectrum. + - ch_names: np.ndarray + Channel names if provided. + + Notes + ----- + This function performs a time-frequency decomposition of the input data, allowing for a time-resolved analysis + of the periodic and aperiodic components of the signal. The STFT is computed for each time window, and IRASA + is applied to separate the spectral components. + + References + ---------- + Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum of + Neurophysiological Signal. Brain Topography, 29(1), 13–26. https://doi.org/10.1007/s10548-015-0448-0 + """ + + # set parameters + if win_func_kwargs is None: + win_func_kwargs = {} + + # Minimal safety checks + if data.ndim == 1: + data = data[np.newaxis, :] + assert data.ndim == 2, 'Data shape needs to be either of shape (Channels, Samples) or (Samples, ).' # noqa PLR2004 + + irasa_params = { + 'data': data, + 'fs': fs, + 'band': band, + 'filter_settings': filter_settings, + } + + _check_irasa_settings(irasa_params=irasa_params, hset_info=hset_info) + + hset = np.round(np.arange(*hset_info), hset_accuracy) + hset = [h for h in hset if h % 1 != 0] # filter integers + + win_kwargs = {'win_func': win_func, 'win_func_kwargs': win_func_kwargs} + dpss_settings = { + 'time_bandwidth': dpss_settings_time_bandwidth, + 'low_bias': dpss_settings_low_bias, + 'eigenvalue_weighting': dpss_eigenvalue_weighting, + } + + nfft = int(2 ** np.ceil(np.log2(np.max(hset) * win_duration * fs))) + hop = int((1 - overlap_fraction) * win_duration * fs) + # hop = int((1 - overlap_fraction) * nfft) + irasa_kwargs: IrasaSprintKwargsTyped = { + 'nfft': nfft, + 'hop': hop, + 'win_duration': win_duration, + 'dpss_settings': dpss_settings, + 'win_kwargs': win_kwargs, + } + + def _local_irasa_fun( + data: np.ndarray, + fs: int, + h: float, + up_down: str | None, + time_orig: np.ndarray | None = None, + ) -> np.ndarray: + return _compute_sgramm(data, fs, h=h, up_down=up_down, time_orig=time_orig, **irasa_kwargs)[2] + + # get time and frequency info + freq, time, sgramm = _compute_sgramm(data, fs, **irasa_kwargs) + + sgramm, sgramm_aperiodic, sgramm_periodic = _gen_irasa( + data=data, + orig_spectrum=sgramm, + fs=fs, + irasa_fun=_local_irasa_fun, + hset=hset, + time=time, + ) + single_ch_dim = 2 + sgramm_aperiodic = ( + sgramm_aperiodic[np.newaxis, :, :] if sgramm_aperiodic.ndim == single_ch_dim else sgramm_aperiodic + ) + sgramm_periodic = sgramm_periodic[np.newaxis, :, :] if sgramm_periodic.ndim == single_ch_dim else sgramm_periodic + + freq, sgramm_aperiodic, sgramm_periodic, sgramm = _crop_data( + band, freq, sgramm_aperiodic, sgramm_periodic, sgramm, axis=1 + ) + + # adjust time info (i.e. cut the padded stuff) + tmax = data.shape[1] / fs + t_mask = np.logical_and(time >= 0, time < tmax) + freq_mask = freq > (1 / win_duration) # mask rayleigh + + return IrasaTfSpectrum( + freqs=freq[freq_mask], + time=time[t_mask], + raw_spectrum=sgramm, + periodic=sgramm_periodic[:, :, t_mask][:, freq_mask, :], + aperiodic=sgramm_aperiodic[:, :, t_mask][:, freq_mask, :], + ch_names=ch_names, + )
+ +
+ +
+ + + + + +
+ +
+
+
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_modules/pyrasa/irasa_mne/irasa_mne.html b/_modules/pyrasa/irasa_mne/irasa_mne.html new file mode 100644 index 0000000..0ef8397 --- /dev/null +++ b/_modules/pyrasa/irasa_mne/irasa_mne.html @@ -0,0 +1,647 @@ + + + + + + + + + + pyrasa.irasa_mne.irasa_mne — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + + + +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for pyrasa.irasa_mne.irasa_mne

+"""Interface to use the IRASA algorithm with MNE objects."""
+
+import mne
+import numpy as np
+
+from pyrasa.irasa import irasa
+from pyrasa.irasa_mne.mne_objs import (
+    AperiodicEpochsSpectrum,
+    AperiodicSpectrumArray,
+    IrasaEpoched,
+    IrasaRaw,
+    PeriodicEpochsSpectrum,
+    PeriodicSpectrumArray,
+)
+
+
+
+[docs] +def irasa_raw( + data: mne.io.Raw, + band: tuple[float, float] = (1.0, 100.0), + duration: float | None = None, + overlap: float | int = 50, + hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05), +) -> IrasaRaw: + """ + Separate aperiodic from periodic power spectra using the IRASA algorithm. + + This function applies the Irregular Resampling Auto-Spectral Analysis (IRASA) algorithm + as described by Wen & Liu (2016) to decompose the power spectrum of neurophysiological + signals into aperiodic (fractal) and periodic (oscillatory) components. This function is + essentially a wrapper function for `pyrasa.irasa` + + Parameters + ---------- + data : mne.io.Raw + The time-series data from which the aperiodic and periodic power spectra are extracted. + This should be an instance of `mne.io.Raw`. The function will automatically extract + relevant parameters such as sampling frequency (`sfreq`) and filtering settings from the `mne` object + to make sure the model is specified correctly. + band : tuple of (float, float), optional, default: (1.0, 100.0) + A tuple specifying the lower and upper bounds of the frequency range (in Hz) used + for extracting the aperiodic and periodic spectra. + duration : float, required + The duration (in seconds) of each segment used to calculate the power spectral density (PSD). + This must be less than the total duration of the data. + overlap : float or int, optional, default: 50 + The overlap between segments, specified as a percentage (0-100). + hset_info : tuple of (float, float, float), optional, default: (1.05, 2.0, 0.05) + Contains the range of up/downsampling factors used in the IRASA algorithm. + This should be a tuple specifying the (min, max, step) values for the resampling. + + Returns + ------- + IrasaRaw + A custom object containing the separated aperiodic and periodic components of the data: + - `periodic`: An instance of `PeriodicSpectrumArray`, which includes the periodic + (oscillatory) component of the power spectrum. + - `aperiodic`: An instance of `AperiodicSpectrumArray`, which includes the aperiodic + (fractal) component of the power spectrum. + + References + ---------- + Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum + of Neurophysiological Signal. Brain Topography, 29(1), 13–26. + https://doi.org/10.1007/s10548-015-0448-0 + + Notes + ----- + - Ensure that `data` does not contain any bad channels (`data.info['bads']` should be empty), + as this could affect the results. + - The overlap percentage should be carefully chosen to balance between segment independence + and sufficient data for analysis. A value between 0 and 100% is valid. + - The function will raise assertions if the input parameters are not consistent with the + expected formats or if the provided `duration` exceeds the length of the data. + + """ + + # set parameters & safety checks + # ensure that input data is in the right format + assert isinstance(data, mne.io.BaseRaw), 'Data should be of type mne.BaseRaw' + assert data.info['bads'] == [], ( + 'Data should not contain bad channels ' 'as this might mess up the creation of the returned data structure' + ) + + # extract relevant info from mne object + info = data.info.copy() + fs = data.info['sfreq'] + data_array = data.get_data() + + overlap /= 100 + assert isinstance(duration, int | float), 'You need to set the duration of your time window in seconds' + assert data_array.shape[1] > int(fs * duration), 'The duration for each segment cant be longer than the actual data' + assert np.logical_and( + overlap < 1, overlap > 0 + ), 'The overlap between segments cant be larger than 100% or less than 0%' + + nfft = 2 ** (np.ceil(np.log2(int(fs * duration * np.max(hset_info))))) + kwargs_psd = { + 'window': 'hann', + 'average': 'median', + 'nfft': nfft, + 'nperseg': int(fs * duration), + 'noverlap': int(fs * duration * overlap), + } + + irasa_spectrum = irasa( + data_array, + fs=fs, + band=band, + filter_settings=(data.info['highpass'], data.info['lowpass']), + hset_info=hset_info, + psd_kwargs=kwargs_psd, + ) + + return IrasaRaw( + periodic=PeriodicSpectrumArray(irasa_spectrum.periodic, info, freqs=irasa_spectrum.freqs), + aperiodic=AperiodicSpectrumArray(irasa_spectrum.aperiodic, info, freqs=irasa_spectrum.freqs), + )
+ + + +
+[docs] +def irasa_epochs( + data: mne.Epochs, + band: tuple[float, float] = (1.0, 100.0), + hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05), +) -> IrasaEpoched: + """ + Separate aperiodic from periodic power spectra using the IRASA algorithm for Epochs data. + + This function applies the Irregular Resampling Auto-Spectral Analysis (IRASA) algorithm + as described by Wen & Liu (2016) to decompose the power spectrum of neurophysiological + signals into aperiodic (fractal) and periodic (oscillatory) components. It is specifically + designed for time-series data in `mne.Epochs` format, making it suitable for event-related + EEG/MEG analyses. + + Parameters + ---------- + data : mne.Epochs + The time-series data used to extract aperiodic and periodic power spectra. + This should be an instance of `mne.Epochs`. + band : tuple of (float, float), optional, default: (1.0, 100.0) + A tuple specifying the lower and upper bounds of the frequency range (in Hz) used + for extracting the aperiodic and periodic spectra. + hset_info : tuple of (float, float, float), optional, default: (1.05, 2.0, 0.05) + Contains the range of up/downsampling factors used in the IRASA algorithm. + This should be a tuple specifying the (min, max, step) values for the resampling. + + Returns + ------- + aperiodic : AperiodicEpochsSpectrum + The aperiodic component of the data as an `AperiodicEpochsSpectrum` object. + periodic : PeriodicEpochsSpectrum + The periodic component of the data as a `PeriodicEpochsSpectrum` object. + + References + ---------- + Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum + of Neurophysiological Signal. Brain Topography, 29(1), 13–26. + https://doi.org/10.1007/s10548-015-0448-0 + + """ + + # set parameters & safety checks + # ensure that input data is in the right format + assert isinstance(data, mne.BaseEpochs), 'Data should be of type mne.BaseEpochs' + assert ( + data.info['bads'] == [] + ), 'Data should not contain bad channels as this might mess up the creation of the returned data structure' + + info = data.info.copy() + fs = data.info['sfreq'] + events = data.events + event_ids = data.event_id + + data_array = data.get_data(copy=True) + + # TODO: check if hset.max() is really max + nfft = 2 ** (np.ceil(np.log2(int(data_array.shape[2] * np.max(hset_info))))) + + # TODO: does zero padding make sense? + kwargs_psd = { + 'window': 'hann', + 'nperseg': None, + 'nfft': nfft, + 'noverlap': 0, + } + + # Do the actual IRASA stuff.. + psd_list_aperiodic, psd_list_periodic = [], [] + for epoch in data_array: + irasa_spectrum = irasa( + epoch, + fs=fs, + band=band, + filter_settings=(data.info['highpass'], data.info['lowpass']), + hset_info=hset_info, + psd_kwargs=kwargs_psd, + ) + psd_list_aperiodic.append(irasa_spectrum.aperiodic.copy()) + psd_list_periodic.append(irasa_spectrum.periodic.copy()) + + psds_aperiodic = np.array(psd_list_aperiodic) + psds_periodic = np.array(psd_list_periodic) + + return IrasaEpoched( + periodic=PeriodicEpochsSpectrum( + psds_periodic, info, freqs=irasa_spectrum.freqs, events=events, event_id=event_ids + ), + aperiodic=AperiodicEpochsSpectrum( + psds_aperiodic, info, freqs=irasa_spectrum.freqs, events=events, event_id=event_ids + ), + )
+ +
+ +
+ + + + + +
+ +
+
+
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_modules/pyrasa/utils/aperiodic_utils.html b/_modules/pyrasa/utils/aperiodic_utils.html new file mode 100644 index 0000000..b00265a --- /dev/null +++ b/_modules/pyrasa/utils/aperiodic_utils.html @@ -0,0 +1,681 @@ + + + + + + + + + + pyrasa.utils.aperiodic_utils — PyRASA dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+
+
+
+ +
+ +
+ + + + + +
+
+ + + + + +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for pyrasa.utils.aperiodic_utils

+"""Utilities for slope fitting."""
+
+import warnings
+from collections.abc import Iterable
+
+import numpy as np
+import pandas as pd
+
+from pyrasa.utils.fit_funcs import AbstractFitFun, FixedFitFun, KneeFitFun
+from pyrasa.utils.types import AperiodicFit
+
+
+def _compute_aperiodic_model(
+    aperiodic_spectrum: np.ndarray,
+    freq: np.ndarray,
+    fit_func: str | type[AbstractFitFun],
+    scale_factor: float | int = 1,
+) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
+    """helper function to model the aperiodic spectrum"""
+
+    if isinstance(fit_func, str):
+        if fit_func == 'fixed':
+            fit_func = FixedFitFun
+        elif fit_func == 'knee':
+            fit_func = KneeFitFun
+        else:
+            raise ValueError('fit_func should be either a string ("fixed", "knee") or of type AbastractFitFun')
+
+    fit_f = fit_func(freq, aperiodic_spectrum, scale_factor=scale_factor)
+    params, gof, pred = fit_f.fit_func()
+
+    return params, gof, pred
+
+
+
+[docs] +def compute_aperiodic_model( + aperiodic_spectrum: np.ndarray, + freqs: np.ndarray, + fit_func: str | type[AbstractFitFun] = 'fixed', + ch_names: Iterable | None = None, + scale: bool = False, + fit_bounds: tuple[float, float] | None = None, +) -> AperiodicFit: + """ + Computes aperiodic parameters from the aperiodic spectrum using scipy's curve fitting function. + + This function can be used to model the aperiodic (1/f-like) component of the power spectrum. Per default, users can + choose between a fixed or knee model fit or specify their own fit method see examples custom_fit_functions.ipynb + for an example. The function returns the fitted parameters for each channel along with some + goodness of fit metrics. + + Parameters + ---------- + aperiodic_spectrum : np.ndarray + A 1 or 2D array of power values for the aperiodic spectrum where the shape is + expected to be either (Samples,) or (Channels, Samples). + freqs : np.ndarray + A 1D array of frequency values corresponding to the aperiodic spectrum. + fit_func : str or type[AbstractFitFun], optional + The fitting function to use. Can be "fixed" for a linear fit or "knee" for a fit that includes a + knee (bend) in the spectrum or a class that is inherited from AbstractFitFun. The default is 'fixed'. + ch_names : Iterable or None, optional + Channel names corresponding to the aperiodic spectrum. If None, channels will be named numerically + in ascending order. Default is None. + scale : bool, optional + Whether to scale the data to improve fitting accuracy. This is useful in cases where + power values are very small (e.g., 1e-28), which may lead to numerical precision issues during fitting. + After fitting, the parameters are rescaled to match the original data scale. Default is False. + fit_bounds : tuple[float, float] or None, optional + Tuple specifying the lower and upper frequency bounds for the fit function. If None, the entire frequency + range is used. Otherwise, the spectrum is cropped to the specified bounds. Default is None. + + Returns + ------- + AperiodicFit + An object containing three pandas DataFrames: + - aperiodic_params : pd.DataFrame + A DataFrame containing the fitted aperiodic parameters for each channel. + - gof : pd.DataFrame + A DataFrame containing the goodness of fit metrics for each channel. + - model : pd.DataFrame + A DataFrame containing the predicted aperiodic model for each channel. + + Notes + ----- + This function fits the aperiodic component of the power spectrum using scipy's curve fitting function. + The fitting can be performed using either a simple linear model ('fixed') or a more complex model + that includes a "knee" point, where the spectrum bends. The resulting parameters can help in + understanding the underlying characteristics of the aperiodic component in the data. + + If the `fit_bounds` parameter is used, it ensures that only the specified frequency range is considered + for fitting, which can be important to avoid fitting artifacts outside the region of interest. + + The `scale` parameter can be crucial when dealing with data that have extremely small values, + as it helps to mitigate issues related to machine precision during the fitting process. + + The function asserts that the input data are of the correct type and shape, and raises warnings + if the first frequency value is zero, as this can cause issues during model fitting. + """ + + assert isinstance(aperiodic_spectrum, np.ndarray), 'aperiodic_spectrum should be a numpy array.' + if aperiodic_spectrum.ndim == 1: + aperiodic_spectrum = aperiodic_spectrum[np.newaxis, :] + assert aperiodic_spectrum.ndim == 2, 'Data shape needs to be either of shape (Channels, Samples) or (Samples, ).' # noqa PLR2004 + + assert isinstance(freqs, np.ndarray), 'freqs should be a numpy array.' + assert freqs.ndim == 1, 'freqs needs to be of shape (freqs,).' + + assert isinstance( + ch_names, list | tuple | np.ndarray | None + ), 'Channel names should be of type list, tuple or numpy.ndarray or None' + + if fit_bounds is not None: + fmin, fmax = freqs.min(), freqs.max() + assert fit_bounds[0] > fmin, f'The selected lower bound is lower than the lowest frequency of {fmin}Hz' + assert fit_bounds[1] < fmax, f'The selected upper bound is higher than the highest frequency of {fmax}Hz' + freq_logical = np.logical_and(freqs >= fit_bounds[0], freqs <= fit_bounds[1]) + aperiodic_spectrum, freqs = aperiodic_spectrum[:, freq_logical], freqs[freq_logical] + + if freqs[0] == 0: + warnings.warn( + 'The first frequency appears to be 0 this will result in aperiodic model fitting problems. ' + + 'Frequencies will be evaluated starting from the next highest in Hz' + ) + freqs = freqs[1:] + aperiodic_spectrum = aperiodic_spectrum[:, 1:] + + # generate channel names if not given + if ch_names is None: + ch_names = [str(i) for i in np.arange(aperiodic_spectrum.shape[0])] + + if scale: + + def num_zeros(decimal: int) -> float: + return np.inf if decimal == 0 else -np.floor(np.log10(abs(decimal))) - 1 + + scale_factor = 10 ** num_zeros(aperiodic_spectrum.min()) + aperiodic_spectrum = aperiodic_spectrum * scale_factor + else: + scale_factor = 1 + + ap_list, gof_list, pred_list = [], [], [] + for ix, ch_name in enumerate(ch_names): + params, gof, pred = _compute_aperiodic_model( + aperiodic_spectrum=aperiodic_spectrum[ix], + freq=freqs, + fit_func=fit_func, + scale_factor=scale_factor, + ) + + params['ch_name'] = ch_name + gof['ch_name'] = ch_name + pred['ch_name'] = ch_name + + ap_list.append(params) + gof_list.append(gof) + pred_list.append(pred) + + # combine & return + return AperiodicFit(aperiodic_params=pd.concat(ap_list), gof=pd.concat(gof_list), model=pd.concat(pred_list))
+ + + +def compute_aperiodic_model_sprint( + aperiodic_spectrum: np.ndarray, + freqs: np.ndarray, + times: np.ndarray, + fit_func: str | type[AbstractFitFun] = 'fixed', + scale: bool = False, + ch_names: Iterable | None = None, + fit_bounds: tuple[float, float] | None = None, +) -> AperiodicFit: + """ + Extracts aperiodic parameters from the aperiodic spectrogram using scipy's curve fitting + function. + + This function computes aperiodic parameters for each time point in the spectrogram by applying either one of + two different curve fitting functions (`fixed` or `knee`) or a custom function specified by user to the data. + See examples custom_fit_functions.ipynb. The parameters, along with the goodness of + fit for each time point, are returned in a concatenated format. + + Parameters + ---------- + aperiodic_spectrum : np.ndarray + A 2 or 3D array of power values from the aperiodic spectrogram, with shape (Frequencies, Time) + or (Channels, Frequencies, Time). + freqs : np.ndarray + A 1D array of frequency values corresponding to the aperiodic spectrogram. + times : np.ndarray + A 1D array of time values corresponding to the aperiodic spectrogram. + fit_func : str or type[AbstractFitFun], optional + The fitting function to use. Can be "fixed" for a linear fit or "knee" for a fit that includes a + knee (bend) in the spectrum or a class that is inherited from AbstractFitFun. The default is 'fixed'.. + ch_names : Iterable or None, optional + Channel names corresponding to the aperiodic spectrogram. If None, channels will be named numerically + in ascending order. Default is None. + scale : bool, optional + Whether to scale the data to improve fitting accuracy. This is useful when fitting a knee in cases where + power values are very small, leading to numerical precision issues. Default is False. + fit_bounds : tuple[float, float] or None, optional + Tuple specifying the lower and upper frequency bounds for the fit function. If None, the entire frequency + range is used. Otherwise, the spectrum is cropped to the specified bounds before fitting. Default is None. + + Returns + ------- + AperiodicFit + An object containing three pandas DataFrames: + - aperiodic_params : pd.DataFrame + A DataFrame containing the aperiodic parameters (e.g., Offset and Exponent) + for each channel and each time point. + - gof : pd.DataFrame + A DataFrame containing the goodness of fit metrics for each channel and each time point. + - model : pd.DataFrame + A DataFrame containing the predicted aperiodic model for each channel and each time point. + + Notes + ----- + This function iterates over each time point in the provided spectrogram to extract aperiodic parameters + using the specified fit function. It leverages the `compute_aperiodic_model` function for individual fits + at each time point, then combines the results across all time points into comprehensive DataFrames. + + The `fit_bounds` parameter allows for frequency range restrictions during fitting, which can help in focusing + the analysis on a particular frequency band of interest. + + Scaling the data using the `scale` parameter can be particularly important when dealing with very small power + values that might lead to poor fitting due to numerical precision limitations. + + """ + + ap_t_list, gof_t_list, pred_t_list = [], [], [] + + for ix, t in enumerate(times): + aperiodic_fit = compute_aperiodic_model( + aperiodic_spectrum[:, :, ix], + freqs=freqs, + fit_func=fit_func, + ch_names=ch_names, + fit_bounds=fit_bounds, + scale=scale, + ) + aperiodic_fit.aperiodic_params['time'] = t + aperiodic_fit.gof['time'] = t + aperiodic_fit.model['time'] = t + + ap_t_list.append(aperiodic_fit.aperiodic_params) + gof_t_list.append(aperiodic_fit.gof) + pred_t_list.append(aperiodic_fit.model) + + return AperiodicFit(aperiodic_params=pd.concat(ap_t_list), gof=pd.concat(gof_t_list), model=pd.concat(pred_t_list)) +
+ +
+ + + + + +
+ +
+
+
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/_sources/api.rst.txt b/_sources/api.rst.txt deleted file mode 100644 index acd0e35..0000000 --- a/_sources/api.rst.txt +++ /dev/null @@ -1,15 +0,0 @@ -API Documentation -================= - -pyrasa ------- - -.. automodule:: pyrasa - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - :exclude-members: __weakref__ - :private-members: - :special-members: - :noindex: \ No newline at end of file diff --git a/_sources/auto_examples/sg_execution_times.rst.txt b/_sources/auto_examples/sg_execution_times.rst.txt deleted file mode 100644 index ccb2da1..0000000 --- a/_sources/auto_examples/sg_execution_times.rst.txt +++ /dev/null @@ -1,37 +0,0 @@ - -:orphan: - -.. _sphx_glr_auto_examples_sg_execution_times: - - -Computation times -================= -**00:00.000** total execution time for 0 files **from auto_examples**: - -.. container:: - - .. raw:: html - - - - - - - - .. list-table:: - :header-rows: 1 - :class: table table-striped sg-datatable - - * - Example - - Time - - Mem (MB) - * - N/A - - N/A - - N/A diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt deleted file mode 100644 index fb8f103..0000000 --- a/_sources/index.rst.txt +++ /dev/null @@ -1,18 +0,0 @@ -.. PyRASA documentation master file, created by - sphinx-quickstart on Fri Sep 20 14:42:34 2024. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -PyRASA documentation -==================== - -Add your content using ``reStructuredText`` syntax. See the -`reStructuredText `_ -documentation for details. - - -.. toctree:: - :hidden: - - API - diff --git a/_sources/sg_execution_times.rst.txt b/_sources/sg_execution_times.rst.txt deleted file mode 100644 index 78433a9..0000000 --- a/_sources/sg_execution_times.rst.txt +++ /dev/null @@ -1,37 +0,0 @@ - -:orphan: - -.. _sphx_glr_sg_execution_times: - - -Computation times -================= -**00:00.000** total execution time for 0 files **from all galleries**: - -.. container:: - - .. raw:: html - - - - - - - - .. list-table:: - :header-rows: 1 - :class: table table-striped sg-datatable - - * - Example - - Time - - Mem (MB) - * - N/A - - N/A - - N/A diff --git a/_static/documentation_options.js b/_static/documentation_options.js index cefb30d..39953c4 100644 --- a/_static/documentation_options.js +++ b/_static/documentation_options.js @@ -1,11 +1,11 @@ const DOCUMENTATION_OPTIONS = { - VERSION: '0.1.0.dev0', + VERSION: 'dev', LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', FILE_SUFFIX: '.html', LINK_SUFFIX: '.html', - HAS_SOURCE: true, + HAS_SOURCE: false, SOURCELINK_SUFFIX: '.txt', NAVIGATION_WITH_KEYS: false, SHOW_SEARCH_SUMMARY: true, diff --git a/_static/style.css b/_static/style.css new file mode 100644 index 0000000..9bfeee2 --- /dev/null +++ b/_static/style.css @@ -0,0 +1,33 @@ +a[class^="sphx-glr-backref-module-mne_bids"] { + /* make all MNE-BIDS backrefs bold */ + font-weight: 800; + } + + span.option { + /* avoid breaking lines in our command-line parameters */ + white-space: nowrap; + } + + /* ************************************************* Previous / Next buttons */ + .prev-next-bottom a.left-prev:before { + content:"❮\00A0" + } + .prev-next-bottom a.right-next:after { + content:"\00A0❯" + } + .prev-next-bottom a.right-next { + text-align: right; + } + + /* ************************************************* truncate version string */ + div.navbar-item:first-child { + overflow-x: hidden; + } + a.navbar-brand.logo { + flex-shrink: 1; + overflow-x: hidden; + } + p.logo__title { + overflow-x: hidden; + text-overflow: ellipsis; + } \ No newline at end of file diff --git a/api.html b/api.html index 65f8056..a5e67d4 100644 --- a/api.html +++ b/api.html @@ -2,19 +2,19 @@ - + - API Documentation — PyRASA 0.1.0 + API Reference — PyRASA dev documentation @@ -39,19 +39,24 @@ - + - + + + + + + - + @@ -121,7 +126,7 @@ -

PyRASA 0.1.0

+

PyRASA dev documentation

@@ -135,6 +140,13 @@ @@ -378,7 +360,7 @@ - + @@ -395,188 +377,52 @@
-
-

API Documentation#

-
-

pyrasa#

-

IRASA Core Functions.

-
-
-pyrasa.irasa(data: ~numpy.ndarray, fs: int, band: tuple[float, float], psd_kwargs: dict, ch_names: ~numpy.ndarray | None = None, win_func: ~collections.abc.Callable = <function hann>, win_func_kwargs: dict | None = None, dpss_settings_time_bandwidth: float = 2.0, dpss_settings_low_bias: bool = True, dpss_eigenvalue_weighting: bool = True, filter_settings: tuple[float | None, float | None] = (None, None), hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05), hset_accuracy: int = 4) IrasaSpectrum
-

Computes the aperiodic and periodic components of the power spectrum from a time series using the -Irregular Resampling Autocorrelation (IRASA) algorithm.

-

The IRASA algorithm allows for the decomposition of neural signals into fractal (aperiodic) and -oscillatory (periodic) components, providing insight into the underlying dynamics of the data.

-
-
Parameters:
-
-
datanp.ndarray

Time series data, where the shape is expected to be either (Samples,) or (Channels, Samples).

-
-
fsint

Sampling frequency of the data in Hz.

-
-
bandtuple[float, float]

The frequency range (lower and upper bounds in Hz) over which to compute the spectra.

-
-
psd_kwargsdict

Keyword arguments to be passed to the scipy.signal.welch function for PSD estimation.

-
-
ch_namesnp.ndarray | None, optional

Channel names associated with the data, if available. Default is None.

-
-
win_funcCallable, optional

Window function to be used in Welch’s method. Default is dsp.windows.hann.

-
-
win_func_kwargsdict | None, optional

Additional keyword arguments for the window function. Default is None.

-
-
dpss_settings_time_bandwidthfloat, optional

Time-bandwidth product for the DPSS windows if used. Default is 2.0.

-
-
dpss_settings_low_biasbool, optional

Keep only tapers with eigenvalues > 0.9. Default is True.

-
-
dpss_eigenvalue_weightingbool, optional

Whether or not to apply eigenvalue weighting in DPSS. If True, spectral estimates weighted by -the concentration ratio of their respective tapers before combining. Default is True.

-
-
filter_settingstuple[float | None, float | None], optional

Cutoff frequencies for highpass and lowpass filtering to avoid artifacts in the evaluated frequency range. -Default is (None, None).

-
-
hset_infotuple[float, float, float], optional

Tuple specifying the range of the resampling factors as (min, max, step). Default is (1.05, 2.0, 0.05).

-
-
hset_accuracyint, optional

Decimal precision for the resampling factors. Default is 4.

-
-
-
-
Returns:
-
-
IrasaSpectrum
-
An object containing the following attributes:
    -
  • -
    freqs: np.ndarray

    Frequencies corresponding to the computed spectra.

    -
    -
    -
  • -
  • -
    raw_spectrum: np.ndarray

    The raw power spectrum.

    -
    -
    -
  • -
  • -
    aperiodic: np.ndarray

    The aperiodic (fractal) component of the spectrum.

    -
    -
    -
  • -
  • -
    periodic: np.ndarray

    The periodic (oscillatory) component of the spectrum.

    -
    -
    -
  • -
  • -
    ch_names: np.ndarray

    Channel names if provided.

    -
    -
    -
  • -
-
-
-
-
-
-
-

Notes

-

This function provides fine-grained control over the IRASA parameters. For users working with MNE-Python, -the irasa_raw and irasa_epochs functions from pyrasa.irasa_mne are recommended, as they handle -additional preprocessing steps.

-

References

-

Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum -of Neurophysiological Signal. Brain Topography, 29(1), 13–26. https://doi.org/10.1007/s10548-015-0448-0

-
- -
-
-pyrasa.irasa_sprint(data: ~numpy.ndarray, fs: int, ch_names: ~numpy.ndarray | None = None, band: tuple[float, float] = (1.0, 100.0), win_duration: float = 0.4, overlap_fraction: float = 0.9, win_func: ~collections.abc.Callable = <function hann>, win_func_kwargs: dict | None = None, dpss_settings_time_bandwidth: float = 2.0, dpss_settings_low_bias: bool = True, dpss_eigenvalue_weighting: bool = True, filter_settings: tuple[float | None, float | None] = (None, None), hset_info: tuple[float, float, float] = (1.05, 2.0, 0.05), hset_accuracy: int = 4) IrasaTfSpectrum
-

Computes time-resolved aperiodic and periodic components of the power spectrum from a time series -using the Irregular Resampling Autocorrelation (IRASA) algorithm.

-

This function is useful for analyzing how the aperiodic and periodic components of the power spectrum -change over time, providing a time-frequency decomposition of the signal.

-
-
Parameters:
-
-
datanp.ndarray

Time series data, where the shape is expected to be either (Samples,) or (Channels, Samples).

-
-
fsint

Sampling frequency of the data in Hz.

-
-
ch_namesnp.ndarray | None, optional

Channel names associated with the data, if available. Default is None.

-
-
bandtuple[float, float], optional

The frequency range (lower and upper bounds in Hz) over which to compute the spectra. Default is (1.0, 100.0).

-
-
win_durationfloat, optional

Duration of the window in seconds used for the short-time Fourier transforms (STFTs). Default is 0.4 seconds.

-
-
overlap_fractionint, optional

The overlap between the STFT sliding windows as fraction. Default is .99 of the windows.

-
-
win_funcCallable, optional

Window function to be used in computing the time frequency spectrum. Default is dsp.windows.hann.

-
-
win_func_kwargsdict | None, optional

Additional keyword arguments for the window function. Default is None.

-
-
dpss_settings_time_bandwidthfloat, optional

Time-bandwidth product for the DPSS windows if used. Default is 2.0.

-
-
dpss_settings_low_biasbool, optional

Keep only tapers with eigenvalues > 0.9. Default is True.

-
-
dpss_eigenvalue_weightingbool, optional

Whether or not to apply eigenvalue weighting in DPSS. If True, spectral estimates weighted by -the concentration ratio of their respective tapers before combining. Default is True.

-
-
filter_settingstuple[float | None, float | None], optional

Cutoff frequencies for highpass and lowpass filtering to avoid artifacts in the evaluated frequency range. -Default is (None, None).

-
-
hset_infotuple[float, float, float], optional

Tuple specifying the range of the resampling factors as (min, max, step). Default is (1.05, 2.0, 0.05).

-
-
hset_accuracyint, optional

Decimal precision for the resampling factors. Default is 4.

-
-
-
-
Returns:
-
-
IrasaTfSpectrum
-
An object containing the following attributes:
    -
  • -
    freqs: np.ndarray

    Frequencies corresponding to the computed spectra.

    -
    -
    -
  • -
  • -
    time: np.ndarray

    Time bins in seconds associated with the (a-)periodic spectra.

    -
    -
    -
  • -
  • -
    raw_spectrum: np.ndarray

    The raw time-frequency power spectrum.

    -
    -
    -
  • -
  • -
    aperiodic: np.ndarray

    The aperiodic (fractal) component of the spectrum.

    -
    -
    -
  • -
  • -
    periodic: np.ndarray

    The periodic (oscillatory) component of the spectrum.

    -
    -
    -
  • -
  • -
    ch_names: np.ndarray

    Channel names if provided.

    -
    -
    -
  • -
-
-
-
-
-
-
-

Notes

-

This function performs a time-frequency decomposition of the input data, allowing for a time-resolved analysis -of the periodic and aperiodic components of the signal. The STFT is computed for each time window, and IRASA -is applied to separate the spectral components.

-

References

-

Wen, H., & Liu, Z. (2016). Separating Fractal and Oscillatory Components in the Power Spectrum of -Neurophysiological Signal. Brain Topography, 29(1), 13–26. https://doi.org/10.1007/s10548-015-0448-0

-
- +
+

API Reference#

+
+

irasa#

+

pyrasa.irasa

+

Functions to compute IRASA.

+
+ + + + + + + + +

irasa(data, fs, band, psd_kwargs[, ...])

Computes the aperiodic and periodic components of the power spectrum from a time series using the Irregular Resampling Autocorrelation (IRASA) algorithm.

irasa_sprint(data, fs[, ch_names, band, ...])

Computes time-resolved aperiodic and periodic components of the power spectrum from a time series using the Irregular Resampling Autocorrelation (IRASA) algorithm.

+
+
+
+

irasa_mne#

+

pyrasa.irasa_mne

+

Interface to use the IRASA algorithm with MNE objects.

+
+ + + + + + + + +

irasa_raw(data[, band, duration, overlap, ...])

Separate aperiodic from periodic power spectra using the IRASA algorithm.

irasa_epochs(data[, band, hset_info])

Separate aperiodic from periodic power spectra using the IRASA algorithm for Epochs data.

+
+
+
+

aperiodic_utils#

+

pyrasa.utils.aperiodic_utils

+

Utilities for slope fitting.

+
+ + + + + +

compute_aperiodic_model(aperiodic_spectrum, ...)

Computes aperiodic parameters from the aperiodic spectrum using scipy's curve fitting function.

+
@@ -591,14 +437,23 @@

pyrasa#

previous

-

PyRASA documentation

+

<no title>

+ +
+

next

+

pyrasa.irasa.irasa

+
+ +
@@ -617,19 +472,12 @@

pyrasa# - - @@ -686,4 +534,4 @@

pyrasa# - + \ No newline at end of file diff --git a/auto_examples/sg_execution_times.html b/auto_examples/sg_execution_times.html index 9c78607..d38ce54 100644 --- a/auto_examples/sg_execution_times.html +++ b/auto_examples/sg_execution_times.html @@ -2,19 +2,19 @@ - + - Computation times — PyRASA 0.1.0 + Computation times — PyRASA dev documentation @@ -39,18 +39,22 @@ - + + + + + - + @@ -120,7 +124,7 @@ -

PyRASA 0.1.0

+

PyRASA dev documentation

@@ -134,6 +138,13 @@

@@ -413,4 +478,4 @@

Index

- + \ No newline at end of file diff --git a/index.html b/index.html index 114b45e..ec4a8b7 100644 --- a/index.html +++ b/index.html @@ -2,19 +2,19 @@ - + - PyRASA — PyRASA 0.1.0.dev0 + PyRASA - Spectral parameterization in python based on IRASA — PyRASA dev documentation @@ -39,18 +39,23 @@ - + + - + + + + + - + @@ -120,7 +125,7 @@ -

PyRASA 0.1.0

+

PyRASA dev documentation

@@ -134,6 +139,13 @@