OSCR

The cellular correlates and adolescent reorganisation of cortical myelination networks in the common marmoset.

Code ↔ Paper

40 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 40 matches
  1. [1] § Methods › Marmoset transcriptional data and pre-processing › Single-cell, whole genome mRNA data ↔ Fig3.ipynb, lines 26–102 · score 0.91 · highly_variable_genes, gene expression vectors, CELLxGENE, gene expression matrix, correlated gene expression, visual cortex
  2. [2] § Methods › Marmoset transcriptional data and pre-processing › Single-cell, whole genome mRNA data ↔ Fig3.ipynb, lines 26–102 · score 0.91 · highly_variable_genes, gene expression vectors, CELLxGENE, gene expression matrix, correlated gene expression, visual cortex
  3. [3] § Methods › Age prediction ↔ Fig5.ipynb, lines 81–135 · score 0.88 · Gaussian process regression, white noise kernel, support vector regression, radial basis function, summed linear, alpha
  4. [4] § Methods › Age prediction ↔ Fig5.ipynb, lines 78–132 · score 0.88 · Gaussian process regression, white noise kernel, support vector regression, radial basis function, summed linear, alpha
  5. [5] § Methods › Statistical analysis › Spatial null models ↔ code/stats_helpers.py, lines 204–253 · score 0.80 · BrainSMASH permuted maps, spatial autocorrelation preserving, Euclidean distance, left hemispheric, surrogate, error
  6. [6] § Methods › Statistical analysis › Spatial null models ↔ code/stats_helpers.py, lines 204–253 · score 0.80 · BrainSMASH permuted maps, spatial autocorrelation preserving, Euclidean distance, left hemispheric, surrogate, error
  7. [7] § Results › Developmental changes in myelination similarity ↔ Fig6.ipynb, lines 89–137 · score 0.73 · left hemisphere regions, bilateral regions, Hierarchical clustering, sensory cluster, association cluster, Koniocortex
  8. [8] § Methods › Marmoset transcriptional data and pre-processing › Single-cell, whole genome mRNA data ↔ Fig3.ipynb, lines 104–175 · score 0.71 · endothelial cells, immune, astrocytes, glut, oligodendrocytes, GAD
  9. [9] § Methods › Marmoset transcriptional data and pre-processing › Single-cell, whole genome mRNA data ↔ Fig3.ipynb, lines 104–175 · score 0.71 · endothelial cells, immune, astrocytes, glut, oligodendrocytes, GAD
  10. [10] § Methods › Statistical analysis › Multiple linear regression ↔ code/stats_helpers.py, lines 408–462 · score 0.71 · Benjamini Hochberg, multiple linear regressions, interaction, FDR, sex, variable
  11. [11] § Methods › Statistical analysis › Multiple linear regression ↔ code/stats_helpers.py, lines 367–421 · score 0.71 · Benjamini Hochberg, multiple linear regressions, interaction, FDR, sex, variable
  12. [12] § Methods › Age prediction ↔ Fig5.ipynb, lines 341–431 · score 0.69 · absolute error, predicted age, partial correlation, outer, eTIV, fold
  13. [13] § Methods › Age prediction ↔ Fig5.ipynb, lines 338–428 · score 0.69 · absolute error, predicted age, partial correlation, outer, eTIV, fold
  14. [14] § Methods › Statistical analysis › Network null models ↔ code/stats_helpers.py, lines 130–170 · score 0.69 · BrainSmash, Euclidean distance, left hemisphere, MBP expression, permute, permutations
  15. [15] § Methods › Statistical analysis › Network null models ↔ code/stats_helpers.py, lines 130–170 · score 0.69 · BrainSmash, Euclidean distance, left hemisphere, MBP expression, permute, permutations
  16. [16] § Results › Estimation and anatomical validation of T1w/T2w similarity networks ↔ Sup_Fig2-4.ipynb, lines 447–514 · score 0.68 · intra class edges, cortical class, tract tracing, thresholded, biological, cytoarchitecture
  17. [17] § Results › Estimation and anatomical validation of T1w/T2w similarity networks ↔ Sup_Fig2-4.ipynb, lines 446–513 · score 0.68 · intra class edges, cortical class, tract tracing, thresholded, biological, cytoarchitecture
  18. [18] § Results › Developmental changes in myelination similarity ↔ Fig3.ipynb, lines 26–102 · score 0.67 · dorsolateral prefrontal, orbitofrontal cortex, parietal, cingulate, posterior, auditory
  19. [19] § Results › Developmental changes in myelination similarity ↔ Fig6.ipynb, lines 85–130 · score 0.66 · left hemisphere regions, Hierarchical clustering, sensory cluster, association cluster, Koniocortex, Agranular
  20. [20] § Methods › Marmoset anatomical data › Axonal connectivity ↔ Sup_Fig2-4.ipynb, lines 447–514 · score 0.66 · tract tracing matrix, upper triangle, edge complete, metric
  21. [21] § Methods › Marmoset anatomical data › Axonal connectivity ↔ Sup_Fig2-4.ipynb, lines 446–513 · score 0.66 · tract tracing matrix, upper triangle, edge complete, metric
  22. [22] § Results › Age-related changes in cortical T1w/T2w ↔ Sup_Fig8-.ipynb, lines 547–606 · score 0.65 · pre pubertal, pre puberty, multiple linear regressions, age related change, animal, T1w
  23. [23] § Results › Age-related changes in cortical T1w/T2w ↔ Sup_Figs7-.ipynb, lines 428–487 · score 0.65 · pre pubertal, pre puberty, multiple linear regressions, age related change, animal, T1w
  24. [24] § Methods › Statistical analysis › Linear regression sensitivity analyses ↔ Sup_Fig8-.ipynb, lines 609–677 · score 0.63 · median vitreous humour, median white matter, T2w models, covariates, regression, age
  25. [25] § Methods › Statistical analysis › Linear regression sensitivity analyses ↔ Sup_Figs7-.ipynb, lines 490–558 · score 0.63 · median vitreous humour, median white matter, T2w models, covariates, regression, age
  26. [26] § Results › Developmental changes in myelination similarity ↔ Fig5.ipynb, lines 341–431 · score 0.63 · absolute error, predict age, partial correlation, eTIV, trained, MAE
  27. [27] § Results › Developmental changes in myelination similarity ↔ Fig5.ipynb, lines 338–428 · score 0.63 · absolute error, predict age, partial correlation, eTIV, trained, MAE
  28. [28] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig2.ipynb, lines 369–402 · score 0.63 · Regional correlations, T2w MIND edge, cortical hierarchy, MBP MIND, positioned, Spearman
  29. [29] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig2.ipynb, lines 311–340 · score 0.63 · Regional correlations, T2w MIND edge, cortical hierarchy, MBP MIND, positioned, Spearman
  30. [30] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig2.ipynb, lines 369–402 · score 0.60 · cross modal, cortical hierarchy, MBP MIND, T2w MIND, Spearman, T1w
  31. [31] § Methods › Marmoset transcriptional data and pre-processing › In-situ hybridisation data ↔ Fig2.ipynb, lines 40–61 · score 0.60 · myelin basic protein, male marmoset, mRNA, parcellation, spaced, adult
  32. [32] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig2.ipynb, lines 40–61 · score 0.60 · T2w volume, myelin basic protein, mRNA, T2w images, parcellated, matched
  33. [33] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig2.ipynb, lines 311–340 · score 0.60 · cross modal, cortical hierarchy, MBP MIND, T2w MIND, Spearman, T1w
  34. [34] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Sup_Fig8-.ipynb, lines 193–285 · score 0.59 · sex matched animals, Standard deviation, MBP expression, skewness, maps, age
  35. [35] § Methods › Marmoset transcriptional data and pre-processing › In-situ hybridisation data ↔ Fig2.ipynb, lines 20–41 · score 0.58 · myelin basic protein, male marmoset, mRNA, parcellation, adult, MBP
  36. [36] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig3.ipynb, lines 689–826 · score 0.58 · interneuron subtypes, cell subtypes, VIP, GAD, PV, clustering
  37. [37] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig3.ipynb, lines 690–827 · score 0.58 · interneuron subtypes, cell subtypes, VIP, GAD, PV, clustering
  38. [38] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig3.ipynb, lines 104–175 · score 0.58 · glutamatergic neurons, correlated gene expression, expression network, astrocytes, CGE, bars
  39. [39] § Results › T1w/T2w similarity networks align with molecular and cellular transcriptomic markers of myeloarchitecture ↔ Fig3.ipynb, lines 104–175 · score 0.58 · glutamatergic neurons, correlated gene expression, expression network, astrocytes, CGE, bars
  40. [40] § Methods › Statistical analysis › Linear regression sensitivity analyses ↔ Sup_Fig8-.ipynb, lines 767–810 · score 0.56 · degree age coefficients, eTIV, covariate, regression, correlation

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

