FieldTrip connectivity demo

In this demonstration we will use the face recognition dataset.

Please use the general instructions to get started.

Part 1 - virtual channel connectivity

%% start with data that was preprocessed in FieldTrip
subj = 15;
prefix = sprintf('Sub%02d', subj);
load([prefix '_raw']);  % this is called "data" rather than "raw"

% load the results from beamformer_part1
load vol
load sens
load mri_realigned


%% deal with maxfilter

% the data has been maxfiltered and subsequently contatenated
% this results in an ill-conditioned estimate of covariance or CSD

cfg             = [];
cfg.method      = 'pca';
cfg.updatesens  = 'no';
cfg.channel     = 'MEGMAG';
comp = ft_componentanalysis(cfg, data);

cfg             = [];
cfg.updatesens  = 'no';
cfg.component   = comp.label(51:end);
data_fix = ft_rejectcomponent(cfg, comp);


%%

pos1 = [21 -64 30];
pos2 = [0 35 83];

cfg = [];
cfg.location = pos1;
figure; ft_sourceplot(cfg, mri_realigned);
cfg.location = pos2;
figure; ft_sourceplot(cfg, mri_realigned);

%%
% timelock2 was computed in https://www.fieldtriptoolbox.org/workshop/meg-uk-2015/fieldtrip-beamformer-demo#part_3_-_reconstruct_single-trial_cortical_responses

cfg             = [];
cfg.headmodel   = vol;
cfg.grad        = sens;
cfg.senstype    = 'meg';
cfg.method      = 'lcmv';
cfg.lcmv.keepfilter = 'yes';
cfg.lcmv.projectmom = 'yes';
cfg.unit   = 'mm';
cfg.sourcemodel.pos    = pos1;
source1 = ft_sourceanalysis(cfg, timelock2);

cfg.sourcemodel.pos = pos2;
source2 = ft_sourceanalysis(cfg, timelock2);


%% construct single-trial virtual channel representation

virtualchannel_raw = [];
virtualchannel_raw.label = {'pos1'; 'pos2'};
virtualchannel_raw.trialinfo = data_fix.trialinfo;
for i=1:882
% note that this is the non-filtered raw data
virtualchannel_raw.time{i}       = data_fix.time{i};
virtualchannel_raw.trial{i}(1,:) = source1.avg.filter{1} * data_fix.trial{i}(:,:);
virtualchannel_raw.trial{i}(2,:) = source2.avg.filter{1} * data_fix.trial{i}(:,:);
end

%%

cfg                 = [];
cfg.keeptrials      = 'yes';
cfg.preproc.demean  = 'yes';
cfg.preproc.baselinewindow = [-inf 0];
virtualchannel_avg = ft_timelockanalysis(cfg, virtualchannel_raw);

figure
plot(virtualchannel_avg.time, virtualchannel_avg.avg)
legend(virtualchannel_avg.label);

%%

cfg         = [];
cfg.method  = 'wavelet';
cfg.output  = 'powandcsd';
cfg.foi     = 4:2:70;
cfg.toi     = -0.200:0.020:1.000;
virtualchannel_wavelet = ft_freqanalysis(cfg, virtualchannel_raw);

cfg                 = [];
cfg.baselinetype    = 'relative';
cfg.baseline        = [-inf 0];
cfg.channel         = {'pos1'};
figure; ft_singleplotTFR(cfg, virtualchannel_wavelet);

cfg.channel         = {'pos2'};
figure; ft_singleplotTFR(cfg, virtualchannel_wavelet);

%%

cfg = [];
cfg.method = 'coh';
coherence = ft_connectivityanalysis(cfg, virtualchannel_wavelet);


figure
imagesc(coherence.time, coherence.freq, squeeze(coherence.cohspctrm(1,:,:)));
axis xy

Part 2 - whole brain connectivity

%% start from data that was processed by FieldTrip
subj = 15;
prefix = sprintf('Sub%02d', subj);
load([prefix '_raw']);  % this is called "data" rather than "raw"

% load the results from beamformer_part1
load vol
load sens
load mri_realigned


%% deal with maxfilter

% the data has been maxfiltered and subsequently contatenated
% this results in an ill-conditioned estimate of covariance or CSD

cfg = [];
cfg.method = 'pca';
cfg.updatesens = 'no';
cfg.channel = 'MEGMAG';
comp = ft_componentanalysis(cfg, data);

