Estimating the 1/f aperiodic component for DICS Source Space Power

Hello everyone,

I am working on estimating the 1/f (aperiodic) component of my power spectrum for source space power mapping with Dynamic Imaging of Coherent Sources (DICS).

DICS implementation as in:
MNE DICS Tutorial
FLUX MNE DICS TUTORIAL

I am facing the issue that the fooof algorithm does not currently support complex values.

        # Check if power values are complex
        if np.iscomplexobj(power_spectrum):
            raise DataError("Input power spectra are complex values. "
                            "FOOOF does not currently support complex inputs.")

Has anyone tried this before?
When and how would you implement the fooofing in the pipeline?
My first intuition would be to estimate the aperiodic and periodic components before creating and applying the DICS filters. However, this would require the complex power spectrum to be converted to real values, which complicates/hampers the later DICS power mapping…
Alternatively, one could estimate the power per frequency via DICS and do the fooofing at the very end. This could be very time- and computation-consuming… Any suggestions?

If you need more information about the code or some sample data, just let me know :wink:

Thanks for your support!
Cheers,
Katharina

#########################

  • MNE version: e.g. 1.3.0
  • fooof version: 1.0.0
  • operating system: Ubuntu 20.04

#########################

Example Code:

import numpy as np
from fooof import FOOOF
from joblib import Parallel, delayed
from tqdm import tqdm


# Fooofing Algorithm
def fooofing_power_single_vertex(vertex, freqs, power):
    fm = FOOOF(peak_width_limits=[2, 6], min_peak_height=0.1, aperiodic_mode='fixed', verbose=True)
    fm.fit(freqs, power[vertex, :])
    r2, error = fm.r_squared_, fm.error_
    offset, slope = fm.aperiodic_params_
    L = 10 ** (offset - slope * np.log10(freqs))
    fooofed_power = power[vertex, :] - L
    fooof_meta = np.array([offset, slope, r2, error])
    return fooofed_power, fooof_meta

def fooofing_power(power, freqs, n_jobs):
    results = Parallel(n_jobs=n_jobs)(
        delayed(fooofing_power_single_vertex)(vertex, freqs, power) for vertex in tqdm(range(power.shape[0])))

    fooofed_power = np.zeros(power.shape)
    fooof_meta = np.zeros((power.shape[0], 4))

    for vertex, (fp, fm) in enumerate(results):
        fooofed_power[vertex, :] = fp
        fooof_meta[vertex, :] = fm

    return fooofed_power, fooof_meta

#####################################################

from mne.time_frequency import csd_morlet
from mne.beamformer import make_dics, apply_dics_csd

cond = 'HW' # High working memory load

csd = csd_morlet(epochs[cond], np.arange(fmin, fmax, 1),
                                             tmin=epochs[cond].tmin,
                                             tmax=epochs[cond].tmax, n_cycles=3)
csd_fooofed = csd.copy()

# Traceback due to complex data 
csd_fooof_cond._data, fooof_meta = fooofing_power(csd._data, csd.frequencies, n_jobs)

# Converting the csd to a real power spectrum (np.abs()) leads unsurprisingly to a RuntimeWarning during make_dics(): 
# data covariance does not appear to be positive semidefinite, results will likely be incorrect

Hi Kathlin,

Estimating the 1/f component of the power spectrum is equivalent to curve-fitting the power spectrum amplitude (the absolute value of the frequency component). The complex values are there to also represent a phase in the frequency decomposition. You will need to thus pass the absolute value of the power spectrum to the fooof algorithm.

Kind regards,
Steven

Hi,

If I understand the question correctly, the problem is how to go about having a DICS estimation separately for the periodic and aperiodic components of the signals instead of the original signals.

I don’t know of any way to go around the fooof limitation that you have mentioned. As you suggested, you probably need to compute the 1/f at the end of the pipeline over a range of frequencies that are of interest to your problem.

Cheers,

Hi Steven,

You are correct that using the absolute values would solve the aperiodic and periodic component estimation. However, later creation of the DICS filter would result in a warning/potential error due to positive semidefinite covariance matrices…
Best,
Katharina

Hi Sotiris,

I so far only applied the DICS to frequency bands (e.g. averaging over the frequencies of interest within each band before creating the filter).
The fooofing at the end would require creating DICS filters and applying them to each frequency within the band of interest… I was hoping for a more efficient way…
But many thanks for your thoughts!
Cheers,
Katharina

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.