Skip to content

Commit

Permalink
Merge pull request #65 from nguyen-td/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
nguyen-td authored Sep 7, 2023
2 parents b4a40aa + 93a5ed1 commit 16ec72a
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 25 deletions.
8 changes: 4 additions & 4 deletions libs/haufe/data2sctrgcmim.m
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@

if ~isempty(intersect(output, {'MIM', 'MIC'}))
%MIC and MIM
[MIC(:, iind) , MIM(:, iind)] = roi_mim2(cCOH, inds{iind}{1}, inds{iind}{2});
[MIC(:, iind) , MIM(:, iind)] = roi_mim2_v2(cCOH, inds{iind}{1}, inds{iind}{2});
end

if ~isempty(intersect(output, {'GC', 'TRGC'}))
Expand Down Expand Up @@ -235,7 +235,7 @@

if ~isempty(intersect(output, {'MIM', 'MIC'}))
%MIC and MIM
[MIC(:, iind) , MIM(:, iind)] = roi_mim2(cCOH(subset, subset, :), subinds{1}, subinds{2});
[MIC(:, iind) , MIM(:, iind)] = roi_mim2_v2(cCOH(subset, subset, :), subinds{1}, subinds{2});
end

if ~isempty(intersect(output, {'GC', 'TRGC'}))
Expand Down Expand Up @@ -340,7 +340,7 @@

if ~isempty(intersect(output, {'MIM', 'MIC'}))
%MIC and MIM
[MIC(:, iind, iboot) , MIM(:, iind, iboot)] = roi_mim2(cCOH_, inds{iind}{1}, inds{iind}{2});
[MIC(:, iind, iboot) , MIM(:, iind, iboot)] = roi_mim2_v2(cCOH_, inds{iind}{1}, inds{iind}{2});
end

if ~isempty(intersect(output, {'GC', 'TRGC'}))
Expand Down Expand Up @@ -377,7 +377,7 @@

if ~isempty(intersect(output, {'MIM', 'MIC'}))
%MIC and MIM
[MIC(:, iind, iboot) , MIM(:, iind, iboot)] = roi_mim2(cCOH_(subset, subset, :), subinds{1}, subinds{2});
[MIC(:, iind, iboot) , MIM(:, iind, iboot)] = roi_mim2_v2(cCOH_(subset, subset, :), subinds{1}, subinds{2});
end

if ~isempty(intersect(output, {'GC', 'TRGC'}))
Expand Down
7 changes: 4 additions & 3 deletions pop_roi_connect.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
% 'conn_stats' - ['on'|'off'] Run statistics on connectivity metrics. Default is 'off'.
% 'nshuf' - [integer] number of shuffles for statistical significance testing. The first shuffle is the true value. Default is 1001.
% 'freqrange' - [min max] frequency range in Hz. This is used to compute and plot p-values. Default is to plot broadband power.
%
% 'poolsize' - [integer] Number of workers in the parallel pool (check parpool documentation) for parallel computing
%
% Output:
% EEG - EEGLAB dataset with field 'roi' containing connectivity info.
Expand Down Expand Up @@ -182,7 +182,8 @@
'bs_outopts' 'integer' { } 1;
'roi_selection' 'cell' { } { };
'conn_stats' 'string' { } 'off'; ...
'nshuf' 'integer' { } 1001}, 'pop_roi_connect');
'nshuf' 'integer' { } 1001; ...
'poolsize' 'integer' { } 1}, 'pop_roi_connect');
if ischar(g), error(g); end

% process multiple datasets
Expand Down Expand Up @@ -259,7 +260,7 @@
end