cfg = [];
cfg.updatesens = 'no';
cfg.component = comp.label(51:end);
data_fix = ft_rejectcomponent(cfg, comp);

%%

cfg = [];
cfg.channel = 'MEGMAG';
cfg.method = 'wavelet';
cfg.output = 'fourier';
cfg.keeptrials = 'yes';
cfg.foi = 16;
cfg.toi = 0.150;
freq = ft_freqanalysis(cfg, data_fix);


%%

cfg = [];
cfg.resolution = 7;
% cfg.inwardshift = -7; % allow dipoles 10mm outside the brain, this improves interpolation at the edges
cfg.unit = 'mm';
cfg.headmodel = vol;  % from FT
cfg.grad      = sens; % from FT
cfg.senstype  = 'meg';
cfg.normalize = 'yes';
grid = ft_prepare_leadfield(cfg, freq);

% save grid grid


%%

cfg           = [];
cfg.headmodel = vol;  % from FT
cfg.grad      = sens; % from FT
cfg.senstype  = 'meg';
cfg.grid      = grid;
cfg.method    = 'pcc';
cfg.pcc.fixedori = 'yes';
cfg.latency   = [0.140 0.160];
cfg.frequency = [14 18];

source = ft_sourceanalysis(cfg, freq);

figure
plot(source.avg.mom{source.inside(1)}, '.')
xlabel('real');
ylabel('imag');

%%

pos = [21 -64 30];

% compute the nearest grid location
dif = grid.pos;
dif(:,1) = dif(:,1)-pos(1);
dif(:,2) = dif(:,2)-pos(2);
dif(:,3) = dif(:,3)-pos(3);
dif = sqrt(sum(dif.^2,2));
[distance, refindx] = min(dif);

cfg = [];
cfg.method    = 'coh';
% cfg.complex   = 'abs';
cfg.complex   = 'absimag';
cfg.refindx   = refindx;
conn = ft_connectivityanalysis(cfg, source);

% the output contains both the actual source position, as well as the position of the reference
% this is ugly and will probably change in future FieldTrip versions
orgpos = conn.pos(:,1:3);
refpos = conn.pos(:,4:6);
conn.pos = orgpos;

%% visualise the seed-based connectivity results

cfg               = [];
cfg.funparameter  = 'cohspctrm';
figure; ft_sourceplot(cfg, conn);

cfg             = [];
cfg.parameter   = 'cohspctrm';
sourceI = ft_sourceinterpolate(cfg, conn, mri_realigned);

cfg               = [];
cfg.funparameter  = 'cohspctrm';
figure; ft_sourceplot(cfg, sourceI);

%% look at connectivity difference

cfg         = [];
cfg.trials  = find(freq.trialinfo==1 | freq.trialinfo==2); % 1=Famous, 2=Unfamiliar
source1 = ft_selectdata(cfg, source);

cfg.trials  = find(freq.trialinfo==3); % 3=Scrambled
source2 = ft_selectdata(cfg, source);

% consider using ft_stratify to equalise number of trials going in to source 1 and 2, as SNR differences between conditions affects connectivity measures between conditions

cfg         = [];
cfg.method  = 'coh';
cfg.complex = 'absimag';
cfg.refindx = refindx;
conn1 = ft_connectivityanalysis(cfg, source1);
conn2 = ft_connectivityanalysis(cfg, source2);

conn1.pos = conn1.pos(:,1:3);
conn2.pos = conn2.pos(:,1:3);

cfg           = [];
cfg.parameter = 'cohspctrm';
cfg.operation = 'x1-x2'; % or 'subtract'
conn_dif = ft_math(cfg, conn1, conn2);

cfg           = [];
cfg.parameter = 'cohspctrm';
source1int    = ft_sourceinterpolate(cfg, conn1, mri_realigned);
source2int    = ft_sourceinterpolate(cfg, conn2, mri_realigned);
source_difint = ft_sourceinterpolate(cfg, conn_dif, mri_realigned);

cfg               = [];
cfg.funparameter  = 'cohspctrm';
cfg.funcolorlim   = [-0.1 0.1];
cfg.maskparameter = 'cohspctrm';
cfg.opacitylim    = [-0.15 0.15];
figure; ft_sourceplot(cfg, source_difint);

%% look at the analysis history

% for saving to disk
prefix = sprintf('Sub%02d', subj);

cfg           = [];
cfg.filename  = [prefix '_source_difint.html'];
ft_analysispipeline(cfg, source_difint);