[FieldTrip] Single trial time series of spectral data in source space

Schoffelen, J.M. (Jan Mathijs) janmathijs.schoffelen at donders.ru.nl
Fri Mar 22 08:14:55 CET 2024


Hi Johan,

If you want to do a ’superlet’ analysis on time series data that are defined in source space, you need to ensure first and foremost that you input data in to ft_freqanalysis is recognized by FieldTrip as if it is a channel level data structure. Source level data is not supported by ft_freqanalysis. Moreover, it typically does not make sense to compute a TFR-like decomposition on 10,000’s of source points, if the original data consisted only of 300’ish channel points. Therefore, the recommended way forward would be to compute the source-level time series on a parcellated (e.g. cortical sheet).

The way forward would be:

1 compute a spatial filter on a well-defined sourcemodel, using the inverse operator of choice. (and cfg.keepfilter = ‘yes’)
2 create a parcellation (e.g. atlas-based) of the sourcemodel of your liking.
3 use ft_virtualchannel with the original input data, together with the output of step 1 and 2 to create virtual channel time series, where each channel represents a source parcel
4 do the superlet (or whatever other downstream) analysis.

Good luck and happy computing,
Jan-Mathijs


On 15 Mar 2024, at 16:59, Johan Liljefors via fieldtrip <fieldtrip at science.ru.nl<mailto:fieldtrip at science.ru.nl>> wrote:

Dear Fieldtrip users
I am working on calculating trial level time series of spectral power in source space, for a MEG dataset I have collected. I have pre-processed and cleaned my data, which for a single subject is stored in the variable data_meg. I have the following variables:

  *   data_meg: The cleaned and preprocessed dataset for a single subject
  *   Headmodel_mne_meg and sourcemodelT: aligned headmodels, and sourcemodel (which has been calculated using Freesurfer)


If anyone has experience they can share it would be very appreciated. I have made an attempt below, the code runs but I cant tell if the results makes sense or not.

Thank  you for your time,
Regards
Johan

My code is as follows:
% Load the data
[data_meg, headmodel_mne_meg, sourcemodelT] = load_data(wsl_path,par_i,false);

% Compute the forward solution
leadfield_mne = compute_leadfield(data_ meg, sourcemodelT, headmodel_mne_meg);

% Calculate evoked data and apply noise covariance matrix from empty room recording
cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-1 7.5];
cfg.keeptrials = 'no';
data_ind_avg = ft_timelockanalysis(cfg, data_ meg);
data_ind_avg.cov = cov_noise{par_i};                        % cov_noise{par_i} is the subject covariance matrix from the empty room recording

% Calculate the spatial filter using the evoked dataset and the noise covariance
source_avg = source_recon(leadfield_mne, headmodel_mne_meg,  [],data_ind_avg);
filter = source_avg.avg.filter;

% Do trial level source reconstruction using the filter
source_trial = source_recon_trials(leadfield_mne, headmodel_mne_meg, filter, data_meg);

% Calculate trial level spectral power using superlets and save the power spectrum
% This is done by “faking” a fieldtrip structure by putting each single trial into the .avg field and then running ft_freqanalysis
foi = 8:26;
toi = -1:0.01:7.5;
powspctrm = zeros(length(data_meg.trialinfo),...
    size(sourcemodelT.pos,1),...
    length(foi),...
    length(toi));

