Brain-fingerprinting

Authors: Jason da Silva Castanheira, Raymundo Cassani

This tutorial introduces the concept of neurophysiological brain-fingerprinting and its implementation in Brainstorm. To follow this tutorial, please first complete the OMEGA tutorial as we will derive the brain-fingerprints of its five participants.

Introduction

Brain-fingerprinting is a method to assess inter-individual differences in brain activity. It was first proposed by Finn and colleagues in 2015. This tutorial will derive spectral brain-fingerprints using neural power spectra at computed within each parcel of the Destrieux atlas. Once the individuals' brain-fingerprints have been obtained, differentiation accuracy and differentiability are computed for the cohort. Finally, we analyze relative contribution of each of the cortical parcels (i.e., brain regions) and frequency bins to participant differentiation


This demonstration uses the pre-processed data from five participants obtained from the outputs of the OMEGA tutorial. Please run the entire tutorial before using the tutorial_brain_fingerprint.m script (shown at the end of this page).

Preparing the data for brain-fingerprinting

The brain-fingerprint of an individual can be derived from functional connectomes or neural power spectrum, as detailed in da Silva Castanheira et al., 2021. Note that this is not an exhaustive list of all possible neurophysiological features that can be used to define brain-fingerprints.

From the estimated surface source maps, we compute the power spectrum density (i.e., PSD) using the Welch method at every vertex of the cortical surface, and average the resulting spectra within each region defined by the Destrieux atlas (see Scout page for more details). Note, this is done to downsample the spatial features of the brain-fingerprint. If we did not downsample the PSD to a cortical atlas, the resulting feature space would be too large to work with (e.g., 15,000 vertices × 300 frequency bins). The choice of atlas and neurophysiological features (e.g., functional connectomes vs power spectra) to define the brain-fingerprint is dependent on the user's specific hypotheses. See the section of the script entitled Compute PSD for all ROIs of an atlas

Brain-fingerprinting requires at least two data segments for every individual. This can be two separate recordings (i.e., between-session fingerprinting), or two segments within the same recording session (i.e., within-session fingerprinting). For this demonstration, we will split the MEG recordings of the OMEGA tutorial into two parts (data segments). As such, for each participant, there will be two brain-fingerprints (b-fp1 and b-fp2), each consisting of a vector of nParcellations×nFrequencies elements. See the image below for a summary of the pipeline:

AlternativeText

The brain-fingerprinting method

The brain-fingerprinting method is based on the correlational similarity of participants across data segments (see image above). For each participant in a given cohort, we compute the Pearson correlation coefficient between the brain-fingerprint of the first segment and second segment of all participants in the cohort, including the probe participant. This yields a participant similarity matrix, where off-diagonal elements represent the similarity of a participant to all other participants and diagonal elements represent the similarity of a participant's brain-fingerprint across data segments (i.e., similarity to their own brain-fingerprint). See the image below for an example participant similarity matrix.

Participant differentiation consists of a lookup procedure along the rows (or columns) of the participant similarity matrix. A participant is said to be correctly differentiated if a participant's brain-fingerprint is more similar to themselves (self-similarity, also referred to as Iself) than all other participants in the cohort (other-similarity, also referred to as Iothers). In other words, if the brain-fingerprint of participant i is most similar to their brain-fingerprint taken at the second time point, this participant is said to be correctly differentiated.

Differentiation accuracy

Differentiation accuracy represents the percent ratio of the number of participants correctly differentiated across the cohort (i.e., differentiation accuracy). Brain-fingerprinting is typically repeated for all possible pairs of data segments. In the case of this tutorial, there are only two data segments, the first and second half of the recording. We therefore obtain two differentiation accuracies along the rows and columns of the participant similarity matrix respectively. In the case where three data segments are available, we can compute six differentiation accuracies: the accuracy for the columns and rows of data segment 1 vs segment 2, and for each possible pair of recordings (i.e., data segment 2 vs 3 and data segment 1 vs 3).

Differentiability

Differentiability is a measure which describes how easily a given participant is to differentiate from a cohort of individuals. This measure consists of scaling (z-scoring) the self-similarity of brain-fingerprints against the other-similarity (off-diagonal elements). A participant with a high differentiability score will have a higher self-similarity relative to their similarity to others in the cohort (other-similarity) and therefore are easily differentiated (see the last row in the example participant similarity matrix below). In contrast, a participant whose brain-fingerprint is most similar to others in the cohort will be more challenging to differentiate (see the second row of the participant similarity matrix below). AlternativeText