Jupyter notebook · 925 lines · 32 KB · MIT · 5 matches

  1. # %% [markdown]
  2. # ### **Figure 3: Myeloarchitectonic similarity is associated with co-expression of genes in glutamatergic neurons and PV+ and VIP+ interneurons**
  3. #
  4. # Cell type and cell subtype-specific correlated gene expression networks are provided in output/gene_exp/cge/
  5. #
  6. # Coarse MIND network edges per subject are saved to output/subj_dfs/edge_per_subj_coarse.csv
  7. #
  8. # If using these, 3.2 and 3.3 do not need to be run
  9. # %% [markdown]
  10. # #### **3.1 Setup**
  11. # %%
  12. # Autoreload
  13. %load_ext autoreload
  14. %autoreload 2
  15. # Import helper functions
  16. import sys
  17. sys.path.append('code')
  18. from stats_helpers import *
  19. from MIND_helpers import *
  20. from preprocessing_helpers import *
  21. from plotting_helpers import *
  22. # %% [markdown]
  23. # #### **3.2 Generate correlated gene expression (CGE) networks**
  24. # %% [markdown]
  25. # CELLxGENE data from Krienen et al. (2023) can be downloaded at:
  26. # https://cellxgene.cziscience.com/collections/0fd39ad7-5d2d-41c2-bda0-c55bde614bdb
  27. # %%
  28. # Import packages
  29. import scanpy as sc
  30. # Initialise directories
  31. data_dir = "data/"
  32. save_dir = "output/gene_exp/cge/"
  33. # Dictionary holding cell type filenames
  34. cell_types_dict = {
  35. 'GAD': 'd48da0be-0e47-485f-a36b-f02643d1058d.h5ad',
  36. 'oligo': 'c5e9c2f7-a450-409f-90d3-382f7109f5e1.h5ad',
  37. 'astro': 'd6d9942f-491b-416b-8951-330309bbc654.h5ad',
  38. 'glut': '5123a9c0-67e1-41da-9f59-f0894d62393a.h5ad',
  39. 'endo': '7d4ce011-c8d5-472f-8256-e3d5551e13e9.h5ad',
  40. 'immune': 'ac4323c8-c065-4d30-978b-ddb5537c36a2.h5ad'
  41. }
  42. # Dictionary holding coarse region names
  43. # Keys = names given in CELLxGENE matrices
  44. # Values = short names
  45. regions = {
  46. "dorsolateral prefrontal cortex":'DLP',
  47. "ventrolateral prefrontal cortex":'VLP',
  48. "medial prefrontal cortex":'MPC',
  49. "orbitofrontal cortex":'OFC',
  50. "lateral temporal cortex":'LTC',
  51. "lateral parietal cortex":'LPC',
  52. "posterior cingulate area 23":'PCA',
  53. "primary motor cortex":'M1',
  54. "primary somatosensory cortex":'S1',
  55. "primary auditory cortex":'A1',
  56. "primary visual cortex":'V1',
  57. "secondary visual cortex":'V2'
  58. }
  59. # Loop cell types
  60. for cell_type, cell_type_path in tqdm(cell_types_dict.items()):
  61. # Load CELLxGENE df
  62. adata = sc.read_h5ad(os.path.join(data_dir, cell_type_path))
  63. # Retain cortical regions of interest
  64. adata = adata[adata.obs['anatomical_name'].isin(list(regions.keys()))]
  65. # Retain top 10% most variable genes
  66. sc.pp.log1p(adata)
  67. sc.pp.highly_variable_genes(adata, flavor='seurat', n_top_genes=int(adata.var.shape[0]*0.1))
  68. adata = adata[:, adata.var['highly_variable']]
  69. # Get list of genes for which expression was measured
  70. genes = adata.var['human_gene_name'].unique().tolist()
  71. # Initialse df to hold mean expression of each gene in each region
  72. region_gene_mat = np.zeros((len(regions), len(genes)))
  73. # Loop regions
  74. for idx_region, region in enumerate(list(regions.keys())):
  75. # Get region indices
  76. region_indices = np.where(adata.obs['anatomical_name'] == region)[0].tolist()
  77. region_data = adata.X[region_indices, :]
  78. # Get mean expression of all genes over all cells in this region
  79. if region_data.shape[0] > 0:
  80. region_gene_mat[idx_region, :] = region_data.mean(axis=0)
  81. # Cross-correlate regional expression vectors to get correlated gene expression matrix
  82. cge = pd.DataFrame(np.corrcoef(region_gene_mat), index=list(regions.values()), columns=list(regions.values()))
  83. # Save
  84. cge.to_csv(os.path.join(save_dir, f'{cell_type}_cge.csv'))
  85. # %% [markdown]
  86. # Visualise correlated gene expression networks
  87. # %%
  88. from matplotlib.colors import LinearSegmentedColormap
  89. from matplotlib import rcParams
  90. # Set font to Arial
  91. rcParams['font.family'] = 'Arial'
  92. # Directory containing CGE matrices
  93. cge_mat_dir = 'output/gene_exp/cge/'
  94. # Dictionary holding cell type filenames
  95. cell_dict = {
  96. 'GAD': 'GAD_cge.csv',
  97. 'oligo': 'oligo_cge.csv',
  98. 'astro': 'astro_cge.csv',
  99. 'glut': 'glut_cge.csv',
  100. 'endo': 'endo_cge.csv',
  101. 'immune': 'immune_cge.csv'
  102. }
  103. # Dictionary holding colour mapping for cell types
  104. cmap = {
  105. 'GAD': [55/255, 126/255, 184/255, 1],
  106. 'oligo': [77/255, 175/255, 74/255, 1],
  107. 'astro': [152/255, 78/255, 163/255, 1],
  108. 'glut': [228/255, 26/255, 28/255, 1],
  109. 'endo': [0/255, 191/255, 196/255, 1],
  110. 'immune': [255/255, 127/255, 0/255, 1],
  111. }
  112. # Dictionary holding full names for cell types
  113. cell_names = {
  114. 'GAD': 'GAD+ interneurons',
  115. 'oligo': 'Oligodendrocytes',
  116. 'astro': 'Astrocytes',
  117. 'glut': 'Glutamatergic neurons',
  118. 'endo': 'Endothelial cells',
  119. 'immune': 'Immune cells',
  120. }
  121. # Create subplots
  122. n_cells = len(cell_dict)
  123. fig, axes = plt.subplots(2, 3, figsize=(12, 7)) # Adjust grid size as needed
  124. axes = axes.flatten() # Flatten to easily iterate over
  125. # Iterate over cell types and plot
  126. for i, (cell, filename) in enumerate(cell_dict.items()):
  127. # Load CGE matrix
  128. cge_mat_path = os.path.join(cge_mat_dir, filename)
  129. cge_mat = pd.read_csv(cge_mat_path, index_col=0)
  130. # Set colourmap
  131. cmap_custom = LinearSegmentedColormap.from_list(f'{cell}_cmap', [[1, 1, 1, 1], cmap[cell]])
  132. # Plot
  133. ax = axes[i]
  134. sns.heatmap(cge_mat, cmap=cmap_custom, ax=ax, cbar=True, xticklabels=[], yticklabels=[], rasterized=True)
  135. ax.set_title(f'{cell_names[cell]}', fontsize=24, pad=20)
  136. # Adjust colour bar
  137. cbar = ax.collections[0].colorbar
  138. cbar.ax.tick_params(labelsize=16)
  139. min_val = np.nanmin(cge_mat.values)
  140. ticks = np.linspace(min_val, 1, 4)
  141. cbar.set_ticks(ticks)
  142. cbar.set_ticklabels([f'{tick:.2f}' for tick in ticks], fontname='Arial')
  143. plt.tight_layout()
  144. plt.show()
  145. # %% [markdown]
  146. # Calculate correlated gene expression matrices for interneuron clusters defined in Krienen et al. (2023)
  147. # %%
  148. # Import packages
  149. import scanpy as sc
  150. # Initialise directories
  151. data_dir = "data/"
  152. save_dir = "output/gene_exp/cge/"
  153. # GAD CELLxGENE df path
  154. GAD_path = os.path.join(data_dir, "d48da0be-0e47-485f-a36b-f02643d1058d.h5ad")
  155. # Dictionary holding cell type filenames
  156. regions = {
  157. "dorsolateral prefrontal cortex":'DLP',
  158. "ventrolateral prefrontal cortex":'VLP',
  159. "medial prefrontal cortex":'MPC',
  160. "orbitofrontal cortex":'OFC',
  161. "lateral temporal cortex":'LTC',
  162. "lateral parietal cortex":'LPC',
  163. "posterior cingulate area 23":'PCA',
  164. "primary motor cortex":'M1',
  165. "primary somatosensory cortex":'S1',
  166. "primary auditory cortex":'A1',
  167. "primary visual cortex":'V1',
  168. "secondary visual cortex":'V2'
  169. }
  170. # Load CELLxGENE df
  171. adata = sc.read_h5ad(GAD_path)
  172. # Retain cortical regions of interest
  173. adata = adata[adata.obs['anatomical_name'].isin(list(regions.keys()))]
  174. # Retain top 10% most variable genes
  175. sc.pp.log1p(adata)
  176. sc.pp.highly_variable_genes(adata, flavor='seurat', n_top_genes=int(adata.var.shape[0]*0.1))
  177. adata = adata[:, adata.var['highly_variable']]
  178. # Get genes
  179. genes = adata.var['human_gene_name'].unique().tolist()
  180. # Get clusters
  181. clusters = adata.obs["CLUSTER"].unique()
  182. # Loop clusers
  183. for cluster in tqdm(clusters):
  184. # Initialse df to hold mean expression of each gene in each region
  185. region_gene_mat = np.zeros((len(regions), len(genes)))
  186. # Loop regions, average across regions
  187. for idx_region, region in enumerate(regions.keys()):
  188. # Get indices of cells in the relevant region AND cluster
  189. region_cluster_idx = np.where((adata.obs["anatomical_name"] == region) & (adata.obs["CLUSTER"] == cluster))[0]
  190. region_cluster_data = adata.X[region_cluster_idx, :]
  191. # Get mean expression of all genes over all cells in this cluster in this region
  192. if region_cluster_data.shape[0] > 0: # Take mean
  193. region_gene_mat[idx_region, :] = region_cluster_data.mean(axis=0).A1
  194. # Calculate CGE
  195. cge = np.corrcoef(region_gene_mat)
  196. # Save
  197. cge = pd.DataFrame(cge, index = regions.values(), columns = regions.values())
  198. cge.to_csv(os.path.join(save_dir, f'GAD_{cluster}_cge.csv'))
  199. # %% [markdown]
  200. # #### **3.3 Estimate individual coarse T1w/T2w similarity networks**
  201. # %% [markdown]
  202. # First, extract voxels from T1w/T2w images using `extract_voxels_coarse()`
  203. # %%
  204. # Load region lookup table(s)
  205. lut = pd.read_csv('data/lut_master.csv', index_col=0)
  206. coarse_lut = pd.read_csv('data/coarse_lut.csv', index_col=0)
  207. # Load subject lookup table
  208. subj_df = pd.read_csv('data/subj_df_all.csv', index_col=0)
  209. # Load relevant MRI directories
  210. scan_dir = 'data/t12_img/'
  211. label_dir = 'data/label_img/'
  212. # Create dir to hold voxel values
  213. vox_dir = 'output/T1wT2w/t12_MIND_coarse_all/'
  214. os.makedirs(vox_dir, exist_ok=True)
  215. # Loop subjects, extract voxels, save
  216. for _, row in subj_df.iterrows():
  217. t12_img_path = os.path.join(scan_dir, f'T1wT2w_{row["id"].astype(int).astype(str).zfill(3)}.nii')
  218. label_img_path = os.path.join(label_dir, f'{row["id"].astype(int).astype(str).zfill(3)}_labels.nii')
  219. vox_coarse = extract_voxels_coarse(
  220. t12_img_path,
  221. label_img_path,
  222. lut, 'bm_code', 'Code',
  223. coarse_lut, 'ROIs_short', 'Side', 'Codes'
  224. )
  225. vox_coarse.to_csv(os.path.join(vox_dir, f'{row["id"].astype(int).astype(str).zfill(3)}_vox_coarse.csv'))
  226. # %% [markdown]
  227. # Now calculate MIND networks for each subject using `calculate_MIND_network()`
  228. # %%
  229. # Import it to iterate subjects
  230. import itertools as it
  231. # Ignore division by 0 errors (these are normal)
  232. import warnings
  233. warnings.filterwarnings('ignore', category=RuntimeWarning)
  234. # Create dir to hold MIND networks
  235. MIND_dir = 'output/T1wT2w/t12_MIND_coarse_all/'
  236. os.makedirs(MIND_dir, exist_ok=True)
  237. # Get ROIs
  238. labs = coarse_lut['Label'].unique()
  239. n_rois = len(labs)
  240. # Initialise df to hold edge values per subject
  241. edge_per_subj_coarse = np.zeros((subj_df.shape[0], int((n_rois**2-n_rois)/2)))
  242. # Loop subjects, calculate MIND network, save
  243. for i, row in subj_df.iterrows():
  244. vox_path = os.path.join(vox_dir, f'{row["id"].astype(int).astype(str).zfill(3)}_vox_coarse.csv')
  245. vox_df = pd.read_csv(vox_path)
  246. MIND_net = calculate_mind_network(vox_df, ['Value'], labs)
  247. edge_per_subj_coarse[i,:] = MIND_net.values[np.triu_indices(n_rois, k=1)]
  248. MIND_path = os.path.join(MIND_dir, f'{row["id"].astype(int).astype(str).zfill(3)}_MIND_coarse.csv')
  249. MIND_net.to_csv(MIND_path)
  250. # Save edge df
  251. edge_per_subj_coarse_df = pd.concat([
  252. subj_df,
  253. pd.DataFrame(edge_per_subj_coarse, columns=list(it.combinations(labs,2)))
  254. ])
  255. edge_per_subj_coarse_df.to_csv('output/subj_dfs/edge_per_subj_coarse.csv', index=False)
  256. # %% [markdown]
  257. # #### **3.4 Compute mean adult coarse T1w/T2w similarity network**
  258. # %% [markdown]
  259. # Remove outliers
  260. #
  261. # Outliers are defined:
  262. # 1. Automatically, by being in the top/bottom 1% of `global_t12` or `global_MIND`, i.e. mean T1w/T2w or degree across all regions
  263. # 2. Manually, by identifying poorly registered scans
  264. # %%
  265. # Regional T1/2w
  266. mean_t12_per_subj_df = pd.read_csv('output/subj_dfs/mean_t12_per_subj.csv', index_col=0)
  267. mean_t12_per_subj_df = mean_t12_per_subj_df.sort_values('Age').reset_index(drop=True)
  268. # Regional KNN MIND
  269. degree_per_subj_df = pd.read_csv('output/subj_dfs/degree_per_subj.csv', index_col=0)
  270. degree_per_subj_df = degree_per_subj_df.sort_values('Age').reset_index(drop=True)
  271. # Edge KNN MIND
  272. edge_per_subj_df = pd.read_csv('output/subj_dfs/edge_per_subj.csv', index_col=0)
  273. edge_per_subj_df = edge_per_subj_df.sort_values('Age').reset_index(drop=True)
  274. # Define global measures
  275. global_t12 = mean_t12_per_subj_df.iloc[:,4:].mean(axis=1)
  276. global_MIND = degree_per_subj_df.iloc[:,4:].mean(axis=1)
  277. # Generate list of indices to remove
  278. outlier_ind = mean_t12_per_subj_df.loc[
  279. (global_t12 < global_t12.quantile(0.01)) |
  280. (global_t12 > global_t12.quantile(0.99))
  281. ].index.tolist() + degree_per_subj_df.loc[
  282. (global_MIND < global_MIND.quantile(0.01)) |
  283. (global_MIND > global_MIND.quantile(0.99))
  284. ].index.tolist()
  285. # Add manually identified outliers to the list
  286. outlier_id = [425,128,412,410,292,358]
  287. outlier_ind += [np.where(degree_per_subj_df['id'] == i)[0][0] for i in outlier_id]
  288. outlier_ind = np.unique(outlier_ind).tolist()
  289. # Filter
  290. edge_per_subj_coarse_df = pd.read_csv('output/subj_dfs/edge_per_subj_coarse.csv', index_col=0)
  291. edge_per_subj_coarse_df_filt = edge_per_subj_coarse_df.drop(index=outlier_ind).reset_index(drop=True)
  292. # %% [markdown]
  293. # Calculate mean adult T1w/T2w and mean adult MIND network, using subjects > 1.75 years, save to `/output`
  294. # %%
  295. # Get ROIs
  296. coarse_lut = pd.read_csv('data/coarse_lut.csv', index_col=0)
  297. labs = coarse_lut['Label'].unique()
  298. # Compute average MIND network
  299. adult_edges = edge_per_subj_coarse_df_filt[edge_per_subj_coarse_df_filt['Age'] > 1.75].iloc[:,3:].mean(axis=0)
  300. adult_MIND = np.zeros((len(labs), len(labs)))
  301. adult_MIND[np.triu_indices(len(labs), k=1)] = adult_edges
  302. adult_MIND += adult_MIND.T
  303. np.fill_diagonal(adult_MIND, 1)
  304. adult_MIND = pd.DataFrame(adult_MIND, index=labs, columns=labs)
  305. # Save
  306. save_dir = 'output/T1wT2w/mean/'
  307. os.makedirs(save_dir, exist_ok=True)
  308. adult_MIND.to_csv(os.path.join(save_dir, 'mean_adult_t12_MIND_coarse.csv'))
  309. # %% [markdown]
  310. # #### **3.5 Estimate coarse 4-year MBP expression similarity network**
  311. # %% [markdown]
  312. # First, extract voxels from MBP 4Y image using `extract_voxels_coarse()`
  313. # %%
  314. # Load region lookup table(s)
  315. lut = pd.read_csv('data/lut_master.csv', index_col=0)
  316. coarse_lut = pd.read_csv('data/coarse_lut.csv', index_col=0)
  317. # Initialise image paths
  318. MBP_4Y_path = 'data/MBP_4Y_img.nii'
  319. parc_img_path = 'data/sp2_label_512_v1.0.0.nii.gz'
  320. # Extract voxels
  321. vox_coarse = extract_voxels_coarse(
  322. MBP_4Y_path,
  323. parc_img_path,
  324. lut, 'bm_code', 'Code',
  325. coarse_lut, 'ROIs_short', 'Side', 'Codes'
  326. )
  327. # Remove outlier values caused by slice artefacts
  328. vox_coarse = vox_coarse[vox_coarse.Value < 0.8]
  329. # Save
  330. MBP_dir = 'output/MBP/'
  331. os.makedirs(MBP_dir, exist_ok=True)
  332. vox_coarse.to_csv(os.path.join(MBP_dir, 'MBP_4Y_vox_coarse.csv'))
  333. # %% [markdown]
  334. # Now calculate MIND network using `calculate_MIND_network()`
  335. # %%
  336. # Ignore division by 0 errors (these are normal)
  337. import warnings
  338. warnings.filterwarnings('ignore', category=RuntimeWarning)
  339. # Get ROIs
  340. labs = coarse_lut['Label'].unique()
  341. n_rois = len(labs)
  342. # Load voxel values from coarse parcellation
  343. vox_coarse = pd.read_csv('output/MBP/MBP_4Y_vox_coarse.csv', index_col=0)
  344. # Calculate coarse MIND network
  345. MBP_4Y_MIND_coarse = calculate_mind_network(vox_coarse, ['Value'], labs)
  346. # Save
  347. MBP_dir = 'output/MBP/'
  348. os.makedirs(MBP_dir, exist_ok=True)
  349. MBP_4Y_MIND_coarse.to_csv(os.path.join(MBP_dir, 'MBP_4Y_MIND_coarse.csv'))
  350. # %% [markdown]
  351. # #### **3.6 Correlate CGE and similarity network edges**
  352. # %% [markdown]
  353. # Start by loading data
  354. # %%
  355. # ----- Gene expression data ----- #
  356. # Path to CGE matries
  357. cge_mat_dir = 'output/gene_exp/cge/'
  358. # Dictionary containing CGE matrix filenames
  359. cell_dict = {
  360. 'GAD': 'GAD_cge.csv',
  361. 'oligo': 'oligo_cge.csv',
  362. 'astro': 'astro_cge.csv',
  363. 'glut': 'glut_cge.csv',
  364. 'endo': 'endo_cge.csv',
  365. 'immune': 'immune_cge.csv'
  366. }
  367. # Dictionary containing cell type colour mapping
  368. cmap = {
  369. 'GAD': [55/255, 126/255, 184/255, 1],
  370. 'oligo': [77/255, 175/255, 74/255, 1],
  371. 'astro': [152/255, 78/255, 163/255, 1],
  372. 'glut': [228/255, 26/255, 28/255, 1],
  373. 'endo': [0/255, 191/255, 196/255, 1],
  374. 'immune': [255/255, 127/255, 0/255, 1],
  375. }
  376. # ----- Anatomical data ----- #
  377. # Lookup table
  378. lut = pd.read_csv('data/lut_master.csv', index_col=0)
  379. # Coarse lookup table
  380. coarse_lut = pd.read_csv('data/coarse_lut.csv', index_col=0)
  381. # Distance matrix
  382. dist = pd.read_csv('data/distance_matrix.csv', index_col=0)
  383. dist = dist.iloc[0:115,0:115].values
  384. # Modality-specific anatomical data
  385. anat = {
  386. 'T12':{
  387. 'mat':pd.read_csv('output/T1wT2w/mean/mean_adult_t12_MIND_coarse.csv', index_col=0), # Coarse matrix
  388. 'mat_full':pd.read_csv('output/T1wT2w/mean/mean_adult_t12_MIND.csv', index_col=0), # Full matrix
  389. 'map':pd.read_csv('output/T1wT2w/mean/mean_adult_regional_t12.csv', index_col=0), # Mean value map (full)
  390. 'surrogates_filename':'output/surrogates/mean_adult_t12_surrogates.csv' # Surrogate mean value maps (full)
  391. },
  392. 'MBP':{
  393. 'mat':pd.read_csv('output/MBP/MBP_4Y_MIND_coarse.csv', index_col=0), # Coarse matrix
  394. 'mat_full':pd.read_csv('output/MBP/MBP_4Y_MIND.csv', index_col=0), # Full matrix
  395. 'map':pd.read_csv('output/MBP/MBP_4Y_regional_mean.csv', index_col=0), # Mean value map (full)
  396. 'surrogates_filename': 'output/surrogates/MBP_4Y_regional_mean_surrogates.csv' # Surrogate mean value maps (full)
  397. }
  398. }
  399. # %% [markdown]
  400. # Function to compute correlations and plot
  401. # %%
  402. def plot_cell_type_cge_MIND_correlations(modality, save_path=None):
  403. # Load anatomical data
  404. mat = anat[modality]['mat'].iloc[0:12,0:12] # Get lh
  405. mat_full = anat[modality]['mat_full'].iloc[0:115,0:115].values
  406. map = anat[modality]['map']; map = map[map.columns[0]].values[0:115]
  407. surrogates_filename = anat[modality]['surrogates_filename']
  408. # Make sure the MIND matrix is ordered correctly
  409. rois_ordered = ['DLP_L', 'VLP_L', 'MPC_L', 'OFC_L', 'LTC_L', 'LPC_L', 'PCA_L', 'M1_L', 'S1_L', 'A1_L', 'V1_L', 'V2_L']
  410. mat = mat.loc[rois_ordered,rois_ordered]
  411. # ----- Compute correlations ----- #
  412. # Initialise lists to hold r and p values
  413. cell_type_r_vals = []
  414. cell_type_p_vals = []
  415. # Iterate over cell types and plot
  416. for i, (cell, filename) in enumerate(cell_dict.items()):
  417. print(f"Calculating cell type: {cell}")
  418. cge_mat_path = os.path.join(cge_mat_dir, filename)
  419. cge_mat = pd.read_csv(cge_mat_path, index_col=0)
  420. # Make sure the matrix is ordered correctly
  421. rois_ordered = ['DLP', 'VLP', 'MPC', 'OFC', 'LTC', 'LPC', 'PCA', 'M1', 'S1', 'A1', 'V1', 'V2']
  422. cge_mat = cge_mat.loc[rois_ordered,rois_ordered]
  423. # Get r and p value
  424. r, p = get_brainsmashed_edge_correlation_p_val_coarse(mat_a = mat.values,
  425. mat_b = cge_mat.values,
  426. mat_a_full = mat_full,
  427. map_a = map,
  428. dist = dist,
  429. coarse_lut = coarse_lut[coarse_lut['Side']=='L'],
  430. lut = lut[lut['Side']=='L'],
  431. surrogates_filename = surrogates_filename,
  432. n_perm = 1000,
  433. test_type = 'two-tailed')
  434. cell_type_r_vals.append(r)
  435. cell_type_p_vals.append(p)
  436. # ----- Plotting ----- #
  437. # Sort cell types, colour map, r list, and p list to plot in descending order
  438. sorted_indices = np.argsort(cell_type_r_vals)
  439. sorted_cell_types = [list(cmap.keys())[i] for i in sorted_indices]
  440. sorted_colors = [list(cmap.values())[i] for i in sorted_indices]
  441. sorted_r_list = [cell_type_r_vals[i] for i in sorted_indices]
  442. sorted_p_list = [cell_type_p_vals[i] for i in sorted_indices]
  443. # Get corrected p-values (Bonferroni)
  444. _, p_corr, _, _ = multipletests(sorted_p_list, alpha=0.05, method='bonferroni')
  445. # Bar plot
  446. plt.figure(figsize=(4, 2.5)) # Adjust figure size for horizontal layout
  447. bars = plt.barh(sorted_cell_types, sorted_r_list, alpha=0.7, color=sorted_colors, height=0.9)
  448. plt.xlim([0,0.799])
  449. plt.title('All cell types', fontsize=20, pad=10, fontfamily='Arial')
  450. plt.yticks(fontsize=14, fontfamily='Arial')
  451. plt.xlabel('Spearman R', fontsize=20, fontfamily='Arial')
  452. plt.axvline(x=0, color='k') # Baseline
  453. # Remove top and right spines
  454. ax=plt.gca()
  455. ax.spines['top'].set_visible(False)
  456. ax.spines['right'].set_visible(False)
  457. # Annotate bars with asterisks based on p-values
  458. for bar, p_value in zip(bars, p_corr):
  459. if p_value < 0.001:
  460. annotation = '***'
  461. elif p_value < 0.01:
  462. annotation = '**'
  463. elif p_value < 0.05:
  464. annotation = '*'
  465. else:
  466. annotation = ''
  467. if annotation: # Only annotate if there is an asterisk
  468. width = bar.get_width()
  469. y = bar.get_y() + bar.get_height() / 2
  470. plt.text(
  471. width + 0.02, y - 0.15,
  472. annotation,
  473. ha='left', va='center', fontsize=12, color='black', fontweight='bold'
  474. )
  475. plt.tight_layout()
  476. if save_path is not None:
  477. plt.savefig(save_path, bbox_inches='tight')
  478. plt.show()
  479. # ----- Build and display results table ----- #
  480. results_df = pd.DataFrame({
  481. "cell": sorted_cell_types,
  482. "r val": sorted_r_list,
  483. "p val": sorted_p_list,
  484. "p val corrected": p_corr
  485. })
  486. print(results_df)
  487. # %% [markdown]
  488. # Correlate T1w/T2w MIND with CGE
  489. # %%
  490. plot_cell_type_cge_MIND_correlations('T12', save_path=None)
  491. # %% [markdown]
  492. # Repeat for MBP expression MIND
  493. # %%
  494. plot_cell_type_cge_MIND_correlations('MBP', save_path=None)
  495. # %% [markdown]
  496. # Plot scatterplot for correlation between MBP MIND and glutamatergic neuronal co-expression
  497. # %%
  498. # Load anatomical data
  499. modality = 'MBP'
  500. mat = anat[modality]['mat'].iloc[0:12,0:12] # Get lh
  501. # Make sure the matrix is ordered correctly
  502. rois_ordered = ['DLP_L', 'VLP_L', 'MPC_L', 'OFC_L', 'LTC_L', 'LPC_L', 'PCA_L', 'M1_L', 'S1_L', 'A1_L', 'V1_L', 'V2_L']
  503. mat = mat.loc[rois_ordered,rois_ordered]
  504. mat_full = anat[modality]['mat_full'].iloc[0:115,0:115].values
  505. map = anat[modality]['map']; map = map[map.columns[0]].values[0:115]
  506. surrogates_filename = anat[modality]['surrogates_filename']
  507. # Set path
  508. cell = 'glut'
  509. cge_mat = pd.read_csv(os.path.join(cge_mat_dir, cell_dict[cell]), index_col=0)
  510. # Make sure the matrix is ordered correctly
  511. rois_ordered = ['DLP', 'VLP', 'MPC', 'OFC', 'LTC', 'LPC', 'PCA', 'M1', 'S1', 'A1', 'V1', 'V2']
  512. cge_mat = cge_mat.loc[rois_ordered,rois_ordered]
  513. # Get r and p value
  514. r, p = get_brainsmashed_edge_correlation_p_val_coarse(mat_a = mat.values,
  515. mat_b = cge_mat.values,
  516. mat_a_full = mat_full,
  517. map_a = map,
  518. dist = dist,
  519. coarse_lut = coarse_lut[coarse_lut['Side']=='L'],
  520. lut = lut[lut['Side']=='L'],
  521. surrogates_filename = surrogates_filename,
  522. n_perm = 1000,
  523. test_type = 'two-tailed')
  524. # Scatter plot
  525. coarse_triu_ind = np.triu_indices_from(cge_mat, k=1)
  526. cge_mat_triu = cge_mat.values[coarse_triu_ind]
  527. mat_triu = mat.values[coarse_triu_ind]
  528. plt.figure(figsize=(4,2))
  529. sns.regplot(x=cge_mat_triu, y=mat_triu,
  530. scatter_kws={'alpha': 0.7, 'color': cmap[cell], 'edgecolors':'white', 's': 50},
  531. line_kws={'color': cmap[cell]})
  532. ax=plt.gca()
  533. if p < 0.001:
  534. p_text = 'p < 0.001'
  535. else:
  536. p_text = f'p = {p:.3f}'
  537. x1, x2 = ax.get_xlim(); y1, y2 = ax.get_ylim()
  538. ax.text((x1 + 0.025*(x2-x1)), (y1 + 0.75*(y2-y1)), f'r = {r:.2f}\n{p_text}', fontsize=18, fontfamily='Arial')
  539. ax.set_xlabel('CGE', fontsize=20, fontfamily='Arial')
  540. ax.set_ylabel('MBP\nMIND', fontsize=20, fontfamily='Arial')
  541. ax.set_title('Glutamatergic neurons', fontsize=20, pad=15, fontfamily='Arial')
  542. ax.spines['right'].set_visible(False)
  543. ax.spines['top'].set_visible(False)
  544. plt.show()
  545. # %% [markdown]
  546. # Repeat for interneuron correlated gene expression matrices
  547. #
  548. # Function to compute correlations and plot
  549. # %%
  550. def plot_cell_subtype_cge_MIND_correlations(modality, save_path=None):
  551. # Load anatomical data
  552. mat = anat[modality]['mat'].iloc[0:12,0:12] # Get lh
  553. mat_full = anat[modality]['mat_full'].iloc[0:115,0:115].values
  554. map = anat[modality]['map']; map = map[map.columns[0]].values[0:115]
  555. surrogates_filename = anat[modality]['surrogates_filename']
  556. # Make sure the MIND matrix is ordered correctly
  557. rois_ordered = ['DLP_L', 'VLP_L', 'MPC_L', 'OFC_L', 'LTC_L', 'LPC_L', 'PCA_L', 'M1_L', 'S1_L', 'A1_L', 'V1_L', 'V2_L']
  558. mat = mat.loc[rois_ordered,rois_ordered]
  559. # Dictionary storing interneuron subtypes
  560. subtype_cge_dict = {
  561. 'GAD': range(1, 13)
  562. }
  563. # ----- Compute correlations ----- #
  564. # Initialise df to hold results
  565. results = []
  566. # Loop clusters
  567. for cell, clusters in subtype_cge_dict.items():
  568. for cluster in clusters:
  569. print(f"Calculating cell type cluster: {cell}_{cluster}")
  570. # Load cell subtype CGE matrix
  571. file_path = os.path.join(cge_mat_dir, f'{cell}_{cluster}_cge.csv')
  572. if not os.path.exists(file_path):
  573. continue
  574. cge_mat = pd.read_csv(file_path, index_col=0)
  575. # Make sure rois are in the correct order
  576. rois_ordered = ['DLP', 'VLP', 'MPC', 'OFC', 'LTC', 'LPC', 'PCA', 'M1', 'S1', 'A1', 'V1', 'V2']
  577. cge_mat = cge_mat.loc[rois_ordered,rois_ordered]
  578. # Skip subtype if does not contain data from all cell types
  579. if cge_mat.isna().any().any():
  580. print(f'{cell}_{cluster} contains nans: skipping...')
  581. else:
  582. # Get r and p value
  583. r, p = get_brainsmashed_edge_correlation_p_val_coarse(mat_a = mat.values,
  584. mat_b = cge_mat.values,
  585. mat_a_full = mat_full,
  586. map_a = map,
  587. dist = dist,
  588. coarse_lut = coarse_lut[coarse_lut['Side']=='L'],
  589. lut = lut[lut['Side']=='L'],
  590. surrogates_filename = surrogates_filename,
  591. n_perm = 1000,
  592. test_type = 'two-tailed')
  593. results.append({
  594. 'cell_type': cell,
  595. 'cluster': cluster,
  596. 'r': r,
  597. 'p': p,
  598. })
  599. # Multiple comparisons correction
  600. raw_p_vals = [res['p'] for res in results]
  601. valid_idx = [i for i, p in enumerate(raw_p_vals) if not np.isnan(p)]
  602. valid_p_vals = [raw_p_vals[i] for i in valid_idx]
  603. _, p_corr, _, _ = multipletests(valid_p_vals, alpha=0.05, method='Bonferroni')
  604. for i, p_val in zip(valid_idx, p_corr):
  605. results[i]['p_corr'] = p_val
  606. for i in range(len(results)):
  607. if 'p_corr' not in results[i]:
  608. results[i]['p_corr'] = np.nan
  609. results_df = pd.DataFrame(results)
  610. # ----- Plotting ----- #
  611. # Mapping between clusters and neuronal subtypes (determined in Supplementary Figure 8)
  612. cluster_to_subtype_mapping = {
  613. '1':'LAMP5+ 1',
  614. '2':'LAMP5+ 2',
  615. '3':'VIP+',
  616. '4':'SNCG+ 1',
  617. '5':'SNCG+ 2',
  618. '6':'MEIS2+',
  619. '7':'SST+ 1',
  620. '8':'PV+ 1',
  621. '9':'PV+ 2',
  622. '10':'SST+ CHODL+',
  623. '11':'SST+ 2',
  624. '12':'SST+ 3',
  625. }
  626. # Map clusers to subtypes
  627. results_df['subtype'] = results_df['cluster'].astype(str).map(cluster_to_subtype_mapping)
  628. # Sort results
  629. results_df = results_df.sort_values(by=['r'], ascending=[False])
  630. # Bar plot
  631. g = sns.catplot(
  632. data=results_df, kind="bar", x="r", y="subtype", color=[55/255, 126/255, 184/255, 1],
  633. errorbar=None, alpha=0.7, height=3, aspect=2
  634. )
  635. g.set_axis_labels("Spearman R", "", fontsize=20, fontfamily='Arial')
  636. g.ax.set_yticklabels(g.ax.get_yticklabels(), ha='right', fontsize=14, fontfamily='Arial')
  637. g.ax.set_xlim([0, 0.7])
  638. ax = g.ax
  639. # Annotate significance
  640. for bar, (_, row) in zip(ax.patches, results_df.iterrows()):
  641. p = row['p_corr']
  642. if p < 0.001:
  643. txt = '***'
  644. elif p < 0.01:
  645. txt = '**'
  646. elif p < 0.05:
  647. txt = '*'
  648. else:
  649. txt = ''
  650. width = bar.get_width()
  651. y = bar.get_y() + bar.get_height() / 2
  652. ax.text(width + 0.01, y + 0.1, txt, ha='left', va='center', fontsize=14, fontweight='bold')
  653. if save_path is not None:
  654. plt.savefig(save_path, bbox_inches='tight')
  655. plt.show()
  656. # ----- Display results table ----- #
  657. print(results_df)
  658. # %% [markdown]
  659. # Correlate T1w/T2w MIND with subtype CGE
  660. # %%
  661. plot_cell_subtype_cge_MIND_correlations('T12', save_path=None)
  662. # %% [markdown]
  663. # Repeat for MBP expression MIND
  664. # %%
  665. plot_cell_subtype_cge_MIND_correlations('MBP', save_path=None)
  666. # %% [markdown]
  667. # Repeat for oligodendrocyte subtype correlated gene expression matrices (**Supplementary Methods:** *Analysis of oligodendrocyte subtypes*)
  668. #
  669. # Function to compute correlations and plot
  670. # %%
  671. def oligo_subtype_correlations(modality, save_path=None):
  672. # Load anatomical data
  673. mat = anat[modality]['mat'].iloc[0:12,0:12] # Get lh
  674. mat_full = anat[modality]['mat_full'].iloc[0:115,0:115].values
  675. map = anat[modality]['map']; map = map[map.columns[0]].values[0:115]
  676. surrogates_filename = anat[modality]['surrogates_filename']
  677. # Make sure the MIND matrix is ordered correctly
  678. rois_ordered = ['DLP_L', 'VLP_L', 'MPC_L', 'OFC_L', 'LTC_L', 'LPC_L', 'PCA_L', 'M1_L', 'S1_L', 'A1_L', 'V1_L', 'V2_L']
  679. mat = mat.loc[rois_ordered,rois_ordered]
  680. # Dictionary storing interneuron subtypes
  681. subtype_cge_dict = {
  682. 'oligo': range(1, 3)
  683. }
  684. # ----- Compute correlations ----- #
  685. # Initialise df to hold results
  686. results = []
  687. # Loop clusters
  688. for cell, clusters in subtype_cge_dict.items():
  689. for cluster in clusters:
  690. print(f"Calculating cell type cluster: {cell}_{cluster}")
  691. # Load cell subtype CGE matrix
  692. file_path = os.path.join(cge_mat_dir, f'{cell}_{cluster}_cge.csv')
  693. if not os.path.exists(file_path):
  694. continue
  695. cge_mat = pd.read_csv(file_path, index_col=0)
  696. # Make sure rois are in the correct order
  697. rois_ordered = ['DLP', 'VLP', 'MPC', 'OFC', 'LTC', 'LPC', 'PCA', 'M1', 'S1', 'A1', 'V1', 'V2']
  698. cge_mat = cge_mat.loc[rois_ordered,rois_ordered]
  699. # Skip subtype if does not contain data from all cell types
  700. if cge_mat.isna().any().any():
  701. print(f'{cell}_{cluster} contains nans: skipping...')
  702. else:
  703. # Get r and p value
  704. r, p = get_brainsmashed_edge_correlation_p_val_coarse(mat_a = mat.values,
  705. mat_b = cge_mat.values,
  706. mat_a_full = mat_full,
  707. map_a = map,
  708. dist = dist,
  709. coarse_lut = coarse_lut[coarse_lut['Side']=='L'],
  710. lut = lut[lut['Side']=='L'],
  711. surrogates_filename = surrogates_filename,
  712. n_perm = 1000,
  713. test_type = 'two-tailed')
  714. results.append({
  715. 'cell_type': cell,
  716. 'cluster': cluster,
  717. 'r': r,
  718. 'p': p,
  719. })
  720. # Multiple comparisons correction
  721. raw_p_vals = [res['p'] for res in results]
  722. valid_idx = [i for i, p in enumerate(raw_p_vals) if not np.isnan(p)]
  723. valid_p_vals = [raw_p_vals[i] for i in valid_idx]
  724. _, p_corr, _, _ = multipletests(valid_p_vals, alpha=0.05, method='Bonferroni')
  725. for i, p_val in zip(valid_idx, p_corr):
  726. results[i]['p_corr'] = p_val
  727. for i in range(len(results)):
  728. if 'p_corr' not in results[i]:
  729. results[i]['p_corr'] = np.nan
  730. results_df = pd.DataFrame(results)
  731. print(results_df)
  732. # %%
  733. oligo_subtype_correlations('T12', save_path=None)
  734. # %%
  735. oligo_subtype_correlations('MBP', save_path=None)