elseif strcmpi(g.conn_stats, 'on')
EEG = roi_connstats(EEG, 'methods', g.methods, 'nshuf', g.nshuf, 'roi_selection', g.roi_selection, 'freqresolution', g.freqresolution);
EEG = roi_connstats(EEG, 'methods', g.methods, 'nshuf', g.nshuf, 'roi_selection', g.roi_selection, 'freqresolution', g.freqresolution, 'poolsize', g.poolsize);
else
EEG = roi_connect(EEG, 'morder', g.morder, 'naccu', g.naccu, 'methods', g.methods,'freqresolution', g.freqresolution, ...
'roi_selection', g.roi_selection);
Expand Down
1 change: 0 additions & 1 deletion pop_roi_statsplot.m
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,5 @@
set(h, 'fontsize', 20);
catch
warning('There are no "significant" p-values to be plotted. These are the p-values:')
disp(FC_pn)
end
end
10 changes: 6 additions & 4 deletions roi_connstats.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
% 'freqresolution' - [integer] Desired frequency resolution (in number of frequencies). If
% specified, the signal is zero padded accordingly.
% Default is 0 (means no padding).
% 'poolsize' - [integer] Number of workers in the parallel pool (check parpool documentation) for parallel computing

function EEG = roi_connstats(EEG, varargin)

Expand All @@ -41,7 +42,8 @@
'methods' 'cell' { } { };
'nshuf' 'integer' { } 1001;
'freqresolution' 'integer' { } 0;
'roi_selection' 'cell' { } { } }, 'roi_connstats');
'roi_selection' 'cell' { } { }; ...
'poolsize' 'integer' { } 1 }, 'roi_connstats');
if ischar(g), error(g); end

if ~isempty(intersect(g.methods, {'COH'}))
Expand All @@ -51,14 +53,14 @@
g.methods{coh_idx} = 'aCOH';
end

methodset1 = { 'CS' 'MIM' 'wPLI' 'cCOH' 'aCOH' 'iCOH' }; % GC/TRGC, PDC/TRPDC, DTF/TRDTF not included (yet)
methodset1 = { 'CS' 'MIM' 'MIC' 'wPLI' 'cCOH' 'aCOH' 'iCOH' }; % GC/TRGC, PDC/TRPDC, DTF/TRDTF not included (yet)
tmpMethods1 = intersect(g.methods, methodset1);
if ~isempty(tmpMethods1)
npcs = repmat(EEG.roi.nPCA, 1, EEG.roi.nROI);
conn = shuffle_MIM(data, npcs, tmpMethods1, g.nshuf, 'freqresolution', g.freqresolution, 'roi_selection', g.roi_selection); % (nfreq, nROI, nROI, nshuf)
conn = shuffle_MIM(data, npcs, tmpMethods1, g.nshuf, 'freqresolution', g.freqresolution, 'roi_selection', g.roi_selection, 'poolsize', g.poolsize); % (nfreq, nROI, nROI, nshuf)
for iMethod = 1:length(tmpMethods1)
EEG.roi.(tmpMethods1{iMethod}) = conn.(tmpMethods1{iMethod});
if strcmpi(tmpMethods1{iMethod}, 'MIM')
if strcmpi(tmpMethods1{iMethod}, 'MIM') || strcmpi(tmpMethods1{iMethod}, 'MIC')
EEG.roi.inds = conn.inds;
end
end
Expand Down
5 changes: 4 additions & 1 deletion roi_networkplot.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,15 @@
'plotmode' 'string' {'2D' '3D' 'both' 'none' } '2D';
'plotopt' 'cell' {} {};
'filename' 'string' {} '';
'threshold' 'float' {} 0.1;
'threshold' {'string' 'float'} { {} {} } 0.1;
'precomputed' 'struct' {} struct([]);
}, 'roi_networkplot', 'ignore');
if isstr(g)
error(g);
end
if ischar(g.threshold) || isstring(g.threshold)
g.threshold = str2double(g.threshold);
end
if ~isempty(g.filename) % remove file extension
[filePath,g.filename] = fileparts(g.filename);
g.filename = fullfile(filePath, g.filename);
Expand Down
7 changes: 5 additions & 2 deletions test_pipes/test_largebarplot_dkatlas.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
'sourcemodel2mni',[0 -24 -45 0 0 -1.5708 1000 1000 1000] ,'downsample',1);