Note that other measures to quantify the relative easy of differentiating a participant exist: Idiff represents the difference between Iself and Iothers. See Amico & Goñi 2018 and Sareen at el., 2021.

The participant similarity matrix is generally symmetric (although it does not necessarily have to be). This implies that the differentiability across rows and columns are generally strongly correlated, as such, the participant differentiability can be computed as the mean of these two per participant

Quantifying the most salient features of the brain-fingerprint

Beyond differentiation accuracy and differentiability, we can quantify the relative contribution of cortical parcels (i.e., brain regions) and frequency bins to participant differentiation.

To do so, we calculated intraclass correlations (ICC). ICC quantifies the ratio of within-participant variance and between-participant variance, with participants as their own raters across data segments (see Amico et al., 2018 & da Silva Castanheira et al., 2021 for details). Features that contribute the most to participant differentiation should be highly consistent within individuals, but show great inter-individual variance. Larger values of ICC indicate that a neurophysiological feature (e.g., region of interest or frequency band) contributes more to participant differentiation than smaller values.

See the subsection entitled IntraClass Correlations (ICC) under the section SIMILARITY AND DIFFERENTIABILITY in the script.

In this tutorial we plot the average ICC value per cortical parcel within each frequency band of interest as defined in the script. See image below:

% Bands for ICC cortex plot
BandNames = {'theta', 'alpha', 'beta', 'gamma', 'highgamma'};
BandLowerFreqs = [ 4,  8, 13, 30,  50]; % Hz, inclusive
BandUpperFreqs = [ 8, 13, 30, 50, 150]; % Hz, exclusive

In the Brainstorm database, the ICC values are saved: as (i) Matrix files (which can be exported to tabular files) and, as (ii) cortical maps (which allow to visualize their spatial distribution). Both set of files are found in the Group analysis folder. The image below presents the database (left), and ICC values for theta band, as cortical maps (center), and as matrix (right).

AlternativeText

Applications of the brain-fingerprint

Beyond biometric differentiation, brain-fingerprints advance the neurobiological origins of individual traits and inform clinical. Below we summarize some of the most recent applications of brain-fingerprints.

Additional documentation

Please cite previous work on brain-fingerprinting:

Further reading:

Tutorials

Scripting

The following script from the Brainstorm distribution reproduces the analysis presented in this tutorial page: brainstorm3/toolbox/script/tutorial_brain_fingerprint.m