Fig3.ipynb at commit e44a2ec, under MIT · at the source

Overview

  1. Department of Psychiatry, University of Cambridge, Cambridge, UK
  2. Department of Physiology, Development and Neuroscience, University of Cambridge, Cambridge, UK
  3. Human Genetics Branch, National Institute of Mental Health, Bethesda, MD USA
  4. Department of Psychology, University of Cambridge, Cambridge, UK
  5. School of Academic Psychiatry, Institute of Psychiatry, Psychology & Neuroscience, King’s College London, London, UK
Institutions: University of Cambridge (United Kingdom); National Institute of Mental Health (United States); King's College London (United Kingdom)
Journal: Communications biology, volume 9, issue 1, article 1066
Dates: received 5 November 2025; accepted 6 May 2026; published online 19 May 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s42003-026-10276-y · PMID 42156922 · PMCID PMC13454510 · OpenAlex W7161740480
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: structural MRI / diffusion (modality), human (organism), non-human primate (organism)
Methods: Statistics, Machine learning, Connectivity, fMRI & imaging
Keywords: Neuroscience, Developmental biology, Development of the nervous system
MeSH: Callithrix*, Cerebral Cortex*, Myelin Sheath*, Animals, Female, Magnetic Resonance Imaging, Male, Myelin Basic Protein (* major topic)
Topic: Neurogenesis and neuroplasticity mechanisms (Developmental Neuroscience, Neuroscience), according to OpenAlex
Funding: Rosetrees Trust (MB2023\100002)
Citations: cited by 1 paper (Europe PMC); 101 references in the paper
Research resources: RRID:SCR_021059

