OSCR

Feasibility of precision functional mapping in youth multi-echo fMRI data.

Code ↔ Paper

6 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 6 matches
  1. [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. [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. [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. [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. [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. [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

  1. % CREATE FC MATRICES - first three cells
  2. % silhouette calculations on FC matrices - fourth cell
  3. % FC properties - fifth cell
  4. %% (1) set up
  5. addpath(genpath('~/Documents/Randy/APM_Imaging/processingPFM/'))
  6. addpath('/Users/isaactreves/MIT Dropbox/Isaac Treves/BACKUP_LOCAL_MIT_2/MATLAB/GraphVar_2.03/GraphVar_2.03a/src/ext/BCT');
  7. addpath(genpath('~/Documents/Homologous-Functional-Regions/HFR_ai/'))
  8. ProgramPath = '~/Documents/Homologous-Functional-Regions/HFR_ai';
  9. % add freesurfer code to matlab path
  10. addpath(genpath('/Applications/MATLAB_R2024a.app/bin'))
  11. addpath(genpath('/Users/isaactreves/Documents/CBIG'))
  12. % ADJUST HERE
  13. sub='sub-abd1113';
  14. pfmpath=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub '-pfm-sparse/pfmsplitcomparison/'];
  15. columns = 21;
  16. load("~/Documents/PFM-Depression/PFM-Tutorial/Utilities/priors.mat")
  17. labels=Priors.NetworkLabels(1:21);
  18. Templates=Priors.Spatial;
  19. ArbitraryCutoff=0.25;
  20. Templates(Templates>=0.25)=1;
  21. Templates(Templates<0.25)=0;
  22. tc = ft_read_cifti_mod([pfmpath 'concatenated_regressed_smoothed2.55_32k_fsLR.dtseries.nii']);
  23. tc.brainstructure(tc.brainstructure==-1)=[];
  24. tc.data = tc.data(tc.brainstructure<3,:);
  25. %tc_corr=fisherz(corr(tc.data'));
  26. %%
  27. %networksload = ft_read_cifti_mod([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling.dlabel.nii']);
  28. % adjustment to use networks only from small amount
  29. pfmpath=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub '-pfm-sparse/pfmsplit400/'];
  30. networksload = ft_read_cifti_mod([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling.dlabel.nii']);
  31. %networksload = niftiread(['/Users/isaactreves/Documents/Randy/APM_Imaging/bids/derivatives/sub-abd1006/CIFTI/pfm_charles/Bipartite_PhysicalCommunities+AlgorithmicLabeling.dlabel.nii']);
  32. networks=struct;
  33. networks.data=networksload.data;
  34. % networks.data=networks.data +1 ;
  35. %Ic = ft_read_cifti_mod(['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub{1} '/pfm/Bipartite_PhysicalCommunities+SpatialFiltering.dtseries.nii']);
  36. communities=ft_read_cifti_mod([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling_InfoMapCommunities.dlabel.nii']);
  37. if isfile([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling_NetworkLabels.xls'])
  38. [assignment]=readtable([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling_NetworkLabels.xls']);
  39. "manual found"
  40. else
  41. [assignment]=readtable([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling_NetworkLabels.xls']);
  42. end
  43. assignment=table2cell(assignment); % fine
  44. communities.brainstructure(communities.brainstructure==-1)=[];
  45. communities.data=communities.data(communities.brainstructure<3,:);
  46. %% (2)
  47. maps_data=communities.data';
  48. [labeledVector, uniqueLabels] = niftiMapsToLabeledVector(maps_data,assignment);
  49. %% (3)
  50. [refFC,ref_network]=createStructuredFCMatrix(tc,labeledVector,Priors.NetworkColors,0);
  51. %% (4) silhouette - adjust output
  52. outputpath=['/Users/isaactreves/Documents/Randy/APM_Imaging/outputs/' sub '/whole/Silhouette.csv'];
  53. FC = refFC;
  54. network_mapping= ref_network;
  55. % FC is an n x n matrix of correlations between patches
  56. % network_mapping is a structure with fields corresponding to network names
  57. % Each field contains a vector of patch indices belonging to that network
  58. % Get all network names
  59. network_names = network_mapping.keys;
  60. num_networks = length(network_names);
  61. % Initialize output array for network silhouette indices
  62. network_silhouette_indices = zeros(num_networks, 1);
  63. network_si_std = zeros(num_networks, 1);
  64. % not FIsher z transformed, so this works
  65. % Convert correlation matrix to distance matrix (1 - correlation)
  66. % Assuming correlation ranges from -1 to 1, distance will range from 0 to 2
  67. distance_matrix = 1 - FC;
  68. % For each network, calculate silhouette index
  69. for net_idx = 1:num_networks
  70. current_network = network_names{net_idx};
  71. current_patches = network_mapping(current_network).patches;
  72. startIdx = network_mapping(current_network).startIdx
  73. % Initialize array to store silhouette indices for each patch in current network
  74. patch_si = zeros(length(current_patches), 1);
  75. % Calculate silhouette index for each patch in the network
  76. for i = 1:length(current_patches)
  77. patch = current_patches(i)+startIdx-1;
  78. % Calculate mean within-network distance (a)
  79. current_patches_adjusted=current_patches+startIdx-1;
  80. within_patches = current_patches_adjusted(current_patches_adjusted ~= patch); % All patches in same network except current
  81. if isempty(within_patches)
  82. a = 0; % If only one patch in network, set a to 0
  83. else
  84. a = mean(distance_matrix(patch, within_patches));
  85. end
  86. % Initialize array to store mean distances to other networks
  87. b_values = zeros(num_networks - 1, 1);
  88. b_idx = 1;
  89. % Calculate mean distance to each other network
  90. % for other_net_idx = 1:num_networks
  91. % if other_net_idx ~= net_idx
  92. % other_network = network_names{other_net_idx};
  93. % other_patches = network_mapping(other_network).patches;
  94. % other_idx=network_mapping(other_network).startIdx;
  95. % if ~isempty(other_patches)
  96. % b_values(b_idx) = mean(distance_matrix(patch, other_patches+other_idx-1));
  97. % b_idx = b_idx + 1;
  98. % end
  99. % end
  100. % end
  101. % b is the minimum mean distance to other networks - seems
  102. % restrictive - this is like the closest other network
  103. % b = min(b_values);
  104. % Collect all patches not in the current network
  105. all_other_patches = [];
  106. for other_net_idx = 1:num_networks
  107. if other_net_idx ~= net_idx
  108. other_network = network_names{other_net_idx};
  109. other_patches_relative = network_mapping(other_network).patches;
  110. other_start_idx = network_mapping(other_network).startIdx;
  111. % Convert relative indices to absolute indices
  112. other_patches_absolute = other_patches_relative + other_start_idx - 1;
  113. all_other_patches = [all_other_patches; other_patches_absolute];
  114. end
  115. end
  116. % Calculate mean distance to all patches outside the current network
  117. if isempty(all_other_patches)
  118. b = 0 % Should not happen if there are multiple networks
  119. else
  120. b = mean(distance_matrix(patch, all_other_patches));
  121. end
  122. % Calculate silhouette index
  123. patch_si(i) = (b - a) / max(a, b);
  124. end
  125. % Store mean silhouette index for network
  126. network_silhouette_indices(net_idx) = mean(patch_si);
  127. if length(current_patches)<2
  128. network_silhouette_indices(net_idx)=0;
  129. end
  130. % Store standard deviation of silhouette indices for network (extra credit)
  131. network_si_std(net_idx) = std(patch_si);
  132. end
  133. % Create table for output
  134. result_table = table(network_names', network_silhouette_indices, network_si_std, ...
  135. 'VariableNames', {'Network', 'SilhouetteIndex', 'SilhouetteStd'});
  136. % Display results
  137. disp('Network Silhouette Indices:');
  138. disp(result_table);
  139. writetable(result_table,outputpath)
  140. %% save to scalar
  141. custom_order = {...
  142. 'Default_Parietal', ...
  143. 'Default_Anterolateral', ...
  144. 'Default_Dorsolateral', ...
  145. 'Default_Retrosplenial', ...
  146. 'Visual_Lateral', ...
  147. 'Visual_Dorsal/VentralStream', ...
  148. 'Visual_V5', ...
  149. 'Visual_V1', ...
  150. 'Frontoparietal', ...
  151. 'DorsalAttention', ...
  152. 'Premotor/DorsalAttentionII', ...
  153. 'Language', ...
  154. 'Salience', ...
  155. 'CinguloOpercular/Action-mode', ...
  156. 'MedialParietal', ...
  157. 'Somatomotor_Hand', ...
  158. 'Somatomotor_Face', ...
  159. 'Somatomotor_Foot', ...
  160. 'Auditory', ...
  161. 'SomatoCognitiveAction', ...
  162. 'Noise'};
  163. % Create table for output
  164. result_table = table(network_names', network_silhouette_indices, network_si_std, ...
  165. 'VariableNames', {'Network', 'SilhouetteIndex', 'SilhouetteStd'});
  166. % Sort the table according to the custom order
  167. [~, sort_idx] = ismember(custom_order, result_table.Network);
  168. valid_idx = sort_idx > 0; % In case some networks in custom_order are not in the data
  169. sort_idx = sort_idx(valid_idx);
  170. sorted_table = result_table(sort_idx, :);
  171. % Display results
  172. disp('Network Silhouette Indices:');
  173. disp(sorted_table);
  174. %
  175. network_silhouette_indices = sorted_table.SilhouetteIndex;
  176. networkscopy=networksload;
  177. for i =1:length(network_silhouette_indices)
  178. networkscopy.data(networkscopy.data==i)=network_silhouette_indices(i);
  179. end
  180. networkscopy.data(networkscopy.data==21)=0;
  181. networkscopy.mapname={'bananas'};
  182. ft_write_cifti_mod([pfmpath 'SI_mean.dscalar.nii'],networkscopy)
  183. % If you need the indices in the sorted order as return value
  184. network_silhouette_indices = sorted_table.SilhouetteStd;
  185. networkscopy=networksload;
  186. for i =1:length(network_silhouette_indices)
  187. networkscopy.data(networkscopy.data==i)=network_silhouette_indices(i);
  188. end
  189. networkscopy.data(networkscopy.data==21)=0;
  190. networkscopy.mapname={'bananas'};
  191. ft_write_cifti_mod([pfmpath 'SI_std.dscalar.nii'],networkscopy)
  192. %% loop through - deprecated
  193. Stopping=100:100:1600;
  194. pfm_ref=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub{1} '/CIFTIS/pfm/'];
  195. tc = ft_read_cifti_mod([pfm_ref 'concatenated_regressed_smoothed2.55_32k_fsLR.dtseries.nii']);
  196. tc.brainstructure(tc.brainstructure==-1)=[];
  197. tc.data = tc.data(tc.brainstructure<3,:);
  198. %tc_corr=fisherz(corr(tc.data'));
  199. metrics_all=[];
  200. for i = Stopping
  201. pfmpath=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub{1} '/CIFTIS/pfm' num2str(i) '/'];
  202. [labeledVector]=prepare_pfm(pfmpath);
  203. [targetFC,target_network]=createStructuredFCMatrix(tc,labeledVector,Priors.NetworkColors,1);
  204. [metrics,networksBoth]=calculateFCSimilarity(refFC,ref_network,targetFC,target_network);
  205. close all;
  206. metrics_all=[metrics_all;metrics];
  207. end
  208. %% (5) actual method - run reference FC stuff first
  209. Stopping=100:100:1600;
  210. Stop_end=1600; %for 1065
  211. % remember for split you have to use other data like split1600
  212. % for rest, you should use pfm rest ,same data
  213. pfm_target=['/Users/isaactreves/Documents/Randy/APM_Imaging/' sub '-pfm-sparse/pfmsplit1600/'];
  214. tc = ft_read_cifti_mod([pfm_target 'concatenated_regressed_smoothed2.55_32k_fsLR.dtseries.nii']);
  215. [labeledVector]=prepare_pfm(pfm_target); % I think we only need to do this once - unless you want to get fancy and use different
  216. %%
  217. % parcellations for each data chunk
  218. tc.brainstructure(tc.brainstructure==-1)=[];
  219. tc.data = tc.data(tc.brainstructure<3,:);
  220. %tc_corr=fisherz(corr(tc.data'));
  221. metrics_all=nan(length(Stopping),4);
  222. shuffles=100;
  223. delete(gcp('nocreate'))
  224. parpool(3) % reminder this is RAM intensive
  225. % not in parallel does 5-8 shuffles / min
  226. parfor i = 1:length(Stopping)
  227. i
  228. if Stopping(i)<Stop_end
  229. allshufflemetrics=[];
  230. for j = 1:shuffles
  231. max_start = size(tc.data,2) - Stopping(i) + 1;
  232. start_col = randi(max_start);
  233. tc_copy=tc;
  234. tc_copy.data=tc_copy.data(:,start_col:(start_col+Stopping(i)-1));
  235. [targetFC,target_network]=createStructuredFCMatrix(tc_copy,labeledVector,Priors.NetworkColors,1);
  236. [metrics,networksBoth]=calculateFCSimilarity(refFC,ref_network,targetFC,target_network);
  237. allshufflemetrics=[allshufflemetrics;metrics];
  238. end
  239. close all;
  240. metrics=mean(allshufflemetrics,1);
  241. metrics_all(i,:)=metrics;
  242. end
  243. end
  244. %%
  245. metricsAll_save=array2table(metrics_all,"VariableNames",{'FC_sim','PartCoef_Sim','Global Eff Diff','Modularity Diff'})
  246. writetable(metricsAll_save,['/Users/isaactreves/Documents/Randy/APM_Imaging/outputs/' sub '/metrics_FC_split_10min.csv'])
  247. %%
  248. function [labeledVector]=prepare_pfm(pfmpath)
  249. communities=ft_read_cifti_mod([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling_InfoMapCommunities.dlabel.nii']);
  250. if isfile([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling_NetworkLabels.xls'])
  251. [assignment]=readtable([pfmpath 'Bipartite_PhysicalCommunities+FinalLabeling_NetworkLabels.xls']);
  252. "manual found prepare pfm"
  253. else
  254. [assignment]=readtable([pfmpath 'Bipartite_PhysicalCommunities+AlgorithmicLabeling_NetworkLabels.xls']);
  255. end
  256. assignment=table2cell(assignment);
  257. communities.brainstructure(communities.brainstructure==-1)=[];
  258. communities.data=communities.data(communities.brainstructure<3,:);
  259. %%
  260. maps_data=communities.data';
  261. [labeledVector, uniqueLabels] = niftiMapsToLabeledVector(maps_data,assignment);
  262. end
  263. function [labeledVector, uniqueLabels] = niftiMapsToLabeledVector(data, labelCell)
  264. % Converts a set of NIFTI maps to a 1D labeled vector where vertices with
  265. % value > 0 in a map receive the corresponding label from a cell array
  266. %
  267. % Inputs:
  268. % data - NIFTI data with maps in dim 5 and vertices in dim 6
  269. % labelCell - Cell array where rows 2 to (2+numMaps-1) contain labels:
  270. % column 2 has primary labels, column 3 (if exists)
  271. % takes precedence when non-empty
  272. %
  273. % Outputs:
  274. % labeledVector - Cell array with two columns:
  275. % Column 1: Network label (e.g., 'Frontoparietal', 'Default')
  276. % Column 2: Community number for that network (e.g., 1, 2, ...)
  277. % uniqueLabels - List of unique network labels used in the resulting vector
  278. % Get dimensions
  279. numMaps = size(data, 1)
  280. numVertices = size(data, 2)
  281. % Check if labelCell has sufficient rows
  282. if size(labelCell, 1) < numMaps
  283. error('Label cell array must have at least %d rows', numMaps + 1);
  284. end
  285. % Initialize output vector (empty cells will represent unlabeled vertices)
  286. labeledVector = cell(numVertices, 2);
  287. for i = 1:numVertices
  288. labeledVector{i,1} = '';
  289. labeledVector{i,2} = 0;
  290. end
  291. % Track communities for each label
  292. labelCommunities = containers.Map('KeyType', 'char', 'ValueType', 'any');
  293. % Process each map
  294. for mapIdx = 1:numMaps
  295. % Get label for this map from cell array
  296. labelRowIdx = mapIdx; % Skip first row
  297. % Determine label - column 3 takes precedence if it exists and is non-empty
  298. if size(labelCell, 2) >= 3 && ~isempty(labelCell{labelRowIdx, 3}) && all(~isnan(labelCell{labelRowIdx, 3}))
  299. mapLabel = labelCell{labelRowIdx, 3};
  300. else
  301. mapLabel = labelCell{labelRowIdx, 2};
  302. end
  303. % Skip if label is empty
  304. if isempty(mapLabel)
  305. continue;
  306. end
  307. % Convert to string if it's a number
  308. if isnumeric(mapLabel)
  309. mapLabel = num2str(mapLabel);
  310. end
  311. % Update community counter for this label
  312. if ~isKey(labelCommunities, mapLabel)
  313. labelCommunities(mapLabel) = 1;
  314. else
  315. labelCommunities(mapLabel) = labelCommunities(mapLabel) + 1;
  316. end
  317. % Get current community number for this label
  318. communityNumber = labelCommunities(mapLabel);
  319. % Find vertices where the current map has value > 0
  320. activeVertices = data(mapIdx,:) > 0;
  321. % If data is high-dimensional, ensure we get correct vertex indices
  322. if ndims(activeVertices) > 1
  323. activeVertices = reshape(activeVertices, [], numVertices);
  324. activeVertices = any(activeVertices, 1)';
  325. end
  326. % Assign label and community to active vertices
  327. for i = find(activeVertices)'
  328. labeledVector{i,1} = mapLabel;
  329. labeledVector{i,2} = communityNumber;
  330. end
  331. end
  332. % Get list of unique network labels (excluding empty/unlabeled)
  333. networkLabels = cellfun(@(x) num2str(x), labeledVector(:,1), 'UniformOutput', false);
  334. validNetworks = ~cellfun(@isempty, networkLabels);
  335. if any(validNetworks)
  336. uniqueLabels = unique(networkLabels(validNetworks));
  337. else
  338. uniqueLabels = {};
  339. end
  340. % Remove empty string from uniqueLabels if present
  341. if ~isempty(uniqueLabels) && any(cellfun(@isempty, uniqueLabels))
  342. uniqueLabels(cellfun(@isempty, uniqueLabels)) = [];
  343. end
  344. end
  345. function numericalVector = convertLabelsToNumerical(labeledVector, networkLabels)
  346. % Converts a cell array of network names to a numerical vector using a
  347. % reference cell array of network labels
  348. %
  349. % Inputs:
  350. % labeledVector - Cell array of network names (e.g., {'Frontoparietal', 'Default', ...})
  351. % networkLabels - Cell array containing network names indexed from 1 to N
  352. %
  353. % Output:
  354. % numericalVector - Vector where each element is the numerical index
  355. % of the corresponding network in networkLabels
  356. % Initialize output vector with zeros (for unmatched labels)
  357. numericalVector = zeros(size(labeledVector));
  358. % Convert to cell array if input is not already a cell array
  359. if ~iscell(labeledVector)
  360. error('labeledVector must be a cell array of network names');
  361. end
  362. % Ensure networkLabels is a cell array
  363. if ~iscell(networkLabels)
  364. error('networkLabels must be a cell array');
  365. end
  366. % Process each label in the input vector
  367. for i = 1:length(labeledVector)
  368. % Skip empty cells
  369. if isempty(labeledVector{i})
  370. continue;
  371. end
  372. % Find the index of the current label in the networkLabels array
  373. idx = find(strcmpi(labeledVector{i}, networkLabels));
  374. % If found, assign the index to the output vector
  375. if ~isempty(idx)
  376. numericalVector(i) = idx(1); % Use first match if multiple found
  377. else
  378. warning('Network "%s" not found in networkLabels', labeledVector{i});
  379. end
  380. end
  381. end
  382. function [FC,networkMap]=createStructuredFCMatrix(data, labeledVector, networkColors,noPlot)
  383. % data: struct with field 'data' of size N vertices x T timepoints
  384. % labeledVector: cell array of size N x 2 with network and patch info
  385. % networkColors: matrix of size 21 x 3 with RGB colors (first entry to be ignored)
  386. % Extract necessary data
  387. vertexData = data.data; %
  388. networkIDs = labeledVector(:, 1);
  389. patchIDs = labeledVector(:, 2);
  390. % Get unique networks
  391. % Handle potential issues with cell arrays
  392. if iscell(networkIDs)
  393. uniqueNetworks = unique(networkIDs);
  394. else
  395. uniqueNetworks = unique(num2cell(networkIDs));
  396. end
  397. load("~/Documents/PFM-Depression/PFM-Tutorial/Utilities/priors.mat")
  398. labels=Priors.NetworkLabels(1:21);
  399. [~, indices] = ismember(uniqueNetworks, labels);
  400. % Sort foundNetworks based on these indices
  401. [~, sortOrder] = sort(indices);
  402. uniqueNetworks = uniqueNetworks(sortOrder);
  403. numNetworks = length(uniqueNetworks);
  404. % Create mapping of each vertex to its network and patch
  405. networkMap = containers.Map('KeyType', 'char', 'ValueType', 'any');
  406. patchMap = containers.Map('KeyType', 'char', 'ValueType', 'double');
  407. patchCount = 0;
  408. % First, identify all patches and count them
  409. for i = 1:numNetworks
  410. currentNetwork = uniqueNetworks{i};
  411. % Handle different data types for comparison
  412. if iscell(networkIDs)
  413. networkVertices = strcmp(networkIDs, currentNetwork);
  414. else
  415. networkVertices = (networkIDs == currentNetwork);
  416. end
  417. % Extract patches for this network safely
  418. networkPatchIDs = patchIDs(networkVertices);
  419. % Handle different data types for unique operation
  420. if iscell(networkPatchIDs)
  421. uniquePatches = unique(cell2mat(networkPatchIDs));
  422. else
  423. uniquePatches = unique(networkPatchIDs); % Convert to cell if numeric
  424. end
  425. % Store patch information for this network
  426. if ischar(currentNetwork)
  427. networkKey = currentNetwork;
  428. else
  429. networkKey = num2str(currentNetwork);
  430. end
  431. networkMap(networkKey) = struct('patches', uniquePatches, 'startIdx', patchCount+1);
  432. % Map each patch to an index for the FC matrix
  433. for j = 1:length(uniquePatches)
  434. patchCount = patchCount + 1;
  435. if iscell(uniquePatches)
  436. patchID = uniquePatches{j};
  437. else
  438. patchID = uniquePatches(j);
  439. end
  440. % Create a string key regardless of input type
  441. if ischar(patchID)
  442. patchKey = patchID;
  443. else
  444. patchKey = num2str(patchID);
  445. end
  446. patchMap([networkKey '_' patchKey]) = patchCount;
  447. end
  448. end
  449. % debugged up to here
  450. % Create FC matrix (correlation matrix)
  451. FC = zeros(patchCount, patchCount);
  452. % For each patch, compute average time series
  453. patchTimeSeries = zeros(patchCount, size(vertexData, 2));
  454. for i = 1:numNetworks
  455. currentNetwork = uniqueNetworks{i};
  456. % Convert to string key for map lookup
  457. if ischar(currentNetwork)
  458. networkKey = currentNetwork;
  459. else
  460. networkKey = num2str(currentNetwork);
  461. end
  462. patches = networkMap(networkKey).patches;
  463. for j = 1:length(patches)
  464. if iscell(patches)
  465. currentPatch = patches{j};
  466. else
  467. currentPatch = patches(j);
  468. end
  469. % Handle different data types for comparison
  470. patchIDs_forcompare=cell2mat(patchIDs);
  471. if iscell(networkIDs) && iscell(patchIDs_forcompare)
  472. % doesn't work
  473. patchVertices = strcmp(networkIDs, currentNetwork) & strcmp(patchIDs_forcompare, currentPatch);
  474. elseif ~iscell(networkIDs) && ~iscell(patchIDs_forcompare)
  475. patchVertices = (networkIDs == currentNetwork) & (patchIDs_forcompare == currentPatch);
  476. elseif iscell(networkIDs) && ~iscell(patchIDs_forcompare)
  477. patchVertices = strcmp(networkIDs, currentNetwork) & (patchIDs_forcompare == currentPatch);
  478. else
  479. patchVertices = (networkIDs == currentNetwork) & strcmp(patchIDs_forcompare, currentPatch);
  480. end
  481. % Average time series for this patch
  482. if any(patchVertices)
  483. % Convert to string for map lookup
  484. if ischar(currentPatch)
  485. patchKey = currentPatch;
  486. else
  487. patchKey = num2str(currentPatch);
  488. end
  489. patchIdx = patchMap([networkKey '_' patchKey]);
  490. patchTimeSeries(patchIdx, :) = mean(vertexData(patchVertices, :), 1);
  491. end
  492. end
  493. end
  494. % Compute correlation matrix (FC)
  495. FC = corrcoef(patchTimeSeries');
  496. if ~noPlot
  497. % Create figure
  498. figure('Position', [100, 100, 1200, 1000]);
  499. % Plot the FC matrix
  500. axes('Position', [0.1, 0.1, 0.8, 0.8]);
  501. imagesc(FC, [-1, 1]);
  502. %colormap(redbluecmap);
  503. colorbar;
  504. end
  505. % Create labels for the axes
  506. axisLabels = cell(patchCount, 1);
  507. networkBoundaries = zeros(numNetworks+1, 1);
  508. networkBoundaries(1) = 0.5;
  509. % Tick positions and labels
  510. tickPositions = [];
  511. networkCenters = [];
  512. for i = 1:numNetworks
  513. currentNetwork = uniqueNetworks{i};
  514. % Convert to string key for map lookup
  515. if ischar(currentNetwork)
  516. networkKey = currentNetwork;
  517. else
  518. networkKey = num2str(currentNetwork);
  519. end
  520. patches = networkMap(networkKey).patches;
  521. startIdx = networkMap(networkKey).startIdx;
  522. % Calculate center position for this network's label
  523. networkCenter = startIdx + (length(patches)-1)/2;
  524. networkCenters = [networkCenters; networkCenter];
  525. for j = 1:length(patches)
  526. if iscell(patches)
  527. currentPatch = patches{j};
  528. else
  529. currentPatch = patches(j);
  530. end
  531. % Convert to string for map lookup
  532. if ischar(currentPatch)
  533. patchKey = currentPatch;
  534. else
  535. patchKey = num2str(currentPatch);
  536. end
  537. patchIdx = patchMap([networkKey '_' patchKey]);
  538. % Format label based on type
  539. if ischar(currentPatch)
  540. axisLabels{patchIdx} = currentPatch;
  541. else
  542. axisLabels{patchIdx} = num2str(currentPatch);
  543. end
  544. tickPositions = [tickPositions; patchIdx];
  545. end
  546. networkBoundaries(i+1) = startIdx + length(patches) - 0.5;
  547. end
  548. if ~noPlot
  549. % Set axis ticks and labels
  550. set(gca, 'XTick', tickPositions, 'XTickLabel', axisLabels, 'XTickLabelRotation', 90,'FontSize',8);
  551. set(gca, 'YTick', tickPositions, 'YTickLabel', axisLabels);
  552. % Draw network boundaries
  553. hold on;
  554. for i = 1:length(networkBoundaries)
  555. % Horizontal lines
  556. if i > 1
  557. line([0.5, patchCount+0.5], [networkBoundaries(i), networkBoundaries(i)], 'Color', 'k', 'LineWidth', 2);
  558. end
  559. % Vertical lines
  560. if i > 1
  561. line([networkBoundaries(i), networkBoundaries(i)], [0.5, patchCount+0.5], 'Color', 'k', 'LineWidth', 2);
  562. end
  563. end
  564. % Add network colors on the left and top using the provided RGB values
  565. axisWidth = 0.05;
  566. % Colors on the left
  567. axes('Position', [0.05, 0.1, axisWidth, 0.8]);
  568. colorMap = zeros(patchCount, 3);
  569. end
  570. % problem is here
  571. for i = 1:numNetworks
  572. currentNetwork = uniqueNetworks{i};
  573. % Convert to string key for map lookup
  574. if ischar(currentNetwork)
  575. networkKey = currentNetwork;
  576. else
  577. networkKey = num2str(currentNetwork);
  578. end
  579. startIdx = networkMap(networkKey).startIdx;
  580. patches = networkMap(networkKey).patches;
  581. numPatches = length(patches);
  582. % Get the color for this network
  583. colorIdx=find(strcmp(labels,networkKey));
  584. %colorIdx = min(i, size(networkColors, 1));
  585. networkColor = networkColors(colorIdx, :);
  586. % Fill the color block for this network
  587. colorMap(startIdx:(startIdx+numPatches-1), :) = repmat(networkColor, numPatches, 1);
  588. end
  589. if ~noPlot
  590. imagesc((1:patchCount)', 'CDataMapping', 'direct');
  591. colormap(gca, colorMap);
  592. axis off;
  593. % Colors on the top
  594. axes('Position', [0.1, 0.9, 0.76, axisWidth]);
  595. imagesc(1:patchCount, 'CDataMapping', 'direct');
  596. colormap(gca, colorMap);
  597. axis off;
  598. % Return to main axes and label
  599. axes('Position', [0.1, 0.1, 0.8, 0.8], 'Visible', 'off');
  600. title('Functional Connectivity Matrix by Network and Patch', 'FontSize', 16);
  601. % Save as PDF
  602. print('-dpdf', 'FunctionalConnectivity.pdf','-bestfit');
  603. end
  604. end
  605. function [metrics,networksInBoth] = calculateFCSimilarity(refFC, refNetworkMap, testFC, testNetworkMap)
  606. % Calculate similarity between functional connectivity matrices
  607. % across different data lengths, comparing only networks that exist in both
  608. %
  609. % Inputs:
  610. % refFC - Reference FC matrix (NxN, where N is the total number of patches)
  611. % refNetworkMap - Structure with fields for each network containing:
  612. % - patches: indices of patches belonging to the network
  613. % - startIdx: starting index for the network
  614. % testFC - Test FC matrix to compare against reference
  615. % testNetworkMap - Network map for the test data
  616. %
  617. % Outputs:
  618. % similarity - Correlation similarity between average FC values (upper triangle only)
  619. % networksInBoth - Cell array of networks found in both datasets
  620. % Get the network names from both maps
  621. refNetworks = refNetworkMap.keys;
  622. testNetworks = testNetworkMap.keys;
  623. % Find networks that exist in both datasets
  624. networksInBoth = intersect(refNetworks, testNetworks);
  625. % Create average FC matrices for networks in both datasets
  626. numNetworks = length(networksInBoth);
  627. refNetFC_avg = zeros(numNetworks, numNetworks);
  628. testNetFC_avg = zeros(numNetworks, numNetworks);
  629. %% quick do modularity and efficiency
  630. geff1=efficiency_wei(refFC);
  631. geff2=efficiency_wei(testFC);
  632. geff_dif=abs(geff2-geff1);
  633. %
  634. [~,Q1]=modularity_louvain_und_sign(refFC);
  635. [~,Q2]=modularity_louvain_und_sign(testFC);
  636. modularity_dif=abs(Q1-Q2);
  637. % For each pair of networks, calculate the average FC
  638. for i = 1:numNetworks
  639. netI = networksInBoth{i};
  640. % Get true patch indices for network i in reference data
  641. refPatchesI = refNetworkMap(netI).patches + (refNetworkMap(netI).startIdx - 1);
  642. % Get true patch indices for network i in test data
  643. testPatchesI = testNetworkMap(netI).patches + (testNetworkMap(netI).startIdx - 1);
  644. for j = 1:numNetworks
  645. netJ = networksInBoth{j};
  646. % Get true patch indices for network j in reference data
  647. refPatchesJ = refNetworkMap(netJ).patches + (refNetworkMap(netJ).startIdx - 1);
  648. % Get true patch indices for network j in test data
  649. testPatchesJ = testNetworkMap(netJ).patches + (testNetworkMap(netJ).startIdx - 1);
  650. % Calculate average FC between networks i and j
  651. refNetFC_avg(i,j) = mean(mean(refFC(refPatchesI, refPatchesJ)));
  652. testNetFC_avg(i,j) = mean(mean(testFC(testPatchesI, testPatchesJ)));
  653. end
  654. end
  655. % figure;
  656. % imagesc(refNetFC_avg)
  657. % figure;
  658. % imagesc(testNetFC_avg)
  659. % Extract only the upper triangular part (including diagonal)
  660. % to avoid counting symmetric pairs twice
  661. upperTri_mask = triu(true(numNetworks));
  662. % Get values from upper triangular part
  663. refValues = refNetFC_avg(upperTri_mask);
  664. testValues = testNetFC_avg(upperTri_mask);
  665. % Calculate correlation between these values
  666. similarity = corr(refValues, testValues);
  667. participation_coef1=participation_coef_sign(refNetFC_avg,1:length(networksInBoth));
  668. participation_coef2=participation_coef_sign(testNetFC_avg,1:length(networksInBoth));
  669. participation_sim=corrcoef(participation_coef1,participation_coef2,'rows','complete');
  670. participation_sim=participation_sim(1,2);
  671. metrics=[similarity,participation_sim,modularity_dif,geff_dif];
  672. end

makeFC.m, no license · at the source

Overview

Authors: Isaac N Treves1,2, David Pagliaccio1,2, Gaurav H Patel1,3, Reem Tamimi4, Jihoon A Kimerty1,5, Randy P Auerbach1,2, Hilary A Marusak4,6,7
ORCID iDs: Isaac N Treves
  1. Department of Psychiatry, Columbia University Irving Medical Center, New York, NY 10032, USA
  2. Division of Child and Adolescent Psychiatry, New York State Psychiatric Institute, New York, NY 10032, USA
  3. Division of Experimental Therapeutics, New York State Psychiatric Institute, New York, NY 10032, USA
  4. Department of Psychiatry and Behavioral Neurosciences, Wayne State University School of Medicine, 3901 Chrysler Service Dr., Detroit, MI 48201, USA
  5. Department of Psychiatry, Weill Cornell Medicine, New York, NY 10065, USA
  6. Merrill Palmer Skillman Institute for Child and Family Development, Wayne State University, 71 East Ferry Street, Detroit, MI 48202, USA
  7. Department of Pharmacology, Wayne State University School of Medicine, 540 E Canfield St, Detroit, MI 48201, USA
Journal: Developmental cognitive neuroscience, volume 81, article 101789
Dates: received 26 October 2025; accepted 23 July 2026; published online 24 July 2026; in print July 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1016/j.dcn.2026.101789 · PMID 42508279 · PMCID PMC13446092 · OpenAlex W7170783909
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: fMRI (modality), human (organism), developmental (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions, Preprocessing, Connectivity, fMRI & imaging
Keywords: Precision functional mapping, PFM, Adolescents, FMRI, Topology, Individualized network, Feasibility
Topic: Functional Brain Connectivity Studies (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: NIMH NIH HHS (K01 MH119241, R01 MH132830); NICHD NIH HHS (R21 HD105882)
Citations: not cited yet (Europe PMC); 51 references in the paper

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

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 6 files
Software Heritage: not checked
Found in: “Data availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
29 files

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:

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://doi.org/10.1016/j.dcn.2026.101789

BibTeX

@article{treves2026feasibility,
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/j.dcn.2026.101789},
url = {https://doi.org/10.1016/j.dcn.2026.101789},
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/07/24
VL - 81
SP - 101789
SN - 1878-9293
PB - Elsevier
DO - 10.1016/j.dcn.2026.101789
UR - https://doi.org/10.1016/j.dcn.2026.101789
LA - en
ER -

CSL-JSON

{
"id": "10.1016/j.dcn.2026.101789",
"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": "Dev Cogn Neurosci",
"volume": "81",
"page": "101789",
"DOI": "10.1016/j.dcn.2026.101789",
"PMID": "42508279",
"PMCID": "PMC13446092",
"ISSN": "1878-9293",
"publisher": "Elsevier",
"URL": "https://doi.org/10.1016/j.dcn.2026.101789",
"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: Neuron
In 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: Psychoradiology
In 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 brain
Journal: 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 brain
Journal: 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 communications
In 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 communications
In 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.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

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.