Feasibility of precision functional mapping in youth multi-echo fMRI data.
The 6 matches
- [1] § Methods › Individualized networks ↔ ToShareCode.zip/ToShareCode/FC_Reliability/makeFC.m, lines 165–227 · score 1.00 · Somato Cognitive Action, Cingulo opercular, Somatomotor Foot, Medial Parietal, Visual V5, Default Anterolateral
- [2] § Methods › Reliability and stability measures ↔ ToShareCode.zip/ToShareCode/Spatial_Topology/DiceScript.m, lines 62–145 · score 0.69 · Normalized Mutual Information, perfect overlap, Dice coefficients, NMI, Network
- [3] § Results › Network topology ↔ ToShareCode.zip/ToShareCode/FC_Reliability/makeFC.m, lines 165–227 · score 0.58 · visual lateral, default retrosplenial, streams, language, salience, Networks
- [4] § Methods › Data preprocessing and denoising ↔ ToShareCode.zip/ToShareCode/Miscellaneous/plot_sizes.m, lines 140–178 · score 0.57 · Signal complexity, Head motion, displacement, correlation, networks
- [5] § Methods › Reliability and stability measures ↔ ToShareCode.zip/ToShareCode/Spatial_Topology/Patch_Pipeline/diceForPatches.m, lines 515–601 · score 0.56 · Normalized Mutual Information, Dice coefficients, NMI, Network
- [6] § Results › Network topology ↔ ToShareCode.zip/ToShareCode/Miscellaneous/plot_sizes.m, lines 140–178 · score 0.52 · signal complexity, head motion, FDR, correlations, Networks
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
MATLAB · 797 lines · 28 KB · no license · 2 matches
- % CREATE FC MATRICES - first three cells
- % silhouette calculations on FC matrices - fourth cell
- % FC properties - fifth cell
- %% (1) set up
- addpath(genpath('~/Documents/Randy/APM_Imaging/processingPFM/'))
- addpath('/Users/isaactreves/MIT Dropbox/Isaac Treves/BACKUP_LOCAL_MIT_2/MATLAB/GraphVar_2.03/GraphVar_2.03a/src/ext/BCT');
- addpath(genpath('~/Documents/Homologous-Functional-Regions/HFR_ai/'))
- ProgramPath = '~/Documents/Homologous-Functional-Regions/HFR_ai';
- % add freesurfer code to matlab path
- addpath(genpath('/Applications/MATLAB_R2024a.app/bin'))
- addpath(genpath('/Users/isaactreves/Documents/CBIG'))
- % ADJUST HERE
- sub='sub-abd1113';
- pfmpath=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub '-pfm-sparse/pfmsplitcomparison/'];
- columns = 21;
- load("~/Documents/PFM-Depression/PFM-Tutorial/Utilities/priors.mat")
- labels=Priors.NetworkLabels(1:21);
- Templates=Priors.Spatial;
- ArbitraryCutoff=0.25;
- Templates(Templates>=0.25)=1;
- Templates(Templates<0.25)=0;
- tc = ft_read_cifti_mod([pfmpath 'concatenated_regressed_smoothed2.55_32k_fsLR.dtseries.nii']);
- tc.brainstructure(tc.brainstructure==-1)=[];
- tc.data = tc.data(tc.brainstructure<3,:);
- %tc_corr=fisherz(corr(tc.data'));
- %%
- %networksload = ft_read_cifti_mod([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling.dlabel.nii']);
- % adjustment to use networks only from small amount
- pfmpath=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub '-pfm-sparse/pfmsplit400/'];
- networksload = ft_read_cifti_mod([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling.dlabel.nii']);
- %networksload = niftiread(['/Users/isaactreves/Documents/Randy/APM_Imaging/bids/derivatives/sub-abd1006/CIFTI/pfm_charles/Bipartite_PhysicalCommunities+AlgorithmicLabeling.dlabel.nii']);
- networks=struct;
- networks.data=networksload.data;
- % networks.data=networks.data +1 ;
- %Ic = ft_read_cifti_mod(['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub{1} '/pfm/Bipartite_PhysicalCommunities+SpatialFiltering.dtseries.nii']);
- communities=ft_read_cifti_mod([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling_InfoMapCommunities.dlabel.nii']);
- if isfile([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling_NetworkLabels.xls'])
- [assignment]=readtable([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling_NetworkLabels.xls']);
- "manual found"
- else
- [assignment]=readtable([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling_NetworkLabels.xls']);
- end
- assignment=table2cell(assignment); % fine
- communities.brainstructure(communities.brainstructure==-1)=[];
- communities.data=communities.data(communities.brainstructure<3,:);
- %% (2)
- maps_data=communities.data';
- [labeledVector, uniqueLabels] = niftiMapsToLabeledVector(maps_data,assignment);
- %% (3)
- [refFC,ref_network]=createStructuredFCMatrix(tc,labeledVector,Priors.NetworkColors,0);
- %% (4) silhouette - adjust output
- outputpath=['/Users/isaactreves/Documents/Randy/APM_Imaging/outputs/' sub '/whole/Silhouette.csv'];
- FC = refFC;
- network_mapping= ref_network;
- % FC is an n x n matrix of correlations between patches
- % network_mapping is a structure with fields corresponding to network names
- % Each field contains a vector of patch indices belonging to that network
- % Get all network names
- network_names = network_mapping.keys;
- num_networks = length(network_names);
- % Initialize output array for network silhouette indices
- network_silhouette_indices = zeros(num_networks, 1);
- network_si_std = zeros(num_networks, 1);
- % not FIsher z transformed, so this works
- % Convert correlation matrix to distance matrix (1 - correlation)
- % Assuming correlation ranges from -1 to 1, distance will range from 0 to 2
- distance_matrix = 1 - FC;
- % For each network, calculate silhouette index
- for net_idx = 1:num_networks
- current_network = network_names{net_idx};
- current_patches = network_mapping(current_network).patches;
- startIdx = network_mapping(current_network).startIdx
- % Initialize array to store silhouette indices for each patch in current network
- patch_si = zeros(length(current_patches), 1);
- % Calculate silhouette index for each patch in the network
- for i = 1:length(current_patches)
- patch = current_patches(i)+startIdx-1;
- % Calculate mean within-network distance (a)
- current_patches_adjusted=current_patches+startIdx-1;
- within_patches = current_patches_adjusted(current_patches_adjusted ~= patch); % All patches in same network except current
- if isempty(within_patches)
- a = 0; % If only one patch in network, set a to 0
- else
- a = mean(distance_matrix(patch, within_patches));
- end
- % Initialize array to store mean distances to other networks
- b_values = zeros(num_networks - 1, 1);
- b_idx = 1;
- % Calculate mean distance to each other network
- % for other_net_idx = 1:num_networks
- % if other_net_idx ~= net_idx
- % other_network = network_names{other_net_idx};
- % other_patches = network_mapping(other_network).patches;
- % other_idx=network_mapping(other_network).startIdx;
- % if ~isempty(other_patches)
- % b_values(b_idx) = mean(distance_matrix(patch, other_patches+other_idx-1));
- % b_idx = b_idx + 1;
- % end
- % end
- % end
- % b is the minimum mean distance to other networks - seems
- % restrictive - this is like the closest other network
- % b = min(b_values);
- % Collect all patches not in the current network
- all_other_patches = [];
- for other_net_idx = 1:num_networks
- if other_net_idx ~= net_idx
- other_network = network_names{other_net_idx};
- other_patches_relative = network_mapping(other_network).patches;
- other_start_idx = network_mapping(other_network).startIdx;
- % Convert relative indices to absolute indices
- other_patches_absolute = other_patches_relative + other_start_idx - 1;
- all_other_patches = [all_other_patches; other_patches_absolute];
- end
- end
- % Calculate mean distance to all patches outside the current network
- if isempty(all_other_patches)
- b = 0 % Should not happen if there are multiple networks
- else
- b = mean(distance_matrix(patch, all_other_patches));
- end
- % Calculate silhouette index
- patch_si(i) = (b - a) / max(a, b);
- end
- % Store mean silhouette index for network
- network_silhouette_indices(net_idx) = mean(patch_si);
- if length(current_patches)<2
- network_silhouette_indices(net_idx)=0;
- end
- % Store standard deviation of silhouette indices for network (extra credit)
- network_si_std(net_idx) = std(patch_si);
- end
- % Create table for output
- result_table = table(network_names', network_silhouette_indices, network_si_std, ...
- 'VariableNames', {'Network', 'SilhouetteIndex', 'SilhouetteStd'});
- % Display results
- disp('Network Silhouette Indices:');
- disp(result_table);
- writetable(result_table,outputpath)
- %% save to scalar
- custom_order = {...
- 'Default_Parietal', ...
- 'Default_Anterolateral', ...
- 'Default_Dorsolateral', ...
- 'Default_Retrosplenial', ...
- 'Visual_Lateral', ...
- 'Visual_Dorsal/VentralStream', ...
- 'Visual_V5', ...
- 'Visual_V1', ...
- 'Frontoparietal', ...
- 'DorsalAttention', ...
- 'Premotor/DorsalAttentionII', ...
- 'Language', ...
- 'Salience', ...
- 'CinguloOpercular/Action-mode', ...
- 'MedialParietal', ...
- 'Somatomotor_Hand', ...
- 'Somatomotor_Face', ...
- 'Somatomotor_Foot', ...
- 'Auditory', ...
- 'SomatoCognitiveAction', ...
- 'Noise'};
- % Create table for output
- result_table = table(network_names', network_silhouette_indices, network_si_std, ...
- 'VariableNames', {'Network', 'SilhouetteIndex', 'SilhouetteStd'});
- % Sort the table according to the custom order
- [~, sort_idx] = ismember(custom_order, result_table.Network);
- valid_idx = sort_idx > 0; % In case some networks in custom_order are not in the data
- sort_idx = sort_idx(valid_idx);
- sorted_table = result_table(sort_idx, :);
- % Display results
- disp('Network Silhouette Indices:');
- disp(sorted_table);
- %
- network_silhouette_indices = sorted_table.SilhouetteIndex;
- networkscopy=networksload;
- for i =1:length(network_silhouette_indices)
- networkscopy.data(networkscopy.data==i)=network_silhouette_indices(i);
- end
- networkscopy.data(networkscopy.data==21)=0;
- networkscopy.mapname={'bananas'};
- ft_write_cifti_mod([pfmpath 'SI_mean.dscalar.nii'],networkscopy)
- % If you need the indices in the sorted order as return value
- network_silhouette_indices = sorted_table.SilhouetteStd;
- networkscopy=networksload;
- for i =1:length(network_silhouette_indices)
- networkscopy.data(networkscopy.data==i)=network_silhouette_indices(i);
- end
- networkscopy.data(networkscopy.data==21)=0;
- networkscopy.mapname={'bananas'};
- ft_write_cifti_mod([pfmpath 'SI_std.dscalar.nii'],networkscopy)
- %% loop through - deprecated
- Stopping=100:100:1600;
- pfm_ref=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub{1} '/CIFTIS/pfm/'];
- tc = ft_read_cifti_mod([pfm_ref 'concatenated_regressed_smoothed2.55_32k_fsLR.dtseries.nii']);
- tc.brainstructure(tc.brainstructure==-1)=[];
- tc.data = tc.data(tc.brainstructure<3,:);
- %tc_corr=fisherz(corr(tc.data'));
- metrics_all=[];
- for i = Stopping
- pfmpath=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub{1} '/CIFTIS/pfm' num2str(i) '/'];
- [labeledVector]=prepare_pfm(pfmpath);
- [targetFC,target_network]=createStructuredFCMatrix(tc,labeledVector,Priors.NetworkColors,1);
- [metrics,networksBoth]=calculateFCSimilarity(refFC,ref_network,targetFC,target_network);
- close all;
- metrics_all=[metrics_all;metrics];
- end
- %% (5) actual method - run reference FC stuff first
- Stopping=100:100:1600;
- Stop_end=1600; %for 1065
- % remember for split you have to use other data like split1600
- % for rest, you should use pfm rest ,same data
- pfm_target=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub '-pfm-sparse/pfmsplit1600/'];
- tc = ft_read_cifti_mod([pfm_target 'concatenated_regressed_smoothed2.55_32k_fsLR.dtseries.nii']);
- [labeledVector]=prepare_pfm(pfm_target); % I think we only need to do this once - unless you want to get fancy and use different
- %%
- % parcellations for each data chunk
- tc.brainstructure(tc.brainstructure==-1)=[];
- tc.data = tc.data(tc.brainstructure<3,:);
- %tc_corr=fisherz(corr(tc.data'));
- metrics_all=nan(length(Stopping),4);
- shuffles=100;
- delete(gcp('nocreate'))
- parpool(3) % reminder this is RAM intensive
- % not in parallel does 5-8 shuffles / min
- parfor i = 1:length(Stopping)
- i
- if Stopping(i)<Stop_end
- allshufflemetrics=[];
- for j = 1:shuffles
- max_start = size(tc.data,2) - Stopping(i) + 1;
- start_col = randi(max_start);
- tc_copy=tc;
- tc_copy.data=tc_copy.data(:,start_col:(start_col+Stopping(i)-1));
- [targetFC,target_network]=createStructuredFCMatrix(tc_copy,labeledVector,Priors.NetworkColors,1);
- [metrics,networksBoth]=calculateFCSimilarity(refFC,ref_network,targetFC,target_network);
- allshufflemetrics=[allshufflemetrics;metrics];
- end
- close all;
- metrics=mean(allshufflemetrics,1);
- metrics_all(i,:)=metrics;
- end
- end
- %%
- metricsAll_save=array2table(metrics_all,"VariableNames",{'FC_sim','PartCoef_Sim','Global Eff Diff','Modularity Diff'})
- writetable(metricsAll_save,['/Users/isaactreves/Documents/Randy/APM_Imaging/outputs/' sub '/metrics_FC_split_10min.csv'])
- %%
- function [labeledVector]=prepare_pfm(pfmpath)
- communities=ft_read_cifti_mod([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling_InfoMapCommunities.dlabel.nii']);
- if isfile([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling_NetworkLabels.xls'])
- [assignment]=readtable([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling_NetworkLabels.xls']);
- "manual found prepare pfm"
- else
- [assignment]=readtable([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling_NetworkLabels.xls']);
- end
- assignment=table2cell(assignment);
- communities.brainstructure(communities.brainstructure==-1)=[];
- communities.data=communities.data(communities.brainstructure<3,:);
- %%
- maps_data=communities.data';
- [labeledVector, uniqueLabels] = niftiMapsToLabeledVector(maps_data,assignment);
- end
- function [labeledVector, uniqueLabels] = niftiMapsToLabeledVector(data, labelCell)
- % Converts a set of NIFTI maps to a 1D labeled vector where vertices with
- % value > 0 in a map receive the corresponding label from a cell array
- %
- % Inputs:
- % data - NIFTI data with maps in dim 5 and vertices in dim 6
- % labelCell - Cell array where rows 2 to (2+numMaps-1) contain labels:
- % column 2 has primary labels, column 3 (if exists)
- % takes precedence when non-empty
- %
- % Outputs:
- % labeledVector - Cell array with two columns:
- % Column 1: Network label (e.g., 'Frontoparietal', 'Default')
- % Column 2: Community number for that network (e.g., 1, 2, ...)
- % uniqueLabels - List of unique network labels used in the resulting vector
- % Get dimensions
- numMaps = size(data, 1)
- numVertices = size(data, 2)
- % Check if labelCell has sufficient rows
- if size(labelCell, 1) < numMaps
- error('Label cell array must have at least %d rows', numMaps + 1);
- end
- % Initialize output vector (empty cells will represent unlabeled vertices)
- labeledVector = cell(numVertices, 2);
- for i = 1:numVertices
- labeledVector{i,1} = '';
- labeledVector{i,2} = 0;
- end
- % Track communities for each label
- labelCommunities = containers.Map('KeyType', 'char', 'ValueType', 'any');
- % Process each map
- for mapIdx = 1:numMaps
- % Get label for this map from cell array
- labelRowIdx = mapIdx; % Skip first row
- % Determine label - column 3 takes precedence if it exists and is non-empty
- if size(labelCell, 2) >= 3 && ~isempty(labelCell{labelRowIdx, 3}) && all(~isnan(labelCell{labelRowIdx, 3}))
- mapLabel = labelCell{labelRowIdx, 3};
- else
- mapLabel = labelCell{labelRowIdx, 2};
- end
- % Skip if label is empty
- if isempty(mapLabel)
- continue;
- end
- % Convert to string if it's a number
- if isnumeric(mapLabel)
- mapLabel = num2str(mapLabel);
- end
- % Update community counter for this label
- if ~isKey(labelCommunities, mapLabel)
- labelCommunities(mapLabel) = 1;
- else
- labelCommunities(mapLabel) = labelCommunities(mapLabel) + 1;
- end
- % Get current community number for this label
- communityNumber = labelCommunities(mapLabel);
- % Find vertices where the current map has value > 0
- activeVertices = data(mapIdx,:) > 0;
- % If data is high-dimensional, ensure we get correct vertex indices
- if ndims(activeVertices) > 1
- activeVertices = reshape(activeVertices, [], numVertices);
- activeVertices = any(activeVertices, 1)';
- end
- % Assign label and community to active vertices
- for i = find(activeVertices)'
- labeledVector{i,1} = mapLabel;
- labeledVector{i,2} = communityNumber;
- end
- end
- % Get list of unique network labels (excluding empty/unlabeled)
- networkLabels = cellfun(@(x) num2str(x), labeledVector(:,1), 'UniformOutput', false);
- validNetworks = ~cellfun(@isempty, networkLabels);
- if any(validNetworks)
- uniqueLabels = unique(networkLabels(validNetworks));
- else
- uniqueLabels = {};
- end
- % Remove empty string from uniqueLabels if present
- if ~isempty(uniqueLabels) && any(cellfun(@isempty, uniqueLabels))
- uniqueLabels(cellfun(@isempty, uniqueLabels)) = [];
- end
- end
- function numericalVector = convertLabelsToNumerical(labeledVector, networkLabels)
- % Converts a cell array of network names to a numerical vector using a
- % reference cell array of network labels
- %
- % Inputs:
- % labeledVector - Cell array of network names (e.g., {'Frontoparietal', 'Default', ...})
- % networkLabels - Cell array containing network names indexed from 1 to N
- %
- % Output:
- % numericalVector - Vector where each element is the numerical index
- % of the corresponding network in networkLabels
- % Initialize output vector with zeros (for unmatched labels)
- numericalVector = zeros(size(labeledVector));
- % Convert to cell array if input is not already a cell array
- if ~iscell(labeledVector)
- error('labeledVector must be a cell array of network names');
- end
- % Ensure networkLabels is a cell array
- if ~iscell(networkLabels)
- error('networkLabels must be a cell array');
- end
- % Process each label in the input vector
- for i = 1:length(labeledVector)
- % Skip empty cells
- if isempty(labeledVector{i})
- continue;
- end
- % Find the index of the current label in the networkLabels array
- idx = find(strcmpi(labeledVector{i}, networkLabels));
- % If found, assign the index to the output vector
- if ~isempty(idx)
- numericalVector(i) = idx(1); % Use first match if multiple found
- else
- warning('Network "%s" not found in networkLabels', labeledVector{i});
- end
- end
- end
- function [FC,networkMap]=createStructuredFCMatrix(data, labeledVector, networkColors,noPlot)
- % data: struct with field 'data' of size N vertices x T timepoints
- % labeledVector: cell array of size N x 2 with network and patch info
- % networkColors: matrix of size 21 x 3 with RGB colors (first entry to be ignored)
- % Extract necessary data
- vertexData = data.data; %
- networkIDs = labeledVector(:, 1);
- patchIDs = labeledVector(:, 2);
- % Get unique networks
- % Handle potential issues with cell arrays
- if iscell(networkIDs)
- uniqueNetworks = unique(networkIDs);
- else
- uniqueNetworks = unique(num2cell(networkIDs));
- end
- load("~/Documents/PFM-Depression/PFM-Tutorial/Utilities/priors.mat")
- labels=Priors.NetworkLabels(1:21);
- [~, indices] = ismember(uniqueNetworks, labels);
- % Sort foundNetworks based on these indices
- [~, sortOrder] = sort(indices);
- uniqueNetworks = uniqueNetworks(sortOrder);
- numNetworks = length(uniqueNetworks);
- % Create mapping of each vertex to its network and patch
- networkMap = containers.Map('KeyType', 'char', 'ValueType', 'any');
- patchMap = containers.Map('KeyType', 'char', 'ValueType', 'double');
- patchCount = 0;
- % First, identify all patches and count them
- for i = 1:numNetworks
- currentNetwork = uniqueNetworks{i};
- % Handle different data types for comparison
- if iscell(networkIDs)
- networkVertices = strcmp(networkIDs, currentNetwork);
- else
- networkVertices = (networkIDs == currentNetwork);
- end
- % Extract patches for this network safely
- networkPatchIDs = patchIDs(networkVertices);
- % Handle different data types for unique operation
- if iscell(networkPatchIDs)
- uniquePatches = unique(cell2mat(networkPatchIDs));
- else
- uniquePatches = unique(networkPatchIDs); % Convert to cell if numeric
- end
- % Store patch information for this network
- if ischar(currentNetwork)
- networkKey = currentNetwork;
- else
- networkKey = num2str(currentNetwork);
- end
- networkMap(networkKey) = struct('patches', uniquePatches, 'startIdx', patchCount+1);
- % Map each patch to an index for the FC matrix
- for j = 1:length(uniquePatches)
- patchCount = patchCount + 1;
- if iscell(uniquePatches)
- patchID = uniquePatches{j};
- else
- patchID = uniquePatches(j);
- end
- % Create a string key regardless of input type
- if ischar(patchID)
- patchKey = patchID;
- else
- patchKey = num2str(patchID);
- end
- patchMap([networkKey '_' patchKey]) = patchCount;
- end
- end
- % debugged up to here
- % Create FC matrix (correlation matrix)
- FC = zeros(patchCount, patchCount);
- % For each patch, compute average time series
- patchTimeSeries = zeros(patchCount, size(vertexData, 2));
- for i = 1:numNetworks
- currentNetwork = uniqueNetworks{i};
- % Convert to string key for map lookup
- if ischar(currentNetwork)
- networkKey = currentNetwork;
- else
- networkKey = num2str(currentNetwork);
- end
- patches = networkMap(networkKey).patches;
- for j = 1:length(patches)
- if iscell(patches)
- currentPatch = patches{j};
- else
- currentPatch = patches(j);
- end
- % Handle different data types for comparison
- patchIDs_forcompare=cell2mat(patchIDs);
- if iscell(networkIDs) && iscell(patchIDs_forcompare)
- % doesn't work
- patchVertices = strcmp(networkIDs, currentNetwork) & strcmp(patchIDs_forcompare, currentPatch);
- elseif ~iscell(networkIDs) && ~iscell(patchIDs_forcompare)
- patchVertices = (networkIDs == currentNetwork) & (patchIDs_forcompare == currentPatch);
- elseif iscell(networkIDs) && ~iscell(patchIDs_forcompare)
- patchVertices = strcmp(networkIDs, currentNetwork) & (patchIDs_forcompare == currentPatch);
- else
- patchVertices = (networkIDs == currentNetwork) & strcmp(patchIDs_forcompare, currentPatch);
- end
- % Average time series for this patch
- if any(patchVertices)
- % Convert to string for map lookup
- if ischar(currentPatch)
- patchKey = currentPatch;
- else
- patchKey = num2str(currentPatch);
- end
- patchIdx = patchMap([networkKey '_' patchKey]);
- patchTimeSeries(patchIdx, :) = mean(vertexData(patchVertices, :), 1);
- end
- end
- end
- % Compute correlation matrix (FC)
- FC = corrcoef(patchTimeSeries');
- if ~noPlot
- % Create figure
- figure('Position', [100, 100, 1200, 1000]);
- % Plot the FC matrix
- axes('Position', [0.1, 0.1, 0.8, 0.8]);
- imagesc(FC, [-1, 1]);
- %colormap(redbluecmap);
- colorbar;
- end
- % Create labels for the axes
- axisLabels = cell(patchCount, 1);
- networkBoundaries = zeros(numNetworks+1, 1);
- networkBoundaries(1) = 0.5;
- % Tick positions and labels
- tickPositions = [];
- networkCenters = [];
- for i = 1:numNetworks
- currentNetwork = uniqueNetworks{i};
- % Convert to string key for map lookup
- if ischar(currentNetwork)
- networkKey = currentNetwork;
- else
- networkKey = num2str(currentNetwork);
- end
- patches = networkMap(networkKey).patches;
- startIdx = networkMap(networkKey).startIdx;
- % Calculate center position for this network's label
- networkCenter = startIdx + (length(patches)-1)/2;
- networkCenters = [networkCenters; networkCenter];
- for j = 1:length(patches)
- if iscell(patches)
- currentPatch = patches{j};
- else
- currentPatch = patches(j);
- end
- % Convert to string for map lookup
- if ischar(currentPatch)
- patchKey = currentPatch;
- else
- patchKey = num2str(currentPatch);
- end
- patchIdx = patchMap([networkKey '_' patchKey]);
- % Format label based on type
- if ischar(currentPatch)
- axisLabels{patchIdx} = currentPatch;
- else
- axisLabels{patchIdx} = num2str(currentPatch);
- end
- tickPositions = [tickPositions; patchIdx];
- end
- networkBoundaries(i+1) = startIdx + length(patches) - 0.5;
- end
- if ~noPlot
- % Set axis ticks and labels
- set(gca, 'XTick', tickPositions, 'XTickLabel', axisLabels, 'XTickLabelRotation', 90,'FontSize',8);
- set(gca, 'YTick', tickPositions, 'YTickLabel', axisLabels);
- % Draw network boundaries
- hold on;
- for i = 1:length(networkBoundaries)
- % Horizontal lines
- if i > 1
- line([0.5, patchCount+0.5], [networkBoundaries(i), networkBoundaries(i)], 'Color', 'k', 'LineWidth', 2);
- end
- % Vertical lines
- if i > 1
- line([networkBoundaries(i), networkBoundaries(i)], [0.5, patchCount+0.5], 'Color', 'k', 'LineWidth', 2);
- end
- end
- % Add network colors on the left and top using the provided RGB values
- axisWidth = 0.05;
- % Colors on the left
- axes('Position', [0.05, 0.1, axisWidth, 0.8]);
- colorMap = zeros(patchCount, 3);
- end
- % problem is here
- for i = 1:numNetworks
- currentNetwork = uniqueNetworks{i};
- % Convert to string key for map lookup
- if ischar(currentNetwork)
- networkKey = currentNetwork;
- else
- networkKey = num2str(currentNetwork);
- end
- startIdx = networkMap(networkKey).startIdx;
- patches = networkMap(networkKey).patches;
- numPatches = length(patches);
- % Get the color for this network
- colorIdx=find(strcmp(labels,networkKey));
- %colorIdx = min(i, size(networkColors, 1));
- networkColor = networkColors(colorIdx, :);
- % Fill the color block for this network
- colorMap(startIdx:(startIdx+numPatches-1), :) = repmat(networkColor, numPatches, 1);
- end
- if ~noPlot
- imagesc((1:patchCount)', 'CDataMapping', 'direct');
- colormap(gca, colorMap);
- axis off;
- % Colors on the top
- axes('Position', [0.1, 0.9, 0.76, axisWidth]);
- imagesc(1:patchCount, 'CDataMapping', 'direct');
- colormap(gca, colorMap);
- axis off;
- % Return to main axes and label
- axes('Position', [0.1, 0.1, 0.8, 0.8], 'Visible', 'off');
- title('Functional Connectivity Matrix by Network and Patch', 'FontSize', 16);
- % Save as PDF
- print('-dpdf', 'FunctionalConnectivity.pdf','-bestfit');
- end
- end
- function [metrics,networksInBoth] = calculateFCSimilarity(refFC, refNetworkMap, testFC, testNetworkMap)
- % Calculate similarity between functional connectivity matrices
- % across different data lengths, comparing only networks that exist in both
- %
- % Inputs:
- % refFC - Reference FC matrix (NxN, where N is the total number of patches)
- % refNetworkMap - Structure with fields for each network containing:
- % - patches: indices of patches belonging to the network
- % - startIdx: starting index for the network
- % testFC - Test FC matrix to compare against reference
- % testNetworkMap - Network map for the test data
- %
- % Outputs:
- % similarity - Correlation similarity between average FC values (upper triangle only)
- % networksInBoth - Cell array of networks found in both datasets
- % Get the network names from both maps
- refNetworks = refNetworkMap.keys;
- testNetworks = testNetworkMap.keys;
- % Find networks that exist in both datasets
- networksInBoth = intersect(refNetworks, testNetworks);
- % Create average FC matrices for networks in both datasets
- numNetworks = length(networksInBoth);
- refNetFC_avg = zeros(numNetworks, numNetworks);
- testNetFC_avg = zeros(numNetworks, numNetworks);
- %% quick do modularity and efficiency
- geff1=efficiency_wei(refFC);
- geff2=efficiency_wei(testFC);
- geff_dif=abs(geff2-geff1);
- %
- [~,Q1]=modularity_louvain_und_sign(refFC);
- [~,Q2]=modularity_louvain_und_sign(testFC);
- modularity_dif=abs(Q1-Q2);
- % For each pair of networks, calculate the average FC
- for i = 1:numNetworks
- netI = networksInBoth{i};
- % Get true patch indices for network i in reference data
- refPatchesI = refNetworkMap(netI).patches + (refNetworkMap(netI).startIdx - 1);
- % Get true patch indices for network i in test data
- testPatchesI = testNetworkMap(netI).patches + (testNetworkMap(netI).startIdx - 1);
- for j = 1:numNetworks
- netJ = networksInBoth{j};
- % Get true patch indices for network j in reference data
- refPatchesJ = refNetworkMap(netJ).patches + (refNetworkMap(netJ).startIdx - 1);
- % Get true patch indices for network j in test data
- testPatchesJ = testNetworkMap(netJ).patches + (testNetworkMap(netJ).startIdx - 1);
- % Calculate average FC between networks i and j
- refNetFC_avg(i,j) = mean(mean(refFC(refPatchesI, refPatchesJ)));
- testNetFC_avg(i,j) = mean(mean(testFC(testPatchesI, testPatchesJ)));
- end
- end
- % figure;
- % imagesc(refNetFC_avg)
- % figure;
- % imagesc(testNetFC_avg)
- % Extract only the upper triangular part (including diagonal)
- % to avoid counting symmetric pairs twice
- upperTri_mask = triu(true(numNetworks));
- % Get values from upper triangular part
- refValues = refNetFC_avg(upperTri_mask);
- testValues = testNetFC_avg(upperTri_mask);
- % Calculate correlation between these values
- similarity = corr(refValues, testValues);
- participation_coef1=participation_coef_sign(refNetFC_avg,1:length(networksInBoth));
- participation_coef2=participation_coef_sign(testNetFC_avg,1:length(networksInBoth));
- participation_sim=corrcoef(participation_coef1,participation_coef2,'rows','complete');
- participation_sim=participation_sim(1,2);
- metrics=[similarity,participation_sim,modularity_dif,geff_dif];
- end
makeFC.m, no license · at the source
Overview
- Department of Psychiatry, Columbia University Irving Medical Center, New York, NY 10032, USA
- Division of Child and Adolescent Psychiatry, New York State Psychiatric Institute, New York, NY 10032, USA
- Division of Experimental Therapeutics, New York State Psychiatric Institute, New York, NY 10032, USA
- Department of Psychiatry and Behavioral Neurosciences, Wayne State University School of Medicine, 3901 Chrysler Service Dr., Detroit, MI 48201, USA
- Department of Psychiatry, Weill Cornell Medicine, New York, NY 10065, USA
- Merrill Palmer Skillman Institute for Child and Family Development, Wayne State University, 71 East Ferry Street, Detroit, MI 48202, USA
- Department of Pharmacology, Wayne State University School of Medicine, 540 E Canfield St, Detroit, MI 48201, USA
Abstract
The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.
Repository
Its files are read in the Code ↔ Paper reader above, with 6 matches between paragraphs and lines of code.
OSF kgvsb
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
29 files
- ToShareCode.zip/
ToShareCode/ , MATLAB, 761 linesFC_Reliability/ FC_ICC.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 358 linesFC_Reliability/ Patches/ FC_metrics_patch.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 71 linesFC_Reliability/ cortex_vertex_reliabilit y.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 797 lines, 2 matchesFC_Reliability/ makeFC.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 76 linesFC_Reliability/ makeFC_template.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 151 linesFC_Reliability/ pfm_vertex_connectivity_ analysis.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 272 linesHomogeneity (Supplement)/ Patches/ rotations_mgh.m - ToShareCode.zip/
ToShareCode/ , Shell, 397 linesHomogeneity (Supplement)/ Patches/ run_rotation.sh - ToShareCode.zip/
ToShareCode/ , MATLAB, 387 linesHomogeneity (Supplement)/ rotations_pca_infomap.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 339 linesMiscellaneous/ Patch_modifications/ indisys_commandline_pipe line.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 251 linesMiscellaneous/ Patch_modifications/ indisys_patch_with_infom ap.m - ToShareCode.zip/
ToShareCode/ , Shell, 8 linesMiscellaneous/ VertexAreas.sh - ToShareCode.zip/
ToShareCode/ , MATLAB, 33 linesMiscellaneous/ example_MSHBM_run.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 74 linesMiscellaneous/ numvertices.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 178 lines, 2 matchesMiscellaneous/ plot_sizes.m - ToShareCode.zip/
ToShareCode/ , Shell, 69 linesMiscellaneous/ processMCFLIRT.sh - ToShareCode.zip/
ToShareCode/ , Shell, 38 linesMiscellaneous/ separate_communities.sh - ToShareCode.zip/
ToShareCode/ , MATLAB, 126 linesMiscellaneous/ update_sizes.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 797 lines, 1 matchSpatial_Topology/ DiceScript.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 714 lines, 1 matchSpatial_Topology/ Patch_Pipeline/ diceForPatches.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 228 linesSpatial_Topology/ Patch_Pipeline/ variancePatch_sizes.m - ToShareCode.zip/
ToShareCode/ , Shell, 63 linesStructural_Analyses/ sizes.sh - ToShareCode.zip/
ToShareCode/ , MATLAB, 181 linesSupport/ triangle_threshold.m - ToShareCode.zip/
ToShareCode/ , MATLAB, 99 linesSupport/ zrand.m - ToShareCode.zip/
ToShareCode/ , Jupyter, 129 linesTask_analyses/ Fitlins_setup/ TaskModelling.ipynb - ToShareCode.zip/
ToShareCode/ , Shell, 233 linesTask_analyses/ Fitlins_setup/ example_func_vol2surf_fi tlins.sh - ToShareCode.zip/
ToShareCode/ , Jupyter, 172 linesTask_analyses/ Fitlins_setup/ file_handle_fitlins.ipyn b - ToShareCode.zip/
ToShareCode/ , Jupyter, 288 linesTask_analyses/ Fitlins_setup/ onsets.ipynb - ToShareCode.zip/
ToShareCode/ , MATLAB, 343 linesTask_analyses/ processFunc.m
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 29 scripts, each with its path and the digest of its content;
- 6 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Code and data availability statement
The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- it points to the authors' code: OSF kgvsb
Read it in the paper: doi.org/10.1016/j.dcn.2026.101789.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, pages, dates, 7 authors, 7 keywords, 2 funders, 49 references.
Cite
This paper
Treves, I. N., Pagliaccio, D., Patel, G. H., Tamimi, R., Kimerty, J. A., Auerbach, R. P., & Marusak, H. A. (2026). Feasibility of precision functional mapping in youth multi-echo fMRI data. Developmental cognitive neuroscience, 81, 101789. https://
BibTeX
@article{treves2026feasi
author = {Treves, Isaac N and Pagliaccio, David and Patel, Gaurav H and Tamimi, Reem and Kimerty, Jihoon A and Auerbach, Randy P and Marusak, Hilary A},
title = {{Feasibility of precision functional mapping in youth multi-echo fMRI data}},
journal = {Developmental cognitive neuroscience},
year = {2026},
month = jul,
volume = {81},
pages = {101789},
publisher = {Elsevier},
issn = {1878-9293},
doi = {10.1016/
url = {https://
pmid = {42508279},
pmcid = {PMC13446092}
}
RIS
TY - JOUR
AU - Treves, Isaac N
AU - Pagliaccio, David
AU - Patel, Gaurav H
AU - Tamimi, Reem
AU - Kimerty, Jihoon A
AU - Auerbach, Randy P
AU - Marusak, Hilary A
TI - Feasibility of precision functional mapping in youth multi-echo fMRI data
T2 - Developmental cognitive neuroscience
J2 - Dev Cogn Neurosci
PY - 2026
DA - 2026/
VL - 81
SP - 101789
SN - 1878-9293
PB - Elsevier
DO - 10.1016/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1016/
"type": "article-journal",
"title": "Feasibility of precision functional mapping in youth multi-echo fMRI data",
"container-title": "Developmental cognitive neuroscience",
"author": [
{
"family": "Treves",
"given": "Isaac N"
},
{
"family": "Pagliaccio",
"given": "David"
},
{
"family": "Patel",
"given": "Gaurav H"
},
{
"family": "Tamimi",
"given": "Reem"
},
{
"family": "Kimerty",
"given": "Jihoon A"
},
{
"family": "Auerbach",
"given": "Randy P"
},
{
"family": "Marusak",
"given": "Hilary A"
}
],
"container-title-short":
"volume": "81",
"page": "101789",
"DOI": "10.1016/
"PMID": "42508279",
"PMCID": "PMC13446092",
"ISSN": "1878-9293",
"publisher": "Elsevier",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
24
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1162/imag.a.1285 [code]
- Individualized mapping of functional brain networks in older adulthood.Journal: Imaging neuroscience (Cambridge, Mass.)In common: Connectome Workbench, FieldTrip, Parallel Computing Toolbox, 1 other tool, fMRI, 13 references
- [2] doi:10.1016/j.neuron.2026.04.011 [code]
- Precision fMRI reveals densely interdigitated network patches with conserved motifs in the lateral prefrontal cortex.Journal: NeuronIn common: Connectome Workbench, FieldTrip, Parallel Computing Toolbox, 4 other tools, fMRI, 10 references
- [3] doi:10.1093/psyrad/kkag013 [code]
- Convergent and divergent spatial topographies of individualized brain functional networks and their developmental origins.Journal: PsychoradiologyIn common: Connectome Workbench, FieldTrip, Parallel Computing Toolbox, 2 other tools, developmental, fMRI, 11 references
- [4] doi:10.1162/imag.a.1262 [code]
- Frame-wise multi-echo distortion correction for superior functional MRI.Journal: Imaging neuroscience (Cambridge, Mass.)In common: Connectome Workbench, FieldTrip, Parallel Computing Toolbox, 5 other tools, fMRI, 7 references
- [5] doi:10.1162/imag.a.1222 [code]
- Network-based near-scalp personalized brain stimulation targets.Journal: Imaging neuroscience (Cambridge, Mass.)In common: Connectome Workbench, FieldTrip, FreeSurfer, 3 other tools, 9 references
- [6] doi:10.21203/rs.3.rs-9326213/v1 [code]
- Multi-task fMRI outperforms resting-state fMRI for revealing task-invariant organization of the human brainJournal: Research Square (preprint)In common: Connectome Workbench, FreeSurfer, Image Processing Toolbox, 2 other tools, fMRI, 9 references
- [7] doi:10.64898/2026.03.09.710558 [code]
- Multi-task fMRI outperforms resting-state fMRI for revealing task-invariant organization of the human brainJournal: bioRxiv (preprint)In common: Connectome Workbench, FreeSurfer, Image Processing Toolbox, 2 other tools, fMRI, 9 references
- [8] doi:10.1038/s41467-026-73668-y [code]
- Convergent and divergent brain-cognition development in early adolescence.Journal: Nature communicationsIn common: fdr_bh (Benjamini-Hochberg FDR), Connectome Workbench, FieldTrip, 5 other tools, fMRI, 4 references
- [9] doi:10.1002/advs.202523009 [code]
- Personalized Network-Guided Neuromodulation Enhances Human Working Memory.Journal: Advanced science (Weinheim, Baden-Wurttemberg, Germany)In common: Connectome Workbench, FieldTrip, FreeSurfer, 4 other tools, 6 references
- [10] doi:10.1038/s41467-026-74565-0 [code]
- The functional neurobiology of dispositions towards negative emotions.Journal: Nature communicationsIn common: Brain Connectivity Toolbox, fdr_bh (Benjamini-Hochberg FDR), Connectome Workbench, 7 other tools, 1 reference
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 29 scripts, and 6 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:090125af11c28367…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[.
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