EEG = pop_roi_activity(EEG, 'leadfield',EEG.dipfit.sourcemodel,'model','LCMV','modelparams',{0.05},'atlas','LORETA-Talairach-BAs','nPCA',3);
EEG = pop_roi_connect(EEG, 'methods', {'MIM', 'TRGC'});
tic
EEG = pop_roi_connect(EEG, 'methods', {'MIM'});
toc

%% Plot barplot
% plot barplot with specified frequency band
EEG = pop_roi_connectplot(EEG, 'measure', 'roipsd', 'plotcortex', 'off', 'plotbarplot', 'on', 'freqrange', [4 8]);
% pop_roi_connectplot(EEG, 'measure', 'roipsd', 'plotcortex', 'off', 'plotbarplot', 'on', 'freqrange', [4 8]);
pop_roi_connectplot(EEG, 'measure', 'MIM', 'plotcortex', 'off', 'plotmatrix', 'on', 'freqrange', [4 8]);
45 changes: 45 additions & 0 deletions utils/roi_mim2_v2.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function [mic, mim] = roi_mim2_v2(Cohroi, subinds1, subinds2)

regu = 0.000001;
[~, ~, nfreq] = size(Cohroi);

ipcs = numel(subinds1);
jpcs = numel(subinds2);

cs_red1 = Cohroi(subinds1,subinds1, :);
cs_red2 = Cohroi(subinds1,subinds2, :);
cs_red3 = Cohroi(subinds2,subinds2, :);

[mean_diag_r_csred1, dim1] = get_mean_diag(cs_red1, nfreq);
caainv = pageinv(real(cs_red1) + regu * ones(dim1, dim1, nfreq) .* eye(ipcs) .* mean_diag_r_csred1);
cab = imag(cs_red2);
[mean_diag_r_csred3, dim1] = get_mean_diag(cs_red3, nfreq);
cbbinv = pageinv(real(cs_red3) + regu * ones(dim1, dim1, nfreq) .* eye(jpcs) .* mean(mean_diag_r_csred3));
X = pagemtimes(pagemtimes(cab, cbbinv), pagetranspose(cab));

% MIM Ewald Eq. 14
r_caainv_X = reshape(pagemtimes(caainv, X), [], nfreq);
diag_idx = 1:dim1+1:size(r_caainv_X, 1);
trace_operator = zeros(1, size(r_caainv_X, 1));
trace_operator(diag_idx) = 1;
mim = trace_operator * r_caainv_X;

caainvsqrt = zeros(size(caainv, 1), size(caainv, 2), size(caainv, 3));
for ifq = 1:nfreq
caainvsqrt(:, :, ifq) = sqrtm(caainv(:, :, ifq));
end
Y = pagemtimes(pagemtimes(caainvsqrt, X), caainvsqrt); % Eq. 23
[~, s, ~] = pagesvd(Y);

% MIC
mic = sqrt(s(1, 1, :));
end

function [mean_diag_r_csred, dim1] = get_mean_diag(cs_red, nfreq)
% equivalent to diag(real(cs_red) in 2D
dim1 = size(cs_red, 1);
r_csred = reshape(real(cs_red), [], nfreq);
diag_idx = 1:dim1+1:size(r_csred, 1);
diag_r_csred = r_csred(diag_idx, :);
mean_diag_r_csred = reshape(mean(diag_r_csred, 1), 1, 1, []);
end
31 changes: 21 additions & 10 deletions utils/shuffle_MIM.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
% specified, the signal is zero padded accordingly. Default is 0 (means no padding).
% 'roi_selection' - [cell array of integers] Cell array of ROI indices {1, 2, 3, ...} indicating for which regions (ROIs) connectivity should be computed.
% Default is all (set to EEG.roi.nROI).
% 'poolsize' - [integer] Number of workers in the parallel pool (check parpool documentation) for parallel computing
%
% Outputs
% conn - [struct] Struct of (nfreq x nROI x nROI x nshuf) FC metrics
%
Expand All @@ -29,7 +31,8 @@
% decode input parameters
g = finputcheck(varargin, { ...
'freqresolution' 'integer' { } 0;
'roi_selection' 'cell' { } { } }, 'shuffle_MIM');
'roi_selection' 'cell' { } { }; ...
'poolsize' 'integer' { } 1 }, 'shuffle_MIM');
if ischar(g), error(g); end

