OSCR

A functional connectome identifies vulnerability to cognitive decline and Alzheimer’s disease progression

Code ↔ Paper

3 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 3 matches
  1. [1] § MATERIALS AND METHODS › Neuropsychological assessments ↔ clustering.py, lines 1478 to 1533 · score 0.90 · CFT VEG, RAVLT Immediate, RAVLT Learning, Forgetting, bills, events · Report a mismatch
  2. [2] § MATERIALS AND METHODS › Classification between SA and AD ↔ SA_AD_classification.py, lines 568 to 628 · score 0.58 · AD classification, L1, penalty, probabilities, AUC, accuracy · Report a mismatch
  3. [3] § MATERIALS AND METHODS › Superager definition ↔ clustering.py, lines 1478 to 1533 · score 0.55 · CFT VEG, vegetable, delayed, TMT, RAVLT, animal · Report a mismatch

Paper

Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 1,691 lines · 97 KB · no license · 2 matches

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Mon Feb 19 00:07:12 2024
  4. @author: 99488
  5. """
  6. '''
  7. result with age corrected subjects from adni, then cross validation in subject level were obtained, combat all subjects
  8. '''
  9. import os
  10. from arc_harmonization import FoldCombat, load_adni_calibration, participant_scores
  11. import pandas as pd
  12. import numpy as np
  13. import scipy.io as sio
  14. from pathlib import Path
  15. from bids.layout import parse_file_entities
  16. import sys
  17. sys.path.append(r'F:\OPT\research\fMRI\utils_for_all')
  18. from common_utils import read_singal_fmri_ts, get_fc, t_test, keep_triangle_half, sens_spec, setup_seed, \
  19. vector_to_matrix, heatmap, get_net_net_connect, diverge_map_unipolar_colore, cohen_d
  20. from sklearn.preprocessing import StandardScaler, OneHotEncoder
  21. from sklearn.model_selection import StratifiedKFold
  22. from sklearn.utils.class_weight import compute_sample_weight
  23. from sklearn.svm import LinearSVC, SVC, OneClassSVM
  24. from sklearn.metrics import accuracy_score, r2_score, auc, roc_curve, roc_auc_score
  25. from sklearn.ensemble import RandomForestClassifier, IsolationForest
  26. import xgboost as xgb
  27. from mrmr import mrmr_classif
  28. import matplotlib.pyplot as plt
  29. from sklearn.impute import SimpleImputer
  30. import copy
  31. from scipy.stats import pearsonr, chi2_contingency, shapiro, kstest, iqr, ranksums, kendalltau, f_oneway, kruskal, kendalltau, spearmanr
  32. import matplotlib
  33. import seaborn as sns
  34. from matplotlib import cm
  35. from matplotlib.colors import ListedColormap, LinearSegmentedColormap
  36. from collections import namedtuple, OrderedDict
  37. from matplotlib import colors as mcolors
  38. from statsmodels.stats.multitest import multipletests
  39. import statsmodels.api as sm
  40. from statsmodels.stats.anova import anova_lm
  41. from sklearn.linear_model import LinearRegression
  42. from statsmodels.formula.api import ols
  43. font2 = {'family': 'Tahoma', 'weight': 'bold', 'size': 30}
  44. matplotlib.rc('font', **font2)
  45. setup_seed(6)
  46. Color = namedtuple('RGB', 'red, green, blue')
  47. colors = {} # dict of colors
  48. class RGB(Color):
  49. def hex_format(self):
  50. return '#{:02X}{:02X}{:02X}'.format(self.red, self.green, self.blue)
  51. # Color Contants
  52. red = RGB(0.941, 0.502, 0.498)
  53. blue = RGB(0.388, 0.584, 0.933)
  54. def make_colormap(seq):
  55. """Return a LinearSegmentedColormap
  56. seq: a sequence of floats and RGB-tuples. The floats should be increasing
  57. and in the interval (0,1).
  58. """
  59. seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
  60. cdict = {'red': [], 'green': [], 'blue': []}
  61. for i, item in enumerate(seq):
  62. if isinstance(item, float):
  63. r1, g1, b1 = seq[i - 1]
  64. r2, g2, b2 = seq[i + 1]
  65. cdict['red'].append([item, r1, r2])
  66. cdict['green'].append([item, g1, g2])
  67. cdict['blue'].append([item, b1, b2])
  68. return mcolors.LinearSegmentedColormap('CustomMap', cdict)
  69. def diverge_map(high=(0.565, 0.392, 0.173), low=(0.094, 0.310, 0.635)):
  70. '''
  71. low and high are colors that will be used for the two
  72. ends of the spectrum. they can be either color strings
  73. or rgb color tuples
  74. '''
  75. c = mcolors.ColorConverter().to_rgb
  76. if isinstance(low, str): low = c(low)
  77. if isinstance(high, str): high = c(high)
  78. return make_colormap([low, c('white'), 0.5, c('white'), high])
  79. # ---- Load cohort inputs (AD=1, SA=0, CN=2, MCI=3) ----
  80. info = sio.loadmat(r'F:\PHD\learning\project\super_age\more_sub\SA_defined_ricado\superage_data_adni.mat')
  81. sa_dem_fc_adni = info['fc_sa_dem']
  82. sa_dem_dx_adni = np.squeeze(info['dx_sa_dem'])
  83. sa_dem_age_adni = np.squeeze(info['age_sa_dem'])
  84. sa_dem_sex_adni = np.squeeze(info['sex_sa_dem'])
  85. sa_dem_sex_adni = np.array([2 if sex == 'Female' else 1 for sex in sa_dem_sex_adni])
  86. sa_dem_sub_adni = np.squeeze(info['sub_id_sa_dem'])
  87. sa_dem_sess_adni = np.squeeze(info['sess_sa_dem'])
  88. df=pd.DataFrame(np.c_[sa_dem_sub_adni, sa_dem_sess_adni],columns=['sub','sess'])
  89. df['sub_sess']=df['sub']+'_'+df['sess']
  90. sa_dem_sub_sess_adni = df['sub_sess'].values
  91. half_fc_adni = keep_triangle_half(sa_dem_fc_adni.shape[1] * (sa_dem_fc_adni.shape[1]-1)//2, sa_dem_fc_adni.shape[0], sa_dem_fc_adni)
  92. all_fc_adni = info['adni_fc_all']
  93. all_dx_adni = np.squeeze(info['adni_dx_all'])
  94. all_age_adni = np.squeeze(info['adni_age_all'])
  95. all_sex_adni = np.squeeze(info['adni_sex_all'])
  96. # all_sex_adni = np.array([2 if sex == 'Female' else 1 for sex in all_sex_adni])
  97. all_sub_adni = np.squeeze(info['adni_sub_all'])
  98. all_sess_adni = np.squeeze(info['adni_sess_all'])
  99. other_adni_sub = np.setdiff1d(all_sub_adni, sa_dem_sub_adni)
  100. other_fc_adni = []
  101. other_dx_adni = []
  102. other_age_adni = []
  103. other_sex_adni = []
  104. other_sess_adni = []
  105. other_sub_adni = []
  106. for i,sub in enumerate(other_adni_sub):
  107. other_fc_adni.extend(list(all_fc_adni[all_sub_adni==sub]))
  108. other_dx_adni.extend(list(all_dx_adni[all_sub_adni==sub]))
  109. other_age_adni.extend(list(all_age_adni[all_sub_adni==sub]))
  110. other_sex_adni.extend(list(all_sex_adni[all_sub_adni==sub]))
  111. other_sess_adni.extend(list(all_sess_adni[all_sub_adni==sub]))
  112. other_sub_adni.extend(list(all_sub_adni[all_sub_adni==sub]))
  113. other_fc_adni = np.array(other_fc_adni)
  114. other_dx_adni = np.array(other_dx_adni)
  115. other_age_adni = np.array(other_age_adni)
  116. other_sex_adni = np.array(other_sex_adni)
  117. other_sess_adni = np.array(other_sess_adni)
  118. other_sub_adni = np.array(other_sub_adni)
  119. low_qua_fc_idx = np.where(np.isnan(np.sum(np.sum(other_fc_adni,-1),-1)))[0]
  120. other_fc_adni = np.delete(other_fc_adni, low_qua_fc_idx, 0)
  121. other_dx_adni = np.delete(other_dx_adni, low_qua_fc_idx, 0)
  122. other_age_adni = np.delete(other_age_adni, low_qua_fc_idx, 0)
  123. other_sex_adni = np.delete(other_sex_adni, low_qua_fc_idx, 0)
  124. other_sess_adni = np.delete(other_sess_adni, low_qua_fc_idx, 0)
  125. other_sub_adni = np.delete(other_sub_adni, low_qua_fc_idx, 0)
  126. df=pd.DataFrame(np.c_[other_sub_adni, other_sess_adni],columns=['sub','sess'])
  127. df['sub_sess']=df['sub']+'_'+df['sess']
  128. other_sub_sess_adni = df['sub_sess'].values
  129. for i in range(len(other_sex_adni)):
  130. if 'F' in other_sex_adni[i]:
  131. other_sex_adni[i] = 2
  132. elif 'M' in other_sex_adni[i]:
  133. other_sex_adni[i] = 1
  134. if 'CN' in other_dx_adni[i]:
  135. other_dx_adni[i] = 2
  136. elif 'MCI' in other_dx_adni[i]:
  137. other_dx_adni[i] = 3
  138. elif 'Dementia' in other_dx_adni[i]:
  139. other_dx_adni[i] = 1
  140. other_dx_adni = other_dx_adni.astype(float)
  141. other_sex_adni = other_sex_adni.astype(float)
  142. info_oas = sio.loadmat(r'F:\PHD\learning\project\super_age\more_sub\SA_defined_ricado\superage_data_oas_dem.mat')
  143. sa_dem_fc_oas = info_oas['multi_run_fcs_sa_dem']
  144. sa_dem_dx_oas = np.squeeze(info_oas['multi_run_dx_sa_dem'])
  145. sa_dem_sub_oas_ = np.squeeze(info_oas['multi_run_subs_sa_dem'])
  146. sa_dem_sess_oas = np.squeeze(info_oas['multi_run_sess_sa_dem'])
  147. all_pcd_oas = np.squeeze(info_oas['multi_run_pcd_all'])
  148. sa_dem_sub_oas = pd.Series(sa_dem_sub_oas_).str.cat(pd.Series(sa_dem_sess_oas), sep = '_').values
  149. sex_oas = np.squeeze(info_oas['sex_sa_dem'])
  150. pcd_oas = info_oas['pcd_sa_dem']
  151. sess_oas = info_oas['sess_sa_dem']
  152. age_oas = pcd_oas[:,2].astype(float).squeeze()
  153. sub_oas = pcd_oas[:,0]
  154. sub_oas = np.array([sub[0].split('_')[0] for sub in sub_oas])
  155. oasis_path = r'E:\PHD\learning\research\AD\data\OASIS3'
  156. oasis_demo = pd.read_csv(os.path.join(oasis_path, 'UDS-A2-InformatDemos.csv'))
  157. oasis_demo2 = pd.read_csv(os.path.join(oasis_path, 'OASIS3_UDSa2_cs_demo.csv'))
  158. oasis_demo_sub = oasis_demo['Subject']
  159. oasis_demo_sub2 = oasis_demo2['OASISID']
  160. sa_dem_sex_oas = []
  161. sa_dem_age_oas = []
  162. for i, sub in enumerate(sa_dem_sub_oas_):
  163. # sa_dem_sex_oas.append(sex_oas[(sub_oas==sub)&(sess_oas == sa_dem_sess_oas[i])])
  164. if sum(oasis_demo_sub == sub) >= 1:
  165. sa_dem_sex_oas.append(oasis_demo['INSEX'][oasis_demo_sub == sub].values[0])
  166. else:
  167. if sum(oasis_demo_sub2 == sub) >= 1:
  168. sa_dem_sex_oas.append(oasis_demo2['INSEX'][oasis_demo_sub2 == sub].values[0])
  169. sa_dem_age_oas.append(age_oas[(sub_oas==sub)&(sess_oas == sa_dem_sess_oas[i])])
  170. sa_dem_sex_oas = np.array(sa_dem_sex_oas).squeeze() # female: 2; male: 1
  171. sa_dem_age_oas = np.array(sa_dem_age_oas).squeeze()
  172. all_fc_oas = info_oas['multi_run_fcs_all']
  173. all_sub_oas = np.squeeze(info_oas['multi_run_subs_all'])
  174. all_sess_oas = np.squeeze(info_oas['multi_run_sess_all'])
  175. all_pcd_oas = np.squeeze(info_oas['multi_run_pcd_all'])
  176. all_sex_oas = np.squeeze(info_oas['multi_run_sex_all'])
  177. all_age_oas = all_pcd_oas[:,2].astype(float).squeeze()
  178. all_dx_oas = all_pcd_oas[:,1]
  179. other_oas_sub = np.setdiff1d(all_sub_oas, sa_dem_sub_oas_)
  180. other_fc_oas = []
  181. other_dx_oas = []
  182. other_age_oas = []
  183. other_sex_oas = []
  184. other_sess_oas = []
  185. other_sub_oas_multises = []
  186. for i,sub in enumerate(other_oas_sub):
  187. other_fc_oas.extend(list(all_fc_oas[all_sub_oas==sub]))
  188. other_dx_oas.extend([s[0][0] if isinstance(s[0], np.ndarray) else s[0] for s in all_dx_oas[all_sub_oas==sub]])
  189. other_age_oas.extend(list(all_age_oas[all_sub_oas==sub]))
  190. other_sex_oas.extend(list(all_sex_oas[all_sub_oas==sub]))
  191. other_sess_oas.extend(list(all_sess_oas[all_sub_oas==sub]))
  192. other_sub_oas_multises.extend(list(all_sub_oas[all_sub_oas==sub]))
  193. other_fc_oas = np.array(other_fc_oas)
  194. other_dx_oas = np.array(other_dx_oas)
  195. other_age_oas = np.array(other_age_oas)
  196. other_sex_oas = np.array(other_sex_oas)
  197. other_sess_oas = np.array(other_sess_oas)
  198. other_sub_oas_multises = np.array(other_sub_oas_multises)
  199. mask_nc = pd.Series(other_dx_oas).str.contains('normal', regex=False)
  200. mask_ad = (pd.Series(other_dx_oas).str.contains('AD', regex=False)) |(pd.Series(other_dx_oas).str.contains('DAT', regex=False)) | \
  201. (pd.Series(other_dx_oas)=='Frontotemporal demt. prim') | (pd.Series(other_dx_oas)=='DLBD, primary') | (pd.Series(other_dx_oas).str.contains('primary', regex=False)) | \
  202. (pd.Series(other_dx_oas)=='Vascular Demt, secondary') | (pd.Series(other_dx_oas)=='uncertain dementia') | \
  203. (pd.Series(other_dx_oas)=='uncertain, possible NON AD dem') | (pd.Series(other_dx_oas)=='DLBD, primary')
  204. mask_mci = pd.Series(other_dx_oas).str.contains('0.5 in memory', regex=False) | (pd.Series(other_dx_oas)=='Unc: ques. Impairment')
  205. other_dx_oas_encode = np.zeros((len(other_dx_oas)))
  206. other_dx_oas_encode[mask_nc] = 2
  207. other_dx_oas_encode[mask_mci] = 3
  208. other_dx_oas_encode[mask_ad] = 1
  209. low_qua_fc_idx = np.where(np.isnan(np.sum(np.sum(other_fc_oas,-1),-1)))[0]
  210. other_fc_oas = np.delete(other_fc_oas, low_qua_fc_idx, 0)
  211. other_dx_oas_encode_raw = np.delete(other_dx_oas_encode, low_qua_fc_idx, 0)
  212. other_age_oas_raw = np.delete(other_age_oas, low_qua_fc_idx, 0)
  213. other_sex_oas_raw = np.delete(other_sex_oas, low_qua_fc_idx, 0)
  214. other_sess_oas_raw = np.delete(other_sess_oas, low_qua_fc_idx, 0)
  215. other_sub_oas_multises = np.delete(other_sub_oas_multises, low_qua_fc_idx, 0)
  216. half_fc_oas_sa_dem = keep_triangle_half(sa_dem_fc_oas.shape[1] * (sa_dem_fc_oas.shape[1]-1)//2, sa_dem_fc_oas.shape[0], sa_dem_fc_oas)
  217. half_fc_oas_other = keep_triangle_half(other_fc_oas.shape[1] * (other_fc_oas.shape[1]-1)//2, other_fc_oas.shape[0], other_fc_oas)
  218. half_fc_adni_other = keep_triangle_half(other_fc_adni.shape[1] * (other_fc_adni.shape[1]-1)//2, other_fc_adni.shape[0], other_fc_adni)
  219. info_habs = sio.loadmat(r'F:\PHD\learning\project\super_age\more_sub\SA_defined_ricado\superage_data_habs.mat')
  220. sa_pcd_habs = info_habs['multi_run_pcd_sa'].squeeze()
  221. sa_fc_habs = info_habs['multi_run_fcs_sa'][:,:100,:100]
  222. sa_sub_sess_habs = np.array([sub[0] for sub in sa_pcd_habs[:,-1].squeeze()])
  223. sa_sex_habs = np.array([2 if sex[0] == 'F' else 1 for sex in sa_pcd_habs[:,59]])
  224. sa_age_habs = np.array([sub[0][0] for sub in sa_pcd_habs[:,58].squeeze()])
  225. sa_sex_habs = sa_sex_habs.astype(float)
  226. sa_dx_habs = np.zeros((len(sa_sex_habs)))
  227. half_fc_habs = keep_triangle_half(sa_fc_habs.shape[1] * (sa_fc_habs.shape[1]-1)//2, sa_fc_habs.shape[0], sa_fc_habs)
  228. sa_sub_habs = pd.Series(sa_sub_sess_habs).str.split('_', expand = True)[0]
  229. habs_pcd_all = info_habs['multi_run_pcd_all'].squeeze()
  230. habs_fc_all = info_habs['multi_run_fc_all'][:,:100,:100]
  231. habs_sub_sess_all = np.array([sub[0] for sub in habs_pcd_all[:,-1].squeeze()])
  232. habs_sex_all = np.array([2 if sex[0] == 'F' else 1 for sex in habs_pcd_all[:,59]])
  233. habs_age_all = np.array([sub[0][0] for sub in habs_pcd_all[:,58].squeeze()])
  234. habs_sex_all = habs_sex_all.astype(float)
  235. habs_dx_all = np.array([sub[0] for sub in habs_pcd_all[:,67].squeeze()])
  236. habs_dx_all[habs_dx_all == 'CN'] = 2
  237. habs_dx_all[habs_dx_all == 'MCI'] = 3
  238. habs_dx_all[habs_dx_all == 'Dementia'] = 1
  239. habs_dx_all = habs_dx_all.astype(float)
  240. half_habs_fc_all = keep_triangle_half(habs_fc_all.shape[1] * (habs_fc_all.shape[1]-1)//2, habs_fc_all.shape[0], habs_fc_all)
  241. habs_sub_all = pd.Series(habs_sub_sess_all).str.split('_', expand = True)[0]
  242. other_habs_sub = np.unique(habs_sub_sess_all[~np.isin(np.asarray(habs_sub_all), np.asarray(sa_sub_habs))])
  243. other_fc_habs = []
  244. other_dx_habs = []
  245. other_age_habs = []
  246. other_sex_habs = []
  247. other_sub_sess_habs = []
  248. for i,sub in enumerate(other_habs_sub):
  249. other_fc_habs.extend(list(half_habs_fc_all[habs_sub_sess_all==sub]))
  250. other_dx_habs.extend(list(habs_dx_all[habs_sub_sess_all==sub]))
  251. other_age_habs.extend(list(habs_age_all[habs_sub_sess_all==sub]))
  252. other_sex_habs.extend(list(habs_sex_all[habs_sub_sess_all==sub]))
  253. other_sub_sess_habs.extend(list(habs_sub_sess_all[habs_sub_sess_all==sub]))
  254. other_fc_habs = np.array(other_fc_habs)
  255. other_dx_habs = np.array(other_dx_habs)
  256. other_age_habs = np.array(other_age_habs)
  257. other_sex_habs = np.array(other_sex_habs)
  258. other_sub_sess_habs = np.array(other_sub_sess_habs)
  259. half_fc_ind = np.r_[half_fc_oas_sa_dem, half_fc_habs]
  260. age_ind = np.r_[sa_dem_age_oas, sa_age_habs]
  261. sex_ind = np.r_[sa_dem_sex_oas, sa_sex_habs]
  262. dx_ind = np.r_[sa_dem_dx_oas, sa_dx_habs]
  263. sub_ind = np.r_[sa_dem_sub_oas, sa_sub_sess_habs]
  264. sub_ind_ = np.r_[sa_dem_sub_oas_, sa_sub_habs]
  265. site_ind = np.r_[np.zeros(len(sa_dem_sub_oas)), sa_dx_habs+20]
  266. # sub_ind is visit-level; the original subject IDs live in sub_ind_.
  267. participant_keys = np.array([f'{site}:{str(pid).strip()}' for site, pid in zip(site_ind, sub_ind_)])
  268. subject_used, uni_id = np.unique(participant_keys, return_index=True)
  269. if any(np.unique(dx_ind[participant_keys == person]).size != 1 for person in subject_used):
  270. raise ValueError('Anchor diagnosis changes across visits; verify anchor inclusion first')
  271. print('Counts of raw subjects: {}, superager: {}, dementia: {}'.format(len(set(sub_ind)), sum(dx_ind[uni_id]==0), sum(dx_ind[uni_id]==1)))
  272. print('Counts of used runs: {}, superager: {}, dementia: {}'.format(len(sub_ind), sum(dx_ind==0), sum(dx_ind==1)))
  273. scaler = StandardScaler()
  274. half_fc_adni = scaler.fit_transform(half_fc_adni.T).T
  275. half_fc_ind = scaler.fit_transform(half_fc_ind.T).T
  276. half_fc_oas_other = scaler.fit_transform(half_fc_oas_other.T).T
  277. half_fc_adni_other = scaler.fit_transform(half_fc_adni_other.T).T
  278. other_fc_habs = scaler.fit_transform(other_fc_habs.T).T
  279. df=pd.DataFrame(np.c_[other_sub_oas_multises, other_sess_oas_raw],columns=['sub','sess'])
  280. df['sub_sess']=df['sub']+'_'+df['sess']
  281. sub_sess_oas = df['sub_sess'].values
  282. sub_combine_uni_oas, uni_id_oas = np.unique(df['sub_sess'], return_index=True)
  283. #################averaging runs
  284. half_fc_oas_other_uni = []
  285. for i, sub in enumerate(sub_combine_uni_oas):
  286. mask = df['sub_sess'].values == sub
  287. half_fc_oas_other_uni.append(half_fc_oas_other[mask].mean(0))
  288. half_fc_oas_other_uni = np.array(half_fc_oas_other_uni)
  289. other_dx_oas_encode = other_dx_oas_encode_raw[uni_id_oas]
  290. other_age_oas = other_age_oas_raw[uni_id_oas]
  291. other_sex_oas = other_sex_oas_raw[uni_id_oas]
  292. #####################redefine MCI based on ADNI criteria
  293. oasis_sa_sub_sess_uniq, oasis_sa_sub_sess_idx, oasis_sa_sub_sess_idx_reverse = np.unique(sub_combine_uni_oas, return_index=True, return_inverse=True)
  294. oas_sess_info = sio.loadmat(r'F:\PHD\learning\project\super_age\sess_match_oas_all.mat')
  295. day_all = oas_sess_info['day']
  296. sess_all = oas_sess_info['sess']
  297. idx = np.argsort(sess_all)
  298. sess_all = sess_all[idx]
  299. day_all = pd.Series(day_all[idx]).str.split('d', expand = True).iloc[:,-1].astype(int)
  300. oas_pcd_info = sio.loadmat(r'E:\PHD\learning\research\AD\data\OASIS3\fMRIdata_OASIS3_struct.mat')
  301. tvar = oas_pcd_info['OASIS3_Phenotypic_struct']
  302. PCD_data = []
  303. pcd_keys = ['subjectID_Date', 'apoe', 'NPIQINF', 'NPIQINFX', 'DEL',
  304. 'DELSEV', 'HALL', 'HALLSEV', 'AGIT', 'AGITSEV', 'DEPD', 'DEPDSEV', 'ANX',
  305. 'ANXSEV', 'ELAT', 'ELATSEV', 'APA', 'APASEV', 'DISN', 'DISNSEV', 'IRR',
  306. 'IRRSEV', 'MOT', 'MOTSEV', 'NITE', 'NITESEV', 'APP', 'APPSEV', 'mmse',
  307. 'cdr', 'commun','homehobb', 'judgment', 'memory', 'orient', 'perscare', 'sumbox',
  308. 'DIGIF', 'DIGIB', 'ANIMALS', 'VEG', 'TRAILA', 'TRAILALI', 'TRAILB',
  309. 'TRAILBLI', 'WAIS', 'LOGIMEM', 'MEMUNITS', 'MEMTIME', 'BOSTON']
  310. for idx in range(len(tvar)):
  311. sub_data = []
  312. for name in pcd_keys:
  313. value = tvar[idx][0][name]
  314. for i in range(3):
  315. if isinstance(value, np.ndarray):
  316. try:
  317. value = value[0]
  318. except IndexError:
  319. if name == 'DX':
  320. value = 'nan'
  321. else:
  322. value = "error"
  323. else:
  324. if name == 'subjectID_Date' or name == 'dx1':
  325. value = str(value)
  326. sub_data.append(value)
  327. break
  328. PCD_data.append(sub_data)
  329. PCD_data = np.array(PCD_data)
  330. PCD_data[:,1] = pd.Series(PCD_data[:,1]).str.count('4')
  331. #update NPI 0 score
  332. for i in [5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27]:
  333. mask = PCD_data[:, i] == 'nan'
  334. PCD_data[np.isfinite(PCD_data[:,2].astype(float))&mask, i] = 0
  335. PCD_data[np.isfinite(PCD_data[:,2].astype(float))][:,[5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27]] = 0
  336. PCD_sub = np.array([sub[:8] for sub in PCD_data[:,0]])
  337. PCD_day = np.array([sub[10:] for sub in PCD_data[:,0]]).astype(int)
  338. PCD_sess = []
  339. day_min = []
  340. for da in PCD_day:
  341. mask = day_all==da
  342. if sum(mask) > 0:
  343. PCD_sess.append(sess_all[day_all==da][0])
  344. else:
  345. diff = day_all-da
  346. diff_min_id = np.argmin(abs(diff))
  347. diff_min = diff[diff_min_id]
  348. day_min.append(diff_min)
  349. PCD_sess.append(sess_all[diff_min_id])
  350. PCD_sess = np.array(PCD_sess)
  351. PCD_interest = []
  352. for sub_sess in oasis_sa_sub_sess_uniq:
  353. sub = sub_sess[:8]
  354. sess = sub_sess[9:]
  355. if sum((PCD_sub == sub) & (PCD_sess == sess))== 1:
  356. PCD_interest.append(PCD_data[:,np.r_[[1, 2, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25], np.arange(27,50)]][
  357. (PCD_sub == sub) & (PCD_sess == sess)].squeeze())
  358. elif sum((PCD_sub == sub) & (PCD_sess == sess))> 1:
  359. pcd = PCD_data[:,np.r_[[1, 2, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25], np.arange(27,50)]][
  360. (PCD_sub == sub) & (PCD_sess == sess)].squeeze()
  361. pcd_new = []
  362. for i in range(pcd.shape[-1]):
  363. info = pcd[:,i]
  364. if np.isnan(info.astype(float)).sum() == len(info):
  365. pcd_new.append(np.nan)
  366. else:
  367. pcd_new.append(info[~np.isnan(info.astype(float))][0].squeeze())
  368. PCD_interest.append(np.array(pcd_new))
  369. else:
  370. PCD_interest.append(np.array([np.nan for i in range(len(['apoe', 'NPIQINF', 'DELSEV', 'HALLSEV', 'AGITSEV', 'DEPDSEV',
  371. 'ANXSEV', 'ELATSEV', 'APASEV', 'DISNSEV', 'IRRSEV', 'MOTSEV', 'NITESEV',
  372. 'APPSEV', 'mmse', 'cdr', 'commun','homehobb', 'judgment', 'memory', 'orient', 'perscare', 'sumbox',
  373. 'DIGIF', 'DIGIB', 'ANIMALS', 'VEG', 'TRAILA', 'TRAILALI', 'TRAILB',
  374. 'TRAILBLI', 'WAIS', 'LOGIMEM', 'MEMUNITS', 'MEMTIME', 'BOSTON']))]))
  375. PCD_interest = np.array(PCD_interest)
  376. df=pd.DataFrame(np.c_[other_sub_adni, other_sess_adni],columns=['sub','sess'])
  377. df['sub_sess']=df['sub']+'_'+df['sess']
  378. sub_combine_uni, uni_id = np.unique(df['sub_sess'], return_index=True)
  379. half_fc_adni_other_uni = []
  380. for i, sub in enumerate(sub_combine_uni):
  381. mask = df['sub_sess'].values == sub
  382. half_fc_adni_other_uni.append(half_fc_adni_other[mask].mean(0))
  383. half_fc_adni_other_uni = np.array(half_fc_adni_other_uni)
  384. other_dx_adni = other_dx_adni[uni_id]
  385. other_sub_sess_adni = other_sub_sess_adni[uni_id]
  386. other_age_adni = other_age_adni[uni_id]
  387. other_age_adni[other_age_adni == 0] = np.nan
  388. other_sex_adni = other_sex_adni[uni_id]
  389. other_sub_adni = other_sub_adni[uni_id]
  390. other_sess_adni = other_sess_adni[uni_id]
  391. # Inputs to fold-local ComBat, after the original per-scan normalization.
  392. half_fc_adni_correct = half_fc_adni
  393. half_fc_adni_other_correct = half_fc_adni_other_uni
  394. half_fc_oas_other_correct = half_fc_oas_other_uni
  395. half_fc_habs_other_correct = other_fc_habs
  396. half_fc_adni_correct_all = np.r_[half_fc_adni_correct, half_fc_adni_other_correct]
  397. half_fc_adni_dx_all = np.r_[sa_dem_dx_adni, other_dx_adni]
  398. half_fc_adni_age_all = np.r_[sa_dem_age_adni, other_age_adni]
  399. half_fc_adni_sex_all = np.r_[sa_dem_sex_adni, other_sex_adni]
  400. half_fc_adni_sub_sess_all = np.r_[sa_dem_sub_sess_adni, other_sub_sess_adni]
  401. info_other_sa_define = sio.loadmat(r'F:\PHD\learning\project\super_age\more_sub\SA_defined_ricado\superage_data_adni_logicmem_based.mat')
  402. sa_dem_sub_adni_new_define = np.squeeze(info_other_sa_define['sub_id_sa_dem'])
  403. sa_dem_sess_adni_new_define = np.squeeze(info_other_sa_define['sess_sa_dem'])
  404. sa_dem_dx_adni_new_define = np.squeeze(info_other_sa_define['dx_sa_dem'])
  405. df=pd.DataFrame(np.c_[sa_dem_sub_adni_new_define, sa_dem_sess_adni_new_define],columns=['sub','sess'])
  406. df['sub_sess']=df['sub']+'_'+df['sess']
  407. sa_dem_sub_sess_adni_new_define = df['sub_sess'].values
  408. _, sa_adni_new_define_idx, sa_adni_idx = np.intersect1d(sa_dem_sub_sess_adni_new_define[sa_dem_dx_adni_new_define == 0], half_fc_adni_sub_sess_all[half_fc_adni_dx_all == 0], return_indices=True)
  409. sa_fc_adni_new_define = half_fc_adni_correct_all[half_fc_adni_dx_all == 0][sa_adni_idx]
  410. sa_sex_adni_new_define = half_fc_adni_sex_all[half_fc_adni_dx_all == 0][sa_adni_idx]
  411. sa_age_adni_new_define = half_fc_adni_age_all[half_fc_adni_dx_all == 0][sa_adni_idx]
  412. sa_sub_sess_adni_new_define = half_fc_adni_sub_sess_all[half_fc_adni_dx_all == 0][sa_adni_idx]
  413. dem_fc_adni_new_define = half_fc_adni_correct[sa_dem_dx_adni == 1]
  414. dem_sex_adni_new_define = sa_dem_sex_adni[sa_dem_dx_adni == 1]
  415. dem_age_adni_new_define = sa_dem_age_adni[sa_dem_dx_adni == 1]
  416. dem_sub_sess_adni_new_define = sa_dem_sub_sess_adni[sa_dem_dx_adni == 1]
  417. sa_dem_fc_adni_new_define = np.r_[dem_fc_adni_new_define, sa_fc_adni_new_define]
  418. sa_dem_sex_adni_new_define = np.r_[dem_sex_adni_new_define, sa_sex_adni_new_define]
  419. sa_dem_age_adni_new_define = np.r_[dem_age_adni_new_define, sa_age_adni_new_define]
  420. sa_dem_sub_sess_adni_new_define = np.r_[dem_sub_sess_adni_new_define, sa_sub_sess_adni_new_define]
  421. sa_dem_sub_adni_new_define = pd.Series(sa_dem_sub_sess_adni_new_define).str.split(' ', expand = True).iloc[:,0]
  422. sa_dem_dx_adni_new_define = np.r_[np.ones(len(dem_fc_adni_new_define)), np.zeros(len(sa_fc_adni_new_define))]
  423. ########################
  424. # sub_ind is visit-level; the original subject IDs live in sub_ind_.
  425. participant_keys = np.array([f'{site}:{str(pid).strip()}' for site, pid in zip(site_ind, sub_ind_)])
  426. subject_used, uni_id = np.unique(participant_keys, return_index=True)
  427. if any(np.unique(dx_ind[participant_keys == person]).size != 1 for person in subject_used):
  428. raise ValueError('Anchor diagnosis changes across visits; verify anchor inclusion first')
  429. dx_ind_uniq = dx_ind[uni_id]
  430. site_ind_uniq = site_ind[uni_id]
  431. site_ind_uniq[site_ind_uniq == 1] = 20
  432. # half_fc_adni_correct = copy.deepcopy(half_fc_adni)
  433. t_p_vector = np.zeros((4950, 2))
  434. for i in range(4950):
  435. t_p_vector[i, 0], t_p_vector[i, 1] = t_test(half_fc_ind[dx_ind == 1, i], half_fc_ind[dx_ind == 0, i], 0.05, False)
  436. weight_sys, _ = vector_to_matrix(t_p_vector[:,0])
  437. label_idx = np.arange(0,100,1)
  438. cbarlabel = 'Weights'
  439. plt.figure(figsize =(15,15))
  440. ax = plt.gca()
  441. im, cbar = heatmap(weight_sys.squeeze(), label_idx, ax=ax, cmap='RdBu_r', connect_type='roi',
  442. cbarlabel=cbarlabel, half_or_full = 'half', with_diag = True)
  443. folds = 10
  444. kf = StratifiedKFold(n_splits=folds, random_state=9, shuffle=True)
  445. perform = []
  446. perform_sub = []
  447. perform_oas = []
  448. perform_habs = []
  449. weights = []
  450. t_p_vector_all = []
  451. indep_pred_prob = []
  452. indep_performance_all = []
  453. indep_performance_logic = []
  454. indep_pred_prob_logic = []
  455. other_adni_pred_label = []
  456. other_oas_pred_label = []
  457. other_habs_pred_label = []
  458. # Auxiliary ADNI contrasts; descriptive, not a new fitted classifier.
  459. cn = half_fc_adni_other_correct[other_dx_adni == 2]
  460. ad = half_fc_adni_correct[sa_dem_dx_adni == 1]
  461. sa = half_fc_adni_correct[sa_dem_dx_adni == 0]
  462. half_fc_cn_dem_pair = np.r_[cn, ad]
  463. dx_cn_dem_pair = np.r_[np.zeros(len(cn)), np.ones(len(ad))]
  464. half_fc_cn_sa_pair = np.r_[cn, sa]
  465. dx_cn_sa_pair = np.r_[np.ones(len(cn)), np.zeros(len(sa))]
  466. indep_cn_dem_prob = []
  467. indep_cn_sa_prob = []
  468. # ---- Participant CV, fold harmonization, and external scoring ----
  469. adni_calibration = load_adni_calibration(np.r_[all_sub_adni, sa_dem_sub_adni], half_fc_ind.shape[1])
  470. for train_index, test_index in kf.split(dx_ind_uniq, dx_ind_uniq):
  471. tr_all_id = []
  472. for sub in subject_used[train_index]:
  473. tr_all_id.extend(list(np.where(participant_keys==sub)[0]))
  474. tr_all_id = np.array(tr_all_id)
  475. te_all_id = []
  476. for sub in subject_used[test_index]:
  477. te_all_id.extend(list(np.where(participant_keys==sub)[0]))
  478. te_all_id = np.array(te_all_id)
  479. if set(participant_keys[tr_all_id]) & set(participant_keys[te_all_id]):
  480. raise RuntimeError('Participant appears in train and test')
  481. te_subs = participant_keys[te_all_id]
  482. te_sub_unqiu, te_id = np.unique(te_subs, return_index=True)
  483. X_train = half_fc_ind[tr_all_id]
  484. X_test = half_fc_ind[te_all_id]
  485. y_train = dx_ind[tr_all_id]
  486. y_test = dx_ind[te_all_id]
  487. site_test = site_ind[te_all_id]
  488. site_train = site_ind[tr_all_id]
  489. site_test_te = site_test[te_id]
  490. idx = np.arange(len(X_train))
  491. np.random.default_rng(9 + len(weights)).shuffle(idx)
  492. site_train = site_train[idx]
  493. train_people = participant_keys[tr_all_id][idx]
  494. X_train = X_train[idx]
  495. y_train = y_train[idx]
  496. p_thre = 0.01
  497. people, inverse = np.unique(train_people, return_inverse=True)
  498. subject_x = np.stack([X_train[inverse == j].mean(axis=0) for j in range(len(people))])
  499. subject_y = np.array([y_train[inverse == j][0] for j in range(len(people))])
  500. person_sites = np.array([site_train[inverse == j][0] for j in range(len(people))])
  501. # The separate ADNI calibration set defines batch 2 in the shared space.
  502. combat = FoldCombat().fit(np.r_[subject_x, adni_calibration],
  503. np.r_[person_sites, np.full(len(adni_calibration), 2)])
  504. subject_x = combat.transform(subject_x, person_sites)
  505. X_train = combat.transform(X_train, site_train)
  506. X_test = combat.transform(X_test, site_test)
  507. def transform_cohort(fc, site):
  508. return scaler.transform(combat.transform(fc, np.full(len(fc), site)))
  509. scaler = StandardScaler().fit(subject_x)
  510. subject_x = scaler.transform(subject_x)
  511. X_train = scaler.transform(X_train)
  512. t_p_vector = np.zeros((4950, 2))
  513. for i in range(4950):
  514. t_p_vector[i, 0], t_p_vector[i, 1] = t_test(subject_x[subject_y==1, i], subject_x[subject_y==0, i], 0.05, False)
  515. t_p_vector_all.append(t_p_vector)
  516. X_train = X_train[:,t_p_vector[:,1]<=p_thre]
  517. # Preset common parameters; no tuning against external results.
  518. # dx arrays are float; bincount and indexing need integer labels.
  519. sample_weights = (1.0 / np.bincount(inverse)[inverse]
  520. / np.bincount(subject_y.astype(int), minlength=2)[y_train.astype(int)])
  521. sample_weights *= len(sample_weights) / sample_weights.sum()
  522. if X_train.shape[1] == 0:
  523. raise ValueError('No edges passed the training-only filter')
  524. clf = LinearSVC(penalty='l1', C=0.1, max_iter=20000, dual=False,
  525. random_state=9).fit(X_train, y_train, sample_weight=sample_weights)
  526. pred_tr = np.expand_dims(clf.predict(X_train), -1)
  527. weight = np.zeros((len(t_p_vector)))
  528. weight[t_p_vector[:,1]<=p_thre] = clf.coef_.squeeze()
  529. # weight[t_p_vector[:,1]<=p_thre] = clf.feature_importances_.squeeze()
  530. weights.append(weight.squeeze())
  531. X_test = scaler.transform(X_test)
  532. half_fc_adni_correct_ = transform_cohort(half_fc_adni_correct, 2)
  533. half_fc_adni_correct_logic_define_ = transform_cohort(sa_dem_fc_adni_new_define, 2)
  534. half_fc_adni_other_correct_ = transform_cohort(half_fc_adni_other_correct, 2)
  535. half_fc_adni_other_correct_ = half_fc_adni_other_correct_[:,t_p_vector[:,1]<=p_thre]
  536. pred_adni_other = clf.decision_function(half_fc_adni_other_correct_)
  537. other_adni_pred_label.append(pred_adni_other)
  538. half_fc_oas_other_correct_ = transform_cohort(half_fc_oas_other_correct, 0)
  539. half_fc_oas_other_correct_ = half_fc_oas_other_correct_[:,t_p_vector[:,1]<=p_thre]
  540. pred_oas_other = clf.decision_function(half_fc_oas_other_correct_)
  541. other_oas_pred_label.append(pred_oas_other)
  542. half_fc_habs_other_correct_ = transform_cohort(half_fc_habs_other_correct, 20)
  543. half_fc_habs_other_correct_ = half_fc_habs_other_correct_[:,t_p_vector[:,1]<=p_thre]
  544. pred_habs_other = clf.decision_function(half_fc_habs_other_correct_)
  545. other_habs_pred_label.append(pred_habs_other)
  546. X_test = X_test[:,t_p_vector[:,1]<=p_thre]
  547. predPROB_te = clf.decision_function(X_test)
  548. pred_test_uni = []
  549. predPROB_test_uni = []
  550. for te in te_sub_unqiu:
  551. predPROB = np.mean(predPROB_te[te_subs == te],0)
  552. predPROB_test_uni.append(predPROB)
  553. if predPROB>0:
  554. pred_test_uni.append(1)
  555. else:
  556. pred_test_uni.append(0)
  557. pred_test_uni = np.array(pred_test_uni)
  558. predPROB_test_uni = np.array(predPROB_test_uni)
  559. run_pred = (predPROB_te > 0).astype(int)
  560. sen, spe = sens_spec(run_pred, y_test)
  561. perform.append([accuracy_score(y_test, run_pred), sen, spe,
  562. roc_auc_score(y_test, predPROB_te)])
  563. subject_y, subject_margin = participant_scores(te_subs, y_test, predPROB_te)
  564. subject_pred = (subject_margin > 0).astype(int)
  565. sen, spe = sens_spec(subject_pred, subject_y)
  566. perform_sub.append([accuracy_score(subject_y, subject_pred), sen, spe,
  567. roc_auc_score(subject_y, subject_margin)])
  568. sen, spe = sens_spec(pred_test_uni[site_test_te==0], y_test[te_id][site_test_te==0])
  569. acc = accuracy_score(y_test[te_id][site_test_te==0],pred_test_uni[site_test_te==0])
  570. AUC = roc_auc_score(y_test[te_id][site_test_te==0], predPROB_test_uni[site_test_te==0])
  571. print('training acc oas: {}'.format(accuracy_score(y_train[site_train==0],pred_tr[site_train==0])))
  572. perform_oas.append([acc, sen, spe, AUC])
  573. acc = accuracy_score(y_test[te_id][site_test_te==20],pred_test_uni[site_test_te==20])
  574. print('training acc hasb: {}'.format(accuracy_score(y_train[site_train==20],pred_tr[site_train==20])))
  575. perform_habs.append(acc)
  576. #################independent test
  577. pred_ind = np.expand_dims(clf.predict(half_fc_adni_correct_[:,t_p_vector[:,1]<=p_thre]), -1)
  578. predPROB_ind = clf.decision_function(half_fc_adni_correct_[:,t_p_vector[:,1]<=p_thre])
  579. indep_pred_prob.append(predPROB_ind)
  580. sen, spe = sens_spec(pred_ind, sa_dem_dx_adni)
  581. acc = accuracy_score(sa_dem_dx_adni,pred_ind)
  582. AUC = roc_auc_score(sa_dem_dx_adni, np.array(predPROB_ind))
  583. indep_performance_all.append([acc, sen, spe, AUC])
  584. #################independent test logic mem
  585. pred_ind = np.expand_dims(clf.predict(half_fc_adni_correct_logic_define_[:,t_p_vector[:,1]<=p_thre]), -1)
  586. predPROB_ind = clf.decision_function(half_fc_adni_correct_logic_define_[:,t_p_vector[:,1]<=p_thre])
  587. indep_pred_prob_logic.append(predPROB_ind)
  588. sen, spe = sens_spec(pred_ind, sa_dem_dx_adni_new_define)
  589. acc = accuracy_score(sa_dem_dx_adni_new_define,pred_ind)
  590. AUC = roc_auc_score(sa_dem_dx_adni_new_define, np.array(predPROB_ind))
  591. indep_performance_logic.append([acc, sen, spe, AUC])
  592. #################independent test cn and dem
  593. half_fc_cn_dem_pair_ = transform_cohort(half_fc_cn_dem_pair, 2)
  594. half_fc_cn_sa_pair_ = transform_cohort(half_fc_cn_sa_pair, 2)
  595. predPROB_ind = clf.decision_function(half_fc_cn_dem_pair_[:,t_p_vector[:,1]<=p_thre])
  596. indep_cn_dem_prob.append(predPROB_ind)
  597. predPROB_ind = clf.decision_function(half_fc_cn_sa_pair_[:,t_p_vector[:,1]<=p_thre])
  598. indep_cn_sa_prob.append(predPROB_ind)
  599. other_adni_pred_label = np.array(other_adni_pred_label)
  600. other_oas_pred_label = np.array(other_oas_pred_label)
  601. other_habs_pred_label = np.array(other_habs_pred_label)
  602. #################averaging runs
  603. other_oas_pred_label_uni = []
  604. half_fc_oas_other_correct_uni = []
  605. idx_oas_uni = []
  606. for i, sub in enumerate(oasis_sa_sub_sess_uniq):
  607. other_oas_pred_label_uni.append(other_oas_pred_label[:,oasis_sa_sub_sess_uniq == sub].mean(-1))
  608. half_fc_oas_other_correct_uni.append(half_fc_oas_other_correct[oasis_sa_sub_sess_uniq == sub,:].mean(0))
  609. idx_oas_uni.append(i)
  610. other_oas_pred_label_uni = np.array(other_oas_pred_label_uni)
  611. half_fc_oas_other_correct_uni = np.array(half_fc_oas_other_correct_uni)
  612. idx_oas_uni = np.array(idx_oas_uni)
  613. perform_oas = np.array(perform_oas)
  614. print(perform_oas.mean(0))
  615. perform_habs = np.array(perform_habs)
  616. print(perform_habs.mean(0))
  617. perform = np.array(perform)
  618. print("Discovery input-row level [acc, sen, spe, auc]:", perform.mean(0))
  619. perform_sub = np.array(perform_sub)
  620. print("Discovery participant level [acc, sen, spe, auc]:", perform_sub.mean(0))
  621. indep_pred_prob = np.array(indep_pred_prob)
  622. indep_pred_prob_mean = np.mean(indep_pred_prob, 0).squeeze()
  623. indep_pred_all_mean = np.zeros((len(indep_pred_prob_mean)))
  624. indep_pred_all_mean[indep_pred_prob_mean>0] = 1
  625. indep_pred_all_mean[indep_pred_prob_mean<0] = 0
  626. acc = accuracy_score(sa_dem_dx_adni,indep_pred_all_mean)
  627. AUC = roc_auc_score(sa_dem_dx_adni, np.array(indep_pred_prob_mean))
  628. sen, spe = sens_spec(indep_pred_all_mean, sa_dem_dx_adni)
  629. adni_perf = [acc, sen, spe, AUC]
  630. print('ensemble input-row level acc:{} sen:{} spe:{} auc:{}'.format(acc, sen, spe, AUC))
  631. _, sa_dem_sub_adni_unqi = np.unique(sa_dem_sub_adni, return_index=True)
  632. adni_y_sub, adni_margin_sub = participant_scores(
  633. sa_dem_sub_adni, sa_dem_dx_adni, indep_pred_prob_mean)
  634. adni_pred_sub = (adni_margin_sub > 0).astype(int)
  635. acc = accuracy_score(adni_y_sub, adni_pred_sub)
  636. AUC = roc_auc_score(adni_y_sub, adni_margin_sub)
  637. sen, spe = sens_spec(adni_pred_sub, adni_y_sub)
  638. adni_perf_sublevel = [acc, sen, spe, AUC]
  639. print('ADNI ensemble participant level acc:{} sen:{} spe:{} auc:{}'.format(acc, sen, spe, AUC))
  640. adni_perf_uni = [acc, sen, spe, AUC]
  641. indep_pred_prob = np.array(indep_cn_dem_prob)
  642. indep_pred_prob_mean = np.mean(indep_pred_prob, 0).squeeze()
  643. indep_pred_all_mean = np.zeros((len(indep_pred_prob_mean)))
  644. indep_pred_all_mean[indep_pred_prob_mean>0] = 1
  645. indep_pred_all_mean[indep_pred_prob_mean<0] = 0
  646. acc = accuracy_score(dx_cn_dem_pair,indep_pred_all_mean)
  647. AUC = roc_auc_score(dx_cn_dem_pair, np.array(indep_pred_prob_mean))
  648. sen, spe = sens_spec(indep_pred_all_mean, dx_cn_dem_pair)
  649. adni_perf = [acc, sen, spe, AUC]
  650. print('ensemble acc cn vs dem:{} sen:{} spe:{} auc:{}'.format(acc, sen, spe, AUC))
  651. indep_pred_prob = np.array(indep_cn_sa_prob)
  652. indep_pred_prob_mean = np.mean(indep_pred_prob, 0).squeeze()
  653. indep_pred_all_mean = np.zeros((len(indep_pred_prob_mean)))
  654. indep_pred_all_mean[indep_pred_prob_mean>0] = 1
  655. indep_pred_all_mean[indep_pred_prob_mean<0] = 0
  656. acc = accuracy_score(dx_cn_sa_pair,indep_pred_all_mean)
  657. AUC = roc_auc_score(dx_cn_sa_pair, np.array(indep_pred_prob_mean))
  658. sen, spe = sens_spec(indep_pred_all_mean, dx_cn_sa_pair)
  659. adni_perf = [acc, sen, spe, AUC]
  660. print('ensemble acc cn vs sa:{} sen:{} spe:{} auc:{}'.format(acc, sen, spe, AUC))
  661. # # #################association of PCD in ADNI
  662. other_sub_adni_uni, other_idx_adni_uni = np.unique(other_sub_adni, return_index=True)
  663. other_sub_adni_unique = []
  664. other_sess_adni_unique = []
  665. other_idx_adni_unique = []
  666. for sub in other_sub_adni_uni:
  667. # sub = '002_S_20.50 '
  668. mask = other_sub_adni == sub
  669. sess_sub = other_sess_adni[mask]
  670. idx = np.where(mask)[0]
  671. if sum(mask) == 1:
  672. other_sub_adni_unique.append(sub)
  673. other_sess_adni_unique.append(other_sess_adni[mask][0])
  674. other_idx_adni_unique.append(idx[0])
  675. else:
  676. sess_num = []
  677. for i,sess in enumerate(sess_sub):
  678. if 'bl' in sess:
  679. other_sub_adni_unique.append(sub)
  680. other_sess_adni_unique.append(other_sess_adni[mask][i])
  681. other_idx_adni_unique.append(idx[i])
  682. skip = True
  683. break
  684. else:
  685. sess_num.append(float(sess.split('m')[-1]))
  686. skip = False
  687. if skip == False:
  688. sess_num = np.array(sess_num)
  689. other_sub_adni_unique.append(sub)
  690. other_sess_adni_unique.append(other_sess_adni[mask][np.argmin(sess_num)])
  691. other_idx_adni_unique.append(idx[np.argmin(sess_num)])
  692. skip = True
  693. other_sub_adni_unique = np.array(other_sub_adni_unique)
  694. other_sess_adni_unique = np.array(other_sess_adni_unique)
  695. other_idx_adni_unique = np.array(other_idx_adni_unique)
  696. PCD_adni_interest = {}
  697. adni_path = r'E:\PHD\learning\research\AD\data\ADNI'
  698. adni_demo = pd.read_csv(os.path.join(adni_path, 'ADNIMERGE_01May2024.csv'))
  699. adni_demo_sub = adni_demo['PTID']
  700. adni_demo_sess = adni_demo['VISCODE']
  701. adni_demo_interest = []
  702. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  703. if sum((adni_demo_sub == sub.strip())&(adni_demo_sess == sess.split(' ')[0])) > 0:
  704. adni_demo_interest.append(adni_demo[['PTEDUCAT', 'PTRACCAT', 'APOE4', 'FDG', 'PIB', 'AV45', 'FBB',
  705. 'ABETA', 'TAU', 'PTAU', 'CDRSB', 'ADAS11', 'ADAS13', 'MMSE', 'RAVLT_immediate',
  706. 'RAVLT_learning', 'RAVLT_forgetting', 'RAVLT_perc_forgetting', 'LDELTOTAL', 'DIGITSCOR',
  707. 'TRABSCOR', 'FAQ', 'MOCA', 'EcogPtMem', 'EcogPtLang', 'EcogPtVisspat', 'EcogPtPlan',
  708. 'EcogPtOrgan', 'EcogPtDivatt', 'EcogPtTotal', 'EcogSPMem', 'EcogSPLang', 'EcogSPVisspat',
  709. 'EcogSPPlan', 'EcogSPOrgan', 'EcogSPDivatt', 'EcogSPTotal']][
  710. (adni_demo_sub == sub.strip())&(adni_demo_sess == sess.split(' ')[0])].values[0,:])
  711. else:
  712. adni_demo_interest.append([np.nan for i in range(len(['PTEDUCAT', 'PTRACCAT', 'APOE4', 'FDG', 'PIB', 'AV45', 'FBB',
  713. 'ABETA', 'TAU', 'PTAU', 'CDRSB', 'ADAS11', 'ADAS13', 'MMSE', 'RAVLT_immediate',
  714. 'RAVLT_learning', 'RAVLT_forgetting', 'RAVLT_perc_forgetting', 'LDELTOTAL', 'DIGITSCOR',
  715. 'TRABSCOR', 'FAQ', 'MOCA', 'EcogPtMem', 'EcogPtLang', 'EcogPtVisspat', 'EcogPtPlan',
  716. 'EcogPtOrgan', 'EcogPtDivatt', 'EcogPtTotal', 'EcogSPMem', 'EcogSPLang', 'EcogSPVisspat',
  717. 'EcogSPPlan', 'EcogSPOrgan', 'EcogSPDivatt', 'EcogSPTotal']))])
  718. adni_demo_interest = np.array(adni_demo_interest)
  719. adni_demo_interest[adni_demo_interest[:,1]!='White',1] = 0
  720. adni_demo_interest[adni_demo_interest[:,1]=='White',1] = 1
  721. adni_demo_interest[adni_demo_interest[:,7]=='>1700',7] = 2000
  722. adni_demo_interest[adni_demo_interest[:,9]=='<8',9] = 8
  723. adni_demo_interest[adni_demo_interest[:,17]<-300,17] = np.nan
  724. PCD_adni_interest.update({"AGE": other_age_adni[other_idx_adni_unique], 'GENDER': other_sex_adni[other_idx_adni_unique], 'dx': other_dx_adni[other_idx_adni_unique],
  725. 'PTEDUCAT': adni_demo_interest[:,0],
  726. 'PTRACCAT': adni_demo_interest[:,1], 'APOE4': adni_demo_interest[:,2], 'FDG': adni_demo_interest[:,3],
  727. 'AV45': adni_demo_interest[:,5], 'FBB': adni_demo_interest[:,6], 'ABETA': adni_demo_interest[:,7],
  728. 'TAU': adni_demo_interest[:,8], 'PTAU': adni_demo_interest[:,9], 'CDRSB': adni_demo_interest[:,10],
  729. 'ADAS11': adni_demo_interest[:,11], 'ADAS13': adni_demo_interest[:,12], 'MMSE': adni_demo_interest[:,13],
  730. 'RAVLT_immediate': adni_demo_interest[:,14], 'RAVLT_learning': adni_demo_interest[:,15], 'RAVLT_forgetting': adni_demo_interest[:,16],
  731. 'RAVLT_perc_forgetting': adni_demo_interest[:,17], 'LDELTOTAL': adni_demo_interest[:,18],
  732. 'TRABSCOR': adni_demo_interest[:,20], 'FAQ': adni_demo_interest[:,21], 'MOCA': adni_demo_interest[:,22],
  733. 'EcogPtMem': adni_demo_interest[:,23], 'EcogPtLang': adni_demo_interest[:,24], 'EcogPtVisspat': adni_demo_interest[:,25],
  734. 'EcogPtPlan': adni_demo_interest[:,26], 'EcogPtOrgan': adni_demo_interest[:,27], 'EcogPtDivatt': adni_demo_interest[:,28],
  735. 'EcogPtTotal': adni_demo_interest[:,29], 'EcogSPMem': adni_demo_interest[:,30], 'EcogSPLang': adni_demo_interest[:,31],
  736. 'EcogSPVisspat': adni_demo_interest[:,32], 'EcogSPPlan': adni_demo_interest[:,33], 'EcogSPOrgan': adni_demo_interest[:,34],
  737. 'EcogSPDivatt': adni_demo_interest[:,35], 'EcogSPTotal': adni_demo_interest[:,36]})
  738. adni_cdr = pd.read_csv(os.path.join(adni_path, 'CDR_07May2024.csv'))
  739. adni_cdr_sub = adni_cdr['PTID']
  740. adni_cdr_sess = adni_cdr['VISCODE2']
  741. adni_cdr_sess[adni_cdr_sess == 'sc'] = 'bl'
  742. adni_cdr_sess[adni_cdr_sess == 'f'] = 'bl'
  743. adni_cdr_interest = []
  744. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  745. if sum((adni_cdr_sub == sub.strip())&(adni_cdr_sess == sess.split(' ')[0])) > 0:
  746. adni_cdr_interest.append(adni_cdr[['CDMEMORY', 'CDORIENT', 'CDJUDGE', 'CDCOMMUN', 'CDHOME', 'CDCARE', 'CDGLOBAL']][
  747. (adni_cdr_sub == sub.strip())&(adni_cdr_sess == sess.split(' ')[0])].values[0,:])
  748. else:
  749. adni_cdr_interest.append([np.nan for i in range(len(['CDMEMORY', 'CDORIENT', 'CDJUDGE', 'CDCOMMUN', 'CDHOME', 'CDCARE', 'CDGLOBAL']))])
  750. adni_cdr_interest = np.array(adni_cdr_interest)
  751. PCD_adni_interest.update({'CDMEMORY': adni_cdr_interest[:,0], 'CDORIENT': adni_cdr_interest[:,1], 'CDJUDGE': adni_cdr_interest[:,2],
  752. 'CDCOMMUN': adni_cdr_interest[:,3], 'CDHOME': adni_cdr_interest[:,4], 'CDCARE': adni_cdr_interest[:,5],
  753. 'CDGLOBAL': adni_cdr_interest[:,6]})
  754. adni_faq = pd.read_csv(os.path.join(adni_path, 'FAQ_08May2024.csv'))
  755. adni_faq_sub = adni_faq['PTID']
  756. adni_faq_sess = adni_faq['VISCODE2']
  757. adni_faq_interest = []
  758. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  759. if sum((adni_faq_sub == sub.strip())&(adni_faq_sess == sess.split(' ')[0])) > 0:
  760. adni_faq_interest.append(adni_faq[['FAQFINAN', 'FAQFORM', 'FAQSHOP', 'FAQGAME', 'FAQBEVG', 'FAQMEAL',
  761. 'FAQEVENT', 'FAQTV', 'FAQREM', 'FAQTRAVL']][
  762. (adni_faq_sub == sub.strip())&(adni_faq_sess == sess.split(' ')[0])].values[0,:])
  763. else:
  764. adni_faq_interest.append([np.nan for i in range(len(['FAQFINAN', 'FAQFORM', 'FAQSHOP', 'FAQGAME', 'FAQBEVG', 'FAQMEAL',
  765. 'FAQEVENT', 'FAQTV', 'FAQREM', 'FAQTRAVL']))])
  766. adni_faq_interest = np.array(adni_faq_interest)
  767. adni_faq_interest[(adni_faq_interest==1)|(adni_faq_interest==2)|(adni_faq_interest==3)] = 1
  768. adni_faq_interest[(adni_faq_interest==4)] = 2
  769. adni_faq_interest[(adni_faq_interest==5)] = 3
  770. PCD_adni_interest.update({'FAQFINAN': adni_faq_interest[:,0], 'FAQFORM': adni_faq_interest[:,1], 'FAQSHOP': adni_faq_interest[:,2],
  771. 'FAQGAME': adni_faq_interest[:,3], 'FAQBEVG': adni_faq_interest[:,4], 'FAQMEAL': adni_faq_interest[:,5],
  772. 'FAQEVENT': adni_faq_interest[:,6], 'FAQTV': adni_faq_interest[:,7], 'FAQREM': adni_faq_interest[:,8],
  773. 'FAQTRAVL': adni_faq_interest[:,9]})
  774. adni_neuroBIO = pd.read_csv(os.path.join(adni_path, 'UPENNBIOMK_ROCHE_ELECSYS_16May2024.csv'))
  775. adni_neuroBIO_sub = adni_neuroBIO['RID']
  776. adni_neuroBIO_sess = adni_neuroBIO['VISCODE2']
  777. adni_neuroBIO_interest = []
  778. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  779. if sum((adni_neuroBIO_sub == int(sub.strip().split("_")[-1]))&(adni_neuroBIO_sess == sess.split(' ')[0])) > 0:
  780. adni_neuroBIO_interest.append(adni_neuroBIO[['ABETA42', 'TAU', 'PTAU']][
  781. (adni_neuroBIO_sub == int(sub.strip().split("_")[-1]))&(adni_neuroBIO_sess == sess.split(' ')[0])].values[0,:])
  782. else:
  783. adni_neuroBIO_interest.append([np.nan for i in range(len(['ABETA42', 'TAU', 'PTAU']))])
  784. adni_neuroBIO_interest = np.array(adni_neuroBIO_interest, dtype=object)
  785. # These columns replace the ADNIMERGE ones cleaned above, so apply the same censoring convention here.
  786. adni_neuroBIO_interest[adni_neuroBIO_interest[:,0]=='>1700',0] = 2000
  787. adni_neuroBIO_interest[adni_neuroBIO_interest[:,2]=='<8',2] = 8
  788. try:
  789. adni_neuroBIO_interest = adni_neuroBIO_interest.astype(float)
  790. except ValueError as exc:
  791. raise ValueError('Unhandled censored CSF value in the Elecsys file; add it to the convention above') from exc
  792. PCD_adni_interest.update({'ABETA': adni_neuroBIO_interest[:,0], 'TAU': adni_neuroBIO_interest[:,1], 'PTAU': adni_neuroBIO_interest[:,2]})
  793. adni_gds = pd.read_csv(os.path.join(adni_path, 'GDSCALE_08May2024.csv'))
  794. adni_gds_sub = adni_gds['PTID']
  795. adni_gds_sess = adni_gds['VISCODE2']
  796. adni_gds_interest = []
  797. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  798. if sum((adni_gds_sub == sub.strip())&(adni_gds_sess == sess.split(' ')[0])) > 0:
  799. adni_gds_interest.append(adni_gds['GDTOTAL'][
  800. (adni_gds_sub == sub.strip())&(adni_gds_sess == sess.split(' ')[0])].values[0])
  801. else:
  802. adni_gds_interest.append(np.nan)
  803. adni_gds_interest = np.array(adni_gds_interest)
  804. PCD_adni_interest.update({'GDTOTAL': adni_gds_interest})
  805. adni_his = pd.read_csv(os.path.join(adni_path, 'MODHACH_08May2024.csv'))
  806. adni_his_sub = adni_his['PTID']
  807. adni_his_sess = adni_his['VISCODE2']
  808. adni_his_interest = []
  809. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  810. if sum((adni_his_sub == sub.strip())) > 0:
  811. adni_his_interest.append(adni_his[['HMSTEPWS', 'HMSOMATC', 'HMEMOTIO', 'HMHYPERT', 'HMSTROKE', 'HMNEURSM',
  812. 'HMNEURSG', 'HMSCORE', 'HMONSET']][
  813. (adni_his_sub == sub.strip())].values[0,:])
  814. else:
  815. adni_his_interest.append([np.nan for i in range(len(['HMSTEPWS', 'HMSOMATC', 'HMEMOTIO', 'HMHYPERT', 'HMSTROKE', 'HMNEURSM',
  816. 'HMNEURSG', 'HMSCORE', 'HMONSET']))])
  817. adni_his_interest = np.array(adni_his_interest)
  818. PCD_adni_interest.update({'HMSTEPWS': adni_his_interest[:,0], 'HMSOMATC': adni_his_interest[:,1], 'HMEMOTIO': adni_his_interest[:,2],
  819. 'HMHYPERT': adni_his_interest[:,3], 'HMSTROKE': adni_his_interest[:,4], 'HMNEURSM': adni_his_interest[:,5],
  820. 'HMNEURSG': adni_his_interest[:,6], 'HMSCORE': adni_his_interest[:,7], 'HMONSET': adni_his_interest[:,8]})
  821. adni_moca = pd.read_csv(os.path.join(adni_path, 'MOCA_08May2024.csv'))
  822. adni_moca_sub = adni_moca['PTID']
  823. adni_moca_sess = adni_moca['VISCODE2']
  824. adni_moca_interest = []
  825. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  826. if sum((adni_moca_sub == sub.strip())&(adni_moca_sess == sess.split(' ')[0])) > 0:
  827. adni_moca_interest.append(adni_moca[['TRAILS', 'CUBE', 'CLOCKCON', 'CLOCKNO', 'CLOCKHAN', 'LION', 'RHINO', 'CAMEL',
  828. 'IMMT1W1', 'IMMT1W2', 'IMMT1W3', 'IMMT1W4', 'IMMT1W5', 'IMMT2W1', 'IMMT2W2', 'IMMT2W3',
  829. 'IMMT2W4', 'IMMT2W5', 'DIGFOR', 'DIGBACK', 'LETTERS', 'SERIAL1', 'SERIAL2', 'SERIAL3', 'SERIAL4',
  830. 'SERIAL5', 'REPEAT1', 'REPEAT2', 'FFLUENCY', 'ABSTRAN', 'ABSMEAS', 'DELW1', 'DELW2', 'DELW3',
  831. 'DELW4', 'DELW5', 'DATE', 'MONTH', 'YEAR', 'DAY', 'PLACE', 'CITY']][
  832. (adni_moca_sub == sub.strip())&(adni_moca_sess == sess.split(' ')[0])].values[0,:])
  833. else:
  834. adni_moca_interest.append([np.nan for i in range(len(['TRAILS', 'CUBE', 'CLOCKCON', 'CLOCKNO', 'CLOCKHAN', 'LION', 'RHINO', 'CAMEL',
  835. 'IMMT1W1', 'IMMT1W2', 'IMMT1W3', 'IMMT1W4', 'IMMT1W5', 'IMMT2W1', 'IMMT2W2', 'IMMT2W3',
  836. 'IMMT2W4', 'IMMT2W5', 'DIGFOR', 'DIGBACK', 'LETTERS', 'SERIAL1', 'SERIAL2', 'SERIAL3', 'SERIAL4',
  837. 'SERIAL5', 'REPEAT1', 'REPEAT2', 'FFLUENCY', 'ABSTRAN', 'ABSMEAS', 'DELW1', 'DELW2', 'DELW3',
  838. 'DELW4', 'DELW5', 'DATE', 'MONTH', 'YEAR', 'DAY', 'PLACE', 'CITY']))])
  839. adni_moca_interest = np.array(adni_moca_interest)
  840. adni_moca_subtract = adni_moca_interest[:,21:26].sum(-1)
  841. adni_moca_subtract[(adni_moca_subtract>=2) & (adni_moca_subtract<=3)] = 2
  842. adni_moca_subtract[adni_moca_subtract>=4] = 3
  843. adni_moca_frq = adni_moca_interest[:,28]
  844. adni_moca_frq[adni_moca_frq<11] = 0
  845. adni_moca_frq[adni_moca_frq>=11] = 1
  846. PCD_adni_interest.update({'visuospatial_executive': adni_moca_interest[:,:5].sum(-1), 'naming': adni_moca_interest[:,5:8].sum(-1),
  847. 'abstraction': adni_moca_interest[:,29:31].sum(-1), 'delayed_recall': adni_moca_interest[:,31:36].sum(-1)/3,
  848. 'orientation': adni_moca_interest[:,36:].sum(-1), 'attention': adni_moca_interest[:,18:20].sum(-1) + adni_moca_interest[:,20] + adni_moca_subtract,
  849. 'language': adni_moca_interest[:,26:28].sum(-1) + adni_moca_frq})
  850. adni_nps = pd.read_csv(os.path.join(adni_path, 'NPIQ_08May2024.csv'))
  851. adni_nps_sub = adni_nps['PTID']
  852. adni_nps_sess = adni_nps['VISCODE2']
  853. adni_nps_interest = []
  854. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  855. if sum((adni_nps_sub == sub.strip())&(adni_nps_sess == sess.split(' ')[0])) > 0:
  856. adni_nps_interest.append(adni_nps[['NPIASEV', 'NPIBSEV', 'NPICSEV', 'NPIDSEV', 'NPIESEV', 'NPIFSEV', 'NPIGSEV',
  857. 'NPIHSEV', 'NPIISEV', 'NPIJSEV', 'NPIKSEV', 'NPILSEV','NPISCORE']][
  858. (adni_nps_sub == sub.strip())&(adni_nps_sess == sess.split(' ')[0])].values[0,:])
  859. else:
  860. adni_nps_interest.append([np.nan for i in range(len(['NPIASEV', 'NPIBSEV', 'NPICSEV', 'NPIDSEV', 'NPIESEV', 'NPIFSEV', 'NPIGSEV',
  861. 'NPIHSEV', 'NPIISEV', 'NPIJSEV', 'NPIKSEV', 'NPILSEV','NPISCORE']))])
  862. adni_nps_interest = np.array(adni_nps_interest)
  863. adni_nps_interest[adni_nps_interest == -4] = 0
  864. adni_nps_interest[np.isnan(adni_nps_interest)] = 0
  865. PCD_adni_interest.update({'NPIASEV': adni_nps_interest[:,0], 'NPIBSEV': adni_nps_interest[:,1], 'NPICSEV': adni_nps_interest[:,2],
  866. 'NPIDSEV': adni_nps_interest[:,3], 'NPIESEV': adni_nps_interest[:,4], 'NPIFSEV': adni_nps_interest[:,5],
  867. 'NPIGSEV': adni_nps_interest[:,6], 'NPIHSEV': adni_nps_interest[:,7], 'NPIISEV': adni_nps_interest[:,8],
  868. 'NPIJSEV': adni_nps_interest[:,9], 'NPIKSEV': adni_nps_interest[:,10], 'NPILSEV': adni_nps_interest[:,11],
  869. 'NPISCORE': adni_nps_interest[:,12]})
  870. adni_neu = pd.read_csv(os.path.join(adni_path, 'NEUROBAT_08May2024.csv'))
  871. adni_neu_sub = adni_neu['PTID']
  872. adni_neu_sess = adni_neu['VISCODE2']
  873. adni_neu_interest = []
  874. for sub, sess in zip(other_sub_adni_unique, other_sess_adni_unique):
  875. if sum((adni_neu_sub == sub.strip())&(adni_neu_sess == sess.split(' ')[0])) > 0:
  876. adni_neu_interest.append(adni_neu[['LIMMTOTAL', 'DSPANFOR', 'DSPANFLTH', 'DSPANBAC', 'DSPANBLTH', 'CATANIMSC', 'CATANPERS',
  877. 'CATVEGESC', 'CATVGPERS', 'TRAASCOR', 'TRABSCOR', 'DIGITSCOR','LDELTOTAL', 'BNTTOTAL']][
  878. (adni_neu_sub == sub.strip())&(adni_neu_sess == sess.split(' ')[0])].values[0,:])
  879. else:
  880. adni_neu_interest.append([np.nan for i in range(len(['LIMMTOTAL', 'DSPANFOR', 'DSPANFLTH', 'DSPANBAC', 'DSPANBLTH', 'CATANIMSC',
  881. 'CATANPERS', 'CATVEGESC', 'CATVGPERS', 'TRAASCOR', 'TRABSCOR', 'DIGITSCOR','LDELTOTAL',
  882. 'BNTTOTAL']))])
  883. adni_neu_interest = np.array(adni_neu_interest)
  884. adni_neu_interest[adni_neu_interest == -4] = 0
  885. PCD_adni_interest.update({'LIMMTOTAL': adni_neu_interest[:,0], 'CATANIMSC': adni_neu_interest[:,5],
  886. 'CATANPERS': adni_neu_interest[:,6], 'CATVEGESC': adni_neu_interest[:,7], 'DSPANFOR': adni_neu_interest[:,1],
  887. 'TRAASCOR': adni_neu_interest[:,9], 'DSPANBAC': adni_neu_interest[:,3], 'DIGITSCOR': adni_neu_interest[:,11],
  888. 'BNTTOTAL': adni_neu_interest[:,13]})
  889. # ---- Phenotype group comparisons ----
  890. PCD_keys = ['AGE', 'GENDER', 'PTEDUCAT', 'PTRACCAT', 'APOE4', 'FDG', 'AV45', 'FBB', 'ABETA', 'TAU', 'PTAU', 'CDRSB',
  891. 'ADAS11', 'ADAS13', 'MMSE', 'RAVLT_immediate', 'RAVLT_learning', 'RAVLT_forgetting',
  892. 'RAVLT_perc_forgetting', 'LDELTOTAL', 'TRABSCOR', 'FAQ', 'MOCA', 'CDMEMORY',
  893. 'CDORIENT', 'CDJUDGE', 'CDCOMMUN', 'CDHOME', 'CDCARE', 'CDGLOBAL', 'FAQFINAN', 'FAQFORM',
  894. 'FAQSHOP', 'FAQGAME', 'FAQBEVG', 'FAQMEAL', 'FAQEVENT', 'FAQTV', 'FAQREM', 'FAQTRAVL', 'GDTOTAL',
  895. 'visuospatial_executive', 'naming', 'abstraction', 'delayed_recall', 'orientation', 'attention',
  896. 'language', 'NPIASEV', 'NPIBSEV', 'NPICSEV',
  897. 'NPIDSEV', 'NPIESEV', 'NPIFSEV', 'NPIGSEV', 'NPIHSEV', 'NPIISEV', 'NPIJSEV', 'NPIKSEV', 'NPILSEV',
  898. 'NPISCORE', 'LIMMTOTAL', 'DSPANFOR', 'DSPANBAC', 'CATANIMSC', 'CATANPERS', 'CATVEGESC', 'TRAASCOR', 'DIGITSCOR', 'BNTTOTAL']
  899. df_adni = pd.DataFrame(PCD_adni_interest).astype(float)
  900. df_adni['A+'] = (df_adni['ABETA'] <= float(os.environ['ARC_CSF_ABETA_CUTOFF'])) * 1.0
  901. df_adni.loc[df_adni['ABETA'].isnull(), 'A+'] = np.nan
  902. df_adni['T+'] = (df_adni['PTAU'] > float(os.environ['ARC_CSF_PTAU_CUTOFF'])) * 1.0
  903. df_adni.loc[df_adni['PTAU'].isnull(), 'T+'] = np.nan
  904. PCD_keys.append('A+')
  905. PCD_keys.append('T+')
  906. stat_all_adni_cn = []
  907. stat_keys_adni = []
  908. stat_test = []
  909. mask_cn = (other_dx_adni[other_idx_adni_unique]==2)
  910. mask_MCI = (other_dx_adni[other_idx_adni_unique]==3)
  911. # other_adni_pred_label_avg = other_adni_pred_label.mean(0)[other_idx_adni_unique]
  912. other_adni_pred_label_mask = other_adni_pred_label>0
  913. other_adni_pred_label_avg = other_adni_pred_label_mask.mean(0)[other_idx_adni_unique]
  914. for i, key in enumerate(PCD_keys):
  915. stat_keys_adni.append(key)
  916. fea = df_adni[key]
  917. fea_demlike_cn = fea[mask_cn&(other_adni_pred_label_avg>=0.5)]
  918. fea_demlike_cn = fea_demlike_cn[np.isfinite(fea_demlike_cn)]
  919. fea_salike_cn = fea[mask_cn&(other_adni_pred_label_avg<0.5)]
  920. fea_salike_cn = fea_salike_cn[np.isfinite(fea_salike_cn)]
  921. fea_unstable_cn = fea[mask_cn&(other_adni_pred_label_avg!=0)&(other_adni_pred_label_avg!=1)]
  922. fea_unstable_cn = fea_unstable_cn[np.isfinite(fea_unstable_cn)]
  923. if len(fea_demlike_cn)>5 and len(fea_salike_cn)>5 and (len(fea_salike_cn) + len(fea_demlike_cn))>20 and (len(set(fea_salike_cn))>1 or len(set(fea_demlike_cn)) > 1):
  924. if key == 'A+' or key == 'T+':
  925. [F_cn,p_cn,_,_]=chi2_contingency([[np.sum(fea_salike_cn==1), np.sum(fea_demlike_cn==1)],
  926. [np.sum(fea_salike_cn==0), np.sum(fea_demlike_cn==0)]])
  927. cohens_d = cohen_d(fea_salike_cn, fea_demlike_cn)
  928. stat_all_adni_cn.append([F_cn, p_cn, cohens_d, len(fea_demlike_cn), len(fea_salike_cn)])
  929. if key == 'GENDER' or key == 'PTRACCAT':
  930. plt.figure(figsize=(5,10))
  931. ax = plt.gca()
  932. count = np.sum(fea_salike_cn==1)
  933. ax.bar(0, count, color = red, width = 1, fill=False, edgecolor= red, linewidth=5, hatch = '+')
  934. count = np.sum(fea_demlike_cn==1)
  935. ax.bar(1, count, color = blue, width = 1, fill=False, edgecolor= blue, linewidth=5, hatch = '+')
  936. if key == 'PTRACCAT':
  937. count = np.sum(fea_salike_cn==0)
  938. else:
  939. count = np.sum(fea_salike_cn==2)
  940. ax.bar(2, count, color = red, width = 1, fill=False, edgecolor= red, linewidth=5, hatch = 'x')
  941. if key == 'PTRACCAT':
  942. count = np.sum(fea_demlike_cn==0)
  943. else:
  944. count = np.sum(fea_demlike_cn==2)
  945. ax.bar(3, count, color = blue, width = 1, fill=False, edgecolor= blue, linewidth=5, hatch = 'x')
  946. ax.set_yticks((0, 100, 200, 300, 400))
  947. ax.set_xticks([1.5])
  948. ax.set_xticklabels(['CN'])
  949. ax.set_xlabel(key, **font2)
  950. ax.spines['top'].set_color('none') # 设置上‘脊梁’为红色
  951. ax.spines['right'].set_color('none') # 设置上‘脊梁’为无色
  952. else:
  953. plt.figure(figsize=(5,10))
  954. ax = plt.gca()
  955. count = np.sum(fea_demlike_cn<0.5)
  956. ax.bar(0, count, color = red, width = 1, fill=False, edgecolor= red, linewidth=5, hatch = '+')
  957. count = np.sum(fea_salike_cn<0.5)
  958. ax.bar(1, count, color = blue, width = 1, fill=False, edgecolor= blue, linewidth=5, hatch = '+')
  959. count = np.sum(fea_demlike_cn==1)
  960. ax.bar(2, count, color = red, width = 1, fill=False, edgecolor= red, linewidth=5, hatch = 'x')
  961. count = np.sum(fea_salike_cn==1)
  962. ax.bar(3, count, color = blue, width = 1, fill=False, edgecolor= blue, linewidth=5, hatch = 'x')
  963. ax.set_yticks((0, 50, 100, 150))
  964. ax.set_xticks([1.5])
  965. ax.set_xticklabels(['CN'])
  966. ax.set_xlabel(key, **font2)
  967. ax.spines['top'].set_color('none') # 设置上‘脊梁’为红色
  968. ax.spines['right'].set_color('none') # 设置上‘脊梁’为无色
  969. else:
  970. F_cn,p_cn=kruskal(fea_salike_cn, fea_demlike_cn)
  971. cohens_d = cohen_d(fea_salike_cn, fea_demlike_cn)
  972. stat_all_adni_cn.append([F_cn, p_cn, cohens_d, len(fea_demlike_cn), len(fea_salike_cn)])
  973. result1 = np.r_[fea_salike_cn, fea_demlike_cn]
  974. dx_label = np.r_[['CN' for i in range(len(fea_salike_cn)+len(fea_demlike_cn))]]
  975. cluster_label = np.r_[['SA-like' for i in range(len(fea_salike_cn))], ['DEM-like' for i in range(len(fea_demlike_cn))]]
  976. df = pd.DataFrame({'data': result1, 'DX': dx_label, 'Cluster': cluster_label})
  977. plt.figure(figsize=(5,10))
  978. ax = plt.gca()
  979. my_pal = {'SA-like': blue, 'DEM-like': red}
  980. # my_pal = {'SA-like': blue, 1: red, 2: 'limegreen', 3: RGB(0,.8,0.1)}
  981. sns.stripplot(data=df, x="DX", y="data", hue="Cluster", palette = my_pal, ax = ax, dodge=True, legend = False, size = 5, jitter=0.2)
  982. sns.violinplot(data=df, x="DX", y="data", hue="Cluster", palette = my_pal, fill=False, ax = ax, saturation=1, inner = 'box')
  983. ax.scatter([-0.2,0.2],y= np.r_[fea_salike_cn.median(), fea_demlike_cn.median()],c="white",s = 100, edgecolor = 'grey', zorder=3, linewidth = 2)
  984. plt.xlim(-1, 1)
  985. for collection in ax.collections:
  986. if isinstance(collection, matplotlib.collections.PolyCollection):
  987. collection.set_edgecolor(collection.get_facecolor())
  988. collection.set_facecolor('none')
  989. for h in ax.legend_.legendHandles:
  990. if isinstance(h, matplotlib.patches.Rectangle):
  991. h.set_edgecolor(h.get_facecolor())
  992. h.set_facecolor('none')
  993. h.set_linewidth(2.5)
  994. ax.get_legend().remove()
  995. unit = (np.max(fea[np.isfinite(fea)]) - np.min(fea[np.isfinite(fea)]))//2
  996. if abs(unit) < 1:
  997. unit = round((np.max(fea[np.isfinite(fea)]) - np.min(fea[np.isfinite(fea)]))/2, 2)
  998. ax.set_yticks(np.arange(np.min(fea[np.isfinite(fea)])-unit//2, np.max(fea[np.isfinite(fea)])+unit//2, unit))
  999. else:
  1000. ax.set_yticks(np.arange(np.min(fea[np.isfinite(fea)])-unit//2, np.max(fea[np.isfinite(fea)])+unit//2, unit).astype(int))
  1001. if key == 'AGE':
  1002. ax.set_yticks(np.arange(20, 110, 30))
  1003. plt.ylim(20, 110)
  1004. ax.set_ylabel(key)
  1005. ax.spines['top'].set_color('none') # 设置上‘脊梁’为红色
  1006. ax.spines['right'].set_color('none') # 设置上‘脊梁’为无色
  1007. # plt.savefig(r'F:\PHD\learning\project\super_age\more_sub\SA_defined_ricado\cluster\stats_compare\0.5\{}_adni_f.svg'.format(key), bbox_inches = 'tight')
  1008. else:
  1009. stat_all_adni_cn.append([np.nan, np.nan, np.nan, len(fea_demlike_cn), len(fea_salike_cn)])
  1010. stat_all_adni_cn = np.array(stat_all_adni_cn)
  1011. stat_all_adni_cn[np.r_[[70,71], np.arange(5,11)],1]
  1012. out = multipletests(stat_all_adni_cn[np.r_[[70,71], np.arange(5,11)],1], method="fdr_bh")[1]
  1013. np.array(stat_keys_adni)[np.r_[[70,71], np.arange(5,11)]]
  1014. stat_adni_nonan_fdrp = multipletests(stat_all_adni_cn[np.isfinite(stat_all_adni_cn[:,1]),1], method="fdr_bh")[1]
  1015. stat_keys_adni_nonan_fdrp = np.array(stat_keys_adni)[np.isfinite(stat_all_adni_cn[:,1])]
  1016. stat_adni_nonan = stat_all_adni_cn[np.isfinite(stat_all_adni_cn[:,1])]
  1017. # sio.savemat(r'F:\PHD\learning\project\super_age\more_sub\SA_defined_ricado\cluster\stats_compare\0.5\stats_compare_ini_adni.mat', {'stat_keys_adni':stat_keys_adni,
  1018. # 'stat_all_adni_cn': stat_all_adni_cn})
  1019. # #################association of PCD in OASIS
  1020. oasis_sa_sub = pd.Series(oasis_sa_sub_sess_uniq).str.split('_', expand = True).iloc[:,0]
  1021. oasis_sa_sub_unique, unique_id = np.unique(oasis_sa_sub, return_index=True)
  1022. oasis_sa_sub_sess_unique = oasis_sa_sub_sess_uniq[unique_id]
  1023. PCD_all_interest = {}
  1024. oasis_demo = pd.read_csv(os.path.join(oasis_path, 'UDS-A2-InformatDemos.csv'))
  1025. oasis_demo2 = pd.read_csv(os.path.join(oasis_path, 'OASIS3_UDSa2_cs_demo.csv'))
  1026. oasis_demo_sub = oasis_demo['Subject']
  1027. oasis_demo_sub2 = oasis_demo2['OASISID']
  1028. sa_dem_sex_oas = []
  1029. sa_dem_age_oas = []
  1030. for i, sub in enumerate(sa_dem_sub_oas_):
  1031. # sa_dem_sex_oas.append(sex_oas[(sub_oas==sub)&(sess_oas == sa_dem_sess_oas[i])])
  1032. if sum(oasis_demo_sub == sub) >= 1:
  1033. sa_dem_sex_oas.append(oasis_demo['INSEX'][oasis_demo_sub == sub].values[0])
  1034. else:
  1035. if sum(oasis_demo_sub2 == sub) >= 1:
  1036. sa_dem_sex_oas.append(oasis_demo2['INSEX'][oasis_demo_sub2 == sub].values[0])
  1037. sa_dem_age_oas.append(age_oas[(sub_oas==sub)&(sess_oas == sa_dem_sess_oas[i])])
  1038. sa_dem_sex_oas = np.array(sa_dem_sex_oas).squeeze() # female: 2; male: 1
  1039. sa_dem_age_oas = np.array(sa_dem_age_oas).squeeze()
  1040. oasis_path = r'E:\PHD\learning\research\AD\data\OASIS3'
  1041. oasis_demo = pd.read_csv(os.path.join(oasis_path, 'UDS-A2-InformatDemos.csv'))
  1042. oasis_demo2 = pd.read_csv(os.path.join(oasis_path, 'OASIS3_UDSa2_cs_demo.csv'))
  1043. oasis_demo_sub = oasis_demo['Subject']
  1044. oasis_demo_sub2 = oasis_demo2['OASISID']
  1045. oasis_demo_interest = []
  1046. for sub in oasis_sa_sub_sess_unique:
  1047. sub = sub[:8]
  1048. if sum(oasis_demo_sub == sub) >= 1:
  1049. oasis_demo_interest.append(oasis_demo[['INRACE', 'INEDUC', 'INSEX']][oasis_demo_sub == sub].values[0,:])
  1050. else:
  1051. if sum(oasis_demo_sub2 == sub) >= 1:
  1052. oasis_demo_interest.append(oasis_demo2[['INRACE', 'INEDUC', 'INSEX']][oasis_demo_sub2 == sub].values[0,:])
  1053. else:
  1054. oasis_demo_interest.append([np.nan, np.nan, np.nan])
  1055. oasis_demo_interest = np.array(oasis_demo_interest)
  1056. PCD_all_interest.update({"INRACE": oasis_demo_interest[:,0], 'INEDUC': oasis_demo_interest[:,1], 'age': other_age_oas[unique_id],
  1057. 'sex': oasis_demo_interest[:,2], 'dx': other_dx_oas_encode[unique_id]})
  1058. oas_pcd_info = sio.loadmat(r'E:\PHD\learning\research\AD\data\OASIS3\fMRIdata_OASIS3_struct.mat')
  1059. tvar = oas_pcd_info['OASIS3_Phenotypic_struct']
  1060. PCD_data = []
  1061. pcd_keys = ['subjectID_Date', 'apoe', 'NPIQINF', 'NPIQINFX', 'DEL',
  1062. 'DELSEV', 'HALL', 'HALLSEV', 'AGIT', 'AGITSEV', 'DEPD', 'DEPDSEV', 'ANX',
  1063. 'ANXSEV', 'ELAT', 'ELATSEV', 'APA', 'APASEV', 'DISN', 'DISNSEV', 'IRR',
  1064. 'IRRSEV', 'MOT', 'MOTSEV', 'NITE', 'NITESEV', 'APP', 'APPSEV', 'mmse',
  1065. 'cdr', 'commun','homehobb', 'judgment', 'memory', 'orient', 'perscare', 'sumbox',
  1066. 'DIGIF', 'DIGIB', 'ANIMALS', 'VEG', 'TRAILA', 'TRAILALI', 'TRAILB',
  1067. 'TRAILBLI', 'WAIS', 'LOGIMEM', 'MEMUNITS', 'MEMTIME', 'BOSTON']
  1068. for idx in range(len(tvar)):
  1069. sub_data = []
  1070. for name in pcd_keys:
  1071. value = tvar[idx][0][name]
  1072. for i in range(3):
  1073. if isinstance(value, np.ndarray):
  1074. try:
  1075. value = value[0]
  1076. except IndexError:
  1077. if name == 'DX':
  1078. value = 'nan'
  1079. else:
  1080. value = "error"
  1081. else:
  1082. if name == 'subjectID_Date' or name == 'dx1':
  1083. value = str(value)
  1084. sub_data.append(value)
  1085. break
  1086. PCD_data.append(sub_data)
  1087. PCD_data = np.array(PCD_data)
  1088. PCD_data[:,1] = pd.Series(PCD_data[:,1]).str.count('4')
  1089. #update NPI 0 score
  1090. for i in [5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27]:
  1091. mask = PCD_data[:, i] == 'nan'
  1092. PCD_data[np.isfinite(PCD_data[:,2].astype(float))&mask, i] = 0
  1093. PCD_data[np.isfinite(PCD_data[:,2].astype(float))][:,[5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27]] = 0
  1094. PCD_sub = np.array([sub[:8] for sub in PCD_data[:,0]])
  1095. PCD_day = np.array([sub[10:] for sub in PCD_data[:,0]]).astype(int)
  1096. PCD_sess = []
  1097. day_min = []
  1098. for da in PCD_day:
  1099. mask = day_all==da
  1100. if sum(mask) > 0:
  1101. PCD_sess.append(sess_all[day_all==da][0])
  1102. else:
  1103. diff = day_all-da
  1104. diff_min_id = np.argmin(abs(diff))
  1105. diff_min = diff[diff_min_id]
  1106. day_min.append(diff_min)
  1107. PCD_sess.append(sess_all[diff_min_id])
  1108. PCD_sess = np.array(PCD_sess)
  1109. PCD_interest = []
  1110. for sub_sess in oasis_sa_sub_sess_unique:
  1111. sub = sub_sess[:8]
  1112. sess = sub_sess[9:]
  1113. if sum((PCD_sub == sub) & (PCD_sess == sess))== 1:
  1114. PCD_interest.append(PCD_data[:,np.r_[[1, 2, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25], np.arange(27,50)]][
  1115. (PCD_sub == sub) & (PCD_sess == sess)].squeeze())
  1116. elif sum((PCD_sub == sub) & (PCD_sess == sess))> 1:
  1117. pcd = PCD_data[:,np.r_[[1, 2, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25], np.arange(27,50)]][
  1118. (PCD_sub == sub) & (PCD_sess == sess)].squeeze()
  1119. pcd_new = []
  1120. for i in range(pcd.shape[-1]):
  1121. info = pcd[:,i]
  1122. if np.isnan(info.astype(float)).sum() == len(info):
  1123. pcd_new.append(np.nan)
  1124. else:
  1125. pcd_new.append(info[~np.isnan(info.astype(float))][0].squeeze())
  1126. PCD_interest.append(np.array(pcd_new))
  1127. else:
  1128. PCD_interest.append(np.array([np.nan for i in range(len(['apoe', 'NPIQINF', 'DELSEV', 'HALLSEV', 'AGITSEV', 'DEPDSEV',
  1129. 'ANXSEV', 'ELATSEV', 'APASEV', 'DISNSEV', 'IRRSEV', 'MOTSEV', 'NITESEV',
  1130. 'APPSEV', 'mmse', 'cdr', 'commun','homehobb', 'judgment', 'memory', 'orient', 'perscare', 'sumbox',
  1131. 'DIGIF', 'DIGIB', 'ANIMALS', 'VEG', 'TRAILA', 'TRAILALI', 'TRAILB',
  1132. 'TRAILBLI', 'WAIS', 'LOGIMEM', 'MEMUNITS', 'MEMTIME', 'BOSTON']))]))
  1133. PCD_interest = np.array(PCD_interest)
  1134. PCD_all_interest.update({"apoe": PCD_interest[:,0], 'NPIQINF': PCD_interest[:,1], 'DELSEV': PCD_interest[:,2],
  1135. 'HALLSEV': PCD_interest[:,3], 'AGITSEV': PCD_interest[:,4], 'DEPDSEV': PCD_interest[:,5],
  1136. 'ANXSEV': PCD_interest[:,6], 'ELATSEV': PCD_interest[:,7], 'APASEV': PCD_interest[:,8],
  1137. 'DISNSEV': PCD_interest[:,9], 'IRRSEV': PCD_interest[:,10], 'MOTSEV': PCD_interest[:,11],
  1138. 'NITESEV': PCD_interest[:,12], 'APPSEV': PCD_interest[:,13], 'mmse': PCD_interest[:,14],
  1139. 'cdr': PCD_interest[:,15], 'commun': PCD_interest[:,16], 'homehobb': PCD_interest[:,17],
  1140. 'judgment': PCD_interest[:,18], 'memory': PCD_interest[:,19], 'orient': PCD_interest[:,20], 'perscare': PCD_interest[:,21],
  1141. 'sumbox': PCD_interest[:,22], 'DIGIF': PCD_interest[:,23], 'DIGIB': PCD_interest[:,24],
  1142. 'ANIMALS': PCD_interest[:,25], 'VEG': PCD_interest[:,26], 'TRAILA': PCD_interest[:,27],
  1143. 'TRAILALI': PCD_interest[:,28], 'TRAILB': PCD_interest[:,29], 'TRAILBLI': PCD_interest[:,30], 'WAIS': PCD_interest[:,31],
  1144. 'LOGIMEM': PCD_interest[:,32], 'MEMUNITS': PCD_interest[:,33], 'MEMTIME': PCD_interest[:,34], 'BOSTON': PCD_interest[:,35]})
  1145. oasis_faq = pd.read_csv(os.path.join(oasis_path, 'UDS-B7-FAQ.csv'))
  1146. oasis_faq_sub_day = oasis_faq['UDS_B7FAQDATA ID']
  1147. oasis_faq_sub = oasis_faq_sub_day.str.split('_', expand = True).iloc[:,0]
  1148. oasis_faq_day = oasis_faq_sub_day.str.split('_d', expand = True).iloc[:,-1].astype(int)
  1149. oasis_faq_sess = []
  1150. day_min = []
  1151. for da in oasis_faq_day:
  1152. mask = day_all==da
  1153. if sum(mask) > 0:
  1154. oasis_faq_sess.append(sess_all[day_all==da][0])
  1155. else:
  1156. diff = day_all-da
  1157. diff_min_id = np.argmin(abs(diff))
  1158. diff_min = diff[diff_min_id]
  1159. day_min.append(diff_min)
  1160. oasis_faq_sess.append(sess_all[diff_min_id])
  1161. oasis_faq_sess = np.array(oasis_faq_sess)
  1162. oasis_faq_interest = []
  1163. for sub_sess in oasis_sa_sub_sess_unique:
  1164. sub = sub_sess[:8]
  1165. sess = sub_sess[9:]
  1166. if sum((oasis_faq_sub == sub) & (oasis_faq_sess == sess))> 0:
  1167. oasis_faq_interest.append(oasis_faq[['BILLS', 'TAXES', 'SHOPPING', 'GAMES', 'STOVE', 'MEALPREP', 'EVENTS',
  1168. 'PAYATTN', 'REMDATES', 'TRAVEL']][
  1169. (oasis_faq_sub == sub) & (oasis_faq_sess == sess)].values[0,:])
  1170. else:
  1171. oasis_faq_interest.append([np.nan for i in range(len(['BILLS', 'TAXES', 'SHOPPING', 'GAMES', 'STOVE', 'MEALPREP', 'EVENTS',
  1172. 'PAYATTN', 'REMDATES', 'TRAVEL']))])
  1173. oasis_faq_interest = np.array(oasis_faq_interest)
  1174. oasis_faq_interest[(oasis_faq_interest==8)|(oasis_faq_interest==9)] = np.nan
  1175. PCD_all_interest.update({"BILLS": oasis_faq_interest[:,0], 'TAXES': oasis_faq_interest[:,1], 'SHOPPING': oasis_faq_interest[:,2],
  1176. 'GAMES': oasis_faq_interest[:,3], 'STOVE': oasis_faq_interest[:,4], 'MEALPREP': oasis_faq_interest[:,5],
  1177. 'EVENTS': oasis_faq_interest[:,6], 'PAYATTN': oasis_faq_interest[:,7], 'REMDATES': oasis_faq_interest[:,8],
  1178. 'TRAVEL': oasis_faq_interest[:,9]})
  1179. oasis_pet = pd.read_csv(os.path.join(oasis_path, 'OASIS3_PUP.csv'))
  1180. oasis_pet['Centil_fBP_TOT_CORTMEAN_av45'] = np.zeros((oasis_pet.shape[0]))
  1181. oasis_pet['Centil_fBP_TOT_CORTMEAN_av45'] = oasis_pet['Centil_fBP_TOT_CORTMEAN'][oasis_pet['tracer'] == 'AV45']
  1182. oasis_pet['Centil_fSUVR_TOT_CORTMEAN_av45'] = np.zeros((oasis_pet.shape[0]))
  1183. oasis_pet['Centil_fSUVR_TOT_CORTMEAN_av45'] = oasis_pet['Centil_fSUVR_TOT_CORTMEAN'][oasis_pet['tracer'] == 'AV45']
  1184. oasis_pet['Centil_fBP_rsf_TOT_CORTMEAN_av45'] = np.zeros((oasis_pet.shape[0]))
  1185. oasis_pet['Centil_fBP_rsf_TOT_CORTMEAN_av45'] = oasis_pet['Centil_fBP_rsf_TOT_CORTMEAN'][oasis_pet['tracer'] == 'AV45']
  1186. oasis_pet['Centil_fSUVR_rsf_TOT_CORTMEAN_av45'] = np.zeros((oasis_pet.shape[0]))
  1187. oasis_pet['Centil_fSUVR_rsf_TOT_CORTMEAN_av45'] = oasis_pet['Centil_fSUVR_rsf_TOT_CORTMEAN'][oasis_pet['tracer'] == 'AV45']
  1188. oasis_pet['Centil_fBP_TOT_CORTMEAN_pib'] = np.zeros((oasis_pet.shape[0]))
  1189. oasis_pet['Centil_fBP_TOT_CORTMEAN_pib'] = oasis_pet['Centil_fBP_TOT_CORTMEAN'][oasis_pet['tracer'] == 'PIB']
  1190. oasis_pet['Centil_fSUVR_TOT_CORTMEAN_pib'] = np.zeros((oasis_pet.shape[0]))
  1191. oasis_pet['Centil_fSUVR_TOT_CORTMEAN_pib'] = oasis_pet['Centil_fSUVR_TOT_CORTMEAN'][oasis_pet['tracer'] == 'PIB']
  1192. oasis_pet['Centil_fBP_rsf_TOT_CORTMEAN_pib'] = np.zeros((oasis_pet.shape[0]))
  1193. oasis_pet['Centil_fBP_rsf_TOT_CORTMEAN_pib'] = oasis_pet['Centil_fBP_rsf_TOT_CORTMEAN'][oasis_pet['tracer'] == 'PIB']
  1194. oasis_pet['Centil_fSUVR_rsf_TOT_CORTMEAN_pib'] = np.zeros((oasis_pet.shape[0]))
  1195. oasis_pet['Centil_fSUVR_rsf_TOT_CORTMEAN_pib'] = oasis_pet['Centil_fSUVR_rsf_TOT_CORTMEAN'][oasis_pet['tracer'] == 'PIB']
  1196. oasis_pet_sub_day = oasis_pet['PUP_PUPTIMECOURSEDATA ID']
  1197. oasis_pet_sub = oasis_pet_sub_day.str.split('_', expand = True).iloc[:,0]
  1198. oasis_pet_day = oasis_pet_sub_day.str.split('_d', expand = True).iloc[:,-1].astype(int)
  1199. oasis_pet_sess = []
  1200. day_min = []
  1201. for da in oasis_pet_day:
  1202. mask = day_all==da
  1203. if sum(mask) > 0:
  1204. oasis_pet_sess.append(sess_all[day_all==da][0])
  1205. else:
  1206. diff = day_all-da
  1207. diff_min_id = np.argmin(abs(diff))
  1208. diff_min = diff[diff_min_id]
  1209. day_min.append(diff_min)
  1210. oasis_pet_sess.append(sess_all[diff_min_id])
  1211. oasis_pet_sess = np.array(oasis_pet_sess)
  1212. oasis_pet_interest = []
  1213. for sub_sess in oasis_sa_sub_sess_unique:
  1214. sub = sub_sess[:8]
  1215. sess = sub_sess[9:]
  1216. if sum((oasis_pet_sub == sub) & (oasis_pet_sess == sess))> 0:
  1217. oasis_pet_interest.append(oasis_pet[['Centil_fBP_TOT_CORTMEAN_av45', 'Centil_fSUVR_TOT_CORTMEAN_av45',
  1218. 'Centil_fBP_rsf_TOT_CORTMEAN_av45', 'Centil_fSUVR_rsf_TOT_CORTMEAN_av45',
  1219. 'Centil_fBP_TOT_CORTMEAN_pib', 'Centil_fSUVR_TOT_CORTMEAN_pib',
  1220. 'Centil_fBP_rsf_TOT_CORTMEAN_pib', 'Centil_fSUVR_rsf_TOT_CORTMEAN_pib']][
  1221. (oasis_pet_sub == sub) & (oasis_pet_sess == sess)].values[0,:])
  1222. else:
  1223. oasis_pet_interest.append([np.nan for i in range(len(['Centil_fBP_TOT_CORTMEAN_av45', 'Centil_fSUVR_TOT_CORTMEAN_av45',
  1224. 'Centil_fBP_rsf_TOT_CORTMEAN_av45', 'Centil_fSUVR_rsf_TOT_CORTMEAN_av45',
  1225. 'Centil_fBP_TOT_CORTMEAN_pib', 'Centil_fSUVR_TOT_CORTMEAN_pib',
  1226. 'Centil_fBP_rsf_TOT_CORTMEAN_pib', 'Centil_fSUVR_rsf_TOT_CORTMEAN_pib']))])
  1227. oasis_pet_interest = np.array(oasis_pet_interest)
  1228. PCD_all_interest.update({"Centil_fBP_TOT_CORTMEAN_av45": oasis_pet_interest[:,0], 'Centil_fSUVR_TOT_CORTMEAN_av45': oasis_pet_interest[:,1],
  1229. 'Centil_fBP_rsf_TOT_CORTMEAN_av45': oasis_pet_interest[:,2], 'Centil_fSUVR_rsf_TOT_CORTMEAN_av45': oasis_pet_interest[:,3],
  1230. "Centil_fBP_TOT_CORTMEAN_pib": oasis_pet_interest[:,4], 'Centil_fSUVR_TOT_CORTMEAN_pib': oasis_pet_interest[:,5],
  1231. 'Centil_fBP_rsf_TOT_CORTMEAN_pib': oasis_pet_interest[:,6], 'Centil_fSUVR_rsf_TOT_CORTMEAN_pib': oasis_pet_interest[:,7]})
  1232. PCD_all_interest['TRAILB'] = PCD_all_interest['TRAILB'].astype(float)
  1233. PCD_all_interest['TRAILB'][PCD_all_interest['TRAILB']>400] = np.nan
  1234. df_oas = pd.DataFrame(PCD_all_interest).astype(float)
  1235. PCD_keys = ['INRACE', 'INEDUC', 'sex', 'age', 'apoe', 'DELSEV', 'HALLSEV', 'AGITSEV',
  1236. 'DEPDSEV', 'ANXSEV', 'ELATSEV', 'APASEV', 'DISNSEV', 'IRRSEV', 'MOTSEV', 'NITESEV',
  1237. 'APPSEV', 'mmse', 'cdr', 'commun','homehobb', 'judgment', 'memory', 'orient', 'perscare', 'sumbox', 'VEG',
  1238. 'DIGIF', 'DIGIB', 'ANIMALS', 'TRAILA', 'TRAILALI', 'TRAILB', 'TRAILBLI', 'WAIS', 'LOGIMEM',
  1239. 'MEMUNITS', 'MEMTIME', 'BOSTON', 'BILLS', 'TAXES', 'SHOPPING', 'GAMES', 'STOVE', 'MEALPREP',
  1240. 'EVENTS', 'PAYATTN', 'REMDATES', 'TRAVEL', 'Centil_fBP_TOT_CORTMEAN_av45', 'Centil_fSUVR_TOT_CORTMEAN_av45',
  1241. 'Centil_fBP_rsf_TOT_CORTMEAN_av45', 'Centil_fSUVR_rsf_TOT_CORTMEAN_av45', 'Centil_fBP_TOT_CORTMEAN_pib', 'Centil_fSUVR_TOT_CORTMEAN_pib',
  1242. 'Centil_fBP_rsf_TOT_CORTMEAN_pib', 'Centil_fSUVR_rsf_TOT_CORTMEAN_pib']
  1243. stat_all_oas_cn = []
  1244. stat_keys_oas = []
  1245. stat_test = []
  1246. # mask_cn = (other_dx_oas_encode==2)&(other_age_oas>=75)
  1247. mask_MCI = (other_dx_oas_encode[unique_id]==3)
  1248. # mask_cn = ((other_dx_oas_encode[unique_id]==2)|(other_dx_oas_encode[unique_id]==3))
  1249. mask_cn = (other_dx_oas_encode[unique_id]==2)
  1250. other_oas_pred_label_mask = other_oas_pred_label>0
  1251. other_oas_pred_label_avg = other_oas_pred_label_mask.mean(0)[unique_id]
  1252. # other_oas_pred_label_avg = other_oas_pred_label.mean(0)[unique_id]
  1253. oasis_sa_sub_sess_uniq_ = pd.Series(oasis_sa_sub_sess_unique).str.split('_', expand = True).iloc[:,0]
  1254. # #################association of PCD in HABS sa
  1255. half_fc_habs_aging_correct_uniq = []
  1256. sub_ind_ = pd.Series(sub_ind).str.split('_', expand = True).iloc[:,0]
  1257. other_sub_habs = pd.Series(other_sub_sess_habs).str.split('_', expand = True).iloc[:,0]
  1258. habs_sub_uni, uni_idx = np.unique(other_sub_habs, return_index=True)
  1259. age_habs_aging_correct_uniq = []
  1260. sex_habs_aging_correct_uniq = []
  1261. for i in range(len(habs_sub_uni)):
  1262. half_fc_habs_aging_correct_uniq.append(half_fc_habs_other_correct[other_sub_habs == habs_sub_uni[i], :].mean(0))
  1263. age_habs_aging_correct_uniq.append(other_age_habs[other_sub_habs == habs_sub_uni[i]].mean(0))
  1264. sex_habs_aging_correct_uniq.append(other_sex_habs[other_sub_habs == habs_sub_uni[i]][0])
  1265. half_fc_habs_aging_correct_uniq = np.array(half_fc_habs_aging_correct_uniq)
  1266. age_habs_aging_correct_uniq = np.array(age_habs_aging_correct_uniq)
  1267. sex_habs_aging_correct_uniq = np.array(sex_habs_aging_correct_uniq)
  1268. habs_aging_behavior_path = r'I:\data\habs'
  1269. cog_path = os.path.join(habs_aging_behavior_path, 'Cognition_HABS_DataRelease_2.0.csv')
  1270. cog_info = pd.read_csv(cog_path)
  1271. demo_path = os.path.join(habs_aging_behavior_path, 'Demographics_HABS_DataRelease_2.0.csv')
  1272. demo_info = pd.read_csv(demo_path)
  1273. demo_info = demo_info.rename(columns={'SubjID': 'SubjIDshort'})
  1274. clinic_path = os.path.join(habs_aging_behavior_path, 'ClinicalMeasures_HABS_DataRelease_2.0.csv')
  1275. clinic_info = pd.read_csv(clinic_path)
  1276. FDG_path = os.path.join(habs_aging_behavior_path, 'FDG_FS6_SUVR_HABS_DataRelease_2.0.csv')
  1277. FDG_info = pd.read_csv(FDG_path)
  1278. FDG_info['fdg_mean'] = FDG_info.iloc[:,4:].mean(1)
  1279. FTP_path = os.path.join(habs_aging_behavior_path, 'FTP_FS6_SUVR_HABS_DataRelease_2.0.csv')
  1280. FTP_info = pd.read_csv(FTP_path)
  1281. FTP_info['ftp_mean'] = FTP_info.iloc[:,4:].mean(1)
  1282. PIB_path = os.path.join(habs_aging_behavior_path, 'PIB_FS6_DVR_HABS_DataRelease_2.0.csv')
  1283. PIB_info = pd.read_csv(PIB_path)
  1284. PIB_info.loc[PIB_info['StudyArc'] == 'HAB_18m_PET', 'StudyArc'] = 'HAB_3.0'
  1285. FDG_info.loc[FDG_info['StudyArc'] == 'HAB_18m_PET', 'StudyArc'] = 'HAB_3.0'
  1286. FDG_info.loc[FDG_info['StudyArc'] == 'HAB_AI', 'StudyArc'] = 'HAB_6.0'
  1287. pcd_all_habs = pd.merge(cog_info, demo_info, on=['SubjIDshort', 'StudyArc', 'NP_SessionDate'], how='outer')
  1288. pcd_all_habs = pd.merge(pcd_all_habs, clinic_info, on=['SubjIDshort', 'StudyArc', 'NP_SessionDate'], how='outer')
  1289. pcd_all_habs = pd.merge(pcd_all_habs, FDG_info, on=['SubjIDshort', 'StudyArc'], how='outer')
  1290. pcd_all_habs = pd.merge(pcd_all_habs, FTP_info, on=['SubjIDshort', 'StudyArc'], how='outer')
  1291. pcd_all_habs = pd.merge(pcd_all_habs, PIB_info, on=['SubjIDshort', 'StudyArc'], how='outer')
  1292. pcd_all_habs['sub_sess'] = pcd_all_habs['SubjIDshort'].str.split('_', expand = True).iloc[:,-1] + '_' +pcd_all_habs['StudyArc']
  1293. # Build both masks before recoding; match OASIS INRACE (1 = White), non-White = 2, missing stays NaN.
  1294. race_raw = pcd_all_habs['Race'].copy()
  1295. pcd_all_habs['Race'] = np.where(race_raw.isnull(), np.nan, np.where(race_raw == 'W', 1.0, 2.0))
  1296. _, hpc_fc_idx, pcd_idx = np.intersect1d(habs_sub_uni, pd.Series(pcd_all_habs['sub_sess']).str.split('_', expand = True).iloc[:,0], return_indices=True)
  1297. PCD_habs_interest = {}
  1298. PCD_habs_interest['age']= other_age_habs[uni_idx][hpc_fc_idx]
  1299. PCD_habs_interest['sex']= other_sex_habs[uni_idx][hpc_fc_idx]
  1300. PCD_habs_interest['YrsOfEd']= pcd_all_habs['YrsOfEd'][pcd_idx]
  1301. PCD_habs_interest['APOE_haplotype']= pcd_all_habs['APOE_haplotype'][pcd_idx].astype(str).str.count('4')
  1302. PCD_habs_interest['BNT_30']= pcd_all_habs['BNT_30'][pcd_idx]
  1303. PCD_habs_interest['CAT3']= pcd_all_habs['CAT3'][pcd_idx]
  1304. PCD_habs_interest['CAT_Animal_Total']= pcd_all_habs['CAT_Animal_Total'][pcd_idx]
  1305. PCD_habs_interest['CAT_Vegetable_Total']= pcd_all_habs['CAT_Vegetable_Total'][pcd_idx]
  1306. PCD_habs_interest['CAT_Fruit_Total']= pcd_all_habs['CAT_Fruit_Total'][pcd_idx]
  1307. PCD_habs_interest['Digits_Forward']= pcd_all_habs['Digits_Forward'][pcd_idx]
  1308. PCD_habs_interest['Digits_Backwards']= pcd_all_habs['Digits_Backwards'][pcd_idx]
  1309. PCD_habs_interest['DigitSym']= pcd_all_habs['DigitSym'][pcd_idx]
  1310. PCD_habs_interest['FAS_Total']= pcd_all_habs['FAS_Total'][pcd_idx]
  1311. PCD_habs_interest['FAS_F_Total']= pcd_all_habs['FAS_F_Total'][pcd_idx]
  1312. PCD_habs_interest['FAS_A_Total']= pcd_all_habs['FAS_A_Total'][pcd_idx]
  1313. PCD_habs_interest['FAS_S_Total']= pcd_all_habs['FAS_S_Total'][pcd_idx]
  1314. PCD_habs_interest['FCsrt_FNC']= pcd_all_habs['FCsrt_FNC'][pcd_idx]
  1315. PCD_habs_interest['FCsrt_Free']= pcd_all_habs['FCsrt_Free'][pcd_idx]
  1316. PCD_habs_interest['LetterNum_Total']= pcd_all_habs['LetterNum_Total'][pcd_idx]
  1317. PCD_habs_interest['LogicMem_IL']= pcd_all_habs['LogicMem_IL'][pcd_idx]
  1318. PCD_habs_interest['LogicMem_DR']= pcd_all_habs['LogicMem_DR'][pcd_idx]
  1319. PCD_habs_interest['SRT_dr']= pcd_all_habs['SRT_dr'][pcd_idx]
  1320. PCD_habs_interest['SRT_cltr']= pcd_all_habs['SRT_cltr'][pcd_idx]
  1321. PCD_habs_interest['SRT_cr']= pcd_all_habs['SRT_cr'][pcd_idx]
  1322. PCD_habs_interest['SRT_ltr']= pcd_all_habs['SRT_ltr'][pcd_idx]
  1323. PCD_habs_interest['SRT_lts']= pcd_all_habs['SRT_lts'][pcd_idx]
  1324. PCD_habs_interest['SRT_mc']= pcd_all_habs['SRT_mc'][pcd_idx]
  1325. PCD_habs_interest['SRT_str']= pcd_all_habs['SRT_str'][pcd_idx]
  1326. PCD_habs_interest['SRT_tr']= pcd_all_habs['SRT_tr'][pcd_idx]
  1327. PCD_habs_interest['TMT_A']= pcd_all_habs['TMT_A'][pcd_idx]
  1328. PCD_habs_interest['TMT_B']= pcd_all_habs['TMT_B'][pcd_idx]
  1329. PCD_habs_interest['VFDT']= pcd_all_habs['VFDT'][pcd_idx]
  1330. PCD_habs_interest['CDR_Global']= pcd_all_habs['CDR_Global'][pcd_idx]
  1331. PCD_habs_interest['CDR_SB']= pcd_all_habs['CDR_SB'][pcd_idx]
  1332. PCD_habs_interest['CDR_Memory']= pcd_all_habs['CDR_Memory'][pcd_idx]
  1333. PCD_habs_interest['MMSE_Total']= pcd_all_habs['MMSE_Total'][pcd_idx]
  1334. PCD_habs_interest['MMSE_Orientation']= pcd_all_habs['MMSE_Orientation'][pcd_idx]
  1335. PCD_habs_interest['MMSE_ImmRecall']= pcd_all_habs['MMSE_ImmRecall'][pcd_idx]
  1336. PCD_habs_interest['MMSE_AttnCalc']= pcd_all_habs['MMSE_AttnCalc'][pcd_idx]
  1337. PCD_habs_interest['MMSE_DelRecall']= pcd_all_habs['MMSE_DelRecall'][pcd_idx]
  1338. PCD_habs_interest['MMSE_Language']= pcd_all_habs['MMSE_Language'][pcd_idx]
  1339. PCD_habs_interest['MMSE_Pentagons']= pcd_all_habs['MMSE_Pentagons'][pcd_idx]
  1340. PCD_habs_interest['GDS_Total']= pcd_all_habs['GDS_Total'][pcd_idx]
  1341. PCD_habs_interest['Hachinski']= pcd_all_habs['Hachinski'][pcd_idx]
  1342. PCD_habs_interest['Race']= pcd_all_habs['Race'][pcd_idx]
  1343. PCD_keys = ['Race', 'YrsOfEd', 'sex', 'age', 'APOE_haplotype', 'BNT_30', 'CAT3', 'CAT_Animal_Total', 'CAT_Vegetable_Total', 'CAT_Fruit_Total',
  1344. 'Digits_Forward', 'Digits_Backwards', 'DigitSym', 'FAS_Total', 'FAS_F_Total', 'FAS_A_Total', 'FAS_S_Total', 'FCsrt_FNC', 'FCsrt_Free', 'LetterNum_Total',
  1345. 'LogicMem_IL', 'LogicMem_DR', 'SRT_dr', 'SRT_cltr', 'SRT_cr', 'SRT_ltr', 'SRT_lts', 'SRT_mc', 'SRT_str', 'SRT_tr', 'TMT_A', 'TMT_B', 'VFDT', 'CDR_Global',
  1346. 'CDR_SB', 'CDR_Memory', 'MMSE_Total', 'MMSE_Orientation', 'MMSE_ImmRecall', 'MMSE_AttnCalc', 'MMSE_DelRecall', 'MMSE_Language', 'MMSE_Pentagons',
  1347. 'GDS_Total', 'Hachinski']
  1348. df_pcd_habs = pd.DataFrame(PCD_habs_interest).astype(float)
  1349. # ---- Phenotype group comparisons ----
  1350. stat_all_habs_cn = []
  1351. stat_keys_habs = []
  1352. stat_test = []
  1353. other_habs_pred_label_mask = other_habs_pred_label>0
  1354. other_habs_pred_label_avg = other_habs_pred_label_mask.mean(0)[uni_idx[hpc_fc_idx]]
  1355. df_all = {'age': np.r_[df_oas['age'], df_pcd_habs['age']],
  1356. # 'sub': np.r_[np.delete(HPC_sa_sub_uni,idx), oasis_sa_sub_sess_uniq_, habs_sub_uni[hpc_fc_idx]],
  1357. 'sub': np.r_[oasis_sa_sub_sess_uniq_, habs_sub_uni[hpc_fc_idx]],
  1358. 'sex': np.r_[df_oas['sex'], df_pcd_habs['sex']],
  1359. 'cluster_label': np.r_[other_oas_pred_label_avg, other_habs_pred_label_avg],
  1360. # White = 1, non-White = 2 in both cohorts.
  1361. 'race': np.r_[np.where(df_oas['INRACE'].isnull(), np.nan, np.where(df_oas['INRACE'] == 1, 1.0, 2.0)),
  1362. df_pcd_habs['Race']],
  1363. 'educ': np.r_[df_oas['INEDUC'], df_pcd_habs['YrsOfEd']],
  1364. 'dx': np.r_[df_oas['dx'], other_dx_habs[uni_idx[hpc_fc_idx]]],
  1365. 'tmt_a': np.r_[df_oas['TRAILA'], df_pcd_habs['TMT_A']],
  1366. 'tmt_b': np.r_[df_oas['TRAILB'], df_pcd_habs['TMT_B']],
  1367. # OASIS apoe is already an e4 count (see PCD_data[:,1] above).
  1368. 'apoe': np.r_[df_oas['apoe'], df_pcd_habs['APOE_haplotype']],
  1369. 'DELSEV': np.r_[df_oas['DELSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1370. 'HALLSEV': np.r_[df_oas['HALLSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1371. 'AGITSEV': np.r_[df_oas['AGITSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1372. 'DEPDSEV': np.r_[df_oas['DEPDSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1373. 'ANXSEV': np.r_[df_oas['ANXSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1374. 'ELATSEV': np.r_[df_oas['ELATSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1375. 'APASEV': np.r_[df_oas['APASEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1376. 'DISNSEV': np.r_[df_oas['DISNSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1377. 'IRRSEV': np.r_[df_oas['IRRSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1378. 'MOTSEV': np.r_[df_oas['MOTSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1379. 'NITESEV': np.r_[df_oas['NITESEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1380. 'APPSEV': np.r_[df_oas['APPSEV'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1381. 'mmse': np.r_[df_oas['mmse'], df_pcd_habs['MMSE_Total']],
  1382. 'cdr': np.r_[df_oas['cdr'], df_pcd_habs['CDR_Global']],
  1383. 'commun': np.r_[df_oas['commun'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1384. 'homehobb': np.r_[df_oas['homehobb'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1385. 'perscare': np.r_[df_oas['perscare'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1386. 'judgment': np.r_[df_oas['judgment'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1387. 'memory': np.r_[df_oas['memory'], df_pcd_habs['CDR_Memory']],
  1388. 'orient': np.r_[df_oas['orient'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1389. 'sumbox': np.r_[df_oas['sumbox'], df_pcd_habs['CDR_SB']],
  1390. 'RAVLT_immediate': np.r_[[np.nan for i in range(len(df_oas['sex']))], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1391. 'RAVLT_learning': np.r_[[np.nan for i in range(len(df_oas['sex']))], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1392. 'RAVLT_forgetting': np.r_[[np.nan for i in range(len(df_oas['sex']))], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1393. 'RAVLT_perc_forgetting': np.r_[[np.nan for i in range(len(df_oas['sex']))], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1394. 'LogMem_Delay': np.r_[df_oas['MEMUNITS'], df_pcd_habs['LogicMem_DR']],
  1395. 'LogMem_immediate': np.r_[df_oas['LOGIMEM'], df_pcd_habs['LogicMem_IL']],
  1396. 'CFT_ANIMALS': np.r_[df_oas['ANIMALS'], df_pcd_habs['CAT_Animal_Total']],
  1397. 'CFT_VEG': np.r_[df_oas['VEG'], df_pcd_habs['CAT_Vegetable_Total']],
  1398. 'DIGIF': np.r_[df_oas['DIGIF'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1399. 'DIGIB': np.r_[df_oas['DIGIB'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1400. 'BOSTON': np.r_[df_oas['BOSTON'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1401. 'BILLS': np.r_[df_oas['BILLS'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1402. 'TAXES': np.r_[df_oas['TAXES'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1403. 'SHOPPING': np.r_[df_oas['SHOPPING'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1404. 'GAMES': np.r_[df_oas['GAMES'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1405. 'STOVE': np.r_[df_oas['STOVE'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1406. 'MEALPREP': np.r_[df_oas['MEALPREP'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1407. 'EVENTS': np.r_[df_oas['EVENTS'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1408. 'PAYATTN': np.r_[df_oas['PAYATTN'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1409. 'REMDATES': np.r_[df_oas['REMDATES'], [np.nan for i in range(len(df_pcd_habs['sex']))]],
  1410. 'TRAVEL': np.r_[df_oas['TRAVEL'], [np.nan for i in range(len(df_pcd_habs['sex']))]]}
  1411. df_all = pd.DataFrame(df_all)
  1412. stat_discovery_cn = []
  1413. stat_keys_discovery = []
  1414. stat_test = []
  1415. mask_cn = (df_all['dx']==2)#&(df_all['age']>=75)
  1416. PCD_all_keys = list(df_all.columns)
  1417. for i, key in enumerate(PCD_all_keys):
  1418. if key in {'sub', 'cluster_label', 'dx'}:
  1419. continue
  1420. stat_keys_discovery.append(key)
  1421. fea = df_all[key]
  1422. fea_demlike_cn = fea[mask_cn&(df_all['cluster_label']>=.5)]
  1423. fea_demlike_cn = fea_demlike_cn[np.isfinite(fea_demlike_cn)]
  1424. fea_salike_cn = fea[mask_cn&(df_all['cluster_label']<.5)]
  1425. fea_salike_cn = fea_salike_cn[np.isfinite(fea_salike_cn)]
  1426. fea_unstable_cn = fea[mask_cn&(df_all['cluster_label']!=0)&(df_all['cluster_label']!=1)]
  1427. fea_unstable_cn = fea_unstable_cn[np.isfinite(fea_unstable_cn)]
  1428. if len(fea_demlike_cn)>5 and len(fea_salike_cn)>5 and (len(fea_salike_cn) + len(fea_demlike_cn))>20 and (len(set(fea_salike_cn)) >1 or len(set(fea_demlike_cn)) > 1):
  1429. F_cn,p_cn=kruskal(fea_salike_cn, fea_demlike_cn)
  1430. if key == 'sex' or key == 'race':
  1431. [F_cn,p_cn,_,_]=chi2_contingency([[np.sum(fea_salike_cn==1), np.sum(fea_demlike_cn==1)],
  1432. [np.sum((fea_salike_cn==2)|(fea_salike_cn==0)), np.sum((fea_demlike_cn==2)|(fea_demlike_cn==0))]])
  1433. cohens_d = cohen_d(fea_salike_cn, fea_demlike_cn)
  1434. stat_discovery_cn.append([F_cn, p_cn, cohens_d, len(fea_demlike_cn), len(fea_salike_cn)])
  1435. if key == 'sex' or key == 'race':
  1436. plt.figure(figsize=(5,10))
  1437. ax = plt.gca()
  1438. count = np.sum(fea_salike_cn==1)
  1439. ax.bar(0, count, color = red, width = 1, fill=False, edgecolor= red, linewidth=5, hatch = '+')
  1440. count = np.sum(fea_demlike_cn==1)
  1441. ax.bar(1, count, color = blue, width = 1, fill=False, edgecolor= blue, linewidth=5, hatch = '+')
  1442. if key == 'race':
  1443. count = np.sum(fea_salike_cn==2)
  1444. else:
  1445. count = np.sum(fea_salike_cn==2)
  1446. ax.bar(2, count, color = red, width = 1, fill=False, edgecolor= red, linewidth=5, hatch = 'x')
  1447. if key == 'race':
  1448. count = np.sum(fea_demlike_cn==2)
  1449. else:
  1450. count = np.sum(fea_demlike_cn==2)
  1451. ax.bar(3, count, color = blue, width = 1, fill=False, edgecolor= blue, linewidth=5, hatch = 'x')
  1452. ax.set_yticks((0, 200, 400, 600, 800))
  1453. ax.set_xticks([1.5])
  1454. ax.set_xticklabels(['CN'])
  1455. ax.set_xlabel(key, **font2)
  1456. ax.spines['top'].set_color('none') # 设置上‘脊梁’为红色
  1457. ax.spines['right'].set_color('none') # 设置上‘脊梁’为无色
  1458. else:
  1459. result1 = np.r_[fea_salike_cn, fea_demlike_cn]
  1460. dx_label = np.r_[['CN' for i in range(len(fea_salike_cn)+len(fea_demlike_cn))]]
  1461. cluster_label = np.r_[['SA-like' for i in range(len(fea_salike_cn))], ['DEM-like' for i in range(len(fea_demlike_cn))]]
  1462. df = pd.DataFrame({'data': result1, 'DX': dx_label, 'Cluster': cluster_label})
  1463. plt.figure(figsize=(5,10))
  1464. ax = plt.gca()
  1465. my_pal = {'SA-like': blue, 'DEM-like': red}
  1466. # my_pal = {'SA-like': blue, 1: red, 2: 'limegreen', 3: RGB(0,.8,0.1)}
  1467. sns.stripplot(data=df, x="DX", y="data", hue="Cluster", palette = my_pal, ax = ax, dodge=True, legend = False, size = 5, jitter=0.2)
  1468. sns.violinplot(data=df, x="DX", y="data", hue="Cluster", palette = my_pal, fill=False, ax = ax, saturation=1, inner = 'box')
  1469. ax.scatter([-0.2,0.2],y= np.r_[fea_salike_cn.median(), fea_demlike_cn.median()],c="white",s = 100, edgecolor = 'grey', zorder=3, linewidth = 2)
  1470. plt.xlim(-1, 1)
  1471. for collection in ax.collections:
  1472. if isinstance(collection, matplotlib.collections.PolyCollection):
  1473. collection.set_edgecolor(collection.get_facecolor())
  1474. collection.set_facecolor('none')
  1475. for h in ax.legend_.legendHandles:
  1476. if isinstance(h, matplotlib.patches.Rectangle):
  1477. h.set_edgecolor(h.get_facecolor())
  1478. h.set_facecolor('none')
  1479. h.set_linewidth(2.5)
  1480. ax.get_legend().remove()
  1481. unit = (np.max(fea[np.isfinite(fea)]) - np.min(fea[np.isfinite(fea)]))//2
  1482. if abs(unit) < 1:
  1483. unit = round((np.max(fea[np.isfinite(fea)]) - np.min(fea[np.isfinite(fea)]))/2, 2)
  1484. ax.set_yticks(np.arange(np.min(fea[np.isfinite(fea)])-unit, np.max(fea[np.isfinite(fea)])+unit, unit))
  1485. else:
  1486. ax.set_yticks(np.arange(np.min(fea[np.isfinite(fea)])-unit, np.max(fea[np.isfinite(fea)])+unit, unit).astype(int))
  1487. if key == 'age':
  1488. ax.set_yticks(np.arange(20, 110, 30))
  1489. plt.ylim(20, 110)
  1490. ax.set_ylabel(key)
  1491. ax.spines['top'].set_color('none') # 设置上‘脊梁’为红色
  1492. ax.spines['right'].set_color('none') # 设置上‘脊梁’为无色
  1493. # plt.savefig(r'F:\PHD\learning\project\super_age\more_sub\SA_defined_ricado\cluster\stats_compare\0.5\{}_discovery_nodelete.svg'.format(key), bbox_inches = 'tight')
  1494. else:
  1495. stat_discovery_cn.append([np.nan, np.nan, np.nan, len(fea_demlike_cn), len(fea_salike_cn)])
  1496. stat_discovery_cn = np.array(stat_discovery_cn)
  1497. valid = np.isfinite(stat_discovery_cn[:, 1])
  1498. stat_discovery_cn_fdr = stat_discovery_cn.copy()
  1499. if valid.any():
  1500. stat_discovery_cn_fdr[valid, 1] = multipletests(stat_discovery_cn[valid, 1], method='fdr_bh')[1]
  1501. stat_keys_discovery_nonan = np.array(stat_keys_discovery)[valid]
  1502. ###################################demograph in discovery
  1503. sub_ind_ = pd.Series(sub_ind).str.split('_', expand = True).iloc[:,0]
  1504. sub_ind_uni, sub_idx = np.unique(sub_ind_, return_index=True)
  1505. oasis_demo_interest_classification = []
  1506. for sub in sub_ind_uni:
  1507. if sum(oasis_demo_sub == sub) >= 1:
  1508. oasis_demo_interest_classification.append(oasis_demo[['INRACE', 'INEDUC']][oasis_demo_sub == sub].values[0,:])
  1509. else:
  1510. if sum(oasis_demo_sub2 == sub) >= 1:
  1511. oasis_demo_interest_classification.append(oasis_demo2[['INRACE', 'INEDUC']][oasis_demo_sub2 == sub].values[0,:])
  1512. else:
  1513. oasis_demo_interest_classification.append([np.nan, np.nan])
  1514. oasis_demo_interest_classification = np.array(oasis_demo_interest_classification)
  1515. habs_demo_interest_classification = []
  1516. habs_demo_sub = pcd_all_habs["SubjIDshort"].str.split('_', expand = True).iloc[:,-1]
  1517. for sub in sub_ind_uni:
  1518. if sum(habs_demo_sub == sub) >= 1:
  1519. habs_demo_interest_classification.append(pcd_all_habs[['Race', 'YrsOfEd']][habs_demo_sub == sub].values[0,:])
  1520. else:
  1521. habs_demo_interest_classification.append([np.nan, np.nan])
  1522. habs_demo_interest_classification = np.array(habs_demo_interest_classification)
  1523. oasis_demo_interest_classification[np.isnan(oasis_demo_interest_classification).sum(1)!=0] = habs_demo_interest_classification[np.isnan(oasis_demo_interest_classification).sum(1)!=0]
  1524. dx_ind_uni = dx_ind[sub_idx]
  1525. sex_ind_uni = sex_ind[sub_idx]
  1526. age_ind_uni = age_ind[sub_idx]
  1527. site_ind_uni = site_ind[sub_idx]
  1528. chi2_contingency([[np.sum(sex_ind_uni[(dx_ind_uni==0)]==1),np.sum(sex_ind_uni[(dx_ind_uni==1)]==1)],
  1529. [np.sum(sex_ind_uni[(dx_ind_uni==0)]==2),np.sum(sex_ind_uni[(dx_ind_uni==1)]==2)]])
  1530. # chi2_contingency([[np.sum(sex_ind_uni[(sex_ind_uni==0)&(site_ind_uni==1)]==1),np.sum(sex_ind_uni[(sex_ind_uni==1)&(site_ind_uni==1)]==1)],
  1531. # [np.sum(sex_ind_uni[(sex_ind_uni==0)&(site_ind_uni==1)]==2),np.sum(sex_ind_uni[(sex_ind_uni==1)&(site_ind_uni==1)]==2)]])
  1532. Q1 = np.percentile(age_ind_uni[dx_ind_uni==1], 25)
  1533. Q3 = np.percentile(age_ind_uni[dx_ind_uni==1], 75)
  1534. print(Q1)
  1535. print(Q3)
  1536. ranksums(age_ind_uni[dx_ind_uni==0], age_ind_uni[dx_ind_uni==1])
  1537. chi2_contingency([[np.sum(oasis_demo_interest_classification[(dx_ind_uni==0)]==1),np.sum(oasis_demo_interest_classification[(dx_ind_uni==1)]==1)],
  1538. [np.sum(oasis_demo_interest_classification[(dx_ind_uni==0)]==2),np.sum(oasis_demo_interest_classification[(dx_ind_uni==1)]==2)]])
  1539. # chi2_contingency([[np.sum(sex_ind_uni[(sex_ind_uni==0)&(site_ind_uni==1)]==1),np.sum(sex_ind_uni[(sex_ind_uni==1)&(site_ind_uni==1)]==1)],
  1540. # [np.sum(sex_ind_uni[(sex_ind_uni==0)&(site_ind_uni==1)]==2),np.sum(sex_ind_uni[(sex_ind_uni==1)&(site_ind_uni==1)]==2)]])
  1541. Q1 = np.percentile(oasis_demo_interest_classification[(dx_ind_uni==0)&np.isfinite(oasis_demo_interest_classification[:,1]),1], 25)
  1542. Q3 = np.percentile(oasis_demo_interest_classification[(dx_ind_uni==0)&np.isfinite(oasis_demo_interest_classification[:,1]),1], 75)
  1543. np.median(oasis_demo_interest_classification[(dx_ind_uni==0)&np.isfinite(oasis_demo_interest_classification[:,1]),1])
  1544. print(Q1)
  1545. print(Q3)
  1546. ranksums(oasis_demo_interest_classification[(dx_ind_uni==0)&np.isfinite(oasis_demo_interest_classification[:,1]),1], oasis_demo_interest_classification[(dx_ind_uni==1)&np.isfinite(oasis_demo_interest_classification[:,1]),1])
  1547. site_indx = []
  1548. for i,sub in enumerate(sub_ind_uni):
  1549. if 'HAB' in sub:
  1550. site_indx.append(i)
  1551. site_indx = np.array(site_indx)

clustering.py at commit ba44ae2, no license · at the source

Overview

Authors: Kanhao Zhao1,2,3, Hua Xie4, Gregory A. Fonzo5, Nancy B. Carlisle6, Tovia Jacobs7, Ricardo S. Osorio8, Arpana Church3, Feng Vankee Lin1,9,10, Yu Zhang1,9,10, Alzheimer’s Disease Neuroimaging Initiative
  1. Department of Psychiatry and Behavioral Sciences, Stanford University School of Medicine, Stanford, CA, USA
  2. Department of Bioengineering, Lehigh University, Bethlehem, PA, USA
  3. Goodman-Luskin Microbiome Center, Vache and Tamar Manoukian Division of Digestive Diseases, David Geffen School of Medicine, University of California, Los Angeles, Los Angeles, CA, USA
  4. Center for Neuroscience Research, Children’s National Hospital, Washington, DC, USA
  5. Center for Psychedelic Research and Therapy, Department of Psychiatry and Behavioral Sciences, Dell Medical School, The University of Texas at Austin, Austin, TX, USA
  6. Department of Psychology, Lehigh University, Bethlehem, PA, USA
  7. Penn State College of Medicine, Hershey, PA, USA
  8. Department of Psychiatry, New York University Grossman School of Medicine, New York, NY, USA
  9. Wu Tsai Neurosciences Institute, Stanford University, Stanford, CA, USA
  10. Stanford Institute for Human-Centered Artificial Intelligence, Stanford, CA, USA
Journal: Science advances, volume 12, issue 45, article eaed9351
Dates: received 15 November 2025; accepted 2 October 2026; published online 4 November 2026; in print November 2026
Type: Research article · Language: English
License: CC BY-NC
Identifiers: DOI · PMCID PMC13733855
Status: code verified (how the code is found and verified)
Categories: Alzheimer's / dementia (population)
Methods: Connectivity, Statistics, Smoothing, state filtering, decompositions, Machine learning, Preprocessing, fMRI & imaging
Journal subjects: Neuroscience, Health and Medicine
Funding: National Science Foundation (2019035); national institutes of health (R21AG080425, R01MH129694, R01AG081768, R01MH132784); Brain & Behavior Research Foundation; Alzheimer's Association (AARG-22-972541); Stanford Knight Initiative for Brain Resilience and the Rosenkranz Foundation grant (RAR1-03); Lehigh University (CORE grant); One Mind - Baszucki Brain Research Fund; SEAL Future Fund
Citations: not cited yet (Europe PMC); 71 references in the paper

Abstract

Identifying the neurobiological basis of cognitive vulnerability is essential for preventing Alzheimer’s disease (AD). We derived the Alzheimer’s Resilience-Vulnerability Connectome (ARC) by contrasting SuperAgers (SA), an extreme phenotype of preserved late-life memory, with AD using resting-state fMRI. ARC distinguished SA from AD in a discovery cohort (N = 290; AUC = 0.85) and replicated independently (N = 143), involving prefrontal, temporal, and insular networks and associating with brain age. Applied to cognitively unimpaired adults (discovery: N = 818; replication: N = 497), ARC-based subtyping revealed SA-like and AD-like subgroups with comparable baseline cognition but divergent longitudinal trajectories. AD-like individuals exhibited faster cognitive decline, greater amyloid-β accumulation, and higher AD conversion risk. Exploratory GWAS nominated CLYBL and FRMD6 as candidate novel loci associated with the subtype difference. These findings suggest that ARC captures a continuous connectomic dimension of cognitive aging spanning SA, cognitively typical aging, and AD, highlighting the potential of functional connectomic variation for early risk stratification in AD.

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

Repositories

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

Zenodo 20073656

License: CC-BY-4.0
State: the link answers, verified on 7 November 2026
Evidence: files inventoried
Size: 0 files, 0 scripts
Software Heritage: not checked
Found in: “Data, code, and materials availability:”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 7 November 2026: the link answers (HTTP 200)
  • 7 November 2026: the link answers (HTTP 200)

zhangyubrain/Alzheimers-resilient-connectome

License: none: the authors keep all their rights
State: the link answers, verified on 7 November 2026
Evidence: files inventoried
Commit: ba44ae26a27c55a13b3eb69fcdfae8361e73a5ba, 5 November 2026
Languages: Python (3)
Size: 4 files, 3 scripts
Software Heritage: not archived
Found in: “Data, code, and materials availability:”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (3 files), pandas (3 files), Matplotlib (2 files), PyBIDS (2 files), scikit-learn (2 files), SciPy (2 files), seaborn (2 files), statsmodels (2 files), XGBoost (2 files), neuroCombat (1 file)
Availability: 1 check, the latest on 7 November 2026: the link answers
  • 7 November 2026: the link answers
4 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;
  • 3 scripts, each with its path and the digest of its content;
  • 3 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data, code, and materials availability

All data needed to evaluate and reproduce the results in the paper are present in the paper and/or the Supplementary Materials. Requests for the data should be submitted to different public database portals. The OASIS-3 dataset is publicly available at www.oasis-brains.org/. The ADNI dataset is publicly available at https://adni.loni.usc.edu/. The HABS dataset is publicly available at https://habs.mgh.harvard.edu/. The code can be found at https://zenodo.org/records/20073656 and https://github.com/zhangyubrain/Alzheimers-resilient-connectome. This study did not generate new materials.

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

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 7 November 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 10 authors, 8 funders, 64 references.

Cite

This paper

Zhao, K., Xie, H., Fonzo, G. A., Carlisle, N. B., Jacobs, T., Osorio, R. S., Church, A., Lin, F. V., Zhang, Y., & Alzheimer’s Disease Neuroimaging Initiative. (2026). A functional connectome identifies vulnerability to cognitive decline and Alzheimer’s disease progression. Science advances, 12(45), eaed9351.

BibTeX

@article{zhao2026functional,
author = {Zhao, Kanhao and Xie, Hua and Fonzo, Gregory A. and Carlisle, Nancy B. and Jacobs, Tovia and Osorio, Ricardo S. and Church, Arpana and Lin, Feng Vankee and Zhang, Yu and {Alzheimer’s Disease Neuroimaging Initiative}},
title = {{A functional connectome identifies vulnerability to cognitive decline and Alzheimer’s disease progression}},
journal = {Science advances},
year = {2026},
month = nov,
volume = {12},
number = {45},
pages = {eaed9351},
publisher = {American Association for the Advancement of Science},
issn = {2375-2548},
pmcid = {PMC13733855}
}

RIS

TY - JOUR
AU - Zhao, Kanhao
AU - Xie, Hua
AU - Fonzo, Gregory A.
AU - Carlisle, Nancy B.
AU - Jacobs, Tovia
AU - Osorio, Ricardo S.
AU - Church, Arpana
AU - Lin, Feng Vankee
AU - Zhang, Yu
AU - Alzheimer’s Disease Neuroimaging Initiative
TI - A functional connectome identifies vulnerability to cognitive decline and Alzheimer’s disease progression
T2 - Science advances
J2 - Sci Adv
PY - 2026
DA - 2026/11/06
VL - 12
IS - 45
SP - eaed9351
SN - 2375-2548
PB - American Association for the Advancement of Science
LA - en
ER -

CSL-JSON

{
"id": "pmcid:PMC13733855",
"type": "article-journal",
"title": "A functional connectome identifies vulnerability to cognitive decline and Alzheimer’s disease progression",
"container-title": "Science advances",
"author": [
{
"family": "Zhao",
"given": "Kanhao"
},
{
"family": "Xie",
"given": "Hua"
},
{
"family": "Fonzo",
"given": "Gregory A."
},
{
"family": "Carlisle",
"given": "Nancy B."
},
{
"family": "Jacobs",
"given": "Tovia"
},
{
"family": "Osorio",
"given": "Ricardo S."
},
{
"family": "Church",
"given": "Arpana"
},
{
"family": "Lin",
"given": "Feng Vankee"
},
{
"family": "Zhang",
"given": "Yu"
},
{
"literal": "Alzheimer’s Disease Neuroimaging Initiative"
}
],
"container-title-short": "Sci Adv",
"volume": "12",
"issue": "45",
"page": "eaed9351",
"PMCID": "PMC13733855",
"ISSN": "2375-2548",
"publisher": "American Association for the Advancement of Science",
"language": "en",
"issued": {
"date-parts": [
[
2026,
11,
6
]
]
}
}

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.1001/jamanetworkopen.2024.20479 [code]
Dementia Subtypes Defined Through Neuropsychiatric Symptom-Associated Brain Connectivity Patterns.
Journal: JAMA network open
In common: PyBIDS, statsmodels, seaborn, 5 other tools, Alzheimer's / dementia, 4 references, 3 authors
[2] doi:10.1038/s41380-025-02974-6 [code]
Deep graph learning of multimodal brain networks defines treatment-predictive signatures in major depression.
Journal: Molecular psychiatry
In common: 5 references, 3 authors
[3] doi:10.1093/geront/gnaf277 [code]
What characterizes the exceptional cognition of superagers? A systematic review of multidomain biomarkers of successful cognitive aging.
Journal: The Gerontologist
In common: 9 references
[4] doi:10.1016/j.xcrm.2025.102151 [code]
Contrastive functional connectivity defines neurophysiology-informed symptom dimensions in major depression.
Journal: Cell reports. Medicine
In common: scikit-learn, pandas, SciPy, 2 other tools, 2 references, 2 authors
[5] doi:10.1038/s41398-022-02134-2
Transdiagnostic connectome signatures from resting-state fMRI predict individual-level intellectual capacity.
Journal: Translational psychiatry
In common: 3 references, 2 authors
[6] doi:10.1002/hbm.26453 [code]
Robust hierarchically organized whole-brain patterns of dysconnectivity in schizophrenia spectrum disorders observed after personalized intrinsic network topography.
Journal: Human brain mapping
In common: neuroCombat, PyBIDS, seaborn, 4 other tools, 5 references
[7] doi:10.1093/braincomms/fcae205 [code]
SuperAging functional connectomics from resting-state functional MRI.
Journal: Brain communications
In common: scikit-learn, SciPy, Matplotlib, 1 other tool, Alzheimer's / dementia, 7 references
[8] doi:10.1016/j.dcn.2023.101337 [code]
A multi-sample evaluation of the measurement structure and function of the modified monetary incentive delay task in adolescents.
Journal: Developmental cognitive neuroscience
In common: PyBIDS, statsmodels, seaborn, 5 other tools, 5 references
[9] doi:10.1016/j.neurobiolaging.2022.06.008 [code]
Predicting future cognitive decline from non-brain and multimodal brain imaging data in healthy and pathological aging.
Journal: Neurobiology of aging
In common: PyBIDS, seaborn, scikit-learn, 4 other tools, Alzheimer's / dementia, 5 references
[10] doi:10.1007/s00234-026-04103-8 [code]
Enhanced detection of subtle cortical abnormalities in focal epilepsy using 7 T MRI surface-based models and graph neural networks.
Journal: Neuroradiology
In common: neuroCombat, PyBIDS, statsmodels, 6 other tools, 1 reference

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Add the badge to the code's README

OSCR: the badge of this paper

If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.

Markdown
<!-- oscr-badge:start -->
[![OSCR](https://openscicode.org/badge/repo/zenodo:20073656.svg)](https://openscicode.org/badge/repo/zenodo:20073656)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/repo/zenodo:20073656.svg
   :target: https://openscicode.org/badge/repo/zenodo:20073656
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/repo/zenodo:20073656"><img src="https://openscicode.org/badge/repo/zenodo:20073656.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->

On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".

If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge 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: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.

Report a mismatch between the code and the paper · Report a code error (signed in)

Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.

Report a reproduction failure (signed in)

Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.