Abstract

Structural similarity provides a powerful framework for measuring coordinated macro- and micro-structural variation across the cortex of a single brain. Similarity networks derived from myelin-sensitive MRI sequences undergo marked reorganisation during adolescence, linked to adversity exposure and behavioural outcomes in humans and rodents. However, the cellular mechanisms of MRI similarity and its development in non-human primate cortex remain unexplored. Here, we use myelin-sensitive T1w/T2w ratio images from a cross-sectional sample of 446 common marmosets (aged 0.62 to 12.75 years) to estimate MIND (Morphometric INverse Divergence) as a measure of myelination similarity in individual animals. We find that MIND metrics of myelination similarity are highly correlated with spatial gene expression of myelin basic protein (MBP) and other genes enriched in glutamatergic neurons and PV+ and VIP+ interneurons, reflecting the activity dependence of myelination. Across adolescence, network phenotypes accurately predict animal age and reproducibly capture an axis of myeloarchitectonic maturation spanning primary to transmodal association cortices, consistent with patterns observed in humans. Similarity mapping is a biologically validated and technically reliable measure of cortical myelination networks that can advance our understanding of phylogenetically conserved patterns of myelination network development in the marmoset cortex.

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

Repositories

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

edhutch1/marm_MIND

License: MIT
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: e44a2ec1fd464ee08c5cc70c5a4865c7e064d019, 27 July 2026
Languages: Jupyter (8), Python (5), R (1)
Size: 65 files, 14 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, environment (requirements.txt), 8 notebooks
Not found: CITATION.cff, tests, continuous integration, documentation
Tools: Matplotlib (6 files), SciPy (6 files), NumPy (5 files), pandas (5 files), statannotations (3 files), Scanpy (2 files), seaborn (2 files), statsmodels (2 files), BrainSMASH (1 file), mgcv (1 file), NiBabel (1 file), patchwork (1 file), Pingouin (1 file), scikit-learn (1 file), tidyverse (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
16 files

Zenodo 19758838

License: MIT
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Matplotlib (7 files), NumPy (6 files), pandas (6 files), SciPy (6 files), statannotations (3 files), Scanpy (2 files), seaborn (2 files), statsmodels (2 files), BrainSMASH (1 file), NiBabel (1 file), Pingouin (1 file), scikit-learn (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
  • 28 September 2026: the link answers (HTTP 200)
15 files
At the source:

TrangeTung/marmoset_gradient

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 76754a70be363ca5fe80a28d5de819377dc97e20, 1 November 2022
Languages: MATLAB (151)
Size: 194 files, 151 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
152 files

isebenius/MIND

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 0d334454eaac62e49a197801446ce7750256c882, 12 March 2024
Languages: Python (4), Jupyter (2)
Size: 15 files, 6 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, environment (requirements.txt)
Not found: license file, CITATION.cff, tests, continuous integration, documentation
Tools: NumPy (5 files), pandas (5 files), NiBabel (3 files), SciPy (3 files), Matplotlib (2 files), AFNI (1 file), FreeSurfer (1 file), Nipype (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
7 files

Code availability

Preprocessing of MRI data used Brainsuite18a80 and Advanced Normalisation Tools81 (ANTs). Preprocessing of in-situ hybridisation data used a modified version of previously published Matlab code87 (https://github.com/TrangeTung/marmoset_gradient) and ANTs. Computation of MIND networks used previously published Python code8 (https://github.com/isebenius/MIND). Downstream analyses were conducted in Python 3.11 using publicly available packages. Code and data required to reproduce all the analyses and results reported in this paper are openly available at https://github.com/edhutch1/marm_MIND and 10.5281/zenodo.19758838.

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

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:

  • 4 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 184 scripts, each with its path and the digest of its content;
  • 40 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 Statement

All raw data accessed in this study are openly available. Retrograde tract tracing data22 are available from http://marmosetbrain.org. Hierarchical location assignments for cortical areas25 are available from 10.1093/cercor/bhab191. Cytoarchitectonic class assignments46 are available from https://www.marmosetbrain.org/whole_brain_cb_maps. MRI data28 are available from the Brain/MINDs 2.0 data portal (https://dataportal.brainminds.jp/marmoset-mri-na216). In-situ hybridisation data37,38 are available from the Brain/MINDs Marmoset Gene Atlas data portal (https://gene-atlas.brainminds.jp/). Processed single nucleus RNA-sequencing data39 are available from the CELLxGENE data repository (RRID:SCR_021059; https://cellxgene.cziscience.com/collections/0fd39ad7-5d2d-41c2-bda0-c55bde614bdb). Marker gene sets used to assign biological identities to interneuron clusters are available from 10.1038/s41586-021-03465-8. Intermediate data files generated in this analysis are openly available at https://github.com/edhutch1/marm_MIND and 10.5281/zenodo.19758838. All other data are available from the corresponding author on reasonable request.

Preprocessing of MRI data used Brainsuite18a80 and Advanced Normalisation Tools81 (ANTs). Preprocessing of in-situ hybridisation data used a modified version of previously published Matlab code87 (https://github.com/TrangeTung/marmoset_gradient) and ANTs. Computation of MIND networks used previously published Python code8 (https://github.com/isebenius/MIND). Downstream analyses were conducted in Python 3.11 using publicly available packages. Code and data required to reproduce all the analyses and results reported in this paper are openly available at https://github.com/edhutch1/marm_MIND and 10.5281/zenodo.19758838.

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, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 6 authors, 3 keywords, 8 MeSH terms, 1 funder, 94 references, 1 RRID.

Cite

This paper

Hutchings, E. D., Sawiak, S. J., Smith, R. L., Bethlehem, R. A. I., Roberts, A. C., & Bullmore, E. T. (2026). The cellular correlates and adolescent reorganisation of cortical myelination networks in the common marmoset. Communications biology, 9(1), 1066. https://doi.org/10.1038/s42003-026-10276-y

BibTeX

@article{hutchings2026cellular,
author = {Hutchings, E D and Sawiak, S J and Smith, R L and Bethlehem, R A I and Roberts, A C and Bullmore, E T},
title = {{The cellular correlates and adolescent reorganisation of cortical myelination networks in the common marmoset}},
journal = {Communications biology},
year = {2026},
month = may,
volume = {9},
number = {1},
pages = {1066},
publisher = {Nature Publishing Group},
issn = {2399-3642},
doi = {10.1038/s42003-026-10276-y},
url = {https://doi.org/10.1038/s42003-026-10276-y},
pmid = {42156922},
pmcid = {PMC13454510}
}

RIS

TY - JOUR
AU - Hutchings, E D
AU - Sawiak, S J
AU - Smith, R L
AU - Bethlehem, R A I
AU - Roberts, A C
AU - Bullmore, E T
TI - The cellular correlates and adolescent reorganisation of cortical myelination networks in the common marmoset
T2 - Communications biology
J2 - Commun Biol
PY - 2026
DA - 2026/05/19
VL - 9
IS - 1
SP - 1066
SN - 2399-3642
PB - Nature Publishing Group
DO - 10.1038/s42003-026-10276-y
UR - https://doi.org/10.1038/s42003-026-10276-y
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s42003-026-10276-y",
"type": "article-journal",
"title": "The cellular correlates and adolescent reorganisation of cortical myelination networks in the common marmoset",
"container-title": "Communications biology",
"author": [
{
"family": "Hutchings",
"given": "E D"
},
{
"family": "Sawiak",
"given": "S J"
},
{
"family": "Smith",
"given": "R L"
},
{
"family": "Bethlehem",
"given": "R A I"
},
{
"family": "Roberts",
"given": "A C"
},
{
"family": "Bullmore",
"given": "E T"
}
],
"container-title-short": "Commun Biol",
"volume": "9",
"issue": "1",
"page": "1066",
"DOI": "10.1038/s42003-026-10276-y",
"PMID": "42156922",
"PMCID": "PMC13454510",
"ISSN": "2399-3642",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s42003-026-10276-y",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
19
]
]
}
}

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/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, BrainSpace, Nipype, 14 other tools, 8 references
[2] doi:10.1038/s41467-026-73714-9 [code]
The genetic architecture of cortical similarity networks.
Journal: Nature communications
In common: Nipype, AFNI, FreeSurfer, 7 other tools, structural MRI / diffusion, 10 references, 2 authors
[3] doi:10.1038/s41398-026-04025-2 [code]
Brain energetic landscapes shape state dysregulation in major depressive disorder: a morphological network controllability perspective.
Journal: Translational psychiatry
In common: BrainSMASH, BrainSpace, Nipype, 15 other tools, 5 references
[4] doi:10.1038/s41586-026-10631-3 [code]
A prognostic human brain network for diffuse midline glioma.
Journal: Nature
In common: CAT12, BrainSMASH, BrainSpace, 15 other tools, 1 reference
[5] doi:10.1038/s41467-026-76011-7 [code]
Human cortex organizes dynamic co-fluctuations along the sensorimotor-association axis.
Journal: Nature communications
In common: BrainSpace, mgcv, Brain Connectivity Toolbox, 12 other tools, 4 references
[6] doi:10.1038/s41593-026-02205-3 [code]
Competitive interactions shape mammalian brain network dynamics and computation.
Journal: Nature neuroscience
In common: Nipype, Brain Connectivity Toolbox, Parallel Computing Toolbox, 11 other tools, non-human primate, 6 references
[7] doi:10.7554/elife.103097 [code]
Canonical neurodevelopmental trajectories of structural and functional manifolds.
Journal: eLife
In common: BrainSpace, mgcv, Brain Connectivity Toolbox, 9 other tools, structural MRI / diffusion, 4 references, author Richard Bethlehem
[8] 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: Nipype, Brain Connectivity Toolbox, AFNI, 16 other tools
[9] doi:10.1038/s41467-026-71270-w [code]
Spatiotemporal dynamics of the human cortical functional hierarchy across the lifespan.
Journal: Nature communications
In common: BrainSpace, GIfTI library for MATLAB, Parallel Computing Toolbox, 9 other tools, 8 references
[10] doi:10.1371/journal.pbio.3003856 [code]
Aging and metabolism contribute separately to brain-body health.
Journal: PLoS biology
In common: AFNI, GIfTI library for MATLAB, FreeSurfer, 11 other tools, structural MRI / diffusion, 5 references

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.