[nchan, ndat, nepo] = size(data);
Expand Down Expand Up @@ -74,8 +77,10 @@

% warning('One iteration takes about 90 seconds.')
fprintf('Generating null distribution using %d shuffles...\n', nshuf)
fprintf('Progress of %d:', nshuf);
for ishuf = 1:nshuf
fprintf('Progress of %d:\n', nshuf);

parpool(g.poolsize)
parfor ishuf = 1:nshuf
if mod(ishuf, 10) == 0
fprintf('%d', ishuf);
elseif mod(ishuf, 2) == 0
Expand All @@ -89,16 +94,16 @@
shuf_inds = randperm(nepo);
end

clear MIM2 CS

data_shuf = data(:, :, shuf_inds);
[CS, ~, wPLI, ~] = data2cs_event_shuf(data(:, :)', data_shuf(:, :)', ndat, floor(ndat/2), ndat, [], CSpara);
% CS = fp_tsdata_to_cpsd(data, fres, 'WELCH', 1:nchan, 1:nchan,1:nepo,shuf_inds);

nfreqs = size(CS, 3);

if ~isempty(intersect(output, {'MIM', 'MIC', 'cCOH' 'iCOH', 'aCOH'}))
clear cCOH iCOH aCOH
cCOH = zeros(nchan, nchan, nfreqs)
aCOH = zeros(nchan, nchan, nfreqs)
iCOH = zeros(nchan, nchan, nfreqs)
for ifreq = 1:size(CS,3)
clear pow
pow = real(diag(CS(:,:,ifreq)));
cCOH(:,:,ifreq) = CS(:,:,ifreq) ./ sqrt(pow*pow');
aCOH(:,:,ifreq) = abs(CS(:,:,ifreq)) ./ sqrt(pow*pow');
Expand All @@ -107,19 +112,22 @@
end

% loop over sender/receiver combinations to compute time-reversed GC
MIM2 = zeros(nfreqs, ninds)
MIC2 = zeros(nfreqs, ninds)
for iind = 1:ninds
if ~isequal(inds{iind}{1}, inds{iind}{2})
%ind configuration
subset = [inds{iind}{1} inds{iind}{2}];
subinds = {1:length(inds{iind}{1}), length(inds{iind}{1}) + (1:length(inds{iind}{2}))};

%MIC and MIM
[~ , MIM2(:, iind)] = roi_mim2(cCOH(subset, subset, :), subinds{1}, subinds{2});
[MIC2(:, iind) , MIM2(:, iind)] = roi_mim2(cCOH(subset, subset, :), subinds{1}, subinds{2});
end
end

% reshape (in the case of MIM) or only keep the first principal component (other metrics)
MIM_s(:, :, :, ishuf) = get_connect_mat(MIM2, nROI, +1);
MIC_s(:, :, :, ishuf) = get_connect_mat(MIC2, nROI, +1);
CS_s(:, :, :, ishuf) = rm_components(permute(CS, [3 1 2 4]), npcs(1));
cCOH_s(:, :, :, ishuf) = rm_components(permute(cCOH, [3 1 2 4]), npcs(1));
aCOH_s(:, :, :, ishuf) = rm_components(permute(aCOH, [3 1 2 4]), npcs(1));
Expand All @@ -133,5 +141,8 @@
for iout = 1:length(output)
eval(['conn.' output{iout} ' = ' output{iout} '_s;'])
end
% shut down current parallel pool
poolobj = gcp('nocreate');
delete(poolobj);
fprintf('\n');
end
end

0 comments on commit 16ec72a

Please sign in to comment.