OSCR

Metabolism-weighted brain connectome reveals synaptic integration and vulnerability to neurodegeneration.

Code ↔ Paper

12 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 12 matches
  1. [1] § Materials and Methods › Weighted Degree Centrality (wDC). ↔ src/Functions.ipynb, lines 502–595 · score 0.66 · Pearson correlation, edge weighted, FC matrix, thresholded, masked, SC
  2. [2] § Results › Metabolism-Weighted Hubness Reflects Synaptic Gene Expression and Susceptibility to Neurodegenerative Diseases. ↔ scripts/Figures_codes.ipynb, lines 2218–2277 · score 0.62 · oxidative phosphorylation, Alzheimer, neurodegenerative, KEGG, diseases, pathways
  3. [3] § Materials and Methods › Participants. ↔ scripts/Figures_codes.ipynb, lines 97–209 · score 0.61 · Vienna.rep, TUM.rep, split
  4. [4] § Materials and Methods › Control Analyses. ↔ scripts/Figures_codes.ipynb, lines 3759–3889 · score 0.60 · MI threshold, SC threshold, sensitivity, voxels, energy, PET
  5. [5] § Results › MwC Reveals Energy-Based Architecture of Cortical Integration. ↔ scripts/Figures_codes.ipynb, lines 3891–4033 · score 0.59 · Julich Brain atlas, spatial correlation, CMRglc, MNI, S6, parcellation
  6. [6] § Materials and Methods › Statistical Analyses. ↔ src/Functions.ipynb, lines 1530–1558 · score 0.57 · correlation coefficients, dependent correlations, Steiger, variable, scored
  7. [7] § Materials and Methods › Statistical Analyses. ↔ src/functions.py, lines 732–759 · score 0.57 · correlation coefficients, dependent correlations, Steiger, variable, scored
  8. [8] § Results › Metabolism-Weighted Hubs Align with Cognitive Network Hierarchies. ↔ scripts/Figures_codes.ipynb, lines 1474–1489 · score 0.57 · eye movements, visuospatial, inhibition, Neurosynth, memory, cognitive
  9. [9] § Materials and Methods › Participants. ↔ scripts/MwC_generation.ipynb, lines 18–61 · score 0.56 · Vienna.rep, TUM.rep
  10. [10] § Materials and Methods › Model Description. ↔ src/Functions.ipynb, lines 912–915 · score 0.54 · Gaussian Copula Mutual, mutual information
  11. [11] § Materials and Methods › Model Description. ↔ src/functions.py, lines 336–338 · score 0.54 · Gaussian Copula Mutual, mutual information
  12. [12] § Materials and Methods › Weighted Degree Centrality (wDC). ↔ src/functions.py, lines 922–984 · score 0.51 · edge weighted, FC matrix, thresholded, masked, SC, graph

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 · 4,803 lines · 159 KB · MIT · 5 matches

  1. # %% [markdown]
  2. # # Setting
  3. # %% [markdown]
  4. # ## libraries
  5. # %%
  6. %load_ext autoreload
  7. %autoreload 2
  8. import sys
  9. from pathlib import Path
  10. SRC = (Path.cwd().parent / "src").resolve()
  11. sys.path.insert(0, str(SRC))
  12. import importlib
  13. import functions
  14. importlib.reload(functions)
  15. from functions import *
  16. # %%
  17. import os
  18. import os,sys
  19. import numpy as np
  20. import scipy as sp
  21. import igraph as ig
  22. import scipy.speciali ws
  23. import scipy.stats as stats
  24. from scipy.stats import norm
  25. np.float = float
  26. np.int = int
  27. import pandas as pd
  28. import pickle
  29. import csv
  30. import shutil
  31. import time
  32. import warnings
  33. import nilearn as ni
  34. from nilearn import datasets, plotting #, surface, plotting, input_data
  35. from nilearn.image import math_img, threshold_img, smooth_img
  36. from nilearn.plotting import cm as nip_cm
  37. import nibabel as nib
  38. import networkx as nx
  39. import seaborn as sns
  40. import matplotlib.pyplot as plt
  41. import matplotlib.cm as cm
  42. import matplotlib.colors as mcolors
  43. from matplotlib.colors import ListedColormap, LinearSegmentedColormap, Normalize
  44. from matplotlib.patches import Patch
  45. from matplotlib.cm import ScalarMappable
  46. from scipy.stats import pearsonr, zscore, spearmanr
  47. from scipy.spatial.distance import euclidean
  48. from scipy.spatial import distance
  49. from scipy import linalg, optimize
  50. import matplotlib.colorbar as colorbar
  51. from enigmatoolbox.permutation_testing import rotate_parcellation, perm_sphere_p
  52. import matplotlib as mpl
  53. # import plotly.io as pio
  54. np.seterr(invalid='ignore')
  55. #import enigmatoolbox
  56. from enigmatoolbox.utils.parcellation import surface_to_parcel, parcel_to_surface
  57. import statsmodels.api as sm
  58. import plotly.graph_objects as go
  59. # from brainsmash.mapgen.base import Base
  60. # from brainsmash.mapgen.eval import base_fit
  61. # from brainsmash.mapgen.stats import nonparp, pairwise_r
  62. # import plotly.graph_objects as go
  63. # from neuromaps.datasets import fetch_annotation
  64. # import matplotlib.ticker as ticker
  65. # import textwrap
  66. # # Define FSL directories
  67. os.environ["FSLDIR"] = "/usr/share/fsl/5.0"
  68. os.environ["FSLOUTPUTTYPE"] = "NIFTI_GZ"
  69. os.environ["FSLTCLSH"] = "/usr/bin/tclsh"
  70. os.environ["FSLWISH"] = "/usr/bin/wish"
  71. os.environ["FSLMULTIFILEQUIT"] = "True"
  72. os.environ["LD_LIBRARY_PATH"] = "/usr/share/fsl/5.0:/usr/lib/fsl/5.0"
  73. # Fix deprecated NumPy aliases
  74. np.float = float
  75. np.int = int
  76. # %% [markdown]
  77. # ## IMPORTANT: select the data (main or external) AND including/excluding the limbic nework
  78. # %%
  79. # ================================================
  80. # 1. session selection (main or external dataset):
  81. # ================================================
  82. session = "AUF" # AUF(main), ZU(TUM.rep), m1 (Vienna.rep session 1) or m2 (Vienna.rep session 2)
  83. #DIR = f'/data/raw/{session}/'
  84. nrois = 360
  85. # ================================================
  86. # 2. select if you want to include limbic or not:
  87. # ================================================
  88. # including limbic:
  89. # limb_ind = []
  90. # LIMB = 'with'
  91. # excluding limbic:
  92. limb_ind = np.array([88, 90, 92, 93, 110, 118, 120, 122, 131, 135, 165, 166, 172, 268, 270, 272, 273, 290, 298, 300, 302, 311, 314, 315, 346, 352])-1
  93. LIMB = 'without'
  94. # ================================================
  95. # 3. Parameter assignments:
  96. # ================================================
  97. # sub = os.listdir(DIR)
  98. # sub = sorted([int(s.split('-')[1]) for s in sub if s.startswith('sub-') and s.split('-')[1].isdigit()])
  99. # if session == "ZU":
  100. # sub.remove(14)
  101. # if session == 'AUF':
  102. # sub = [3,7,12,14,17,20,23,25,26,28,29,30,31,32,33,35,36,37,38]
  103. # sub_size = len(sub)
  104. nrois_rem = nrois - len(limb_ind)
  105. net_label = pd.read_csv(f'../data/external/mmp2yeo7nw_mapping.csv')
  106. net_label = net_label.drop(limb_ind,axis=0)
  107. net_names = pd.unique(net_label['yeo_7_nw'])
  108. net_label.reset_index(drop=True, inplace=True)
  109. network_to_number = {network: i + 1 for i, network in enumerate(net_label['yeo_7_nw'].unique())}
  110. net_label['network_number'] = net_label['yeo_7_nw'].map(network_to_number)
  111. ## network colors assignment:
  112. color = [(139, 19, 140),(1,131, 182),(51, 116, 32),
  113. (222, 75, 82),(226, 55, 255),(239, 156, 60), (255, 254, 211)]
  114. net_color = [(r/255, g/255, b/255 , 1) for r,g,b in color]
  115. customPalette = sns.set_palette(sns.color_palette(net_color))
  116. xtik = ['Vis','Som','Dors','Def', 'Sal' , 'Cont', 'Limbic']
  117. net_names = ['Vis', 'SomMot' ,'DorsAttn' ,'Default' ,'SalVentAttn', 'Cont', 'Limbic' ]
  118. net_num = net_label["network_number"]
  119. new_net_num = np.tile(net_num.transpose(), (nrois_rem, 1))
  120. num_net = len(net_names)
  121. # ================================================
  122. # 4. Parcellation setting:
  123. # ================================================
  124. mmp = nib.load(f'../data/external/MMP_in_MNI_corr_3mm.nii.gz').get_fdata()
  125. v11 , v22 , v33 = mmp.shape
  126. nvox2 = v11 * v22 * v33
  127. mmp_re = mmp.reshape((nvox2, 1),order='F')
  128. regions = np.unique(mmp_re)[1:]
  129. regions_rem = regions.copy()
  130. regions_rem = np.delete(regions_rem , limb_ind)
  131. # ================================================
  132. # 4. figure's properties:
  133. # ================================================
  134. FONT = 18
  135. COLOR = "#8DD084" #"#97A8C0" #"#8DD084"
  136. IC_PET_COLf = '#70DEB6'
  137. IC_PET_COLe = '#1FC488'
  138. organg = [255/255,164/255,0/255]
  139. GRAY = "#7F7F7F"
  140. deg_color = "#97A8C0"
  141. IC_color = "#8DD084"
  142. approximate_colors = [
  143. "#341C54",
  144. "#3E2166",
  145. "#482677", # Dark Purple
  146. "#44357F",
  147. "#404387", # Purple-Blue
  148. "#33638D", # Blue
  149. "#2A788E", # Blue-Green
  150. "#1F9E89", # Greenish-Blue
  151. "#35B779", # Green
  152. "#6DCD59", # Lime Green
  153. "#B4DE2C", # Yellow-Green
  154. "#D9E329",
  155. "#EBE527",
  156. "#FDE725" # Yellow
  157. ]
  158. approximate_cmap = LinearSegmentedColormap.from_list("approximate_colormap", approximate_colors, N=256)
  159. CMAP_IC = approximate_cmap
  160. cool_cmap = plt.get_cmap('cool')
  161. #cool_cmap = cm.get_cmap('cool')
  162. cool_colors = cool_cmap(np.linspace(0.15, 0.95, 256))
  163. CMAP_DC = LinearSegmentedColormap.from_list("adjusted_cool", cool_colors)
  164. # %% [markdown]
  165. # ## color maps/ colors
  166. # %%
  167. approximate_colors = [
  168. "#341C54",
  169. "#3E2166",
  170. "#482677", # Dark Purple
  171. "#44357F",
  172. "#404387", # Purple-Blue
  173. "#33638D", # Blue
  174. "#2A788E", # Blue-Green
  175. "#1F9E89", # Greenish-Blue
  176. "#35B779", # Green
  177. "#6DCD59", # Lime Green
  178. "#B4DE2C", # Yellow-Green
  179. "#D9E329",
  180. "#EBE527",
  181. "#FDE725" # Yellow
  182. ]
  183. approximate_cmap = LinearSegmentedColormap.from_list("approximate_colormap", approximate_colors, N=256)
  184. CMAP_IC = approximate_cmap
  185. import matplotlib.pyplot as plt
  186. # Now this works:
  187. cool_cmap = plt.get_cmap('cool')
  188. #cool_cmap = cm.get_cmap('cool')
  189. cool_colors = cool_cmap(np.linspace(0.15, 0.95, 256))
  190. CMAP_DC = LinearSegmentedColormap.from_list("adjusted_cool", cool_colors)
  191. network_colors = [(139, 19, 140), (1, 131, 182), (51, 116, 32), (222, 75, 82), (226, 55, 255), (239, 156, 60), (255, 254, 211)]
  192. network_colors = [(r / 255, g / 255, b / 255) for (r, g, b) in network_colors]
  193. network_colors = ['#9A199A', '#45B7F0','#58B73B','#DE4B52','#E237FF','#F29A36','#FEFFD3']
  194. lighter_colors = [sns.light_palette(color, n_colors=100, input="hex")[50] for color in network_colors]
  195. #lighter_colors2 = [(*sns.color_palette([color])[0], 0.01) for color in lighter_colors] # Adding 50% opacity
  196. lighter_colors2 = ['#C788C7' , '#C0EBFF' , '#BEE6B2' , '#F2BABD', '#F6C2FF','#F7C58D']
  197. network_order_original = ['Vis', 'SomMot', 'DorsAttn', 'Default', 'SalVentAttn', 'Cont']
  198. network_color_map = dict(zip(network_order_original, network_colors))
  199. lighter_color_map = dict(zip(network_order_original, lighter_colors))
  200. import matplotlib.colors as mcolors
  201. def matplotlib_to_plotly(cmap, n=256):
  202. """Convert a Matplotlib colormap to a Plotly-friendly colorscale."""
  203. return [
  204. [i / (n - 1), mcolors.rgb2hex(cmap(i / (n - 1))[:3])]
  205. for i in range(n)
  206. ]
  207. # %% [markdown]
  208. # # Preparing data
  209. # %% [markdown]
  210. # ## Loading MwC and DC matrices
  211. # %%
  212. '''
  213. The following files were generated in MwC_generation.ipynb notebook:
  214. 1. matrices_data_{session}_{LIMB}_limbic.pkl
  215. 2. DATA_avg_wSC_{session}_{LIMB}_limb.csv
  216. 3. data_single_sub_wSC_{session}_{LIMB}_limb.pkl
  217. 4. DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv
  218. 5. data_single_sub_wSC_pr_{session}_{LIMB}_limb.pkl
  219. '''
  220. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  221. with open(file_path, 'rb') as file:
  222. data_input = pickle.load(file)
  223. num_voxels = data_input['num_voxels']
  224. MIconn_allsub = data_input['MIconn_allsub']
  225. SCconn_allsub = data_input['SCconn_allsub']
  226. Pearconn_allsub = data_input['Pearconn_allsub']
  227. edata_medianallsub = data_input['edata_medianallsub']
  228. #--------------------------------------------------------------------------------------------
  229. #-------------- Reading MWC matrices --------------------------
  230. #--------------------------------------------------------------------------------------------
  231. ## with structural connectivity masking:
  232. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  233. data_sub_path = f'../data/processed/data_single_sub_wSC_{session}_{LIMB}_limb.pkl'
  234. data_avg_pr_path = f'../data/processed/DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv'
  235. data_sub_pr_path = f'../data/processed/data_single_sub_wSC_pr_{session}_{LIMB}_limb.pkl'
  236. ## without structural connectivity masking:
  237. # data_avg_pr_path = f'../data/processed/DATA_avg_woSC_pr_{session}_{LIMB}_limb.csv'
  238. # data_sub_pr_path = f'../data/processed/data_single_sub_woSC_pr_{session}_{LIMB}_limb.pkl'
  239. # data_avg_path = f'../data/processed/DATA_avg_woSC_{session}_{LIMB}_limb.csv'
  240. # data_sub_path = f'../data/processed/data_single_sub_woSC_{session}_{LIMB}_limb.pkl'
  241. DATA_avg = pd.read_csv(data_avg_path)
  242. with open(data_sub_path, 'rb') as file:
  243. data_single_sub = pickle.load(file)
  244. ICallsub_w = data_single_sub['ICallsub_w']
  245. ICallsub_b = data_single_sub['ICallsub_b']
  246. degallsub_w = data_single_sub['degallsub_w']
  247. degallsub_b = data_single_sub['degallsub_b']
  248. AvgMIallsub = data_single_sub['AvgMIallsub']
  249. #--------------------------------------------------------------------------------------------
  250. #-------------- Reading DC matrices ----------------
  251. #--------------------------------------------------------------------------------------------
  252. DATA_avg_pr = pd.read_csv(data_avg_pr_path)
  253. with open(data_sub_pr_path, 'rb') as file:
  254. data_single_sub_pr = pickle.load(file)
  255. ICallsub_w_pr = data_single_sub_pr['ICallsub_w']
  256. ICallsub_b_pr = data_single_sub_pr['ICallsub_b']
  257. degallsub_w_pr = data_single_sub_pr['degallsub_w']
  258. degallsub_b_pr = data_single_sub_pr['degallsub_b']
  259. AvgMIallsub_pr = data_single_sub_pr['AvgMIallsub']
  260. sub_size = ICallsub_w_pr.shape[1]
  261. # %% [markdown]
  262. # ## Correlation values
  263. # %%
  264. from scipy.stats import pearsonr
  265. corr_IC_E_allsub = np.zeros((sub_size))
  266. corr_btw_E_allsub = np.zeros((sub_size))
  267. corr_eig_E_allsub = np.zeros((sub_size))
  268. corr_deg_w_E_allsub = np.zeros((sub_size))
  269. corr_IC_E_net_allsub = np.zeros((sub_size, len(net_names)))
  270. p_IC_E_allsub = np.zeros((sub_size))
  271. p_deg_w_E_allsub = np.zeros((sub_size))
  272. p_btw_E_allsub = np.zeros((sub_size, 1))
  273. p_eig_E_allsub = np.zeros((sub_size, 1))
  274. p_IC_E_net_allsub = np.zeros((sub_size, len(net_names)))
  275. for j in range(sub_size):
  276. degallsub_w_z = zscore(degallsub_w[:, j] , nan_policy='omit')
  277. corr_IC_E_allsub[j], p_IC_E_allsub[j] = pcor(ICallsub_w[:, j], edata_medianallsub[:, j])
  278. corr_deg_w_E_allsub[j], p_deg_w_E_allsub[j] = pcor(degallsub_w_z, edata_medianallsub[:, j])
  279. corr_IC_w_E, p_IC_w_E = pcor(DATA_avg.ICallsub_w_avg, DATA_avg.pet_avg)
  280. corr_IC_b_E, p_IC_b_E = pcor(DATA_avg.ICallsub_b_avg, DATA_avg.pet_avg)
  281. corr_IC_w_deg, p_IC_w_deg = pcor(DATA_avg.ICallsub_w_avg, DATA_avg.degallsub_w_avg)
  282. corr_IC_b_deg, p_IC_b_deg = pcor(DATA_avg.ICallsub_b_avg, DATA_avg.degallsub_b_avg)
  283. corr_deg_w_E, p_deg_w_E = pcor(zscore(DATA_avg.degallsub_w_avg , nan_policy='omit'), DATA_avg.pet_avg)
  284. # %% [markdown]
  285. # # Figures
  286. # %% [markdown]
  287. # ## Fig 2a: MwC vs CMRglc
  288. # %%
  289. #--------------------------------------------------------------------------------------------
  290. #---------------------- spatial autocorrelation (SAC) -----------------------------------
  291. #--------------------------------------------------------------------------------------------
  292. ##### BRAIN SMASH:
  293. # niter = 10
  294. # test_stat_IC ,surrogate_brainmap_corrs_IC, sa_corrected_p_value_IC, spatially_naive_p_value_IC = Spatial_AC(DATA_avg , "IC", LIMB,niter)
  295. # sac1 = '#0199DD'
  296. # sac2 = '#8CCF83'
  297. # sac3 = '#FEAD01'
  298. # fig, ax = plt.subplots(figsize=(3, 7))
  299. # plt.grid(True)
  300. # g = sns.kdeplot(surrogate_brainmap_corrs_IC, color= "#E0E0E0", ax=ax, fill= True, linewidth=2.5 )
  301. # ax.axvline(corr_IC_w_E, 0, 0.9, color= COLOR, linestyle='dashed', lw=3)
  302. # ax.set_xticks(np.arange(-1, 1.1, 0.5))
  303. # ax.set_ylim(0, 2)
  304. # ax.set_xlim(-0.8, 0.8)
  305. # spine_width = 1.6
  306. # spine_color = 'gray'
  307. # for spine in ax.spines.values():
  308. # spine.set_linewidth(spine_width)
  309. # spine.set_color(spine_color)
  310. # plt.tick_params(axis='both', which='major', labelsize= FONT)
  311. # plt.xlabel('Correlation', fontsize = FONT)
  312. # plt.ylabel('Density', fontsize = FONT)
  313. # plt.savefig(f'../results/Figures/CMRglc_IC_hist.png', dpi=300, bbox_inches='tight')
  314. # plt.show()
  315. # lower_bound = np.percentile(surrogate_brainmap_corrs_IC, 5)
  316. # upper_bound = np.percentile(surrogate_brainmap_corrs_IC, 95)
  317. # print(f"95% CI of null distribution: [{lower_bound:.2f}, {upper_bound:.2f}]")
  318. ### SPIN TEST###################
  319. N_ROT = 10000
  320. RNG_SEED = 42
  321. session = 'AUF'
  322. LIMB = 'with'
  323. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  324. DATA_avg_spin = pd.read_csv(data_avg_path)
  325. cmrglc = DATA_avg_spin['pet_avg'].to_numpy(dtype=float).ravel()
  326. ic = DATA_avg_spin['ICallsub_w_avg'].to_numpy(dtype=float).ravel()
  327. #rho_ic, p_spin_ic, null_ic = run_spin_test(ic, cmrglc, N_ROT,RNG_SEED)
  328. FONT = 22
  329. COLOR = IC_color
  330. null_r = np.asarray(null_ic, dtype=float)
  331. null_r = null_r[np.isfinite(null_r)]
  332. fig, ax = plt.subplots(figsize=(3, 7))
  333. plt.grid(True)
  334. sns.kdeplot(
  335. null_r,
  336. color="#E0E0E0",
  337. ax=ax,
  338. fill=True,
  339. linewidth=2.5
  340. )
  341. ax.axvline(rho_ic, 0, 0.9, color=COLOR, linestyle='dashed', lw=3)
  342. ax.set_xticks(np.arange(-1, 1.1, 0.5))
  343. ax.set_ylim(0, 4)
  344. ax.set_xlim(-0.8, 0.8)
  345. spine_width = 1.6
  346. spine_color = 'gray'
  347. for spine in ax.spines.values():
  348. spine.set_linewidth(spine_width)
  349. spine.set_color(spine_color)
  350. plt.tick_params(axis='both', which='major', labelsize=FONT)
  351. plt.xlabel('Correlation', fontsize=FONT)
  352. plt.ylabel('Density', fontsize=FONT)
  353. #plt.savefig('../results/Figures/CMRglc_IC_hist.png', dpi=300, bbox_inches='tight')
  354. plt.show()
  355. lower_bound = np.percentile(null_r, 5)
  356. upper_bound = np.percentile(null_r, 95)
  357. print(f"90% CI of null distribution: [{lower_bound:.2f}, {upper_bound:.2f}]")
  358. #--------------------------------------------------------------------------------------------
  359. #------------------ scatter IC_avg , CMRglc_avg / group analysis ----------------------------
  360. #--------------------------------------------------------------------------------------------
  361. COLOR = IC_color
  362. plt.figure(figsize=(6,4))
  363. g = sns.jointplot(data=DATA_avg, x='pet_avg', y='ICallsub_w_avg', kind="reg", color=COLOR,
  364. marginal_kws=dict(bins=15, fill=True, color='gray'),
  365. line_kws={'color': 'black', 'lw': 1},
  366. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  367. p_IC_w_E_smash = p_IC_w_E
  368. if p_IC_w_E_smash < 0.0001:
  369. title = "r = {:.2f} , p-smash < {:.3f}".format(float(corr_IC_w_E), float(0.001))
  370. else:
  371. title = "r = {:.2f} , p-smash = {:.3f}".format(float(corr_IC_w_E), float(p_IC_w_E_smash))
  372. #g.fig.suptitle(f"corr = {corr_IC_w_E:.2f}"", $Pval_{smash}$ < 0.001", fontsize=FONT, va='baseline', y=0.8)
  373. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  374. g.set_axis_labels('Target Energy', 'MwC', fontsize=FONT)
  375. plt.tick_params(axis='both', which='major', labelsize= FONT)
  376. plt.grid(True)
  377. plt.xlabel('Target Energy (CMRglc)', fontsize = FONT)
  378. plt.ylabel('MwC', fontsize = FONT)
  379. ax = g.ax_joint
  380. spine_width = 1.6
  381. for spine in ax.spines.values():
  382. spine.set_linewidth(spine_width)
  383. spine.set_edgecolor("gray")
  384. #plt.savefig(f'../results/Figures/CMRglc_IC_scatter.png', dpi=300, bbox_inches='tight')
  385. plt.show()
  386. #--------------------------------------------------------------------------------------------
  387. #------------------ Box plot individual correlation between IC and E -----------------------
  388. #--------------------------------------------------------------------------------------------
  389. data = pd.DataFrame({'r': corr_IC_E_allsub, 'p': p_IC_E_allsub})
  390. fig, ax = plt.subplots(figsize=(3, 7))
  391. plt.grid(True)
  392. violin = sns.violinplot(data=data, y='r', ax=ax, color = COLOR)
  393. violin.collections[0].set_facecolor('none')
  394. sns.stripplot(data=data[data['p'] < 0.05], y='r', color=COLOR , size = 8, ax=ax)
  395. sns.stripplot(data=data[data['p'] >= 0.05], y='r', color='red' , size = 8, ax=ax)
  396. ax.set_ylabel('Correlation MwC and target\'s energy', fontsize = FONT)
  397. ax.set_ylim([-0.15,0.72])
  398. plt.tick_params(axis='both', which='major', labelsize= FONT)
  399. spine_width = 1.6
  400. spine_color = 'gray'
  401. for spine in ax.spines.values():
  402. spine.set_linewidth(spine_width)
  403. spine.set_color(spine_color)
  404. #plt.savefig(f'../results/Figures/CMRglc_IC_box.png', dpi=300, bbox_inches='tight')
  405. plt.show()
  406. #--------------------------------------------------------------------------------------------
  407. #--------------------------- IC map on the brain surface -----------------------------------
  408. #--------------------------------------------------------------------------------------------
  409. IC = np.array(DATA_avg.ICallsub_w_avg).reshape(-1, 1)
  410. IC_allrois = np.zeros((360,1))
  411. ind = np.arange(360)
  412. mask = np.ones(ind.shape , dtype = bool)
  413. mask[limb_ind] = False
  414. ind = ind[mask]
  415. IC_allrois[ind] = np.abs(IC)
  416. fig = plt.figure(figsize=(5, 5),dpi=300)
  417. fsaverage = datasets.fetch_surf_fsaverage()
  418. V_min = IC.min()
  419. V_max = IC.max()
  420. V_max = 34
  421. col_fsa = parcel_to_surface(IC_allrois,'glasser_360_fsa5')
  422. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  423. hemi='left', vmin= V_min, vmax = V_max, view='lateral',
  424. bg_map=fsaverage['sulc_left'], bg_on_data=False,
  425. darkness=0.5, cmap=CMAP_IC,colorbar=False)
  426. #plt.savefig(f'../results/Figures/IC_surf_l_lateral.png', dpi=300, bbox_inches='tight')
  427. plt.show()
  428. col_fsa = parcel_to_surface(IC_allrois,'glasser_360_fsa5')
  429. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  430. hemi='left', vmin= V_min, vmax = V_max, view='medial',
  431. bg_map=fsaverage['sulc_left'], bg_on_data = False,
  432. darkness=0.5,cmap=CMAP_IC,colorbar=False)
  433. #plt.savefig(f'../results/Figures/IC_surf_l_medial.png', dpi=300, bbox_inches='tight')
  434. plt.show()
  435. col_fsa = parcel_to_surface(IC_allrois,'glasser_360_fsa5')
  436. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map = col_fsa[int(col_fsa.shape[0]/2):],
  437. hemi='right', vmin= V_min, vmax = V_max, view='lateral',
  438. bg_map=fsaverage['sulc_right'], bg_on_data=False,
  439. darkness=0.5, cmap=CMAP_IC,colorbar=False)
  440. #plt.savefig(f'../results/Figures/IC_surf_r_lateral.png', dpi=300, bbox_inches='tight')
  441. plt.show()
  442. col_fsa = parcel_to_surface(IC_allrois,'glasser_360_fsa5')
  443. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map = col_fsa[int(col_fsa.shape[0]/2):],
  444. hemi='right', vmin= V_min, vmax = V_max, view='medial',
  445. bg_map=fsaverage['sulc_right'], bg_on_data = False,
  446. darkness=0.5,cmap=CMAP_IC,colorbar=False)
  447. #plt.savefig(f'../results/Figures/IC_surf_r_medial.png', dpi=300, bbox_inches='tight')
  448. plt.show()
  449. cmap = plt.get_cmap(CMAP_IC)
  450. norm = plt.Normalize(vmin=V_min, vmax=V_max)
  451. fig, ax = plt.subplots(figsize=(6, 1))
  452. fig.subplots_adjust(bottom=0.5)
  453. cb = colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation='horizontal')
  454. cb.ax.tick_params(labelsize=18)
  455. #plt.savefig('../results/Figures/IC_colorbar_horizontal.png', dpi=300, bbox_inches='tight')
  456. plt.show()
  457. #--------------------------------------------------------------------------------------------
  458. #---------------------- regions with strongest IC values -----------------------------------
  459. #--------------------------------------------------------------------------------------------
  460. #plot_node_surf(DATA_avg, MIconn_allsub, 'ICallsub_w_avg', CMAP_IC,0.1, limb_ind)
  461. # %% [markdown]
  462. # ## Fig 2b: DC vs CMRglc
  463. # %%
  464. deg_color = '#9CB9E8'
  465. COLOR = deg_color
  466. corr_deg_w_E_allsub = np.zeros((sub_size))
  467. p_deg_w_E_allsub = np.zeros((sub_size))
  468. for j in range(sub_size):
  469. corr_deg_w_E_allsub[j], p_deg_w_E_allsub[j] = pcor(degallsub_w_pr[:,j], edata_medianallsub[:, j])
  470. corr_deg_w_E, p_deg_w_E = pcor(DATA_avg_pr.degallsub_w_avg , DATA_avg_pr.pet_avg)
  471. #--------------------------------------------------------------------------------------------
  472. #---------------------- spatial autocorrelation (SAC) -----------------------------------
  473. #--------------------------------------------------------------------------------------------
  474. ### BRAI SMASH:
  475. # niter = 1000
  476. # test_stat_DC ,surrogate_brainmap_corrs_DC, sa_corrected_p_value_DC, spatially_naive_p_value_DC = Spatial_AC(DATA_avg_pr , "deg_w", LIMB,niter)
  477. # sac1 = '#0199DD'
  478. # sac2 = '#8CCF83'
  479. # sac3 = '#FEAD01'
  480. # fig, ax = plt.subplots(figsize=(3, 7))
  481. # plt.grid(True)
  482. # g = sns.kdeplot(surrogate_brainmap_corrs_DC, color= "#E0E0E0", ax=ax, fill= True, linewidth=2.5 )
  483. # ax.axvline(corr_deg_w_E, 0, 0.9, color= COLOR, linestyle='dashed', lw=3)
  484. # ax.set_xticks(np.arange(-1, 1.1, 0.5))
  485. # ax.set_ylim(0, 2)
  486. # ax.set_xlim(-0.8, 0.8)
  487. # #ax.text(0.5, -0.1, "Pearson correlation\nwith IE map", ha='center', va='top', transform=ax.transAxes)
  488. # spine_width = 1.6
  489. # spine_color = 'gray'
  490. # for spine in ax.spines.values():
  491. # spine.set_linewidth(spine_width)
  492. # spine.set_color(spine_color)
  493. # plt.tick_params(axis='both', which='major', labelsize= FONT)
  494. # plt.xlabel('Correlation', fontsize = FONT)
  495. # plt.ylabel('Density', fontsize = FONT)
  496. # plt.savefig(f'../results/Figures/CMRglc_DC_hist.png', dpi=300, bbox_inches='tight')
  497. # plt.show()
  498. # lower_bound = np.percentile(surrogate_brainmap_corrs_DC, 5)
  499. # upper_bound = np.percentile(surrogate_brainmap_corrs_DC, 95)
  500. # print(f"95% CI of null distribution: [{lower_bound:.2f}, {upper_bound:.2f}]")
  501. #--------------------------------------------------------------------------------------------
  502. #---------------------- spin test -----------------------------------
  503. #--------------------------------------------------------------------------------------------
  504. N_ROT = 10000
  505. RNG_SEED = 42
  506. session = 'AUF'
  507. LIMB = 'with'
  508. data_avg_path_pr = f'../data/processed/DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv'
  509. DATA_avg_spin = pd.read_csv(data_avg_path_pr)
  510. cmrglc = DATA_avg_spin['pet_avg'].to_numpy(dtype=float).ravel()
  511. deg = DATA_avg_spin['degallsub_w_avg'].to_numpy(dtype=float).ravel()
  512. rho_deg, p_spin_deg, null_deg = run_spin_test(deg, cmrglc, N_ROT,RNG_SEED)
  513. FONT = 22
  514. null_r = np.asarray(null_deg, dtype=float)
  515. null_r = null_r[np.isfinite(null_r)]
  516. fig, ax = plt.subplots(figsize=(3, 7))
  517. plt.grid(True)
  518. sns.kdeplot(
  519. null_r,
  520. color="#E0E0E0",
  521. ax=ax,
  522. fill=True,
  523. linewidth=2.5
  524. )
  525. ax.axvline(rho_deg, 0, 0.9, color=COLOR, linestyle='dashed', lw=3)
  526. ax.set_xticks(np.arange(-1, 1.1, 0.5))
  527. ax.set_ylim(0, 4)
  528. ax.set_xlim(-0.8, 0.8)
  529. spine_width = 1.6
  530. spine_color = 'gray'
  531. for spine in ax.spines.values():
  532. spine.set_linewidth(spine_width)
  533. spine.set_color(spine_color)
  534. plt.tick_params(axis='both', which='major', labelsize=FONT)
  535. plt.xlabel('Correlation', fontsize=FONT)
  536. plt.ylabel('Density', fontsize=FONT)
  537. #plt.savefig('../results/Figures/CMRglc_DC_hist.png', dpi=300, bbox_inches='tight')
  538. plt.show()
  539. lower_bound = np.percentile(null_r, 5)
  540. upper_bound = np.percentile(null_r, 95)
  541. print(f"90% CI of null distribution: [{lower_bound:.2f}, {upper_bound:.2f}]")
  542. #--------------------------------------------------------------------------------------------
  543. #------------------ scatter deg_avg , CMRglc_avg / group analysis ----------------------------
  544. #--------------------------------------------------------------------------------------------
  545. plt.figure(figsize=(6,4))
  546. g = sns.jointplot(data=DATA_avg_pr, x='pet_avg', y='degallsub_w_avg', kind="reg", color=COLOR,
  547. marginal_kws=dict(bins=15, fill=True, color='gray'),
  548. line_kws={'color': 'black', 'lw': 1},
  549. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  550. p_deg_w_E_smash = p_spin_deg
  551. if p_deg_w_E_smash < 0.0001:
  552. title = "r = {:.2f} , p-spin< {:.3f}".format(float(corr_deg_w_E), float(0.001))
  553. else:
  554. title = "r = {:.2f} , p-spin = {:.2f}".format(float(corr_deg_w_E), float(p_deg_w_E_smash))
  555. #title = "corr = {:.2f} , pvalue = {:.0e}".format(float(corr_deg_w_E), float(p_deg_w_E))
  556. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  557. g.set_axis_labels('Target Energy', 'Degree', fontsize=FONT)
  558. plt.tick_params(axis='both', which='major', labelsize= FONT)
  559. plt.grid(True)
  560. plt.xlabel('Target Energy (CMRglc)', fontsize = FONT)
  561. plt.ylabel('DC', fontsize = FONT)
  562. ax = g.ax_joint
  563. spine_width = 1.6
  564. spine_color = 'gray'
  565. for spine in ax.spines.values():
  566. spine.set_linewidth(spine_width)
  567. spine.set_color(spine_color)
  568. plt.savefig(f'../results/Figures/CMRglc_DC_scatter.png', dpi=300, bbox_inches='tight')
  569. plt.show()
  570. # #--------------------------------------------------------------------------------------------
  571. # #------------------ Box plot individual correlation between IC and E -----------------------
  572. # #--------------------------------------------------------------------------------------------
  573. data = pd.DataFrame({'corr': corr_deg_w_E_allsub, 'pval': p_deg_w_E_allsub})
  574. fig, ax = plt.subplots(figsize=(3, 7))
  575. plt.grid(True)
  576. violin = sns.violinplot(data=data, y='corr', ax=ax, color = COLOR)
  577. violin.collections[0].set_facecolor('none')
  578. sns.stripplot(data=data[data['pval'] < 0.05], y='corr', color=COLOR , size = 8, ax=ax)
  579. sns.stripplot(data=data[data['pval'] >= 0.05], y='corr', color='red' , size = 8, ax=ax)
  580. ax.set_ylabel('Correlation DC and target\'s energy', fontsize = FONT)
  581. ax.set_ylim([-0.1,0.72])
  582. plt.tick_params(axis='both', which='major', labelsize= FONT)
  583. spine_width = 1.6
  584. spine_color = 'gray'
  585. for spine in ax.spines.values():
  586. spine.set_linewidth(spine_width)
  587. spine.set_color(spine_color)
  588. x_position = 0.25
  589. y_position = 0.92
  590. ax.scatter(x_position, y_position, s=80, color='red', transform=ax.transAxes)
  591. ax.text(x_position + 0.08, y_position, 'p > 0.05',
  592. color='gray', fontsize=FONT, va='center', ha='left', transform=ax.transAxes)
  593. plt.savefig(f'../results/Figures/CMRglc_DC_box.png', dpi=300, bbox_inches='tight')
  594. plt.show()
  595. #--------------------------------------------------------------------------------------------
  596. #--------------------------- Degree map on the brain surface -----------------------------------
  597. #--------------------------------------------------------------------------------------------
  598. deg = np.array(DATA_avg_pr.degallsub_w_avg).reshape(-1, 1)
  599. deg_allrois = np.zeros((360,1))
  600. ind = np.arange(360)
  601. mask = np.ones(ind.shape , dtype = bool)
  602. mask[limb_ind] = False
  603. ind = ind[mask]
  604. deg_allrois[ind] = np.abs(deg)
  605. fig = plt.figure(figsize=(5, 5),dpi=300)
  606. fsaverage = datasets.fetch_surf_fsaverage()
  607. V_min = deg.min()
  608. V_max = deg.max()
  609. #V_max = 34
  610. col_fsa = parcel_to_surface(deg_allrois,'glasser_360_fsa5')
  611. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  612. hemi='left', vmin= V_min, vmax = V_max, view='lateral',
  613. bg_map=fsaverage['sulc_left'], bg_on_data=False,
  614. darkness=0.5, cmap=CMAP_DC,colorbar=False)
  615. plt.savefig(f'../results/Figures/DC_surf_l_lateral.png', dpi=300, bbox_inches='tight')
  616. plt.show()
  617. col_fsa = parcel_to_surface(deg_allrois,'glasser_360_fsa5')
  618. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  619. hemi='left', vmin= V_min, vmax = V_max, view='medial',
  620. bg_map=fsaverage['sulc_left'], bg_on_data = False,
  621. darkness=0.5,cmap=CMAP_DC,colorbar=False)
  622. plt.savefig(f'../results/Figures/DC_surf_l_medial.png', dpi=300, bbox_inches='tight')
  623. plt.show()
  624. col_fsa = parcel_to_surface(deg_allrois,'glasser_360_fsa5')
  625. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map = col_fsa[int(col_fsa.shape[0]/2):],
  626. hemi='right', vmin= V_min, vmax = V_max, view='lateral',
  627. bg_map=fsaverage['sulc_right'], bg_on_data=False,
  628. darkness=0.5, cmap=CMAP_DC,colorbar=False)
  629. plt.savefig(f'../results/Figures/DC_surf_r_lateral.png', dpi=300, bbox_inches='tight')
  630. plt.show()
  631. col_fsa = parcel_to_surface(deg_allrois,'glasser_360_fsa5')
  632. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map = col_fsa[int(col_fsa.shape[0]/2):],
  633. hemi='right', vmin= V_min, vmax = V_max, view='medial',
  634. bg_map=fsaverage['sulc_right'], bg_on_data = False,
  635. darkness=0.5,cmap=CMAP_DC,colorbar=False)
  636. plt.savefig(f'../results/Figures/DC_surf_r_medial.png', dpi=300, bbox_inches='tight')
  637. plt.show()
  638. cmap = plt.get_cmap(CMAP_DC)
  639. norm = plt.Normalize(vmin=V_min, vmax=V_max)
  640. fig, ax = plt.subplots(figsize=(6, 1))
  641. fig.subplots_adjust(bottom=0.5)
  642. cb = colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation='horizontal')
  643. cb.ax.tick_params(labelsize=18)
  644. plt.savefig('../results/Figures/DC_colorbar_horizontal.png', dpi=300, bbox_inches='tight')
  645. plt.show()
  646. #--------------------------------------------------------------------------------------------
  647. #---------------------- regions with strongest IC values -----------------------------------
  648. #--------------------------------------------------------------------------------------------
  649. #plot_node_surf(DATA_avg_pr, Pearconn_allsub, 'degallsub_w_avg', CMAP_DC,0.3, limb_ind)
  650. # %% [markdown]
  651. # ## Fig 3a: MwC and DC across networks
  652. # %%
  653. #--------------------------------------------------------------------------------------------
  654. #--------------------------- test across networks ----------------------------------------------
  655. #--------------------------------------------------------------------------------------------
  656. import scipy.stats as stats
  657. from statsmodels.stats.multicomp import pairwise_tukeyhsd
  658. from matplotlib.cbook import boxplot_stats
  659. # Group data by network
  660. groups_ic = [DATA_avg[DATA_avg['yeo_7_nw'] == nw]['ICallsub_w_avg'].dropna() for nw in DATA_avg['yeo_7_nw'].unique()]
  661. groups_dc = [DATA_avg_pr[DATA_avg_pr['yeo_7_nw'] == nw]['degallsub_w_avg'].dropna() for nw in DATA_avg_pr['yeo_7_nw'].unique()]
  662. # Run ANOVA test
  663. anova_mwc_result = stats.f_oneway(*groups_ic)
  664. anova_dc_result = stats.f_oneway(*groups_dc)
  665. print(f"ANOVA for MwC across networks: F = {anova_mwc_result.statistic:.2f}, p = {anova_mwc_result.pvalue:.4f}")
  666. print(f"ANOVA for DC across networks: F = {anova_dc_result.statistic:.2f}, p = {anova_dc_result.pvalue:.4f}")
  667. # Run Tukey's HSD test for MwC
  668. tukey_mwc = pairwise_tukeyhsd(DATA_avg['ICallsub_w_avg'], DATA_avg['yeo_7_nw'])
  669. tukey_df_mwc = pd.DataFrame(data=tukey_mwc._results_table.data[1:], columns=tukey_mwc._results_table.data[0])
  670. sig_results_mwc = tukey_df_mwc[tukey_df_mwc['p-adj'] < 0.05]
  671. # Run Tukey's HSD test for DC
  672. tukey_dc = pairwise_tukeyhsd(DATA_avg_pr['degallsub_w_avg'], DATA_avg_pr['yeo_7_nw'])
  673. tukey_df_dc = pd.DataFrame(data=tukey_dc._results_table.data[1:], columns=tukey_dc._results_table.data[0])
  674. sig_results_dc = tukey_df_dc[tukey_df_dc['p-adj'] < 0.05]
  675. #--------------------------------------------------------------------------------------------
  676. #--------------------------- DC across networks ----------------------------------------------
  677. #--------------------------------------------------------------------------------------------
  678. # Calculate median values for each network
  679. median_values = DATA_avg.groupby('yeo_7_nw')['ICallsub_w_avg'].median()
  680. # Sort networks by the median values
  681. ordered_networks = median_values.sort_values().index
  682. # Generate ordered palettes based on the original colors
  683. ordered_palette = [lighter_color_map[network] for network in ordered_networks]
  684. strip_palette = [network_color_map[network] for network in ordered_networks]
  685. # Plot with the correct colors and sorted order
  686. plt.figure(figsize=(6, 4), dpi=300)
  687. ax = plt.gca()
  688. ax.set_axisbelow(True)
  689. # Violin plot with lighter colors for fills
  690. violin_parts = sns.violinplot(
  691. data=DATA_avg, x='yeo_7_nw', y='ICallsub_w_avg',
  692. inner=None, linewidth=1.5, palette=ordered_palette,
  693. width=0.9, density_norm='width', ax=ax,
  694. order=ordered_networks # Sort the networks based on median values
  695. )
  696. # Adjust violin outlines to use the correct lighter colors
  697. for pc, network in zip(violin_parts.collections, ordered_networks):
  698. mpath = np.array(pc.get_paths()[0].vertices)
  699. mpath[:, 0] = np.clip(mpath[:, 0], np.median(mpath[:, 0]), np.max(mpath[:, 0]))
  700. pc.set_paths([mpath])
  701. pc.set_edgecolor(lighter_color_map[network]) # Use the correct lighter color for outlines
  702. # Strip plot with the correct network colors
  703. strip_plot = sns.stripplot(
  704. data=DATA_avg, x='yeo_7_nw', y='ICallsub_w_avg',
  705. jitter=0.1, marker='o', alpha=0.7,
  706. palette=strip_palette, ax=ax, size=3, order=ordered_networks
  707. )
  708. # Offset points in the strip plot (if required)
  709. for patch in strip_plot.collections:
  710. x_shift = -0.15
  711. patch.set_offsets(np.c_[patch.get_offsets()[:, 0] + x_shift, patch.get_offsets()[:, 1]])
  712. # Box plot with updated order but original style
  713. sns.boxplot(
  714. data=DATA_avg, x='yeo_7_nw', y='ICallsub_w_avg',
  715. width=0.07, fliersize=0, ax=ax,
  716. boxprops={'facecolor': 'none', 'edgecolor': '#595B61', 'linewidth': 1},
  717. whiskerprops={'color': '#595B61', 'linewidth': 1},
  718. capprops={'color': '#595B61', 'linewidth': 1},
  719. medianprops={'color': '#595B61', 'linewidth': 1},
  720. order=ordered_networks
  721. )
  722. xvals = list(ordered_networks)
  723. networks = sorted(DATA_avg['yeo_7_nw'].unique())
  724. networks = sorted(DATA_avg['yeo_7_nw'].unique())
  725. box_top = {}
  726. for net in networks:
  727. vals = DATA_avg.loc[DATA_avg['yeo_7_nw'] == net, 'ICallsub_w_avg']
  728. stats = boxplot_stats(vals, whis=1.5)[0]
  729. whisker = stats["whishi"]
  730. actual_max = vals.max()
  731. # Use whichever is higher
  732. box_top[net] = max(whisker, actual_max)
  733. if net == 'Default':
  734. box_top[net] =box_top[net] + 0.8
  735. star_counts = {net: 0 for net in ordered_networks}
  736. star_offset = 0.8
  737. star_spacing = 0.3
  738. for idx, row in sig_results_mwc.iterrows():
  739. group1 = row['group1']
  740. group2 = row['group2']
  741. p_value = row['p-adj']
  742. star_text = get_star(p_value)
  743. x_coord1 = xvals.index(group1)
  744. y_coord1 = box_top[group1] + star_offset + star_counts[group1] * star_spacing
  745. ax.text(x_coord1, y_coord1, star_text,
  746. ha='center', va='bottom', fontsize=8, color=network_color_map[group2])
  747. star_counts[group1] += 1
  748. x_coord2 = xvals.index(group2)
  749. y_coord2 = box_top[group2] + star_offset + star_counts[group2] * star_spacing
  750. ax.text(x_coord2, y_coord2, star_text,
  751. ha='center', va='bottom', fontsize=8, color=network_color_map[group1])
  752. star_counts[group2] += 1
  753. for spine in ax.spines.values():
  754. spine.set_edgecolor('gray')
  755. plt.grid(True, axis='both', which='major', linestyle='--', linewidth=0.5, color='gray')
  756. ax.set_xticklabels([])
  757. plt.xlabel('')
  758. plt.ylabel('MwC')
  759. plt.ylim([24,39])
  760. plt.tight_layout()
  761. plt.savefig(f'../results/Figures/network_IC_psmash.png', dpi=300, bbox_inches='tight')
  762. plt.show()
  763. #--------------------------------------------------------------------------------------------
  764. #--------------------------- DC across networks ----------------------------------------------
  765. #--------------------------------------------------------------------------------------------
  766. # Calculate median values for each network
  767. median_values = DATA_avg_pr.groupby('yeo_7_nw')['degallsub_w_avg'].median()
  768. # Sort networks by the median values
  769. ordered_networks = median_values.sort_values().index
  770. # Generate ordered palettes based on the original colors
  771. ordered_palette = [lighter_color_map[network] for network in ordered_networks]
  772. strip_palette = [network_color_map[network] for network in ordered_networks]
  773. # Plot with the correct colors and sorted order
  774. plt.figure(figsize=(6, 4), dpi=300)
  775. ax = plt.gca()
  776. # Violin plot with lighter colors for fills
  777. violin_parts = sns.violinplot(
  778. data=DATA_avg_pr, x='yeo_7_nw', y='degallsub_w_avg',
  779. inner=None, linewidth=1.5, palette=ordered_palette,
  780. width=0.9, density_norm='width', ax=ax,
  781. order=ordered_networks # Sort the networks based on median values
  782. )
  783. # Adjust violin outlines to use the correct lighter colors
  784. for pc, network in zip(violin_parts.collections, ordered_networks):
  785. mpath = np.array(pc.get_paths()[0].vertices)
  786. mpath[:, 0] = np.clip(mpath[:, 0], np.median(mpath[:, 0]), np.max(mpath[:, 0]))
  787. pc.set_paths([mpath])
  788. pc.set_edgecolor(lighter_color_map[network]) # Use the correct lighter color for outlines
  789. # Strip plot with the correct network colors
  790. strip_plot = sns.stripplot(
  791. data=DATA_avg_pr, x='yeo_7_nw', y='degallsub_w_avg',
  792. jitter=0.1, marker='o', alpha=0.7,
  793. palette=strip_palette, ax=ax, size=3, order=ordered_networks
  794. )
  795. # Offset points in the strip plot (if required)
  796. for patch in strip_plot.collections:
  797. x_shift = -0.15
  798. patch.set_offsets(np.c_[patch.get_offsets()[:, 0] + x_shift, patch.get_offsets()[:, 1]])
  799. # Box plot with updated order but original style
  800. sns.boxplot(
  801. data=DATA_avg_pr, x='yeo_7_nw', y='degallsub_w_avg',
  802. width=0.07, fliersize=0, ax=ax,
  803. boxprops={'facecolor': 'none', 'edgecolor': '#595B61', 'linewidth': 1},
  804. whiskerprops={'color': '#595B61', 'linewidth': 1},
  805. capprops={'color': '#595B61', 'linewidth': 1},
  806. medianprops={'color': '#595B61', 'linewidth': 1},
  807. order=ordered_networks
  808. )
  809. xvals = list(ordered_networks)
  810. networks = sorted(DATA_avg_pr['yeo_7_nw'].unique())
  811. networks = sorted(DATA_avg_pr['yeo_7_nw'].unique())
  812. box_top = {}
  813. for net in networks:
  814. print(net)
  815. vals = DATA_avg_pr.loc[DATA_avg_pr['yeo_7_nw'] == net, 'degallsub_w_avg']
  816. stats = boxplot_stats(vals, whis=1.5)[0]
  817. whisker = stats["whishi"]
  818. actual_max = vals.max()
  819. # Use whichever is higher
  820. box_top[net] = max(whisker, actual_max) +2
  821. if net == 'Vis':
  822. box_top[net] =box_top[net] + 1
  823. star_counts = {net: 0 for net in ordered_networks}
  824. star_offset = 0.8
  825. star_spacing = 0.3
  826. for idx, row in sig_results_dc.iterrows():
  827. group1 = row['group1']
  828. group2 = row['group2']
  829. p_value = row['p-adj']
  830. star_text = get_star(p_value)
  831. x_coord1 = xvals.index(group1)
  832. y_coord1 = box_top[group1] + star_offset + star_counts[group1] * star_spacing
  833. ax.text(x_coord1, y_coord1, star_text,
  834. ha='center', va='bottom', fontsize= 10, color=network_color_map[group2])
  835. star_counts[group1] += 1
  836. x_coord2 = xvals.index(group2)
  837. y_coord2 = box_top[group2] + star_offset + star_counts[group2] * star_spacing
  838. ax.text(x_coord2, y_coord2, star_text,
  839. ha='center', va='bottom', fontsize=10, color=network_color_map[group1])
  840. star_counts[group2] += 1
  841. for spine in ax.spines.values():
  842. spine.set_edgecolor('gray')
  843. # Final plot adjustments
  844. ax.set_xticklabels([])
  845. plt.grid(True, linestyle='--', linewidth=0.5, color='gray')
  846. plt.xlabel('')
  847. plt.ylabel('DC')
  848. plt.tight_layout()
  849. plt.savefig(f'../results/Figures/network_DC_psmash.png', dpi=300, bbox_inches='tight')
  850. plt.show()
  851. # %% [markdown]
  852. # ## Fig 3b: Diversity
  853. # %%
  854. #--------------------------------------------------------------------------------------------
  855. #--------------------------- MwC diversity ----------------------------------------------
  856. #--------------------------------------------------------------------------------------------
  857. from scipy.stats import spearmanr
  858. thr_sc = 0.1
  859. network_colors = ['#9A199A', '#45B7F0','#58B73B','#DE4B52','#E237FF','#F29A36','#FEFFD3']
  860. Conn_Mat_IC = MIconn_allsub.copy()
  861. Conn_Mat_IC[Conn_Mat_IC < 0.001] = 0
  862. FCmat = Conn_Mat_IC
  863. SCmat = SCconn_allsub.copy()
  864. SCmat_th = np.zeros((SCmat.shape[0], SCmat.shape[1], sub_size))
  865. for i in range(sub_size):
  866. SCmat_th[:, :, i] = threshold_proportional(SCmat[:, :, i], thr_sc)
  867. SC_mask = SCmat_th.copy()
  868. SC_mask[SC_mask > 0] = 1
  869. FCmat_SC = np.multiply(FCmat , SC_mask)
  870. net_assign_allsub_IC = np.zeros((nrois_rem,num_net, sub_size))
  871. for i in range(sub_size):
  872. FC = FCmat_SC[:,:,i]
  873. FC[FC > 0] = 1
  874. #FC[FC < 0] = 1
  875. FC_net = np.multiply(FC, new_net_num)
  876. for r in range(nrois_rem):
  877. for s in range(num_net):
  878. net_assign_allsub_IC[r,s,i] = np.nansum(FC_net[r,:] == s+1)
  879. div_allsub_IC = np.zeros((nrois_rem, sub_size))
  880. for i in range(sub_size):
  881. net_assign = net_assign_allsub_IC[:,:,i]
  882. conn_sum = np.nansum(net_assign, axis=1, keepdims=True)
  883. probabilities = net_assign / conn_sum
  884. div_allsub_IC[:,i] = 1 - np.nansum(probabilities ** 2 , axis = 1)
  885. div_avg_IC = np.nanmean(div_allsub_IC , axis = 1)
  886. #
  887. # --------- finding p-smash --------------------------------------
  888. # ic_array = DATA_avg['ICallsub_w_avg'].to_numpy()
  889. # niter = 1000
  890. # data = pd.DataFrame({"x":div_avg_IC, "y":ic_array})
  891. # test_stat_ic ,surrogate_brainmap_corrs_ic, sa_corrected_p_value_ic, spatially_naive_p_value_ic = Spatial_AC(data , "div", LIMB,niter)
  892. # sac1 = '#0199DD'
  893. # sac2 = '#8CCF83'
  894. # sac3 = '#FEAD01'
  895. # fig, ax = plt.subplots(figsize=(3, 7))
  896. # plt.grid(True)
  897. # g = sns.kdeplot(surrogate_brainmap_corrs_ic, color= "#E0E0E0", ax=ax, fill= True, linewidth=2.5 )
  898. # ax.axvline(test_stat_ic, 0, 0.96, color= COLOR, linestyle='dashed', lw=3)
  899. # ax.set_xticks(np.arange(-1, 1.1, 0.5))
  900. # ax.set_ylim(0, 1.8)
  901. # ax.set_xlim(-0.8, 0.8)
  902. # spine_width = 1.6
  903. # spine_color = 'gray'
  904. # for spine in ax.spines.values():
  905. # spine.set_linewidth(spine_width)
  906. # spine.set_color(spine_color)
  907. # plt.tick_params(axis='both', which='major', labelsize= FONT)
  908. # plt.xlabel('Correlation', fontsize = FONT)
  909. # plt.ylabel('Density', fontsize = FONT)
  910. # plt.show()
  911. # lower_bound = np.percentile(surrogate_brainmap_corrs_ic, 5)
  912. # upper_bound = np.percentile(surrogate_brainmap_corrs_ic, 95)
  913. #print(f"95% CI of null distribution: [{lower_bound:.2f}, {upper_bound:.2f}]")
  914. # ---------------------------------------------------
  915. plt.figure(figsize=(5, 5), dpi = 300)
  916. cor , p = pcor(div_avg_IC , DATA_avg['ICallsub_w_avg'])
  917. p_IC_w_E_smash = p
  918. data = pd.DataFrame({'ent_avg': div_avg_IC, 'ICallsub_w_avg': DATA_avg['ICallsub_w_avg'], 'Network': net_label["yeo_7_nw"]})
  919. grid = sns.FacetGrid(data, hue="Network", palette=network_colors, height=6, aspect=5/4)
  920. grid.map(plt.scatter, 'ent_avg', 'ICallsub_w_avg', alpha=0.9 , s=85)
  921. sns.regplot(data=data, x='ent_avg', y='ICallsub_w_avg', scatter=False, ax=grid.ax, color='gray')
  922. plt.grid(True)
  923. if p_IC_w_E_smash < 0.001:
  924. title = "r = {:.2f} , p < {:.3f}".format(float(cor), float(0.001))
  925. else:
  926. title = "r = {:.2f} , p = {:.2f}".format(float(cor), float(p_IC_w_E_smash))
  927. #plt.title(title , fontsize=FONT)
  928. grid.ax.set_title(title, fontsize=FONT)
  929. plt.xlabel('Simpson Diversity Index', fontsize=FONT)
  930. plt.ylabel('MwC', fontsize=FONT)
  931. plt.tick_params(axis='both', which='major', labelsize=FONT)
  932. for _, spine in grid.ax.spines.items():
  933. spine.set_visible(True)
  934. spine.set_linewidth(1)
  935. spine.set_edgecolor('gray')
  936. plt.savefig(f'../results/Figures/diversity_IC_psmash.png', dpi=300, bbox_inches='tight')
  937. plt.show()
  938. #--------------------------------------------------------------------------------------------
  939. #--------------------------- DC diversity ----------------------------------------------
  940. #--------------------------------------------------------------------------------------------
  941. thr_FC = 0.2
  942. thr_SC = 0.1
  943. Conn_Mat_pr = Pearconn_allsub.copy()
  944. Conn_Mat_pr[Conn_Mat_pr < 0] = 0
  945. Conn_Mat_th = np.zeros((Conn_Mat_pr.shape[0], Conn_Mat_pr.shape[1], sub_size))
  946. for i in range(sub_size):
  947. Conn_Mat_th[:,:,i] = threshold_proportional(Conn_Mat_pr[:, :, i], thr_FC)
  948. SCmat = SCconn_allsub.copy()
  949. SCmat_th = np.zeros((SCmat.shape[0], SCmat.shape[1], sub_size))
  950. for i in range(sub_size):
  951. SCmat_th[:, :, i] = threshold_proportional(SCmat[:, :, i], thr_SC)
  952. SC_mask = SCmat_th.copy()
  953. SC_mask[SC_mask > 0] = 1
  954. FCmat_SC_pr = np.multiply(Conn_Mat_th , SC_mask)
  955. degallsub = np.zeros((nrois_rem, sub_size))
  956. for i in range(sub_size):
  957. dd = FCmat_SC_pr [:,:,i]
  958. degallsub[:,i] = np.nansum(dd, axis=1)
  959. net_assign_allsub_pr = np.zeros((nrois_rem,num_net, sub_size))
  960. for i in range(sub_size):
  961. FC = np.abs(FCmat_SC_pr[:,:,i])
  962. FC[FC > 0] = 1
  963. FC_net = np.multiply(FC, new_net_num)
  964. for r in range(nrois_rem):
  965. for s in range(num_net):
  966. net_assign_allsub_pr[r,s,i] = np.nansum(FC_net[r,:] == s+1)
  967. div_allsub_DC = np.zeros((nrois_rem, sub_size))
  968. for i in range(sub_size):
  969. net_assign = net_assign_allsub_pr[:,:,i]
  970. conn_sum = np.nansum(net_assign, axis=1, keepdims=True)
  971. probabilities = net_assign / conn_sum
  972. div_allsub_DC[:,i] = 1 - np.nansum(probabilities ** 2 , axis = 1)
  973. div_avg_DC = np.nanmean(div_allsub_DC , axis = 1)
  974. # --------- finding p-smash -----------------------------------------
  975. deg_array = DATA_avg_pr['degallsub_w_avg'].to_numpy()
  976. cor , p = pcor(div_avg_DC , deg_array)
  977. # niter = 10
  978. # data = pd.DataFrame({"x":div_avg_DC, "y":deg_array})
  979. # sac1 = '#0199DD'
  980. # sac2 = '#8CCF83'
  981. # sac3 = '#FEAD01'
  982. # fig, ax = plt.subplots(figsize=(3, 7))
  983. # plt.grid(True)
  984. # g = sns.kdeplot(surrogate_brainmap_corrs_dc, color= "#E0E0E0", ax=ax, fill= True, linewidth=2.5 )
  985. # ax.axvline(test_stat_dc, 0, 0.96, color= COLOR, linestyle='dashed', lw=3)
  986. # ax.set_xticks(np.arange(-1, 1.1, 0.5))
  987. # ax.set_ylim(0, 1.8)
  988. # ax.set_xlim(-0.8, 0.8)
  989. # spine_width = 1.6
  990. # spine_color = 'gray'
  991. # for spine in ax.spines.values():
  992. # spine.set_linewidth(spine_width)
  993. # spine.set_color(spine_color)
  994. # plt.tick_params(axis='both', which='major', labelsize= FONT)
  995. # plt.xlabel('Correlation', fontsize = FONT)
  996. # plt.ylabel('Density', fontsize = FONT)
  997. # plt.show()
  998. # lower_bound = np.percentile(surrogate_brainmap_corrs_dc, 5)
  999. # upper_bound = np.percentile(surrogate_brainmap_corrs_dc, 95)
  1000. # print(f"95% CI of null distribution: [{lower_bound:.2f}, {upper_bound:.2f}]")
  1001. # ----------------------------------------------------------------
  1002. plt.figure(figsize=(5, 5), dpi = 300)
  1003. data = pd.DataFrame({'ent_avg': div_avg_DC, 'degallsub_w_avg': deg_array, 'Network': net_label["yeo_7_nw"]})
  1004. grid = sns.FacetGrid(data, hue="Network", palette=network_colors, height=6, aspect=5/4)
  1005. grid.map(plt.scatter, 'ent_avg', 'degallsub_w_avg', alpha=0.9 , s=85)
  1006. sns.regplot(data=data, x='ent_avg', y='degallsub_w_avg', scatter=False, ax=grid.ax, color='gray')
  1007. p_DC_w_E_smash = p
  1008. if p_DC_w_E_smash < 0.001:
  1009. title = "r = {:.2f} , p < {:.3f}".format(float(cor), float(0.001))
  1010. else:
  1011. title = "r = {:.2f} , p = {:.2f}".format(float(cor), float(p_IC_w_E_smash))
  1012. plt.grid(True)
  1013. #plt.title(title, fontsize=FONT)grid.ax.set_title(title, fontsize=FONT)
  1014. grid.ax.set_title(title, fontsize=FONT)
  1015. plt.xlabel('Simpson Diversity Index', fontsize=FONT)
  1016. plt.ylabel('DC', fontsize=FONT)
  1017. plt.tick_params(axis='both', which='major', labelsize=FONT)
  1018. for _, spine in grid.ax.spines.items():
  1019. spine.set_visible(True)
  1020. spine.set_linewidth(1)
  1021. spine.set_edgecolor('gray')
  1022. plt.savefig(f'../results/Figures/diversity_DC_psmash.png', dpi=300, bbox_inches='tight')
  1023. plt.show()
  1024. # %% [markdown]
  1025. # ## Fig 3c: Neurosynth
  1026. # %%
  1027. alltasks_rois = pd.read_csv('../data/external/Neurosynth_roi.csv', header=None)
  1028. alltasks_rois_rem = np.delete(alltasks_rois, limb_ind, axis =0 )
  1029. labels = ['face', 'verbal semantics', 'cued attention', 'working memory','autobiographical memory', 'reading', 'inhibition', 'motor',
  1030. 'visual perception', 'numerical cognition', 'reward', 'visual attention','multisensory', 'visuospatial','eye movements', 'action',
  1031. 'auditory', 'pain', 'language', 'declarative memory','visual semantics', 'emotion', 'cognitive control', 'social cognition']
  1032. base_radius = 0.25
  1033. correlation_values = np.linspace(0, 0.4, 5)
  1034. max_correlation = max(correlation_values)
  1035. #--------------------------------------------------------------------------------------------
  1036. #------------------ Neurosynth and IC map -------------------------------
  1037. #-------------------------------------------------------------------------------------------
  1038. CMAP = 'viridis'
  1039. #data preperation
  1040. data = DATA_avg.ICallsub_w_avg
  1041. IC = np.array((data)).reshape(-1, 1)
  1042. IC_allrois = np.zeros((360,1))
  1043. ind = np.arange(360)
  1044. mask = np.ones(ind.shape , dtype = bool)
  1045. mask[limb_ind] = False
  1046. ind = ind[mask]
  1047. IC_allrois[ind] = (np.abs(IC))
  1048. cor =np.zeros((len(labels)))
  1049. p =np.zeros((len(labels)))
  1050. for i, label in enumerate(labels):
  1051. cor[i],p[i] = pcor(alltasks_rois_rem[:,i],data )
  1052. data = pd.DataFrame({'corr':cor, 'Pval':p, 'task':labels})
  1053. labels = data['task']
  1054. stats = data['corr']
  1055. Pval = data['Pval']
  1056. df = pd.DataFrame({'label': labels, 'corr': stats, 'Pval':Pval})
  1057. df_sorted = df.sort_values('corr', ascending=False).reset_index(drop=True)
  1058. sorted_labels = df_sorted['label'].tolist()
  1059. sorted_stats = df_sorted['corr'].tolist()
  1060. sorted_p = df_sorted['Pval'].tolist()
  1061. V_max = IC.max()
  1062. V_max = 34
  1063. V_min = IC.min()
  1064. fig = plt.figure(figsize=(6, 6))
  1065. ax_brain = fig.add_axes([0.38, 0.38, 0.24, 0.24], projection='3d')
  1066. fsaverage = datasets.fetch_surf_fsaverage()
  1067. col_fsa = parcel_to_surface(IC_allrois,'glasser_360_fsa5')
  1068. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  1069. hemi='left', vmin= V_min, vmax = V_max, view='medial',
  1070. bg_map=fsaverage['sulc_left'], bg_on_data=False,
  1071. darkness=0.5, cmap=CMAP_IC, axes=ax_brain, figure=fig, colorbar=False)
  1072. ax_brain.set_axis_off()
  1073. ax = fig.add_subplot(111, polar=True, label="PolarPlot", frame_on=False)
  1074. # Generate angles for each sector
  1075. angles = np.linspace(0, 2 * np.pi, len(sorted_labels) + 1, endpoint=True).tolist()
  1076. # Compute sector centers by averaging adjacent angles
  1077. sector_centers = [(angles[i] + angles[i + 1]) / 2 for i in range(len(angles) - 1)]
  1078. for angle in angles:
  1079. ax.plot([angle, angle], [base_radius, base_radius + max_correlation + 0.05],
  1080. linestyle='dashed', color='gray', linewidth=0.5)
  1081. # Bar width
  1082. width = (2 * np.pi / len(sorted_labels))
  1083. # Base radius for bars
  1084. base_radius = 0.25
  1085. # Plot bars
  1086. bars = ax.bar(angles[:-1], np.abs(sorted_stats), width=width, bottom=base_radius,
  1087. align='edge', edgecolor='white')
  1088. # Set colors based on correlation values
  1089. for bar, stat, pval in zip(bars, sorted_stats, sorted_p):
  1090. bar.set_facecolor('#F5A614' if (stat > 0 and pval < 0.05) else ('#35B0F7' if (stat < 0 and pval < 0.05) else 'gray'))
  1091. bar.set_alpha(0.9)
  1092. # Correlation ring values
  1093. correlation_values = np.linspace(0, 0.4, 5)
  1094. max_correlation = max(correlation_values)
  1095. for r in correlation_values:
  1096. ax.plot(np.linspace(0, 2 * np.pi, 100), [base_radius + r] * 100, '--', color='gray', linewidth=0.5)
  1097. ax.text(0, base_radius + r , f'{r:.1f}', horizontalalignment='center', verticalalignment='bottom', fontsize = 10)
  1098. # Label placement adjustments
  1099. dash_line_length = base_radius + max_correlation + 0.05
  1100. label_distance = dash_line_length + 0.02
  1101. for angle, label in zip(sector_centers, sorted_labels):
  1102. if label == "autobiographical memory":
  1103. label = "autobiog memory"
  1104. if len(label) > 10:
  1105. label = label.replace(' ', '\n', 1)
  1106. # alignment based on angle
  1107. c = np.cos(angle) # + on right half, – on left half, ~0 at top/bottom
  1108. eps = 0.15 # how wide to treat as “vertical” (tune 0.10–0.20)
  1109. if abs(c) < eps: # near top/bottom → center
  1110. ha = 'center'
  1111. elif c > 0: # right half → left-align outward
  1112. ha = 'left'
  1113. else: # left half → right-align outward
  1114. ha = 'right'
  1115. ax.text(angle, label_distance, label,
  1116. ha=ha, va='center', fontsize=10, color='black', clip_on=False)
  1117. ax.set_xticks([])
  1118. ax.set_yticklabels([])
  1119. ax.grid(False)
  1120. ax.spines['polar'].set_visible(False)
  1121. plt.savefig(f'../results/Figures/neurosynth_IC.png', dpi=300, bbox_inches='tight')
  1122. plt.show()
  1123. #--------------------------------------------------------------------------------------------
  1124. #------------------ Neurosynth and DC map -------------------------------
  1125. #--------------------------------------------------------------------------------------------
  1126. # cool_cmap = cm.get_cmap('cool')
  1127. # cool_colors = cool_cmap(np.linspace(0.15, 0.95, 256))
  1128. # CMAP = LinearSegmentedColormap.from_list("adjusted_cool", cool_colors)
  1129. #data preperation
  1130. data = DATA_avg_pr.degallsub_w_avg
  1131. DC = np.array((data)).reshape(-1, 1)
  1132. DC_allrois = np.zeros((360,1))
  1133. ind = np.arange(360)
  1134. mask = np.ones(ind.shape , dtype = bool)
  1135. mask[limb_ind] = False
  1136. ind = ind[mask]
  1137. DC_allrois[ind] = (np.abs(DC))
  1138. cor =np.zeros((len(labels)))
  1139. p =np.zeros((len(labels)))
  1140. for i, label in enumerate(labels):
  1141. cor[i],p[i] = pcor(alltasks_rois_rem[:,i],data )
  1142. data = pd.DataFrame({'corr':cor, 'Pval':p, 'task':labels})
  1143. labels = data['task']
  1144. stats = data['corr']
  1145. Pval = data['Pval']
  1146. df = pd.DataFrame({'label': labels, 'corr': stats, 'Pval':Pval})
  1147. df_sorted = df.sort_values('corr', ascending=False).reset_index(drop=True)
  1148. sorted_labels = df_sorted['label'].tolist()
  1149. sorted_stats = df_sorted['corr'].tolist()
  1150. sorted_p = df_sorted['Pval'].tolist()
  1151. V_max = DC.max()
  1152. V_min = DC.min()
  1153. fig = plt.figure(figsize=(6, 6))
  1154. ax_brain = fig.add_axes([0.38, 0.38, 0.24, 0.24], projection='3d')
  1155. fsaverage = datasets.fetch_surf_fsaverage()
  1156. col_fsa = parcel_to_surface(DC_allrois,'glasser_360_fsa5')
  1157. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  1158. hemi='left', vmin= V_min, vmax = V_max, view='medial',
  1159. bg_map=fsaverage['sulc_left'], bg_on_data=False,
  1160. darkness=0.5, cmap=CMAP_DC, axes=ax_brain, figure=fig, colorbar=False)
  1161. ax_brain.set_axis_off()
  1162. ax = fig.add_subplot(111, polar=True, label="PolarPlot", frame_on=False)
  1163. # Generate angles for each sector
  1164. angles = np.linspace(0, 2 * np.pi, len(sorted_labels) + 1, endpoint=True).tolist()
  1165. # Compute sector centers by averaging adjacent angles
  1166. sector_centers = [(angles[i] + angles[i + 1]) / 2 for i in range(len(angles) - 1)]
  1167. for angle in angles:
  1168. ax.plot([angle, angle], [base_radius, base_radius + max_correlation + 0.05],
  1169. linestyle='dashed', color='gray', linewidth=0.5)
  1170. # Bar width
  1171. width = (2 * np.pi / len(sorted_labels))
  1172. # Base radius for bars
  1173. # Plot bars
  1174. bars = ax.bar(angles[:-1], np.abs(sorted_stats), width=width, bottom=base_radius,
  1175. align='edge', edgecolor='white')
  1176. # Set colors based on correlation values
  1177. for bar, stat, pval in zip(bars, sorted_stats, sorted_p):
  1178. bar.set_facecolor('#F5A614' if (stat > 0 and pval < 0.05) else ('#35B0F7' if (stat < 0 and pval < 0.05) else 'gray'))
  1179. bar.set_alpha(0.9)
  1180. # Correlation ring values
  1181. correlation_values = np.linspace(0, 0.4, 5)
  1182. max_correlation = max(correlation_values)
  1183. for r in correlation_values:
  1184. ax.plot(np.linspace(0, 2 * np.pi, 100), [base_radius + r] * 100, '--', color='gray', linewidth=0.5)
  1185. ax.text(0, base_radius + r, f'{r:.1f}', horizontalalignment='center', verticalalignment='bottom',
  1186. fontsize=10)
  1187. # Label placement adjustments
  1188. dash_line_length = base_radius + max_correlation + 0.05
  1189. label_distance = dash_line_length + 0.02
  1190. for angle, label in zip(sector_centers, sorted_labels):
  1191. if label == "multisensory":
  1192. label = "multi-\nsensory"
  1193. if label == "autobiographical memory":
  1194. label = "autobiog memory"
  1195. if len(label) > 9:
  1196. label = label.replace(' ', '\n', 1)
  1197. # alignment based on angle
  1198. c = np.cos(angle) # + on right half, – on left half, ~0 at top/bottom
  1199. eps = 0.15 # how wide to treat as “vertical” (tune 0.10–0.20)
  1200. if abs(c) < eps: # near top/bottom → center
  1201. ha = 'center'
  1202. elif c > 0: # right half → left-align outward
  1203. ha = 'left'
  1204. else: # left half → right-align outward
  1205. ha = 'right'
  1206. ax.text(angle, label_distance, label,
  1207. ha=ha, va='center', fontsize=10, color='black', clip_on=False)
  1208. ax.set_xticks([])
  1209. ax.set_yticklabels([])
  1210. ax.grid(False)
  1211. ax.spines['polar'].set_visible(False)
  1212. plt.savefig(f'../results/Figures/neurosynth_DC.png', dpi=300, bbox_inches='tight')
  1213. plt.show()
  1214. # %% [markdown]
  1215. # ## Fig 4a: PLS
  1216. # %%
  1217. genes = pd.read_csv("../data/external/glasser_expression.csv" )
  1218. gene_names = genes.columns[0:]
  1219. CMAP = 'plasma'
  1220. nregs_lh = 167
  1221. limb_ind_l = np.array([88, 90, 92, 93, 110, 118, 120, 122, 131, 135, 165, 166, 172])-1
  1222. gene_exp_l = genes.to_numpy()[:180 , :]
  1223. gene_exp_l = np.delete(gene_exp_l , limb_ind_l , axis = 0)
  1224. rows_with_nan = np.any(np.isnan(gene_exp_l), axis=1)
  1225. rows_with_nan_ind = [i for i, val in enumerate(rows_with_nan) if val]
  1226. allgenes_expression = pd.read_csv("../data/external/glasser_expression.csv" )
  1227. #rows_with_nan_ind = []
  1228. data_avg = DATA_avg
  1229. nregs_lh = 167
  1230. IC_l = np.array(data_avg.ICallsub_w_avg[:nregs_lh])
  1231. IC_l = np.delete(IC_l , rows_with_nan_ind , axis = 0)
  1232. IC_l = np.array(IC_l).reshape(-1, 1)
  1233. SIZE = 50
  1234. #--------------------------------------------------------------------------------------------
  1235. #------------------------ IC map -----------------------------
  1236. #--------------------------------------------------------------------------------------------
  1237. CMAP = 'plasma'
  1238. gene_exp_l = genes.to_numpy()[:180 , :]
  1239. rows_with_nan = np.any(np.isnan(gene_exp_l), axis=1)
  1240. rows_with_nan_ind = [i for i, val in enumerate(rows_with_nan) if val]
  1241. data_allrois = np.zeros((360,1))
  1242. ind = np.arange(360)
  1243. mask = np.ones(ind.shape , dtype = bool)
  1244. mask[180:] = False
  1245. mask[limb_ind_l] = False
  1246. mask[rows_with_nan_ind] = False
  1247. ind = ind[mask]
  1248. IC_l = zscore(IC_l)
  1249. data_allrois[ind] = IC_l
  1250. vmax1 = 2
  1251. vmin1 = -2
  1252. # vmax1 = IC_l.max()
  1253. # vmin1 = IC_l.min()
  1254. col_fsa = parcel_to_surface(data_allrois,'glasser_360_fsa5')
  1255. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  1256. hemi='left', vmin= vmin1, vmax = vmax1, view='lateral',
  1257. bg_map=fsaverage['sulc_left'], bg_on_data=False,
  1258. darkness=0.5, cmap=CMAP,colorbar=False)
  1259. plt.savefig('../results/Figures/IC_l_lateral_GO.png', dpi=300, bbox_inches='tight')
  1260. plt.show()
  1261. col_fsa = parcel_to_surface(data_allrois,'glasser_360_fsa5')
  1262. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  1263. hemi='left', vmin= vmin1, vmax = vmax1, view='medial',
  1264. bg_map=fsaverage['sulc_left'], bg_on_data = False,
  1265. darkness=0.5,cmap=CMAP,colorbar=False)
  1266. plt.savefig('../results/Figures/IC_l_medial_GO.png', dpi=300, bbox_inches='tight')
  1267. plt.show()
  1268. cmap = plt.get_cmap(CMAP)
  1269. norm = plt.Normalize(vmin=vmin1, vmax=vmax1)
  1270. fig, ax = plt.subplots(figsize=(6, 1))
  1271. fig.subplots_adjust(bottom=0.5)
  1272. cb = colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation='horizontal')
  1273. cb.ax.tick_params(labelsize=16)
  1274. plt.savefig('../results/Figures/IC_colorbar_GO.png', dpi=300, bbox_inches='tight')
  1275. plt.show()
  1276. #--------------------------------------------------------------------------------------------
  1277. #------------------------- AHBA genes PLS1 scores -----------------------------------------
  1278. #--------------------------------------------------------------------------------------------
  1279. pls1_score = pd.read_csv('../data/external/PLS1_ROIscores.csv', header=None)
  1280. pls1_score = np.array(pls1_score).reshape(-1, 1)
  1281. pls1_score_allrois = np.zeros((360,1))
  1282. ind = np.arange(360)
  1283. mask = np.ones(ind.shape , dtype = bool)
  1284. mask[180:] = False
  1285. mask[limb_ind_l] = False
  1286. mask[rows_with_nan_ind] = False
  1287. ind = ind[mask]
  1288. pls1_score = zscore(pls1_score)
  1289. pls1_score_allrois[ind] = pls1_score
  1290. # vmax1 = pls1_score.max()
  1291. # vmin1 = pls1_score.min()
  1292. vmax1 = 2
  1293. vmin1 = -2
  1294. fsaverage = datasets.fetch_surf_fsaverage()
  1295. col_fsa = parcel_to_surface(pls1_score_allrois, 'glasser_360_fsa5')
  1296. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map=col_fsa[:int(col_fsa.shape[0]/2)],
  1297. hemi='left', vmin= vmin1, vmax= vmax1, view='lateral',
  1298. bg_map=fsaverage['sulc_right'], bg_on_data= False,
  1299. darkness=0.5, cmap=CMAP, colorbar= False)
  1300. plt.savefig('../results/Figures/pls1_l_lateral_GO.png', dpi=300, bbox_inches='tight')
  1301. plt.show()
  1302. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map=col_fsa[:int(col_fsa.shape[0]/2)],
  1303. hemi='left', vmin= vmin1, vmax= vmax1, view='medial',
  1304. bg_map=fsaverage['sulc_left'], bg_on_data=False,
  1305. darkness=0.5, cmap=CMAP, colorbar= False)
  1306. plt.savefig('../results/Figures/pls1_l_medial_GO.png', dpi=300, bbox_inches='tight')
  1307. plt.show()
  1308. cmap = plt.get_cmap(CMAP)
  1309. norm = plt.Normalize(vmin=vmin1, vmax=vmax1)
  1310. fig, ax = plt.subplots(figsize=(6, 1))
  1311. fig.subplots_adjust(bottom=0.5)
  1312. cb = colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation='horizontal')
  1313. cb.ax.tick_params(labelsize=16)
  1314. plt.savefig('../results/Figures/IC_colorbar_GO.png', dpi=300, bbox_inches='tight')
  1315. plt.show()
  1316. #--------------------------------------------------------------------------------------------
  1317. #------------------------- scatter plot IC and pls1 score ---------------------------------------
  1318. #--------------------------------------------------------------------------------------------
  1319. IC = IC_l.flatten()
  1320. pls1 = pls1_score.flatten()
  1321. corr_IC_w_pls1, p_IC_w_pls1 = pcor(IC, pls1 )
  1322. fig, ax = plt.subplots(figsize=(4, 4))
  1323. sns.regplot(
  1324. x=IC,
  1325. y=pls1,
  1326. scatter_kws={
  1327. 'facecolors': "#E6E6E6",
  1328. 'edgecolor': '#787B76' ,
  1329. 'linewidths': 1,
  1330. 's': 85
  1331. },
  1332. line_kws={
  1333. 'color': '#000000',
  1334. 'lw': 2
  1335. },
  1336. ci=None # This removes the confidence interval
  1337. )
  1338. title = "corr = {:.2f} , p-val = {:.0e}".format(float(corr_IC_w_pls1) , float(p_IC_w_pls1))
  1339. ax.set_title(title , fontdict={'fontsize': FONT})
  1340. plt.xlabel('Group level MwC' , fontsize = FONT)
  1341. plt.ylabel('PLS1 score' , fontsize = FONT)
  1342. plt.grid(True)
  1343. plt.tick_params(axis='both', which='major', labelsize= FONT) # Increase the tick label font size
  1344. ax = plt.gca() # Get the current Axes instance
  1345. # Set the spine linewidth
  1346. spine_width = 1.6 # Change this value to your preferred linewidth
  1347. for spine in ax.spines.values():
  1348. spine.set_linewidth(spine_width)
  1349. plt.savefig('../results/Figures/IC_pls1_GO.png', dpi=300, bbox_inches='tight')
  1350. plt.show()
  1351. # %% [markdown]
  1352. # ## Fig 4b: Gene enrichment
  1353. # %%
  1354. target_strings = ['axon', 'synap', 'example', 'dendritic', 'mito', 'signal' , 'transporter' , 'carbo'] # Add your specific strings here
  1355. FONT = 12
  1356. data = pd.read_csv(f'../data/external/metascape_result_summary.csv', delimiter=';')
  1357. pattern = '|'.join(target_strings)
  1358. data = data[data['Description'].str.contains(pattern, case=False, na=False)]
  1359. data['LogP'] = pd.to_numeric(data['Log10(P)'], errors='coerce')
  1360. data['-Log10(P)'] = -data['Log10(P)']
  1361. data['Description'] = data['Description'].apply(lambda x: x[0].upper() + x[1:] if pd.notnull(x) and len(x) > 0 else x)
  1362. p_values = data['LogP']
  1363. num_genes = data['Count']
  1364. descriptions = data['Description']
  1365. colors = ['#E4191D', '#367EB8', '#4DAF4A','#FFFC32','#F781BF','#999999','#8DD3C7','#FB8072','#D9D9D9'] # Add your desired colors here
  1366. target_strings = ['axon', 'synap', 'example', 'dendritic', 'mito', 'signal' , 'transporter' , 'carbo'] # Add your specific strings here
  1367. DPI = 300
  1368. min_count = data['Count'].min()
  1369. max_count = data['Count'].max()
  1370. sizes = (min_count*2.5, max_count*2.5)
  1371. start = min_count * 2.5
  1372. end = max_count * 2.5
  1373. step_size = (end - start) / 3
  1374. representative_sizes = [start, start + step_size, start + 2 * step_size, end]
  1375. plt.figure(figsize=(5, 6), dpi=DPI)
  1376. ax = plt.gca()
  1377. ax.set_axisbelow(True)
  1378. ax.grid(True)
  1379. g = sns.scatterplot(
  1380. x='-Log10(P)',
  1381. y='Description',
  1382. size='Count',
  1383. hue='Description',
  1384. sizes=(start, end),
  1385. palette=colors,
  1386. alpha=1,
  1387. data=data
  1388. )
  1389. # Remove seaborn’s legend
  1390. g.get_legend().remove()
  1391. # Wrap long descriptions onto multiple lines
  1392. y_labels = [textwrap.fill(desc, 30) for desc in data['Description']]
  1393. plt.yticks(range(len(y_labels)), y_labels, fontsize=FONT, fontweight='bold')
  1394. plt.xlabel('-log10(p)', fontsize=FONT+5)
  1395. plt.ylabel('', fontsize=FONT)
  1396. ax.set_axisbelow(True)
  1397. plt.xlim([0, 40])
  1398. ax = plt.gca()
  1399. for spine in ax.spines.values():
  1400. spine.set_linewidth(1.6)
  1401. # --- Inset legend above the plotting rectangle ----------
  1402. legend_ax = ax.inset_axes([0, 1.03, 1, 0.08], transform=ax.transAxes)
  1403. legend_ax.axis('off')
  1404. legend_ax.set_zorder(10)
  1405. for size in representative_sizes:
  1406. legend_ax.scatter([], [], s=size, color='grey', alpha=0.6,
  1407. label=f'{int(size/2.5)}', zorder=11)
  1408. # Single legend call, centered in the inset, with smaller text
  1409. legend = legend_ax.legend(
  1410. title="Genes",
  1411. loc='center',
  1412. bbox_to_anchor=(0.5, 0.5),
  1413. ncol=len(representative_sizes),
  1414. columnspacing=0.8,
  1415. handletextpad=0.5,
  1416. frameon=False,
  1417. prop={'size': FONT-2}
  1418. )
  1419. legend.set_title("Genes", prop={'size': FONT-2})
  1420. legend._legend_box.align = "center"
  1421. # --- Save and show ----------
  1422. plt.savefig('../results/Figures/Gene_enrichment.png', dpi=300, bbox_inches='tight')
  1423. plt.show()
  1424. # %% [markdown]
  1425. # ## Fig 4c: synaptic density
  1426. # %%
  1427. mmp_in_mni_6 = f'../data/external/mmp_in_mni_6.nii.gz'
  1428. atlas_mni6 = nib.load(mmp_in_mni_6)
  1429. atlas_data_mni6 = atlas_mni6.get_fdata()
  1430. Bmax_mean_mni_img = nib.load('PATH to synaptic density atlas')
  1431. Bmax_mean_mni_data = Bmax_mean_mni_img.get_fdata()
  1432. region_labels = np.unique(atlas_data_mni6)
  1433. region_labels = region_labels[region_labels > 0]
  1434. thr = 0.001
  1435. n_regions = len(region_labels)
  1436. syn_values = np.zeros(n_regions)
  1437. for i, label in enumerate(region_labels):
  1438. region_mask = atlas_data_mni6 == label
  1439. region_vals_syn = Bmax_mean_mni_data[region_mask]
  1440. #syn_values[i] = np.median(region_vals_syn)
  1441. syn_values[i] = np.nanmedian(region_vals_syn[region_vals_syn > thr])
  1442. syn_values = np.delete(syn_values, limb_ind , axis = 0)
  1443. CMAP_IC = 'plasma'
  1444. # IC = np.array(DATA_avg.ICallsub_w_avg).reshape(-1, 1)
  1445. # V_min = 27
  1446. # V_max = 34
  1447. IC = np.array(syn_values).reshape(-1, 1)
  1448. V_min = 450
  1449. V_max = 700
  1450. IC_allrois = np.zeros((360,1))
  1451. ind = np.arange(360)
  1452. mask = np.ones(ind.shape , dtype = bool)
  1453. mask[limb_ind] = False
  1454. ind = ind[mask]
  1455. IC_allrois[ind] = np.abs(IC)
  1456. fig = plt.figure(figsize=(5, 5),dpi=300)
  1457. fsaverage = datasets.fetch_surf_fsaverage()
  1458. col_fsa = parcel_to_surface(IC_allrois,'glasser_360_fsa5')
  1459. col_fsa[col_fsa == 0] = np.nan
  1460. col_fsa = np.where(np.isnan(col_fsa), np.nan, np.clip(col_fsa, V_min, V_max))
  1461. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  1462. hemi='left', vmin= V_min, vmax = V_max, view='lateral',
  1463. bg_map=fsaverage['sulc_left'], bg_on_data=False,
  1464. darkness=0.5, cmap=CMAP_IC,colorbar=False)
  1465. plt.savefig('../results/Figures/synaptic_den_l_lateral.png', dpi=300, bbox_inches='tight')
  1466. plt.show()
  1467. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map = col_fsa[:int(col_fsa.shape[0]/2)],
  1468. hemi='left', vmin= V_min, vmax = V_max, view='medial',
  1469. bg_map=fsaverage['sulc_left'], bg_on_data = False,
  1470. darkness=0.5,cmap=CMAP_IC,colorbar=False)
  1471. plt.savefig('../results/Figures/synaptic_den_l_medial.png', dpi=300, bbox_inches='tight')
  1472. plt.show()
  1473. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map = col_fsa[int(col_fsa.shape[0]/2):],
  1474. hemi='right', vmin= V_min, vmax = V_max, view='lateral',
  1475. bg_map=fsaverage['sulc_right'], bg_on_data=False,
  1476. darkness=0.5, cmap=CMAP_IC,colorbar=False)
  1477. plt.savefig('../results/Figures/synaptic_den_r_lateral.png', dpi=300, bbox_inches='tight')
  1478. plt.show()
  1479. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map = col_fsa[int(col_fsa.shape[0]/2):],
  1480. hemi='right', vmin= V_min, vmax = V_max, view='medial',
  1481. bg_map=fsaverage['sulc_right'], bg_on_data = False,
  1482. darkness=0.5,cmap=CMAP_IC,colorbar=False)
  1483. plt.savefig('../results/Figures/synaptic_den_r_medial.png', dpi=300, bbox_inches='tight')
  1484. plt.show()
  1485. ticks = np.linspace(V_min, V_max, 6)
  1486. norm = plt.Normalize(vmin= V_min, vmax = V_max)
  1487. sm = plt.cm.ScalarMappable(cmap=CMAP, norm=norm)
  1488. sm.set_array([])
  1489. cbar = plt.colorbar(sm, ax=ax, ticks=ticks, orientation='horizontal', pad=0.0001, shrink=0.6)
  1490. cmap = plt.get_cmap(CMAP_IC)
  1491. norm = plt.Normalize(vmin=V_min, vmax=V_max)
  1492. fig, ax = plt.subplots(figsize=(6, 1))
  1493. fig.subplots_adjust(bottom=0.5)
  1494. cb = colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation='horizontal')
  1495. cb.ax.tick_params(labelsize=16)
  1496. plt.savefig('../results/Figures/synaptic_den_colorbar.png', dpi=300, bbox_inches='tight')
  1497. plt.show()
  1498. #==================================================================
  1499. #==================================================================
  1500. ind = []
  1501. ind = syn_values>400
  1502. data = pd.DataFrame({'IC':DATA_avg.ICallsub_w_avg[ind],'syn':syn_values[ind],
  1503. 'pet':DATA_avg.pet_avg[ind], 'deg':DATA_avg.degallsub_w_avg[ind], 'net':net_label['yeo_7_nw'][ind]})
  1504. metric = 'IC'
  1505. r, p = pearsonr(data['syn'], data[metric])
  1506. fig, ax = plt.subplots(figsize=(4,4))
  1507. FONT = 18
  1508. sns.regplot(
  1509. data = data,
  1510. x= 'syn',
  1511. y= 'IC',
  1512. scatter_kws={
  1513. 'facecolors': "#E6E6E6",
  1514. 'edgecolor': '#787B76' ,
  1515. 'linewidths': 1,
  1516. 's': 85
  1517. },
  1518. line_kws={
  1519. 'color': '#000000',
  1520. 'lw': 2
  1521. },
  1522. ci=None # This removes the confidence interval
  1523. )
  1524. title = "r = {:.2f} , p = {:.0e}".format(float(r) , float(p))
  1525. ax.set_title(title , fontdict={'fontsize': FONT})
  1526. plt.xlabel('Synaptic Density' , fontsize = FONT)
  1527. plt.ylabel('MwC' , fontsize = FONT)
  1528. plt.grid(True)
  1529. plt.tick_params(axis='both', which='major', labelsize= FONT) # Increase the tick label font size
  1530. ax = plt.gca() # Get the current Axes instance
  1531. # Set the spine linewidth
  1532. spine_width = 1.6 # Change this value to your preferred linewidth
  1533. for spine in ax.spines.values():
  1534. spine.set_linewidth(spine_width)
  1535. spine.set_edgecolor("gray")
  1536. plt.savefig('../results/Figures/IC_synaptic_den_scatter.png', dpi=300, bbox_inches='tight')
  1537. plt.show()
  1538. # %% [markdown]
  1539. # ## Fig 4d: KEGG and beta amyloid
  1540. # %%
  1541. data = pd.read_csv(f'../data/external/Enrichment_Analysis_Visualizer_data_KEGG_enrichr.csv')
  1542. print(data)
  1543. brain_terms = ['Oxidative phosphorylation','Pathways of neurodegeneration','Huntington disease',
  1544. 'Parkinson disease','Prion disease','Thermogenesis','Alzheimer disease','Amyotrophic lateral sclerosis']
  1545. neurodegen_terms = ['Pathways of neurodegeneration','Huntington disease',
  1546. 'Parkinson disease','Prion disease','Alzheimer disease','Amyotrophic lateral sclerosis']
  1547. subset_data = data.head(10)
  1548. subset_data = subset_data.iloc[::-1].reset_index(drop=True)
  1549. subset_data['NegLog10P'] = -np.log10(subset_data['p-value'])
  1550. plt.figure(figsize=(10, 7), dpi = 300)
  1551. bars = plt.barh(subset_data['term'], subset_data['NegLog10P'], color='#B3E2CD')
  1552. plt.yticks([])
  1553. gray = '#7A7777'
  1554. dark_gray = '#68686A'
  1555. black = 'black'
  1556. for bar, term, value in zip(bars, subset_data['term'], subset_data['p-value']):
  1557. if term in neurodegen_terms:
  1558. bar.set_edgecolor("#2E3834")
  1559. bar.set_linewidth(2) # adjust thickness as you like
  1560. else:
  1561. bar.set_edgecolor("none") # keep others without border
  1562. text_color = black if term in brain_terms else gray
  1563. fontweight = 550 if term in neurodegen_terms else 'normal'
  1564. Font = 21 if term in neurodegen_terms else 17
  1565. plt.text(bar.get_width() - (0.01 * max(subset_data['NegLog10P'])), bar.get_y() + bar.get_height() / 2,
  1566. term, va='center', ha='right', color=text_color, fontsize=Font)
  1567. plt.xlabel('-log10(p-value)' , fontsize = FONT+4)
  1568. plt.xticks(fontsize=FONT+4)
  1569. plt.tight_layout()
  1570. spine_width = 1.6 # Change this value to your preferred linewidth
  1571. for spine in ax.spines.values():
  1572. spine.set_linewidth(spine_width)
  1573. #plt.savefig('../results/Figures/KEGG.png', dpi=300, bbox_inches='tight')
  1574. plt.show()
  1575. #--------------------------------------------------------------------------------------------
  1576. #---------------------- beta-amyloid -----------------------------------
  1577. #--------------------------------------------------------------------------------------------
  1578. limb_ind = np.array([88, 90, 92, 93, 110, 118, 120, 122, 131, 135, 165, 166, 172, 268, 270, 272, 273, 290, 298, 300, 302, 311, 314, 315, 346, 352])
  1579. roi_label = pd.read_csv("../data/external/hcp_mmp10_yeo7_modes.csv", delimiter=";")
  1580. roi_label["ROI_Name"] = (
  1581. roi_label["ROI_Name"]
  1582. .str.replace(r"^R_", "r", regex=True)
  1583. .str.replace(r"^L_", "l", regex=True)
  1584. .str.replace(r"_ROI$", "", regex=True)
  1585. .str.replace("-", ".", regex=False)
  1586. )
  1587. centrality ='MwC' # it can be DC or MCC
  1588. amyloid_status = 'Ab.pos' # it can be Ab.neg, Ab.pos
  1589. DX = 'MCI' #it can be MCI, CN, Dementia
  1590. remove_limbic = True
  1591. tracer = 'amyloid'
  1592. group_name = f"{DX}_{amyloid_status}"
  1593. group_data = pd.read_csv("../data/external/group_amyloid_mmp.csv")
  1594. amyloid = group_data[["ROI", group_name]].rename(columns={"ROI": "label", group_name: "Amyloid"})
  1595. roi = roi_label["ROI_Name"].reset_index(drop=True)
  1596. limb_labels = roi_label.loc[roi_label["ROI_Number"].isin(limb_ind + 1), "ROI_Name"]
  1597. if remove_limbic:
  1598. limb_labels = roi_label.loc[roi_label["ROI_Number"].isin(limb_ind + 1), "ROI_Name"]
  1599. amyloid = amyloid[~amyloid["label"].isin(limb_labels)].reset_index(drop=True)
  1600. roi = roi.drop(limb_ind, errors="ignore").reset_index(drop=True)
  1601. amyloid = amyloid.set_index("label").reindex(roi).reset_index()
  1602. IC = DATA_avg.ICallsub_w_avg if centrality == "MwC" else DATA_avg_pr.degallsub_w_avg
  1603. ad_IC = pd.DataFrame({
  1604. "IC": np.asarray(IC),
  1605. "Amyloid": amyloid["Amyloid"].values,
  1606. "label": roi.values,
  1607. "Network": net_label["yeo_7_nw"].reset_index(drop=True).values
  1608. })
  1609. corr_ic_ad, p_ic_ad = pcor(ad_IC['IC'], ad_IC['Amyloid'])
  1610. print("Correlation coefficient:", corr_ic_ad)
  1611. print("P-value:", p_ic_ad)
  1612. COLOR = "#8DD084"
  1613. plt.figure(figsize=(4,4))
  1614. plt.title = plt.gca().set_title
  1615. ax = sns.regplot(
  1616. x=ad_IC['Amyloid'],
  1617. y=ad_IC['IC'],
  1618. scatter_kws={
  1619. 'facecolors': "#FFFFFF",
  1620. 'edgecolor': '#43B180' ,
  1621. 'linewidths': 2,
  1622. 's': 85
  1623. },
  1624. line_kws={
  1625. 'color': '#000000',
  1626. 'lw': 1
  1627. },
  1628. ci=None # This removes the confidence interval
  1629. )
  1630. plt.title("r = {:.2f} , p-val = {:.0e}".format(float(corr_ic_ad), float(p_ic_ad)), fontsize=FONT)
  1631. #g.fig.suptitle(f"corr = {corr_IC_w_E:.2f}"", $Pval_{smash}$ < 0.0001", fontsize=FONT, va='baseline', y=0.8)
  1632. #g.fig.suptitle(f"corr = {corr_ic_ad:.2f}, Pval ={p_ic_ad:.5f}", fontsize=FONT, va='baseline', y=0.8)
  1633. #g.set_axis_labels('Amyloid', 'MCC', fontsize=FONT)
  1634. plt.tick_params(axis='both', which='major', labelsize= FONT)
  1635. plt.grid(True)
  1636. plt.xlabel(tracer + ' (' + amyloid_status + ', ' + DX + ')', fontsize=FONT)
  1637. plt.rcParams['axes.edgecolor'] = plt.rcParams['grid.color']
  1638. plt.ylabel(centrality, fontsize = FONT)
  1639. plt.savefig('../results/Figures/IC_bamyloid_MCI.png', dpi=300, bbox_inches='tight')
  1640. plt.show()
  1641. # %% [markdown]
  1642. # ## Fig S1: hub details
  1643. # %%
  1644. plt.rcdefaults()
  1645. color_shades1 = ['#00915C','#519470','#748078']
  1646. color_shades2 = ['#E6AC00', '#b29049', '#7b7469']
  1647. color_shades3 = ['#0062F5', '#568FE3', '#8395AD']
  1648. data = pd.read_csv("../data/external/HCP-MMP1_UniqueRegionList.csv")
  1649. coord = data[["x-cog",'y-cog', 'z-cog']]
  1650. coord = coord.drop(limb_ind)
  1651. coord = coord.reset_index(drop = True)
  1652. roi_info = data[['cortex']]
  1653. roi_info= roi_info.drop(limb_ind)
  1654. roi_info = roi_info.reset_index(drop = True)
  1655. roi_label = data[['regionName']]
  1656. roi_label = roi_label.drop(limb_ind)
  1657. roi_label = roi_label.reset_index(drop = True)
  1658. roi_label1 = data[['Lobe']]
  1659. roi_label1 = roi_label1.drop(limb_ind)
  1660. roi_label1 = roi_label1.reset_index(drop = True)
  1661. roi_info["Network"] = net_label["yeo_7_nw"]
  1662. roi_info["Region"] = roi_label['regionName']
  1663. roi_info["Lobe"] = roi_label1['Lobe']
  1664. ICmap = DATA_avg.ICallsub_w_avg
  1665. wdegmap = DATA_avg_pr.degallsub_w_avg
  1666. ICmap = np.array(ICmap).reshape(-1, 1)
  1667. wdegmap = np.array(wdegmap).reshape(-1, 1)
  1668. ind = np.arange(360)
  1669. mask = np.ones(ind.shape, dtype=bool)
  1670. mask[limb_ind] = False
  1671. ind = ind[mask]
  1672. #--------------------------------------------------------------------------------------------
  1673. #---------------------- regions with strongest MwC values -----------------------------------
  1674. #--------------------------------------------------------------------------------------------
  1675. n_shades = 3
  1676. ic_cmap = LinearSegmentedColormap.from_list("ic_shades", color_shades1, N=n_shades)
  1677. #percentiles = [95, 90, 85, 80, 75]
  1678. percentiles = [95, 85, 75]
  1679. data_values = np.linspace(1, 5, len(percentiles))
  1680. data = np.zeros_like(ICmap)
  1681. for i, percentile in enumerate(percentiles):
  1682. threshold = np.percentile(ICmap, percentile)
  1683. mask = (ICmap >= threshold) & (data == 0)
  1684. data[mask] = i + 1
  1685. if percentile == 95:
  1686. data_ic = roi_info.loc[mask,:]
  1687. ind = np.arange(360)
  1688. mask = np.ones(ind.shape, dtype=bool)
  1689. mask[limb_ind] = False
  1690. ind = ind[mask]
  1691. data_allrois = np.zeros((360,1))
  1692. data_allrois[ind] = data
  1693. norm = Normalize(vmin=data_values.min(), vmax=data_values.max())
  1694. fsaverage = datasets.fetch_surf_fsaverage()
  1695. col_fsa = parcel_to_surface(data_allrois, 'glasser_360_fsa5')
  1696. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map=col_fsa[:int(col_fsa.shape[0]/2)],
  1697. hemi='left', view='medial', bg_map=fsaverage['sulc_left'],
  1698. bg_on_data=True, darkness=0.5, cmap=ic_cmap, colorbar = False,
  1699. title='MwC map')
  1700. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map=col_fsa[:int(col_fsa.shape[0]/2)],
  1701. hemi='left', view='lateral', bg_map=fsaverage['sulc_left'],
  1702. bg_on_data=True, darkness=0.5, cmap=ic_cmap, colorbar = False)
  1703. legend_elements = [
  1704. Patch(facecolor=color_shades1[0], label='Top 5%'),
  1705. # Patch(facecolor=color_shades1[1], label='Top 10%'),
  1706. Patch(facecolor=color_shades1[1], label='Top 15%'),
  1707. # Patch(facecolor=color_shades1[3], label='Top 20%'),
  1708. Patch(facecolor=color_shades1[2], label='Top 25%')
  1709. ]
  1710. plt.legend(handles=legend_elements, loc='upper center', bbox_to_anchor=(0.5, -0.05),
  1711. title='Percentile Ranges', ncol=len(legend_elements), frameon=False, fancybox=False, framealpha=0)
  1712. plt.show()
  1713. col_fsa = parcel_to_surface(data_allrois, 'glasser_360_fsa5')
  1714. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map=col_fsa[int(col_fsa.shape[0]/2):],
  1715. hemi='right', view='medial', bg_map=fsaverage['sulc_right'],
  1716. bg_on_data=True, darkness=0.5, cmap=ic_cmap, colorbar = False,
  1717. title='MwC map')
  1718. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map=col_fsa[int(col_fsa.shape[0]/2):],
  1719. hemi='right', view='lateral', bg_map=fsaverage['sulc_right'],
  1720. bg_on_data=True, darkness=0.5, cmap=ic_cmap, colorbar = False)
  1721. legend_elements = [
  1722. Patch(facecolor=color_shades1[0], label='Top 5%'),
  1723. # Patch(facecolor=color_shades1[1], label='Top 10%'),
  1724. Patch(facecolor=color_shades1[1], label='Top 15%'),
  1725. # Patch(facecolor=color_shades1[3], label='Top 20%'),
  1726. Patch(facecolor=color_shades1[2], label='Top 25%')
  1727. ]
  1728. plt.legend(handles=legend_elements, loc='upper center', bbox_to_anchor=(0.5, -0.05),
  1729. title='Percentile Ranges', ncol=len(legend_elements), frameon=False, fancybox=False, framealpha=0)
  1730. plt.show()
  1731. #--------------------------------------------------------------------------------------------
  1732. #---------------------- regions with strongest DC values -------------------------------
  1733. #--------------------------------------------------------------------------------------------
  1734. n_shades = 3
  1735. ic_cmap = LinearSegmentedColormap.from_list("ic_shades", color_shades3, N=n_shades)
  1736. percentiles = [95, 85, 75]
  1737. data_values = np.linspace(1, 5, len(percentiles))
  1738. data = np.zeros_like(wdegmap)
  1739. for i, percentile in enumerate(percentiles):
  1740. threshold = np.percentile(wdegmap, percentile)
  1741. mask = (wdegmap >= threshold) & (data == 0)
  1742. data[mask] = i + 1
  1743. if percentile == 95:
  1744. data_degree = roi_info.loc[mask,:]
  1745. #print( data_degree)
  1746. data_allrois = np.zeros((360,1))
  1747. data_allrois[ind] = data
  1748. norm = Normalize(vmin=data_values.min(), vmax=data_values.max())
  1749. fsaverage = datasets.fetch_surf_fsaverage()
  1750. col_fsa = parcel_to_surface(data_allrois, 'glasser_360_fsa5')
  1751. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map=col_fsa[:int(col_fsa.shape[0]/2)],
  1752. hemi='left', view='medial', bg_map=fsaverage['sulc_left'],
  1753. bg_on_data=True, darkness=0.5, cmap=ic_cmap, colorbar = False,
  1754. title='DC map')
  1755. plotting.plot_surf_roi(fsaverage['infl_left'], roi_map=col_fsa[:int(col_fsa.shape[0]/2)],
  1756. hemi='left', view='lateral', bg_map=fsaverage['sulc_left'],
  1757. bg_on_data=True, darkness=0.5, cmap=ic_cmap, colorbar = False)
  1758. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map=col_fsa[int(col_fsa.shape[0]/2):],
  1759. hemi='right', view='medial', bg_map=fsaverage['sulc_right'],
  1760. bg_on_data=True, darkness=0.5, cmap=ic_cmap, colorbar = False,
  1761. title='DC map')
  1762. plotting.plot_surf_roi(fsaverage['infl_right'], roi_map=col_fsa[int(col_fsa.shape[0]/2):],
  1763. hemi='right', view='lateral', bg_map=fsaverage['sulc_right'],
  1764. bg_on_data=True, darkness=0.5, cmap=ic_cmap, colorbar = False)
  1765. legend_elements = [
  1766. Patch(facecolor=color_shades3[0], label='Top 5%'),
  1767. # Patch(facecolor=color_shades3[1], label='Top 10%'),
  1768. Patch(facecolor=color_shades3[1], label='Top 15%'),
  1769. # Patch(facecolor=color_shades3[3], label='Top 20%'),
  1770. Patch(facecolor=color_shades3[2], label='Top 25%')
  1771. ]
  1772. plt.legend(handles=legend_elements, loc='upper center', bbox_to_anchor=(0.5, 1.05),
  1773. title='Percentile Ranges', ncol=len(legend_elements), frameon=False)
  1774. plt.show()
  1775. data_ic = data_ic.reset_index(drop=True)
  1776. data_degree = data_degree.reset_index(drop=True)
  1777. #df_combined = pd.concat([data_ic, data_cmrglc, data_degree], axis=1)
  1778. df_combined = data_ic
  1779. #df_combined = data_cmrglc
  1780. #df_combined = data_degree.iloc[:,0:3]
  1781. df_combined.replace('Posterior_Cingulate', 'PCC', inplace=True)
  1782. df_combined.replace('Somatosensory_and_Motor', 'SomSen_Mot', inplace=True)
  1783. df_combined.replace('Dorsolateral_Prefrontal', 'DLPFC', inplace=True)
  1784. df_combined.replace('Dorsal_Stream_Visual', 'Dors_Str_Vis', inplace=True)
  1785. def add_padding(text, padding=1):
  1786. return ' ' * padding + text + ' ' * padding
  1787. k = 1
  1788. i = 0
  1789. col1 = ['#00915C','#e4f1e9']
  1790. col2 = ['#E6AC00','#fff4e3']
  1791. col3 = ['#0199DD','#D6F3FF']
  1792. number_of_columns = len(df_combined.columns)
  1793. col_width = 0.5 / number_of_columns # Equal width for all columns, adjust as needed
  1794. col_widths = [col_width] * number_of_columns # List of column widths
  1795. #--------------------------------------------------------------------------------------------
  1796. #---------------------- regions with strongest MwC values -------------------------------
  1797. #--------------------------------------------------------------------------------------------
  1798. df_combined = data_ic
  1799. df_combined.replace('Posterior_Cingulate', 'PCC', inplace=True)
  1800. df_combined.replace('Somatosensory_and_Motor', 'SomSen_Mot', inplace=True)
  1801. df_combined.replace('Dorsolateral_Prefrontal', 'DLPFC', inplace=True)
  1802. df_combined.replace('Dorsal_Stream_Visual', 'Dors_Str_Vis', inplace=True)
  1803. col = col1
  1804. header_colors = [col[i], col[i],col[i],col[i]]#, col2[i], col2[i],col2[i], col3[i], col3[i], col3[i]]
  1805. row_colors = [col[k], col[k], col[k], col[k]]#, col2[k], col2[k], col2[k], col3[k], col3[k], col3[k]]
  1806. fig, ax = plt.subplots(figsize=(7, 8), dpi=300)
  1807. ax.axis('tight')
  1808. ax.axis('off')
  1809. the_table = ax.table(cellText=df_combined.values,
  1810. colLabels=df_combined.columns,
  1811. cellLoc='center',
  1812. loc='center',
  1813. colWidths=col_widths)
  1814. the_table.auto_set_font_size(False)
  1815. the_table.set_fontsize(8)
  1816. for col, header_color in enumerate(header_colors):
  1817. header_cell = the_table[(0, col)]
  1818. header_cell.set_facecolor(header_color)
  1819. header_cell.set_text_props(color='white', weight='bold', size=8)
  1820. header_cell.set_height(0.3)
  1821. for col, row_color in enumerate(row_colors):
  1822. for row in range(1, len(df_combined) + 1):
  1823. body_cell = the_table[(row, col)]
  1824. body_cell.set_facecolor(row_color)
  1825. body_cell.set_text_props(color='black', weight='bold', size=6)
  1826. body_cell.set_height(0.1)
  1827. plt.savefig(f'../results/Figures/IC_hubs_table.png', dpi=300, bbox_inches='tight')
  1828. plt.tight_layout()
  1829. plt.show()
  1830. #--------------------------------------------------------------------------------------------
  1831. #---------------------- regions with strongest Degree values -------------------------------
  1832. #--------------------------------------------------------------------------------------------
  1833. df_combined = data_degree
  1834. df_combined.replace('Posterior_Cingulate', 'PCC', inplace=True)
  1835. df_combined.replace('Somatosensory_and_Motor', 'SomSen_Mot', inplace=True)
  1836. df_combined.replace('Dorsolateral_Prefrontal', 'DLPFC', inplace=True)
  1837. df_combined.replace('Dorsal_Stream_Visual', 'Dors_Str_Vis', inplace=True)
  1838. df_combined.replace('Paracentral_Lobular_and_Mid_Cingulate', 'PCL and MCC', inplace=True)
  1839. df_combined.replace('Inferior_', 'PCL and MCC', inplace=True)
  1840. col = col3
  1841. header_colors = [col[i], col[i],col[i],col[i]]#, col2[i], col2[i],col2[i], col3[i], col3[i], col3[i]]
  1842. row_colors = [col[k], col[k], col[k], col[k]]#, col2[k], col2[k], col2[k], col3[k], col3[k], col3[k]]
  1843. fig, ax = plt.subplots(figsize=(7,8), dpi=300)
  1844. ax.axis('tight')
  1845. ax.axis('off')
  1846. # Create the table with specified column widths
  1847. the_table = ax.table(cellText=df_combined.values,
  1848. colLabels=df_combined.columns,
  1849. cellLoc='center',
  1850. loc='center',
  1851. colWidths=col_widths)
  1852. the_table.auto_set_font_size(False)
  1853. the_table.set_fontsize(8) # Set the font size for all cells
  1854. # Set the background color and text properties for header cells
  1855. for col, header_color in enumerate(header_colors):
  1856. header_cell = the_table[(0, col)]
  1857. header_cell.set_facecolor(header_color)
  1858. header_cell.set_text_props(color='white', weight='bold', size=8)
  1859. header_cell.set_height(0.3) # Visually increase the header cell height
  1860. # Set the background color and text properties for the rest of the cells
  1861. for col, row_color in enumerate(row_colors):
  1862. for row in range(1, len(df_combined) + 1): # Start from 1 to skip the header
  1863. body_cell = the_table[(row, col)]
  1864. body_cell.set_facecolor(row_color)
  1865. body_cell.set_text_props(color='black', weight='bold', size=6)
  1866. body_cell.set_height(0.1) # Set a consistent height for the rest of the cells
  1867. plt.savefig(f'../results/Figures/DC_hubs_table.png', dpi=300, bbox_inches='tight')
  1868. plt.tight_layout()
  1869. plt.show()
  1870. # %% [markdown]
  1871. # ## Fig S2: external data (MwC)
  1872. # %%
  1873. COLOR1 = "#859F81"
  1874. COLOR2 = '#3C9A62'
  1875. session1 = "m1"
  1876. session2 = "m2"
  1877. session3 = "ZU"
  1878. LIMB = 'without'
  1879. data_path = f'../data/processed/'
  1880. with open(os.path.join(data_path,f'matrices_data_{session1}_{LIMB}_limbic.pkl'), 'rb') as file:
  1881. data_input_ex1 = pickle.load(file)
  1882. with open(os.path.join(data_path,f'matrices_data_{session2}_{LIMB}_limbic.pkl'), 'rb') as file:
  1883. data_input_ex2 = pickle.load(file)
  1884. with open(os.path.join(data_path,f'matrices_data_{session3}_{LIMB}_limbic.pkl'), 'rb') as file:
  1885. data_input_ex3 = pickle.load(file)
  1886. edata_medianallsub_ex1 = data_input_ex1['edata_medianallsub']
  1887. edata_medianallsub_ex2 = data_input_ex2['edata_medianallsub']
  1888. edata_medianallsub_ex3 = data_input_ex3['edata_medianallsub']
  1889. sub_size1 = edata_medianallsub_ex1.shape[1]
  1890. sub_size2 = edata_medianallsub_ex2.shape[1]
  1891. sub_size3 = edata_medianallsub_ex3.shape[1]
  1892. DATA_avg_ex1 = pd.read_csv(os.path.join(data_path,f'DATA_avg_woSC_{session1}_{LIMB}_limb.csv'))
  1893. with open(os.path.join(data_path,f'data_single_sub_woSC_{session1}_{LIMB}_limb.pkl'), 'rb') as file:
  1894. data_single_sub_ex1 = pickle.load(file)
  1895. DATA_avg_ex2 = pd.read_csv(os.path.join(data_path,f'DATA_avg_woSC_{session2}_{LIMB}_limb.csv'))
  1896. with open(os.path.join(data_path,f'data_single_sub_woSC_{session2}_{LIMB}_limb.pkl'), 'rb') as file:
  1897. data_single_sub_ex2 = pickle.load(file)
  1898. DATA_avg_ex3 = pd.read_csv(os.path.join(data_path,f'DATA_avg_wSC_{session3}_{LIMB}_limb.csv'))
  1899. with open(os.path.join(data_path,f'data_single_sub_wSC_{session3}_{LIMB}_limb.pkl'), 'rb') as file:
  1900. data_single_sub_ex3 = pickle.load(file)
  1901. ICallsub_w_ex1 = zscore(data_single_sub_ex1['ICallsub_w'], nan_policy='omit')
  1902. ICallsub_w_ex2 = zscore(data_single_sub_ex2['ICallsub_w'], nan_policy='omit')
  1903. ICallsub_w_ex3 = zscore(data_single_sub_ex3['ICallsub_w'], nan_policy='omit')
  1904. #--------------------------------------------------------------------------------------------
  1905. #------------------ SPatial Autocorrelation -----------------------
  1906. #--------------------------------------------------------------------------------------------
  1907. LIMB = 'without'
  1908. niter = 10
  1909. limb_ind = np.array([88, 90, 92, 93, 110, 118, 120, 122, 131, 135, 165, 166, 172, 268, 270, 272, 273, 290, 298, 300, 302, 311, 314, 315, 346, 352])-1
  1910. mode = "IC"
  1911. test_stat_ex1 ,surrogate_brainmap_corrs_ex1,sa_corrected_p_value_ex1,spatially_naive_p_value_ex1 = Spatial_AC(DATA_avg_ex1, mode, LIMB, niter )
  1912. test_stat_ex2 ,surrogate_brainmap_corrs_ex2,sa_corrected_p_value_ex2,spatially_naive_p_value_ex2 = Spatial_AC(DATA_avg_ex2, mode, LIMB, niter )
  1913. test_stat_ex3 ,surrogate_brainmap_corrs_ex3,sa_corrected_p_value_ex3,spatially_naive_p_value_ex3 = Spatial_AC(DATA_avg_ex3, mode, LIMB, niter )
  1914. fig, ax = plt.subplots(figsize=(3, 7))
  1915. plt.grid(True)
  1916. sns.kdeplot(
  1917. surrogate_brainmap_corrs_ex1,
  1918. color=COLOR1,
  1919. fill=False,
  1920. linewidth=2.5,
  1921. alpha=0.7,
  1922. label="Data Ex1",
  1923. ax=ax
  1924. )
  1925. ax.axvline(
  1926. test_stat_ex1,
  1927. ymin=0, ymax=0.96,
  1928. color=COLOR1,
  1929. linestyle='dashed',
  1930. lw=3
  1931. )
  1932. sns.kdeplot(
  1933. surrogate_brainmap_corrs_ex2,
  1934. color=COLOR2,
  1935. fill=False,
  1936. linewidth=2.5,
  1937. alpha=0.7,
  1938. label="Data Ex2",
  1939. ax=ax
  1940. )
  1941. ax.axvline(
  1942. test_stat_ex2,
  1943. ymin=0, ymax=0.96,
  1944. color=COLOR2,
  1945. linestyle='dashed',
  1946. lw=3
  1947. )
  1948. sns.kdeplot(
  1949. surrogate_brainmap_corrs_ex3,
  1950. color=COLOR,
  1951. fill=False,
  1952. linewidth=2.5,
  1953. alpha=0.7,
  1954. label="Data Ex3",
  1955. ax=ax
  1956. )
  1957. ax.axvline(
  1958. test_stat_ex3,
  1959. ymin=0, ymax=0.96,
  1960. color=COLOR,
  1961. linestyle='dashed',
  1962. lw=3
  1963. )
  1964. ax.set_xticks(np.arange(-1, 1.1, 0.5))
  1965. ax.set_xlim(-0.8, 0.8)
  1966. spine_width = 1.6
  1967. spine_color = 'gray'
  1968. for spine in ax.spines.values():
  1969. spine.set_linewidth(spine_width)
  1970. spine.set_color(spine_color)
  1971. plt.tick_params(axis='both', which='major', labelsize=FONT)
  1972. plt.xlabel('Correlation', fontsize=FONT)
  1973. plt.ylabel('Density', fontsize=FONT)
  1974. plt.show()
  1975. data_ex1_z = pd.DataFrame({'pet_avg':DATA_avg_ex1['pet_avg'], 'ICallsub_w_avg':zscore(DATA_avg_ex1['ICallsub_w_avg'], nan_policy='omit'),
  1976. 'degallsub_w_avg':zscore(DATA_avg_ex1['degallsub_w_avg'], nan_policy='omit')})
  1977. data_ex2_z = pd.DataFrame({'pet_avg':DATA_avg_ex2['pet_avg'], 'ICallsub_w_avg':zscore(DATA_avg_ex2['ICallsub_w_avg'], nan_policy='omit'),
  1978. 'degallsub_w_avg':zscore(DATA_avg_ex2['degallsub_w_avg'], nan_policy='omit')})
  1979. data_ex3_z = pd.DataFrame({'pet_avg':DATA_avg_ex3['pet_avg'], 'ICallsub_w_avg':zscore(DATA_avg_ex3['ICallsub_w_avg'], nan_policy='omit'),
  1980. 'degallsub_w_avg':zscore(DATA_avg_ex3['degallsub_w_avg'], nan_policy='omit')})
  1981. corr_IC_w_E_ex1, p_IC_w_E_ex1 = pcor(data_ex1_z.ICallsub_w_avg, data_ex1_z.pet_avg)
  1982. corr_IC_w_deg_ex1, p_IC_w_deg_ex1 = pcor(data_ex1_z.ICallsub_w_avg, data_ex1_z.degallsub_w_avg)
  1983. corr_IC_w_E_ex2, p_IC_w_E_ex2 = pcor(data_ex2_z.ICallsub_w_avg, data_ex2_z.pet_avg)
  1984. corr_IC_w_deg_ex2, p_IC_w_deg_ex2 = pcor(data_ex2_z.ICallsub_w_avg, data_ex2_z.degallsub_w_avg)
  1985. corr_IC_w_E_ex3, p_IC_w_E_ex3 = pcor(data_ex3_z.ICallsub_w_avg, data_ex3_z.pet_avg)
  1986. corr_IC_w_deg_ex3, p_IC_w_deg_ex3 = pcor(data_ex3_z.ICallsub_w_avg, data_ex3_z.degallsub_w_avg)
  1987. corr_IC_E_allsub_ex1 = np.zeros((sub_size1))
  1988. p_IC_E_allsub_ex1 = np.zeros((sub_size1))
  1989. corr_IC_E_allsub_ex2 = np.zeros((sub_size2))
  1990. p_IC_E_allsub_ex2 = np.zeros((sub_size2))
  1991. corr_IC_E_allsub_ex3 = np.zeros((sub_size3))
  1992. p_IC_E_allsub_ex3 = np.zeros((sub_size3))
  1993. for j in range(sub_size1):
  1994. corr_IC_E_allsub_ex1[j], p_IC_E_allsub_ex1[j] = pcor(ICallsub_w_ex1[:, j], edata_medianallsub_ex1[:, j])
  1995. for j in range(sub_size2):
  1996. corr_IC_E_allsub_ex2[j], p_IC_E_allsub_ex2[j] = pcor(ICallsub_w_ex2[:, j], edata_medianallsub_ex2[:, j])
  1997. for j in range(sub_size3):
  1998. corr_IC_E_allsub_ex3[j], p_IC_E_allsub_ex3[j] = pcor(ICallsub_w_ex3[:, j], edata_medianallsub_ex3[:, j])
  1999. #----------------------------------------------------------------------------------------------------
  2000. # scatter IC_avg , CMRglc_avg / group analysis >>> external data Vienna with two sessions (m1 and m2)
  2001. #----------------------------------------------------------------------------------------------------
  2002. g = sns.jointplot(
  2003. data=data_ex1_z, x='pet_avg', y='ICallsub_w_avg', kind="reg",
  2004. scatter_kws={'s': 50, 'alpha': 0.7, 'facecolors': COLOR1, 'edgecolors': COLOR1},
  2005. line_kws={'color': COLOR1, 'lw': 2},
  2006. color=COLOR1, label="session1", marginal_ticks=False
  2007. )
  2008. g.ax_marg_x.clear()
  2009. g.ax_marg_y.clear()
  2010. g.ax_marg_x.tick_params(
  2011. axis='both',
  2012. which='both',
  2013. bottom=False,
  2014. labelbottom=False,
  2015. left=False,
  2016. labelleft=False
  2017. )
  2018. g.ax_marg_y.tick_params(
  2019. axis='both',
  2020. which='both',
  2021. left=False,
  2022. labelleft=False,
  2023. bottom=False,
  2024. labelbottom=False
  2025. )
  2026. sns.regplot(
  2027. data=data_ex2_z, x='pet_avg', y='ICallsub_w_avg',
  2028. scatter_kws={'s': 50, 'alpha': 0.7, 'facecolors': COLOR2, 'edgecolors': COLOR2},
  2029. line_kws={'color': COLOR2, 'lw': 2},
  2030. color=COLOR2, ax=g.ax_joint, label="session2"
  2031. )
  2032. sns.kdeplot(data=data_ex1_z, x='pet_avg', ax=g.ax_marg_x, color=COLOR1, lw=2, label="Session 1", fill=False)
  2033. sns.kdeplot(data=data_ex2_z, x='pet_avg', ax=g.ax_marg_x, color=COLOR2, lw=2, label="Session 2", fill=False)
  2034. sns.kdeplot(data=data_ex1_z, y='ICallsub_w_avg', ax=g.ax_marg_y, color=COLOR1, lw=2, label="Session 1", fill=False)
  2035. sns.kdeplot(data=data_ex2_z, y='ICallsub_w_avg', ax=g.ax_marg_y, color=COLOR2, lw=2, label="Session 2", fill=False)
  2036. g.ax_marg_x.set_ylabel("")
  2037. g.ax_marg_y.set_xlabel("")
  2038. g.ax_joint.set_xlabel('Target Energy (CMRglc)', fontsize=FONT)
  2039. g.ax_joint.set_ylabel('MwC (z-score)', fontsize=FONT)
  2040. g.ax_joint.set_ylim([-3,3])
  2041. p_val1 = sa_corrected_p_value_ex1;
  2042. p_val2 = p_IC_w_E_ex1
  2043. if p_IC_w_E_smash < 0.001:
  2044. title1 = "corr1 = {:.2f} , p-smash < {:.3f}".format(float(corr_IC_w_E_ex1 ), float(0.001))
  2045. else:
  2046. title1 = "corr1 = {:.2f} , p-smash < {:.3f}".format(float(corr_IC_w_E_ex1 ), float(p_val1.item()))
  2047. if p_IC_w_E_smash < 0.001:
  2048. title2 = "corr2 = {:.2f} , p-smash < {:.3f}".format(float(corr_IC_w_E_ex2 ), float(0.001))
  2049. else:
  2050. title2 = "corr2 = {:.2f} , p-smash < {:.3f}".format(float(corr_IC_w_E_ex2 ), float(p_val2.item()))
  2051. g.ax_joint.set_title(
  2052. title1 + "\n"+ title2,
  2053. fontsize=FONT, va='baseline', y=0.85
  2054. )
  2055. plt.grid(True)
  2056. g.ax_joint.tick_params(axis='both', which='major', labelsize=FONT)
  2057. spine_width = 1.6
  2058. for spine in g.ax_joint.spines.values():
  2059. spine.set_linewidth(spine_width)
  2060. g.ax_joint.legend(fontsize=FONT-2, loc="lower right")
  2061. plt.savefig('../results/Figures/ext_IC_CMRglc_wien.png', dpi=300, bbox_inches='tight')
  2062. plt.show()
  2063. #----------------------------------------------------------------------------------------------------
  2064. # scatter IC_avg , CMRglc_avg / group analysis >>> external data TUM: closed eyes(ZU):
  2065. #----------------------------------------------------------------------------------------------------
  2066. plt.figure(figsize=(7,7))
  2067. g = sns.jointplot(data=data_ex3_z, x='pet_avg', y='ICallsub_w_avg', kind="reg", color=COLOR,
  2068. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2069. line_kws={'color': COLOR, 'lw': 1},
  2070. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':IC_color, 'edgecolors':IC_color} )
  2071. g.ax_marg_x.clear()
  2072. g.ax_marg_y.clear()
  2073. g.ax_marg_x.tick_params(
  2074. axis='both',
  2075. which='both',
  2076. bottom=False,
  2077. labelbottom=False,
  2078. left=False,
  2079. labelleft=False
  2080. )
  2081. g.ax_marg_y.tick_params(
  2082. axis='both',
  2083. which='both',
  2084. left=False,
  2085. labelleft=False,
  2086. bottom=False,
  2087. labelbottom=False
  2088. )
  2089. sns.kdeplot(data=data_ex3_z, x='pet_avg', ax=g.ax_marg_x, color=COLOR, lw=2, fill=False)
  2090. sns.kdeplot(data=data_ex3_z, y='ICallsub_w_avg', ax=g.ax_marg_y, color=COLOR, lw=2 ,fill=False)
  2091. title = f"corr = {corr_IC_w_E_ex3:.2f}, p-smash< 0.001"
  2092. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2093. g.set_axis_labels('Target Energy', 'MCC', fontsize=FONT)
  2094. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2095. plt.grid(True)
  2096. plt.xlabel('Target Energy (CMRglc)', fontsize = FONT)
  2097. plt.ylabel('MwC (z-score)', fontsize = FONT)
  2098. plt.ylim([-4,4])
  2099. ax = g.ax_joint
  2100. spine_width = 1.6
  2101. for spine in ax.spines.values():
  2102. spine.set_linewidth(spine_width)
  2103. plt.savefig('../results/Figures/ext_IC_CMRglc_ZU.png', dpi=300, bbox_inches='tight')
  2104. plt.show()
  2105. #--------------------------------------------------------------------------------------------
  2106. # Box plot individual correlation between IC and E >>> external data Vienna with two sessions (m1 and m2)
  2107. #--------------------------------------------------------------------------------------------
  2108. group_colors = [COLOR1, COLOR2]
  2109. data = pd.DataFrame({
  2110. 'corr': np.concatenate([corr_IC_E_allsub_ex1, corr_IC_E_allsub_ex2]),
  2111. 'session': ['session1'] * sub_size1+ ['session2'] * sub_size2,
  2112. 'pval' : np.concatenate([p_IC_E_allsub_ex1, p_IC_E_allsub_ex2])
  2113. })
  2114. fig, ax = plt.subplots(figsize=(3, 6))
  2115. plt.grid(True)
  2116. violin = sns.violinplot(data=data, x = 'session', y='corr', ax=ax, color = COLOR)
  2117. violin.collections[0].set_facecolor('none')
  2118. violin.collections[1].set_facecolor('none')
  2119. sns.stripplot(data=data[data['pval'] < 0.05], x='session', y='corr', hue='session', palette=group_colors, size=8, ax=ax, jitter=True, label="p < 0.05")
  2120. sns.stripplot(data=data[data['pval'] >= 0.05], x='session', y='corr', color='red', size=8, ax=ax, jitter=True, label="p >= 0.05")
  2121. ax.set_ylabel('Correlation MwC and target\'s energy', fontsize = FONT)
  2122. ax.set_ylim([-0.15,0.72])
  2123. plt.tick_params(axis='both', which='major', labelsize= FONT, rotation = 45)
  2124. spine_width = 1.6
  2125. spine_color = 'gray'
  2126. for spine in ax.spines.values():
  2127. spine.set_linewidth(spine_width)
  2128. spine.set_color(spine_color)
  2129. plt.savefig('../results/Figures/ext_box_IC_CMRglc_wien.png', dpi=300, bbox_inches='tight')
  2130. plt.show()
  2131. #--------------------------------------------------------------------------------------------
  2132. # Box plot individual correlation between IC and E >>> external data TUM (closed eyes)
  2133. #--------------------------------------------------------------------------------------------
  2134. data = pd.DataFrame({'corr': corr_IC_E_allsub_ex3, 'pval': p_IC_E_allsub_ex3})
  2135. fig, ax = plt.subplots(figsize=(3, 7))
  2136. plt.grid(True)
  2137. violin = sns.violinplot(data=data, y='corr', ax=ax, color = COLOR)
  2138. violin.collections[0].set_facecolor('none')
  2139. sns.stripplot(data=data[data['pval'] < 0.05], y='corr', color=IC_color , size = 8, ax=ax)
  2140. sns.stripplot(data=data[data['pval'] >= 0.05], y='corr', color='red' , size = 8, ax=ax)
  2141. ax.set_ylabel('Correlation MwC and target\'s energy', fontsize = FONT)
  2142. ax.set_ylim([-0.15,0.72])
  2143. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2144. spine_width = 1.6
  2145. spine_color = 'gray'
  2146. for spine in ax.spines.values():
  2147. spine.set_linewidth(spine_width)
  2148. spine.set_color(spine_color)
  2149. plt.savefig('../results/Figures/ext_box_IC_CMRglc_zu.png', dpi=300, bbox_inches='tight')
  2150. plt.show()
  2151. # %% [markdown]
  2152. # ## Fig S3: participation coefficient
  2153. # %%
  2154. '''
  2155. participation coefficent can be calculated with one of these methods:
  2156. 'infomap', 'louvain', 'walktrap', 'label_prop'
  2157. '''
  2158. PC_COLOR = '#7DA3DA'
  2159. session = "AUF"
  2160. LIMB = "without"
  2161. thr_fc = 0.1
  2162. thr_sc = 0.1
  2163. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_with_limb.csv'
  2164. DATA_avg = pd.read_csv(data_avg_path)
  2165. file_path = f'../data/processed/matrices_data_{session}_with_limbic.pkl'
  2166. with open(file_path, 'rb') as file:
  2167. data_input = pickle.load(file)
  2168. edata_medianallsub = data_input['edata_medianallsub']
  2169. conn_mat = data_input['Pearconn_allsub']
  2170. SCconn_allsub = data_input['SCconn_allsub']
  2171. sub_size = SCconn_allsub.shape[2]
  2172. all_pc = ParticipationCoeff(thr_fc, thr_sc, conn_mat, SCconn_allsub, sub_size)
  2173. pc_allmethods_avg = {method: np.mean(pc_matrix, axis=1) for method, pc_matrix in all_pc.items()}
  2174. data_pc_avg = pd.DataFrame({'pet_avg': DATA_avg.pet_avg, 'PCallsub_w_avg': pc_allmethods_avg[method], 'ICallsub_w_avg': DATA_avg.ICallsub_w_avg})
  2175. ind = data_pc_avg['PCallsub_w_avg']>0
  2176. #data_pc_avg = pd.DataFrame({'pet_avg': DATA_avg.pet_avg, 'PCallsub_w_avg': bg.pc, 'ICallsub_w_avg': DATA_avg.ICallsub_w_avg})
  2177. corr_PC_w_E, p_PC_w_E = pcor(data_pc_avg.PCallsub_w_avg[ind], data_pc_avg.pet_avg[ind])
  2178. #--------------------------------------------------------------------------------------------
  2179. #--------------------------- spatial autocorrelation correction -----------------------
  2180. #--------------------------------------------------------------------------------------------
  2181. N_ROT = 1000
  2182. RNG_SEED = 42
  2183. session = 'AUF'
  2184. LIMB = 'with'
  2185. ind = data_pc_avg['PCallsub_w_avg']>0
  2186. map1 = data_pc_avg.PCallsub_w_avg
  2187. map2 = data_pc_avg.pet_avg
  2188. cmrglc =map1.to_numpy(dtype=float).ravel()
  2189. ic = map2.to_numpy(dtype=float).ravel()
  2190. #rho_ic, p_spin_ic, null_ic = run_spin_test(ic, cmrglc, N_ROT,RNG_SEED)
  2191. # print(p_spin_ic)
  2192. FONT = 22
  2193. COLOR = IC_color
  2194. null_r = np.asarray(null_ic, dtype=float)
  2195. null_r = null_r[np.isfinite(null_r)]
  2196. fig, ax = plt.subplots(figsize=(3, 7))
  2197. plt.grid(True)
  2198. sns.kdeplot(
  2199. null_r,
  2200. color="#E0E0E0",
  2201. ax=ax,
  2202. fill=True,
  2203. linewidth=2.5
  2204. )
  2205. ax.axvline(rho_ic, 0, 0.9, color='#9CB9E8', linestyle='dashed', lw=3)
  2206. ax.set_xticks(np.arange(-1, 1.1, 0.5))
  2207. ax.set_ylim(0, 5)
  2208. ax.set_xlim(-0.8, 0.8)
  2209. spine_width = 1.6
  2210. spine_color = 'gray'
  2211. for spine in ax.spines.values():
  2212. spine.set_linewidth(spine_width)
  2213. spine.set_color(spine_color)
  2214. plt.tick_params(axis='both', which='major', labelsize=FONT)
  2215. plt.xlabel('Correlation', fontsize=FONT)
  2216. plt.ylabel('Density', fontsize=FONT)
  2217. plt.show()
  2218. lower_bound = np.percentile(null_r, 5)
  2219. upper_bound = np.percentile(null_r, 95)
  2220. print(f"90% CI of null distribution: [{lower_bound:.2f}, {upper_bound:.2f}]")
  2221. #--------------------------------------------------------------------------------------------
  2222. #--------------------------- group level: scatter plot CMRglc and PC -----------------------------------
  2223. #--------------------------------------------------------------------------------------------
  2224. plt.figure(figsize=(6,4))
  2225. g = sns.jointplot(data=data_pc_avg, x='pet_avg', y='PCallsub_w_avg', kind="reg", color=PC_COLOR,
  2226. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2227. line_kws={'color': 'black', 'lw': 1},
  2228. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':PC_COLOR, 'edgecolors':PC_COLOR} )
  2229. p_PC_w_E_smash = p_spin_ic
  2230. if p_PC_w_E_smash < 0.001:
  2231. title = "corr = {:.2f} , psmash< {:.0e}".format(float(corr_PC_w_E), float(0.001))
  2232. else:
  2233. title = "corr = {:.2f} , p-val = {:.0e}".format(float(corr_PC_w_E), float(p_PC_w_E_smash))
  2234. #g.fig.suptitle(f"corr = {corr_IC_w_E:.2f}"", $Pval_{smash}$ < 0.001", fontsize=FONT, va='baseline', y=0.8)
  2235. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2236. g.set_axis_labels('Target Energy', 'PC', fontsize=FONT)
  2237. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2238. plt.grid(True)
  2239. plt.xlabel('Target Energy (CMRglc)', fontsize = FONT)
  2240. plt.ylabel('PC', fontsize = FONT)
  2241. ax = g.ax_joint
  2242. spine_width = 1.6
  2243. for spine in ax.spines.values():
  2244. spine.set_linewidth(spine_width)
  2245. plt.show()
  2246. #--------------------------------------------------------------------------------------------
  2247. #--------------------------- subject level: box plot CMRglc and PC -----------------------------------
  2248. #--------------------------------------------------------------------------------------------
  2249. corr_PC_E_allsub = np.zeros((sub_size))
  2250. p_PC_E_allsub = np.zeros((sub_size))
  2251. for j in range(sub_size):
  2252. corr_PC_E_allsub[j], p_PC_E_allsub[j] = pcor(all_pc[method][:, j], edata_medianallsub[:, j])
  2253. data = pd.DataFrame({'corr': corr_PC_E_allsub, 'pval': p_PC_E_allsub})
  2254. fig, ax = plt.subplots(figsize=(3, 7))
  2255. plt.grid(True)
  2256. violin = sns.violinplot(data=data, y='corr', ax=ax, color = PC_COLOR)
  2257. violin.collections[0].set_facecolor('none')
  2258. sns.stripplot(data=data[data['pval'] < 0.05], y='corr', color=PC_COLOR , size = 8, ax=ax)
  2259. sns.stripplot(data=data[data['pval'] >= 0.05], y='corr', color='red' , size = 8, ax=ax)
  2260. ax.set_ylabel('Correlation PC and target\'s energy', fontsize = FONT)
  2261. ax.set_ylim([-0.15,0.72])
  2262. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2263. spine_width = 1.6
  2264. spine_color = 'gray'
  2265. for spine in ax.spines.values():
  2266. spine.set_linewidth(spine_width)
  2267. spine.set_color(spine_color)
  2268. plt.show()
  2269. #--------------------------------------------------------------------------------------------
  2270. #--------------------------- PC map on the brain surface -----------------------------------
  2271. #--------------------------------------------------------------------------------------------
  2272. #plot_node_surf(data_pc_avg, Pearconn_allsub, 'PCallsub_w_avg', CMAP_DC,0.35, [])
  2273. PC = np.array(data_pc_avg.PCallsub_w_avg).reshape(-1, 1)
  2274. PC_allrois = np.full((360, 1), np.nan)
  2275. ind = np.arange(360)
  2276. mask = np.ones(ind.shape , dtype = bool)
  2277. #mask[limb_ind] = False
  2278. ind = ind[mask]
  2279. PC_allrois[ind] = np.abs(PC)
  2280. fig = plt.figure(figsize=(5, 5),dpi=300)
  2281. fsaverage = datasets.fetch_surf_fsaverage()
  2282. V_min = 0
  2283. V_max = PC.max()
  2284. #V_max = 34
  2285. ticks = [V_min, 0.1, V_max]
  2286. col_fsa = parcel_to_surface(PC_allrois,'glasser_360_fsa5')
  2287. plotting.plot_surf_stat_map( fsaverage['infl_left'], stat_map = col_fsa[:int(col_fsa.shape[0]/2)],
  2288. title='PC, left hemisphere',
  2289. hemi='left', vmin= V_min, vmax = V_max, view='lateral',
  2290. bg_map=fsaverage['sulc_left'], bg_on_data=False,
  2291. cmap=CMAP_DC,colorbar=False)
  2292. plt.show()
  2293. col_fsa = parcel_to_surface(PC_allrois,'glasser_360_fsa5')
  2294. plotting.plot_surf_stat_map(fsaverage['infl_left'], stat_map = col_fsa[:int(col_fsa.shape[0]/2)],
  2295. title='PC, left hemisphere',
  2296. hemi='left', vmin= V_min, vmax = V_max, view='medial',
  2297. bg_map=fsaverage['sulc_left'], bg_on_data = False,
  2298. cmap=CMAP_DC,colorbar=False)
  2299. plt.show()
  2300. col_fsa = parcel_to_surface(PC_allrois,'glasser_360_fsa5')
  2301. plotting.plot_surf_stat_map(fsaverage['infl_right'], stat_map = col_fsa[int(col_fsa.shape[0]/2):],
  2302. title='PC, right hemisphere',
  2303. hemi='right', vmin= V_min, vmax = V_max, view='lateral',
  2304. bg_map=fsaverage['sulc_right'], bg_on_data=False,
  2305. cmap=CMAP_DC,colorbar=False)
  2306. plt.show()
  2307. col_fsa = parcel_to_surface(PC_allrois,'glasser_360_fsa5')
  2308. plotting.plot_surf_stat_map(fsaverage['infl_right'], stat_map = col_fsa[int(col_fsa.shape[0]/2):],
  2309. title='PC, right hemisphere',
  2310. hemi='right', vmin= V_min, vmax = V_max, view='medial',
  2311. bg_map=fsaverage['sulc_right'], bg_on_data = False,
  2312. cmap=CMAP_DC,colorbar=True)
  2313. plt.show()
  2314. norm = mpl.colors.Normalize(vmin=V_min, vmax=V_max)
  2315. sm = mpl.cm.ScalarMappable(cmap=CMAP_DC, norm=norm)
  2316. sm.set_array([])
  2317. fig, ax = plt.subplots(figsize=(6, 1))
  2318. cbar = plt.colorbar(
  2319. sm,
  2320. cax = ax,
  2321. orientation = 'horizontal',
  2322. ticks = ticks,
  2323. format = "%.2f"
  2324. )
  2325. cbar.set_label("Participation Coefficient", fontsize=10)
  2326. plt.tight_layout()
  2327. plt.show()
  2328. # %% [markdown]
  2329. # ## Fig S4: MwC vs CMRglc for combined datasets
  2330. # %%
  2331. #--------------------------------------------------------------------------------------------
  2332. #------------------ read all sessions data -------------------------------
  2333. #-------------------------------------------------------------------------------------------
  2334. session = 'AUF'
  2335. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  2336. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  2337. data_sub_path = f'../data/processed/data_single_sub_wSC_{session}_{LIMB}_limb.pkl'
  2338. data_avg_pr_path = f'../data/processed/DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv'
  2339. data_sub_pr_path = f'../data/processed/data_single_sub_wSC_pr_{session}_{LIMB}_limb.pkl'
  2340. with open(file_path, 'rb') as file:
  2341. data_input_auf = pickle.load(file)
  2342. DATA_avg_auf = pd.read_csv(data_avg_path)
  2343. with open(data_sub_path, 'rb') as file:
  2344. data_single_sub_auf = pickle.load(file)
  2345. DATA_avg_pr_auf = pd.read_csv(data_avg_pr_path)
  2346. with open(data_sub_pr_path, 'rb') as file:
  2347. data_single_sub_pr_auf = pickle.load(file)
  2348. session = 'ZU'
  2349. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  2350. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  2351. data_sub_path = f'../data/processed/data_single_sub_wSC_{session}_{LIMB}_limb.pkl'
  2352. data_avg_pr_path = f'../data/processed/DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv'
  2353. data_sub_pr_path = f'../data/processed/data_single_sub_wSC_pr_{session}_{LIMB}_limb.pkl'
  2354. with open(file_path, 'rb') as file:
  2355. data_input_zu = pickle.load(file)
  2356. DATA_avg_zu = pd.read_csv(data_avg_path)
  2357. with open(data_sub_path, 'rb') as file:
  2358. data_single_sub_zu = pickle.load(file)
  2359. DATA_avg_pr_zu = pd.read_csv(data_avg_pr_path)
  2360. with open(data_sub_pr_path, 'rb') as file:
  2361. data_single_sub_pr_zu = pickle.load(file)
  2362. session = 'm1'
  2363. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  2364. data_avg_path = f'../data/processed/DATA_avg_woSC_{session}_{LIMB}_limb.csv'
  2365. data_sub_path = f'../data/processed/data_single_sub_woSC_{session}_{LIMB}_limb.pkl'
  2366. data_avg_pr_path = f'../data/processed/DATA_avg_woSC_pr_{session}_{LIMB}_limb.csv'
  2367. data_sub_pr_path = f'../data/processed/data_single_sub_woSC_pr_{session}_{LIMB}_limb.pkl'
  2368. with open(file_path, 'rb') as file:
  2369. data_input_m1 = pickle.load(file)
  2370. DATA_avg_m1 = pd.read_csv(data_avg_path)
  2371. with open(data_sub_path, 'rb') as file:
  2372. data_single_sub_m1 = pickle.load(file)
  2373. DATA_avg_pr_m1 = pd.read_csv(data_avg_pr_path)
  2374. with open(data_sub_pr_path, 'rb') as file:
  2375. data_single_sub_pr_m1 = pickle.load(file)
  2376. session = 'm2'
  2377. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  2378. data_avg_path = f'../data/processed/DATA_avg_woSC_{session}_{LIMB}_limb.csv'
  2379. data_sub_path = f'../data/processed/data_single_sub_woSC_{session}_{LIMB}_limb.pkl'
  2380. data_avg_pr_path = f'../data/processed/DATA_avg_woSC_pr_{session}_{LIMB}_limb.csv'
  2381. data_sub_pr_path = f'../data/processed/data_single_sub_woSC_pr_{session}_{LIMB}_limb.pkl'
  2382. with open(file_path, 'rb') as file:
  2383. data_input_m2 = pickle.load(file)
  2384. DATA_avg_m2 = pd.read_csv(data_avg_path)
  2385. with open(data_sub_path, 'rb') as file:
  2386. data_single_sub_m2 = pickle.load(file)
  2387. DATA_avg_pr_m2 = pd.read_csv(data_avg_pr_path)
  2388. with open(data_sub_pr_path, 'rb') as file:
  2389. data_single_sub_pr_m2 = pickle.load(file)
  2390. #--------------------------------------------------------------------------------------------
  2391. #------------------ concatenated all sessions data -------------------------------
  2392. #-------------------------------------------------------------------------------------------
  2393. df1 = zscore(data_single_sub_auf['ICallsub_w'], nan_policy='omit')
  2394. df2 = zscore(data_single_sub_zu['ICallsub_w'], nan_policy='omit')
  2395. df3 = zscore(data_single_sub_m1['ICallsub_w'], nan_policy='omit')
  2396. df4 = zscore(data_single_sub_m2['ICallsub_w'], nan_policy='omit')
  2397. ICallsub_allsessions = np.hstack((df1, df2, df3, df4))
  2398. #ICallsub_allsessions = df3
  2399. ICallsub_allsessions = pd.DataFrame(ICallsub_allsessions)
  2400. df1 = zscore(data_single_sub_pr_auf['degallsub_w'], nan_policy='omit')
  2401. df2 = zscore(data_single_sub_pr_zu['degallsub_w'], nan_policy='omit')
  2402. df3 = zscore(data_single_sub_pr_m1['degallsub_w'], nan_policy='omit')
  2403. df4 = zscore(data_single_sub_pr_m2['degallsub_w'], nan_policy='omit')
  2404. degallsub_allsessions = np.hstack((df1, df2, df3, df4))
  2405. #degallsub_allsessions = df3
  2406. degallsub_allsessions = pd.DataFrame(degallsub_allsessions)
  2407. df1 = zscore(data_input_auf['edata_medianallsub'], nan_policy='omit')
  2408. df2 = zscore(data_input_zu['edata_medianallsub'], nan_policy='omit')
  2409. df3 = zscore(data_input_m1['edata_medianallsub'], nan_policy='omit')
  2410. df4 = zscore(data_input_m2['edata_medianallsub'], nan_policy='omit')
  2411. edata_allsub_allsessions = np.hstack((df1, df2, df3, df4))
  2412. #edata_allsub_allsessions = df3
  2413. edata_allsub_allsessions = pd.DataFrame(edata_allsub_allsessions)
  2414. ICallsub_allsessions_avg = np.nanmean(ICallsub_allsessions, axis = 1)
  2415. degallsub_allsessions_avg = np.nanmean(degallsub_allsessions, axis = 1)
  2416. edata_allsub_allsessions_avg = np.nanmean(edata_allsub_allsessions, axis = 1)
  2417. #--------------------------------------------------------------------------------------------
  2418. #------------------ concatenated all sessions data -------------------------------
  2419. #-------------------------------------------------------------------------------------------
  2420. IC = ICallsub_allsessions_avg
  2421. DC = degallsub_allsessions_avg
  2422. CMRglc = edata_allsub_allsessions_avg
  2423. IC = np.array(IC).flatten()
  2424. DC = np.array(DC).flatten()
  2425. CMRglc = np.array(CMRglc).flatten()
  2426. alldata_avg = pd.DataFrame({'IC':IC, 'DC':DC, 'pet':CMRglc})
  2427. r_IC_CMRglc,p_IC_CMRglc = pcor(IC,CMRglc)
  2428. print(r_IC_CMRglc )
  2429. r_DC_CMRglc , p_DC_CMRglc= pcor(DC,CMRglc)
  2430. print(r_DC_CMRglc)
  2431. r_IC_DC , p_IC_DC = pcor(IC,DC)
  2432. print(r_IC_DC)
  2433. #--------------------------------------------------------------------------------------------
  2434. #------------------ scatter IC_avg , CMRglc_avg / group analysis ----------------------------
  2435. #--------------------------------------------------------------------------------------------
  2436. COLOR = IC_color
  2437. plt.figure(figsize=(6,4))
  2438. g = sns.jointplot(data=alldata_avg, x='pet', y='IC', kind="reg", color=COLOR,
  2439. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2440. line_kws={'color': 'black', 'lw': 1},
  2441. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  2442. title = "corr = {:.2f} , p-val = {:.0e}".format(float(r_IC_CMRglc), float(p_IC_CMRglc,))
  2443. #g.fig.suptitle(f"corr = {corr_IC_w_E:.2f}"", $Pval_{smash}$ < 0.001", fontsize=FONT, va='baseline', y=0.8)
  2444. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2445. g.set_axis_labels('Target Energy', 'MCC', fontsize=FONT)
  2446. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2447. plt.grid(True)
  2448. plt.xlabel('Target Energy (CMRglc)', fontsize = FONT)
  2449. plt.ylabel('MwC', fontsize = FONT)
  2450. ax = g.ax_joint
  2451. spine_width = 1.6
  2452. for spine in ax.spines.values():
  2453. spine.set_linewidth(spine_width)
  2454. plt.savefig('../results/Figures/all_scatter_IC_CMRglc_.png', dpi=300, bbox_inches='tight')
  2455. plt.show()
  2456. #--------------------------------------------------------------------------------------------
  2457. #------------------ Box plot individual correlation between IC and E -----------------------
  2458. #--------------------------------------------------------------------------------------------
  2459. sub_size = np.size(edata_allsub_allsessions, axis =1)
  2460. corr_IC_E_allsub = np.zeros((sub_size))
  2461. p_IC_E_allsub = np.zeros((sub_size))
  2462. for j in range(sub_size):
  2463. corr_IC_E_allsub[j], p_IC_E_allsub[j] = pcor(edata_allsub_allsessions.iloc[:,j], ICallsub_allsessions.iloc[:,j])
  2464. data = pd.DataFrame({'corr': corr_IC_E_allsub, 'pval': p_IC_E_allsub})
  2465. fig, ax = plt.subplots(figsize=(3, 7))
  2466. plt.grid(True)
  2467. violin = sns.violinplot(data=data, y='corr', ax=ax, color = COLOR)
  2468. violin.collections[0].set_facecolor('none')
  2469. sns.stripplot(data=data[data['pval'] < 0.05], y='corr', color=COLOR , size = 8, ax=ax)
  2470. sns.stripplot(data=data[data['pval'] >= 0.05], y='corr', color='red' , size = 8, ax=ax)
  2471. ax.set_ylabel('Correlation MwC and target\'s energy', fontsize = FONT)
  2472. ax.set_ylim([-0.15,0.72])
  2473. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2474. spine_width = 1.6
  2475. spine_color = 'gray'
  2476. for spine in ax.spines.values():
  2477. spine.set_linewidth(spine_width)
  2478. spine.set_color(spine_color)
  2479. plt.savefig('../results/Figures/all_box_IC_CMRglc_.png', dpi=300, bbox_inches='tight')
  2480. plt.show()
  2481. # %% [markdown]
  2482. # ## Fig S5-a: control analysis
  2483. # %%
  2484. #--------------------------------------------------------------------------------------------
  2485. #---- same weights for one target (keep the number of connection same as the real data)------
  2486. #--------------------------------------------------------------------------------------------
  2487. SCmat = SCconn_allsub
  2488. thr_sc = 0.2
  2489. SCmat_th = np.zeros((SCmat.shape[0], SCmat.shape[1], sub_size))
  2490. for i in range(sub_size):
  2491. SCmat_th[:, :, i] = threshold_proportional(SCmat[:, :, i], thr_sc)
  2492. SC_mask = SCmat_th.copy()
  2493. SC_mask[SC_mask > 0] = 1
  2494. Conn_Mat = SC_mask
  2495. # data_avg_sur2, data_single_sub_sur2 = IC_calculation(Conn_Mat, edata_medianallsub_rem, SCconn_allsub, thr_sc, thr_FC, sub_size, scmask, nrois_rem,net_label)
  2496. # DATA_avg_sur2 = pd.concat([data_avg_sur2 , net_label], axis =1)
  2497. corr_IC_E_allsub = np.zeros((sub_size))
  2498. p_IC_E_allsub = np.zeros((sub_size))
  2499. for j in range(sub_size):
  2500. corr_IC_E_allsub[j], p_IC_E_allsub[j] = pcor(data_single_sub_sur2["ICallsub_w"][:, j], edata_medianallsub_rem[:, j])
  2501. organg = [255/255,164/255,0/255]
  2502. corr_IC_w_E, p_IC_w_E = pcor(DATA_avg_sur2.ICallsub_w_avg, DATA_avg_sur2.pet_avg)
  2503. corr_IC_w_deg, p_IC_w_deg = pcor(DATA_avg_sur2.ICallsub_w_avg, DATA_avg_sur2.degallsub_w_avg)
  2504. g = sns.jointplot(data = DATA_avg_sur2 , x = 'pet_avg' , y ='ICallsub_w_avg' , kind="reg", color="#C83D64",
  2505. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2506. line_kws={'color': 'black', 'lw': 1},
  2507. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':"#E6E6E6", 'edgecolors':"#787B76"} )
  2508. title = "corr = {:.2f} , p-val = {:.0e}".format(float(corr_IC_w_E) , float(p_IC_w_E ))
  2509. g.fig.suptitle(f"corr = {corr_IC_w_E:.2f} , p-val = {p_IC_w_E :.0e}", fontsize=FONT, va='baseline', y=0.8)
  2510. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2511. plt.xlabel('Energy of target', fontsize = FONT)
  2512. plt.ylabel('MwC (CMRglc-only)', fontsize = FONT)
  2513. plt.grid(True)
  2514. ax = g.ax_joint
  2515. spine_width = 1.6
  2516. for spine in ax.spines.values():
  2517. spine.set_linewidth(spine_width)
  2518. plt.savefig('../results/Figures/control_scatter_CMRglc_only.png', dpi=300, bbox_inches='tight')
  2519. plt.show()
  2520. #------------------ Box plot individual correlation between IC and E -----------------------
  2521. print(p_IC_E_allsub)
  2522. data = pd.DataFrame({'corr': corr_IC_E_allsub, 'pval': p_IC_E_allsub})
  2523. fig, ax = plt.subplots(figsize=(3, 6))
  2524. plt.grid(True)
  2525. violin = sns.violinplot(data=data, y='corr', ax=ax, color = '#FBE5CF')
  2526. sns.stripplot(data=data[data['pval'] < 0.05], y='corr', color='#787B76' , size = 8, ax=ax)
  2527. sns.stripplot(data=data[data['pval'] >= 0.05], y='corr', color='red' , size = 8, ax=ax)
  2528. violin.collections[0].set_facecolor('none')
  2529. ax.set_ylabel('Correlation MwC and target\'s energy', fontsize = FONT)
  2530. ax.set_ylim([-0.1,0.72])
  2531. spine_width = 1.6
  2532. spine_color = 'gray'
  2533. for spine in ax.spines.values():
  2534. spine.set_linewidth(spine_width)
  2535. spine.set_color(spine_color)
  2536. plt.savefig('../results/Figures/control_box_CMRglc_only.png', dpi=300, bbox_inches='tight')
  2537. plt.show()
  2538. #--------------------------------------------------------------------------------------------
  2539. #--------------------------- permutation test ----------------------------------------------
  2540. #--------------------------------------------------------------------------------------------
  2541. #1. permutation on average data (IC_avg , E_avg)
  2542. observed_correlation, observed_pvalue = pcor(DATA_avg.pet_avg, DATA_avg.ICallsub_w_avg)
  2543. n_permutations = 500
  2544. permuted_correlations = np.zeros(n_permutations)
  2545. for perm_idx in range(n_permutations):
  2546. permuted_e_avg_values = np.copy(DATA_avg.pet_avg)
  2547. np.random.shuffle(permuted_e_avg_values)
  2548. permuted_correlations[perm_idx], _ = pcor(DATA_avg.ICallsub_w_avg, permuted_e_avg_values)
  2549. #p_value_permutation = np.mean(np.abs(permuted_correlations) >= np.abs(observed_correlation))
  2550. corr_perm_avg = np.mean(permuted_correlations)
  2551. # Print the results
  2552. print("Permutation Test Results:")
  2553. print(f"Observed Correlation: {observed_correlation}")
  2554. print(f"Observed p-value: {observed_pvalue}")
  2555. print(f"Average perumuted correlation : {corr_perm_avg }")
  2556. sns.displot(permuted_correlations, kde=True, color='#787B76')
  2557. #sns.xlabel('Correlation IE and target\'s energy')
  2558. plt.savefig('../results/Figures/control_RandomMatch_CMRglc_only.png', dpi=300, bbox_inches='tight')
  2559. plt.show()
  2560. #2. permutation on individual data (IC , E)
  2561. permuted_correlations = np.zeros((n_permutations, sub_size))
  2562. for i in range(sub_size):
  2563. E_sub = edata_medianallsub_rem[:,i]
  2564. IC_sub = ICallsub_w[:,i]
  2565. for perm_idx in range(n_permutations):
  2566. permuted_E_values = np.copy(E_sub)
  2567. np.random.shuffle(permuted_E_values)
  2568. permuted_correlations[perm_idx,i], _ = pcor(IC_sub, permuted_E_values)
  2569. #sns.boxplot(permuted_correlations)
  2570. #plt.show()
  2571. #---------------------- Ridge plot of each subject histogram -------------------------------
  2572. num_columns = permuted_correlations.shape[1]
  2573. reshaped_array = np.vstack((permuted_correlations.flatten(), np.tile(np.arange(num_columns), permuted_correlations.shape[0]))).T
  2574. df_reshaped = pd.DataFrame(reshaped_array, columns=['Correlation Value', 'Subject'])
  2575. df_filtered = df_reshaped
  2576. sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0), 'axes.linewidth':1})
  2577. palette = "Spectral"
  2578. g = sns.FacetGrid(df_filtered, palette=palette, row="Subject", hue="Subject", aspect=9, height=0.3)
  2579. g.map_dataframe(sns.kdeplot, x='Correlation Value', fill=True, alpha=0.8)
  2580. g.map_dataframe(sns.kdeplot, x='Correlation Value', color='black', linewidth= 0.7)
  2581. def label(x, color, label):
  2582. ax = plt.gca()
  2583. ax.text(0, .2, label, color='black', fontsize=10,
  2584. ha="left", va="center", transform=ax.transAxes)
  2585. g.fig.subplots_adjust(hspace=-.5)
  2586. g.set_titles("")
  2587. g.set(yticks=[], ylabel=None)
  2588. g.despine(left=True)
  2589. for ax in g.axes.flat:
  2590. ax.axvline(0, color='gray', linestyle='--', linewidth=1)
  2591. g.despine(left=True)
  2592. plt.savefig('../results/Figures/control_RandomMatch_single_CMRglc_only.png', dpi=300, bbox_inches='tight')
  2593. plt.show()
  2594. # %% [markdown]
  2595. # ## Fig S5-b: Sensitivity analysis
  2596. # %%
  2597. #--------------------------------------------------------------------------------------------
  2598. #------------------------- sensitivity to sc threshold -----------------------------------
  2599. #--------------------------------------------------------------------------------------------
  2600. plt.grid(True)
  2601. edata_medianallsub_rem = edata_medianallsub
  2602. nrois = 360
  2603. nrois_rem = nrois - len(limb_ind)
  2604. sub_size = MIconn_allsub.shape[2]
  2605. MIconn_allsub[MIconn_allsub < 0.01]=0
  2606. Conn_Mat = MIconn_allsub
  2607. thr_FC = 1
  2608. scmask = 1
  2609. thr_sc = np.linspace(0.01,1 , 20 )
  2610. corr_scthr = np.zeros((len(thr_sc)))
  2611. p_scthr = np.zeros((len(thr_sc)))
  2612. for i , thr in enumerate(thr_sc):
  2613. IC = only_IC_avg(Conn_Mat, edata_medianallsub_rem, SCconn_allsub, thr, thr_FC, sub_size, scmask, nrois_rem)
  2614. corr_scthr[i] , p_scthr[i] = pcor(IC, DATA_avg.pet_avg)
  2615. sc = plt.scatter(thr_sc, corr_scthr, s=100, c=-np.log10(p_scthr), cmap='plasma')
  2616. plt.colorbar(sc, label='-log10(p-value)')
  2617. plt.ylim([0.5,0.7])
  2618. plt.xlabel('SC threshold', fontsize = FONT)
  2619. plt.ylabel('Corr MwC and target\'s energy', fontsize = FONT)
  2620. spine_width = 1.6
  2621. for spine in ax.spines.values():
  2622. spine.set_linewidth(spine_width)
  2623. plt.savefig('../results/Figures/SC_threshold.png', dpi=300, bbox_inches='tight')
  2624. plt.show()
  2625. #--------------------------------------------------------------------------------------------
  2626. #------------------------- sensitivity to fc threshold -----------------------------------
  2627. #--------------------------------------------------------------------------------------------
  2628. plt.grid(True)
  2629. edata_medianallsub_rem = edata_medianallsub
  2630. nrois = 360
  2631. nrois_rem = nrois - len(limb_ind)
  2632. sub_size = MIconn_allsub.shape[2]
  2633. MIconn_allsub[MIconn_allsub < 0.0001]=0
  2634. Conn_Mat = MIconn_allsub
  2635. thr_sc = 1
  2636. scmask = 0
  2637. thr_fc = np.linspace(0.1,1 , 20 )
  2638. corr_fcthr = np.zeros((len(thr_fc)))
  2639. p_fcthr = np.zeros((len(thr_fc)))
  2640. for i , thr in enumerate(thr_fc):
  2641. IC = only_IC_avg(Conn_Mat, edata_medianallsub_rem, SCconn_allsub, thr_sc, thr, sub_size, scmask, nrois_rem)
  2642. corr_fcthr[i] , p_fcthr[i] = pcor(IC, DATA_avg.pet_avg)
  2643. sc = plt.scatter(thr_fc, corr_fcthr, s=100, c=-np.log10(p_fcthr), cmap='plasma')
  2644. plt.colorbar(sc, label='-log10(p-value)')
  2645. plt.ylim([0.5,0.7])
  2646. plt.xlabel('MI threshold', fontsize = FONT)
  2647. plt.ylabel('Corr MwC and target\'s energy', fontsize = FONT)
  2648. spine_width = 1.6
  2649. for spine in ax.spines.values():
  2650. spine.set_linewidth(spine_width)
  2651. plt.savefig('../results/Figures/MI_threshold.png', dpi=300, bbox_inches='tight')
  2652. plt.show()
  2653. #--------------------------------------------------------------------------------------------
  2654. #------------------- sensitivity to region size (number of voxels) -----------------------
  2655. #--------------------------------------------------------------------------------------------
  2656. COLOR = [227/255 , 108/255, 138/255]
  2657. num_voxels_avg = np.mean(num_voxels , axis = 1)
  2658. corr_IC_w_vox, p_IC_w_vox = pcor(DATA_avg.ICallsub_w_avg, num_voxels_avg)
  2659. plt.figure(figsize=(6,4))
  2660. g = sns.jointplot(x = num_voxels_avg , y = DATA_avg.ICallsub_w_avg, kind="reg", color="#547BC9",
  2661. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2662. line_kws={'color': 'black', 'lw': 1},
  2663. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':"#FDC827", 'edgecolors':"#FDC827"} )
  2664. title = "corr = {:.2f} , p-val = {:.0e}".format(float(corr_IC_w_vox) , float(p_IC_w_vox))
  2665. g.fig.suptitle(f"corr = {corr_IC_w_vox:.2f} , p-val = {p_IC_w_vox:.0e}", fontsize=FONT, va='baseline', y=0.8)
  2666. g.set_axis_labels('Actual Target Energy', 'MCC', fontsize=FONT)
  2667. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2668. plt.xlabel('Target size (#voxels)', fontsize = FONT)
  2669. plt.ylabel('MwC', fontsize = FONT)
  2670. ax = g.ax_joint
  2671. spine_width = 1.6
  2672. for spine in ax.spines.values():
  2673. spine.set_linewidth(spine_width)
  2674. plt.grid(True)
  2675. plt.savefig('../results/Figures/Target_size.png', dpi=300, bbox_inches='tight')
  2676. plt.show()
  2677. #--------------------------------------------------------------------------------------------
  2678. #-------------------------- 3. sensitivity to source numbers --------------------------------
  2679. #--------------------------------------------------------------------------------------------
  2680. corr_IC_w_source, p_IC_w_source = pcor(DATA_avg.ICallsub_w_avg, DATA_avg.degallsub_b_avg)
  2681. #sns.lmplot(data = DATA_avg , x = 'pet_avg' , y ='ICallsu_w_avg' , hue = 'yeo_7_nw' )
  2682. sns.scatterplot(data = DATA_avg , x = 'degallsub_b_avg' , y ='ICallsub_w_avg' , color = 'Orange')
  2683. title = "corr = {:.2f} , p-val = {:.0e}".format(float(corr_IC_w_source) , float(p_IC_w_source))
  2684. plt.title(title , fontdict={'fontsize': 15})
  2685. plt.xlabel('Source Numbers')
  2686. plt.ylabel('MwC')
  2687. plt.show()
  2688. # %% [markdown]
  2689. # ## Fig S6: replication spatial correlation using Julich parcellation
  2690. # %%
  2691. #--------------------------------------------------------------------------------------------
  2692. #------------------ remove limbic and subcortical rois ----------------------------
  2693. #--------------------------------------------------------------------------------------------
  2694. atlas = '../data/external/JulichBrainAtlas_fsl_mni_3mm.nii.gz'
  2695. atlas_data = nib.load(atlas).get_fdata()
  2696. all_labels = np.unique(atlas_data)
  2697. all_labels = all_labels[all_labels > 0]
  2698. counts_remaining = np.array([np.sum(atlas_data == lab) for lab in all_labels])
  2699. small_rois = all_labels[counts_remaining <= 10] # exclude small regions
  2700. removed_rois = [17, 130, 120] # these three rois have more than 75% overlap with MMP limbic's rois
  2701. subcort_ids= [5, 9, 12, 15, 16,17, 18, 23, 24, 31, 38, 39, 44, 45, 47, 51, 52,
  2702. 56, 61, 63, 66, 68, 74, 75, 79, 81, 87, 88, 92, 93, 103, 109,
  2703. 113, 115, 119, 120, 125, 131, 136, 137, 138, 141, 146, 149, 151,
  2704. 153, 154, 156, 166, 168, 169, 172, 173, 174, 176, 178, 181, 184,
  2705. 185, 187, 188, 190, 191, 193, 194, 202, 212, 216, 219, 222, 223,224,
  2706. 225, 230, 231, 238, 245, 246, 251, 252, 256, 259, 260, 263, 268,
  2707. 270, 271, 275, 276, 280, 281, 291, 296, 300, 302, 306, 307, 312,
  2708. 318, 320, 322, 323, 326, 331, 334, 336, 339, 340, 341, 343, 344,
  2709. 353, 355, 356, 358, 361, 364, 365, 367, 371, 372, 373, 375, 378,
  2710. 381, 382, 384,385, 388, 391, 392, 394, 395, 397, 398, 400, 401, 409]
  2711. rem_ind = np.union1d(removed_rois, subcort_ids)
  2712. rem_ind = np.union1d(rem_ind, small_rois)
  2713. roi_ids = np.unique(atlas_data[atlas_data != 0]).astype(np.int32)
  2714. roi_ids = np.setdiff1d(roi_ids, np.array(rem_ind, dtype=np.int32))
  2715. roi_ids = np.sort(roi_ids)
  2716. #print(roi_ids.shape)
  2717. #--------------------------------------------------------------------------------------------
  2718. #-------------- read functional connectivity and other inputs ----------------
  2719. #--------------------------------------------------------------------------------------------
  2720. session = "AUF"
  2721. LIMB = "without"
  2722. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic_Julich.pkl'
  2723. with open(file_path, 'rb') as file:
  2724. data_input_ju = pickle.load(file)
  2725. num_voxels_ju = data_input_ju['num_voxels']
  2726. MIconn_allsub_ju = data_input_ju['MIconn_allsub']
  2727. Pearconn_allsub_ju = data_input_ju['Pearconn_allsub']
  2728. edata_medianallsub_ju = data_input_ju['edata_medianallsub']
  2729. SCconn_allsub_ju = np.ones(Pearconn_allsub_ju.shape)
  2730. nrois_rem = MIconn_allsub_ju.shape[0]
  2731. sub_size = MIconn_allsub_ju.shape[2]
  2732. #--------------------------------------------------------------------------------------------
  2733. #-------------- calculate and save IC and other inputs ----------------
  2734. #--------------------------------------------------------------------------------------------
  2735. data_avg_pr_path = f'../data/processed/DATA_avg_woSC_pr_{session}_{LIMB}_limb_Julich.csv'
  2736. data_sub_pr_path = f'../data/processed/data_single_sub_woSC_pr_{session}_{LIMB}_limb_Julich.pkl'
  2737. data_avg_path = f'../data/processed/DATA_avg_woSC_{session}_{LIMB}_limb_Julich.csv'
  2738. data_sub_path = f'../data/processed/data_single_sub_woSC_{session}_{LIMB}_limb_Julich.pkl'
  2739. MIconn_allsub_ju[MIconn_allsub_ju < 0.01] = 0
  2740. Conn_Mat = MIconn_allsub_ju
  2741. thr_FC = 1
  2742. scmask = 0
  2743. thr_sc = 0.1
  2744. [data_avg, data_single_sub] = IC_calculation(Conn_Mat, edata_medianallsub_ju, SCconn_allsub_ju, thr_sc, thr_FC, sub_size, scmask, nrois_rem)
  2745. DATA_avg = data_avg
  2746. DATA_avg.insert(0, "roi_ids_rem", roi_ids)
  2747. DATA_avg.to_csv(data_avg_path, index=False)
  2748. with open(data_sub_path, 'wb') as file:
  2749. pickle.dump(data_single_sub, file, protocol=pickle.HIGHEST_PROTOCOL)
  2750. # DATA_avg = pd.read_csv(data_avg_path)
  2751. # with open(data_sub_path, 'rb') as file:
  2752. # data_single_sub = pickle.load(file)
  2753. ICallsub_w = data_single_sub['ICallsub_w']
  2754. ICallsub_b = data_single_sub['ICallsub_b']
  2755. degallsub_w = data_single_sub['degallsub_w']
  2756. degallsub_b = data_single_sub['degallsub_b']
  2757. AvgMIallsub = data_single_sub['AvgMIallsub']
  2758. #--------------------------------------------------------------------------------------------
  2759. #------------------ scatter IC_avg , CMRglc_avg / group analysis ----------------------------
  2760. #--------------------------------------------------------------------------------------------
  2761. DATA_avg_new = DATA_avg.copy()
  2762. # DATA_avg_new = DATA_avg_new[DATA_avg_new ["pet_avg"]>20]
  2763. # DATA_avg_new = DATA_avg_new[DATA_avg_new ["ICallsub_w_avg"]>28.5]
  2764. corr_IC_w_E, p_IC_w_E = pcor(DATA_avg_new.ICallsub_w_avg, DATA_avg_new.pet_avg)
  2765. COLOR = "#8DD084"
  2766. plt.figure(figsize=(6,4))
  2767. g = sns.jointplot(data=DATA_avg_new, x='pet_avg', y='ICallsub_w_avg', kind="reg", color=COLOR,
  2768. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2769. line_kws={'color': 'black', 'lw': 1},
  2770. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  2771. p_IC_w_E_smash = p_IC_w_E
  2772. if p_IC_w_E_smash < 0.0001:
  2773. title = "r = {:.2f} , p-val < {:.3f}".format(float(corr_IC_w_E), float(0.001))
  2774. else:
  2775. title = "r = {:.2f} , p-val = {:.3f}".format(float(corr_IC_w_E), float(p_IC_w_E_smash))
  2776. #g.fig.suptitle(f"corr = {corr_IC_w_E:.2f}"", $Pval_{smash}$ < 0.001", fontsize=FONT, va='baseline', y=0.8)
  2777. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2778. g.set_axis_labels('Target Energy', 'MwC', fontsize=FONT)
  2779. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2780. plt.grid(True)
  2781. plt.ylim([28,31.5])
  2782. plt.xlabel('Target Energy (CMRglc)', fontsize = FONT)
  2783. plt.ylabel('MwC', fontsize = FONT)
  2784. ax = g.ax_joint
  2785. spine_width = 1.6
  2786. for spine in ax.spines.values():
  2787. spine.set_linewidth(spine_width)
  2788. spine.set_edgecolor("gray")
  2789. #plt.savefig(f'../results/Figures/CMRglc_IC_scatter_Julich.png', dpi=300, bbox_inches='tight')
  2790. plt.show()
  2791. # %% [markdown]
  2792. # ## Fig S7: Effect of registraion quality on spatial correlation
  2793. # %%
  2794. sub = [3,7,12,14,17,20,23,25,26,28,29,30,31,32,33,35,36,37,38]
  2795. session = "AUF"
  2796. LIMB = "without"
  2797. sub_size = len(sub)
  2798. data_sub_path = f'../data/processed/data_single_sub_wSC_{session}_{LIMB}_limb.pkl'
  2799. data_sub_pr_path = f'../data/processed/data_single_sub_wSC_pr_{session}_{LIMB}_limb.pkl'
  2800. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  2801. with open(file_path, 'rb') as file:
  2802. data_input = pickle.load(file)
  2803. edata_medianallsub = data_input['edata_medianallsub']
  2804. with open(data_sub_path, 'rb') as file:
  2805. data_single_sub = pickle.load(file)
  2806. ICallsub_w = data_single_sub['ICallsub_w']
  2807. degallsub_w = data_single_sub['degallsub_w']
  2808. print(degallsub_w.shape)
  2809. with open(data_sub_pr_path, 'rb') as file:
  2810. data_single_sub_pr = pickle.load(file)
  2811. ICallsub_w_pr = data_single_sub_pr['ICallsub_w']
  2812. degallsub_w_pr = data_single_sub_pr['degallsub_w']
  2813. corr_IC_E_allsub = np.zeros(sub_size)
  2814. p_IC_E_allsub = np.zeros(sub_size)
  2815. corr_deg_w_E_allsub = np.zeros(sub_size)
  2816. p_deg_w_E_allsub = np.zeros(sub_size)
  2817. for j in range(sub_size):
  2818. corr_IC_E_allsub[j], p_IC_E_allsub[j] = pcor(ICallsub_w[:, j], edata_medianallsub[:, j])
  2819. corr_deg_w_E_allsub[j], p_deg_w_E_allsub[j] = pcor(degallsub_w[:, j], edata_medianallsub[:, j])
  2820. ######
  2821. mni2func_qc = pd.read_csv( "../data/processed/MNI2FUNC_AUF_qc_corratio_steps.csv")
  2822. mni2pet_qc = pd.read_csv( "../data/processed/MNI2PET_AUF_qc_corratio_steps.csv")
  2823. data = pd.DataFrame({"mni2func_qc":mni2func_qc["final"], "mni2pet_qc":mni2pet_qc["final"],
  2824. "corr_IC_E_allsub":corr_IC_E_allsub, "corr_deg_w_E_allsub":corr_deg_w_E_allsub})
  2825. corr_IC_qc , p_IC_qc = pcor(mni2func_qc["final"], corr_IC_E_allsub)
  2826. print(corr_IC_qc , p_IC_qc)
  2827. FRONT = 20
  2828. plt.figure(figsize=(6,4))
  2829. g = sns.jointplot(data=data, x='corr_IC_E_allsub', y='mni2func_qc', kind="reg", color=COLOR,
  2830. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2831. line_kws={'color': 'black', 'lw': 1},
  2832. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  2833. title = "r = {:.2f} , p = {:.2f}".format(float(corr_IC_qc), float(p_IC_qc))
  2834. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2835. g.set_axis_labels('Target Energy', 'Degree', fontsize=FONT)
  2836. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2837. plt.grid(True)
  2838. plt.xlabel('subject-level corr(MwC,CMRglc)', fontsize = FONT)
  2839. plt.ylabel('corratio(MNI to functional)', fontsize = FONT)
  2840. ax = g.ax_joint
  2841. spine_width = 1.6
  2842. spine_color = 'gray'
  2843. for spine in ax.spines.values():
  2844. spine.set_linewidth(spine_width)
  2845. spine.set_color(spine_color)
  2846. plt.savefig(f'../results/Figures/qc_mni2func_corr_scatter.png', dpi=300, bbox_inches='tight')
  2847. plt.show()
  2848. corr_IC_qc_mni2pet , p_IC_qc_mni2pet= pcor(mni2pet_qc["final"], corr_IC_E_allsub)
  2849. plt.figure(figsize=(6,4))
  2850. g = sns.jointplot(data=data, x='corr_IC_E_allsub', y='mni2pet_qc', kind="reg", color=COLOR,
  2851. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2852. line_kws={'color': 'black', 'lw': 1},
  2853. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  2854. title = "r = {:.2f} , p = {:.2f}".format(float(corr_IC_qc_mni2pet), float(p_IC_qc_mni2pet))
  2855. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2856. g.set_axis_labels('Target Energy', 'Degree', fontsize=FONT)
  2857. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2858. plt.grid(True)
  2859. plt.xlabel('subject-level corr(MwC,CMRglc)', fontsize = FONT)
  2860. plt.ylabel('corratio(MNI to PET)', fontsize = FONT)
  2861. ax = g.ax_joint
  2862. spine_width = 1.6
  2863. spine_color = 'gray'
  2864. for spine in ax.spines.values():
  2865. spine.set_linewidth(spine_width)
  2866. spine.set_color(spine_color)
  2867. plt.savefig(f'../results/Figures/qc_mni2pet_corr_scatter.png', dpi=300, bbox_inches='tight')
  2868. plt.show()
  2869. # %% [markdown]
  2870. # ## Fig S8: relationship between functional/microstructural gradient and MwC
  2871. # %% [markdown]
  2872. # ### functional gradient (Margulies 2016)
  2873. # %%
  2874. LIMB = "without"
  2875. session = "AUF"
  2876. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  2877. data_avg_pr_path = f'../data/processed/DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv'
  2878. grad1_region_rem= pd.read_csv('../data/external/fcgrad1_region_rem.csv', header = None)
  2879. grad1_region_rem = grad1_region_rem.to_numpy(dtype=float).ravel()
  2880. DATA_avg = pd.read_csv(data_avg_path)
  2881. DATA_avg_pr = pd.read_csv(data_avg_pr_path)
  2882. IC =DATA_avg['ICallsub_w_avg']
  2883. deg = DATA_avg_pr['degallsub_w_avg']
  2884. pet = DATA_avg['pet_avg']
  2885. cor_IC_grad , p_IC_grad = pearsonr(IC,grad1_region_rem )
  2886. cor_deg_grad , p_deg_grad = pearsonr(deg,grad1_region_rem )
  2887. print(cor_IC_grad , p_IC_grad)
  2888. print(cor_deg_grad , p_deg_grad)
  2889. data = pd.DataFrame({"IC":IC, "deg":deg, "pet":pet, "grad1":grad1_region_rem})
  2890. #--------------------------------------------------------------------------------------------
  2891. #------------------ scatter IC_avg , fc gradient group analysis ----------------------------
  2892. #--------------------------------------------------------------------------------------------
  2893. COLOR = 'gray'
  2894. FONT = 18
  2895. plt.figure(figsize=(6,4))
  2896. g = sns.jointplot(data=data, x='grad1', y='IC', kind="reg", color=COLOR,
  2897. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2898. line_kws={'color': 'black', 'lw': 1},
  2899. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  2900. title = "r = {:.2f} , p = {:.3f}".format(float(cor_IC_grad), float(p_IC_grad))
  2901. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2902. g.set_axis_labels('First gradient', 'MwC', fontsize=FONT)
  2903. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2904. plt.grid(True)
  2905. plt.xlabel('First gradient', fontsize = FONT)
  2906. plt.ylabel('MwC', fontsize = FONT)
  2907. ax = g.ax_joint
  2908. spine_width = 1.6
  2909. for spine in ax.spines.values():
  2910. spine.set_linewidth(spine_width)
  2911. spine.set_edgecolor("gray")
  2912. plt.savefig(f'../results/Figures/grad1_IC_scatter.png', dpi=300, bbox_inches='tight')
  2913. plt.show()
  2914. #--------------------------------------------------------------------------------------------
  2915. #------------------ scatter deg_avg , first gradient ----------------------------
  2916. #--------------------------------------------------------------------------------------------
  2917. COLOR = 'gray'
  2918. FONT = 18
  2919. plt.figure(figsize=(6,4))
  2920. g = sns.jointplot(data=data, x='grad1', y='deg', kind="reg", color=COLOR,
  2921. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2922. line_kws={'color': 'black', 'lw': 1},
  2923. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  2924. title = "r = {:.2f} , p = {:.3f}".format(float(cor_deg_grad), float(p_deg_grad))
  2925. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2926. g.set_axis_labels('First gradient', 'DC', fontsize=FONT)
  2927. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2928. plt.grid(True)
  2929. plt.xlabel('First gradient', fontsize = FONT)
  2930. plt.ylabel('wDC', fontsize = FONT)
  2931. ax = g.ax_joint
  2932. spine_width = 1.6
  2933. for spine in ax.spines.values():
  2934. spine.set_linewidth(spine_width)
  2935. spine.set_edgecolor("gray")
  2936. plt.savefig(f'../results/Figures/grad1_DC_scatter.png', dpi=300, bbox_inches='tight')
  2937. plt.show()
  2938. # %% [markdown]
  2939. # ### microstructural gradient
  2940. # %%
  2941. LIMB = "without"
  2942. session = "AUF"
  2943. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  2944. data_avg_pr_path = f'../data/processed/DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv'
  2945. grad1_region_rem = pd.read_csv('../data/external/micro_grad1_region_rem.csv', header = None)
  2946. grad1_region_rem = grad1_region_rem.to_numpy(dtype=float).ravel()
  2947. DATA_avg = pd.read_csv(data_avg_path)
  2948. DATA_avg_pr = pd.read_csv(data_avg_pr_path)
  2949. IC =DATA_avg['ICallsub_w_avg']
  2950. deg = DATA_avg_pr['degallsub_w_avg']
  2951. pet = DATA_avg['pet_avg']
  2952. cor_IC_grad , p_IC_grad = pearsonr(IC,grad1_region_rem )
  2953. cor_deg_grad , p_deg_grad = pearsonr(deg,grad1_region_rem )
  2954. print(cor_IC_grad , p_IC_grad)
  2955. print(cor_deg_grad , p_deg_grad)
  2956. data = pd.DataFrame({"IC":IC, "deg":deg, "pet":pet, "grad1":grad1_region_rem})
  2957. #--------------------------------------------------------------------------------------------
  2958. #------------------ scatter IC_avg , CMRglc_avg / group analysis ----------------------------
  2959. #--------------------------------------------------------------------------------------------
  2960. COLOR = 'gray'
  2961. FONT = 18
  2962. plt.figure(figsize=(6,4))
  2963. g = sns.jointplot(data=data, x='grad1', y='IC', kind="reg", color=COLOR,
  2964. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2965. line_kws={'color': 'black', 'lw': 1},
  2966. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  2967. title = "r = {:.2f} , p = {:.3f}".format(float(cor_IC_grad), float(p_IC_grad))
  2968. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2969. g.set_axis_labels('First gradient', 'MwC', fontsize=FONT)
  2970. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2971. plt.grid(True)
  2972. plt.xlabel('Functional gradient', fontsize = FONT)
  2973. plt.ylabel('MwC', fontsize = FONT)
  2974. ax = g.ax_joint
  2975. spine_width = 1.6
  2976. for spine in ax.spines.values():
  2977. spine.set_linewidth(spine_width)
  2978. spine.set_edgecolor("gray")
  2979. plt.savefig(f'../results/Figures/micro_grad_IC_scatter.png', dpi=300, bbox_inches='tight')
  2980. plt.show()
  2981. #--------------------------------------------------------------------------------------------
  2982. #------------------ scatter IC_avg , CMRglc_avg / group analysis ----------------------------
  2983. #--------------------------------------------------------------------------------------------
  2984. COLOR = 'gray'
  2985. FONT = 18
  2986. plt.figure(figsize=(6,4))
  2987. g = sns.jointplot(data=data, x='grad1', y='deg', kind="reg", color=COLOR,
  2988. marginal_kws=dict(bins=15, fill=True, color='gray'),
  2989. line_kws={'color': 'black', 'lw': 1},
  2990. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  2991. title = "r = {:.2f} , p = {:.3f}".format(float(cor_deg_grad), float(p_deg_grad))
  2992. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  2993. g.set_axis_labels('First gradient', 'DC', fontsize=FONT)
  2994. plt.tick_params(axis='both', which='major', labelsize= FONT)
  2995. plt.grid(True)
  2996. plt.xlabel('Microstructural gradient', fontsize = FONT)
  2997. plt.ylabel('DC', fontsize = FONT)
  2998. ax = g.ax_joint
  2999. spine_width = 1.6
  3000. for spine in ax.spines.values():
  3001. spine.set_linewidth(spine_width)
  3002. spine.set_edgecolor("gray")
  3003. plt.savefig(f'../results/Figures/micro_grad_DC_scatter.png', dpi=300, bbox_inches='tight')
  3004. plt.show()
  3005. # %% [markdown]
  3006. # ## Fig S10: MwC-Mito association
  3007. # %%
  3008. mito_img_CI = nib.load('PATH to CI.nii.gz')
  3009. mito_img_CII = nib.load('PATH to CII.nii.gz')
  3010. mito_img_CIV = nib.load('PATH to CIV.nii.gz')
  3011. mito_img_TRC = nib.load('PATH to TRC.nii.gz')
  3012. mito_img_MRC = nib.load('PATH to MRC.nii.gz')
  3013. mito_img_MitoD = nib.load('PATH to MitoD.nii.gz')
  3014. mito_data_CI = mito_img_CI.get_fdata()
  3015. mito_data_CII = mito_img_CII.get_fdata()
  3016. mito_data_CIV = mito_img_CIV.get_fdata()
  3017. mito_data_TRC = mito_img_TRC.get_fdata()
  3018. mito_data_MRC = mito_img_MRC.get_fdata()
  3019. mito_data_MitoD = mito_img_MitoD.get_fdata()
  3020. mmp_in_mni_6 = f'../data/external/mmp_in_mni_6.nii.gz'
  3021. atlas_mito = nib.load(mmp_in_mni_6)
  3022. atlas_data_mito = atlas_mito.get_fdata()
  3023. region_labels_mito = np.unique(atlas_data_mito)
  3024. region_labels_mito = region_labels_mito[region_labels_mito > 0]
  3025. n_regions = len(region_labels_mito)
  3026. mito_values = {
  3027. 'CI': np.zeros(n_regions),
  3028. 'CII': np.zeros(n_regions),
  3029. 'CIV': np.zeros(n_regions),
  3030. 'TRC': np.zeros(n_regions),
  3031. 'MRC': np.zeros(n_regions),
  3032. 'MitoD': np.zeros(n_regions),
  3033. 'syn': np.zeros(n_regions),
  3034. }
  3035. for i, label in enumerate(region_labels_mito):
  3036. region_mask = atlas_data_mito == label
  3037. region_vals_CI = mito_data_CI[region_mask]
  3038. region_vals_CII = mito_data_CII[region_mask]
  3039. region_vals_CIV = mito_data_CIV[region_mask]
  3040. region_vals_TRC = mito_data_TRC[region_mask]
  3041. region_vals_MRC = mito_data_MRC[region_mask]
  3042. region_vals_MitoD = mito_data_MitoD[region_mask]
  3043. # Compute mean of nonzero, non-NaN voxels
  3044. mito_values['CI'][i] = np.nanmedian(region_vals_CI[region_vals_CI != 0])
  3045. mito_values['CII'][i] = np.nanmedian(region_vals_CII[region_vals_CII != 0])
  3046. mito_values['CIV'][i] = np.nanmedian(region_vals_CIV[region_vals_CIV != 0])
  3047. mito_values['TRC'][i] = np.nanmedian(region_vals_TRC[region_vals_TRC != 0])
  3048. mito_values['MRC'][i] = np.nanmedian(region_vals_MRC[region_vals_MRC != 0])
  3049. mito_values['MitoD'][i] = np.nanmedian(region_vals_MitoD[region_vals_MitoD != 0])
  3050. # delete limbic regions, if needed:
  3051. mito_values['CI'] = np.delete(mito_values['CI'], limb_ind , axis = 0)
  3052. mito_values['CII'] = np.delete(mito_values['CII'], limb_ind , axis = 0)
  3053. mito_values['CIV'] = np.delete(mito_values['CIV'], limb_ind , axis = 0)
  3054. mito_values['TRC'] = np.delete(mito_values['TRC'], limb_ind , axis = 0)
  3055. mito_values['MRC'] = np.delete(mito_values['MRC'], limb_ind , axis = 0)
  3056. mito_values['MitoD'] = np.delete(mito_values['MitoD'], limb_ind , axis = 0)
  3057. data = pd.DataFrame({'IC':(DATA_avg.ICallsub_w_avg), 'deg':(DATA_avg_pr.degallsub_w_avg), 'pet':(DATA_avg.pet_avg)
  3058. ,'mito_CI':(mito_values['CI']), 'mito_CII':(mito_values['CII']), 'mito_CIV':(mito_values['CIV']), 'mito_TRC':(mito_values['TRC'])
  3059. , 'mito_MRC':(mito_values['MRC']), 'mito_MitoD':(mito_values['MitoD'])})
  3060. corr_IC_CI, p_IC_CI =spearmanr(data["mito_CI"], data["IC"])
  3061. corr_IC_CII, p_IC_CII =spearmanr(data["mito_CII"], data["IC"])
  3062. corr_IC_CIV, p_IC_CIV = spearmanr(data["mito_CIV"], data["IC"])
  3063. corr_IC_TRC, p_IC_TRC = spearmanr(data["mito_TRC"], data["IC"])
  3064. corr_IC_MRC, p_IC_MRC = spearmanr(data["mito_MRC"], data["IC"])
  3065. corr_IC_MitoD, p_IC_MitoD = spearmanr(data["mito_MitoD"], data["IC"])
  3066. COLOR = IC_color
  3067. plt.figure(figsize=(6,4))
  3068. g = sns.jointplot(data=data, x='IC', y='mito_MitoD', kind="reg", color=COLOR,
  3069. marginal_kws=dict(bins=15, fill=True, color='gray'),
  3070. line_kws={'color': 'black', 'lw': 1},
  3071. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  3072. title = "corr = {:.2f} , p-val = {:.0e}".format(float(corr_IC_MitoD), float(p_IC_MitoD))
  3073. #g.fig.suptitle(f"corr = {corr_IC_w_E:.2f}"", $Pval_{smash}$ < 0.001", fontsize=FONT, va='baseline', y=0.8)
  3074. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  3075. g.set_axis_labels('Target Energy', 'MCC', fontsize=FONT)
  3076. plt.tick_params(axis='both', which='major', labelsize= FONT)
  3077. plt.grid(True)
  3078. plt.xlabel('MwC', fontsize = FONT)
  3079. plt.ylabel('Mitochondrial Density', fontsize = FONT)
  3080. ax = g.ax_joint
  3081. spine_width = 1.6
  3082. for spine in ax.spines.values():
  3083. spine.set_linewidth(spine_width)
  3084. plt.show()
  3085. plt.figure(figsize=(6,4))
  3086. g = sns.jointplot(data=data, x='IC', y='mito_MRC', kind="reg", color=COLOR,
  3087. marginal_kws=dict(bins=15, fill=True, color='gray'),
  3088. line_kws={'color': 'black', 'lw': 1},
  3089. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  3090. title = "corr = {:.2f} , p-val = {:.0e}".format(float(corr_IC_MRC), float(p_IC_MRC))
  3091. #g.fig.suptitle(f"corr = {corr_IC_w_E:.2f}"", $Pval_{smash}$ < 0.001", fontsize=FONT, va='baseline', y=0.8)
  3092. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  3093. plt.tick_params(axis='both', which='major', labelsize= FONT)
  3094. plt.grid(True)
  3095. plt.xlabel('MwC', fontsize = FONT)
  3096. plt.ylabel('MRC', fontsize = FONT)
  3097. ax = g.ax_joint
  3098. spine_width = 1.6
  3099. for spine in ax.spines.values():
  3100. spine.set_linewidth(spine_width)
  3101. plt.show()
  3102. plt.figure(figsize=(6,4))
  3103. g = sns.jointplot(data=data, x='IC', y='mito_TRC', kind="reg", color=COLOR,
  3104. marginal_kws=dict(bins=15, fill=True, color='gray'),
  3105. line_kws={'color': 'black', 'lw': 1},
  3106. scatter_kws={'s': 85, 'alpha': 0.7, 'facecolors':COLOR, 'edgecolors':COLOR} )
  3107. title = "corr = {:.2f} , p-val = {:.0e}".format(float(corr_IC_TRC), float(p_IC_TRC))
  3108. #g.fig.suptitle(f"corr = {corr_IC_w_E:.2f}"", $Pval_{smash}$ < 0.001", fontsize=FONT, va='baseline', y=0.8)
  3109. g.fig.suptitle(title, fontsize=FONT, va='baseline', y=0.8)
  3110. plt.tick_params(axis='both', which='major', labelsize= FONT)
  3111. plt.grid(True)
  3112. plt.xlabel('MwC', fontsize = FONT)
  3113. plt.ylabel('TRC', fontsize = FONT)
  3114. ax = g.ax_joint
  3115. spine_width = 1.6
  3116. for spine in ax.spines.values():
  3117. spine.set_linewidth(spine_width)
  3118. plt.show()
  3119. # %% [markdown]
  3120. # ## Fig S11:CMRglc - networks
  3121. # %%
  3122. net_label_WithLimbic = pd.read_csv(f'../data/external/mmp2yeo7nw_mapping.csv')
  3123. net_label_WithLimbic.reset_index(drop=True, inplace=True)
  3124. network_to_number = {network: i + 1 for i, network in enumerate(net_label_WithLimbic['yeo_7_nw'].unique())}
  3125. net_label_WithLimbic['network_number'] = net_label_WithLimbic['yeo_7_nw'].map(network_to_number)
  3126. color = [(139, 19, 140),(1,131, 182),(51, 116, 32),
  3127. (222, 75, 82),(226, 55, 255),(239, 156, 60), (255, 254, 211)]
  3128. net_color_WithLimbic = [(r/255, g/255, b/255 , 1) for r,g,b in color]
  3129. network_palette = dict(zip(net_names, net_color_WithLimbic))
  3130. xtik = ['Vis','Som','Dors','Def', 'Sal' , 'Cont', 'Limbic']
  3131. net_names_WithLimbic = ['Vis', 'SomMot' ,'DorsAttn' ,'Default' ,'SalVentAttn', 'Cont', 'Limbic' ]
  3132. net_num_WithLimbic = net_label_WithLimbic["network_number"]
  3133. new_net_num_WithLimbic = np.tile(net_num.transpose(), (nrois, 1))
  3134. num_net = len(net_names_WithLimbic)
  3135. LIMB = "with"
  3136. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  3137. DATA_avg_WithLimbic = pd.read_csv(data_avg_path)
  3138. edata = DATA_avg_WithLimbic.pet_avg
  3139. flat_values = edata.values
  3140. flat_networks = net_label_WithLimbic['yeo_7_nw'].values
  3141. df_box = pd.DataFrame({
  3142. 'Value': flat_values,
  3143. 'Network': flat_networks
  3144. })
  3145. plt.figure(figsize=(10, 6))
  3146. sns.set_style("whitegrid")
  3147. sns.boxplot(x='Network', y='Value', data=df_box, palette=network_palette)
  3148. plt.xticks(rotation=45)
  3149. plt.ylabel('Median CMRglc')
  3150. plt.xlabel('Network')
  3151. plt.title(f'Median CMRglc across Networks with Limbic')
  3152. plt.tight_layout()
  3153. plt.show()
  3154. # %% [markdown]
  3155. # # Statistical comparison DC, MCC
  3156. # %% [markdown]
  3157. # ## regression CMRglc = DC + MCC
  3158. # %%
  3159. #--------------------------------------------------------------------------------------------
  3160. #------------------ read all sessions data -------------------------------
  3161. #-------------------------------------------------------------------------------------------
  3162. LIMB = "without"
  3163. session = 'AUF'
  3164. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  3165. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  3166. data_sub_path = f'../data/processed/data_single_sub_wSC_{session}_{LIMB}_limb.pkl'
  3167. data_avg_pr_path = f'../data/processed/DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv'
  3168. data_sub_pr_path = f'../data/processed/data_single_sub_wSC_pr_{session}_{LIMB}_limb.pkl'
  3169. with open(file_path, 'rb') as file:
  3170. data_input_auf = pickle.load(file)
  3171. DATA_avg_auf = pd.read_csv(data_avg_path)
  3172. with open(data_sub_path, 'rb') as file:
  3173. data_single_sub_auf = pickle.load(file)
  3174. DATA_avg_pr_auf = pd.read_csv(data_avg_pr_path)
  3175. with open(data_sub_pr_path, 'rb') as file:
  3176. data_single_sub_pr_auf = pickle.load(file)
  3177. session = 'ZU'
  3178. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  3179. data_avg_path = f'../data/processed/DATA_avg_wSC_{session}_{LIMB}_limb.csv'
  3180. data_sub_path = f'../data/processed/data_single_sub_wSC_{session}_{LIMB}_limb.pkl'
  3181. data_avg_pr_path = f'../data/processed/DATA_avg_wSC_pr_{session}_{LIMB}_limb.csv'
  3182. data_sub_pr_path = f'../data/processed/data_single_sub_wSC_pr_{session}_{LIMB}_limb.pkl'
  3183. with open(file_path, 'rb') as file:
  3184. data_input_zu = pickle.load(file)
  3185. DATA_avg_zu = pd.read_csv(data_avg_path)
  3186. with open(data_sub_path, 'rb') as file:
  3187. data_single_sub_zu = pickle.load(file)
  3188. DATA_avg_pr_zu = pd.read_csv(data_avg_pr_path)
  3189. with open(data_sub_pr_path, 'rb') as file:
  3190. data_single_sub_pr_zu = pickle.load(file)
  3191. session = 'm1'
  3192. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  3193. data_avg_path = f'../data/processed/DATA_avg_woSC_{session}_{LIMB}_limb.csv'
  3194. data_sub_path = f'../data/processed/data_single_sub_woSC_{session}_{LIMB}_limb.pkl'
  3195. data_avg_pr_path = f'../data/processed/DATA_avg_woSC_pr_{session}_{LIMB}_limb.csv'
  3196. data_sub_pr_path = f'../data/processed/data_single_sub_woSC_pr_{session}_{LIMB}_limb.pkl'
  3197. with open(file_path, 'rb') as file:
  3198. data_input_m1 = pickle.load(file)
  3199. DATA_avg_m1 = pd.read_csv(data_avg_path)
  3200. with open(data_sub_path, 'rb') as file:
  3201. data_single_sub_m1 = pickle.load(file)
  3202. DATA_avg_pr_m1 = pd.read_csv(data_avg_pr_path)
  3203. with open(data_sub_pr_path, 'rb') as file:
  3204. data_single_sub_pr_m1 = pickle.load(file)
  3205. session = 'm2'
  3206. file_path = f'../data/processed/matrices_data_{session}_{LIMB}_limbic.pkl'
  3207. data_avg_path = f'../data/processed/DATA_avg_woSC_{session}_{LIMB}_limb.csv'
  3208. data_sub_path = f'../data/processed/data_single_sub_woSC_{session}_{LIMB}_limb.pkl'
  3209. data_avg_pr_path = f'../data/processed/DATA_avg_woSC_pr_{session}_{LIMB}_limb.csv'
  3210. data_sub_pr_path = f'../data/processed/data_single_sub_woSC_pr_{session}_{LIMB}_limb.pkl'
  3211. with open(file_path, 'rb') as file:
  3212. data_input_m2 = pickle.load(file)
  3213. DATA_avg_m2 = pd.read_csv(data_avg_path)
  3214. with open(data_sub_path, 'rb') as file:
  3215. data_single_sub_m2 = pickle.load(file)
  3216. DATA_avg_pr_m2 = pd.read_csv(data_avg_pr_path)
  3217. with open(data_sub_pr_path, 'rb') as file:
  3218. data_single_sub_pr_m2 = pickle.load(file)
  3219. #--------------------------------------------------------------------------------------------
  3220. #------------------ concatenated all sessions data -------------------------------
  3221. #-------------------------------------------------------------------------------------------
  3222. df1 = zscore(data_single_sub_auf['ICallsub_w'], nan_policy='omit')
  3223. df2 = zscore(data_single_sub_zu['ICallsub_w'], nan_policy='omit')
  3224. df3 = zscore(data_single_sub_m1['ICallsub_w'], nan_policy='omit')
  3225. df4 = zscore(data_single_sub_m2['ICallsub_w'], nan_policy='omit')
  3226. ICallsub_allsessions = np.hstack((df1, df2, df3, df4))
  3227. #ICallsub_allsessions = df3
  3228. ICallsub_allsessions = pd.DataFrame(ICallsub_allsessions)
  3229. df1 = zscore(data_single_sub_pr_auf['degallsub_w'], nan_policy='omit')
  3230. df2 = zscore(data_single_sub_pr_zu['degallsub_w'], nan_policy='omit')
  3231. df3 = zscore(data_single_sub_pr_m1['degallsub_w'], nan_policy='omit')
  3232. df4 = zscore(data_single_sub_pr_m2['degallsub_w'], nan_policy='omit')
  3233. degallsub_allsessions = np.hstack((df1, df2, df3, df4))
  3234. #degallsub_allsessions = df3
  3235. degallsub_allsessions = pd.DataFrame(degallsub_allsessions)
  3236. df1 = zscore(data_input_auf['edata_medianallsub'], nan_policy='omit')
  3237. df2 = zscore(data_input_zu['edata_medianallsub'], nan_policy='omit')
  3238. df3 = zscore(data_input_m1['edata_medianallsub'], nan_policy='omit')
  3239. df4 = zscore(data_input_m2['edata_medianallsub'], nan_policy='omit')
  3240. edata_allsub_allsessions = np.hstack((df1, df2, df3, df4))
  3241. #edata_allsub_allsessions = df3
  3242. edata_allsub_allsessions = pd.DataFrame(edata_allsub_allsessions)
  3243. ICallsub_allsessions_avg = np.nanmean(ICallsub_allsessions, axis = 1)
  3244. degallsub_allsessions_avg = np.nanmean(degallsub_allsessions, axis = 1)
  3245. edata_allsub_allsessions_avg = np.nanmean(edata_allsub_allsessions, axis = 1)
  3246. #--------------------------------------------------------------------------------------------
  3247. #------------------ concatenated all sessions data -------------------------------
  3248. #-------------------------------------------------------------------------------------------
  3249. IC = ICallsub_allsessions_avg
  3250. DC = degallsub_allsessions_avg
  3251. CMRglc = edata_allsub_allsessions_avg
  3252. IC = np.array(IC).flatten()
  3253. DC = np.array(DC).flatten()
  3254. CMRglc = np.array(CMRglc).flatten()
  3255. alldata_avg = pd.DataFrame({'IC':IC, 'DC':DC, 'pet':CMRglc})
  3256. r_IC_CMRglc,p_IC_CMRglc = pcor(IC,CMRglc)
  3257. print('correlation MwC and CMRglc allsession datasets',r_IC_CMRglc )
  3258. r_DC_CMRglc , p_DC_CMRglc= pcor(DC,CMRglc)
  3259. print('correlation DC and CMRglc allsession datasets',r_DC_CMRglc)
  3260. r_IC_DC , p_IC_DC = pcor(IC,DC)
  3261. print('correlation MwC and DC allsession datasets',r_IC_DC)
  3262. sub_size = np.size(edata_allsub_allsessions, axis =1)
  3263. corr_IC_E_allsub = np.zeros((sub_size))
  3264. p_IC_E_allsub = np.zeros((sub_size))
  3265. for j in range(sub_size):
  3266. corr_IC_E_allsub[j], p_IC_E_allsub[j] = pcor(edata_allsub_allsessions.iloc[:,j], ICallsub_allsessions.iloc[:,j])
  3267. print('min p-val in subject level data:',p_IC_E_allsub.min())
  3268. print('max p-val in subject level data:',p_IC_E_allsub.max())
  3269. # # Load data
  3270. DC = degallsub_allsessions_avg
  3271. MwC = ICallsub_allsessions_avg
  3272. CMRglc = edata_allsub_allsessions_avg
  3273. # Flatten arrays
  3274. MwC = np.array(MwC).flatten()
  3275. DC = np.array(DC).flatten()
  3276. CMRglc = np.array(CMRglc).flatten()
  3277. # Create dataframe
  3278. df = pd.DataFrame({"MwC": MwC, "DC": DC, "CMRglc": CMRglc})
  3279. # Model 1: CMRglc ~ MCC (Baseline model)
  3280. X1 = sm.add_constant(df["MwC"]) # Add intercept
  3281. model1 = sm.OLS(df["CMRglc"], X1).fit()
  3282. # Model 2: CMRglc ~ MCC + DC (Full model)
  3283. X2 = sm.add_constant(df[["MwC", "DC"]]) # Add intercept
  3284. model2 = sm.OLS(df["CMRglc"], X2).fit()
  3285. # Print Model Summaries
  3286. print("\n### Model 1: CMRglc ~ MwC ###")
  3287. print(model1.summary())
  3288. print("\n### Model 2: CMRglc ~ MwC + DC ###")
  3289. print(model2.summary())
  3290. # Compare R² values
  3291. r2_model1 = model1.rsquared
  3292. r2_model2 = model2.rsquared
  3293. print(f"\nR² for Model 1 (MwC only): {r2_model1:.4f}")
  3294. print(f"R² for Model 2 (MwC + DC): {r2_model2:.4f}")
  3295. # ANOVA Comparison (F-test)
  3296. anova_results = sm.stats.anova_lm(model1, model2)
  3297. anova_p_value = anova_results["Pr(>F)"][1]
  3298. print(f"\nANOVA F-test p-value: {anova_p_value:.4f}")
  3299. # Interpretation
  3300. print(anova_results)
  3301. if anova_p_value < 0.01:
  3302. print("✅ Adding DC significantly improves the model. Both MwC and DC together explain more variance in CMRglc.")
  3303. else:
  3304. print("❌ Adding DC does not significantly improve the model over MwC alone.")
  3305. # %% [markdown]
  3306. # ## Steiger test DC vs MCC
  3307. # %%
  3308. n = 45
  3309. z_score, p_value = steiger_z_test(r_IC_CMRglc, r_DC_CMRglc, r_IC_DC, n)
  3310. print("steiger:", z_score, p_value)

Figures_codes.ipynb at commit 36f1937, under MIT · at the source

Overview

Authors: Mahnaz Ashrafi1, Laura Fraticelli1,2, Gabriel Castrillón1,2,3, Valentin Riedl1,2
  1. Department of Neuroradiology, University Hospital TUM Klinikum, Technical University of Munich, Munich 81675, Germany
  2. Department of Neuroradiology, Universitätsklinikum, Friedrich-Alexander-University Erlangen-Nuernberg, Erlangen 91054, Germany
  3. Research Group in Medical Imaging, SURA Ayudas Diagnósticas, Medellín 6CQ4+M4, Colombia
Dates: received 4 November 2025; accepted 11 May 2026; published online 22 June 2026; in print 30 June 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1073/pnas.2531706123 · PMID 42330267 · PMCID PMC13321360 · OpenAlex W4414757148
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: PET / SPECT (modality), human (organism), other condition (population), cellular / molecular (subfield)
Methods: Spectral & time-frequency, Connectivity, Statistics, Machine learning, Preprocessing, Graphs, fMRI & imaging, Smoothing, state filtering, decompositions
Keywords: brain energy metabolism, brain connectome, synaptic integration, neurodegeneration
MeSH: Brain*, Connectome*, Neurodegenerative Diseases*, Synapses*, Energy Metabolism, Humans, Magnetic Resonance Imaging, Nerve Net, Positron-Emission Tomography (* major topic)
Journal subjects: Biological Sciences, Neuroscience
Topic: Mitochondrial Function and Pathology (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: European Research Council (759659)
Citations: cited by 1 paper (Europe PMC); 77 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repositories

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

SarahMorgan/Morphometric_Similarity_SZ

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 9134abfbc773c57a3a91b96612a7c8fa5969732b, 8 May 2019
Size: 7 files, 0 scripts
Software Heritage: not archived
Found in: “Data, Materials, and Software Availability”
Holds: README, license file
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
2 files

NeuroenergeticsLab/metabolism_weighted_centrality

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 36f1937bd610d762f1b92358c36158550f08e1d3, 8 June 2026
Languages: Python (5), Jupyter (3)
Size: 159 files, 8 scripts
Software Heritage: not archived
Found in: “Data, Materials, and Software Availability”
Holds: README, license file, environment (environment.yml, requirements.txt, setup.py), documentation, 3 notebooks
Not found: CITATION.cff, tests, continuous integration
Tools: Plotly (3 files), SciPy (3 files), BrainSMASH (2 files), igraph (2 files), Matplotlib (2 files), NetworkX (2 files), NiBabel (2 files), NumPy (2 files), pandas (2 files), statsmodels (2 files), Nilearn (1 file), scikit-learn (1 file), seaborn (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
10 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:

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

Datasets cited

Code and data availability statement

The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1073/pnas.2531706123.

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, issue, pages, dates, 4 authors, 4 keywords, 9 MeSH terms, 1 funder, 72 references.

Cite

This paper

Ashrafi, M., Fraticelli, L., Castrillón, G., & Riedl, V. (2026). Metabolism-weighted brain connectome reveals synaptic integration and vulnerability to neurodegeneration. Proceedings of the National Academy of Sciences of the United States of America, 123(26), e2531706123. https://doi.org/10.1073/pnas.2531706123

BibTeX

@article{ashrafi2026metabolism,
author = {Ashrafi, Mahnaz and Fraticelli, Laura and Castrillón, Gabriel and Riedl, Valentin},
title = {{Metabolism-weighted brain connectome reveals synaptic integration and vulnerability to neurodegeneration}},
journal = {Proceedings of the National Academy of Sciences of the United States of America},
year = {2026},
month = jun,
volume = {123},
number = {26},
pages = {e2531706123},
publisher = {National Academy of Sciences},
issn = {0027-8424},
doi = {10.1073/pnas.2531706123},
url = {https://doi.org/10.1073/pnas.2531706123},
pmid = {42330267},
pmcid = {PMC13321360}
}

RIS

TY - JOUR
AU - Ashrafi, Mahnaz
AU - Fraticelli, Laura
AU - Castrillón, Gabriel
AU - Riedl, Valentin
TI - Metabolism-weighted brain connectome reveals synaptic integration and vulnerability to neurodegeneration
T2 - Proceedings of the National Academy of Sciences of the United States of America
J2 - Proc Natl Acad Sci U S A
PY - 2026
DA - 2026/06/22
VL - 123
IS - 26
SP - e2531706123
SN - 0027-8424
PB - National Academy of Sciences
DO - 10.1073/pnas.2531706123
UR - https://doi.org/10.1073/pnas.2531706123
LA - en
ER -

CSL-JSON

{
"id": "10.1073/pnas.2531706123",
"type": "article-journal",
"title": "Metabolism-weighted brain connectome reveals synaptic integration and vulnerability to neurodegeneration",
"container-title": "Proceedings of the National Academy of Sciences of the United States of America",
"author": [
{
"family": "Ashrafi",
"given": "Mahnaz"
},
{
"family": "Fraticelli",
"given": "Laura"
},
{
"family": "Castrillón",
"given": "Gabriel"
},
{
"family": "Riedl",
"given": "Valentin"
}
],
"container-title-short": "Proc Natl Acad Sci U S A",
"volume": "123",
"issue": "26",
"page": "e2531706123",
"DOI": "10.1073/pnas.2531706123",
"PMID": "42330267",
"PMCID": "PMC13321360",
"ISSN": "0027-8424",
"publisher": "National Academy of Sciences",
"URL": "https://doi.org/10.1073/pnas.2531706123",
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
22
]
]
}
}

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/s42003-025-09444-3 [code]
Decoupling of neurophysiological activity from structure mirrors global microarchitectural and neuromodulatory trends.
Journal: Communications biology
In common: Nilearn, NiBabel, scikit-learn, 4 other tools, cellular / molecular, 11 references
[2] doi:10.1186/s12916-026-04903-y [code]
Structural connectome architecture and biological vulnerability shape cortical atrophy in cocaine use disorder.
Journal: BMC medicine
In common: Nilearn, statsmodels, seaborn, 5 other tools, other condition, 9 references
[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, Nilearn, NiBabel, 6 other tools, 6 references
[4] doi:10.1162/imag.a.1275 [code]
Glucose metabolism echoes long-range temporal correlations in the human brain.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: BrainSMASH, NiBabel, scikit-learn, 4 other tools, PET / SPECT, 6 references
[5] doi:10.1038/s41467-026-75959-w [code]
Charting higher-order models of brain function beyond pairwise interactions.
Journal: Nature communications
In common: NetworkX, Nilearn, statsmodels, 7 other tools, 6 references
[6] doi:10.1038/s41467-026-71270-w [code]
Spatiotemporal dynamics of the human cortical functional hierarchy across the lifespan.
Journal: Nature communications
In common: NetworkX, Nilearn, NiBabel, 6 other tools, 6 references
[7] doi:10.1186/s12916-026-04978-7 [code]
Mapping shared and specific cortical after-effects of repetitive TMS on brain function.
Journal: BMC medicine
In common: BrainSMASH, Nilearn, NiBabel, 5 other tools, 5 references
[8] doi:10.1038/s41398-026-03965-z [code]
Disentangling individual heterogeneity reveals robust network and molecular signatures of major depressive disorder with suicidal ideation.
Journal: Translational psychiatry
In common: NetworkX, statsmodels, NiBabel, 6 other tools, cellular / molecular, 5 references
[9] doi:10.7554/elife.103097 [code]
Canonical neurodevelopmental trajectories of structural and functional manifolds.
Journal: eLife
In common: Nilearn, Plotly, statsmodels, 5 other tools, 6 references
[10] doi:10.1038/s41467-026-76812-w [code]
Assessing molecular, cellular and transcriptomic bases of laminar perfusion and cytoarchitecture coupling in the human cortex.
Journal: Nature communications
In common: Nilearn, NiBabel, scikit-learn, 4 other tools, cellular / molecular, 6 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.