parfor iTrial = 1:length(data_meg.trialinfo)
        source_single_trial = rmfield(source_trial,"trial");     % These two lines “fake” a single trial which is then processed by ft_freqanalysis
        source_single_trial.avg = source_trial.trial(iTrial);
        cfg = [];
        cfg.method              = 'superlet';
        cfg.output              = 'pow';
        cfg.pad                 = 'nextpow2';
        cfg.foi                 = foi;
        cfg.toi                 = toi;
        % cfg.order goes from 1 to 30 (https://www.biorxiv.org/content/10.1101/583732v4.full.pdf<https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.biorxiv.org%2Fcontent%2F10.1101%2F583732v4.full.pdf&data=05%7C02%7Cfieldtrip%40science.ru.nl%7C07cc8676cf0d4921fb3b08dc4a3fc655%7C084578d9400d4a5aa7c7e76ca47af400%7C1%7C0%7C638466884958109871%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=m56LrdU5GGAQ3ggboqAuLY2f%2FZkeuu2xcTAWJI541so%3D&reserved=0>)
        cfg.order               = floor(linspace(1,30,numel(cfg.foi)));
        cfg.width               = 5;
        cfg.gwidth               = 3;
        TFR_induced = ft_freqanalysis(cfg,source_single_trial);
        powspctrm(iTrial,:,:,:) = TFR_induced.powspctrm;
end

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%           LOCAL FUNCTIONS                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function leadfield_mne = compute_leadfield(data_meg, sourcemodelT, headmodel_mne_meg)
    cfg = [];
    cfg.grad             = data_meg.grad;              % sensor positions
    cfg.channel          = 'meggrad';                  % the used channels
    cfg.senstype         = 'meg';
    cfg.sourcemodel      = sourcemodelT;
    cfg.headmodel        = headmodel_mne_meg;          % volume conduction model
    leadfield_mne        = ft_prepare_leadfield(cfg,data_meg);
end

function source = source_recon(leadfield_mne, headmodel_mne_meg, filter, data)
    cfg                     = [];
    cfg.method              = 'mne';
    cfg.channel             = 'meggrad';
    cfg.senstype            = 'meg';
    cfg.latency             = [-1 7.5];
    cfg.sourcemodel         = leadfield_mne;
    cfg.headmodel           = headmodel_mne_meg;
    cfg.mne.prewhiten       = 'yes';
    cfg.mne.lambda          = 3;
    cfg.mne.scalesourcecov  = 'yes';
    if isempty(filter)
        cfg.mne.keepfilter      = 'yes';
    else
        cfg.sourcemodel.filter = filter;
    end
    source = ft_sourceanalysis(cfg,data);
end

function source_trial = source_recon_trials(leadfield_mne, headmodel_mne_meg, filter, data_meg)
    cfg                     = [];
    cfg.method              = 'mne';
    cfg.channel             = 'meggrad';
    cfg.senstype            = 'meg';
    cfg.latency             = [-1 7.5];
    cfg.sourcemodel         = leadfield_mne;
    cfg.headmodel           = headmodel_mne_meg;
    cfg.mne.prewhiten       = 'yes';
    cfg.mne.lambda          = 3;
    cfg.mne.scalesourcecov  = 'yes';
    if isempty(filter)
        cfg.mne.keepfilter      = 'yes';
    else
        cfg.sourcemodel.filter = filter;
    end
    cfg.keeptrials = 'yes';
    cfg.rawtrial = 'yes';
    source_trial = ft_sourceanalysis(cfg,data_meg);
end




När du skickar e-post till Karolinska Institutet (KI) innebär detta att KI kommer att behandla dina personuppgifter. Här finns information om hur KI behandlar personuppgifter<https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fki.se%2Fom-ki%2Fintegritetsskyddspolicy&data=05%7C02%7Cfieldtrip%40science.ru.nl%7C07cc8676cf0d4921fb3b08dc4a3fc655%7C084578d9400d4a5aa7c7e76ca47af400%7C1%7C0%7C638466884958109871%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=3V1v25fSl5qz5ApGGj%2BxpRlLh4JuyZHp%2Fn5qreKnKTI%3D&reserved=0>.

Sending email to Karolinska Institutet (KI) will result in KI processing your personal data. You can read more about KI’s processing of personal data here<https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstaff.ki.se%2Fdata-protection-policy&data=05%7C02%7Cfieldtrip%40science.ru.nl%7C07cc8676cf0d4921fb3b08dc4a3fc655%7C084578d9400d4a5aa7c7e76ca47af400%7C1%7C0%7C638466884958109871%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=%2FY8F1cc%2F2j2OlLca1w51ojRfmHeIFzrh5UB9vJM8pcg%3D&reserved=0>.
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip<https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmailman.science.ru.nl%2Fmailman%2Flistinfo%2Ffieldtrip&data=05%7C02%7Cfieldtrip%40science.ru.nl%7C07cc8676cf0d4921fb3b08dc4a3fc655%7C084578d9400d4a5aa7c7e76ca47af400%7C1%7C0%7C638466884958109871%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=VzgeeoAwOsfiHuk8nuOfzAIJFstOeVIn2JtZv5DH7b4%3D&reserved=0>
https://doi.org/10.1371/journal.pcbi.1002202<https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdoi.org%2F10.1371%2Fjournal.pcbi.1002202&data=05%7C02%7Cfieldtrip%40science.ru.nl%7C07cc8676cf0d4921fb3b08dc4a3fc655%7C084578d9400d4a5aa7c7e76ca47af400%7C1%7C0%7C638466884958109871%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=JaA%2BPbdu0ccRSJqCwAn0zwXcaQfS1FKt%2F6gc0Aprv9E%3D&reserved=0>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20240322/34d920ff/attachment.htm>


More information about the fieldtrip mailing list