-
Notifications
You must be signed in to change notification settings - Fork 27
/
limo_clustering.m
130 lines (112 loc) · 4.68 KB
/
limo_clustering.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
function [mask,cluster_pval,max_th] = limo_clustering(varargin)
% FORMAT: [mask,cluster_p,max_th] = limo_clustering(M,P,bootM,bootP,LIMO,MCC,p,fig)
%
% INPUT
% M = 2D matrix of observed F values (for a single channel use 1 in the 1st dimension)
% P = 2D matrix of observed p values (for a single channel use 1 in the 1st dimension)
% bootM = 3D matrix of F values for data bootstrapped under H0
% bootP = 3D matrix of F values for data bootstrapped under H0
% LIMO = the only necessary information is
% LIMO.data.chanlocs: the structure describing channels
% LIMO.data.neighbouring_matrix: the binary matrix of neighbours
% MCC = 2 (spatial-temporal clustering) or 3 (temporal clustering)
% p = threshold to apply (note this applied to create the excursion set,
% and then use as the corrected p value)
% fig = 1/0 to plot the maximum stat under H0 (if empty, turned on if no
% significant values)
%
% OUTPUT
% mask is a labelled matrix of the same size as M corresponding to a threshold
% p corrected for multiple comparisons
% cluster_p are the p-values obtained via the matrix bootM (corrected)
% max_th is the cluster mass threshold controlling the type 1 FWER
%
% Cyril Pernet
% outsourced from limo_stat_values
% ------------------------------
% Copyright (C) LIMO Team 2019
% check inputs
M = varargin{1};
P = varargin{2};
bootM = varargin{3};
bootP = varargin{4};
LIMO = varargin{5};
MCC = varargin{6};
p = varargin{7};
if nargin == 7
fig = [];
else
fig = varargin{8};
end
clear varargin
% switch behavioural to 1D clustering if one channel, no matter user choice
if size(M,1) == 1
MCC = 3;
end
% boostrap parameters
nboot = size(bootM,length(size(bootM))); % nb of boostrap performed
% set outputs empty as default
cluster_pval = [];
mask = [];
max_th = [];
%% spatial-temporal clustering
if MCC == 2 && size(bootM,1)>1
minnbchan = 2;
if isfield(LIMO,'data')
if isfield(LIMO.data,'neighbouring_matrix')
channeighbstructmat = LIMO.data.neighbouring_matrix;
else
channeighbstructmat = LIMO.data.channeighbstructmat;
end
else
channeighbstructmat = LIMO.channeighbstructmat;
end
boot_maxclustersum = zeros(nboot,1); % maximum cluster mass at each bootstrap
disp('Getting clusters under H0 boot, please wait...');
parfor boot = 1:nboot
% 1st find the cluster, thresholding H0 pvalues <= threshold p
[posclusterslabelmat,nposclusters] = limo_findcluster((bootP(:,:,boot) <= p),channeighbstructmat,minnbchan);
% 2nd compute the mass for each cluster
bootM_b = bootM(:,:,boot);
if nposclusters~=0
tmp = zeros(1,nposclusters);
for C = 1:nposclusters
tmp(C) = sum(bootM_b(posclusterslabelmat==C)); % sum stat value in a cluster label
end
boot_maxclustersum(boot) = max(tmp(:)); % save max value only
else
boot_maxclustersum(boot) = 0;
end
end
% 3rd threshold observed cluster mass by the distribution of cluster
% max computed in step 2
[mask, cluster_pval, maxval, max_th] = limo_cluster_test(M,P,...
boot_maxclustersum,channeighbstructmat,minnbchan,p);
end
%% temporal clustering
if MCC == 2 && size(bootM,1)==1 || MCC == 3
% 1st get the distribution of maxima under H0
[th,boot_maxclustersum] = limo_ecluster_make(squeeze(bootM),squeeze(bootP),p);
max_th = th.elec;
% 2nd threshold observed data
[sigcluster, cluster_pval,maxval] = limo_ecluster_test(squeeze(M),squeeze(P),th,p, boot_maxclustersum);
mask = sigcluster.elec_mask;
end
%% plot
% when nothing is significant, always show why
if sum(mask(:)) == 0 && fig == 1
figure('Name','Correction by clustering: results under H0')
mass = sort(boot_maxclustersum);
plot(mass,'LineWidth',3); grid on; hold on;
plot(min(find(mass==max_th)),max_th,'r*','LineWidth',5)
txt = ['bootstrap threashold ' num2str(max_th) '\rightarrow'];
text(min(find(mass==max_th)),max_th,txt,'FontSize',10,'HorizontalAlignment','right');
[val,loc]=min(abs(mass-maxval));
plot(loc,maxval,'r*','LineWidth',5)
txt = ['biggest observed cluster mass: ' num2str(maxval) '\rightarrow'];
text(loc,double(maxval),txt,'FontSize',10,'HorizontalAlignment','right');
title('Cluster-mass Maxima under H0 - no signitifcant results','FontSize',12)
xlabel('sorted bootstrap iterations','FontSize',12);
ylabel('Freq.','FontSize',12)
box on; set(gca,'Layer','Top')
end