1 function tutorial_brain_fingerprint(ProtocolNameOmega, reports_dir) 2 % TUTORIAL_BRAIN_FINGERPRINT: Script that reproduces the results of the online tutorial "Brain-fingerprint". 3 % 4 % CORRESPONDING ONLINE TUTORIAL: 5 % https://neuroimage.usc.edu/brainstorm/Tutorials/BrainFingerprint 6 % 7 % INPUTS: 8 % - ProtocolNameOmega : Name of the protocol created with all the data imported (TutorialOmega) 9 % - reports_dir : Directory where to save the execution report (instead of displaying it) 10 % 11 % @============================================================================= 12 % This function is part of the Brainstorm software: 13 % https://neuroimage.usc.edu/brainstorm 14 % 15 % Copyright (c) University of Southern California & McGill University 16 % This software is distributed under the terms of the GNU General Public License 17 % as published by the Free Software Foundation. Further details on the GPLv3 18 % license can be found at http://www.gnu.org/copyleft/gpl.html. 19 % 20 % FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE 21 % UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY 22 % WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF 23 % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY 24 % LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. 25 % 26 % For more information type "brainstorm license" at command prompt. 27 % =============================================================================@ 28 % 29 % Author: Jason da Silva Castanheira, Raymundo Cassani, 2024 30 31 32 %% ===== CHECK PROTOCOL ===== 33 % Start brainstorm without the GUI 34 if ~brainstorm('status') 35 brainstorm nogui 36 end 37 % Output folder for reports 38 if (nargin < 2) || isempty(reports_dir) || ~isdir(reports_dir) 39 reports_dir = []; 40 end 41 % You have to specify the folder in which the tutorial dataset is unzipped 42 if (nargin < 1) || isempty(ProtocolNameOmega) 43 ProtocolNameOmega = 'TutorialOmega'; 44 end 45 46 47 %% ===== BRAIN-FINGERPRINT PARAMETERS ===== 48 % Subjects 49 SubjectNames = {'sub-0002', 'sub-0003', 'sub-0004', 'sub-0006', 'sub-0007'}; 50 nSubjects = length(SubjectNames); 51 % Frequency range 52 LowerFreq = 4; % Hz, inclusive 53 UpperFreq = 150; % Hz, exclusive 54 % Cortical parcellation (atlas) 55 % Note we downsample the cortical surface using an atlas for computation efficiency 56 AtlasName = 'Destrieux'; 57 AtlasScouts = {'G_Ins_lg_and_S_cent_ins L', 'G_Ins_lg_and_S_cent_ins R', 'G_and_S_cingul-Ant L', 'G_and_S_cingul-Ant R', 'G_and_S_cingul-Mid-Ant L', 'G_and_S_cingul-Mid-Ant R', 'G_and_S_cingul-Mid-Post L', 'G_and_S_cingul-Mid-Post R', 'G_and_S_frontomargin L', 'G_and_S_frontomargin R', 'G_and_S_occipital_inf L', 'G_and_S_occipital_inf R', 'G_and_S_paracentral L', 'G_and_S_paracentral R', 'G_and_S_subcentral L', 'G_and_S_subcentral R', 'G_and_S_transv_frontopol L', 'G_and_S_transv_frontopol R', 'G_cingul-Post-dorsal L', 'G_cingul-Post-dorsal R', 'G_cingul-Post-ventral L', 'G_cingul-Post-ventral R', 'G_cuneus L', 'G_cuneus R', 'G_front_inf-Opercular L', 'G_front_inf-Opercular R', 'G_front_inf-Orbital L', 'G_front_inf-Orbital R', 'G_front_inf-Triangul L', 'G_front_inf-Triangul R', 'G_front_middle L', 'G_front_middle R', 'G_front_sup L', 'G_front_sup R', 'G_insular_short L', 'G_insular_short R', 'G_oc-temp_lat-fusifor L', 'G_oc-temp_lat-fusifor R', 'G_oc-temp_med-Lingual L', 'G_oc-temp_med-Lingual R', 'G_oc-temp_med-Parahip L', 'G_oc-temp_med-Parahip R', 'G_occipital_middle L', 'G_occipital_middle R', 'G_occipital_sup L', 'G_occipital_sup R', 'G_orbital L', 'G_orbital R', 'G_pariet_inf-Angular L', 'G_pariet_inf-Angular R', 'G_pariet_inf-Supramar L', 'G_pariet_inf-Supramar R', 'G_parietal_sup L', 'G_parietal_sup R', 'G_postcentral L', 'G_postcentral R', 'G_precentral L', 'G_precentral R', 'G_precuneus L', 'G_precuneus R', 'G_rectus L', 'G_rectus R', 'G_subcallosal L', 'G_subcallosal R', 'G_temp_sup-G_T_transv L', 'G_temp_sup-G_T_transv R', 'G_temp_sup-Lateral L', 'G_temp_sup-Lateral R', 'G_temp_sup-Plan_polar L', 'G_temp_sup-Plan_polar R', 'G_temp_sup-Plan_tempo L', 'G_temp_sup-Plan_tempo R', 'G_temporal_inf L', 'G_temporal_inf R', 'G_temporal_middle L', 'G_temporal_middle R', 'Lat_Fis-ant-Horizont L', 'Lat_Fis-ant-Horizont R', 'Lat_Fis-ant-Vertical L', 'Lat_Fis-ant-Vertical R', 'Lat_Fis-post L', 'Lat_Fis-post R', 'Pole_occipital L', 'Pole_occipital R', 'Pole_temporal L', 'Pole_temporal R', 'S_calcarine L', 'S_calcarine R', 'S_central L', 'S_central R', 'S_cingul-Marginalis L', 'S_cingul-Marginalis R', 'S_circular_insula_ant L', 'S_circular_insula_ant R', 'S_circular_insula_inf L', 'S_circular_insula_inf R', 'S_circular_insula_sup L', 'S_circular_insula_sup R', 'S_collat_transv_ant L', 'S_collat_transv_ant R', 'S_collat_transv_post L', 'S_collat_transv_post R', 'S_front_inf L', 'S_front_inf R', 'S_front_middle L', 'S_front_middle R', 'S_front_sup L', 'S_front_sup R', 'S_interm_prim-Jensen L', 'S_interm_prim-Jensen R', 'S_intrapariet_and_P_trans L', 'S_intrapariet_and_P_trans R', 'S_oc-temp_lat L', 'S_oc-temp_lat R', 'S_oc-temp_med_and_Lingual L', 'S_oc-temp_med_and_Lingual R', 'S_oc_middle_and_Lunatus L', 'S_oc_middle_and_Lunatus R', 'S_oc_sup_and_transversal L', 'S_oc_sup_and_transversal R', 'S_occipital_ant L', 'S_occipital_ant R', 'S_orbital-H_Shaped L', 'S_orbital-H_Shaped R', 'S_orbital_lateral L', 'S_orbital_lateral R', 'S_orbital_med-olfact L', 'S_orbital_med-olfact R', 'S_parieto_occipital L', 'S_parieto_occipital R', 'S_pericallosal L', 'S_pericallosal R', 'S_postcentral L', 'S_postcentral R', 'S_precentral-inf-part L', 'S_precentral-inf-part R', 'S_precentral-sup-part L', 'S_precentral-sup-part R', 'S_suborbital L', 'S_suborbital R', 'S_subparietal L', 'S_subparietal R', 'S_temporal_inf L', 'S_temporal_inf R', 'S_temporal_sup L', 'S_temporal_sup R', 'S_temporal_transverse L', 'S_temporal_transverse R'}; 58 % Bands for ICC cortex plot 59 BandNames = {'theta', 'alpha', 'beta', 'gamma', 'highgamma'}; 60 BandLowerFreqs = [ 4, 8, 13, 30, 50]; % Hz, inclusive 61 BandUpperFreqs = [ 8, 13, 30, 50, 150]; % Hz, exclusive 62 63 %% ===== VERIFY REQUIRED PROTOCOL ===== 64 % Check Protocol that it exists 65 iProtocolOmega = bst_get('Protocol', ProtocolNameOmega); 66 if isempty(iProtocolOmega) 67 error(['Unknown protocol: ' ProtocolNameOmega]); 68 end 69 % Select input protocol 70 gui_brainstorm('SetCurrentProtocol', iProtocolOmega); 71 72 % Verify the Subjects 73 ProtocolSubjects = bst_get('ProtocolSubjects'); 74 ProtocolSubjectNames = {ProtocolSubjects.Subject.Name}; 75 if ~all(ismember(SubjectNames, ProtocolSubjectNames)) 76 error(['All requested subjects must be present in the ' ProtocolNameOmega ' protocol.']); 77 end 78 79 80 %% ===== FIND FILES ===== 81 bst_report('Start'); 82 83 % Get raw and source files for each Subject 84 sRawDataFiles = []; 85 sSourcesFiles = []; 86 87 for iSubject = 1 : nSubjects 88 % Process: Select data files in: sub-000*/* 89 sFiles = bst_process('CallProcess', 'process_select_files_data', [], [], ... 90 'subjectname', SubjectNames{iSubject}, ... 91 'condition', '', ... 92 'tag', '', ... 93 'includebad', 0, ... 94 'includeintra', 0, ... 95 'includecommon', 0); 96 sRawDataFiles = [sRawDataFiles, sFiles]; 97 98 % Process: Select results files in: sub-000*/* 99 sFiles = bst_process('CallProcess', 'process_select_files_results', [], [], ... 100 'subjectname', SubjectNames{iSubject}, ... 101 'condition', '', ... 102 'tag', '', ... 103 'includebad', 0, ... 104 'includeintra', 0, ... 105 'includecommon', 0); 106 sSourcesFiles = [sSourcesFiles, sFiles]; 107 end 108 109 110 %% Compute PSD for all ROIs of an atlas 111 % For each subject, their recordings are split in two parts (data segments) 112 % these two data segments will be used to create PSDs 113 % These two PSDs are the features which will define the brain-fingerprint 114 115 nSegments = 2; % Training and Validation 116 timeIni = zeros(nSubjects, nSegments); 117 timeFin = zeros(nSubjects, nSegments); 118 sPsdFiles = repmat(db_template('processfile'), nSubjects, nSegments); 119 for iSubject = 1 : nSubjects 120 sData = load(file_fullpath(sRawDataFiles(iSubject).FileName), 'Time'); 121 halfTime = diff(sData.Time) / 2; 122 % First segment 123 timeIni(iSubject, 1) = sData.Time(1) + 30; 124 timeFin(iSubject, 1) = halfTime - 30; 125 % Second segment 126 timeIni(iSubject, 2) = halfTime + 30; 127 timeFin(iSubject, 2) = sData.Time(2) - 30; 128 % Compute PSD 129 for iSegment = 1 : size(timeIni, 2) 130 % Process: Power spectrum density (Welch) 131 sPsdFiles(iSubject, iSegment) = bst_process('CallProcess', 'process_psd', sSourcesFiles(iSubject).FileName, [], ... 132 'timewindow', [timeIni(iSubject, iSegment), timeFin(iSubject, iSegment)], ... 133 'win_length', 2, ... 134 'win_overlap', 50, ... 135 'units', 'physical', ... % Physical: U2/Hz 136 'clusters', {AtlasName, AtlasScouts}, ... 137 'scoutfunc', 1, ... % Mean 138 'win_std', 0, ... 139 'edit', struct(... 140 'Comment', 'Scouts,Power', ... 141 'TimeBands', [], ... 142 'Freqs', [], ... 143 'ClusterFuncTime', 'before', ... 144 'Measure', 'power', ... 145 'Output', 'all', ... 146 'SaveKernel', 0)); 147 end 148 end 149 150 151 %% ===== VECTORIZE PSD DATA FOR FINGERPRINTING ===== 152 % Find size of requested PSD data 153 sPsdMat = in_bst_timefreq(sPsdFiles(1,1).FileName, 0, 'RowNames', 'Freqs'); 154 Freqs = sPsdMat.Freqs; 155 ixLowerFreq = find(Freqs >= LowerFreq, 1, 'first'); 156 ixUpperFreq = find(Freqs < UpperFreq, 1, 'last'); 157 Freqs = sPsdMat.Freqs(ixLowerFreq:ixUpperFreq); 158 nFreqs = (ixUpperFreq - ixLowerFreq + 1); 159 ScoutNames = sPsdMat.RowNames; 160 nScouts = length(ScoutNames); 161 162 % Subject vectors 163 trainingVectors = zeros(iSubject, nScouts * nFreqs); 164 validationVectors = zeros(iSubject, nScouts * nFreqs); 165 166 % Vectorize Scout PSDs 167 for iSubject = 1 : nSubjects 168 for iSegment = 1 : nSegments 169 sPsdMat = in_bst_timefreq(sPsdFiles(iSubject, iSegment).FileName, 0, 'TF'); 170 if iSegment == 1 171 trainingVectors(iSubject,:) = reshape(squeeze(sPsdMat.TF(:, :, ixLowerFreq:ixUpperFreq)), 1, []); 172 elseif iSegment == 2 173 validationVectors(iSubject,:) = reshape(squeeze(sPsdMat.TF(:, :, ixLowerFreq:ixUpperFreq)), 1, []); 174 end 175 end 176 end 177 178 179 %% ==== SIMILARITY AND DIFFERENTIABILITY ===== 180 % Subject similarity matrix 181 % It is generally symmetric although it does not necessarily have to be! 182 SubjectCorrMatrix= corr(trainingVectors', validationVectors'); 183 % Differentiability 184 diff_1= (diag(SubjectCorrMatrix)-mean(SubjectCorrMatrix,1) )/ std(SubjectCorrMatrix,0,1); % along columns 185 diff_2= (diag(SubjectCorrMatrix)-mean(SubjectCorrMatrix,2)')/ std(SubjectCorrMatrix,0,2)'; % along rows 186 % Differentiability across rows and columns are generally strongly correlated 187 % Take the mean for a summary statistic per participant 188 Differentiability = (diff_1 + diff_2)/2; % Mean differentiability derived from rows and columns 189 190 % IntrClass Correlations (ICC) 191 zTraining = (trainingVectors - mean(trainingVectors, 2)) ./ std(trainingVectors, 0, 2); 192 zValidation= (validationVectors - mean(validationVectors, 2)) ./ std(validationVectors, 0, 2); 193 df_b = nSubjects-1; % degrees of freedom for s2 194 df_w = nSubjects*(nSegments-1); % degrees of freedom for r 195 nFeatures = nScouts * nFreqs; 196 icc = zeros(1, nFeatures); 197 for iFeature = 1 : nFeatures 198 x = [zTraining(:, iFeature), zValidation(:, iFeature)]; 199 x_w_mean = mean(x, 2); 200 x_g_mean = mean(x(:)); 201 ss_t = sum((x - x_g_mean).^2, 'all'); 202 ss_w = sum((x - x_w_mean).^2, 'all'); 203 ss_b = ss_t - ss_w; 204 ms_b = ss_b / df_b; 205 ms_w = ss_w / df_w; 206 icc(iFeature) = (ms_b - ms_w) ./ (ms_b + ((nSegments-1).*ms_w)); 207 end 208 iccFreqsScouts = reshape(icc, [nFreqs, nScouts]); 209 % Compute Scout ICC for frequency bands 210 nBands = length(BandNames); 211 iccBands = zeros(nScouts, nBands); 212 for iBand = 1 : nBands 213 ixLowerFreq = find(Freqs >= BandLowerFreqs(iBand), 1, 'first'); 214 ixUpperFreq = find(Freqs < BandUpperFreqs(iBand), 1, 'last'); 215 iccBands(: ,iBand) = mean(iccFreqsScouts(ixLowerFreq:ixUpperFreq, :), 1)'; 216 end 217 218 %% ===== SAVE OUTCOME IN BRAINSTORM DATABASE ===== 219 % Retrieve 'Group_analysis' subject 220 sNormSubj = bst_get('NormalizedSubject'); 221 % Study to save files 222 [sOutputStudy, iOutputStudy] = bst_get('StudyWithCondition', bst_fullfile(sNormSubj.Name, bst_get('DirAnalysisIntra'))); 223 224 % Similarity matrix 225 sSimilarityMat = db_template('timefreqmat'); 226 % Reshape: [nA x nB x nTime x nFreq] => [nA*nB x nTime x nFreq] 227 sSimilarityMat.TF = reshape(SubjectCorrMatrix, [], 1, 1); 228 sSimilarityMat.Comment = 'Similarity matrix'; 229 sSimilarityMat.DataType = 'matrix'; 230 sSimilarityMat.Time = [0, 1]; 231 sSimilarityMat.RefRowNames = cellfun(@(x) ['Train ', x], SubjectNames, 'UniformOutput', false); 232 sSimilarityMat.RowNames = cellfun(@(x) ['Validation ', x], SubjectNames, 'UniformOutput', false); 233 % Output filename 234 SimilarityFile = bst_process('GetNewFilename', bst_fileparts(sOutputStudy.FileName), 'timefreq_connectn_corr'); 235 % Save file 236 bst_save(SimilarityFile, sSimilarityMat, 'v6'); 237 % Add file to database structure 238 db_add_data(iOutputStudy, SimilarityFile, sSimilarityMat); 239 240 % Differentiability matrix 241 sDiffMat = db_template('matrixmat'); 242 sDiffMat.Value = Differentiability; 243 sDiffMat.Comment = 'Differentiability'; 244 sDiffMat.Time = [0, 1]; 245 sDiffMat.Description = SubjectNames; 246 % Output filename 247 DiffFile = bst_process('GetNewFilename', bst_fileparts(sOutputStudy.FileName), 'matrix'); 248 % Save file 249 bst_save(DiffFile, sDiffMat, 'v6'); 250 % Add file to database structure 251 db_add_data(iOutputStudy, DiffFile, sDiffMat); 252 253 % Save band ICC values (scout level) 254 for iBand = 1 : nBands 255 sIccBandMat = db_template('matrixmat'); 256 sIccBandMat.Value = iccBands(:, iBand); 257 sIccBandMat.Comment = ['ICC_' BandNames{iBand}]; 258 sIccBandMat.Time = [0, 1]; 259 sIccBandMat.Description = ScoutNames; 260 % Output filename 261 IccBandFile = bst_process('GetNewFilename', bst_fileparts(sOutputStudy.FileName), 'matrix'); 262 % Save file 263 bst_save(IccBandFile, sIccBandMat, 'v6'); 264 % Add file to database structure 265 db_add_data(iOutputStudy, IccBandFile, sIccBandMat); 266 end 267 268 % Cortex surface display for band ICC values 269 % Verify destination surface 270 sSubjectGroup = bst_get('Subject', sOutputStudy.BrainStormSubject); 271 sSurfFile = sSubjectGroup.Surface(sSubjectGroup.iCortex); 272 sSurfMat = in_tess_bst(sSurfFile.FileName); 273 iAtlas = find(ismember({sSurfMat.Atlas.Name}, AtlasName)); 274 if isempty(iAtlas) 275 error('Default surface in "%s" does not contain "%s" atlas', bst_get('NormalizedSubjectName'), AtlasName); 276 end 277 sAtlas = sSurfMat.Atlas(iAtlas); 278 if ~all(ismember({sAtlas.Scouts.Label}, ScoutNames)) 279 error('Atlas "%s" in "%s" does not contain the same scouts as ICC', AtlasName, bst_get('NormalizedSubjectName')); 280 end 281 % Create one full results file per band ICC values 282 IccBandFiles = {}; 283 for iBand = 1 : nBands 284 sIccBandMat = db_template('resultsmat'); 285 sIccBandMat.SurfaceFile = sSurfFile.FileName; 286 sIccBandMat.ImageGridAmp = nan(size(sSurfMat.Vertices, 1), 1); 287 sIccBandMat.Comment = ['ICC_' BandNames{iBand}]; 288 sIccBandMat.Time = [0, 1]; 289 % Assign ICC values to vertices in Scout 290 for ix = 1 : nScouts 291 iScout = find(ismember({sAtlas.Scouts.Label}, ScoutNames(ix))); 292 sIccBandMat.ImageGridAmp(sAtlas.Scouts(iScout).Vertices) = deal(iccBands(ix, iBand)); 293 end 294 % Output filename 295 IccBandFile = bst_process('GetNewFilename', bst_fileparts(sOutputStudy.FileName), 'results'); 296 IccBandFiles = [IccBandFiles, IccBandFile]; 297 % Save file 298 bst_save(IccBandFile, sIccBandMat, 'v6'); 299 % Add file to database structure 300 db_add_data(iOutputStudy, IccBandFile, sIccBandMat); 301 end 302 303 % Reload database 304 db_reload_studies(iOutputStudy) 305 306 307 %% ===== SNAPSHOTS ===== 308 % Process: Snapshot: Similarity matrix 309 bst_process('CallProcess', 'process_snapshot', SimilarityFile, [], ... 310 'type', 'connectimage', ... % Connectivity matrix 311 'Comment', 'Similarity matrix'); 312 313 % Process: Snapshot: Recordings time series 314 bst_process('CallProcess', 'process_snapshot', DiffFile, [], ... 315 'type', 'data', ... % Recordings time series 316 'time', 0, ... 317 'Comment', 'Differentiability'); 318 319 for iBand = 1 : nBands 320 % Process: Snapshot: Sources (one time) 321 bst_process('CallProcess', 'process_snapshot', IccBandFiles{iBand}, [], ... 322 'type', 'sources', ... % Sources (one time) 323 'orient', 1, ... % left 324 'time', 0, ... 325 'contact_time', [0, 0.1], ... 326 'contact_nimage', 12, ... 327 'threshold', 0, ... 328 'surfsmooth', 30, ... 329 'mni', [0, 0, 0], ... 330 'Comment', ['ICC_' BandNames{iBand}]); 331 end 332 333 % Save report 334 ReportFile = bst_report('Save', []); 335 if ~isempty(reports_dir) && ~isempty(ReportFile) 336 bst_report('Export', ReportFile, reports_dir); 337 else 338 bst_report('Open', ReportFile); 339 end





Feedback: Comments, bug reports, suggestions, questions
Email address (if you expect an answer):


Tutorials/BrainFingerprint (last edited 2024-03-08 07:21:08 by SylvainBaillet)