OSCR

Heritability of movie-evoked brain activity and connectivity.

Code ↔ Paper

11 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 11 matches · 3 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
  1. [1] § Methods › fMRI data ↔ matlab_code/isc_heritability.m, lines 2169–2208 · score 0.73 · onset transients, rest blocks, preceded, montage, clips, ISC
  2. [2] § Methods › Hyperalignment ↔ python_code/pymvpa_hyperalignment.ipynb, lines 38–171 · score 0.69 · transformation matrices, piecewise hyperalignment, connectivity hyperalignment, Procrustes, CHA, parcellation
  3. [3] § Results › Heritable movie-evoked BOLD time courses reflect heritable cortical topographies ↔ matlab_code/isc_heritability.m, lines 447–539 · score 0.67 · power law, hyperaligned heritability, response hyperalignment, connectivity hyperalignment, hyperalignment parcel, MSM
  4. [4] § Methods › Functional connectivity (FC) ↔ matlab_code/dependencies/computeNetworkMagnitude.m, the whole file · a weak match · score 0.63 · FC strengths, FC matrices, network combination, connections, parcel, heritability
  5. [5] § Results › Movie-evoked FC profiles are heritable and reflect heritable cortical topographies ↔ matlab_code/fc_heritability.m, lines 7–36 · score 0.60 · Dorsal Attention, FC heritability, Somatomotor, FD, Language, Auditory
  6. [6] § Methods › ISC and FC profile heritability analyses ↔ matlab_code/isc_heritability.m, lines 1837–1877 · score 0.59 · absolute error, full sample heritability, subsample, Spearman, correlations, parcel
  7. [7] § Methods › Hyperalignment ↔ matlab_code/dependencies/computeNetworkMagnitude.m, the whole file · a weak match · score 0.56 · parcellation resolutions, functional connectivity, Pearson, model, piecewise, matrix
  8. [8] § Methods › Relationships between parcel area and heritability ↔ matlab_code/dependencies/runISCHeritability.m, the whole file · a weak match · score 0.56 · wb_command, Schaefer atlas, vertex, cortex, parcel, heritability
  9. [9] § Results › Movie-evoked FC profiles are heritable and reflect heritable cortical topographies ↔ matlab_code/fc_heritability.m, lines 1094–1145 · score 0.53 · power law, response hyperalignment, connectivity hyperalignment, FC profile, Heatmaps, SEM
  10. [10] § Methods › Relationships between parcel area and heritability ↔ matlab_code/isc_heritability.m, lines 447–539 · score 0.53 · power law model, nonlinear, parcel areas, fit, MSM, squares
  11. [11] § Methods › Neural timescale (NT) analyses ↔ matlab_code/isc_heritability.m, lines 1617–1733 · score 0.52 · family compliant, tailed, Spearman, FDR, timescale, Neural

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 · 2,345 lines · 102 KB · MIT · 5 matches

  1. %%%%%%%%
  2. % Author: David Gruskin
  3. % Contact: [email hidden]
  4. % Project: Heritability of movie-evoked brain activity and connectivity
  5. % Description: This is the main analysis and visualization script for the
  6. % ISC component of the HCP 7T ISC heritability project.
  7. %%%%%%%%
  8. %% Add and set relevant paths
  9. desktop_dir = '/path/to/desktop';
  10. downloads_dir = '/path/to/downloads';
  11. data_dir = '/path/to/data';
  12. % ------------------------------------------------------------------------
  13. addpath([data_dir '/isc_heritability/'])
  14. addpath([downloads_dir '/github_repo/bounded_lines'])
  15. addpath([downloads_dir '/github_repo/inpaint_nans'])
  16. addpath(desktop_dir)
  17. addpath([data_dir '/restsync'])
  18. addpath([downloads_dir '/npy-matlab-master/npy-matlab'])
  19. addpath([data_dir '/isc_heritability/matlab_scripts/h2_multi-master/h2_multi/'])
  20. addpath([data_dir '/restsync/inputs/scripts'])
  21. addpath([downloads_dir '/gifti-main-2/'])
  22. addpath([data_dir '/restsync/inputs/scripts/cifti-matlab-master'])
  23. addpath(fullfile(fileparts(mfilename('fullpath')), 'dependencies')) % helper functions shipped in matlab_code/dependencies
  24. addpath([desktop_dir '/isc_heritability_r'])
  25. addpath([downloads_dir '/palm-alpha119'])
  26. schaefer_400_dscalar = [desktop_dir '/Schaefer2018_400Parcels_17Networks_order.dscalar.nii'];
  27. schaefer_400_pscalar = [desktop_dir '/Schaefer2018_400Parcels_17Networks_order.pscalar.nii'];
  28. schaefer_400_pscalar_kong = [desktop_dir '/Schaefer2018_400Parcels_Kong2022_17Networks_order.pscalar.nii'];
  29. schaefer_100_pscalar_kong = [desktop_dir '/Schaefer2018_100Parcels_Kong2022_17Networks_order.pscalar.nii'];
  30. schaefer_1000_pscalar_kong = [desktop_dir '/Schaefer2018_1000Parcels_Kong2022_17Networks_order.pscalar.nii'];
  31. schaefer_400_label = [desktop_dir '/Schaefer2018_400Parcels_17Networks_order.dlabel.nii'];
  32. pscalar_template = [desktop_dir '/schaefer_400_round2.pscalar.nii'];
  33. medial_mask_path = [data_dir '/isc_heritability_review/mat_files/supporting_files/medial_mask.csv'];
  34. pheno_table_path = [data_dir '/restsync/inputs/accessory_files/hcp_7t_pheno.csv'];
  35. pheno_restricted_table_path = [downloads_dir '/inputs/RESTRICTED_<your_hcp_file>.csv']; % HCP restricted behavioral/kinship CSV; supply your own (filename differs per download)
  36. base_dir = [data_dir '/isc_heritability/data/'];
  37. wb_path = '/path/to/workbench/bin/wb_command';
  38. %% Load some preliminary files
  39. load([data_dir '/isc_heritability_review/mat_files/supporting_files/covari_motion.mat'])
  40. load([data_dir '/isc_heritability_review/mat_files/supporting_files/family_ids.mat'])
  41. load kong_transform.mat
  42. scalar_template = schaefer_400_dscalar;
  43. % align_types to loop over
  44. align_types = {'piecewise';'anatomical'};
  45. % Set up medial mask variables
  46. medial_mask = csvread(medial_mask_path);
  47. medial_mask_lh = medial_mask(1:32492);
  48. medial_mask_rh = medial_mask(32493:end);
  49. schaefer_dscalar = ciftiopen(schaefer_400_dscalar);
  50. vox_ids = schaefer_dscalar.cdata;
  51. vox_ids(medial_mask==0) = [];
  52. num_trs = [1432, 1409];
  53. % Set some basic variables and functions
  54. parc_reses = {'100','200','300','400','500','600','700','800','900','1000'};
  55. hvec = @(x) x(triu(true(size(x)), 1));
  56. isemptycell = @(x) cellfun(@isempty, x);
  57. num_vox_cortex = 59412;
  58. num_parcs = 10;
  59. num_days = 2;
  60. num_fams = 90;
  61. num_subj = 184;
  62. num_perm = 10000;
  63. exclude_rest = [8,66,124,126,130,135,179,183];
  64. subjs_rest = 1:num_subj;
  65. subjs_rest(exclude_rest) = [];
  66. exclude_movie = [66,124,126,130,135,183];
  67. subjs_movie = 1:num_subj;
  68. subjs_movie(exclude_movie) = [];
  69. num_subj_movie = length(subjs_movie);
  70. num_subj_rest = length(subjs_rest);
  71. pheno_table = readtable(pheno_table_path);
  72. pheno_restricted = readtable(pheno_restricted_table_path);
  73. pheno_restricted.Family_ID = string(pheno_restricted.Family_ID);
  74. % Get unique family IDs
  75. unique_famids = unique(pheno_restricted.Family_ID);
  76. % Create a mapping (container) from the unique family IDs to a sequence of integers
  77. famid_mapping = containers.Map(unique_famids, 1:length(unique_famids));
  78. % Apply the mapping to the Family_ID column
  79. % Vectorized approach for efficiency
  80. mapped_famids = arrayfun(@(x) famid_mapping(x), pheno_restricted.Family_ID);
  81. % Update the Family_ID column with the mapped values
  82. pheno_restricted.Family_ID = mapped_famids;
  83. movie_fam_ids = pheno_restricted.Family_ID(subjs_movie);
  84. rest_fam_ids = pheno_restricted.Family_ID(subjs_rest);
  85. pheno_restricted_subset = pheno_restricted(subjs_movie,:);
  86. pheno_restricted_subset.Zygosity = pheno_restricted_subset.ZygosityGT;
  87. pheno_restricted.Zygosity = pheno_restricted.ZygosityGT;
  88. pheno_restricted_subset.Zygosity(isemptycell(pheno_restricted_subset.Zygosity)) = pheno_restricted_subset.ZygositySR(isemptycell(pheno_restricted_subset.Zygosity));
  89. pheno_restricted.Zygosity(isemptycell(pheno_restricted.Zygosity)) = pheno_restricted.ZygositySR(isemptycell(pheno_restricted.Zygosity));
  90. mztwin_new = cell(num_subj,1);
  91. dztwin_new = cell(num_subj,1);
  92. for subj1 = 1:num_subj
  93. for subj2 = 1:num_subj
  94. if subj1~=subj2
  95. if pheno_restricted.Family_ID(subj1) == pheno_restricted.Family_ID(subj2) && strcmp(pheno_restricted.Zygosity(subj1),'MZ') && strcmp(pheno_restricted.Zygosity(subj2),'MZ')
  96. mztwin_new{subj1} = pheno_restricted.Family_ID(subj1);
  97. elseif pheno_restricted.Family_ID(subj1) == pheno_restricted.Family_ID(subj2) && strcmp(pheno_restricted.Zygosity(subj1),'DZ') && strcmp(pheno_restricted.Zygosity(subj2),'DZ')
  98. dztwin_new{subj1} = pheno_restricted.Family_ID(subj1);
  99. end
  100. end
  101. end
  102. end
  103. flat_array_mz = vertcat(mztwin_new{:});
  104. % Find unique elements and sort them
  105. [unique_elements, ~, idx] = unique(flat_array_mz);
  106. % Create a mapping (integer representation for each unique element)
  107. % Starting index from 1
  108. mapping = 1:length(unique_elements);
  109. % Replace elements in mztwin_new with their corresponding integers
  110. % Initialize the output array with NaNs
  111. MZTWIN = nan(num_subj, 1);
  112. for i = 1:length(mztwin_new)
  113. if ~isempty(mztwin_new{i})
  114. MZTWIN(i) = nanmean(mapping(idx(flat_array_mz == mztwin_new{i})));
  115. end
  116. end
  117. flat_array_dz = vertcat(dztwin_new{:});
  118. % Find unique elements and sort them
  119. [unique_elements, ~, idx] = unique(flat_array_dz);
  120. % Create a mapping (integer representation for each unique element)
  121. % Starting index from 1
  122. mapping = 1:length(unique_elements);
  123. % Replace elements in mztwin_new with their corresponding integers
  124. % Initialize the output array with NaNs
  125. DZTWIN = nan(num_subj, 1);
  126. for i = 1:length(dztwin_new)
  127. if ~isempty(dztwin_new{i})
  128. DZTWIN(i) = nanmean(mapping(idx(flat_array_dz == dztwin_new{i})));
  129. end
  130. end
  131. %% Get dyad ids
  132. kinship = zeros(num_subj,num_subj);
  133. for subj1 = 1:num_subj
  134. for subj2 = 1:num_subj
  135. if subj1 == subj2
  136. kinship(subj1,subj2) = 1;
  137. elseif MZTWIN(subj1) == MZTWIN(subj2)
  138. kinship(subj1,subj2) = 1;
  139. elseif family_ids(subj1,2) == family_ids(subj2,2)
  140. kinship(subj1,subj2) = 0.5;
  141. end
  142. end
  143. end
  144. gender_var = grp2idx(categorical(pheno_table.Gender));
  145. ages = pheno_restricted.Age_in_Yrs;
  146. % Initialize the arrays and counters
  147. pairwise_mz_id = zeros(1,1);
  148. pairwise_dz_id = zeros(1,1);
  149. pairwise_nz_id = zeros(1,1);
  150. processedPairs = false(num_subj_movie, num_subj_movie); % Logical array to track processed pairs
  151. dz_counter = 1;
  152. mz_counter = 1;
  153. nz_counter = 1;
  154. total_counter = 1;
  155. for subj1 = 1:num_subj_movie
  156. for subj2 = 1:num_subj_movie
  157. if subj1 ~= subj2
  158. % Check if this pair has already been processed
  159. if ~processedPairs(subj1, subj2) && ~processedPairs(subj2, subj1)
  160. % Process the pair
  161. if DZTWIN(subjs_movie(subj1)) == DZTWIN(subjs_movie(subj2)) && ~isnan(DZTWIN(subjs_movie(subj2)))
  162. pairwise_dz_id(dz_counter,1) = total_counter;
  163. dz_counter = dz_counter + 1;
  164. elseif MZTWIN(subjs_movie(subj1)) == MZTWIN(subjs_movie(subj2)) && ~isnan(MZTWIN(subjs_movie(subj1)))
  165. pairwise_mz_id(mz_counter,1) = total_counter;
  166. mz_counter = mz_counter + 1;
  167. elseif gender_var(subjs_movie(subj1)) == gender_var(subjs_movie(subj2)) && abs(ages(subjs_movie(subj1))-ages(subjs_movie(subj2)))<1 && family_ids(subjs_movie(subj1)) ~= family_ids(subjs_movie(subj2))
  168. pairwise_nz_id(nz_counter,1) = total_counter;
  169. nz_counter = nz_counter + 1;
  170. end
  171. % Mark this pair as processed
  172. processedPairs(subj1, subj2) = true;
  173. processedPairs(subj2, subj1) = true;
  174. end
  175. end
  176. % Increment total counter regardless of whether the pair was processed
  177. total_counter = total_counter + 1;
  178. end
  179. end
  180. % Initialize the arrays and counters
  181. pairwise_mz_id_rest = zeros(1,1);
  182. pairwise_dz_id_rest = zeros(1,1);
  183. pairwise_nz_id_rest = zeros(1,1);
  184. processedPairs = false(num_subj_rest, num_subj_rest); % Logical array to track processed pairs
  185. dz_counter = 1;
  186. mz_counter = 1;
  187. nz_counter = 1;
  188. total_counter = 1;
  189. for subj1 = 1:num_subj_rest
  190. for subj2 = 1:num_subj_rest
  191. if subj1 ~= subj2
  192. % Check if this pair has already been processed
  193. if ~processedPairs(subj1, subj2) && ~processedPairs(subj2, subj1)
  194. % Process the pair
  195. if DZTWIN(subjs_movie(subj1)) == DZTWIN(subjs_movie(subj2)) && ~isnan(DZTWIN(subjs_movie(subj2)))
  196. pairwise_dz_id_rest(dz_counter,1) = total_counter;
  197. dz_counter = dz_counter + 1;
  198. elseif MZTWIN(subjs_movie(subj1)) == MZTWIN(subjs_movie(subj2)) && ~isnan(MZTWIN(subjs_movie(subj1)))
  199. pairwise_mz_id_rest(mz_counter,1) = total_counter;
  200. mz_counter = mz_counter + 1;
  201. elseif gender_var(subjs_movie(subj1)) == gender_var(subjs_movie(subj2)) && abs(ages(subjs_movie(subj1))-ages(subjs_movie(subj2)))<1 && family_ids(subjs_movie(subj1)) ~= family_ids(subjs_movie(subj2))
  202. pairwise_nz_id_rest(nz_counter,1) = total_counter;
  203. nz_counter = nz_counter + 1;
  204. end
  205. % Mark this pair as processed
  206. processedPairs(subj1, subj2) = true;
  207. processedPairs(subj2, subj1) = true;
  208. end
  209. end
  210. % Increment total counter regardless of whether the pair was processed
  211. total_counter = total_counter + 1;
  212. end
  213. end
  214. age_mean = mean(ages(subjs_movie));
  215. age_std = std(ages(subjs_movie));
  216. age_min = min(ages(subjs_movie));
  217. age_max = max(ages(subjs_movie));
  218. hisp_perc = sum(grp2idx(categorical(pheno_restricted.Ethnicity(subjs_movie)))==1)/num_subj_movie;
  219. white_perc = sum(grp2idx(categorical(pheno_restricted.Race(subjs_movie)))==4)/num_subj_movie;
  220. black_perc = sum(grp2idx(categorical(pheno_restricted.Race(subjs_movie)))==2)/num_subj_movie;
  221. asian_perc = sum(grp2idx(categorical(pheno_restricted.Race(subjs_movie)))==1)/num_subj_movie;
  222. unknown_perc = sum(grp2idx(categorical(pheno_restricted.Race(subjs_movie)))==3)/num_subj_movie;%
  223. nonEmptyCellsCount = sum(~cellfun(@isempty, pheno_restricted.ZygosityGT(subjs_movie)));
  224. %% Run anatomical ISC analyses
  225. if exist(strcat(base_dir,'anatomical/outputs/gray/anatomical_isc_herit.mat'),'file') == 2
  226. load(strcat(base_dir,'anatomical/outputs/gray/anatomical_isc_herit.mat'))
  227. load(strcat(base_dir,'anatomical/outputs/gray/anatomical_isc_herit_jack.mat'))
  228. load(strcat(base_dir,'anatomical/outputs/parc/anatomical_isc_herit_parc.mat'))
  229. load(strcat(base_dir,'anatomical/outputs/parc/anatomical_isc_herit_parc_perm.mat'))
  230. else
  231. anatomical_isc_herit = zeros(num_vox_cortex,2); anatomical_isc_herit_perm = zeros(num_vox_cortex,2); anatomical_isc_herit_jack = zeros(num_vox_cortex,length(unique(movie_fam_ids)),2);
  232. anatomical_isc_herit_parc = cell(10,1); anatomical_isc_herit_parc_perm = cell(10,1); anatomical_isc_herit_parc_jack = cell(10,1);
  233. for scan_id = 1:num_days
  234. [anatomical_isc_herit(:,scan_id), anatomical_isc_herit_perm(:,scan_id),anatomical_isc_herit_jack(:,:,scan_id)] = runISCHeritability('400', base_dir, kinship, subjs_movie,'anatomical','gray',pairwise_mz_id,pairwise_dz_id,pairwise_nz_id,scan_id,covari_motion,num_perm,[]);
  235. for parc_id = 4
  236. curr_parc = parc_reses{parc_id};
  237. [anatomical_isc_herit_parc{parc_id,1}(:,scan_id), anatomical_isc_herit_parc_perm{parc_id,1}(:,scan_id),anatomical_isc_herit_parc_jack{parc_id,1}(:,:,scan_id)] = runISCHeritability(curr_parc, base_dir, kinship, subjs_movie,'anatomical','parc',pairwise_mz_id,pairwise_dz_id,pairwise_nz_id,scan_id,covari_motion,num_perm,movie_fam_ids);
  238. end
  239. end
  240. save(strcat(base_dir,'anatomical/outputs/gray/anatomical_isc_herit.mat'),'anatomical_isc_herit')
  241. save(strcat(base_dir,'anatomical/outputs/gray/anatomical_isc_herit_jack.mat'),'anatomical_isc_herit_jack')
  242. save(strcat(base_dir,'anatomical/outputs/parc/anatomical_isc_herit_parc.mat'),'anatomical_isc_herit_parc')
  243. save(strcat(base_dir,'anatomical/outputs/parc/anatomical_isc_herit_parc_perm.mat'),'anatomical_isc_herit_parc_perm')
  244. end
  245. % Get % of parcels significant on both days and mean/std
  246. % heritability
  247. isc_heritability_parc_pValues = anatomical_isc_herit_parc_perm{4,1}(:,:);
  248. isc_heritability_parc_pValues_fdr = zeros(size(isc_heritability_parc_pValues,1),num_days);
  249. for scan_id = 1:num_days
  250. isc_heritability_parc_pValues_fdr(:,scan_id) = fdr_bh(isc_heritability_parc_pValues(:,scan_id));
  251. end
  252. isc_heritability_parc_pValues_perc = sum(isc_heritability_parc_pValues_fdr(:,1).*isc_heritability_parc_pValues_fdr(:,2))/400;
  253. isc_heritability_parc_mean = mean(anatomical_isc_herit_parc{4,1});
  254. isc_heritability_parc_std = std(anatomical_isc_herit_parc{4,1});
  255. % For paper, get correlation between heritability maps and heritability/ISC
  256. isc_heritability_parc_trt = corr(anatomical_isc_herit_parc{4,1}(:,:),'type','spearman','rows','complete');
  257. if num_perm == 10000
  258. save(strcat(base_dir,'anatomical/outputs/gray/anatomical_isc_herit_perm.mat'),'anatomical_isc_herit_perm')
  259. save(strcat(base_dir,'anatomical/outputs/parc/anatomical_isc_herit_parc.mat'),'anatomical_isc_herit_parc_perm')
  260. end
  261. [p_val,anatomical_se(:,1),anatomical_se(:,2)] = compareHeritability(nanmean(anatomical_isc_herit(:,1)),nanmean(anatomical_isc_herit_jack(:,:,1),1),nanmean(anatomical_isc_herit(:,2)),nanmean(anatomical_isc_herit_jack(:,:,2),1));
  262. % Correlate heritability and ISC maps
  263. anat_isc_parc = zeros(400,num_days);
  264. herit_isc_parc = zeros(400,num_days);
  265. herit_isc_corr = zeros(1,num_days);
  266. isc_herit_resid = zeros(400,num_days);
  267. for scan_id = 1:num_days
  268. data = ciftiopen(strcat(base_dir,'anatomical/outputs/parc/anatomical_isc_parc_400_scan_',num2str(scan_id),'.pscalar.nii'));
  269. anat_isc_parc(:,scan_id) = data.cdata;
  270. data = ciftiopen(strcat(base_dir,'anatomical/outputs/parc/anatomical_isc_herit_parc_400_scan_',num2str(scan_id),'.pscalar.nii'));
  271. herit_isc_parc(:,scan_id) = data.cdata;
  272. big_ids = find(anat_isc_parc(:,scan_id)>median(anat_isc_parc(:,scan_id)));
  273. small_ids = find(anat_isc_parc(:,scan_id)<median(anat_isc_parc(:,scan_id)));
  274. herit_isc_corr(1,scan_id) = corr(anat_isc_parc(:,scan_id),herit_isc_parc(:,scan_id),'type','spearman');
  275. mdl = fitlm(anat_isc_parc(:,scan_id),herit_isc_parc(:,scan_id));
  276. isc_herit_resid(:,scan_id) = mdl.Residuals{:,1};
  277. saveCifti(isc_herit_resid(:,scan_id), strcat([data_dir '/isc_heritability/data/anatomical/outputs/parc/anatomical_isc_herit_raw_residuals_parc_'],curr_parc,'_day',num2str(scan_id),'.pscalar.nii'), wb_path, schaefer_400_pscalar_kong,medial_mask);
  278. end
  279. %% Run piecewise ISC analyses
  280. parpool('Threads')
  281. if exist(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit.mat'),'file') == 2
  282. load(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit.mat'))
  283. load(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit_jack.mat'))
  284. else
  285. piecewise_isc_herit = zeros(num_vox_cortex,num_parcs,num_days);
  286. piecewise_isc_herit_perm = zeros(num_vox_cortex,num_parcs,num_days);
  287. piecewise_isc_herit_jack = zeros(num_vox_cortex,num_fams,num_parcs,num_days);
  288. for parc_id = 1:length(parc_reses)
  289. curr_parc = parc_reses{parc_id};
  290. for scan_id = 1:num_days
  291. [piecewise_isc_herit(:,parc_id,scan_id), piecewise_isc_herit_perm(:,parc_id,scan_id),piecewise_isc_herit_jack(:,:,parc_id,scan_id)] = runISCHeritability(curr_parc, base_dir, kinship, subjs_movie,'piecewise','gray',pairwise_mz_id,pairwise_dz_id,pairwise_nz_id,scan_id,covari_motion,num_perm,movie_fam_ids);
  292. save(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit_jack.mat'),'piecewise_isc_herit_jack')
  293. end
  294. end
  295. save(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit.mat'),'piecewise_isc_herit')
  296. save(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit_jack.mat'),'piecewise_isc_herit_jack')
  297. end
  298. if num_perm == 10000
  299. save(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit_perm.mat'),'piecewise_isc_herit_perm')
  300. end
  301. piecewise_isc_se = zeros(num_parcs,num_days);
  302. for parc_id = 1:num_parcs
  303. for scan_id = 1:num_days
  304. [~,~,piecewise_isc_se(parc_id,scan_id)] = compareHeritability(0,nanmean(piecewise_isc_herit_jack(:,:,parc_id,scan_id),1),0,nanmean(piecewise_isc_herit_jack(:,:,parc_id,scan_id),1));
  305. end
  306. end
  307. %% Run connectivity ISC analyses
  308. if exist(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_herit.mat'),'file') == 2
  309. load(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_herit.mat'))
  310. load(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_herit_jack.mat'))
  311. else
  312. connectivity_isc_herit = zeros(num_vox_cortex,num_parcs,num_days);
  313. connectivity_isc_herit_perm = zeros(num_vox_cortex,num_parcs,num_days);
  314. connectivity_isc_herit_jack = zeros(num_vox_cortex,num_fams,num_parcs,num_days);
  315. for parc_id = 1:num_parcs
  316. curr_parc = parc_reses{parc_id};
  317. for scan_id = 1:num_days
  318. [connectivity_isc_herit(:,parc_id,scan_id), connectivity_isc_herit_perm(:,parc_id,scan_id),connectivity_isc_herit_jack(:,:,parc_id,scan_id)] = runISCHeritability(curr_parc, base_dir, kinship, subjs_rest,'connectivity','gray',pairwise_mz_id_rest,pairwise_dz_id_rest,pairwise_nz_id_rest,scan_id,covari_motion,num_perm,rest_fam_ids);
  319. save(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_herit_jack.mat'),'connectivity_isc_herit_jack')
  320. end
  321. end
  322. save(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_herit.mat'),'connectivity_isc_herit')
  323. save(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_herit_jack.mat'),'connectivity_isc_herit_jack')
  324. end
  325. if num_perm == 10000
  326. save(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_herit_perm.mat'),'connectivity_isc_herit_perm')
  327. end
  328. connectivity_isc_se = zeros(num_parcs,num_days);
  329. for parc_id = 1:num_parcs
  330. for scan_id = 1:num_days
  331. [~,~,connectivity_isc_se(parc_id,scan_id)] = compareHeritability(0,nanmean(connectivity_isc_herit_jack(:,:,parc_id,scan_id),1),0,nanmean(connectivity_isc_herit_jack(:,:,parc_id,scan_id),1));
  332. end
  333. end
  334. %% Make difference CIFTIs
  335. curr_parc = '400';
  336. for scan_id = 1:num_days
  337. anatomical_img = ciftiopen(strcat([data_dir '/isc_heritability/data/anatomical/outputs/gray/anatomical_isc_herit_parc_'],curr_parc,'_day',num2str(scan_id),'.pscalar.nii'));
  338. piecewise_img = ciftiopen(strcat([data_dir '/isc_heritability/data/piecewise/outputs/gray/piecewise_isc_herit_parc_'],curr_parc,'_day',num2str(scan_id),'.pscalar.nii'));
  339. connectivity_img = ciftiopen(strcat([data_dir '/isc_heritability/data/connectivity/outputs/gray/connectivity_isc_herit_parc_'],curr_parc,'_day',num2str(scan_id),'.pscalar.nii'));
  340. saveCifti(piecewise_img.cdata-anatomical_img.cdata, strcat([data_dir '/isc_heritability/data/piecewise/outputs/parc/piecewise_anatomical_isc_herit_diff_parc_'],curr_parc,'_day',num2str(scan_id),'.pscalar.nii'), wb_path, schaefer_400_pscalar,medial_mask);
  341. saveCifti(connectivity_img.cdata-anatomical_img.cdata, strcat([data_dir '/isc_heritability/data/connectivity/outputs/parc/connectivity_anatomical_isc_herit_diff_parc_'],curr_parc,'_day',num2str(scan_id),'.pscalar.nii'), wb_path, schaefer_400_pscalar,medial_mask);
  342. end
  343. %% Get average area per parcel
  344. right_areas = gifti([data_dir '/isc_heritability/mat_files/supporting_files/right_areas.func.gii']);
  345. right_areas = right_areas.cdata;
  346. left_areas = gifti([data_dir '/isc_heritability/mat_files/supporting_files/left_areas.func.gii']);
  347. left_areas = left_areas.cdata;
  348. all_areas = cat(1,left_areas,right_areas);
  349. all_areas = all_areas(medial_mask==1);
  350. parc_areas = cell(num_parcs,1);
  351. parc_ids = zeros(num_vox_cortex,num_parcs);
  352. avg_areas = zeros(num_parcs,1);
  353. for parc_id = 1:length(parc_reses)
  354. parc_res = parc_reses{parc_id};
  355. current_parc = strcat('Schaefer2018_',parc_res,'Parcels_17Networks_order.dscalar.nii');
  356. parc_ids_temp = ciftiopen(strcat(desktop_dir, '/', current_parc),wb_path);
  357. parc_ids(:,parc_id) = parc_ids_temp.cdata(medial_mask==1);
  358. for parc_val = 1:max(parc_ids(:,parc_id))
  359. parc_areas{parc_id,1}(parc_val,1) = sum(all_areas(parc_ids(:,parc_id)==parc_val));
  360. end
  361. avg_areas(parc_id,1) = mean(parc_areas{parc_id,1});
  362. end
  363. %% Compare hyperalignment heritability difference to area
  364. connectivity_perc = zeros(1,num_days);
  365. hold on
  366. x_min = 0;
  367. x_max = max(avg_areas) * 1.5;
  368. x_extended = linspace(x_min, x_max, 10000);
  369. piecewise_fits = cell(num_days, 1);
  370. connectivity_fits = cell(num_days, 1);
  371. for scan_id = 1:num_days
  372. subplot(2,1,scan_id)
  373. hold on
  374. % Calculate means and SEMs
  375. mean_movie_herit = nanmean(anatomical_isc_herit(:,scan_id));
  376. mean_piecewise = squeeze(nanmean(piecewise_isc_herit(:,:,scan_id)));
  377. sem_piecewise = piecewise_isc_se(:,scan_id);
  378. mean_connectivity = squeeze(nanmean(connectivity_isc_herit(:,:,scan_id)));
  379. sem_connectivity = connectivity_isc_se(:,scan_id);
  380. sem_movie = nanmean(anatomical_se(:,scan_id));
  381. mean_piecewise = [mean_piecewise';mean_movie_herit];
  382. mean_connectivity = [mean_connectivity';mean_movie_herit];
  383. % Define custom power law model including y-intercept
  384. customModel = fittype('a*x^b + c', 'independent', 'x', 'dependent', 'y');
  385. options = fitoptions('Method', 'NonlinearLeastSquares');
  386. options.Lower = [-Inf, -Inf, -Inf]; % Adjust lower bounds as necessary
  387. options.Upper = [Inf, Inf, Inf]; % Adjust upper bounds as necessary
  388. options.StartPoint = [1, 1, 0]; % Adjust start points as necessary
  389. % Fit custom model for piecewise data
  390. [fitresult_piecewise, gof_piecewise] = fit([avg_areas;0], mean_piecewise, customModel, options);
  391. piecewise_fits{scan_id} = struct('FitResult', fitresult_piecewise, 'GOF', gof_piecewise);
  392. % Fit custom model for connectivity data
  393. [fitresult_connectivity, gof_connectivity] = fit([avg_areas;0], mean_connectivity, customModel, options);
  394. connectivity_fits{scan_id} = struct('FitResult', fitresult_connectivity, 'GOF', gof_connectivity);
  395. % Additional plotting and analysis code remains the same
  396. % Ensure to replace any instance of plotting or evaluating the fit with the new model
  397. % For example, calculating new y values for the extended x range using the fit results
  398. y_extended_piecewise = feval(fitresult_piecewise, x_extended);
  399. y_extended_connectivity = feval(fitresult_connectivity, x_extended);
  400. % Plotting the extended power law lines
  401. plot(x_extended, y_extended_piecewise, 'LineWidth', 4, 'Color', [254/255 97/255 0/255]);
  402. plot(x_extended, y_extended_connectivity, 'LineWidth', 4, 'Color', [120/255 94/255 240/255]);
  403. % boundedline plots
  404. hl1 = boundedline(avg_areas, mean_piecewise(1:10), sem_piecewise, 'alpha', 'cmap', [254/255 97/255 0/255],'LineWidth',.00001);
  405. hl2 = boundedline(avg_areas, mean_connectivity(1:10), sem_connectivity, 'alpha', 'cmap', [120/255 94/255 240/255],'LineWidth',.00001);
  406. % Doubling the line thickness in boundedline plots
  407. set(hl1, 'LineWidth', .001);
  408. set(hl2, 'LineWidth', .0001);
  409. % Scatter plots for mean values
  410. scatter(avg_areas, mean_piecewise(1:10), 150, 'filled', 'MarkerFaceColor', [254/255 97/255 0/255], 'MarkerEdgeColor', 'k','LineWidth',3);
  411. scatter(avg_areas, mean_connectivity(1:10), 150, 'filled', 'MarkerFaceColor', [120/255 94/255 240/255], 'MarkerEdgeColor', 'k','LineWidth',3);
  412. scatter(0, mean_movie_herit, 150, 'filled', 'MarkerFaceColor', 'k', 'MarkerEdgeColor', 'k');
  413. % SEM plot for movieNetHerit_mag (as a vertical line)
  414. errorbar(0, mean_movie_herit, sem_movie, 'Color', 'k', 'LineStyle', '-', 'LineWidth', 5);
  415. % Axes settings
  416. ylim([.01 .025]); xlim([-100 1200]);
  417. xlabel('Average Hyperalignment Parcel Area (mm^2)'); ylabel('% of MSM-aligned Heritability');
  418. yticks([.01 .015 .02 .025]); ax = gca; set(ax, 'TickDir', 'out'); set(ax, 'FontSize', 32); set(ax, 'LineWidth', 5); set(ax, 'Layer', 'bottom');
  419. xticks([0 400 800 1200]);set(ax, 'TickDir', 'out')
  420. grid off; legend({'Response Hyperalignment', 'Connectivity Hyperalignment'}, 'Location', 'best'); set(gcf, 'position', [100,100,600,1200]);
  421. pbaspect([1.5 1 1])
  422. piecewise_perc(1,scan_id) = 1-(mean_piecewise(1)/mean_movie_herit);
  423. connectivity_perc(1,scan_id) = 1-(mean_connectivity(1)/mean_movie_herit);
  424. piecewise_conf(1,scan_id) = 1-((mean_piecewise(1) - (sem_piecewise(1)*1.96))/mean_movie_herit);
  425. piecewise_conf(2,scan_id) = 1-((mean_piecewise(1) + (sem_piecewise(1)*1.96))/mean_movie_herit);
  426. connectivity_conf(1,scan_id) = 1-((mean_connectivity(1) - (sem_connectivity(1)*1.96))/mean_movie_herit);
  427. connectivity_conf(2,scan_id) = 1-((mean_connectivity(1) + (sem_connectivity(1)*1.96))/mean_movie_herit);
  428. end
  429. saveas(gcf,[data_dir '/isc_heritability/figures/fig3_areascatter_power.svg'])
  430. close all
  431. %% Compare hyperalignment heritability difference to area
  432. connectivity_perc = zeros(1,num_days);
  433. hold on
  434. x_min = 0;
  435. x_max = max(avg_areas) * 1.5;
  436. x_extended = linspace(x_min, x_max, 10000);
  437. linear_fits_piecewise = cell(num_days, 1);
  438. linear_fits_connectivity = cell(num_days, 1);
  439. for scan_id = 1:num_days
  440. subplot(2,1,scan_id)
  441. hold on
  442. % Calculate means and SEMs
  443. mean_movie_herit = nanmean(anatomical_isc_herit(:,scan_id));
  444. mean_piecewise = squeeze(nanmean(piecewise_isc_herit(:,:,scan_id)));
  445. sem_piecewise = piecewise_isc_se(:,scan_id);
  446. mean_connectivity = squeeze(nanmean(connectivity_isc_herit(:,:,scan_id)));
  447. sem_connectivity = connectivity_isc_se(:,scan_id);
  448. sem_movie = nanmean(anatomical_se(:,scan_id));
  449. mean_piecewise = [mean_piecewise';mean_movie_herit];
  450. mean_connectivity = [mean_connectivity';mean_movie_herit];
  451. % Fit a linear model for piecewise data
  452. [fitresult_piecewise, gof_piecewise] = fit([avg_areas;0], mean_piecewise, 'poly1');
  453. linear_fits_piecewise{scan_id} = struct('FitResult', fitresult_piecewise, 'GOF', gof_piecewise);
  454. % Fit a linear model for connectivity data
  455. [fitresult_connectivity, gof_connectivity] = fit([avg_areas;0], mean_connectivity, 'poly1');
  456. linear_fits_connectivity{scan_id} = struct('FitResult', fitresult_connectivity, 'GOF', gof_connectivity);
  457. % Plot the extended linear fit lines
  458. y_extended_piecewise = feval(fitresult_piecewise, x_extended);
  459. y_extended_connectivity = feval(fitresult_connectivity, x_extended);
  460. plot(x_extended, y_extended_piecewise, 'LineWidth', 4, 'Color', [254/255 97/255 0/255]);
  461. plot(x_extended, y_extended_connectivity, 'LineWidth', 4, 'Color', [120/255 94/255 240/255]);
  462. % boundedline plots
  463. hl1 = boundedline(avg_areas, mean_piecewise(1:10), sem_piecewise, 'alpha', 'cmap', [254/255 97/255 0/255],'LineWidth',.00001);
  464. hl2 = boundedline(avg_areas, mean_connectivity(1:10), sem_connectivity, 'alpha', 'cmap', [120/255 94/255 240/255],'LineWidth',.00001);
  465. % Doubling the line thickness in boundedline plots
  466. set(hl1, 'LineWidth', .001);
  467. set(hl2, 'LineWidth', .0001);
  468. % Scatter plots for mean values
  469. scatter(avg_areas, mean_piecewise(1:10), 150, 'filled', 'MarkerFaceColor', [254/255 97/255 0/255], 'MarkerEdgeColor', 'k','LineWidth',3);
  470. scatter(avg_areas, mean_connectivity(1:10), 150, 'filled', 'MarkerFaceColor', [120/255 94/255 240/255], 'MarkerEdgeColor', 'k','LineWidth',3);
  471. scatter(0, mean_movie_herit, 150, 'filled', 'MarkerFaceColor', 'k', 'MarkerEdgeColor', 'k');
  472. % SEM plot for movieNetHerit_mag (as a vertical line)
  473. errorbar(0, mean_movie_herit, sem_movie, 'Color', 'k', 'LineStyle', '-', 'LineWidth', 5);
  474. % Axes settings
  475. ylim([.01 .025]); xlim([-100 1200]);
  476. xlabel('Average Hyperalignment Parcel Area (mm^2)'); ylabel('% of MSM-aligned Heritability');
  477. yticks([.01 .015 .02 .025]); ax = gca; set(ax, 'TickDir', 'out'); set(ax, 'FontSize', 32); set(ax, 'LineWidth', 5); set(ax, 'Layer', 'bottom');
  478. xticks([0 400 800 1200]);set(ax, 'TickDir', 'out')
  479. grid off; legend({'Response Hyperalignment', 'Connectivity Hyperalignment'}, 'Location', 'best'); set(gcf, 'position', [100,100,600,1200]);
  480. pbaspect([1.5 1 1])
  481. piecewise_perc(1,scan_id) = 1-(mean_piecewise(1)/mean_movie_herit);
  482. connectivity_perc(1,scan_id) = 1-(mean_connectivity(1)/mean_movie_herit);
  483. piecewise_conf(1,scan_id) = 1-((mean_piecewise(1) - (sem_piecewise(1)*1.96))/mean_movie_herit);
  484. piecewise_conf(2,scan_id) = 1-((mean_piecewise(1) + (sem_piecewise(1)*1.96))/mean_movie_herit);
  485. connectivity_conf(1,scan_id) = 1-((mean_connectivity(1) - (sem_connectivity(1)*1.96))/mean_movie_herit);
  486. connectivity_conf(2,scan_id) = 1-((mean_connectivity(1) + (sem_connectivity(1)*1.96))/mean_movie_herit);
  487. end
  488. saveas(gcf,[data_dir '/isc_heritability/figures/fig3_areascatter_linear.fig'])
  489. close all
  490. log_fits_piecewise = cell(num_days, 1);
  491. log_fits_connectivity = cell(num_days, 1);
  492. for scan_id = 1:num_days
  493. subplot(2,1,scan_id)
  494. hold on
  495. % Calculate means and SEMs
  496. mean_movie_herit = nanmean(anatomical_isc_herit(:,scan_id));
  497. mean_piecewise = squeeze(nanmean(piecewise_isc_herit(:,:,scan_id)));
  498. sem_piecewise = piecewise_isc_se(:,scan_id);
  499. mean_connectivity = squeeze(nanmean(connectivity_isc_herit(:,:,scan_id)));
  500. sem_connectivity = connectivity_isc_se(:,scan_id);
  501. sem_movie = nanmean(anatomical_se(:,scan_id));
  502. mean_piecewise = [mean_piecewise';mean_movie_herit];
  503. mean_connectivity = [mean_connectivity';mean_movie_herit];
  504. % Define a logarithmic model: y = a * log(x) + b
  505. logModel = fittype('a*log(x) + b', 'independent', 'x', 'dependent', 'y');
  506. options = fitoptions('Method', 'NonlinearLeastSquares');
  507. options.StartPoint = [1, 0]; % Adjust start points as necessary
  508. options.Lower = [-Inf, -Inf]; % Adjust lower bounds as necessary
  509. options.Upper = [Inf, Inf]; % Adjust upper bounds as necessary
  510. % Fit logarithmic model for piecewise data
  511. [fitresult_piecewise, gof_piecewise] = fit([avg_areas;1], mean_piecewise, logModel, options);
  512. log_fits_piecewise{scan_id} = struct('FitResult', fitresult_piecewise, 'GOF', gof_piecewise);
  513. % Fit logarithmic model for connectivity data
  514. [fitresult_connectivity, gof_connectivity] = fit([avg_areas;1], mean_connectivity, logModel, options);
  515. log_fits_connectivity{scan_id} = struct('FitResult', fitresult_connectivity, 'GOF', gof_connectivity);
  516. % Plot the extended logarithmic fit lines
  517. y_extended_piecewise = feval(fitresult_piecewise, x_extended);
  518. y_extended_connectivity = feval(fitresult_connectivity, x_extended);
  519. plot(x_extended, y_extended_piecewise, 'LineWidth', 4, 'Color', [254/255 97/255 0/255]);
  520. plot(x_extended, y_extended_connectivity, 'LineWidth', 4, 'Color', [120/255 94/255 240/255]);
  521. % boundedline plots
  522. hl1 = boundedline(avg_areas, mean_piecewise(1:10), sem_piecewise, 'alpha', 'cmap', [254/255 97/255 0/255],'LineWidth',.00001);
  523. hl2 = boundedline(avg_areas, mean_connectivity(1:10), sem_connectivity, 'alpha', 'cmap', [120/255 94/255 240/255],'LineWidth',.00001);
  524. % Doubling the line thickness in boundedline plots
  525. set(hl1, 'LineWidth', .001);
  526. set(hl2, 'LineWidth', .0001);
  527. % Scatter plots for mean values
  528. scatter(avg_areas, mean_piecewise(1:10), 150, 'filled', 'MarkerFaceColor', [254/255 97/255 0/255], 'MarkerEdgeColor', 'k','LineWidth',3);
  529. scatter(avg_areas, mean_connectivity(1:10), 150, 'filled', 'MarkerFaceColor', [120/255 94/255 240/255], 'MarkerEdgeColor', 'k','LineWidth',3);
  530. scatter(1, mean_movie_herit, 150, 'filled', 'MarkerFaceColor', 'k', 'MarkerEdgeColor', 'k');
  531. % SEM plot for movieNetHerit_mag (as a vertical line)
  532. errorbar(1, mean_movie_herit, sem_movie, 'Color', 'k', 'LineStyle', '-', 'LineWidth', 5);
  533. % Axes settings
  534. ylim([.01 .025]); xlim([-100 1200]);
  535. xlabel('Average Hyperalignment Parcel Area (mm^2)'); ylabel('% of MSM-aligned Heritability');
  536. yticks([.01 .015 .02 .025]); ax = gca; set(ax, 'TickDir', 'out'); set(ax, 'FontSize', 32); set(ax, 'LineWidth', 5); set(ax, 'Layer', 'bottom');
  537. xticks([0 400 800 1200]); set(ax, 'TickDir', 'out')
  538. grid off; legend({'Response Hyperalignment', 'Connectivity Hyperalignment'}, 'Location', 'best'); set(gcf, 'position', [100,100,600,1200]);
  539. pbaspect([1.5 1 1])
  540. piecewise_perc(1,scan_id) = 1-(mean_piecewise(1)/mean_movie_herit);
  541. connectivity_perc(1,scan_id) = 1-(mean_connectivity(1)/mean_movie_herit);
  542. piecewise_conf(1,scan_id) = 1-((mean_piecewise(1) - (sem_piecewise(1)*1.96))/mean_movie_herit);
  543. piecewise_conf(2,scan_id) = 1-((mean_piecewise(1) + (sem_piecewise(1)*1.96))/mean_movie_herit);
  544. connectivity_conf(1,scan_id) = 1-((mean_connectivity(1) - (sem_connectivity(1)*1.96))/mean_movie_herit);
  545. connectivity_conf(2,scan_id) = 1-((mean_connectivity(1) + (sem_connectivity(1)*1.96))/mean_movie_herit);
  546. end
  547. saveas(gcf,[data_dir '/isc_heritability/figures/fig3_areascatter_log.svg'])
  548. saveas(gcf,[data_dir '/isc_heritability/figures/fig3_areascatter_log.fig'])
  549. close all
  550. poly_fits_piecewise = cell(num_days, 1);
  551. poly_fits_connectivity = cell(num_days, 1);
  552. % Define the polynomial degree
  553. poly_degree = 2; % For example, degree 2 polynomial (quadratic)
  554. for scan_id = 1:num_days
  555. subplot(2,1,scan_id)
  556. hold on
  557. % Calculate means and SEMs
  558. mean_movie_herit = nanmean(anatomical_isc_herit(:,scan_id));
  559. mean_piecewise = squeeze(nanmean(piecewise_isc_herit(:,:,scan_id)));
  560. sem_piecewise = piecewise_isc_se(:,scan_id);
  561. mean_connectivity = squeeze(nanmean(connectivity_isc_herit(:,:,scan_id)));
  562. sem_connectivity = connectivity_isc_se(:,scan_id);
  563. sem_movie = nanmean(anatomical_se(:,scan_id));
  564. mean_piecewise = [mean_piecewise';mean_movie_herit];
  565. mean_connectivity = [mean_connectivity';mean_movie_herit];
  566. % Polynomial model (degree 2)
  567. polynomialModel = fittype('a*x^2 + b*x + c', 'independent', 'x', 'dependent', 'y');
  568. options = fitoptions(polynomialModel);
  569. options.StartPoint = [1, 1, 0]; % Set reasonable starting points for a, b, and c
  570. % Fit polynomial model for piecewise data, including x = 0
  571. [fitresult_piecewise, gof_piecewise] = fit([avg_areas; 0], mean_piecewise, polynomialModel, options);
  572. poly_fits_piecewise{scan_id} = struct('FitResult', fitresult_piecewise, 'GOF', gof_piecewise);
  573. % Fit polynomial model for connectivity data, including x = 0
  574. [fitresult_connectivity, gof_connectivity] = fit([avg_areas; 0], mean_connectivity, polynomialModel, options);
  575. poly_fits_connectivity{scan_id} = struct('FitResult', fitresult_connectivity, 'GOF', gof_connectivity);
  576. % Plot the extended polynomial fit lines for x >= 0
  577. valid_x_extended = x_extended(x_extended >= 0); % Restrict x to non-negative values
  578. y_extended_piecewise = feval(fitresult_piecewise, valid_x_extended);
  579. y_extended_connectivity = feval(fitresult_connectivity, valid_x_extended);
  580. plot(valid_x_extended, y_extended_piecewise, 'LineWidth', 4, 'Color', [254/255 97/255 0/255]);
  581. plot(valid_x_extended, y_extended_connectivity, 'LineWidth', 4, 'Color', [120/255 94/255 240/255]);
  582. % boundedline plots
  583. hl1 = boundedline(avg_areas, mean_piecewise(1:10), sem_piecewise, 'alpha', 'cmap', [254/255 97/255 0/255], 'LineWidth', .00001);
  584. hl2 = boundedline(avg_areas, mean_connectivity(1:10), sem_connectivity, 'alpha', 'cmap', [120/255 94/255 240/255], 'LineWidth', .00001);
  585. % Doubling the line thickness in boundedline plots
  586. set(hl1, 'LineWidth', .001);
  587. set(hl2, 'LineWidth', .0001);
  588. % Scatter plots for mean values
  589. scatter(avg_areas, mean_piecewise(1:10), 150, 'filled', 'MarkerFaceColor', [254/255 97/255 0/255], 'MarkerEdgeColor', 'k', 'LineWidth', 3);
  590. scatter(avg_areas, mean_connectivity(1:10), 150, 'filled', 'MarkerFaceColor', [120/255 94/255 240/255], 'MarkerEdgeColor', 'k', 'LineWidth', 3);
  591. scatter(0, mean_movie_herit, 150, 'filled', 'MarkerFaceColor', 'k', 'MarkerEdgeColor', 'k');
  592. % SEM plot for movieNetHerit_mag (as a vertical line)
  593. errorbar(0, mean_movie_herit, sem_movie, 'Color', 'k', 'LineStyle', '-', 'LineWidth', 5);
  594. % Axes settings
  595. ylim([.01 .025]); xlim([-100 1200]); % Limit x to non-negative range
  596. xlabel('Average Hyperalignment Parcel Area (mm^2)'); ylabel('% of MSM-aligned Heritability');
  597. yticks([.01 .015 .02 .025]); ax = gca; set(ax, 'TickDir', 'out'); set(ax, 'FontSize', 32); set(ax, 'LineWidth', 5); set(ax, 'Layer', 'bottom');
  598. xticks([0 400 800 1200]); set(ax, 'TickDir', 'out');
  599. grid off; legend({'Response Hyperalignment', 'Connectivity Hyperalignment'}, 'Location', 'best'); set(gcf, 'position', [100,100,600,1200]);
  600. pbaspect([1.5 1 1]);
  601. % Confidence calculations
  602. piecewise_perc(1,scan_id) = 1 - (mean_piecewise(1)/mean_movie_herit);
  603. connectivity_perc(1,scan_id) = 1 - (mean_connectivity(1)/mean_movie_herit);
  604. piecewise_conf(1,scan_id) = 1 - ((mean_piecewise(1) - (sem_piecewise(1)*1.96))/mean_movie_herit);
  605. piecewise_conf(2,scan_id) = 1 - ((mean_piecewise(1) + (sem_piecewise(1)*1.96))/mean_movie_herit);
  606. connectivity_conf(1,scan_id) = 1 - ((mean_connectivity(1) - (sem_connectivity(1)*1.96))/mean_movie_herit);
  607. connectivity_conf(2,scan_id) = 1 - ((mean_connectivity(1) + (sem_connectivity(1)*1.96))/mean_movie_herit);
  608. end
  609. saveas(gcf,[data_dir '/isc_heritability/figures/fig3_areascatter_poly.svg']);
  610. saveas(gcf,[data_dir '/isc_heritability/figures/fig3_areascatter_poly.fig']);
  611. close all;
  612. %% Make ISC MZ/DZ/NZ line plots
  613. % FIGURE 1 LINES
  614. anatomical_parc_dir = [data_dir '/isc_heritability/data/anatomical/outputs/parc/'];
  615. % Initialize anatomical similarity matrices
  616. anatomical_isc_similarity_mz_parc_all = zeros(length(pairwise_mz_id), 400, num_days);
  617. anatomical_isc_similarity_dz_parc_all = zeros(length(pairwise_dz_id), 400, num_days);
  618. anatomical_isc_similarity_nz_parc_all = zeros(length(pairwise_nz_id), 400, num_days);
  619. anatomical_isc_parc_all = zeros(400,num_days);
  620. for scan_id = 1:num_days
  621. iscDataPath = (strcat(anatomical_parc_dir,'anatomical_isc_scan_',num2str(scan_id),'.mat'));
  622. isc = load(iscDataPath);
  623. name = fieldnames(isc);
  624. isc = isc.(name{1});
  625. % Now separate out for MZ, DZ, and NZ
  626. for parc = 1:size(isc,3)
  627. isc_temp = squeeze(isc(:,:,parc));
  628. [m, n] = size(isc_temp);
  629. isc_temp(triu(true(m, n))) = NaN;
  630. anatomical_isc_similarity_mz_parc_all(:,parc,scan_id) = isc_temp(pairwise_mz_id);
  631. anatomical_isc_similarity_dz_parc_all(:,parc,scan_id) = isc_temp(pairwise_dz_id);
  632. anatomical_isc_similarity_nz_parc_all(:,parc,scan_id) = isc_temp(pairwise_nz_id);
  633. end
  634. isc(isc==1)= NaN;
  635. anatomical_isc_parc_all(:,scan_id) = conv_z2r(squeeze(nanmean(nanmean(conv_r2z(isc)))));
  636. end
  637. % Concatenate data
  638. all_xz_isc = cat(2, ...
  639. conv_z2r(squeeze(nanmean(conv_r2z(anatomical_isc_similarity_mz_parc_all), 1))), ...
  640. conv_z2r(squeeze(nanmean(conv_r2z(anatomical_isc_similarity_dz_parc_all), 1))), ...
  641. conv_z2r(squeeze(nanmean(conv_r2z(anatomical_isc_similarity_nz_parc_all), 1))));
  642. % Initialize matrices
  643. mz_std_mat = zeros(size(anatomical_isc_similarity_mz_parc_all, 2), num_days);
  644. dz_std_mat = mz_std_mat;
  645. nz_std_mat = mz_std_mat;
  646. sortIndex1 = mz_std_mat;
  647. % Loop through each scan
  648. for scan_id = 1:num_days
  649. mz_std_mat(:, scan_id) = conv_z2r(nanstd(conv_r2z(anatomical_isc_similarity_mz_parc_all(:,:,scan_id)))' / sqrt(sum(~isnan(anatomical_isc_similarity_mz_parc_all(:,1,scan_id)))));
  650. dz_std_mat(:, scan_id) = conv_z2r(nanstd(conv_r2z(anatomical_isc_similarity_dz_parc_all(:,:,scan_id)))' / sqrt(sum(~isnan(anatomical_isc_similarity_dz_parc_all(:,1,scan_id)))));
  651. nz_std_mat(:, scan_id) = conv_z2r(nanstd(conv_r2z(anatomical_isc_similarity_nz_parc_all(:,:,scan_id)))' / sqrt(sum(~isnan(anatomical_isc_similarity_nz_parc_all(:,1,scan_id)))));
  652. % Sorting and plotting
  653. [~, sortIndex1(:, scan_id)] = sort(anatomical_isc_parc_all(:, scan_id), 1);
  654. sorted_means = all_xz_isc(sortIndex1(:, scan_id), [scan_id, scan_id + 2, scan_id + 4]);
  655. sortIndex_curr = sortIndex1(:, scan_id);
  656. mz_std_mat_sorted = mz_std_mat(sortIndex_curr, scan_id);
  657. dz_std_mat_sorted = dz_std_mat(sortIndex_curr, scan_id);
  658. nz_std_mat_sorted = nz_std_mat(sortIndex_curr, scan_id);
  659. sorted_std_errors = cat(2, mz_std_mat_sorted, dz_std_mat_sorted, nz_std_mat_sorted);
  660. subplot(1, 2, scan_id)
  661. % Create a new x-axis vector
  662. x = 1:size(anatomical_isc_parc_all,1);
  663. % Plot each line with its shaded error region
  664. color_vec = [[100/255, 143/255, 255/255]; [220/255, 38/255, 127/255]; [255/255, 176/255, 0/255]]; % colors for each line
  665. for i = 1:size(sorted_means, 2)
  666. boundedline(x, (sorted_means(:, i)), (sorted_std_errors(:, i)), 'cmap', color_vec(i, :), 'alpha','linewidth',2);
  667. hold on;
  668. end
  669. ylim([0, 1])
  670. xlim([0, size(anatomical_isc_parc_all,1)])
  671. xlabel('Parcel Rank')
  672. ylabel('ISC (r)')
  673. yticks([0, 0.25, .5, .75, 1])
  674. % Customize axes
  675. ax = gca;
  676. set(ax, 'TickDir', 'out', 'FontSize', 20, 'LineWidth', 3, 'Layer', 'bottom')
  677. grid off
  678. legend({'', 'MZ', '', 'DZ', '', 'UR', ''})
  679. pbaspect([1, 1, 1])
  680. end
  681. % Save the figure
  682. set(gcf, 'position', [100, 100, 1200, 1200])
  683. saveas(gcf, [data_dir '/isc_heritability/figures/fig1_ISClines_avgsort_parc.fig'])
  684. %% ISC group scatter plots (MZ vs DZ, MZ vs UR, DZ vs UR)
  685. %% Group ISC arrays: pull dimensions
  686. P = size(anatomical_isc_similarity_mz_parc_all, 1); % # parcels
  687. D = size(anatomical_isc_similarity_mz_parc_all, 3); % # days
  688. %% Ensure DZ/UR arrays are [parcels x subjects x days]
  689. % DZ:
  690. if size(anatomical_isc_similarity_dz_parc_all,1) ~= P && size(anatomical_isc_similarity_dz_parc_all,2) == P
  691. anatomical_isc_similarity_dz_parc_all = permute(anatomical_isc_similarity_dz_parc_all, [2 1 3]);
  692. end
  693. % UR (nZ):
  694. if size(anatomical_isc_similarity_nz_parc_all,1) ~= P && size(anatomical_isc_similarity_nz_parc_all,2) == P
  695. anatomical_isc_similarity_nz_parc_all = permute(anatomical_isc_similarity_nz_parc_all, [2 1 3]);
  696. end
  697. %% Parcel-wise mean ISC per group and day
  698. P = size(anatomical_isc_similarity_mz_parc_all,2);
  699. D = size(anatomical_isc_similarity_mz_parc_all,3); % should be 2 for two days
  700. mz_day = nan(P, D);
  701. dz_day = nan(P, D);
  702. ur_day = nan(P, D);
  703. for d = 1:D
  704. mz_day(:,d) = conv_z2r( nanmean( conv_r2z(anatomical_isc_similarity_mz_parc_all(:,:,d)), 1 ) );
  705. dz_day(:,d) = conv_z2r( nanmean( conv_r2z(anatomical_isc_similarity_dz_parc_all(:,:,d)), 1 ) );
  706. ur_day(:,d) = conv_z2r( nanmean( conv_r2z(anatomical_isc_similarity_nz_parc_all(:,:,d)), 1 ) );
  707. end
  708. %% Scatter grid (rows = days; cols = MZxDZ, MZxUR, DZxUR)
  709. figure;
  710. pairNames = {'MZ','DZ','UR'};
  711. combos = [1 2; 1 3; 2 3]; % which pairs to plot
  712. for d = 1:D
  713. for k = 1:3
  714. idx = (d-1)*3 + k;
  715. subplot(D, 3, idx);
  716. % pick the two ISC vectors for this day
  717. X = eval([lower(pairNames{combos(k,1)}), '_day(:,d)']);
  718. Y = eval([lower(pairNames{combos(k,2)}), '_day(:,d)']);
  719. % scatter with black edge
  720. h = scatter(X, Y, 50, 'filled', 'MarkerEdgeColor', 'k');
  721. h.MarkerFaceAlpha = 0.8;
  722. h.LineWidth = 0.5;
  723. hold on;
  724. % unity line
  725. mn = min([X;Y]); mx = max([X;Y]);
  726. plot([mn mx], [mn mx], 'k--', 'LineWidth', 1);
  727. % styling
  728. axis square;
  729. xlim([0 .6]); ylim([0 .6]);
  730. xlabel([pairNames{combos(k,1)}, ' ISC (r)']);
  731. ylabel([pairNames{combos(k,2)}, ' ISC (r)']);
  732. title(sprintf('Day %d: %s vs. %s', d, pairNames{combos(k,1)}, pairNames{combos(k,2)}));
  733. % Pearson r
  734. R = corr(X, Y, 'Rows', 'complete');
  735. text(0.05, 0.9, sprintf('r = %.2f', R), 'Units', 'normalized', 'FontSize', 11);
  736. set(gca, 'FontSize', 12, 'LineWidth', 1, 'TickDir', 'out', 'Layer', 'bottom');
  737. end
  738. end
  739. set(gcf, 'Position', [200 200 1200 700]);
  740. %% Parcellate Schaefer files and raw data
  741. parc_reses = {'100','200','300','400','500','600','700','800','900','1000'};
  742. schaefer_dlabel = cell(num_parcs,1);
  743. for parc_res_id = 1:length(parc_reses)
  744. curr_parc = parc_reses{parc_res_id};
  745. schaefer_dlabel{parc_res_id} = strcat(desktop_dir, '/Schaefer2018_',curr_parc,'Parcels_17Networks_order.dlabel.nii');
  746. parc_path = strcat(desktop_dir, '/Schaefer2018_',curr_parc,'Parcels_17Networks_order.dscalar.nii');
  747. parc_command = strcat(wb_path,{' '},'-cifti-parcellate',{' '},parc_path,{' '},schaefer_dlabel{parc_res_id},{' '},'COLUMN',{' '} ,strrep(parc_path,'dscalar','pscalar'));
  748. system(parc_command{1})
  749. schaefer_dlabel_kong = strcat(desktop_dir, '/Schaefer2018_',curr_parc,'Parcels_Kong2022_17Networks_order.dlabel.nii');
  750. parc_path = strcat(desktop_dir, '/Schaefer2018_',curr_parc,'Parcels_Kong2022_17Networks_order.dscalar.nii');
  751. parc_command = strcat(wb_path,{' '},'-cifti-parcellate',{' '},parc_path,{' '},schaefer_dlabel_kong,{' '},'COLUMN',{' '} ,strrep(parc_path,'dscalar','pscalar'));
  752. system(parc_command{1})
  753. end
  754. iscHeritabilityParcellate([data_dir '/isc_heritability/data/anatomical/inputs/parc/'], 'raw_data_lh_movie_', num_subj_movie,parc_reses,schaefer_400_label,'400');
  755. iscHeritabilityParcellate([data_dir '/isc_heritability/data/anatomical/inputs/parc/'], 'raw_data_lh_rest_', num_subj_movie,parc_reses,schaefer_400_label,'400');
  756. %% Show difference in ISC heritability after hyperalignment (Fig. 4D)
  757. piecewise_diff_out = zeros(num_vox_cortex,num_days);
  758. connectivity_diff_out = zeros(num_vox_cortex,num_days);
  759. for scan_id = 1:num_days
  760. for vox = 1:num_vox_cortex
  761. piecewise_vals = piecewise_isc_herit(vox, 1, scan_id);
  762. connectivity_vals = connectivity_isc_herit(vox, 1, scan_id);
  763. idxs = parc_ids(vox, :);
  764. if min(idxs) > 0
  765. c = anatomical_isc_herit(vox, scan_id);
  766. piecewise_diff = (piecewise_vals-c);
  767. connectivity_diff = (connectivity_vals-c);
  768. % Storing the results
  769. piecewise_diff_out(vox, scan_id) = (piecewise_diff);
  770. connectivity_diff_out(vox, scan_id) = (connectivity_diff);
  771. end
  772. end
  773. % Saving the results
  774. piecewise_file = fullfile(base_dir, 'piecewise/outputs/gray', ...
  775. sprintf('piecewise_herit_diff_scan_%d.dscalar.nii', scan_id));
  776. connectivity_file = fullfile(base_dir, 'connectivity/outputs/gray', ...
  777. sprintf('connectivity_herit_diff_scan_%d.dscalar.nii', scan_id));
  778. saveCifti(piecewise_diff_out(:, scan_id)', piecewise_file, wb_path, schaefer_400_dscalar, medial_mask);
  779. saveCifti(connectivity_diff_out(:, scan_id)', connectivity_file, wb_path, schaefer_400_dscalar, medial_mask);
  780. end
  781. piecewise_diff_trt = corr(piecewise_diff_out,'type','spearman','rows','complete');
  782. connectivity_diff_trt = corr(connectivity_diff_out,'type','spearman','rows','complete');
  783. piecewise_connectivity_trt(1) = corr(piecewise_diff_out(:,1),connectivity_diff_out(:,1),'type','spearman','rows','complete');
  784. piecewise_connectivity_trt(2) = corr(piecewise_diff_out(:,2),connectivity_diff_out(:,2),'type','spearman','rows','complete');
  785. %% Generate cifti distance matrices
  786. cifti_path = [desktop_dir '/inflated_brains/left_distances.dconn.nii'];
  787. left_surface = cifti_read(cifti_path,wb_path);
  788. left_surface_dist = double(left_surface.cdata);
  789. h5create([desktop_dir '/inflated_brains/distances_l.h5'],"/DS1",[32492 32492])
  790. h5write([desktop_dir '/inflated_brains/distances_l.h5'],"/DS1",left_surface_dist)
  791. cifti_path = [desktop_dir '/inflated_brains/right_distances.dconn.nii'];
  792. right_surface = cifti_read(cifti_path,wb_path);
  793. right_surface_dist = double(right_surface.cdata);
  794. h5create([desktop_dir '/inflated_brains/distances_r.h5'],"/DS1",[32492 32492])
  795. h5write([desktop_dir '/inflated_brains/distances_r.h5'],"/DS1",right_surface_dist)
  796. %% Generate RSFC matrices for CHA
  797. num_subj_rest = 176;
  798. base_dir = [data_dir '/isc_heritability/data/anatomical/inputs/gray/'];
  799. for parc_val_id = 1:length(parc_reses)
  800. parc_val = parc_reses{parc_val_id};
  801. current_parc = strcat('Schaefer2018_',parc_val,'Parcels_17Networks_order.dscalar.nii');
  802. vox_ids = ciftiopen(strcat(downloads_dir, '/ThomasYeoLab CBIG master stable_projects-brain_parcellation_Schaefer2018_LocalGlobal_Parcellations_HCP_fslr32k_cifti/',current_parc));
  803. vox_ids = vox_ids.cdata(medial_mask==1);
  804. parc_num = str2double(parc_val);
  805. for scan_id = 1:num_days
  806. cha_mat = zeros(num_vox_cortex,parc_num,num_subj_rest);
  807. for subj = 1:num_subj_rest
  808. subj_data_lh = readNPY(strcat([data_dir '/isc_heritability/data/anatomical/inputs/gray/raw_data_lh_rest_'],num2str(scan_id),'_',num2str(subj),'.npy'));
  809. subj_data_rh = readNPY(strcat([data_dir '/isc_heritability/data/anatomical/inputs/gray/raw_data_rh_rest_'],num2str(scan_id),'_',num2str(subj),'.npy'));
  810. subj_data = cat(2,subj_data_lh,subj_data_rh);
  811. parc_data = zeros(size(subj_data,2),parc_num);
  812. mean_vec = zeros(parc_num,size(subj_data,1));
  813. parfor parc_id = 1:parc_num
  814. parc_vox_ids = find(vox_ids == parc_id);
  815. mean_vec(parc_id,:) = nanmean(subj_data(:,parc_vox_ids)')';
  816. end
  817. if parc_num ~=1000
  818. cha_mat(:,:,subj) = corr(subj_data,mean_vec','rows','complete');
  819. else
  820. parfor i = 1:parc_num
  821. cha_mat(:,i,subj) = corr(subj_data,mean_vec(i,:)','rows','complete');
  822. end
  823. end
  824. end
  825. save(strcat(base_dir,'cha_mat_parc_',num2str(parc_num),'_day_',num2str(scan_id),'.mat'),'cha_mat','-v7.3')
  826. end
  827. end
  828. %% Parcellate piecewise
  829. iscHeritabilityParcellate([data_dir '/isc_heritability/data/piecewise/inputs/parc/'], 'piecewise_parc_', num_subj_movie,parc_reses(10),schaefer_dlabel{4},num_trs);
  830. %% Parcellate connectivity
  831. iscHeritabilityParcellate([data_dir '/isc_heritability/data/connectivity/inputs/parc/'], 'connectivity_parc_', num_subj_rest,parc_reses(10),schaefer_dlabel{4},num_trs);
  832. base_dir = [data_dir '/isc_heritability/data/'];
  833. %% Calculate MNT (movie neural timescale)
  834. if exist(strcat(base_dir,'anatomical/outputs/gray/mnt_gray.mat'),'file') == 2
  835. load(strcat(base_dir,'anatomical/outputs/gray/mnt_gray.mat'))
  836. else
  837. mnt_acf = zeros(num_vox_cortex,num_subj_movie,num_days);
  838. for scan_id = 1:num_days
  839. for subj = 1:num_subj_movie
  840. subj_data = readNPY(strcat([data_dir '/isc_heritability/data/anatomical/inputs/gray/anatomical_movie_scan_'], num2str(scan_id), '_subj_', num2str(subj), '.npy'));
  841. mnt_acf(:,subj,scan_id) = calculate_int(subj_data);
  842. end
  843. end
  844. save(strcat(base_dir,'anatomical/outputs/gray/mnt_gray.mat'),'mnt_acf')
  845. end
  846. if exist(strcat(base_dir,'piecewise/outputs/gray/mnt_gray.mat'),'file') == 2
  847. load(strcat(base_dir,'piecewise/outputs/gray/mnt_gray.mat'))
  848. else
  849. mnt_acf = zeros(num_vox_cortex,num_subj_movie,num_days);
  850. for scan_id = 1:num_days
  851. for subj = 1:num_subj_movie
  852. subj_data = readNPY(strcat([data_dir '/isc_heritability/data/piecewise/inputs/gray/piecewise_parc_100_scan_'], num2str(scan_id), '_subj_', num2str(subj), '.npy'));
  853. mnt_acf(:,subj,scan_id) = calculate_int(subj_data');
  854. end
  855. end
  856. save(strcat(base_dir,'piecewise/outputs/gray/mnt_gray.mat'),'mnt_acf')
  857. end
  858. %% Are MNT topographies heritable?
  859. for day_id = 1:num_days
  860. mnt_corr = corr(mnt_acf(:,:,day_id),'rows','complete','type','spearman');
  861. mnt_topo_herit(day_id) = h2_mat(mnt_corr, kinship(subjs_movie, subjs_movie), [covari_motion(subjs_movie, [1, 2, day_id + 2])], 0,[]);
  862. end
  863. schaefer_parc = ciftiopen(schaefer_400_dscalar);
  864. schaefer_parc = schaefer_parc.cdata(medial_mask==1);
  865. mnt_parc = zeros(400,num_subj_movie,num_days);
  866. for parc_id = 1:400
  867. mnt_parc(parc_id,:,:) = squeeze(nanmean(mnt_acf(schaefer_parc==parc_id,:,:),1));
  868. end
  869. for scan_id = 1:num_days
  870. csvwrite(strcat(desktop_dir, '/isc_heritability_r/mnt_movie_scan_',num2str(scan_id),'.csv'),mnt_parc(:,:,scan_id));
  871. end
  872. for day_id = 1:num_days
  873. mnt_corr = corr(mnt_parc(:,:,day_id),'type','spearman');
  874. [mnt_topo_herit_parc(day_id), p_perm(day_id), jack_se,h2_jack] = h2_mat(mnt_corr, kinship(subjs_movie, subjs_movie), [covari_motion(subjs_movie, [1, 2, day_id + 2])], 0,[]);
  875. end
  876. for scan_id = 1:num_days
  877. mnt_mag_herit{1,scan_id} = readtable(strcat([data_dir "/isc_heritability/data/solar/mnt_herit_parcel_scan_"], num2str(scan_id), ".csv"));
  878. end
  879. mnt_mag_herit_mat = zeros(400,num_days);
  880. for scan_id = 1:num_days
  881. mnt_mag_herit_mat(:,scan_id) = mnt_mag_herit{1,scan_id}.Var;
  882. end
  883. %% Is MNT associated with average heritability?
  884. % Get pairwise measures and run ANOVA
  885. mnt_avg = squeeze(nanmean(mnt_acf,1));
  886. mnt_acf_out_big = zeros(num_subj_movie,num_subj_movie,num_vox_cortex,num_days);
  887. for scan_id = 1:num_days
  888. mnt_acf_diff = pdist2(mnt_avg(:,scan_id),mnt_avg(:,scan_id),'euclidean');
  889. [m, n] = size(mnt_acf_diff);
  890. mnt_acf_diff(triu(true(m, n))) = NaN;
  891. mnt_mz(:,scan_id) = mnt_acf_diff(pairwise_mz_id);
  892. mnt_dz(:,scan_id) = mnt_acf_diff(pairwise_dz_id);
  893. mnt_nz(:,scan_id) = mnt_acf_diff(pairwise_nz_id);
  894. mnt_acf_out(:,:,scan_id) = mnt_acf_diff;
  895. parfor vox = 1:num_vox_cortex
  896. mnt_acf_out_big(:,:,vox,scan_id) = pdist2(squeeze(mnt_acf(vox,:,scan_id))',squeeze(mnt_acf(vox,:,scan_id))','euclidean');
  897. end
  898. end
  899. for scan_id = 1:num_days
  900. outliers_mz{scan_id} = find_outliers(squeeze(mnt_mz(:, scan_id)));
  901. outliers_dz{scan_id} = find_outliers(squeeze(mnt_dz(:, scan_id)));
  902. outliers_nz{scan_id} = find_outliers(squeeze(mnt_nz(:, scan_id)));
  903. mnt_mz(outliers_mz{scan_id}, scan_id) = NaN;
  904. mnt_dz(outliers_dz{scan_id}, scan_id) = NaN;
  905. mnt_nz(outliers_nz{scan_id}, scan_id) = NaN;
  906. end
  907. perc_outliers = sum(sum(outliers_nz{1}) + sum(outliers_nz{2}) +sum(outliers_dz{1}) + sum(outliers_dz{2}) + sum(outliers_mz{1}) + sum(outliers_mz{2}))/(2*sum(length(mnt_mz) + length(mnt_dz) + length(mnt_nz)));
  908. % Start MATLAB's parallel pool (use threads)
  909. if isempty(gcp('nocreate'))
  910. parpool;
  911. end
  912. % Number of regions, days, and permutations
  913. num_perms = 10000;
  914. % Data arrays
  915. dataArrays = {mnt_mz, mnt_dz, mnt_nz};
  916. % Preallocate arrays for t-scores and p-values
  917. Differences = zeros(1, 6); % 6 comparisons (3 pairs x 2 days)
  918. mnt_pvalues = zeros(1, 6);
  919. mnt_pvalues_fdr = zeros(1, 6);
  920. % Parallel computation over regions
  921. for day = 1:num_days
  922. % Actual data for each group
  923. dataMZ = dataArrays{1}(:, day);
  924. dataDZ = dataArrays{2}(:, day);
  925. dataNZ = dataArrays{3}(:, day);
  926. % Calculate actual differences
  927. diffMZDZ = nanmean(dataMZ) - nanmean(dataDZ);
  928. diffMZNZ = nanmean(dataMZ) - nanmean(dataNZ);
  929. diffDZNZ = nanmean(dataDZ) - nanmean(dataNZ);
  930. actualDifferences = [diffMZDZ, diffMZNZ, diffDZNZ];
  931. % Initialize permutation t-scores
  932. permDifferences = zeros(num_perms, 3);
  933. for perm = 1:num_perms
  934. rng(perm)
  935. % Shuffle group identities while maintaining proportions
  936. allData = [dataMZ; dataDZ; dataNZ];
  937. shuffledData = allData(randperm(length(allData)));
  938. numMZ = numel(dataMZ);
  939. numDZ = numel(dataDZ);
  940. shuffledMZ = shuffledData(1:numMZ);
  941. shuffledDZ = shuffledData(numMZ + 1:numMZ + numDZ);
  942. shuffledNZ = shuffledData(numMZ + numDZ + 1:end);
  943. % Calculate differences for shuffled data
  944. permDifferences(perm, 1, day) = nanmean(shuffledMZ) - nanmean(shuffledDZ);
  945. permDifferences(perm, 2, day) = nanmean(shuffledMZ) - nanmean(shuffledNZ);
  946. permDifferences(perm, 3, day) = nanmean(shuffledDZ) - nanmean(shuffledNZ);
  947. end
  948. % Calculate p-values
  949. for comp = 1:3
  950. mnt_pvalues((day - 1) * 3 + comp) = (sum(abs(permDifferences(:, comp, day)) >= abs(actualDifferences(comp)))+1)/(num_perms+1);
  951. end
  952. mnt_pvalues_fdr(:,(1:3) + (day-1)*3) = fdr_bh(mnt_pvalues(:,(1:3) + (day-1)*3));
  953. % Perform FDR correction for p-values corresponding to the current day
  954. start_idx = (day - 1) * 3 + 1; % Index for the first component of the current day
  955. end_idx = day * 3; % Index for the last component of the current day
  956. [h(start_idx:end_idx), crit_p(day), ~, adj_p(start_idx:end_idx)] = fdr_bh(mnt_pvalues(start_idx:end_idx));
  957. end
  958. % Calculate means for each group and day
  959. meanMZ = [nanmean(squeeze(mnt_mz(:, 1))), nanmean(squeeze(mnt_mz(:, 2)))];
  960. meanDZ = [nanmean(squeeze(mnt_dz(:, 1))), nanmean(squeeze(mnt_dz(:, 2)))];
  961. meanNZ = [nanmean(squeeze(mnt_nz(:, 1))), nanmean(squeeze(mnt_nz(:, 2)))];
  962. % Calculate standard errors for each group and day
  963. semMZ = [nanstd(squeeze(mnt_mz(:, 1)))/sqrt(sum(~isnan(mnt_mz(:, 1)))), nanstd(squeeze(mnt_mz(:, 2)))/sqrt(sum(~isnan(mnt_mz(:, 2))))];
  964. semDZ = [nanstd(squeeze(mnt_dz(:, 1)))/sqrt(sum(~isnan(mnt_dz(:, 1)))), nanstd(squeeze(mnt_dz(:, 2)))/sqrt(sum(~isnan(mnt_dz(:, 2))))];
  965. semNZ = [nanstd(squeeze(mnt_nz(:, 1)))/sqrt(sum(~isnan(mnt_nz(:, 1)))), nanstd(squeeze(mnt_nz(:, 2)))/sqrt(sum(~isnan(mnt_nz(:, 2))))];
  966. % Create bar plot
  967. figure;
  968. b = bar([meanMZ; meanDZ; meanNZ], 'FaceColor', 'flat','LineWidth',3);
  969. hold on;
  970. % Set colors for different days
  971. b(1).CData = repmat([70/255, 130/255, 180/255], 3, 1); % Color for Day 1
  972. b(2).CData = repmat([107/255, 142/255, 35/255], 3, 1); % Color for Day 2
  973. % Add error bars
  974. ngroups = size([meanMZ; meanDZ; meanNZ], 1);
  975. nbars = size([meanMZ; meanDZ; meanNZ], 2);
  976. groupwidth = min(0.8, nbars/(nbars + 1.5));
  977. for i = 1:nbars
  978. x = b(i).XEndPoints;
  979. errorbar(x, [meanMZ(i), meanDZ(i), meanNZ(i)], [semMZ(i), semDZ(i), semNZ(i)], 'k', 'linestyle', 'none','LineWidth',3);
  980. end
  981. % Add significance indicators (example for MZ vs NZ)
  982. % Coordinates for line and asterisk
  983. x1 = sum(b(1).XEndPoints(1) + b(2).XEndPoints(1))/2;
  984. x2 = sum(b(1).XEndPoints(3) + b(2).XEndPoints(3))/2;
  985. y = max([max(meanMZ), max(meanNZ)]) + max([max(semMZ), max(semNZ)]) * 1.5;
  986. plot([x1, x2], [y, y], 'k', 'LineWidth', 3); % Line
  987. plot(mean([x1, x2]), y * 1.05, 'k*', 'LineWidth', 3); % Asterisk
  988. % Set labels and titles
  989. set(gca, 'XTick', 1:3, 'XTickLabel', {'MZ', 'DZ', 'NZ'});
  990. ylabel('BOLD Time Course Similarity');
  991. title('BOLD Time Course Similarity by Group and Day');
  992. legend('Day 1', 'Day 2');
  993. hold off;
  994. % Get the axis handle
  995. ax = gca;
  996. set(ax, 'TickDir', 'out')
  997. set(ax, 'FontSize', 20)
  998. % Set the line width of the x-axis and y-axis
  999. set(ax, 'LineWidth', 3)
  1000. set(ax, 'Layer', 'bottom')
  1001. hPlots = findobj(ax, 'Type', 'line');
  1002. box off
  1003. ylim([0 .3])
  1004. yticks([0 .1 .2 .3])
  1005. pbaspect([2 1 1])
  1006. saveas(gcf,[data_dir '/isc_heritability/figures/fig6_barplot.fig'])
  1007. %% Control for tbold
  1008. % Predefined variables
  1009. indices = find(ismember(subjs_movie, subjs_rest));
  1010. % Initialization
  1011. isc_herit_mnt = zeros(num_vox_cortex, num_days); % 3D array to store results
  1012. isc_herit_mnt_jack = zeros(num_vox_cortex,num_fams, num_days); % 3D array to store results
  1013. % Main processing
  1014. parpool("Threads",10)
  1015. mnt_pval = zeros(num_vox_cortex,num_days,length(align_types));
  1016. num_perm_covari = 1000;
  1017. for align_id = 1:length(align_types)
  1018. align_type = align_types{align_id};
  1019. align_type
  1020. mnt_acf = load(strcat(base_dir,'/',align_type, '/outputs/gray/mnt_gray.mat'),'mnt_acf');
  1021. mnt_acf = mnt_acf.mnt_acf;
  1022. avg_mnt = squeeze(nanmean(mnt_acf,1));
  1023. isc_mnt_corr = zeros(num_vox_cortex,2);
  1024. for scan_id = 1:num_days
  1025. scan_id
  1026. other_scan_id = 3 - scan_id;
  1027. if strcmp(align_type,'anatomical')
  1028. isc = load(sprintf('%s%s/outputs/%s/%s_isc_scan_%s.mat', base_dir, align_type, 'gray', align_type, num2str(scan_id)));
  1029. else
  1030. isc = load(sprintf('%s%s/outputs/%s/%s_isc_parc_100_scan_%s.mat', base_dir, align_type, 'gray', align_type, num2str(scan_id)));
  1031. end
  1032. name = fieldnames(isc);
  1033. isc = isc.(name{1});
  1034. parfor vert = 1:num_vox_cortex
  1035. [isc_herit_mnt(vert, scan_id), ~,~, isc_herit_mnt_jack(vert,:,scan_id,align_id)] = h2_mat(isc(:,:,vert), kinship(subjs_movie, subjs_movie), [covari_motion(subjs_movie, [1, 2, scan_id + 2]), squeeze(mnt_acf(vert, :, other_scan_id))'], num_perm,[]);
  1036. end
  1037. if num_perm_covari == 1000
  1038. perm_order = zeros(num_subj_movie,num_perm_covari);
  1039. for perm_id = 1:num_perm_covari
  1040. rng(perm_id)
  1041. perm_order(:,perm_id) = randperm(num_subj_movie);
  1042. end
  1043. parfor vert = 1:num_vox_cortex
  1044. % Temporary variable for this iteration
  1045. temp_null_herit = zeros(num_perm_covari, 1);
  1046. if mod(vert,1000) == 0
  1047. disp(['vert = ' num2str(vert)])
  1048. disp(['align_type = ' align_type])
  1049. disp(['scan_id = ' num2str(scan_id)])
  1050. end
  1051. isc_temp = isc(:,:,vert);
  1052. mnt_temp = squeeze(mnt_acf(vert, :, other_scan_id))';
  1053. for perm_id = 1:num_perm_covari
  1054. temp_null_herit(perm_id) = h2_mat(isc_temp, kinship(subjs_movie, subjs_movie), [covari_motion(subjs_movie, [1, 2, scan_id + 2]), mnt_temp(perm_order(:,perm_id))], 0,[]);
  1055. end
  1056. null_herit(:,vert,scan_id,align_id) = temp_null_herit;
  1057. mnt_pval(vert,scan_id,align_id) = (sum(temp_null_herit>=abs(isc_herit_mnt(vert,scan_id)))+1)/(num_perm_covari+1);
  1058. end
  1059. end
  1060. isc_herit_mnt(isc_herit_mnt==1) = NaN;
  1061. % Save Cifti
  1062. saveCifti(isc_herit_mnt(:, scan_id)', strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_mnt_scan_', num2str(scan_id), '.dscalar.nii'), wb_path, scalar_template, medial_mask);
  1063. % Make difference ciftis
  1064. if strcmp(align_type,'anatomical')
  1065. no_covari_cifti = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_400_scan_', num2str(scan_id), '.dscalar.nii'));
  1066. else
  1067. no_covari_cifti = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_100_scan_', num2str(scan_id), '.dscalar.nii'));
  1068. end
  1069. mnt_cifti = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_mnt_scan_', num2str(scan_id), '.dscalar.nii'));
  1070. saveCifti(mnt_cifti.cdata(medial_mask == 1)' - no_covari_cifti.cdata(medial_mask == 1)', strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_mnt_diff_scan_', num2str(scan_id), '.dscalar.nii'), wb_path, scalar_template, medial_mask);
  1071. % Now correlate ISC with MNT
  1072. parfor vox = 1:num_vox_cortex
  1073. isc_mnt_corr(vox,scan_id) = corr(hvec(mnt_acf_out_big(:,:,vox,scan_id)),hvec(isc(:,:,vox)),'rows','complete');
  1074. end
  1075. saveCifti(isc_mnt_corr(:, scan_id)', strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_mnt_corr_scan_', num2str(scan_id), '.dscalar.nii'), wb_path, scalar_template, medial_mask);
  1076. end
  1077. end
  1078. if num_perm_covari == 1000
  1079. save([data_dir '/isc_heritability/null_herit_NT.mat'],'null_herit')
  1080. save([data_dir '/isc_heritability/mnt_pval.mat'],'mnt_pval')
  1081. else
  1082. load([data_dir '/isc_heritability/mat_files/supporting_files/mnt_pval.mat'])
  1083. load([data_dir '/isc_heritability/mat_files/supporting_files/null_herit_NT.mat'])
  1084. for align_id = 1:length(align_types)
  1085. align_type = align_types{align_id};
  1086. mnt_acf = load(strcat(base_dir,'/',align_type, '/outputs/gray/mnt_gray.mat'),'mnt_acf');
  1087. mnt_acf = mnt_acf.mnt_acf;
  1088. avg_mnt = squeeze(nanmean(mnt_acf,1));
  1089. isc_mnt_corr = zeros(num_vox_cortex,2);
  1090. for scan_id = 1:num_days
  1091. data = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_mnt_scan_', num2str(scan_id), '.dscalar.nii'));
  1092. if align_id == 2
  1093. nomnt_data = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_scan_', num2str(scan_id), '.dscalar.nii'));
  1094. else
  1095. nomnt_data = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_100_scan_', num2str(scan_id), '.dscalar.nii'));
  1096. end
  1097. isc_herit_m = data.cdata(medial_mask==1);
  1098. isc_herit = nomnt_data.cdata(medial_mask==1);
  1099. null_herit(null_herit==1) = NaN;
  1100. avg_herit_m = nanmean(isc_herit_m);
  1101. avg_herit = nanmean(isc_herit);
  1102. obs_diff_avg = avg_herit_m - avg_herit;
  1103. obs_diff = isc_herit_m - isc_herit;
  1104. parfor vert = 1:num_vox_cortex
  1105. null_diffs = null_herit(:,vert,scan_id,align_id)-isc_herit(vert);
  1106. mnt_pval(vert,scan_id,align_id) = (sum(abs(null_diffs)>=abs(obs_diff(vert,1)))+1)/(num_perm_covari+1);
  1107. end
  1108. avg_null(:,scan_id,align_id) = squeeze(mean(null_herit(:,:,scan_id,align_id),2));
  1109. null_diffs_all=avg_null(:,scan_id,align_id)-avg_herit;
  1110. avg_diff(scan_id,align_id) = (sum(abs(null_diffs_all)>=abs(obs_diff_avg))+1)/(num_perm_covari+1);
  1111. end
  1112. end
  1113. end
  1114. for scan_id = 1:num_days
  1115. piecewise_pval(:,scan_id) = fdr_bh(mnt_pval(:,scan_id,1));
  1116. end
  1117. piecewise_pval_fdr = piecewise_pval(:,1).*piecewise_pval(:,2);
  1118. piecewise_pval_fdr_perc = sum(piecewise_pval_fdr)/length(piecewise_pval_fdr);
  1119. for scan_id = 1:num_days
  1120. anatomical_pval(:,scan_id) = fdr_bh(mnt_pval(:,scan_id,2));
  1121. end
  1122. anatomical_pval_fdr = anatomical_pval(:,1).*anatomical_pval(:,2);
  1123. anatomical_pval_fdr_perc = sum(anatomical_pval_fdr)/length(anatomical_pval_fdr);
  1124. mnt_data_out = zeros(num_vox_cortex,2,2);
  1125. for align_id = 1:length(align_types)
  1126. align_type = align_types{align_id};
  1127. for scan_id = 1:num_days
  1128. if align_id == 1
  1129. no_covari_cifti = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_100_scan_', num2str(scan_id), '.dscalar.nii'));
  1130. else
  1131. no_covari_cifti = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_400_scan_', num2str(scan_id), '.dscalar.nii'));
  1132. end
  1133. mnt_cifti = ciftiopen(strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_mnt_scan_', num2str(scan_id), '.dscalar.nii'));
  1134. nocovari_data = no_covari_cifti.cdata(medial_mask == 1)';
  1135. mnt_data = mnt_cifti.cdata(medial_mask == 1)';
  1136. mnt_data(mnt_data==1) = NaN;
  1137. nocovari_data(nocovari_data==1) = NaN;
  1138. mnt_data_out(:,scan_id,align_id) = mnt_data - nocovari_data ;
  1139. mnt_perc(:,scan_id,align_id) = (mnt_data - nocovari_data)./nocovari_data;
  1140. saveCifti(mnt_perc(:,scan_id), strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_mnt_diff_perc_scan_', num2str(scan_id), '.dscalar.nii'), wb_path, scalar_template, medial_mask);
  1141. saveCifti(mnt_data, strcat(base_dir, align_type, '/outputs/gray/', align_type, '_isc_herit_gray_mnt_scan_', num2str(scan_id), '.dscalar.nii'), wb_path, scalar_template, medial_mask);
  1142. end
  1143. end
  1144. mnt_med = squeeze(nanmean(mnt_data_out));
  1145. % Now make bar plot comparing anatomical/piecewise/int heritability
  1146. anatomical_isc_herit_nocovari = zeros(1,num_days);
  1147. anatomical_isc_herit_mnt = zeros(1,num_days);
  1148. piecewise_isc_herit_mnt = zeros(1,num_days);
  1149. % First load means
  1150. for scan_id = 1:num_days
  1151. data = ciftiopen(strcat(base_dir, 'anatomical', '/outputs/gray/', 'anatomical', '_isc_herit_gray_400_scan_', num2str(scan_id), '.dscalar.nii'));
  1152. anatomical_isc_herit_nocovari(:,scan_id) = median(data.cdata(medial_mask==1));
  1153. data = ciftiopen(strcat(base_dir, 'anatomical', '/outputs/gray/', 'anatomical', '_isc_herit_gray_mnt_scan_', num2str(scan_id), '.dscalar.nii'));
  1154. anatomical_isc_herit_mnt(:,scan_id) = median(data.cdata(medial_mask==1));
  1155. data = ciftiopen(strcat(base_dir, 'piecewise', '/outputs/gray/', 'piecewise', '_isc_herit_gray_mnt_scan_', num2str(scan_id), '.dscalar.nii'));
  1156. piecewise_isc_herit_mnt(:,scan_id) = median(data.cdata(medial_mask==1));
  1157. end
  1158. % Next get SEs
  1159. for scan_id = 1:num_days
  1160. data = ciftiopen(strcat(base_dir, 'anatomical', '/outputs/gray/', 'anatomical', '_isc_herit_gray_400_scan_', num2str(scan_id), '.dscalar.nii'));
  1161. anatomical_isc_herit_nocovari(:,scan_id) = data.cdata(medial_mask==1);
  1162. data = ciftiopen(strcat(base_dir, 'anatomical', '/outputs/gray/', 'anatomical', '_isc_herit_gray_mnt_scan_', num2str(scan_id), '.dscalar.nii'));
  1163. anatomical_isc_herit_mnt(:,scan_id) = data.cdata(medial_mask==1);
  1164. end
  1165. isc_herit_gray = zeros(num_vox_cortex,num_days);
  1166. isc_herit_gray_perm = zeros(num_vox_cortex,num_days);
  1167. isc_herit_gray_int = zeros(num_vox_cortex,num_days);
  1168. isc_herit_gray_mnt_perm = zeros(num_vox_cortex,num_days);
  1169. isc_herit_gray_mnt_covari_perm = zeros(num_vox_cortex,num_perm_covari,2);
  1170. num_perm_covari = 10000;
  1171. for scan_id = 1:num_days
  1172. if scan_id == 1
  1173. other_scan_id = 2;
  1174. else
  1175. other_scan_id = 1;
  1176. end
  1177. isc = load(sprintf('%s%s/outputs/%s/%s_isc_parc_100_scan_%s.mat', base_dir,'anatomical','gray','anatomical', num2str(scan_id)));
  1178. name = fieldnames(isc);
  1179. isc = isc.(name{1});
  1180. parfor vert = 1:num_vox_cortex
  1181. [isc_herit_gray_mnt(vert,scan_id), ~] = h2_multi(isc(:,:,vert), kinship(subjs_movie,subjs_movie), [covari_motion(subjs_movie,[1,2,scan_id+2]), squeeze(mnt_acf(vert,:,other_scan_id))'], 0);
  1182. end
  1183. isc_herit_gray_int(isc_herit_gray_int==1) = NaN;
  1184. isc_herit_gray_mnt(isc_herit_gray_mnt==1) = NaN;
  1185. end
  1186. % Make difference ciftis
  1187. for scan_id = 1:num_days
  1188. no_covari_cifti = ciftiopen(strcat(base_dir,'piecewise/outputs/gray/anatomical_isc_herit_gray_400_scan_',num2str(scan_id),'.dscalar.nii'));
  1189. mnt_cifti = ciftiopen(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit_gray_mnt_scan_',num2str(scan_id),'.dscalar.nii'));
  1190. saveCifti(mnt_cifti.cdata(medial_mask==1)'-no_covari_cifti.cdata(medial_mask==1)', strcat(base_dir,'piecewise/outputs/gray/isc_herit_gray_mnt_diff_scan_',num2str(scan_id),'.dscalar.nii'), wb_path, scalar_template,medial_mask);
  1191. mnt_otherscan_cifti = ciftiopen(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit_gray_mnt_otherscan_',num2str(scan_id),'.dscalar.nii'));
  1192. saveCifti(mnt_otherscan_cifti.cdata(medial_mask==1)'-no_covari_cifti.cdata(medial_mask==1)', strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_herit_gray_mnt_diff_otherscan_',num2str(scan_id),'.dscalar.nii'), wb_path, scalar_template,medial_mask);
  1193. end
  1194. mnt_pval_fdr = fdr_bh(mnt_pval);
  1195. mnt_pval_fdr_perc = nansum(mnt_pval_fdr(:,1).*(mnt_pval_fdr(:,2)))/num_vox_cortex;
  1196. %% Compare heritability across different anatomical parcellation resolutions
  1197. anatomical_herit_parc_multires = zeros(num_parcs,num_days);
  1198. anatomical_parc_se = zeros(num_parcs,num_days);
  1199. for parc_id = 1:length(parc_reses)
  1200. for scan_id = 1:num_days
  1201. anatomical_herit_parc_multires(parc_id,scan_id) = nanmean(anatomical_isc_herit_parc{parc_id,1}(:,scan_id));
  1202. [~,anatomical_parc_se(parc_id,scan_id)] = compareHeritability(0,nanmean(anatomical_isc_herit_parc_jack{parc_id,1}(:,:,scan_id)),0,nanmean(anatomical_isc_herit_parc_jack{parc_id,1}(:,:,scan_id)));
  1203. end
  1204. end
  1205. % FIGURE 2 SCATTER
  1206. hold on
  1207. scatter(avg_areas,anatomical_herit_parc_multires(:,1),100,'filled','MarkerFaceColor',[70/255 130/255 180/255],'MarkerEdgeColor','k')
  1208. scatter(avg_areas,anatomical_herit_parc_multires(:,2),100,'filled','MarkerFaceColor',[107/255 142/255 35/255],'MarkerEdgeColor','k')
  1209. for parc_id = 1:num_parcs
  1210. errorbar(avg_areas(parc_id),anatomical_herit_parc_multires(parc_id,1),anatomical_parc_se(parc_id,1),'Color',[70/255 130/255 180/255],'LineStyle','-','LineWidth',2)
  1211. errorbar(avg_areas(parc_id),anatomical_herit_parc_multires(parc_id,2),anatomical_parc_se(parc_id,2),'Color',[107/255 142/255 35/255],'LineStyle','-','LineWidth',2)
  1212. end
  1213. subplot(2,1,1)
  1214. hold on
  1215. % Calculate means and SEMs
  1216. mean_isc_parc_day1 = anatomical_herit_parc_multires(:,1);
  1217. sem_isc_parc_day1 = anatomical_parc_se(:,1);
  1218. mean_isc_parc_day2 = anatomical_herit_parc_multires(:,2);
  1219. sem_isc_parc_day2 = anatomical_parc_se(:,2);
  1220. % boundedline plots
  1221. hl1 = boundedline(avg_areas, mean_isc_parc_day1, sem_isc_parc_day1, 'alpha', 'cmap', [70/255 130/255 180/255]);
  1222. hl2 = boundedline(avg_areas, mean_isc_parc_day2, sem_isc_parc_day2, 'alpha', 'cmap', [107/255 142/255 35/255]);
  1223. % Doubling the line thickness in boundedline plots
  1224. set(hl1, 'LineWidth', 4);
  1225. set(hl2, 'LineWidth', 4);
  1226. % Scatter plots for mean values
  1227. scatter(avg_areas, mean_isc_parc_day1, 100, 'filled', 'MarkerFaceColor', [70/255 130/255 180/255], 'MarkerEdgeColor', 'k');
  1228. scatter(avg_areas, mean_isc_parc_day2, 100, 'filled', 'MarkerFaceColor', [107/255 142/255 35/255], 'MarkerEdgeColor', 'k');
  1229. % Axes settings
  1230. ylim([.05 .08]); xlim([0 1200]);
  1231. xlabel('Average Parcel Area (mm^2)'); ylabel('Average Heritability (h^2)');
  1232. yticks([.05 .06 .07 .08]); ax = gca; set(ax, 'TickDir', 'out'); set(ax, 'FontSize', 20); set(ax, 'LineWidth', 3); set(ax, 'Layer', 'bottom');
  1233. grid off; legend({'Day 1', 'Day 2'}, 'Location', 'best'); pbaspect([2 1 1]); set(gcf, 'position', [100,100,600,1200]);
  1234. saveas(gcf,[data_dir '/isc_heritability/figures/fig2_parc_areascatter.fig'])
  1235. close all
  1236. %% ISC vs neural-timescale correlation: precompute pairwise NT sums (feeds QAP below)
  1237. num_perms = 1000;
  1238. if exist(strcat(base_dir,'anatomical/outputs/gray/mnt_gray.mat'),'file') == 2
  1239. load(strcat(base_dir,'anatomical/outputs/gray/mnt_gray.mat'))
  1240. else
  1241. mnt_acf = zeros(num_vox_cortex,num_subj_movie,2);
  1242. for scan_id = [1,2]
  1243. for subj = 1:num_subj_movie
  1244. subj
  1245. subj_data = readNPY(strcat([data_dir '/isc_heritability/data/anatomical/inputs/gray/anatomical_movie_scan_'], num2str(scan_id), '_subj_', num2str(subj), '.npy'));
  1246. mnt_acf(:,subj,scan_id) = calculate_int(subj_data);
  1247. end
  1248. end
  1249. save(strcat(base_dir,'anatomical/outputs/gray/mnt_gray.mat'),'mnt_acf')
  1250. end
  1251. mnt_avg = squeeze(nanmean(mnt_acf,1));
  1252. mnt_acf_out_big = zeros(num_subj_movie,num_subj_movie,num_vox_cortex,num_days);
  1253. for scan_id = 1:num_days
  1254. for vox = 1:num_vox_cortex
  1255. for subj1 = 1:num_subj_movie
  1256. for subj2 = 1:num_subj_movie
  1257. if subj1~=subj2
  1258. mnt_acf_out_big(subj1,subj2,vox,scan_id) = squeeze(mnt_acf(vox,subj1,scan_id))+squeeze(mnt_acf(vox,subj2,scan_id));
  1259. else
  1260. mnt_acf_out_big(subj1,subj2,vox,scan_id) = NaN;
  1261. end
  1262. end
  1263. end
  1264. end
  1265. end
  1266. clear mnt_acf
  1267. % Number of permutations
  1268. num_perms = 10000;
  1269. % Precompute hvec for all voxels and scans
  1270. mnt_acf_hvec = cell(num_vox_cortex, 2);
  1271. parfor vox = 1:num_vox_cortex
  1272. for scan_id = 1:num_days
  1273. mnt_acf_hvec{vox, scan_id} = hvec(mnt_acf_out_big(:, :, vox, scan_id));
  1274. end
  1275. end
  1276. %% ISC vs neural-timescale correlation (family-compliant QAP, 1000 permutations)
  1277. align_type = 'anatomical';
  1278. isc_mnt_corr = zeros(num_vox_cortex, 2);
  1279. isc_mnt_pvals = zeros(num_vox_cortex, 2); % To store p-values
  1280. % --- SETTINGS & PREPARATION ---
  1281. num_perms = 1000;
  1282. num_vox_cortex = 59412;
  1283. num_active_subjs = length(subjs_movie);
  1284. num_pairs = (num_active_subjs * (num_active_subjs - 1)) / 2;
  1285. % family_data: num_subjx2 [SubjectID, FamilyID]
  1286. [~, loc] = ismember(subjs_movie, family_ids(:, 1));
  1287. curr_family_ids = family_ids(loc, 2);
  1288. [unique_fams, ~, fam_map] = unique(curr_family_ids);
  1289. num_families = length(unique_fams);
  1290. % --- 1. PRECOMPUTE HCP-COMPLIANT PERMUTATION INDICES ---
  1291. all_perm_indices = zeros(num_active_subjs, num_perms);
  1292. for p_id = 1:num_perms
  1293. rng(p_id);
  1294. fam_perm = randperm(num_families);
  1295. curr_p = zeros(num_active_subjs, 1);
  1296. write_ptr = 1;
  1297. for f = 1:num_families
  1298. orig_member_indices = find(fam_map == fam_perm(f));
  1299. within_fam_perm = orig_member_indices(randperm(length(orig_member_indices)));
  1300. num_members = length(within_fam_perm);
  1301. curr_p(write_ptr : write_ptr + num_members - 1) = within_fam_perm;
  1302. write_ptr = write_ptr + num_members;
  1303. end
  1304. all_perm_indices(:, p_id) = curr_p;
  1305. end
  1306. % --- 2. VOXEL-WISE QAP ANALYSIS ---
  1307. for scan_id = 1:num_days
  1308. other_scan_id = 3 - scan_id;
  1309. fprintf('Processing Scan %d (using ISC from Scan %d)...\n', scan_id, other_scan_id);
  1310. isc_data = load(sprintf('%s%s/outputs/%s/%s_isc_scan_%s.mat', ...
  1311. base_dir, 'anatomical', 'gray', 'anatomical', num2str(other_scan_id)));
  1312. name = fieldnames(isc_data);
  1313. isc = isc_data.(name{1});
  1314. % Slice MNT to avoid broadcast overhead in parfor
  1315. current_scan_mnt = mnt_acf_hvec(:, scan_id);
  1316. isc_mnt_corr = zeros(num_vox_cortex, 1);
  1317. isc_mnt_pvals = ones(num_vox_cortex, 1);
  1318. parfor vox = 1:num_vox_cortex
  1319. if mod(vox, 10000) == 0, fprintf('Voxel: %d\n', vox); end
  1320. % A. Get and Pre-rank Observed Data
  1321. % We use hvec to get the lower triangle of the 178x178 matrix
  1322. vox_isc_matrix = isc(:, :, vox);
  1323. obs_isc_vec = hvec(vox_isc_matrix);
  1324. obs_mnt_vec = current_scan_mnt{vox};
  1325. % Calculate Observed Spearman Correlation
  1326. isc_mnt_corr(vox) = corr(obs_mnt_vec, obs_isc_vec, 'rows', 'complete', 'type', 'spearman');
  1327. if num_perms > 0
  1328. % B. Optimization: Rank the matrix once
  1329. % We rank the full matrix, then permute, then extract hvec
  1330. ranked_isc_mat = reshape(tiedrank(vox_isc_matrix(:)), num_active_subjs, num_active_subjs);
  1331. % C. Pre-rank and Standardize the Predictor (MNT) for fast Pearson
  1332. % Standardizing allows us to use dot product instead of full corr()
  1333. mnt_rank = tiedrank(obs_mnt_vec);
  1334. mnt_rank_std = (mnt_rank - mean(mnt_rank)) / std(mnt_rank);
  1335. % D. Vectorized Null Generation
  1336. % Instead of a 1000-iteration loop, we build a matrix of permuted ISCs
  1337. perm_isc_mtx = zeros(num_pairs, num_perms);
  1338. for p_id = 1:num_perms
  1339. p_idx = all_perm_indices(:, p_id);
  1340. perm_isc_mtx(:, p_id) = hvec(ranked_isc_mat(p_idx, p_idx));
  1341. end
  1342. % E. Ultra-Fast Matrix-Vector Pearson Correlation
  1343. % Rank and standardize the permuted matrix columns
  1344. perm_isc_mtx = (perm_isc_mtx - mean(perm_isc_mtx, 1)) ./ std(perm_isc_mtx, 0, 1);
  1345. % Resulting null_corrs is 1000x1 vector
  1346. null_corrs = (mnt_rank_std' * perm_isc_mtx) / (num_pairs - 1);
  1347. % F. Compute P-Value (Two-Tailed)
  1348. isc_mnt_pvals(vox) = (sum(abs(null_corrs) >= abs(isc_mnt_corr(vox))) + 1) / (num_perms + 1);
  1349. end
  1350. end
  1351. % --- 3. SAVE RESULTS ---
  1352. corr_out = strcat(base_dir, 'anatomical', '/outputs/gray/', 'anatomical', '_isc_mnt_corr_QAP_scan_', num2str(scan_id), '.dscalar.nii');
  1353. pval_out = strcat(base_dir, 'anatomical', '/outputs/gray/', 'anatomical', '_isc_mnt_pvals_QAP_scan_', num2str(scan_id), '.dscalar.nii');
  1354. saveCifti(isc_mnt_corr', corr_out, wb_path, scalar_template, medial_mask);
  1355. saveCifti(isc_mnt_pvals', pval_out, wb_path, scalar_template, medial_mask);
  1356. end
  1357. for scan_id = 1:num_days
  1358. xx= ciftiopen(strcat(base_dir, 'anatomical', '/outputs/gray/', 'anatomical', '_isc_mnt_pvals_QAP_scan_', num2str(scan_id), '.dscalar.nii'));
  1359. pval_mat(:,scan_id) = xx.cdata;
  1360. pval_mat_fdr(:,scan_id) = fdr_bh(pval_mat(:,scan_id));
  1361. end
  1362. for scan_id = 1:num_days
  1363. isc_mnt_pvals_fdr(:,scan_id) = fdr_bh(isc_mnt_pvals(:,scan_id));
  1364. end
  1365. isc_mnt_pvals_fdr_sig = isc_mnt_pvals_fdr(:,1).*isc_mnt_pvals_fdr(:,2);
  1366. isc_mnt_pvals_fdr_sig_perc = sum(isc_mnt_pvals_fdr_sig)/num_vox_cortex;
  1367. isc_mnt_max = max(isc_mnt_corr);
  1368. isc_mnt_mean = mean(isc_mnt_corr);
  1369. %% Subsampling (Fig. S3)
  1370. % Set the seed for reproducibility
  1371. rng(42); % You can choose any seed value
  1372. dataType = 'parc';
  1373. taskType = 'movie';
  1374. alignType = 'anatomical';
  1375. curr_parc = '400';
  1376. Subjects = subjs_movie;
  1377. num_subjs = num_subj_movie;
  1378. num_parcels = 400;
  1379. % Define the percentages of families to drop
  1380. drop_percentages = [5, 10, 15, 20, 25,30, 40, 50, 75,90];
  1381. drop_fractions = drop_percentages / 100;
  1382. % Get unique family IDs
  1383. unique_families = unique(movie_fam_ids);
  1384. num_families = length(unique_families);
  1385. % Number of permutations
  1386. num_permutations = 100;
  1387. % Initialize the results array
  1388. isc_herit_subsample = zeros(num_parcels, 2, length(drop_fractions), num_permutations);
  1389. % Load subject data (once)
  1390. subj_data_full = cell(1,2);
  1391. for scan_id = 1:num_days
  1392. % Load data for all subjects
  1393. subj_data = loadData(num_subjs, base_dir, alignType, taskType, dataType, curr_parc, scan_id, num_trs);
  1394. subj_data = permute(subj_data,[2,1,3]); % [voxels x subjects x time]
  1395. subj_data_full{scan_id} = subj_data;
  1396. end
  1397. % Calculate ISC for all subjects (once)
  1398. isc_full = cell(1,2);
  1399. for scan_id = 1:num_days
  1400. isc = zeros(num_subjs, num_subjs, num_parcels);
  1401. subj_data = subj_data_full{scan_id}; % [voxels x subjects x time]
  1402. for vox = 1:num_parcels
  1403. isc(:,:,vox) = corr(squeeze(subj_data(:,vox,:)));
  1404. end
  1405. isc_full{scan_id} = isc; % Store the ISC matrices
  1406. end
  1407. for scan_id = 1:num_days
  1408. for grayordinate = 1:num_parcels
  1409. isc_matrix = squeeze(isc_full{scan_id}(:,:,grayordinate));
  1410. [isc_herit_full(grayordinate,scan_id), ~, ~, ~] = h2_mat(squeeze(isc(:,:,grayordinate)), kinship(Subjects,Subjects), covari_motion(Subjects,[1,2,scan_id+2]), 0,[]);
  1411. end
  1412. end
  1413. for scan_id = 1:num_days
  1414. isc = isc_full{scan_id}; % Precomputed ISC matrices for this scan
  1415. for frac_idx = 1:length(drop_fractions)
  1416. frac = drop_fractions(frac_idx);
  1417. % Calculate the number of families to drop
  1418. num_families_to_drop = round(frac * num_families);
  1419. parfor perm_id = 1:num_permutations
  1420. % Set seed for each permutation
  1421. rng(42 + perm_id);
  1422. % Randomly select families to drop
  1423. families_to_drop = randsample(unique_families, num_families_to_drop);
  1424. % Find indices of subjects to exclude (belonging to dropped families)
  1425. subjects_to_exclude = ismember(movie_fam_ids, families_to_drop);
  1426. % Indices of subjects to include
  1427. included_subjects = ~subjects_to_exclude;
  1428. % Get the indices of included subjects
  1429. idx_included_subjects = find(included_subjects);
  1430. num_subjs_included = length(idx_included_subjects);
  1431. % Get the subject IDs to include
  1432. Subjects_included = Subjects(included_subjects);
  1433. % Extract the relevant ISC subset
  1434. isc_subset = isc(included_subjects, included_subjects, :); % [subjects x subjects x parcels]
  1435. % Prepare kinship and covariate matrices for included subjects
  1436. kinship_sub = kinship(Subjects_included, Subjects_included);
  1437. covariates_sub = covari_motion(Subjects_included, [1, 2, scan_id+2]);
  1438. % Recalculate heritability
  1439. isc_herit = zeros(num_parcels, 1);
  1440. for grayordinate = 1:num_parcels
  1441. isc_matrix = squeeze(isc_subset(:,:,grayordinate));
  1442. [isc_herit(grayordinate,1), ~, ~, ~] = h2_mat(isc_matrix, kinship_sub, covariates_sub, 0, []);
  1443. end
  1444. % Store the results
  1445. isc_herit_subsample(:, scan_id, frac_idx, perm_id) = isc_herit;
  1446. end
  1447. end
  1448. end
  1449. % Number of fractions and permutations
  1450. num_fractions = length(drop_percentages);
  1451. num_permutations = size(isc_herit_subsample, 4);
  1452. % Initialize arrays to store MAE and correlation results
  1453. MAE_results = zeros(num_days, num_fractions, num_permutations); % [scan_id x fractions x permutations]
  1454. corr_results = zeros(num_days, num_fractions, num_permutations); % [scan_id x fractions x permutations]
  1455. for scan_id = 1:num_days
  1456. % Full-sample heritability for this scan
  1457. isc_herit_full_scan = isc_herit_full(:, scan_id);
  1458. for frac_idx = 1:num_fractions
  1459. for perm_id = 1:num_permutations
  1460. % Subsampled heritability for this permutation
  1461. isc_herit_sub = isc_herit_subsample(:, scan_id, frac_idx, perm_id);
  1462. % Compute absolute error across parcels
  1463. abs_error = abs(isc_herit_sub - isc_herit_full_scan);
  1464. % Compute Mean Absolute Error (MAE)
  1465. MAE = mean(abs_error);
  1466. MAE_results(scan_id, frac_idx, perm_id) = MAE;
  1467. % Compute spatial correlation across parcels
  1468. corr_coef = corr(isc_herit_sub, isc_herit_full_scan(:), 'Type', 'Spearman');
  1469. corr_results(scan_id, frac_idx, perm_id) = corr_coef;
  1470. end
  1471. end
  1472. end
  1473. % Compute the average MAE and correlation across permutations for each fraction level
  1474. mean_MAE = mean(MAE_results, 3); % [scan_id x fractions]
  1475. mean_corr = mean(corr_results, 3); % [scan_id x fractions]
  1476. std_MAE = std(MAE_results, 0, 3); % Standard deviation across permutations
  1477. std_corr = std(corr_results, 0, 3); % Standard deviation across permutations
  1478. % Plotting Mean Absolute Error (MAE) with shading and circles with black edges
  1479. figure;
  1480. subplot(1,2,1)
  1481. hold on;
  1482. % Plot shaded area for standard deviation (Scan 1)
  1483. fill([drop_percentages, fliplr(drop_percentages)], ...
  1484. [mean_MAE(1, :) + std_MAE(1, :), fliplr(mean_MAE(1, :) - std_MAE(1, :))], ...
  1485. 'b', 'FaceAlpha', 0.2, 'EdgeColor', 'none');
  1486. % Plot shaded area for standard deviation (Scan 2)
  1487. fill([drop_percentages, fliplr(drop_percentages)], ...
  1488. [mean_MAE(2, :) + std_MAE(2, :), fliplr(mean_MAE(2, :) - std_MAE(2, :))], ...
  1489. 'r', 'FaceAlpha', 0.2, 'EdgeColor', 'none');
  1490. % Plot mean MAE with circles and black edges
  1491. plot(drop_percentages, mean_MAE(1, :), '-o', 'LineWidth', 2, 'Color', 'b', ...
  1492. 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'b', 'DisplayName', 'Scan 1');
  1493. plot(drop_percentages, mean_MAE(2, :), '-o', 'LineWidth', 2, 'Color', 'r', ...
  1494. 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'r', 'DisplayName', 'Scan 2');
  1495. xlabel('Percentage of Families Dropped');
  1496. ylabel('Mean Absolute Error (MAE)');
  1497. title('Mean Absolute Error vs. Percentage of Families Dropped');
  1498. hold off;
  1499. grid off
  1500. % Customize axes
  1501. ax = gca;
  1502. set(ax, 'TickDir', 'out', 'FontSize', 12, 'LineWidth', 1, 'Layer', 'bottom')
  1503. set(ax, 'LineWidth', 1, 'FontName', 'Arial'); % Increase line width, remove k marks, and set font
  1504. grid off
  1505. legend({'', '', 'Day 1', 'Day 2', ''},'Location','northwest')
  1506. pbaspect([1, 1, 1])
  1507. % Plotting Average Spatial Correlation with shading and circles with black edges
  1508. subplot(1,2,2)
  1509. hold on;
  1510. % Plot shaded area for standard deviation (Scan 1)
  1511. fill([drop_percentages, fliplr(drop_percentages)], ...
  1512. [mean_corr(1, :) + std_corr(1, :), fliplr(mean_corr(1, :) - std_corr(1, :))], ...
  1513. 'b', 'FaceAlpha', 0.2, 'EdgeColor', 'none');
  1514. % Plot shaded area for standard deviation (Scan 2)
  1515. fill([drop_percentages, fliplr(drop_percentages)], ...
  1516. [mean_corr(2, :) + std_corr(2, :), fliplr(mean_corr(2, :) - std_corr(2, :))], ...
  1517. 'r', 'FaceAlpha', 0.2, 'EdgeColor', 'none');
  1518. % Plot mean correlation with circles and black edges
  1519. plot(drop_percentages, mean_corr(1, :), '-o', 'LineWidth', 2, 'Color', 'b', ...
  1520. 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'b', 'DisplayName', 'Scan 1');
  1521. plot(drop_percentages, mean_corr(2, :), '-o', 'LineWidth', 2, 'Color', 'r', ...
  1522. 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'r', 'DisplayName', 'Scan 2');
  1523. xlabel('Percentage of Families Dropped');
  1524. ylabel('Average Spatial Correlation (\rho)');
  1525. title('Spatial Correlation vs. Percentage of Families Excluded', 'FontSize', 20, 'FontName', 'Arial');
  1526. grid off;
  1527. hold off;
  1528. % Customize axes
  1529. ax = gca;
  1530. set(ax, 'TickDir', 'out', 'FontSize', 12, 'LineWidth', 1, 'Layer', 'bottom')
  1531. set(ax, 'LineWidth', 1, 'FontName', 'Arial'); % Increase line width, remove k marks, and set font
  1532. grid off
  1533. legend({'', '', 'Day 1', 'Day 2', ''},'Location','northeast')
  1534. pbaspect([1, 1, 1])
  1535. saveas(gcf,[data_dir '/isc_heritability/figures/figS1_subsample.svg'])
  1536. close all
  1537. %% Compare hyperaligned and MSM ISC (Figure S6)
  1538. mean_piecewise_scaled = mean_piecewise(1:10)./avg_areas;
  1539. mean_connectivity_scaled = mean_connectivity(1:10)./avg_areas;
  1540. for scan_id = 1:num_days
  1541. data = ciftiopen(strcat(base_dir,'anatomical/outputs/gray/anatomical_isc_gray_scan_',num2str(scan_id),'.dscalar.nii'));
  1542. anat_isc_gray(:,scan_id) = data.cdata;
  1543. for parc_id = 1:10
  1544. xx = ciftiopen(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_gray_',parc_reses{parc_id},'_scan_',num2str(scan_id),'.dscalar.nii'));
  1545. piecewise_isc_gray(:,parc_id,scan_id) = xx.cdata;
  1546. xx = ciftiopen(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_gray_',parc_reses{parc_id},'_scan_',num2str(scan_id),'.dscalar.nii'));
  1547. connectivity_isc_gray(:,parc_id,scan_id) =xx.cdata;
  1548. saveCifti(anat_isc_gray(:,scan_id) - piecewise_isc_gray(:,parc_id,scan_id), strcat([data_dir '/isc_heritability/data/anatomical/outputs/gray/anatomical_piecewise_isc_diff_parc_'],parc_reses{parc_id},'_day',num2str(scan_id),'.dscalar.nii'), wb_path, schaefer_400_dscalar,medial_mask);
  1549. saveCifti(anat_isc_gray(:,scan_id) - connectivity_isc_gray(:,parc_id,scan_id), strcat([data_dir '/isc_heritability/data/anatomical/outputs/gray/anatomical_connectivity_isc_diff_parc_'],parc_reses{parc_id},'_day',num2str(scan_id),'.dscalar.nii'), wb_path, schaefer_400_dscalar,medial_mask);
  1550. end
  1551. end
  1552. for scan_id = 1:num_days
  1553. data = ciftiopen(strcat(base_dir,'anatomical/outputs/gray/anatomical_isc_gray_scan_',num2str(scan_id),'.dscalar.nii'));
  1554. anat_isc_gray(:,scan_id) = data.cdata;
  1555. for parc_id = 1:10
  1556. xx = ciftiopen(strcat(base_dir,'piecewise/outputs/gray/piecewise_isc_gray_',parc_reses{parc_id},'_scan_',num2str(scan_id),'.dscalar.nii'));
  1557. piecewise_isc_gray(:,parc_id,scan_id) = xx.cdata;
  1558. xx = ciftiopen(strcat(base_dir,'connectivity/outputs/gray/connectivity_isc_gray_',parc_reses{parc_id},'_scan_',num2str(scan_id),'.dscalar.nii'));
  1559. connectivity_isc_gray(:,parc_id,scan_id) =xx.cdata;
  1560. piecewise_isc_diff(parc_id,scan_id) = mean(mean(anat_isc_gray(:,scan_id) - piecewise_isc_gray(:,parc_id,scan_id)));
  1561. connectivity_isc_diff(parc_id,scan_id) = mean(mean(anat_isc_gray(:,scan_id) - connectivity_isc_gray(:,parc_id,scan_id)));
  1562. end
  1563. end
  1564. % --- Data Preparation ---
  1565. % Concatenate the MSM baseline with the piecewise and connectivity data
  1566. piecewise_data = [nanmedian(anat_isc_gray(:,1)) squeeze(nanmedian(piecewise_isc_gray(:,:,2),1))];
  1567. connectivity_data = [nanmedian(anat_isc_gray(:,1)) squeeze(nanmedian(connectivity_isc_gray(:,:,2),1))];
  1568. % --- Plotting ---
  1569. figure;
  1570. hold on; % Allows multiple lines on the same axes
  1571. % Plot both lines with 'LineWidth' set to 2 (adjust as needed)
  1572. plot(piecewise_data, 'LineWidth', 2, 'DisplayName', 'Piecewise Hyperalignment');
  1573. plot(connectivity_data, 'LineWidth', 2, 'DisplayName', 'Connectivity Hyperalignment');
  1574. % --- Aesthetics ---
  1575. ylim([0.018 0.026]);
  1576. ylabel('ISC (r)');
  1577. xlabel('Parcellation Resolution');
  1578. title('Hyperalignment Comparison');
  1579. % Set X-ticks and Labels
  1580. xticks(1:11);
  1581. xticklabels({'MSM','100','200','300','400','500','600','700','800','900','1000'});
  1582. % Remove top and right axes (spines)
  1583. set(gca, 'Box', 'off');
  1584. % Add Legend
  1585. legend('Location', 'northeast');
  1586. hold off;
  1587. % Define constants
  1588. num_scans = 2;
  1589. orange_col = [254/255 97/255 0/255];
  1590. purple_col = [120/255 94/255 240/255];
  1591. figure;
  1592. set(gcf, 'position', [100, 100, 800, 1200]);
  1593. for scan_id = 1:num_scans
  1594. subplot(2, 1, scan_id)
  1595. hold on
  1596. % --- 1. Data Preparation (Medians) ---
  1597. % MSM (Anatomical Baseline)
  1598. med_msm = double(nanmedian(anat_isc_gray(:, scan_id)));
  1599. % Piecewise Hyperalignment
  1600. med_pw = double(squeeze(nanmedian(piecewise_isc_gray(:,:,scan_id), 1))');
  1601. % Connectivity Hyperalignment
  1602. med_conn = double(squeeze(nanmedian(connectivity_isc_gray(:,:,scan_id), 1))');
  1603. avg_areas_db = double(avg_areas);
  1604. % --- 2. Plotting Connecting Lines ---
  1605. % Since we removed boundedline, we use standard plot calls for the lines
  1606. % Using 'LineWidth', 4 to match the thickness of your original fit lines
  1607. plot(avg_areas_db, med_pw, 'Color', orange_col, 'LineWidth', 4);
  1608. plot(avg_areas_db, med_conn, 'Color', purple_col, 'LineWidth', 4);
  1609. % --- 3. Median Scatter Points ---
  1610. % Piecewise
  1611. hp1 = scatter(avg_areas_db, med_pw, 150, 'filled', ...
  1612. 'MarkerFaceColor', orange_col, 'MarkerEdgeColor', 'k', 'LineWidth', 3);
  1613. % Connectivity
  1614. hp2 = scatter(avg_areas_db, med_conn, 150, 'filled', ...
  1615. 'MarkerFaceColor', purple_col, 'MarkerEdgeColor', 'k', 'LineWidth', 3);
  1616. % MSM point at x=0
  1617. scatter(0, med_msm, 170, 'filled', 'MarkerFaceColor', 'k', 'MarkerEdgeColor', 'k');
  1618. % --- 4. Aesthetics & Formatting ---
  1619. xlim([-100 1200]);
  1620. ylim([0.015 0.03]);
  1621. ylabel('ISC (r)');
  1622. xlabel('Average Parcel Area (mm^2)');
  1623. % Match the heavy axis style from your heritability code
  1624. ax = gca;
  1625. set(ax, 'TickDir', 'out', 'FontSize', 32, 'LineWidth', 5, 'Layer', 'bottom');
  1626. xticks([0 400 800 1200]);
  1627. xticklabels({'MSM', '400', '800', '1200'});
  1628. % Legend only on the top plot
  1629. if scan_id == 1
  1630. legend([hp1, hp2], {'Piecewise', 'Connectivity'}, 'Location', 'best', 'FontSize', 20);
  1631. legend boxoff;
  1632. end
  1633. grid off;
  1634. pbaspect([1.5 1 1]);
  1635. end
  1636. %% Re-run without GSR (Figure S4)
  1637. base_dir = [data_dir '/HCP_7T/'];
  1638. num_parcels = 400;
  1639. % HCP 7T Movie TR counts (standard lengths)
  1640. % Movie 1: 921, Movie 2: 918, Movie 3: 915, Movie 4: 901
  1641. tr_counts = [921, 918, 915, 901];
  1642. % Get subject list
  1643. subjects = dir(fullfile(base_dir, '*'));
  1644. subjects = subjects([subjects.isdir]);
  1645. subjects = subjects(~strncmp({subjects.name}, '.', 1));
  1646. num_subjs = length(subjects);
  1647. subjects(2,:) = [];
  1648. subjects(186,:) = [];
  1649. subjects(185,:) = [];
  1650. % --- PRE-ALLOCATION ---
  1651. % Creating four 3D matrices: [Parcels x Time x Subjects]
  1652. movie1_data = nan(num_parcels, tr_counts(1), num_subjs);
  1653. movie2_data = nan(num_parcels, tr_counts(2), num_subjs);
  1654. movie3_data = nan(num_parcels, tr_counts(3), num_subjs);
  1655. movie4_data = nan(num_parcels, tr_counts(4), num_subjs);
  1656. % Store in a cell array for easier indexing during the loop
  1657. all_movies = {movie1_data, movie2_data, movie3_data, movie4_data};
  1658. % --- LOADING LOOP ---
  1659. % Pre-allocate a status tracker: [num_subj subjects x 4 movies]
  1660. % 0 = Data OK, 1 = Contains NaNs, 2 = Missing File entirely
  1661. subj_nan_status = zeros(num_subj, 4);
  1662. tic
  1663. for i = 1:num_subj
  1664. subj_id = subjects(i).name;
  1665. results_path = fullfile(base_dir, subj_id, 'MNINonLinear', 'Results');
  1666. % Find all parcellated files for this subject
  1667. ptseries_files = dir(fullfile(results_path, 'tfMRI_MOVIE*', '*hp2000_clean.ptseries.nii'));
  1668. % Track which movies were found for this specific subject
  1669. movies_found = false(1, 4);
  1670. for f = 1:length(ptseries_files)
  1671. fname = ptseries_files(f).name;
  1672. tokens = regexp(fname, 'tfMRI_MOVIE(\d)', 'tokens');
  1673. if isempty(tokens), continue; end
  1674. m_idx = str2double(tokens{1}{1});
  1675. movies_found(m_idx) = true;
  1676. try
  1677. cifti_struct = ciftiopen(fullfile(ptseries_files(f).folder, fname), wb_path);
  1678. current_data = cifti_struct.cdata;
  1679. % --- CHECK FOR NANS ---
  1680. if any(isnan(current_data), 'all')
  1681. subj_nan_status(i, m_idx) = 1;
  1682. fprintf('!! Warning: Subj %s Movie %d contains NaNs\n', subj_id, m_idx);
  1683. end
  1684. % Assign to the correct slice
  1685. all_movies{m_idx}(1:size(current_data,1), 1:size(current_data,2), i) = current_data;
  1686. catch ME
  1687. warning('Failed to load %s: %s', fname, ME.message);
  1688. end
  1689. end
  1690. % Mark missing files
  1691. missing_idx = find(~movies_found);
  1692. if ~isempty(missing_idx)
  1693. subj_nan_status(i, missing_idx) = 2;
  1694. for m = missing_idx
  1695. fprintf('-- Missing: Subj %s Movie %d file not found\n', subj_id, m);
  1696. end
  1697. end
  1698. end
  1699. % Summary Report
  1700. fprintf('\n--- DATA QUALITY SUMMARY ---\n');
  1701. fprintf('Subjects with at least one NaN: %d\n', sum(any(subj_nan_status == 1, 2)));
  1702. fprintf('Subjects missing at least one run: %d\n', sum(any(subj_nan_status == 2, 2)));
  1703. xx = (any(subj_nan_status == 2, 2));
  1704. % Unpack cell array back into individual variables
  1705. movie1_data = all_movies{1};
  1706. movie2_data = all_movies{2};
  1707. movie3_data = all_movies{3};
  1708. movie4_data = all_movies{4};
  1709. % --- 1. PRE-PROCESSING ---
  1710. sub_data = cell(4,1);
  1711. sub_data{1} = movie1_data(:,:,1:num_subj);
  1712. sub_data{2} = movie2_data(:,:,1:num_subj);
  1713. sub_data{3} = movie3_data(:,:,1:num_subj);
  1714. sub_data{4} = movie4_data(:,:,1:num_subj);
  1715. % Define which TRs to cut from each of the 4 movie runs.
  1716. % Each movie clip is preceded by 20 seconds of rest. Here, we remove TRs that
  1717. % take place in those 20 seconds as well as in the first 20 seconds of each clip
  1718. % to account for potential onset transients.
  1719. cut_montage = 0; % 0 keeps the trailing montage clip; reproduces num_trs = [1432, 1409]
  1720. % Initialize matrices
  1721. rest_trs = cell(4,1);
  1722. movie_cut = cell(4,1);
  1723. movie_mask = cell(4,1);
  1724. starts = cell(4,1);
  1725. ends = cell(4,1);
  1726. % Rest blocks- Run 1
  1727. starts{1,1} = [0,264.0833,505.75,713.7917,797.5833,901];
  1728. starts{1,1} = floor(starts{1,1} +1);
  1729. ends{1,1} = [19.9583,284.0417,525.7083,733.75,817.5417,920.9583];
  1730. ends{1,1} = floor(ends{1,1} +1);
  1731. for i = 1:length(starts{1,1})
  1732. rest_trs{1,1} = [rest_trs{1,1} starts{1,1}(i):ends{1,1}(i)];
  1733. end
  1734. % Rest blocks- Run 2
  1735. starts{2,1} = [0,246.75,525.375,794.625,898];
  1736. starts{2,1} = floor(starts{2,1}+1);
  1737. ends{2,1} = [19.9583,266.7083,545.3333,814.5417,917.9583];
  1738. ends{2,1} = floor(ends{2,1}+1);
  1739. for i = 1:length(starts{2,1})
  1740. rest_trs{2,1} = [rest_trs{2,1} starts{2,1}(i):ends{2,1}(i)];
  1741. end
  1742. % Rest blocks- Run 3
  1743. starts{3,1} = [0,200.5833,405.125,629.25,791.7917,895];
  1744. starts{3,1} = floor(starts{3,1}+1);
  1745. ends{3,1} = [19.9583,220.5417,425.0833,649.2083,811.5417,914.9583];
  1746. ends{3,1} = floor(ends{3,1}+1);
  1747. for i = 1:length(starts{3,1})
  1748. rest_trs{3,1} = [rest_trs{3,1} starts{3,1}(i):ends{3,1}(i)];
  1749. end
  1750. % Rest blocks- Run 4
  1751. starts{4,1} = [0,252.3333,502.2083,777.4167,881];
  1752. starts{4,1} = floor(starts{4,1}+1);
  1753. ends{4,1} = [19.9583,272.2917,522.1667,797.5417,900.9583];
  1754. ends{4,1} = floor(ends{4,1}+1);
  1755. for i = 1:length(starts{4,1})
  1756. rest_trs{4,1} = [rest_trs{4,1} starts{4,1}(i):ends{4,1}(i)];
  1757. end
  1758. % Movie blocks- Run 1
  1759. starts{1,2} = [20,284.0833,525.75,733.7917,817.5833];
  1760. ends{1,2} = [264.0417,505.7083,713.75,797.5417,900.9583];
  1761. starts{1,2} = ceil(starts{1,2}+1);
  1762. ends{1,2} = floor(ends{1,2});
  1763. if cut_montage == 1
  1764. starts{1,2} = starts{1,2}(:,1:size(starts{1,2},2)-1);
  1765. ends{1,2} = ends{1,2}(:,1:size(ends{1,2},2)-1);
  1766. end
  1767. for i = 1:length(starts{1,2})
  1768. movie_cut{1,1} = [movie_cut{1,1} starts{1,2}(i):starts{1,2}(i)+19];
  1769. movie_mask{1,1}{i} = [starts{1,2}(i)+20 starts{1,1}(i+1)-1];
  1770. end
  1771. % Movie blocks- Run 2
  1772. starts{2,2} = [20,266.75,545.375,814.5833];
  1773. ends{2,2} = [246.7083,525.3333,794.5833,897.9583];
  1774. starts{2,2} = ceil(starts{2,2}+1);
  1775. ends{2,2} = floor(ends{2,2});
  1776. if cut_montage == 1
  1777. starts{2,2} = starts{2,2}(:,1:size(starts{2,2},2)-1);
  1778. ends{2,2} = ends{2,2}(:,1:size(ends{2,2},2)-1);
  1779. end
  1780. for i = 1:length(starts{2,2})
  1781. movie_cut{2,1} = [movie_cut{2,1} starts{2,2}(i):starts{2,2}(i)+19];
  1782. movie_mask{2,1}{i} = [starts{2,2}(i)+20 starts{2,1}(i+1)-1];
  1783. end
  1784. % Movie blocks- Run 3
  1785. starts{3,2} = [20,220.5833,425.125,649.25,811.5833];
  1786. ends{3,2} = [200.5417,405.0833,629.2083,791.75,894.9583];
  1787. starts{3,2} = ceil(starts{3,2}+1);
  1788. ends{3,2} = floor(ends{3,2});
  1789. if cut_montage == 1
  1790. starts{3,2} = starts{3,2}(:,1:size(starts{3,2},2)-1);
  1791. ends{3,2} = ends{3,2}(:,1:size(ends{3,2},2)-1);
  1792. end
  1793. for i = 1:length(starts{3,2})
  1794. movie_cut{3,1} = [movie_cut{3,1} starts{3,2}(i):starts{3,2}(i)+19];
  1795. movie_mask{3,1}{i} = [starts{3,2}(i)+20 starts{3,1}(i+1)-1];
  1796. end
  1797. % Movie blocks- Run 4
  1798. starts{4,2} = [20,272.3333,522.2083,797.5833];
  1799. ends{4,2} = [252.2917,502.1667,777.375,880.9583];
  1800. starts{4,2} = ceil(starts{4,2}+1);
  1801. ends{4,2} = floor(ends{4,2});
  1802. if cut_montage == 1
  1803. starts{4,2} = starts{4,2}(:,1:size(starts{4,2},2)-1);
  1804. ends{4,2} = ends{4,2}(:,1:size(ends{4,2},2)-1);
  1805. end
  1806. for i = 1:length(starts{4,2})
  1807. movie_cut{4,1} = [movie_cut{4,1} starts{4,2}(i):starts{4,2}(i)+19];
  1808. movie_mask{4,1}{i} = [starts{4,2}(i)+20 starts{4,1}(i+1)-1];
  1809. end
  1810. % Get indices of all frames that need to be removed
  1811. all_cut = cell(4,1);
  1812. all_cut{1,1} = unique(cat(2,rest_trs{1,1},movie_cut{1,1}));
  1813. all_cut{2,1} = unique(cat(2,rest_trs{2,1},movie_cut{2,1}));
  1814. all_cut{3,1} = unique(cat(2,rest_trs{3,1},movie_cut{3,1}));
  1815. all_cut{4,1} = unique(cat(2,rest_trs{4,1},movie_cut{4,1}));
  1816. for s_id = 1:4
  1817. % FIRST: Remove rest/onset frames
  1818. sub_data{s_id}(:, all_cut{s_id}, :) = [];
  1819. % SECOND: Z-score the remaining movie frames
  1820. for s = 1:num_subj
  1821. % Dimension 2 is Time
  1822. sub_data{s_id}(:,:,s) = zscore(sub_data{s_id}(:,:,s), 0, 2);
  1823. end
  1824. end
  1825. % Concatenate after cleaning
  1826. sub_data_cat{1} = cat(num_days, sub_data{1}, sub_data{2});
  1827. sub_data_cat{2} = cat(num_days, sub_data{3}, sub_data{4});
  1828. % --- 2. ISC CALCULATION ---
  1829. gsr_isc = zeros(num_subj, num_subj, 400, 2);
  1830. for d_idx = 1:num_days
  1831. parfor s1 = 1:num_subj
  1832. % Get data for all parcels for subject 1
  1833. data1 = sub_data_cat{d_idx}(:, :, s1);
  1834. for s2 = 1:num_subj
  1835. data2 = sub_data_cat{d_idx}(:, :, s2);
  1836. % Vectorized ISC (faster and avoids the 400x400 matrix)
  1837. % This is the same as diag(corr(data1', data2'))
  1838. gsr_isc(s1, s2, :, d_idx) = mean(data1 .* data2, 2);
  1839. end
  1840. end
  1841. end
  1842. % --- 3. HERITABILITY ---
  1843. for parc_id = 1:400
  1844. for day_id = 1:num_days
  1845. % Use day_id consistently throughout this block
  1846. current_isc = squeeze(gsr_isc(subjs_movie, subjs_movie, parc_id, day_id));
  1847. current_motion = covari_motion(subjs_movie, [1, 2, day_id + 2]);
  1848. isc_gsr_herit(parc_id, day_id) = h2_mat(current_isc, ...
  1849. kinship(subjs_movie, subjs_movie), ...
  1850. current_motion, 0, []);
  1851. end
  1852. end
  1853. saveCifti(isc_gsr_herit(:,1), strcat([data_dir '/isc_heritability/data/piecewise/outputs/parc/piecewise_anatomical_isc_herit_GSR_parc_'],curr_parc,'_day',num2str(1),'.pscalar.nii'), wb_path, schaefer_400_pscalar_kong,medial_mask);
  1854. saveCifti(isc_gsr_herit(:,2), strcat([data_dir '/isc_heritability/data/piecewise/outputs/parc/piecewise_anatomical_isc_herit_GSR_parc_'],curr_parc,'_day',num2str(2),'.pscalar.nii'), wb_path, schaefer_400_pscalar_kong,medial_mask);

isc_heritability.m at commit b50deb9, under MIT · at the source

Overview

  1. Medical Scientist Training Program, Columbia University Irving Medical Center, New York, United States
  2. New York State Psychiatric Institute, New York, United States
  3. Department of Psychiatry, Columbia University Irving Medical Center, New York, United States
Journal: eLife, volume 14, article RP106081
Dates: published online 4 August 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.7554/elife.106081 · PMID 42550150 · PMCID PMC13436958 · OpenAlex W4410139156
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), human (organism), systems (subfield)
Methods: Spectral & time-frequency, Statistics, Smoothing, state filtering, decompositions, Connectivity, Machine learning, fMRI & imaging
Keywords: Human
MeSH: Brain*, Motion Pictures*, Adult, Brain Mapping, Female, Humans, Magnetic Resonance Imaging, Male, Photic Stimulation, Young Adult (* major topic)
Topic: Functional Brain Connectivity Studies (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: NIMH NIH HHS (U54 MH091657); NIGMS NIH HHS (T32GM007367, T32 GM007367)
Citations: not cited yet (Europe PMC); 83 references in the paper

Abstract

The neural bases of sensory processing are conserved across people but no two individuals experience the same stimulus in exactly the same way. Recent work has established that the idiosyncratic nature of subjective experience is underpinned by individual variability in brain responses to sensory information. However, the fundamental origins of this individual variability have yet to be systematically investigated. Here, we establish a genetic basis for individual differences in sensory processing by quantifying (1) the heritability of high-dimensional brain responses to movies and (2) the extent to which this heritability is grounded in lower-level aspects of brain function. Specifically, we leverage 7T fMRI data collected from a twin sample to first show that movie-evoked brain activity is heritable across the cortex, and that this heritability is greater for information encoded in lower temporal frequencies, especially in more associative cortical areas. Next, we use hyperalignment to decompose this heritability into genetic similarity in where vs. how sensory information is processed. We also show that the heritability of brain activity patterns can be partially explained by the heritability of the neural timescale, a one-dimensional measure of local circuit functioning. Finally, we generalize our findings by illustrating a similar pattern of results for the heritability of movie-evoked functional connectivity. These results demonstrate that brain responses to complex stimuli are heritable, and that this heritability is due, in part, to genetic control over stable aspects of brain function.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 11 matches between paragraphs and lines of code.

dsclab42/Gruskin-eLife2026

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: b50deb9c846955372863d906037e9b108cbbbe1f, 20 July 2026
Languages: MATLAB (23), Jupyter (2), R (1)
Size: 28 files, 26 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, license file, 2 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Statistics and Machine Learning Toolbox (6 files), boundedline (2 files), cifti-matlab (2 files), fdr_bh (Benjamini-Hochberg FDR) (2 files), Curve Fitting Toolbox (2 files), Parallel Computing Toolbox (2 files), NiBabel (2 files), NumPy (2 files), pandas (2 files), SciPy (2 files), BrainSMASH (1 file), ggpubr (1 file), GIfTI library for MATLAB (1 file), h5py (1 file), Image Processing Toolbox (1 file), statsmodels (1 file), tidyverse (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
28 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;
  • 26 scripts, each with its path and the digest of its content;
  • 11 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.

Data availability

The raw HCP data used for this project can be downloaded from ConnectomeDB (db.humanconnectome.org). Code for all analyses is available at https://github.com/dsclab42/Gruskin-eLife2026 (copy archived at Gruskin, 2026). Analyses were performed in MATLAB (R2023b), Python, and R. All cortical surface visualizations were performed with Connectome Workbench (Marcus et al., 2011).

Reproduced under the paper's license (CC BY), from the paper cited above.

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, 4 authors, 1 keyword, 10 MeSH terms, 2 funders, 82 references.

Cite

This paper

Gruskin, D. C., Vieira, D. J., Lee, J. K., & Patel, G. H. (2026). Heritability of movie-evoked brain activity and connectivity. eLife, 14, RP106081. https://doi.org/10.7554/elife.106081

BibTeX

@article{gruskin2026heritability,
author = {Gruskin, David C and Vieira, Daniel J and Lee, Jessica K and Patel, Gaurav H},
title = {{Heritability of movie-evoked brain activity and connectivity}},
journal = {eLife},
year = {2026},
month = aug,
volume = {14},
pages = {RP106081},
publisher = {eLife Sciences Publications, Ltd},
issn = {2050-084X},
doi = {10.7554/elife.106081},
url = {https://doi.org/10.7554/elife.106081},
pmid = {42550150},
pmcid = {PMC13436958}
}

RIS

TY - JOUR
AU - Gruskin, David C
AU - Vieira, Daniel J
AU - Lee, Jessica K
AU - Patel, Gaurav H
TI - Heritability of movie-evoked brain activity and connectivity
T2 - eLife
J2 - Elife
PY - 2026
DA - 2026/08/04
VL - 14
SP - RP106081
SN - 2050-084X
PB - eLife Sciences Publications, Ltd
DO - 10.7554/elife.106081
UR - https://doi.org/10.7554/elife.106081
LA - en
ER -

CSL-JSON

{
"id": "10.7554/elife.106081",
"type": "article-journal",
"title": "Heritability of movie-evoked brain activity and connectivity",
"container-title": "eLife",
"author": [
{
"family": "Gruskin",
"given": "David C"
},
{
"family": "Vieira",
"given": "Daniel J"
},
{
"family": "Lee",
"given": "Jessica K"
},
{
"family": "Patel",
"given": "Gaurav H"
}
],
"container-title-short": "Elife",
"volume": "14",
"page": "RP106081",
"DOI": "10.7554/elife.106081",
"PMID": "42550150",
"PMCID": "PMC13436958",
"ISSN": "2050-084X",
"publisher": "eLife Sciences Publications, Ltd",
"URL": "https://doi.org/10.7554/elife.106081",
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
4
]
]
}
}

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.1038/s41586-026-10631-3 [code]
A prognostic human brain network for diffuse midline glioma.
Journal: Nature
In common: BrainSMASH, cifti-matlab, Curve Fitting Toolbox, 9 other tools, 2 references
[2] doi:10.1038/s41467-026-71151-2 [code]
Common and distinct neural correlates of social interaction processing and theory of mind in narratives.
Journal: Nature communications
In common: cifti-matlab, boundedline, fdr_bh (Benjamini-Hochberg FDR), 9 other tools
[3] doi:10.1002/hbm.70483 [code]
Untamed: Unconstrained Tensor Decomposition and Graph Node Embedding for Cortical Parcellation.
Journal: Human brain mapping
In common: cifti-matlab, GIfTI library for MATLAB, Parallel Computing Toolbox, 7 other tools, 3 references
[4] doi:10.1111/ene.70678 [code]
Who Falls After a Stroke? Evidence From a Prospective Stroke Cohort.
Journal: European journal of neurology
In common: cifti-matlab, Curve Fitting Toolbox, GIfTI library for MATLAB, 8 other tools, 1 reference
[5] doi:10.1038/s41467-026-74565-0 [code]
The functional neurobiology of dispositions towards negative emotions.
Journal: Nature communications
In common: cifti-matlab, boundedline, fdr_bh (Benjamini-Hochberg FDR), 7 other tools, 1 reference
[6] doi:10.1016/j.celrep.2026.117404 [code]
Action and rest tremor map to distinct networks within the primary motor cortex.
Journal: Cell reports
In common: cifti-matlab, Curve Fitting Toolbox, GIfTI library for MATLAB, 8 other tools, systems
[7] doi:10.1002/advs.202523009 [code]
Personalized Network-Guided Neuromodulation Enhances Human Working Memory.
Journal: Advanced science (Weinheim, Baden-Wurttemberg, Germany)
In common: cifti-matlab, GIfTI library for MATLAB, Image Processing Toolbox, 5 other tools, 4 references
[8] doi:10.1038/s41467-026-74153-2 [code]
Regional, functional and transcriptomic decoding of multidimensional brain structure alterations in obsessive-compulsive disorder.
Journal: Nature communications
In common: BrainSMASH, cifti-matlab, GIfTI library for MATLAB, 7 other tools, genetics / omics, 1 reference
[9] 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), GIfTI library for MATLAB, Image Processing Toolbox, 6 other tools, 4 references
[10] doi:10.1038/s42003-026-10276-y [code]
The cellular correlates and adolescent reorganisation of cortical myelination networks in the common marmoset.
Journal: Communications biology
In common: BrainSMASH, GIfTI library for MATLAB, Parallel Computing Toolbox, 8 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.