├── CPM_external.m ├── CPM_internal.m ├── CPM_internal_permute.m ├── CPM_view_networks.m ├── README.md ├── extract_CONN_atlas_FC.m ├── images └── eg_feature_contributions.png ├── models ├── SITUT-CPM_Schaefer300.mat └── SITUT-CPM_Shen268.mat ├── univariate_SchaeferYeo.m └── utils ├── cbrewer ├── cbrewer.m ├── cbrewer_preview.jpg ├── change_jet.m ├── colorbrewer.mat ├── interpolate_cbrewer.m └── plot_brewer_cmap.m ├── fdr.m ├── fisherz.m └── network_atlases ├── Lookup_shen268 ├── Schaefer2018_300Parcels_17Networks_order_FSLMNI152_2mm.nii ├── Schaefer2018_300Parcels_7Networks_order_FSLMNI152_2mm.nii ├── Schaefer_label300_17networks.mat ├── Schaefer_label300_7networks.mat └── shen_2mm_268_parcellation.nii /CPM_external.m: -------------------------------------------------------------------------------- 1 | function [r_p_all,data]=CPM_external(all_mats,all_behav,cpm,part_var,motion_var) 2 | 3 | % Test CPM in external dataset 4 | % written by Aaron Kucyi, Northeastern University 5 | % INPUTS: 6 | % all_mats (required) : ROI x ROI x trials FC matrix (or single vector 7 | % for one ROI/edge) from test dataset 8 | % all_behav (required) : behavioral score vector from test dataset 9 | % cpm (required) : structure containing coefficient fits (fit_posneg), pos_mask and neg_mask 10 | % from training dataset 11 | % part_var (optional) : partial corr variable (leave blank if not using) 12 | % motion_var (optional) : head motion as FD (if included, removes subjects with FD>0.15) 13 | % OUTPUTS: 14 | % r_p_all = r (Pearson), p (Pearson), rho (Spearman), p (Spearman) 15 | % [plus repeat for partial correlations if selected] 16 | % data: predicted behav (column 1), observed behav (column 2), network strength (column 3) 17 | 18 | %% Settings 19 | FD_thr=.15; % cutoff for remoing subjects based on FD 20 | 21 | %% Defaults 22 | global globalDataDir; 23 | if nargin<4 || isempty(part_var) 24 | part_var=[]; 25 | end 26 | if nargin<5 || isempty(motion_var) 27 | motion_var=[]; 28 | end 29 | 30 | % set parameters 31 | no_sub=length(all_behav); 32 | if ndims(all_mats)==3 33 | no_node=size(all_mats,1); 34 | sub_trials=1:size(all_mats,3); 35 | end 36 | 37 | behav_pred_pos=zeros(no_sub,1); 38 | behav_pred_neg=zeros(no_sub,1); 39 | 40 | % remove high-motion subjects 41 | if ~isempty(motion_var) 42 | rm_subs=find(motion_var>FD_thr); 43 | display(['removing ' num2str(length(rm_subs)) ' subjects due to high motion']); 44 | all_behav(rm_subs)=NaN; 45 | if ~isempty(part_var) 46 | part_var(rm_subs)=NaN; 47 | end 48 | end 49 | 50 | % loop through test subjects 51 | curr_sub_trials=1; 52 | for leftout=1:no_sub 53 | if ndims(all_mats)>1 54 | test_mat=all_mats(:,:,leftout); 55 | test_sumpos(leftout)=nansum(nansum(test_mat.*cpm.pos_mask))/2; 56 | test_sumneg(leftout)=nansum(nansum(test_mat.*cpm.neg_mask))/2; 57 | test_sum_posneg(leftout)=squeeze(test_sumpos(leftout))-squeeze(test_sumneg(leftout)); 58 | behav_pred_posneg(leftout)=cpm.fit_posneg(1)*test_sum_posneg(leftout) + cpm.fit_posneg(2); 59 | behav_pred_pos(leftout)=cpm.fit_pos(1)*test_sumpos(leftout) + cpm.fit_pos(2); 60 | behav_pred_neg(leftout)=cpm.fit_neg(1)*test_sumneg(leftout) + cpm.fit_neg(2); 61 | end 62 | curr_sub_trials=curr_sub_trials+no_sub; 63 | end 64 | 65 | % compare predicted and observed scores 66 | [R_pos,P_pos]=corr(behav_pred_pos,all_behav,'rows','pairwise'); 67 | [R_neg,P_neg]=corr(behav_pred_neg,all_behav,'rows','pairwise'); 68 | [R_posneg,P_posneg]=corr(behav_pred_posneg',all_behav,'rows','pairwise'); 69 | [spearman_R_posneg,spearman_P_posneg]=corr(behav_pred_posneg',all_behav,'type','Spearman','rows','pairwise'); 70 | [spearman_R_pos,spearman_P_pos]=corr(behav_pred_pos,all_behav,'type','Spearman','rows','pairwise'); 71 | [spearman_R_neg,spearman_P_neg]=corr(behav_pred_neg,all_behav,'type','Spearman','rows','pairwise'); 72 | 73 | if ~isempty(part_var) 74 | [partial_R_pos,partial_P_pos]=partialcorr(behav_pred_pos,all_behav,part_var,'rows','pairwise'); 75 | [partial_R_neg,partial_P_neg]=partialcorr(behav_pred_neg,all_behav,part_var,'rows','pairwise'); 76 | [partial_R_posneg,partial_P_posneg]=partialcorr(behav_pred_posneg',all_behav,part_var,'rows','pairwise'); 77 | [partial_rho_pos,partial_rho_P_pos]=partialcorr(behav_pred_pos,all_behav,part_var,'type','Spearman','rows','pairwise'); 78 | [partial_rho_neg,partial_rho_P_neg]=partialcorr(behav_pred_neg,all_behav,part_var,'type','Spearman','rows','pairwise'); 79 | [partial_rho_posneg,partial_rho_P_posneg]=partialcorr(behav_pred_posneg',all_behav,part_var,'type','Spearman','rows','pairwise'); 80 | end 81 | 82 | %% organize output (R and P values, predicted vs observed vs network strength) 83 | if ~isempty(part_var) 84 | r_p_all=[R_posneg P_posneg spearman_R_posneg spearman_P_posneg partial_R_posneg partial_P_posneg partial_rho_posneg partial_rho_P_posneg]; 85 | data=[behav_pred_posneg' all_behav test_sum_posneg']; 86 | else 87 | r_p_all=[R_posneg P_posneg spearman_R_posneg spearman_P_posneg]; 88 | data=[behav_pred_posneg' all_behav test_sum_posneg']; 89 | end 90 | 91 | -------------------------------------------------------------------------------- /CPM_internal.m: -------------------------------------------------------------------------------- 1 | function [R,P,pred_obs]=CPM_internal(all_mats,all_behav,dataset,... 2 | kfolds,r_method,pthresh,part_var,motion_var,outname,train_mode) 3 | 4 | % Connectome-based predictive modeling: internal (within-dataset) validation 5 | % written by Aaron Kucyi, Northeastern University 6 | % adapted from Shen et al. (2017 Nature Protocols) 7 | % INPUTS: 8 | % all_mats (required) : ROI x ROI x subjects FC matrix (or single vector for one ROI/edge) 9 | % all_behav (required) : behavioral score vector 10 | % dataset (required) : name of dataset folder name 11 | % kfolds (optional) : number of cross-validation folds (default = leave one out) 12 | % r_method (optional) : correlation method (1 = Pearson (default); 2 = spearman; 13 | % 3 = robust regress; 4 = Pearson partial using part_var; 14 | % 5 = Spearman partial using part_var 15 | % pthresh (optional) : p threshold for feature selection (default = 0.01) 16 | % part_var (optional) : partial corr variable (leave blank if not using) 17 | % motion_var (optional) : head motion as FD (if included, removes subjects with FD>0.15) 18 | % outname (optional) : name for output files (default = 'test') 19 | % train_mode (optional) : 1 = do cross-validation (default); 2 = use all subjects for 20 | % training in a single fold and save linear regression parameters 21 | % OUTPUTS: 22 | % R : r values for predicted vs observed behav (R_pos R_neg R_pos-neg) 23 | % P : p values for predicted vs observed behav (P_pos P_neg P_pos-neg) 24 | % pred_obs : predicted behav observed behav (pos: columns 1-2, 25 | % neg: columns 3-4, pos-neg: columns 5-6) 26 | % positive and negative masks are saved in cpm_results within dataset folder 27 | 28 | %% Settings 29 | FD_thr=.20; % cutoff for removing subjects based on FD 30 | global globalDataDir; % this must be set within startup.m 31 | datapath=[globalDataDir]; 32 | if nargin<5 || isempty(r_method) 33 | r_method=1; 34 | end 35 | if nargin<8 || isempty(motion_var) 36 | motion_var=[]; 37 | end 38 | if nargin<7 || isempty(part_var) 39 | part_var=[]; 40 | end 41 | 42 | %% remove subjects with missing behavioral data 43 | missing=isnan(all_behav); 44 | all_mats(:,:,missing)=[]; 45 | if ~isempty(motion_var) 46 | motion_var(missing)=[]; 47 | end 48 | if ~isempty(part_var) 49 | part_var(missing)=[]; 50 | end 51 | all_behav(missing)=[]; 52 | 53 | %% remove high-motion subjects 54 | if ~isempty(motion_var) 55 | rm_subs=find(motion_var>FD_thr); 56 | if r_method~=3 57 | display(['removing ' num2str(length(rm_subs)) ' subjects due to high motion']); 58 | all_behav(rm_subs)=[]; 59 | all_mats(:,:,rm_subs)=[]; 60 | if ~isempty(part_var) 61 | part_var(rm_subs)=[]; 62 | end 63 | end 64 | end 65 | 66 | %% Defaults 67 | no_sub=length(all_behav); 68 | if nargin<4 || isempty(kfolds) 69 | kfolds=no_sub; 70 | end 71 | if nargin<6 || isempty(pthresh) 72 | pthresh=0.01; 73 | end 74 | if nargin<9 || isempty(outname) 75 | outname='test'; 76 | end 77 | if nargin<10 || isempty(train_mode) 78 | train_mode=1; 79 | end 80 | 81 | %% set parameters 82 | if train_mode==1 83 | no_sub=length(all_behav); 84 | elseif train_mode==2 85 | no_sub=1; % set to one loop if using all subjects for training 86 | end 87 | if ndims(all_mats)==3 88 | no_node=size(all_mats,1); 89 | sub_trials=1:size(all_mats,3); 90 | else % for single var 91 | no_node=1; 92 | sub_trials=1:length(all_mats); 93 | end 94 | behav_pred_pos=zeros(no_sub,1); 95 | behav_pred_neg=zeros(no_sub,1); 96 | 97 | randinds=randperm(no_sub); 98 | ksample=floor(no_sub/kfolds); 99 | pred_observed_posneg=[]; pred_observed_pos=[]; pred_observed_neg=[]; 100 | %% Run cross-validation folds 101 | if train_mode==2 102 | kfolds=1; 103 | end 104 | for leftout=1:kfolds 105 | if train_mode==1 106 | display(['Running fold ' num2str(leftout)]); 107 | train_mats = all_mats; 108 | train_behav=all_behav; 109 | if kfolds==no_sub % leave one subject out 110 | if ndims(all_mats)==3 111 | train_mats(:,:,leftout)=[]; 112 | else % for single ROI/edge 113 | train_vcts=train_mats; 114 | train_vcts(leftout)=[]; 115 | end 116 | train_behav(leftout)=[]; 117 | else % kfolds 118 | si=1+((leftout-1)*ksample); 119 | fi=si+ksample-1; 120 | testinds=randinds(si:fi); 121 | traininds=setdiff(randinds,testinds); 122 | train_mats(:,:,testinds)=[]; 123 | train_behav(testinds)=[]; 124 | end 125 | train_vcts=reshape(train_mats,[],size(train_mats,3)); 126 | elseif train_mode==2 127 | display(['Using all subjects to estimate model parameters']); 128 | train_mats = all_mats; 129 | train_vcts=reshape(train_mats,[],size(train_mats,3)); 130 | train_behav=all_behav; 131 | end 132 | 133 | % correlate all edges with behavior (in training data) 134 | if r_method==1 || r_method==4 135 | if ndims(all_mats)==3 136 | [r_mat,p_mat]=corr(train_vcts',train_behav,'rows','pairwise'); 137 | r_mat=reshape(r_mat,no_node,no_node); 138 | p_mat=reshape(p_mat,no_node,no_node); 139 | else % for single var 140 | [r_mat,p_mat]=corr(train_vcts,train_behav,'rows','pairwise'); 141 | end 142 | elseif r_method==2 || r_method==5 143 | if ndims(all_mats)==3 144 | [r_mat,p_mat]=corr(train_vcts',train_behav,'type','Spearman','rows','pairwise'); 145 | r_mat=reshape(r_mat,no_node,no_node); 146 | p_mat=reshape(p_mat,no_node,no_node); 147 | else % for single var 148 | [r_mat,p_mat]=corr(train_vcts,train_behav,'type','Spearman','rows','pairwise'); 149 | end 150 | elseif r_method==3 % robust regression 151 | edge_no=size(train_vcts,1); 152 | r_mat=zeros(1,edge_no); 153 | p_mat=zeros(1,edge_no); 154 | for edge_i = 1:edge_no 155 | [~,stats]=robustfit(train_vcts(edge_i,:)',train_behav); 156 | cur_t = stats.t(2); 157 | r_mat(edge_i) = sign(cur_t)*sqrt(cur_t^2/no_trials_all-1-2+cur_t^2); 158 | p_mat(edge_i) = 2*tcdf(cur_t, no_trials_all-1-2); % two-tailed 159 | end 160 | r_mat=reshape(r_mat,no_node,no_node); 161 | p_mat=reshape(p_mat,no_node,no_node); 162 | end 163 | 164 | % set threshold and define masks (in training data) 165 | if ndims(all_mats==3) 166 | pos_mask=zeros(no_node,no_node); 167 | neg_mask=zeros(no_node,no_node); 168 | pos_edges=find(r_mat>0 & p_mat < pthresh); 169 | neg_edges=find(r_mat<0 & p_mat < pthresh); 170 | pos_mask(pos_edges)=1; 171 | neg_mask(neg_edges)=1; 172 | pos_mask_allfolds(:,:,leftout)=pos_mask; 173 | neg_mask_allfolds(:,:,leftout)=neg_mask; 174 | end 175 | 176 | % get sum of all edges in train subs 177 | if ndims(all_mats==3) 178 | if train_mode==1 179 | train_sumpos=zeros(size(train_mats,3),1); % -1 is for leave one out; edit for k-fold 180 | train_sumneg=zeros(size(train_mats,3),1); 181 | train_sumposneg=zeros(size(train_mats,3),1); 182 | elseif train_mode==2 183 | train_sumpos=zeros(size(all_mats,3),1); 184 | train_sumneg=zeros(size(all_mats,3),1); 185 | train_sumposneg=zeros(size(all_mats,3),1); 186 | end 187 | for ss=1:size(train_sumpos) 188 | train_sumpos(ss) = nansum(nansum(train_mats(:,:,ss).*pos_mask))/2; 189 | train_sumneg(ss) = nansum(nansum(train_mats(:,:,ss).*neg_mask))/2; 190 | end 191 | train_sumposneg = train_sumpos-train_sumneg; 192 | end 193 | 194 | % build model on train subjects 195 | if ndims(all_mats)==3 196 | fit_pos=polyfit(train_sumpos(~isnan(train_behav)),train_behav(~isnan(train_behav)),1); 197 | fit_neg=polyfit(train_sumneg(~isnan(train_behav)),train_behav(~isnan(train_behav)),1); 198 | fit_posneg=polyfit(train_sumposneg(~isnan(train_behav)),train_behav(~isnan(train_behav)),1); 199 | else % for single ROI/edge and positive corr only 200 | fit_pos=polyfit(train_vcts(~isnan(train_vcts)),train_behav(~isnan(train_behav)),1); 201 | end 202 | 203 | % run model prediction on test subject 204 | if train_mode==1 205 | behav_pred_pos=[]; behav_pred_neg=[]; behav_pred_posneg=[]; 206 | if ndims(all_mats)==3 207 | if kfolds==no_sub % leave-one-out 208 | test_mat=all_mats(:,:,leftout); 209 | test_behav=all_behav(leftout); 210 | test_sumpos(leftout)=nansum(nansum(test_mat.*pos_mask))/2; 211 | test_sumneg(leftout)=nansum(nansum(test_mat.*neg_mask))/2; 212 | test_sum_posneg(leftout)=squeeze(test_sumpos(leftout))-squeeze(test_sumneg(leftout)); 213 | behav_pred_pos=fit_pos(1)*test_sumpos(leftout) + fit_pos(2); 214 | behav_pred_neg=fit_neg(1)*test_sumneg(leftout) + fit_neg(2); 215 | behav_pred_posneg=fit_posneg(1)*test_sum_posneg(leftout) + fit_posneg(2); 216 | if ~isempty(part_var) 217 | test_part_var=part_var(leftout); 218 | end 219 | else % kfolds 220 | test_mat=all_mats(:,:,testinds); 221 | test_behav=all_behav(testinds); 222 | for j=1:length(test_behav) 223 | test_sumpos(j)=nansum(nansum(test_mat(:,:,j).*pos_mask))/2; 224 | test_sumneg(j)=nansum(nansum(test_mat(:,:,j).*neg_mask))/2; 225 | test_sum_posneg(j)=squeeze(test_sumpos(j))-squeeze(test_sumneg(j)); 226 | behav_pred_pos(j,:)=fit_pos(1)*test_sumpos(j) + fit_pos(2); 227 | behav_pred_neg(j,:)=fit_neg(1)*test_sumneg(j) + fit_neg(2); 228 | behav_pred_posneg(j,:)=fit_posneg(1)*test_sum_posneg(j) + fit_posneg(2); 229 | if ~isempty(part_var) 230 | test_part_var=part_var(testinds); 231 | end 232 | end 233 | end 234 | if ~isempty(part_var) 235 | pred_observed_posneg=[pred_observed_posneg; behav_pred_posneg test_behav test_part_var]; 236 | pred_observed_pos=[pred_observed_pos; behav_pred_pos test_behav test_part_var]; 237 | pred_observed_neg=[pred_observed_neg; behav_pred_neg test_behav test_part_var]; 238 | else 239 | pred_observed_posneg=[pred_observed_posneg; behav_pred_posneg test_behav]; 240 | pred_observed_pos=[pred_observed_pos; behav_pred_pos test_behav]; 241 | pred_observed_neg=[pred_observed_neg; behav_pred_neg test_behav]; 242 | end 243 | 244 | else % for single ROI and leave one out 245 | test_mat=all_mats(leftout); 246 | for j=1:length(leftout) 247 | behav_pred_pos(leftout,:)=fit_pos(1)*test_mat + fit_pos(2); 248 | end 249 | end 250 | end 251 | end 252 | 253 | % compare predicted vs. observed scores across subjects 254 | if train_mode==1 255 | if r_method==1 || r_method==2 || r_method==3 256 | if ndims(all_mats)==3 257 | [R_pos, P_pos] = corr(pred_observed_pos(:,1),pred_observed_pos(:,2),'rows','pairwise'); 258 | [R_neg, P_neg] = corr(pred_observed_neg(:,1),pred_observed_neg(:,2),'rows','pairwise'); 259 | [R_posneg, P_posneg] = corr(pred_observed_posneg(:,1),pred_observed_posneg(:,2),'rows','pairwise'); 260 | else % for single ROI and positive corr 261 | [R_posneg(leftout), P_posneg(leftout)] = corr(behav_pred_pos,behav_test,'rows','pairwise'); 262 | end 263 | elseif r_method==4 % partial Pearson 264 | [R_pos, P_pos] = partialcorr(pred_observed_pos(:,1),pred_observed_pos(:,2),pred_observed_pos(:,3),'rows','pairwise'); 265 | [R_neg, P_neg] = partialcorr(pred_observed_neg(:,1),pred_observed_neg(:,2),pred_observed_neg(:,3),'rows','pairwise'); 266 | [R_posneg, P_posneg] = partialcorr(pred_observed_posneg(:,1),pred_observed_posneg(:,2),pred_observed_posneg(:,3),'rows','pairwise'); 267 | elseif r_method==5 % partial Spearman 268 | [R_pos, P_pos] = partialcorr(pred_observed_pos(:,1),pred_observed_pos(:,2),pred_observed_pos(:,3),'type','Spearman','rows','pairwise'); 269 | [R_neg, P_neg] = partialcorr(pred_observed_neg(:,1),pred_observed_neg(:,2),pred_observed_neg(:,3),'type','Spearman','rows','pairwise'); 270 | [R_posneg, P_posneg] = partialcorr(pred_observed_posneg(:,1),pred_observed_posneg(:,2),pred_observed_posneg(:,3),'type','Spearman','rows','pairwise'); 271 | end 272 | R=[R_pos R_neg R_posneg]; 273 | P=[P_pos P_neg P_posneg]; 274 | pred_obs=[pred_observed_pos,pred_observed_neg,pred_observed_posneg]; 275 | end 276 | 277 | % save linear regression parameters (when using all subjects for training), 278 | % positive mask and negative mask 279 | mkdir([datapath filesep dataset filesep 'cpm_results']); 280 | savepath=[datapath filesep dataset filesep 'cpm_results']; 281 | if train_mode==2 282 | cpm.fit_posneg=fit_posneg; cpm.fit_pos=fit_pos; cpm.fit_neg=fit_neg; 283 | cpm.pos_mask=pos_mask; cpm.neg_mask=neg_mask; 284 | save([savepath filesep outname '_cpm'],'cpm'); 285 | save([savepath filesep 'pos_mask_' outname '.txt'],'pos_mask','-ascii'); 286 | save([savepath filesep 'neg_mask_' outname '.txt'],'neg_mask','-ascii'); 287 | R_posneg=[]; P_posneg=[]; behav_pred_pos=[]; R=[]; P=[]; 288 | end 289 | 290 | % find positive and negative edges with overlap across 90% of all folds, save 291 | if ndims(all_mats)==3 && train_mode==1 292 | pos_mask_overall=NaN(size(pos_mask_allfolds,1),size(pos_mask_allfolds,2)); 293 | for i=1:size(pos_mask_allfolds,2) 294 | for j=1:size(pos_mask_allfolds,2) 295 | if sum(pos_mask_allfolds(i,j,:))/size(pos_mask_allfolds,3)>.9 296 | pos_mask_overall(i,j)=1; 297 | else 298 | pos_mask_overall(i,j)=0; 299 | end 300 | end 301 | end 302 | save([savepath filesep 'pos_mask_90percFolds_' outname '.txt'],'pos_mask_overall','-ascii'); 303 | save([savepath filesep 'pos_mask_90percFolds' outname],'pos_mask_allfolds'); 304 | 305 | neg_mask_overall=NaN(size(neg_mask_allfolds,1),size(neg_mask_allfolds,2)); 306 | for i=1:size(neg_mask_allfolds,2) 307 | for j=1:size(neg_mask_allfolds,2) 308 | if sum(neg_mask_allfolds(i,j,:))/size(neg_mask_allfolds,3)>.9 309 | neg_mask_overall(i,j)=1; 310 | else 311 | neg_mask_overall(i,j)=0; 312 | end 313 | end 314 | end 315 | save([savepath filesep 'neg_mask_90percFolds_' outname '.txt'],'neg_mask_overall','-ascii'); 316 | save([savepath filesep 'neg_mask_90percFolds_' outname],'neg_mask_allfolds'); 317 | end 318 | 319 | -------------------------------------------------------------------------------- /CPM_internal_permute.m: -------------------------------------------------------------------------------- 1 | function [p_all,R,R_permute_all]=CPM_internal_permute(all_mats,all_behav,dataset,... 2 | kfolds,r_method,pthresh,part_var,motion_var,outname,no_iter) 3 | 4 | % Permutation test for CPM_internal.m 5 | % written by Aaron Kucyi, Northeastern University 6 | % adapted from Shen et al. (2017 Nature Protocols) 7 | % INPUTS: 8 | % all_mats (required) : ROI x ROI x trials FC matrix (or single vector for one ROI/edge) 9 | % all_behav (required) : behavioral score vector 10 | % dataset (required) : name of dataset folder name 11 | % kfolds (optional) : number of cross-validation folds (default = leaveone out) 12 | % NOTE: if not using leave-one-out, computes average 13 | % of 120 iterations (Varoquaux et al. 2017 14 | % Neuroimage) 15 | % r_method (optional) : correlation method (1 = Pearson (default); 2 = spearman; 16 | % 3 = robust regress; 4 = Pearson partial using part_var; 17 | % 5 = Spearman partial using part_var 18 | % pthresh (optional) : p threshold for feature selection (default = 0.01) 19 | % part_var (optional) : partial corr variable (leave blank if not using) 20 | % motion_var (optional) : head motion as FD (if included, removes subjects with FD>0.15) 21 | % outname (optional) : name for output files (default = 'test') 22 | % no_iter (optional) : number of iterations for permute test (default=1000) 23 | % OUTPUTS: 24 | % p : p value for permutation test 25 | % R_posneg : real R value (mean of 100 iterations if using kfold) 26 | % R_permute : distribution of null R values 27 | 28 | %% Settings 29 | FD_thr=.20; % cutoff for removing subjects based on FD 30 | if nargin<5 || isempty(r_method) 31 | r_method=1; 32 | end 33 | if nargin<7 || isempty(part_var) 34 | part_var=[]; 35 | end 36 | if nargin<8 || isempty(motion_var) 37 | motion_var=[]; 38 | end 39 | 40 | %% remove subjects with missing behavioral data 41 | missing=isnan(all_behav); 42 | all_mats(:,:,missing)=[]; 43 | if ~isempty(motion_var) 44 | motion_var(missing)=[]; 45 | end 46 | if ~isempty(part_var) 47 | part_var(missing)=[]; 48 | end 49 | all_behav(missing)=[]; 50 | 51 | %% remove high-motion subjects 52 | if ~isempty(motion_var) 53 | rm_subs=find(motion_var>FD_thr); 54 | if r_method~=3 55 | display(['removing ' num2str(length(rm_subs)) ' subjects due to high motion']); 56 | all_behav(rm_subs)=[]; 57 | all_mats(:,:,rm_subs)=[]; 58 | if ~isempty(part_var) 59 | part_var(rm_subs)=[]; 60 | end 61 | end 62 | motion_var(rm_subs)=[]; 63 | end 64 | 65 | %% Defaults 66 | no_sub=length(all_behav); 67 | if nargin<4 || isempty(kfolds) 68 | kfolds=no_sub; 69 | end 70 | if nargin<6 || isempty(pthresh) 71 | pthresh=0.01; 72 | end 73 | if nargin<9 || isempty(outname) 74 | outname='test'; 75 | end 76 | if nargin<10 || isempty(no_iter) 77 | no_iter=1000; 78 | end 79 | 80 | if kfolds==no_sub % for leave-one-out, get one value 81 | [R]=CPM_internal(all_mats,all_behav,dataset,kfolds,r_method,pthresh,part_var,motion_var,outname); 82 | R_pos=R(1); R_neg=R(2); R_posneg=R(3); 83 | else % for kfolds, do 120 iterations and get avg value 84 | for i=1:120 85 | [R]=CPM_internal(all_mats,all_behav,dataset,kfolds,r_method,pthresh,part_var,motion_var,outname); 86 | R_pos(i)=R(1); R_neg(i)=R(2); R_posneg(i)=R(3); 87 | end 88 | R_pos=mean(R_pos); R_neg=mean(R_neg); R_posneg=mean(R_posneg); 89 | end 90 | % permutation test for significance for each subject 91 | R_permute_pos=[]; R_permute_neg=[]; R_permute_posneg=[]; 92 | for it=2:no_iter 93 | display(['Performing iteration ' num2str(it)]); 94 | % Permute labels 95 | if r_method==1 || r_method==2 96 | new_behav = all_behav(randperm(length(all_behav))); 97 | new_partial=[]; 98 | elseif r_method==4 || r_method==5 99 | order = 1:length(all_behav); 100 | new_order = order(randperm(length(order))); 101 | new_behav = all_behav(new_order); 102 | new_partial = part_var(new_order); 103 | end 104 | [R_shuffled]=CPM_internal(all_mats,new_behav,'rand',kfolds,r_method,pthresh,part_var,motion_var); 105 | R_permute_pos=[R_permute_pos; R_shuffled(1)]; 106 | R_permute_neg=[R_permute_neg; R_shuffled(2)]; 107 | R_permute_posneg=[R_permute_posneg; R_shuffled(3)]; 108 | end 109 | 110 | % assess significance 111 | true_prediction_r_posneg=R_posneg; 112 | prediction_r_posneg=[true_prediction_r_posneg; R_permute_posneg]; 113 | sorted_prediction_r_posneg=sort(prediction_r_posneg,'descend'); 114 | position_true_posneg=find(sorted_prediction_r_posneg==true_prediction_r_posneg); 115 | p_posneg=position_true_posneg/no_iter; 116 | 117 | true_prediction_r_pos=R_pos; 118 | prediction_r_pos=[true_prediction_r_pos; R_permute_pos]; 119 | sorted_prediction_r_pos=sort(prediction_r_pos,'descend'); 120 | position_true_pos=find(sorted_prediction_r_pos==true_prediction_r_pos); 121 | p_pos=position_true_pos/no_iter; 122 | 123 | true_prediction_r_neg=R_neg; 124 | prediction_r_neg=[true_prediction_r_neg; R_permute_neg]; 125 | sorted_prediction_r_neg=sort(prediction_r_neg,'descend'); 126 | position_true_neg=find(sorted_prediction_r_neg==true_prediction_r_neg); 127 | p_neg=position_true_neg/no_iter; 128 | 129 | p_all=[p_pos p_neg p_posneg]; 130 | R_permute_all=[R_permute_pos, R_permute_neg, R_permute_posneg]; 131 | -------------------------------------------------------------------------------- /CPM_view_networks.m: -------------------------------------------------------------------------------- 1 | function CPM_view_networks(cpm,atlas,dataset,norm) 2 | 3 | % Extract top intra- and inter-network contributors to a CPM 4 | % written by Aaron Kucyi, Northeastern University 5 | % INPUTS: 6 | % cpm (required) : structure containing pos_mask and neg_mask (e.g. 7 | % the output from CPM_internal.m when setting train_mode to 2) 8 | % atlas (required) : 1=Shen268, 2=Schaefer300 (7Networks), 3=Schaefer300 (17Networks) 9 | % dataset (required) : name of dataset folder name 10 | % norm (optional) : 0 = no normalization; 1 = normalize # of features per network pair by total # of network pairs 11 | % OUTPUTS: 12 | % saves figure within cpm_results/figs 13 | 14 | %% Settings 15 | nfeatures=5; % # of top feature types to extract 16 | pos_colors=cbrewer('seq','Reds',256); 17 | neg_colors=cbrewer('seq','Blues',256); 18 | 19 | global globalDataDir; 20 | datapath=[globalDataDir]; 21 | if nargin<4 || isempty(norm) 22 | norm=0; 23 | end 24 | %% Load network labels 25 | if atlas==1 26 | atlas_name='Shen268'; 27 | net_labels=importdata(['Lookup_shen268']); 28 | net_labels=net_labels(:,7); 29 | net_names={'SMN';'[]'; 'CO'; 'AUD'; 'DMN';'[]'; 'VIS'; 'FPN';... 30 | 'SAL'; 'SUB'; 'VAN'; 'DAN'; 'Unknown'}; 31 | elseif atlas==2 32 | net_labels=importdata(['Schaefer_label300_7networks.mat']); 33 | net_names={'DMN'; 'DAN'; 'SAL'; 'FPCN'; 'LIM'; 'VIS'; 'SMN'}; 34 | atlas_name='Schaefer300'; 35 | elseif atlas==3 36 | net_labels=importdata(['Schaefer_label300_17networks.mat']); 37 | net_names={'VIS_{A}'; 'VIS_{B}'; 'SMN_{A}'; 'SMN_{B}'; 'DAN_{A}'; 'DAN_{B}'; 'SAL_{A}'; 'SAL_{B}';... 38 | 'LIM_{A}'; 'LIM_{B}'; 'FPCN_{B}'; 'FPCN_{A}'; 'FPCN_{C}'; 'DMN_{A}'; 'DMN_{B}'; 'DMN_{C}'; 'TP'}; 39 | atlas_name='Schaefer17Networks'; 40 | end 41 | 42 | %% get n nodes per networks and n network-network pairs 43 | for i=1:length(net_names) 44 | node_count_net(i)=length(find(net_labels==i)); 45 | end 46 | pair_count=NaN(length(net_names),length(net_names)); 47 | for i=1:length(net_names) 48 | for j=1:length(net_names) 49 | pair_count(i,j)=node_count_net(i)*node_count_net(j); 50 | end 51 | end 52 | 53 | %% Pos mask 54 | [x_pos,y_pos]=find(cpm.pos_mask==1); 55 | xy_pos_labels=[net_labels(x_pos) net_labels(y_pos)]; 56 | 57 | % count # of network-pair feature types 58 | pos_count=NaN(length(net_names),length(net_names)); 59 | for i=1:length(net_names) 60 | for j=1:length(net_names) 61 | pos_count(i,j)=length(find(xy_pos_labels(:,1)==i & xy_pos_labels(:,2)==j)); 62 | end 63 | end 64 | pos_count=tril(pos_count); 65 | 66 | %% neg mask 67 | [x_neg,y_neg]=find(cpm.neg_mask==1); 68 | xy_neg_labels=[net_labels(x_neg) net_labels(y_neg)]; 69 | 70 | % count # of network-pair feature types 71 | neg_count=NaN(length(net_names),length(net_names)); 72 | for i=1:length(net_names) 73 | for j=1:length(net_names) 74 | neg_count(i,j)=length(find(xy_neg_labels(:,1)==i & xy_neg_labels(:,2)==j)); 75 | end 76 | end 77 | neg_count=tril(neg_count); 78 | 79 | %% normalize by total number of network-network pairs 80 | if atlas==1 % remove "unknown" networks for Shen268 atlas 81 | pair_count_known=pair_count(1:end-1,1:end-1); 82 | pos_count_known=pos_count(1:end-1,1:end-1); % delete counts for unknown networks 83 | neg_count_known=neg_count(1:end-1,1:end-1); % delete counts for unknown networks 84 | elseif atlas==2 || atlas==3 85 | pair_count_known=pair_count; 86 | pos_count_known=pos_count; % delete counts for unknown networks 87 | neg_count_known=neg_count; 88 | end 89 | if norm==1 90 | pos_count_norm=pos_count_known./pair_count_known; 91 | neg_count_norm=neg_count_known./pair_count_known; 92 | else 93 | pos_count_norm=pos_count_known; 94 | neg_count_norm=neg_count_known; 95 | end 96 | 97 | %% top feature types: pos mask 98 | xpos_top=[]; ypos_top=[]; 99 | temp_pos_count=pos_count_norm; 100 | for i=1:nfeatures 101 | [val_pos_top(i),ind_pos_top(i)]=max(temp_pos_count,[],'all','linear'); 102 | curr_ind=find(temp_pos_count==val_pos_top(i)); 103 | [x,y]=find(temp_pos_count==temp_pos_count(curr_ind(1))); 104 | xpos_top(i)=x(1); 105 | ypos_top(i)=y(1); 106 | temp_pos_count(ind_pos_top(i))=NaN; 107 | end 108 | 109 | %% top feature types: neg mask 110 | xneg_top=[]; yneg_top=[]; 111 | temp_neg_count=neg_count_norm; 112 | for i=1:nfeatures 113 | [val_neg_top(i),ind_neg_top(i)]=max(temp_neg_count,[],'all','linear'); 114 | curr_ind=find(temp_neg_count==val_neg_top(i)); 115 | [x,y]=find(temp_neg_count==temp_neg_count(curr_ind(1))); 116 | xneg_top(i)=x(1); 117 | yneg_top(i)=y(1); 118 | temp_neg_count(ind_neg_top(i))=NaN; 119 | end 120 | 121 | %% plot matrix of relative feature contributions 122 | % positive mask 123 | plot_pos_count=pos_count_norm; 124 | if atlas==1 125 | plot_pos_count([2 6],:)=[]; plot_pos_count(:,[2 6])=[]; 126 | end 127 | net_names_plot=net_names; 128 | if atlas==1 129 | net_names_plot([2 6 13])=[]; 130 | end 131 | pos_colors=[1 1 1; pos_colors(1:end-1,:)]; 132 | if atlas<3 133 | fig=figure('Position',[0 0 900 450]); 134 | elseif atlas==3 135 | fig=figure('Position',[0 0 1300 600]); 136 | end 137 | ax(1)=subplot(1,2,1); 138 | nx=length(net_names_plot); 139 | imagesc(plot_pos_count); 140 | colormap(ax(1),pos_colors); 141 | c=colorbar('Location','southoutside'); 142 | c.FontSize=14; 143 | if norm==1 144 | c.Label.String='Percentage of Edges'; 145 | elseif norm==0 146 | c.Label.String='Number of Edges'; 147 | end 148 | hold on; 149 | cut=1; cut2=-1; 150 | for i=1:nx+1 151 | plot([0.5,cut+0.5],[i-.5,i-.5],'k-'); 152 | plot([i-.5,i-.5],[0.5+cut2,0.5+nx],'k-'); 153 | cut=cut+1; cut2=cut2+1; 154 | end 155 | set(gca,'xtick',1:size(pos_count_norm,2)) 156 | box off 157 | set(gca,'xticklabel',[net_names_plot(1:length(net_names_plot))]) 158 | set(gca,'ytick',1:size(pos_count_norm,2)) 159 | set(gca,'yticklabel',[net_names_plot(1:length(net_names_plot))]) 160 | set(gca,'TickLength',[0 0]) 161 | set(gca,'FontSize',12,'FontName','Arial'); 162 | xtickangle(90); 163 | hold on; 164 | 165 | % negative mask 166 | ax(2)=subplot(1,2,2); 167 | plot_neg_count=neg_count_norm; 168 | if atlas==1 169 | plot_neg_count([2 6],:)=[]; plot_neg_count(:,[2 6])=[]; 170 | end 171 | net_names_plot=net_names; 172 | if atlas==1 173 | net_names_plot([2 6 13])=[]; 174 | end 175 | neg_colors=[1 1 1; neg_colors(1:end-1,:)]; 176 | 177 | nx=length(net_names_plot); %ny=length(net_names_plot); 178 | imagesc(plot_neg_count); 179 | colormap(ax(2),neg_colors); 180 | c=colorbar('Location','southoutside'); 181 | c.FontSize=14; 182 | if norm==1 183 | c.Label.String='Percentage of Edges'; 184 | elseif norm==0 185 | c.Label.String='Number of Edges'; 186 | end 187 | hold on; 188 | cut=1; cut2=-1; 189 | for i=1:nx+1 190 | plot([0.5,cut+0.5],[i-.5,i-.5],'k-'); 191 | plot([i-.5,i-.5],[0.5+cut2,nx+0.5],'k-'); 192 | cut=cut+1; cut2=cut2+1; 193 | end 194 | set(gca,'xtick',1:size(neg_count_norm,2)) 195 | box off 196 | set(gca,'xticklabel',[net_names_plot(1:length(net_names_plot))]) 197 | set(gca,'ytick',1:size(neg_count_norm,2)) 198 | set(gca,'yticklabel',[net_names_plot(1:length(net_names_plot))]) 199 | set(gca,'TickLength',[0 0]) 200 | set(gca,'FontSize',12,'FontName','Arial'); 201 | xtickangle(90); 202 | mkdir([datapath filesep dataset filesep 'cpm_results' filesep 'figs']); 203 | savepath=[datapath filesep dataset filesep 'cpm_results' filesep 'figs']; 204 | print([savepath filesep 'feature_contributions_' atlas_name],'-r600','-dpng'); 205 | pause; close; 206 | 207 | 208 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CPM_CONN 2 | Connectome-based predictive modeling analysis with CONN toolbox outputs 3 | 4 | **Setup** (before using this code): 5 | 6 | 1. Preprocess your dataset in Conn, including extraction of ROIs from an atlas file (see utils) selected as an "atlas file" within Conn 7 | 2. Extract head motion as frame-wise displacement in Conn (Setup > Covariates 1st level > Covariate tools > Compute new/derived first-level covariates > Compute 'FD_jenkinson') 8 | 3. In startup.m file, specify the parent directory of your dataset folders. Example (change to your specific directory): 9 | global globalDataDir; 10 | globalDataDir='/work/swglab/Aaron/data'; 11 | 4. Create a .mat cell array file with a list of subject names included in your Conn project 12 | 5. Create a .mat file with a vector of behavioral scores for each subject 13 | 14 | **Functions:** 15 | 16 | *extract_CONN_atlas_FC.m*: extracts functional connectivity matrices (from atlas) and mean FD, then merges across subjects (for input to CPM_internal.m) 17 | 18 | *CPM_internal.m*: runs CPM within a dataset (kfold, leave one out, or use entire dataset to define and save model parameters) 19 | 20 | *CPM_internal_permute.m*: runs permutation test to assess significance 21 | 22 | *CPM_external.m*: test CPM (defined by CPM_internal.m output) in external data 23 | 24 | *CPM_view_networks.m*: view intra- and inter-network contributions to positive and negative edges of a pre-computed CPM 25 | 26 | ![test](https://github.com/swglab/CPM_CONN/blob/master/images/eg_feature_contributions.png) 27 | 28 | *univariate_SchaeferYeo.m*: correlate behavior vs. connectivity between all intra- and inter-network pairs in the Schaefer atlas; apply FDR correction 29 | -------------------------------------------------------------------------------- /extract_CONN_atlas_FC.m: -------------------------------------------------------------------------------- 1 | function extract_CONN_atlas_FC(sublist,CONN_x,atlas,dataset,run_tag) 2 | 3 | % Extract functional connectivity matrices from an atlas within a CONN project 4 | % INPUTS: 5 | % sublist (required) : cell array with folders names of all subjects included in CONN project 6 | % CONN_x (required) : Conn project .mat structure 7 | % atlas (required) : name of atlas within CONN project (e.g.'Schaefer300') 8 | % dataset (required) : name of dataset folder name 9 | % run_tag (optional) : string specifying which run to use (when there are multiple runs in a session) 10 | % OUTPUTS: 11 | % within Extracted_ts_Conn subfolder for each subject: FC matrices 12 | % within [dataset]/Group folder: saves .mat file with 3D matrix (node x node x subject) r; also saves vector of FD (head motion) 13 | 14 | %% Settings 15 | global globalDataDir; % this must be set within startup.m 16 | datapath=[globalDataDir]; 17 | if nargin<5 || isempty(run_tag) 18 | run_tag=[]; 19 | end 20 | 21 | % make output directories 22 | for i=1:length(sublist) 23 | mkdir([datapath filesep dataset filesep sublist{i} filesep 'Extracted_ts_Conn']); 24 | end 25 | mkdir([datapath filesep dataset filesep 'Group']); 26 | 27 | % load conn directory 28 | conn_dir=CONN_x.folders.data(1:end-5); 29 | mean_FD=NaN(length(sublist),size(CONN_x.Setup.functional{1,1},2)); 30 | 31 | % extract time series 32 | for i=1:length(sublist) 33 | for j=1:1 % edit for >1 run? 34 | atlas_ts=[]; 35 | clear data data_sessions xyz roi_files 36 | % find all subject files 37 | roi_files=dir([conn_dir filesep 'results' filesep 'preprocessing' filesep '*Condition000.mat']); 38 | load([conn_dir filesep 'results' filesep 'preprocessing' filesep roi_files(i).name]); 39 | for k=1:length(data) % find atlas ROIs 40 | if contains(names{k},atlas) 41 | atlas_ts=[atlas_ts data{k}]; 42 | end 43 | end 44 | 45 | % extract FD (Jenkinson) for each run 46 | for k=1:size(CONN_x.Setup.functional{1,1},2) 47 | b=[]; 48 | FD_dir=CONN_x.Setup.functional{1,i}{1,k}{1,3}(1).fname; % edit for >1 run? 49 | b=strfind(FD_dir,filesep); 50 | fd_dir=FD_dir(1:b(end)); 51 | if ~isempty(run_tag) 52 | fd=dir([fd_dir '*FDjenkinson*' run_tag '*']); 53 | else 54 | fd=dir([fd_dir '*FDjenkinson*']); 55 | end 56 | if size(fd,1)==1 57 | fd=load([fd_dir fd.name]); 58 | else 59 | error(['ERROR: Multiple runs in session: re-rerun with run_tag specified']); 60 | end 61 | fd=fd.R; 62 | mean_FD(i,k)=mean(fd(2:end)); 63 | end 64 | 65 | % save subject data 66 | save([datapath filesep dataset filesep sublist{i} filesep 'Extracted_ts_Conn' filesep 'mean_FD'],'mean_FD'); 67 | save([datapath filesep dataset filesep sublist{i} filesep 'Extracted_ts_Conn' filesep atlas '.txt'],'atlas_ts','-ascii'); 68 | display(['Done subject ' num2str(i)]); 69 | end 70 | end 71 | 72 | % save FD (each run and mean across runs) 73 | save([datapath filesep dataset filesep 'Group' filesep 'meanFD_runs' run_tag],'mean_FD'); 74 | mean_FD=mean(mean_FD,2); 75 | save([datapath filesep dataset filesep 'Group' filesep 'meanFD' run_tag],'mean_FD'); 76 | 77 | % merge across subjects 78 | display(['Merging subjects : see output at ' datapath '/' dataset '/Group']); 79 | mean_FD=[]; 80 | for i=1:length(sublist) 81 | atlas_ts=[]; 82 | atlas_ts=importdata([globalDataDir filesep dataset filesep sublist{i} '/Extracted_ts_Conn' filesep atlas '.txt']); 83 | atlas_all_mats(:,:,i)=fisherz(corrcoef(atlas_ts)); 84 | end 85 | 86 | % save concatenated FC matrices and FD 87 | save([datapath filesep dataset filesep 'Group' filesep atlas '_all_mats'],'atlas_all_mats'); 88 | 89 | -------------------------------------------------------------------------------- /images/eg_feature_contributions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/images/eg_feature_contributions.png -------------------------------------------------------------------------------- /models/SITUT-CPM_Schaefer300.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/models/SITUT-CPM_Schaefer300.mat -------------------------------------------------------------------------------- /models/SITUT-CPM_Shen268.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/models/SITUT-CPM_Shen268.mat -------------------------------------------------------------------------------- /univariate_SchaeferYeo.m: -------------------------------------------------------------------------------- 1 | function [beta_lme,p_uncorrected,p_fdr_lme]=univariate_SchaeferYeo(all_mats,all_behav,atlas,motion_var) 2 | 3 | % compute mean within- and between-network Yeo7 network FC (based on 4 | % Schaefer nodes), then perform linear mixed effects analysis to predict behavior 5 | % applies FDR correction across all network pairs 6 | % written by Aaron Kucyi, Northeastern University 7 | % INPUTS: 8 | % all_mats (required) : ROI x ROI x subjects FC matrix 9 | % all_behav (required) : behavioral score vector 10 | % atlas (required) : 1=Schaefer300 (7Networks), 2=Schaefer300 (17Networks) 11 | % motion_var (optional) : head motion as FD (if included, removes subjects with FD>0.15) 12 | % OUTPUTS: 13 | % beta_lme 14 | % p_uncorrected 15 | % p_fdr_lme 16 | 17 | if nargin<4 || isempty(motion_var) 18 | motion_var=[]; 19 | end 20 | 21 | %% Settings 22 | FD_thr=.15; % cutoff for removing subjects based on FD 23 | if atlas==1 24 | net_labels=importdata(['Schaefer_label300_7networks.mat']); 25 | net_names={'DMN'; 'DAN'; 'SAL'; 'FPCN'; 'LIM'; 'VIS'; 'SMN'}; 26 | atlas_name='Schaefer300'; 27 | elseif atlas==2 28 | net_labels=importdata(['Schaefer_label300_17networks.mat']); 29 | net_names={'VIS_{A}'; 'VIS_{B}'; 'SMN_{A}'; 'SMN_{B}'; 'DAN_{A}'; 'DAN_{B}'; 'SAL_{A}'; 'SAL_{B}';... 30 | 'LIM_{A}'; 'LIM_{B}'; 'FPCN_{B}'; 'FPCN_{A}'; 'FPCN_{C}'; 'DMN_{A}'; 'DMN_{B}'; 'DMN_{C}'; 'TP'}; 31 | atlas_name='Schaefer17Networks'; 32 | end 33 | 34 | %% Defaults 35 | global globalDataDir; % this must be set within startup.m 36 | datapath=[globalDataDir]; 37 | mat_colors=cbrewer('div','RdBu',256); 38 | 39 | %% remove high-motion subjects 40 | if ~isempty(motion_var) 41 | rm_subs=find(motion_var>FD_thr); 42 | display(['removing ' num2str(length(rm_subs)) ' subjects due to high motion']); 43 | all_behav(rm_subs)=[]; 44 | all_mats(:,:,rm_subs)=[]; 45 | end 46 | 47 | %% compute within/between network FC and normalize within subjects 48 | no_node=size(all_mats,1); 49 | no_sub=length(all_behav); 50 | sub_FC_all=[]; 51 | for i=1:no_sub 52 | curr_mat = []; 53 | sub_FC=NaN(length(net_names),length(net_names)); 54 | curr_mat=all_mats(:,:,i); 55 | for j=1:max(net_labels) % seed network 56 | curr_network= []; 57 | curr_network=curr_mat(:,find(net_labels==j),:); 58 | for k=1:max(net_labels) % target network 59 | curr_target=[]; 60 | curr_target=curr_network(find(net_labels==k),:,:); 61 | curr_target=curr_target(:); 62 | sub_FC(j,k)=mean(curr_target(~isinf(curr_target))); 63 | end 64 | end 65 | % concatenate across subjects 66 | sub_FC_all=cat(3,sub_FC_all,sub_FC); 67 | end 68 | 69 | % LME for each intra- and inter-network pair vs behavior 70 | lmm_behav=all_behav; 71 | for i=1:size(sub_FC,1) 72 | for j=1:size(sub_FC,2) 73 | curr_edge=[]; 74 | curr_edge=squeeze(sub_FC_all(i,j,:)); 75 | [corr_mat(i,j),p_corr_mat(i,j)]=corr(all_behav,curr_edge); 76 | % LME 77 | lmm_variables=[]; lmm_table=[]; 78 | lmm_variables=[all_behav curr_edge]; 79 | lmm_table=table(lmm_variables(:,1),lmm_variables(:,2),... 80 | 'VariableNames',{'behav','FC'}); 81 | lme=fitlme(lmm_table,'behav~FC'); 82 | lme_anova=anova(lme,'DFmethod','satterthwaite'); 83 | beta=lme.fixedEffects; beta=beta(2); 84 | p=lme_anova.pValue; p=p(2); 85 | beta_lme(i,j)=beta; 86 | p_uncorrected(i,j)=p; 87 | F=lme_anova.FStat; F=F(2); 88 | F_lme(i,j)=F; 89 | end 90 | end 91 | p_lme=tril(p_uncorrected); 92 | p_lme(p_lme==0)=NaN; 93 | beta_lme=tril(beta_lme); 94 | 95 | %% fdr correction 96 | p=p_lme(:); p(isnan(p))=[]; p_fdr=fdr(p); 97 | p_mat=isnan(p_lme); p_fdr_lme=NaN(size(p_lme,1),size(p_lme,2)); 98 | for i=1:length(p_fdr) 99 | ind=[]; 100 | ind=find(p_mat==0); 101 | p_fdr_lme(ind(1))=p_fdr(i); 102 | p_mat(ind(1))=1; 103 | end 104 | [y_fdr,x_fdr]=find(p_fdr_lme<0.05); % coordinates for plotting * 105 | 106 | %% plot beta weights 107 | mat_colors(128,:)=[1 1 1]; 108 | mat_colors(129,:)=[1 1 1]; 109 | anchor=max(beta_lme(:))+.05; 110 | 111 | if atlas==1 112 | fig=figure('Position',[0 0 700 700]); 113 | elseif atlas==2 114 | fig=figure('Position',[0 0 800 800]); 115 | end 116 | nx=length(net_names); %ny=length(net_names_plot); 117 | imagesc(beta_lme,[-anchor anchor]); 118 | colormap(flipud(mat_colors)); 119 | c=colorbar('Location','southoutside'); 120 | c.FontSize=14; 121 | c.Label.String={'\beta'}; 122 | hold on; 123 | cut=1; cut2=-1; 124 | for i=1:nx+1 125 | plot([0.5,cut+0.5],[i-.5,i-.5],'k-'); 126 | plot([i-.5,i-.5],[0.5+cut2,0.5+nx],'k-'); 127 | cut=cut+1; cut2=cut2+1; 128 | end 129 | set(gca,'xtick',1:size(beta_lme,2)) 130 | box off 131 | set(gca,'xticklabel',[net_names(1:length(net_names))]) 132 | set(gca,'ytick',1:size(beta_lme,2)) 133 | set(gca,'yticklabel',[net_names(1:length(net_names))]) 134 | set(gca,'TickLength',[0 0]) 135 | set(gca,'FontSize',14,'FontName','Arial'); 136 | xtickangle(45); 137 | hold on; 138 | s=scatter(x_fdr,y_fdr,60,'k','*','MarkerEdgeColor','k') 139 | legend(s,['{\it p_{FDR}} <0.05']); 140 | legend boxoff 141 | title({['Univariate Analysis'];[' ']},'Fontweight','normal'); 142 | %print(['Univariate_SchaeferYeo_vs_MW_' suffix],'-r600','-dpng'); 143 | 144 | 145 | pause; close; -------------------------------------------------------------------------------- /utils/cbrewer/cbrewer.m: -------------------------------------------------------------------------------- 1 | function [colormap]=cbrewer(ctype, cname, ncol, interp_method) 2 | % 3 | % CBREWER - This function produces a colorbrewer table (rgb data) for a 4 | % given type, name and number of colors of the colorbrewer tables. 5 | % For more information on 'colorbrewer', please visit 6 | % http://colorbrewer2.org/ 7 | % 8 | % The tables were generated from an MS-Excel file provided on the website 9 | % http://www.personal.psu.edu/cab38/ColorBrewer/ColorBrewer_updates.html 10 | % 11 | % 12 | % [colormap]=cbrewer(ctype, cname, ncol, interp_method) 13 | % 14 | % INPUT: 15 | % - ctype: type of color table 'seq' (sequential), 'div' (diverging), 'qual' (qualitative) 16 | % - cname: name of colortable. It changes depending on ctype. 17 | % - ncol: number of color in the table. It changes according to ctype and 18 | % cname 19 | % - interp_method: interpolation method (see interp1.m). Default is "cubic" ) 20 | % 21 | % A note on the number of colors: Based on the original data, there is 22 | % only a certain number of colors available for each type and name of 23 | % colortable. When 'ncol' is larger then the maximum number of colors 24 | % originally given, an interpolation routine is called (interp1) to produce 25 | % the "extended" colormaps. 26 | % 27 | % Example: To produce a colortable CT of ncol X 3 entries (RGB) of 28 | % sequential type and named 'Blues' with 8 colors: 29 | % CT=cbrewer('seq', 'Blues', 8); 30 | % To use this colortable as colormap, simply call: 31 | % colormap(CT) 32 | % 33 | % To see the various colormaps available according to their types and 34 | % names, simply call: cbrewer() 35 | % 36 | % This product includes color specifications and designs developed by 37 | % Cynthia Brewer (http://colorbrewer.org/). 38 | % 39 | % Author: Charles Robert 40 | % email: tannoudji@hotmail.com 41 | % Date: 06.12.2011 42 | % ------------------------------ 43 | % 18.09.2015 Minor fixes, fixed a bug where the 'spectral' color table did not appear in the preview 44 | 45 | 46 | % load colorbrewer data 47 | load('colorbrewer.mat') 48 | % initialise the colormap is there are any problems 49 | colormap=[]; 50 | if (~exist('interp_method', 'var')) 51 | interp_method='cubic'; 52 | end 53 | 54 | % If no arguments 55 | if (~exist('ctype', 'var') | ~exist('cname', 'var') | ~exist('ncol', 'var')) 56 | disp(' ') 57 | disp('[colormap] = cbrewer(ctype, cname, ncol [, interp_method])') 58 | disp(' ') 59 | disp('INPUT:') 60 | disp(' - ctype: type of color table *seq* (sequential), *div* (divergent), *qual* (qualitative)') 61 | disp(' - cname: name of colortable. It changes depending on ctype.') 62 | disp(' - ncol: number of color in the table. It changes according to ctype and cname') 63 | disp(' - interp_method: interpolation method (see interp1.m). Default is "cubic" )') 64 | 65 | disp(' ') 66 | disp('Sequential tables:') 67 | z={'Blues','BuGn','BuPu','GnBu','Greens','Greys','Oranges','OrRd','PuBu','PuBuGn','PuRd',... 68 | 'Purples','RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd', 'Spectral'}; 69 | disp(z') 70 | 71 | disp('Divergent tables:') 72 | z={'BrBG', 'PiYG', 'PRGn', 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn'}; 73 | disp(z') 74 | 75 | disp(' ') 76 | disp('Qualitative tables:') 77 | %getfield(colorbrewer, 'qual') 78 | z={'Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2', 'Set1', 'Set2', 'Set3'}; 79 | disp(z') 80 | 81 | plot_brewer_cmap 82 | return 83 | end 84 | 85 | % Verify that the input is appropriate 86 | ctype_names={'div', 'seq', 'qual'}; 87 | if (~ismember(ctype,ctype_names)) 88 | disp('ctype must be either: *div*, *seq* or *qual*') 89 | colormap=[]; 90 | return 91 | end 92 | 93 | if (~isfield(colorbrewer.(ctype),cname)) 94 | disp(['The name of the colortable of type *' ctype '* must be one of the following:']) 95 | getfield(colorbrewer, ctype) 96 | colormap=[]; 97 | return 98 | end 99 | 100 | if (ncol>length(colorbrewer.(ctype).(cname))) 101 | % disp(' ') 102 | % disp('----------------------------------------------------------------------') 103 | % disp(['The maximum number of colors for table *' cname '* is ' num2str(length(colorbrewer.(ctype).(cname)))]) 104 | % disp(['The new colormap will be extrapolated from these ' num2str(length(colorbrewer.(ctype).(cname))) ' values']) 105 | % disp('----------------------------------------------------------------------') 106 | % disp(' ') 107 | cbrew_init=colorbrewer.(ctype).(cname){length(colorbrewer.(ctype).(cname))}; 108 | colormap=interpolate_cbrewer(cbrew_init, interp_method, ncol); 109 | colormap=colormap./255; 110 | return 111 | end 112 | 113 | if (isempty(colorbrewer.(ctype).(cname){ncol})) 114 | 115 | while(isempty(colorbrewer.(ctype).(cname){ncol})) 116 | ncol=ncol+1; 117 | end 118 | disp(' ') 119 | disp('----------------------------------------------------------------------') 120 | disp(['The minimum number of colors for table *' cname '* is ' num2str(ncol)]) 121 | disp('This minimum value shall be defined as ncol instead') 122 | disp('----------------------------------------------------------------------') 123 | disp(' ') 124 | end 125 | 126 | colormap=(colorbrewer.(ctype).(cname){ncol})./255; 127 | 128 | end -------------------------------------------------------------------------------- /utils/cbrewer/cbrewer_preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/utils/cbrewer/cbrewer_preview.jpg -------------------------------------------------------------------------------- /utils/cbrewer/change_jet.m: -------------------------------------------------------------------------------- 1 | % This script help produce a new 'jet'-like colormap based on other RGB reference colors 2 | 3 | % ------- I WAS ASKED --------------- 4 | % "is there a chance that you could add a diverging map going from blue to green to red as in jet, 5 | % but using the red and blue from your RdBu map and the third darkest green from your RdYlGn map?"" 6 | % 7 | % ANSWER: 8 | % You should construct the new colormap based on the existing RGB values of 'jet' 9 | % but projecting these RGB values on your new RGB basis. 10 | % ----------------------------------- 11 | 12 | % load colormaps 13 | jet=colormap('jet'); 14 | RdBu=cbrewer('div', 'RdBu', 11); 15 | RdYlGn=cbrewer('div', 'RdYlGn', 11); 16 | 17 | % Define the new R, G, B references (p stands for prime) 18 | Rp=RdBu(1,:); 19 | Bp=RdBu(end, :); 20 | Gp=RdYlGn(end-2, :); 21 | RGBp=[Rp;Gp;Bp]; 22 | 23 | % construct the new colormap based on the existing RGB values of jet 24 | % Project the RGB values on your new basis 25 | newjet = jet*RGBp; 26 | 27 | % store data in a strcuture, easier to handle 28 | cmap.jet=jet; 29 | cmap.newjet=newjet; 30 | cnames={'jet', 'newjet'}; 31 | 32 | % plot the RGB values 33 | fh=figure(); 34 | colors={'r', 'g', 'b'}; 35 | for iname=1:length(cnames) 36 | subplot(length(cnames),1,iname) 37 | dat=cmap.(cnames{end-iname+1}); 38 | for icol=1:size(dat,2) 39 | plot(dat(:,icol), 'color', colors{icol}, 'linewidth', 2);hold on; 40 | end % icol 41 | title([' "' cnames{end-iname+1} '" in RGB plot']) 42 | end 43 | 44 | % plot the colormaps 45 | fh=figure(); 46 | for iname=1:length(cnames) 47 | F=cmap.(cnames{iname}); 48 | ncol=length(F); 49 | fg=1./ncol; % geometrical factor 50 | X=fg.*[0 0 1 1]; 51 | Y=0.1.*[1 0 0 1]+(2*iname-1)*0.1; 52 | 53 | for icol=1:ncol 54 | X2=X+fg.*(icol-1); 55 | fill(X2,Y,F(icol, :), 'linestyle', 'none') 56 | hold all 57 | end % icol 58 | text(-0.1, mean(Y), cnames{iname}, 'HorizontalAlignment', 'right', 'FontWeight', 'bold', 'FontSize', 10, 'FontName' , 'AvantGarde') 59 | xlim([-0.4, 1]) 60 | axis off 61 | set(gcf, 'color', [1 1 1]) 62 | ylim([0.1 1.05.*max(Y)]); 63 | end % iname 64 | 65 | -------------------------------------------------------------------------------- /utils/cbrewer/colorbrewer.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/utils/cbrewer/colorbrewer.mat -------------------------------------------------------------------------------- /utils/cbrewer/interpolate_cbrewer.m: -------------------------------------------------------------------------------- 1 | function [interp_cmap]=interpolate_cbrewer(cbrew_init, interp_method, ncolors) 2 | % 3 | % INTERPOLATE_CBREWER - interpolate a colorbrewer map to ncolors levels 4 | % 5 | % INPUT: 6 | % - cbrew_init: the initial colormap with format N*3 7 | % - interp_method: interpolation method, which can be the following: 8 | % 'nearest' - nearest neighbor interpolation 9 | % 'linear' - bilinear interpolation 10 | % 'spline' - spline interpolation 11 | % 'cubic' - bicubic interpolation as long as the data is 12 | % uniformly spaced, otherwise the same as 'spline' 13 | % - ncolors=desired number of colors 14 | % 15 | % Author: Charles Robert 16 | % email: tannoudji@hotmail.com 17 | % Date: 14.10.2011 18 | 19 | 20 | % just to make sure, in case someone puts in a decimal 21 | ncolors=round(ncolors); 22 | 23 | % How many data points of the colormap available 24 | nmax=size(cbrew_init,1); 25 | 26 | % create the associated X axis (using round to get rid of decimals) 27 | a=(ncolors-1)./(nmax-1); 28 | X=round([0 a:a:(ncolors-1)]); 29 | X2=0:ncolors-1; 30 | 31 | z=interp1(X,cbrew_init(:,1),X2,interp_method); 32 | z2=interp1(X,cbrew_init(:,2),X2,interp_method); 33 | z3=interp1(X,cbrew_init(:,3),X2, interp_method); 34 | interp_cmap=round([z' z2' z3']); 35 | 36 | end -------------------------------------------------------------------------------- /utils/cbrewer/plot_brewer_cmap.m: -------------------------------------------------------------------------------- 1 | % Plots and identifies the various colorbrewer tables available. 2 | % Is called by cbrewer.m when no arguments are given. 3 | % 4 | % Author: Charles Robert 5 | % email: tannoudji@hotmail.com 6 | % Date: 14.10.2011 7 | 8 | 9 | 10 | load('colorbrewer.mat') 11 | 12 | ctypes={'div', 'seq', 'qual'}; 13 | ctypes_title={'Diverging', 'Sequential', 'Qualitative'}; 14 | cnames{1,:}={'BrBG', 'PiYG', 'PRGn', 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn', 'Spectral'}; 15 | cnames{2,:}={'Blues','BuGn','BuPu','GnBu','Greens','Greys','Oranges','OrRd','PuBu','PuBuGn','PuRd',... 16 | 'Purples','RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd'}; 17 | cnames{3,:}={'Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2', 'Set1', 'Set2', 'Set3'}; 18 | 19 | figure('position', [314 327 807 420]) 20 | for itype=1:3 21 | 22 | %fh(itype)=figure(); 23 | subplot(1,3,itype) 24 | 25 | for iname=1:length(cnames{itype,:}) 26 | 27 | ncol=length(colorbrewer.(ctypes{itype}).(cnames{itype}{iname})); 28 | fg=1./ncol; % geometrical factor 29 | 30 | X=fg.*[0 0 1 1]; 31 | Y=0.1.*[1 0 0 1]+(2*iname-1)*0.1; 32 | F=cbrewer(ctypes{itype}, cnames{itype}{iname}, ncol); 33 | 34 | for icol=1:ncol 35 | X2=X+fg.*(icol-1); 36 | fill(X2,Y,F(icol, :), 'linestyle', 'none') 37 | text(-0.1, mean(Y), cnames{itype}{iname}, 'HorizontalAlignment', 'right', 'FontWeight', 'bold', 'FontSize', 10, 'FontName' , 'AvantGarde') 38 | xlim([-0.4, 1]) 39 | hold all 40 | end % icol 41 | %set(gca, 'box', 'off') 42 | title(ctypes_title{itype}, 'FontWeight', 'bold', 'FontSize', 16, 'FontName' , 'AvantGarde') 43 | axis off 44 | set(gcf, 'color', [1 1 1]) 45 | end % iname 46 | ylim([0.1 1.05.*max(Y)]); 47 | end %itype 48 | 49 | set(gcf, 'MenuBar', 'none') 50 | set(gcf, 'Name', 'ColorBrewer Color maps') -------------------------------------------------------------------------------- /utils/fdr.m: -------------------------------------------------------------------------------- 1 | % fdr() - compute false detection rate mask 2 | % 3 | % Usage: 4 | % >> [p_fdr, p_masked] = fdr( pvals, alpha); 5 | % 6 | % Inputs: 7 | % pvals - vector or array of p-values 8 | % alpha - threshold value (non-corrected). If no alpha is given 9 | % each p-value is used as its own alpha and FDR corrected 10 | % array is returned. 11 | % fdrtype - ['parametric'|'nonParametric'] FDR type. Default is 12 | % 'parametric'. 13 | % 14 | % Outputs: 15 | % p_fdr - pvalue used for threshold (based on independence 16 | % or positive dependence of measurements) 17 | % p_masked - p-value thresholded. Same size as pvals. 18 | % 19 | % Author: Arnaud Delorme, SCCN, 2008- 20 | % Based on a function by Tom Nichols 21 | % 22 | % Reference: Bejamini & Yekutieli (2001) The Annals of Statistics 23 | 24 | % Copyright (C) 2002 Arnaud Delorme, Salk Institute, arno@salk.edu 25 | % 26 | % This program is free software; you can redistribute it and/or modify 27 | % it under the terms of the GNU General Public License as published by 28 | % the Free Software Foundation; either version 2 of the License, or 29 | % (at your option) any later version. 30 | % 31 | % This program is distributed in the hope that it will be useful, 32 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34 | % GNU General Public License for more details. 35 | % 36 | % You should have received a copy of the GNU General Public License 37 | % along with this program; if not, write to the Free Software 38 | % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 39 | 40 | function [pID, p_masked] = fdr(pvals, q, fdrType); 41 | 42 | if nargin < 3, fdrType = 'parametric'; end; 43 | if isempty(pvals), pID = []; return; end; 44 | p = sort(pvals(:)); 45 | V = length(p); 46 | I = (1:V)'; 47 | 48 | cVID = 1; 49 | cVN = sum(1./(1:V)); 50 | 51 | if nargin < 2 52 | pID = ones(size(pvals)); 53 | thresholds = exp(linspace(log(0.1),log(0.000001), 100)); 54 | for index = 1:length(thresholds) 55 | [tmp p_masked] = fdr(pvals, thresholds(index)); 56 | pID(p_masked) = thresholds(index); 57 | end; 58 | else 59 | if strcmpi(fdrType, 'parametric') 60 | pID = p(max(find(p<=I/V*q/cVID))); % standard FDR 61 | else 62 | pID = p(max(find(p<=I/V*q/cVN))); % non-parametric FDR 63 | end; 64 | end; 65 | if isempty(pID), pID = 0; end; 66 | 67 | if nargout > 1 68 | p_masked = pvals<=pID; 69 | end; 70 | -------------------------------------------------------------------------------- /utils/fisherz.m: -------------------------------------------------------------------------------- 1 | function z=fisherz(r); 2 | 3 | % Z=fisherz(R) 4 | % 5 | % this function performs a fisher Z-transform of vector R and output the 6 | % transformed vector Z. This function is used to modify for example 7 | % correlations in [-1;+1] into a near gaussian population. It could be used 8 | % to transform any uniform population in the interval [-1;+1] into a 9 | % gaussian population. The inverse operation is done by function inverse_fisherz.m 10 | % 11 | % Vincent MORON 12 | % feb. 2005 13 | 14 | z=0.5*log((1+r)./(1-r)); -------------------------------------------------------------------------------- /utils/network_atlases/Lookup_shen268: -------------------------------------------------------------------------------- 1 | 13.9 56.8 -16.6 218 1 1 5 11 2 | 9.6 17.8 -19.5 159 1 1 13 11 3 | 5.1 34.9 -17.4 261 1 1 13 11 4 | 15.6 34.1 -22.6 205 1 1 13 11 5 | 8.2 45.9 -1.7 161 1 2 5 10 6 | 14.6 64.7 3.6 235 1 2 5 10 7 | 30.5 54.9 -3.5 183 1 2 8 10 8 | 44.6 46.2 -4.9 214 1 2 8 10 9 | 28.9 51.1 18.7 149 1 2 9 10 10 | 8.4 53.3 23.9 160 1 3 5 9 11 | 37.6 35.4 31.1 146 1 3 9 9 12 | 14.3 36.9 48.9 154 1 4 5 8 13 | 23.9 30.7 36.4 248 1 4 5 8 14 | 40.7 14.5 48.2 221 1 4 8 8 15 | 6.7 21.4 31.5 202 1 4 9 8 16 | 53.6 24.8 0.9 197 1 5 11 47 17 | 33.4 37.3 -16.4 139 1 5 13 47 18 | 26.6 19.6 -21.3 224 1 5 13 47 19 | 48.3 35.7 15.1 185 1 6 8 46 20 | 37 20.8 5.9 140 1 7 9 45 21 | 55.4 9.6 22.2 190 1 8 8 44 22 | 40 17.6 29.2 239 1 8 8 44 23 | 57.8 -8.3 27.3 211 2 12 1 4 24 | 6 -22.3 65.6 166 2 13 1 6 25 | 7 -8.1 52.9 137 2 13 1 6 26 | 26.3 -12.9 66.2 152 2 13 1 6 27 | 49.2 -4.5 48.1 240 2 13 1 6 28 | 6.1 14 48.7 213 2 13 3 6 29 | 13.7 6.3 65.4 162 2 13 3 6 30 | 25.2 12.4 49.4 188 2 13 8 6 31 | 39.7 3.4 34 168 2 13 8 6 32 | 32 -5.4 52.1 256 2 13 12 6 33 | 42 -23.4 53.4 184 2 23 1 1 34 | 41.8 5 -7.6 176 3 9 3 13 35 | 41.4 3.5 7.2 138 3 9 3 13 36 | 37.5 21.1 -10.1 187 3 9 9 13 37 | 38.3 -12.5 -1.1 260 3 9 10 13 38 | 32.4 -39.2 49.6 249 4 23 1 1 39 | 20 -33.2 69.8 241 4 23 1 1 40 | 43.3 -10.8 13.9 266 4 23 1 1 41 | 25.2 -52.4 68.1 192 4 26 1 7 42 | 14.8 -68.4 34.9 244 4 26 5 7 43 | 31.6 -60.8 49.2 195 4 26 8 7 44 | 7.5 -57.3 61.8 225 4 26 12 7 45 | 52.8 -27.2 40.9 234 4 27 1 40 46 | 58 -29.3 19.5 169 4 27 4 40 47 | 54.2 -45.2 36.9 136 4 27 9 40 48 | 47.8 -61.6 34.7 251 4 28 5 39 49 | 41.4 -75.3 28 216 4 28 5 39 50 | 48.9 -58.1 14.4 198 4 28 12 39 51 | 27.2 11.6 -39.2 242 5 14 5 38 52 | 40 18.9 -34.2 148 5 14 5 38 53 | 52.8 10.9 -21.8 263 5 14 5 38 54 | 50 -33.8 -0.7 178 5 15 11 21 55 | 61.3 -22.9 -22.4 189 5 15 13 21 56 | 54.5 -7.7 -31.5 175 5 16 13 20 57 | 46.8 4 -39.8 191 5 16 13 20 58 | 40.3 -11.3 -35.8 206 5 16 13 20 59 | 43.4 -26.5 -24.6 229 5 16 13 20 60 | 31.5 0.7 -44.4 145 5 16 13 20 61 | 59.2 -3.4 2.7 155 5 17 4 41 62 | 39.9 -25.6 14.4 231 5 17 4 41 63 | 61.8 -23.8 -2.8 210 5 19 5 22 64 | 56.5 -8.5 -14.3 174 5 19 5 22 65 | 59.3 -43.8 8.5 237 5 19 11 22 66 | 46.5 -59.9 -14.8 220 5 22 7 37 67 | 36.4 -69.1 -17.5 223 5 22 7 37 68 | 25.2 -44.6 -12.2 227 5 22 7 37 69 | 55.2 -56.3 -4.8 135 5 22 8 37 70 | 60.8 -43.3 -17.6 201 5 22 8 37 71 | 41.6 -45.7 -22.6 246 5 22 13 37 72 | 21 -63.7 -9 163 6 39 7 19 73 | 30.1 -82.9 20.5 157 6 39 7 19 74 | 45.1 -74.3 2.6 267 6 39 7 19 75 | 18.9 -81.8 41.5 222 6 39 7 19 76 | 17.9 -83.4 -11.3 167 6 40 7 18 77 | 7.7 -75 25 262 6 40 7 18 78 | 23.7 -96 6.5 141 6 40 7 18 79 | 7 -75.7 -2.8 232 6 40 7 18 80 | 7.8 -88.6 11.9 153 6 40 7 18 81 | 31.2 -91.8 -10.8 253 6 40 13 18 82 | 14.6 -68.3 8.3 143 6 41 7 17 83 | 7.8 34.7 17.1 151 7 31 5 32 84 | 5.3 -1 35.6 179 7 32 1 24 85 | 5.1 -38.9 27 265 7 33 5 23 86 | 12.3 -57.2 18.1 209 7 33 5 23 87 | 28.4 -53.8 7.1 204 7 33 7 23 88 | 7 -18.8 29.8 257 7 33 13 23 89 | 7.8 -23.1 44.9 147 7 34 1 31 90 | 6.2 -57.4 38.2 264 7 34 5 31 91 | 8.3 -39.9 48.1 196 7 34 9 31 92 | 31.2 3.7 -21.6 186 7 36 13 53 93 | 28.8 -36.9 -0 230 7 37 5 54 94 | 35.6 -14.7 -18.4 219 7 37 13 54 95 | 28 -28.4 -13.7 228 7 38 5 36 96 | 29.3 -19.6 -26.3 164 7 38 13 36 97 | 24.6 -2.6 -30.7 194 7 38 13 36 98 | 14.6 -46.1 2.8 142 7 40 7 18 99 | 19.3 -7.7 -14.8 226 7 49 13 58 100 | 32.2 -78.5 -40.4 217 8 48 5 57 101 | 6.1 -50.7 -12.3 180 8 48 7 57 102 | 39.1 -74.9 -29.7 247 8 48 13 57 103 | 13.7 -40.1 -25.4 233 8 48 13 57 104 | 23.5 -35.9 -43 156 8 48 13 57 105 | 6.9 -67.9 -37.8 255 8 48 13 57 106 | 7.1 -69 -20.9 236 8 48 13 57 107 | 46 -46.5 -42.4 144 8 48 13 57 108 | 16.2 -47.2 -52.3 150 8 48 13 57 109 | 23.4 -59.3 -52.1 203 8 48 13 57 110 | 21.1 -54.8 -23.8 259 8 48 13 57 111 | 11.7 -84.1 -34.6 193 8 48 13 57 112 | 19.6 -73.5 -50 208 8 48 13 57 113 | 36.7 -57.1 -32.8 258 8 48 13 57 114 | 23 -71.8 -29.1 215 8 48 13 57 115 | 7.6 -56.7 -50.8 182 8 48 13 57 116 | 41.9 -64 -49.2 181 8 48 13 57 117 | 7.1 -53.7 -34.4 170 8 48 13 57 118 | 33.8 -47.2 -53.9 171 8 48 13 57 119 | 30.4 -36.4 -31.1 172 8 48 13 57 120 | 21.2 -36.4 22.6 252 9 0 5 0 121 | 12.7 12.9 11.5 250 9 42 10 48 122 | 13.7 -4.2 20.9 243 9 42 10 48 123 | 12.6 20.2 -0.7 173 9 42 10 48 124 | 26.6 6.3 0.1 158 9 43 10 49 125 | 14 8.3 -9.5 207 9 43 10 49 126 | 10.5 -26.8 -2.2 200 9 44 10 50 127 | 12.3 -27.7 13.5 199 9 44 10 50 128 | 5.5 -9.7 5.2 238 9 44 10 50 129 | 4.7 -37.2 -53 254 10 49 13 58 130 | 9.7 -18.7 -30.7 245 10 49 13 58 131 | 6 -22.2 -42.3 177 10 49 13 58 132 | 6.3 -24.9 -17.5 165 10 49 13 58 133 | 7.5 -34.2 -37.3 212 10 49 13 58 134 | -5.4 29.1 -10.1 27 11 1 5 11 135 | -18.2 19 -21 47 11 1 13 11 136 | -5.8 18.2 -21.6 42 11 1 13 11 137 | -8.2 39.7 -21.4 96 11 1 13 11 138 | -6.9 48.3 -5.7 57 11 2 5 10 139 | -18.2 57 -14.3 6 11 2 5 10 140 | -6 48.1 11.7 123 11 2 5 10 141 | -11.7 65.1 4.2 121 11 2 5 10 142 | -29.2 54.3 2.5 45 11 2 8 10 143 | -42.7 47.3 -6.9 99 11 2 8 10 144 | -28.8 50.1 21.7 75 11 2 9 10 145 | -10.1 55.7 30.2 36 11 3 5 9 146 | -27.3 34.1 36.4 122 11 3 5 9 147 | -46.1 28.2 26.8 64 11 3 8 9 148 | -11.2 34.3 51.5 0 11 4 5 8 149 | -39.3 17.2 46.7 131 11 4 5 8 150 | -5 17.7 46.1 119 11 4 9 8 151 | -46.2 28.2 -7.1 2 11 5 5 47 152 | -28.4 36 -15.6 92 11 5 13 47 153 | -32 20.5 -16 53 11 5 13 47 154 | -43 42 11 26 11 6 8 46 155 | -32.5 22.1 5.8 14 11 7 9 45 156 | -53.1 18.4 10.6 105 11 8 8 44 157 | -46.2 7.9 28.6 81 11 13 8 6 158 | -41.6 -14.7 44.8 98 12 12 1 4 159 | -58.1 -5.6 27.2 20 12 13 1 6 160 | -16.2 -19.2 69.5 28 12 13 1 6 161 | -6.5 -4.3 47.6 13 12 13 3 6 162 | -9.1 0.4 66.5 38 12 13 3 6 163 | -57 -3.4 6.8 112 12 13 4 6 164 | -23.2 10.7 53.6 49 12 13 8 6 165 | -45.8 -0.4 49.3 54 12 13 8 6 166 | -27.6 -9.1 55.9 107 12 13 12 6 167 | -35.9 -23.3 65.6 79 12 23 1 1 168 | -39.1 1.7 9.5 59 13 9 3 13 169 | -38.7 8.1 -4.8 94 13 9 3 13 170 | -37.7 -12.9 -1.4 117 13 9 10 13 171 | -50.6 -23.8 41.4 4 14 23 1 1 172 | -23.5 -31.6 63.6 8 14 23 1 1 173 | -41.2 -15.6 14.5 63 14 23 4 1 174 | -7.4 -34.1 67.5 23 14 26 1 7 175 | -25.4 -54.7 64 74 14 26 1 7 176 | -9.5 -71 31.9 86 14 26 7 7 177 | -28.4 -62.3 40.4 62 14 26 12 7 178 | -9.8 -66.3 55.1 19 14 26 13 7 179 | -35.7 -39.3 47.7 34 14 27 1 40 180 | -42.2 -31.2 15.9 89 14 27 4 40 181 | -59.5 -25.9 21.9 124 14 27 4 40 182 | -42 -65.6 41.7 127 14 28 5 39 183 | -51.4 -56.3 20.5 90 14 28 5 39 184 | -53.4 -43.5 38.8 44 14 28 8 39 185 | -38 6.1 -37.9 128 15 14 5 38 186 | -34.6 18.6 -32.2 43 15 14 5 38 187 | -49.5 11.1 -30.6 7 15 14 5 38 188 | -49.7 6.4 -15.2 55 15 14 5 38 189 | -22.9 9 -38.8 33 15 14 13 38 190 | -57.6 -6.4 -22.7 60 15 15 5 21 191 | -59 -30 3.5 9 15 15 5 21 192 | -57.8 -47.5 5.2 100 15 15 11 21 193 | -59.8 -27.4 -18.1 37 15 15 13 21 194 | -49.3 -4.7 -37.4 35 15 16 13 20 195 | -37.8 -13.2 -29.3 84 15 16 13 20 196 | -51.8 -18.2 -28.8 40 15 16 13 20 197 | -57 -14.5 -6.9 16 15 19 5 22 198 | -26.7 -42.7 -16.1 66 15 22 5 37 199 | -60.3 -50 -14 101 15 22 13 37 200 | -42.6 -52.1 -17.4 80 15 22 13 37 201 | -46.7 -40 -24.3 88 15 22 13 37 202 | -30 -5.8 -40.9 93 15 38 13 36 203 | -41.2 -75.4 22.8 108 16 39 5 19 204 | -31.6 -87.2 12.5 41 16 39 7 19 205 | -17 -50.7 0.8 50 16 39 7 19 206 | -43.2 -70.4 -13.8 22 16 39 7 19 207 | -25.9 -63.1 -12.3 32 16 39 7 19 208 | -16.8 -84.9 33 115 16 39 7 19 209 | -48.3 -67.4 1.1 103 16 39 12 19 210 | -36 -84.2 -3.9 30 16 40 7 18 211 | -8.9 -70.7 -1.7 71 16 40 7 18 212 | -10.8 -98.1 7.6 17 16 40 7 18 213 | -14.7 -84 -13.1 77 16 40 13 18 214 | -22.3 -96.6 -10.1 21 16 40 13 18 215 | -6 -81.2 12.2 24 16 41 7 17 216 | -22.1 -66.7 7.4 134 16 41 7 17 217 | -23.6 -41.3 19.9 58 17 0 4 0 218 | -7.8 -22.4 46 126 17 13 1 6 219 | -6 34.1 26.3 46 17 31 5 32 220 | -3.8 -5 32.6 118 17 32 3 24 221 | -5.1 13.2 28.7 125 17 32 3 24 222 | -8.6 -58.8 17.6 29 17 33 5 23 223 | -5 -36 32 85 17 33 13 23 224 | -7.4 -18.2 30 82 17 33 13 23 225 | -6.5 -53.9 37.4 5 17 34 5 31 226 | -8.8 -42.6 50.1 78 17 34 5 31 227 | -7.5 -42.1 13.3 133 17 35 5 30 228 | -26.8 2.4 -18.7 11 17 36 13 53 229 | -21.5 -36.9 5.7 56 17 37 5 54 230 | -32.1 -40.2 -4 95 17 37 5 54 231 | -22.7 -12.8 -17.4 87 17 37 13 54 232 | -35.7 -24.8 -14.9 76 17 37 13 54 233 | -20.7 -30.8 -11.1 104 17 38 5 36 234 | -30.5 -23.9 -26.6 67 17 38 13 36 235 | -21.4 -4.1 -29.4 109 17 38 13 36 236 | -6.5 -66.2 -37.7 12 18 48 13 57 237 | -8.7 -50.6 -39.6 120 18 48 13 57 238 | -37 -52.9 -31.1 10 18 48 13 57 239 | -8.7 -55.2 -52.1 129 18 48 13 57 240 | -21.2 -70 -48.9 15 18 48 13 57 241 | -40.3 -74.2 -29.1 3 18 48 13 57 242 | -30.2 -80.2 -40.3 1 18 48 13 57 243 | -19.3 -46.4 -53.2 106 18 48 13 57 244 | -6.5 -50.2 -11.4 61 18 48 13 57 245 | -27.8 -36 -30.9 65 18 48 13 57 246 | -42.6 -63.7 -46.3 68 18 48 13 57 247 | -10.3 -81.7 -32.3 69 18 48 13 57 248 | -8 -68.4 -19.9 70 18 48 13 57 249 | -34.6 -50.3 -54 48 18 48 13 57 250 | -22.7 -57.9 -48.8 73 18 48 13 57 251 | -10.3 -37.7 -25.1 39 18 48 13 57 252 | -46.4 -46.8 -42.9 83 18 48 13 57 253 | -26.3 -69.5 -30.6 91 18 48 13 57 254 | -21.2 -53.4 -23.6 31 18 48 13 57 255 | -6.6 -54.7 -26.3 97 18 48 13 57 256 | -24.3 -37.8 -44.3 102 18 48 13 57 257 | -10.8 23.9 9.6 130 19 0 9 0 258 | -12.5 11.6 8.7 111 19 42 10 48 259 | -10.4 10.9 -8.1 52 19 42 10 48 260 | -14.6 -3.5 21.1 25 19 42 10 48 261 | -24.8 5.6 -0.1 132 19 43 10 49 262 | -9.6 -25.4 -1.4 116 19 44 10 50 263 | -4.9 -10.3 5.8 113 19 44 10 50 264 | -11.6 -25.6 14.8 51 19 44 10 50 265 | -5 -21.5 -15.8 18 20 49 10 58 266 | -4.5 -38 -53.1 114 20 49 13 58 267 | -7.2 -33 -39.4 72 20 49 13 58 268 | -6.1 -18.9 -36.8 110 20 49 13 58 269 | -------------------------------------------------------------------------------- /utils/network_atlases/Schaefer2018_300Parcels_17Networks_order_FSLMNI152_2mm.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/utils/network_atlases/Schaefer2018_300Parcels_17Networks_order_FSLMNI152_2mm.nii -------------------------------------------------------------------------------- /utils/network_atlases/Schaefer2018_300Parcels_7Networks_order_FSLMNI152_2mm.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/utils/network_atlases/Schaefer2018_300Parcels_7Networks_order_FSLMNI152_2mm.nii -------------------------------------------------------------------------------- /utils/network_atlases/Schaefer_label300_17networks.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/utils/network_atlases/Schaefer_label300_17networks.mat -------------------------------------------------------------------------------- /utils/network_atlases/Schaefer_label300_7networks.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/utils/network_atlases/Schaefer_label300_7networks.mat -------------------------------------------------------------------------------- /utils/network_atlases/shen_2mm_268_parcellation.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swglab/CPM_CONN/915af8fb610b0bcfca1eac8c8bfdeef26ccb55e5/utils/network_atlases/shen_2mm_268_parcellation.nii --------------------------------------------------------------------------------