MEEG timeseries classification
This example shows MVPA analyses performed on MEEG data.
The input dataset involved a paradigm with electrical median nerve stimulation for durations of 2s at 20Hz.
The code presented here can be adapted for other MEEG analyses, but there are a few potential caveats:
- assignment of targets (labels of conditions) is based here on stimulation periods versus pre-stimulation periods. In typical analyses the targets should be based on different trial conditions, for example as set a FieldTrip .trialinfo field.
- assignment of chunks (parts of the data that are assumed to be independent) is based on a trial-by-trial basis. For cross-validation, the number of chunks is reduced to four to speed up the analysis.
- the time window used for analyses is rather small. This means that in particular for time-freq analysis a lot of data is missing, especially for early and late timepoints in the lower frequency bands. For typical analyses it may be preferred to use a wider time window.
- the current examples do not perform baseline corrections or signal normalizations, which may reduce discriminatory power.
Note: running this code requires FieldTrip.
- For CoSMoMVPA's copyright information and license terms, #
- see the COPYING file distributed with CoSMoMVPA. #
Contents
get timelock data in CoSMoMVPA format
% set configuration config=cosmo_config(); data_path=fullfile(config.tutorial_data_path,'meg_20hz'); % show dataset information readme_fn=fullfile(data_path,'README'); cosmo_type(readme_fn); % reset citation list cosmo_check_external('-tic'); % load data data_fn=fullfile(data_path,'subj102_B01_20Hz_timelock.mat'); data_tl=load(data_fn); % convert to cosmomvpa struct ds_tl=cosmo_meeg_dataset(data_tl); % set the target (trial condition) ds_tl.sa.targets=ds_tl.sa.trialinfo(:,1); % 1=pre, 2=post % set the chunks (independent measurements) % in this dataset, the first half of the samples (in order) % are the post-trials; % the second half the pre-trials ds_tl.sa.chunks=[(1:145) (1:145)]'; % in addition give a label to each trial index2label={'pre','post'}; % 1=pre, 2=peri/post ds_tl.sa.labels=cellfun(@(x)index2label(x),num2cell(ds_tl.sa.targets)); % just to check everything is ok cosmo_check_dataset(ds_tl);
Summary ------- MEG data in raw, time-locked and time-frequency formats. Contents -------- - subj102_B01_20Hz.fif raw MEG recording - preproc.m Matlab preprocessing script (based on FieldTrip) - subj102_B01_20Hz_timefreq.mat Time-locked data (generated by preproc.m) - subj102_B01_20Hz_timelock.mat Time-frequency data (generated by preproc.m) - LICENSE License file - README This file Methods ------- The dataset involved a paradigm with electrical median nerve stimulation with a human participant for durations of 2s at 20Hz. Data was acquired at 1khz using a neuromag306 system. Trial info in the .mat files: 1=pre-stimulus, 2=peri/post-stimulus License ------- The contents are made available by Nathan Weisz <nathanweisz |at| me.com> and Gianpaolo Demarchi <gianpaolo.demarchi |at| unitn.it> under the Creative Commons CC0 1.0 Universal Public Domain Dedication ("CC0"). See the LICENSE file for details, or visit http://creativecommons.org/publicdomain/zero/1.0/deed.en. Acknowledgements ---------------- Thanks to Nathan Weisz and Gianpaolo Demarchi for providing this dataset, and an anonymous participant for volunteering during the recordings. Contact ------- Nikolaas N. Oosterhof <nikolaas.oosterhof |at| unitn.it>
Prepare MVPA
reset chunks: use four chunks
nchunks=4; ds_tl.sa.chunks=cosmo_chunkize(ds_tl,nchunks); % do a take-one-fold out cross validation. % except when using a splithalf correlation measure it is important that % the partitions are *balanced*, i.e. each target (or class) is presented % equally often in each chunk partitions=cosmo_nchoosek_partitioner(ds_tl,1); partitions=cosmo_balance_partitions(partitions, ds_tl); npartitions=numel(partitions); fprintf('There are %d partitions\n', numel(partitions.train_indices)); fprintf('# train samples:%s\n', sprintf(' %d', cellfun(@numel, ... partitions.train_indices))); fprintf('# test samples:%s\n', sprintf(' %d', cellfun(@numel, ... partitions.test_indices)));
There are 4 partitions # train samples: 216 218 218 218 # test samples: 74 72 72 72
Run time-series searchlight on magneto- and gradio-meters seperately
% try two different classification approaches: % 1) without averaging the samples in the train set % 2) by averaging 5 samples at the time in the train set, and re-using % every sample 3 times. % (Note: As of July 2015, there is no clear indication in the literature % which approach is 'better'. These two approaches are used here to % illustrate how they can be used with a searchlight). average_train_args_cell={{},... % { 1 {'average_train_count',5,... % { 2 'average_train_resamplings',3}}; % { 2 n_average_train_args=numel(average_train_args_cell); % compute and plot accuracies for magnetometers and gradiometers separately chantypes={'meg_axial','meg_planar'}; % in the time searchlight analysis, select the time-point itself, the two % timepoints after it, and the two timepoints before it time_radius=2; nchantypes=numel(chantypes); ds_chantypes=cosmo_meeg_chantype(ds_tl); plot_counter=0; for j=1:n_average_train_args % define the measure and its argument. % here a simple naive baysian classifier is used. % Alternative are @cosmo_classify_{svm,nn,lda}. measure=@cosmo_crossvalidation_measure; measure_args=struct(); measure_args.classifier=@cosmo_classify_naive_bayes; measure_args.partitions=partitions; % add the options to average samples to the measure arguments. % (if no averaging is desired, this step can be left out.) average_train_args=average_train_args_cell{j}; measure_args=cosmo_structjoin(measure_args, average_train_args); for k=1:nchantypes parent_type=chantypes{k}; % find feature indices of channels matching the parent_type chantype_idxs=find(cosmo_match(ds_chantypes,parent_type)); % define mask with channels matching those feature indices chan_msk=cosmo_match(ds_tl.fa.chan,chantype_idxs); % slice the dataset to select only the channels matching the channel % types ds_tl_sel=cosmo_dim_slice(ds_tl, chan_msk, 2); ds_tl_sel=cosmo_dim_prune(ds_tl_sel); % remove non-indexed channels % define neighborhood over time; for each time point the time % point itself is included, as well as the two time points before % and the two time points after it nbrhood=cosmo_interval_neighborhood(ds_tl_sel,'time',... 'radius',time_radius); % run the searchlight using the measure, measure arguments, and % neighborhood defined above. % Note that while the input has both 'chan' and 'time' as feature % dimensions, the output only has 'time' as the feature dimension sl_map=cosmo_searchlight(ds_tl_sel,nbrhood,measure,measure_args); fprintf('The output has feature dimensions: %s\n', ... cosmo_strjoin(sl_map.a.fdim.labels,', ')); plot_counter=plot_counter+1; subplot(n_average_train_args,nchantypes,plot_counter); time_values=sl_map.a.fdim.values{1}; % first dim (channels got nuked) plot(time_values,sl_map.samples); ylim([.4 .8]) xlim([min(time_values),max(time_values)]); ylabel('classification accuracy (chance=.5)'); xlabel('time'); if isempty(average_train_args) postfix=' no averaging'; else postfix=' with averaging'; end descr=sprintf('%s - %s', strrep(parent_type,'_',' '), postfix); title(descr); end end % Show citation information cosmo_check_external('-cite');
Warning: cosmo_dim_slice is deprecated and will be removed in the future; instead of: % this is deprecated: result=cosmo_dim_slice(ds, ...) use: ds_sliced=cosmo_slice(ds, ...) result=cosmo_dim_prune(ds_sliced); This warning is shown only once, but the underlying issue may occur multiple times. To show each warning: - every time: cosmo_warning('on') - once: cosmo_warning('once') - never: cosmo_warning('off') +00:00:06 [####################] -00:00:00 The output has feature dimensions: time +00:00:10 [####################] -00:00:00 The output has feature dimensions: time +00:00:10 [####################] -00:00:00 The output has feature dimensions: time +00:00:16 [####################] -00:00:00 The output has feature dimensions: time If you use CoSMoMVPA and/or some other toolboxes for a publication, please cite: N. N. Oosterhof, A. C. Connolly, J. V. Haxby (2016). CoSMoMVPA: multi-modal multivariate pattern analysis of neuroimaging data in Matlab / GNU Octave. Frontiers in Neuroinformatics, doi:10.3389/fninf.2016.00027.. CoSMoMVPA toolbox available online from http://cosmomvpa.org The Mathworks, Natick, MA, United States. Matlab 9.1.0.441655 (R2016b) (September 7, 2016). available online from http://www.mathworks.com