Lifespan brain structural variation reveals shared organization across mental health conditions
The 10 matches
- [1] § Methods › Contextualization of derived cortical axes ↔ code/main/2_Principal_axes.ipynb, lines 463–537 · score 0.92 · spatial auto correlations, variogram permutations, weighted connectome, ENIGMA Toolbox, functional connectivity, connectome hub
- [2] § Methods › Association of axes of deviations with symptom magnitude ↔ code/main/2_Principal_axes.ipynb, lines 1851–1892 · score 0.72 · ADOS CSS, STAI_T, HDRS, BP, symptom, MDD
- [3] § Methods › Main axes of deviation ↔ code/main/2_Principal_axes.ipynb, lines 1464–1512 · score 0.67 · PC1 PC2 subspace, principal angles, perturbation, norm, component, PCA
- [4] § Methods › Normative modeling ↔ code/hbr/PCNToolkit_transfer_cortical_thickness_example.ipynb, lines 289–382 · score 0.64 · response variable, PCNToolkit, Normative models, held, covariates, regional
- [5] § Methods › Normative modeling ↔ PCNToolkit_transfer_cortical_thickness_example.ipynb, lines 292–385 · score 0.64 · response variable, PCNToolkit, Normative models, held, covariates, regional
- [6] § Methods › Heterogeneity of extreme deviations ↔ code/main/3_Extreme_deviation_hubs.ipynb, lines 1025–1162 · score 0.62 · propensity score matching, extreme deviation, positive deviations, sex, SA, disorders
- [7] § Methods › Network embedding of extreme deviations ↔ code/main/2_Principal_axes.ipynb, lines 463–537 · score 0.60 · HCP YA, weighted connectome, network, hubs, normative
- [8] § Methods › Group differences and variability in deviation scores ↔ code/main/helpers.py, lines 51–153 · score 0.59 · logistic regression, propensity score matching
- [9] § Methods › Network embedding of extreme deviations ↔ code/main/3_Extreme_deviation_hubs.ipynb, lines 657–711 · score 0.56 · weighted connectome, extreme deviation, HCP, hubs, network, transdiagnostic
- [10] § Methods › Normative modeling ↔ code/hbr/NormModel_SHASH_parallelized.py, lines 113–164 · score 0.51 · model parameters, heteroskedastic, SHASH, HBR, sex, deviations
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Jupyter notebook · 2,074 lines · 68 KB · no license · 4 matches
- # %% [markdown]
- # ## 2: Axes of deviations
- #
- # This script contains analyses that aim to identify dominant axes of structural deviations across diagnostic boundaries. It:
- #
- # Applies a PCA to all z-scores to extract main axes of (unsigned) deviations from the predicted norm. It also computes group differences between PAT and HC PC scores and contextualizes the axes with normative principles of cortical organization, including: a cytoarchitectonic atlas (Mesulam), the Sensorimotor-association (S-A) axis, and network organization (based on a HCP-YA subsample).
- #
- # It contains the following sections:
- # 1) Apply PCA to deviation scores and plot result
- # 2) Test and visualize case-control differences in PC scores
- # 3) Contextualize the axes with normative principles of cortical organization
- # 4) Test association with symptom severity
- # 5) Test association with PCs derived in the reference cohort only
- #
- # (c) Meike Hettwer, 2026
- # %%
- ## use enigma_norm environment
- # =============================================================================
- # Setup & Imports
- # =============================================================================
- import os
- from pathlib import Path
- from itertools import combinations, product
- import numpy as np
- import pandas as pd
- import nibabel as nib
- from tqdm import tqdm
- from scipy.stats import gaussian_kde, skewnorm, spearmanr, zscore, ttest_ind, linregress
- from statsmodels.stats.multitest import multipletests
- import statsmodels.api as sm
- from sklearn.decomposition import PCA
- from sklearn.preprocessing import StandardScaler
- from sklearn.model_selection import train_test_split
- from scipy.linalg import subspace_angles
- # Plotting & Surface visualizations & Conversions
- import matplotlib.pyplot as plt
- import seaborn as sns
- from matplotlib.colors import ListedColormap
- from matplotlib.cm import register_cmap
- import matplotlib.cm as cm
- import matplotlib.colors as mcolors
- import ptitprince as pt
- from enigmatoolbox.utils.parcellation import parcel_to_surface
- from enigmatoolbox.utils import surface_to_parcel
- from enigmatoolbox.plotting import plot_cortical, plot_subcortical
- from enigmatoolbox.datasets import load_sc, load_fc
- #from enigmatoolbox.permutation_testing import spin_test#, shuf_test
- from brainspace.plotting import plot_hemispheres
- from brainspace.datasets import load_conte69
- from brainsmash.mapgen.base import Base
- from brainsmash.mapgen import eval as bseval
- # Colormaps
- from cmcrameri import cm
- # Custom helpers
- import helpers
- # =============================================================================
- # Paths / config
- # =============================================================================
- # define your personal paths in this text file to run the script on your data
- paths = helpers.read_paths("set_paths.txt")
- # Access paths
- base_dir = paths["base_dir"]
- data_dir = paths["data_dir"]
- resource_dir = paths["resource_dir"] # the src directory
- raw_dir = paths["raw_dir"]
- wdir = os.path.join(base_dir, "ScrFun") #code
- out_dir = os.path.join(data_dir, "generated")
- z_dir = os.path.join(out_dir, "hbr_results") #centiles
- fig_dir = os.path.join(base_dir, "Figures", "Figure2")
- # loading some example enigma data to get the correct roi label order for plotting
- # cortical rois
- sum_stats = pd.read_csv(os.path.join(resource_dir, "scz_case-controls_CortThick.csv"))
- enigma_order = sum_stats.Structure
- # subcortical rois
- sum_stats = pd.read_csv(os.path.join(resource_dir, "scz_case-controls_SubVol.csv"))
- sctx_order = sum_stats.Structure.to_list()
- sctx_order_no_vent = sctx_order.copy()
- sctx_order_no_vent.remove('LLatVent')
- sctx_order_no_vent.remove('RLatVent')
- regions_by_modality = {
- 'CT': enigma_order,
- 'SA': enigma_order,
- 'sctx': sctx_order_no_vent
- }
- # =============================================================================
- # Colormaps
- # =============================================================================
- # Register Crameri maps
- register_cmap('Crameri Managua', cm.managua)
- register_cmap('Crameri Oslo', cm.oslo)
- register_cmap('Crameri Oslo rev', cm.oslo_r)
- register_cmap('Crameri Lapaz', cm.lapaz)
- register_cmap('Crameri Lipari', cm.lipari_r)
- register_cmap('Crameri Cork', cm.cork)
- register_cmap('Crameri Bilbao', cm.bilbao)
- # Seaborn colormaps
- mako = sns.color_palette("mako", as_cmap=True)
- flare = sns.color_palette("flare", as_cmap=True)
- # Global plotting settings
- sns.set_theme(style="white")
- plt.rcParams['pdf.fonttype'] = 42
- plt.rcParams['ps.fonttype'] = 42
- plt.rcParams['svg.fonttype'] = 'none'
- plt.rc('font', size=10)
- nan_color = (0.7, 0.7, 0.7, 1)
- # =============================================================================
- # ENIGMA Data & Structures
- # =============================================================================
- modality = ['CT', 'SA', 'sctx']
- # Disorder orders
- disorder_order_dev = ['ANX', 'ASD', 'BP', 'MDD', 'OCD', 'SCZ', 'Developmental', 'control']
- disorder_order = ['ANX', 'ASD', 'BP', 'MDD', 'OCD', 'SCZ', 'control']
- disorder_order_pat = ['ANX', 'ASD', 'BP', 'MDD', 'OCD', 'SCZ']
- disorder_cmap = ['#2E4757', '#438477', '#FFC487', '#E9735B', '#D3436E', '#6D2D51', '#AEAEAE']
- # set threshold for extreme deviations
- z_extreme = 1.96
- # -----------------------------
- # Reproducibility
- # -----------------------------
- SEED = 42
- pca_abs = True
- # more color action
- n_colors = 5
- # Extract 5 evenly spaced colors
- cmap = plt.get_cmap('Crameri Cork')
- colors = [cmap(i / (n_colors - 1)) for i in range(n_colors)]
- colors[0] = mcolors.to_hex('#B2B2B2')
- cork5 = mcolors.ListedColormap(colors, name='Cork5')
- plt.register_cmap(cmap=cork5)
- cork4_colors = colors[1:]
- # =============================================================================
- # Surfaces & Labels
- # =============================================================================
- surf_lh, surf_rh = load_conte69()
- aparc_conte = np.loadtxt(os.path.join(resource_dir, "aparc_conte69.csv"), delimiter=',')
- # mask the midbrain and CC if we have 71 DK values where there should be 68 (e.g. after re-sampling)
- midbrain_parcels = [0, 4, 39]
- mask = np.isin(aparc_conte, midbrain_parcels)
- keep_parcels = range(71)
- keep_parcels = np.delete(keep_parcels, midbrain_parcels)
- # prepare brainsmash permutations
- #subctx
- centroids_csv = os.path.join(resource_dir,"aseg_subcortex_centroids_shortnames.csv")
- centroids_df = pd.read_csv(centroids_csv).set_index("Structure")
- distmat = np.loadtxt(os.path.join(resource_dir, "aseg_euclidean_distmat.csv"), delimiter=",")
- # cortex
- cortical_centroids_csv = os.path.join(resource_dir,"dk68_cortical_centroids_enigma_order.csv")
- cortical_centroids_df = pd.read_csv(cortical_centroids_csv).set_index("Structure")
- cortical_distmat = np.loadtxt(os.path.join(resource_dir, "dk68_cortical_euclidean_distmat_enigma_order.csv"), delimiter=",")
- n_perm = 10000
- # =============================================================================
- ## load other useful resources
- # =============================================================================
- # get the SA axis from: https://github.com/PennLINC/S-A_ArchetypalAxis/tree/main/FSaverage5
- # parcelated:
- SA_dk = np.load(os.path.join(resource_dir, 'SA_axis_DK.npy'))
- # Mesulam
- mesulam_dk = np.load(os.path.join(resource_dir, 'Mesulam_DK.npy'))
- # %% [markdown]
- # # 1) Identifying main axes of deviations by applying PCA across participant's z scores
- #
- # In this section, we apply a pca to absolute z-scores to get a general insight into patterns of magnified deviations from the norm (no matter in which direction). We apply the PCA to the transdiagnostic sample, including HCs. Hewever, we will also compare it to results derived from applying the PCA in (50% of) HCs only - confirming that derived patterns are not driven by e.g. one disorder.
- # %%
- # Apply PCA to absolute z-scores of each modality separately to get interpretable dimensions
- for mod in modality:
- print(mod)
- # Load the deviation scores for the current modality
- df_te_Z = pd.read_csv(os.path.join(z_dir, f"{mod}_Z_enigma_test.csv"))
- # extract subsamples
- imaging_dev = df_te_Z[df_te_Z['disorder']=='Developmental']
- imaging_pat = df_te_Z[(df_te_Z['diagnosis'] == 1) & (df_te_Z['disorder'] != 'Developmental')] # patients that are not from the developmental cohorts
- imaging_hc = df_te_Z[df_te_Z['diagnosis']==-1] # healthy controls
- imaging_enigma = df_te_Z[df_te_Z['disorder']!='Developmental'] #exclude only patients from developmental datasets (HBN, PNC) - keep patients and controls otherwise --> this is what we use here
- imaging_cols = list(regions_by_modality[mod])
- missing_cols = sorted(set(imaging_cols) - set(imaging_enigma.columns))
- if missing_cols:
- raise KeyError(f"Missing expected columns for {mod}: {missing_cols}")
- scaler = StandardScaler()
- if pca_abs == True:
- X_enigma_scaled = scaler.fit_transform(imaging_enigma[imaging_cols].abs())
- elif pca_abs == False:
- X_enigma_scaled = scaler.fit_transform(imaging_enigma[imaging_cols])
- # Fit PCA on scaled data
- n_components = min(10, len(imaging_cols))
- pca = PCA(n_components=n_components, svd_solver="auto", random_state=0)
- X_enigma_pcs = pca.fit_transform(X_enigma_scaled)
- # Get PCA scores for each group
- pat_mask = imaging_enigma['diagnosis'] == 1
- hc_mask = imaging_enigma['diagnosis'] == -1
- X_pat_pcs = X_enigma_pcs[pat_mask, :]
- X_hc_pcs = X_enigma_pcs[hc_mask, :]
- # Get scores for each subject group
- pca_pat_scores_df = pd.DataFrame(
- X_pat_pcs,
- columns=[f'PC{i+1}' for i in range(n_components)],
- index=imaging_enigma.loc[pat_mask, 'participant_id']
- )
- pca_hc_scores_df = pd.DataFrame(
- X_hc_pcs,
- columns=[f'PC{i+1}' for i in range(n_components)],
- index=imaging_enigma.loc[hc_mask, 'participant_id']
- )
- pca_all_scores_df = pd.DataFrame(
- X_enigma_pcs,
- columns=[f'PC{i+1}' for i in range(n_components)],
- index=imaging_enigma['participant_id']
- )
- # Get loadings (components)
- # Each row is a PC, each column is a feature
- pca_loadings = pd.DataFrame(pca.components_.T, # transpose to get features x PCs
- index=imaging_cols,
- columns=[f'PC{i+1}' for i in range(n_components)])
- pca_loadings.to_csv(os.path.join(out_dir , f'z_pca_loadings_{mod}.csv'))
- # extract variance explained
- explained_var_ratio = pca.explained_variance_ratio_ #relative to other components
- explained_var = pca.explained_variance_
- print('explained variance ratio')
- print(mod + str(explained_var_ratio))
- print('explained variance')
- print(mod + str(explained_var))
- # plot Scree plot
- plt.figure(figsize=(4, 4))
- plt.plot(np.arange(1, len(explained_var_ratio*100)+1), explained_var_ratio*100 , marker='o', linestyle='-')
- plt.title(f'Scree Plot {mod}')
- plt.xlabel('Principal Component')
- plt.ylabel('Variance Explained (%)')
- plt.xticks(np.arange(1, len(explained_var)+1, step=1))
- plt.grid(False)
- plt.tight_layout()
- plt.savefig(os.path.join(fig_dir, f"screeplot_pca_{mod}.svg"),format="svg")
- plt.show()
- ## scatter for full sample
- scores_combined = imaging_enigma[['participant_id', 'disorder']].merge(
- pca_all_scores_df, on='participant_id'
- )
- scores_combined.head()
- scores_combined.to_csv(os.path.join(out_dir, f'z_PCA_scores_{mod}.csv'))
- # sanity checks
- # Check unique disorders
- print(scores_combined['disorder'].unique())
- plt.figure(figsize=(4, 4))
- # Ensure 'disorder' is a categorical variable in desired order for plotting
- scores_combined['disorder'] = pd.Categorical(
- scores_combined['disorder'],
- categories=disorder_order,
- ordered=True
- )
- scores_combined = scores_combined.sort_values('disorder')
- # Plot with specified hue order
- sns.scatterplot(
- data=scores_combined,
- x='PC1',
- y='PC2',
- hue='disorder',
- hue_order=disorder_order,
- palette=disorder_cmap[:len(disorder_order)],
- s=6,
- alpha=0.6,
- edgecolor='none',
- linewidth=0.3
- )
- plt.title(f'PCs {mod}')
- plt.xlabel('PC1')
- plt.ylabel('PC2')
- plt.grid(False)
- plt.tight_layout()
- plt.savefig(os.path.join(fig_dir, f'PCA_scatter_{mod}.svg'), format='svg')
- plt.show()
- # plot on the brain surface
- if mod in ['CT', 'SA']:
- mod_PC12 = [None]*2
- mod_PC1_conte = parcel_to_surface(pca_loadings.loc[enigma_order]['PC1'].values, 'aparc_conte69')
- mod_PC1_conte[mask] = np.nan
- mod_PC2_conte = parcel_to_surface(pca_loadings.loc[enigma_order]['PC2'].values, 'aparc_conte69')
- mod_PC2_conte[mask] = np.nan
- mod_PC12[0] = mod_PC1_conte
- mod_PC12[1] = mod_PC2_conte
- save_dir = os.path.join(fig_dir, f'{mod}_unimodal_pc_z_loadings_full_sample.png')
- if mod == 'CT':
- plot_hemispheres(surf_lh, surf_rh, array_name=mod_PC12, size=(1200*2,800*2), cmap=['BuPu','rocket_r'],label_text=['PC1','PC2'],
- color_bar=True, zoom=1.2, interactive=False, embed_nb=True, filename=save_dir,
- nan_color=nan_color, screenshot=True, background=(1,1,1), color_range=[(0.05,0.18), (-0.25,0.20)],
- transparent_bg=True)
- ## Statistics ##
- # test group differences between patients and controls
- results = []
- for pc in [f'PC{i+1}' for i in range(2)]:# only look at first 2 PCs
- for disorder in disorder_order_pat:
- extr_scores = scores_combined.copy().drop(columns={'disorder'})
- extr_scores = extr_scores.merge(imaging_enigma, on='participant_id')
- # apply propensity score matching to extract matched hc sample based on age and sex
- df_pat_matched, df_hc_matched = helpers.propensity_score_match(
- df_pat=extr_scores.loc[extr_scores['disorder'] == disorder],
- df_ctrl=extr_scores.loc[extr_scores['disorder'] == 'control'],
- covariates=['Age', 'Sex'],
- random_state=SEED
- )
- # compute t-test
- t, p = ttest_ind(df_pat_matched[pc], df_hc_matched[pc], equal_var=False)
- # compute Cohen's d
- nx = len(df_pat_matched[pc])
- ny = len(df_hc_matched[pc])
- mean_x = np.mean(df_pat_matched[pc])
- mean_y = np.mean(df_hc_matched[pc])
- var_x = np.var(df_pat_matched[pc], ddof=1)
- var_y = np.var(df_hc_matched[pc], ddof=1)
- pooled_sd = np.sqrt(((nx - 1) * var_x + (ny - 1) * var_y) / (nx + ny - 2))
- d = (mean_x - mean_y) / pooled_sd
- results.append({
- 'disorder': disorder,
- 'PC': pc,
- 'd': d,
- 'p': p
- })
- results_df = pd.DataFrame(results)
- results_df
- # FDR correction
- reject, pvals_corr, _, _ = multipletests(results_df['p'], method='fdr_bh')
- results_df['p_fdr'] = pvals_corr # FDR-corrected
- results_df['sig'] = reject # boolean significance flag used for thresholding
- print(results_df)
- # Pivot results to have one row per disorder with t-values for PC1 and PC2
- plot_df = results_df.pivot(index="disorder", columns="PC", values="d").reset_index()
- # Mark disorders significant if any of PC1 or PC2 is significant
- sig_status = results_df.loc[results_df["PC"].isin(["PC1", "PC2"])] \
- .groupby("disorder")["sig"].any().reset_index()
- plot_df = plot_df.merge(sig_status, on="disorder", how="left")
- # plot
- plt.figure(figsize=(4,4))
- ax = plt.gca()
- if mod == 'CT':
- ax.set_xlim(-0.55, 0.55)
- ax.set_ylim(-0.55, 0.55)
- ax.set_xticks([-0.5,0, 0.5])
- ax.set_yticks([-0.5,0, 0.5])
- else:
- ax.set_xlim(-0.55, 0.55)
- ax.set_ylim(-0.55, 0.55)
- ax.set_xticks([-0.5,0, 0.5])
- ax.set_yticks([-0.5,0, 0.5])
- # reference lines
- ax.axhline(0, color="grey", linestyle="--", linewidth=0.8)
- ax.axvline(0, color="grey", linestyle="--", linewidth=0.8)
- # scatter
- sns.scatterplot(
- data=plot_df,
- x="PC1",
- y="PC2",
- hue="disorder",
- palette=disorder_cmap[:6],
- s=280,
- edgecolor=plot_df["sig"].map(lambda x: "black" if x else "none"),
- linewidth=1.2,
- ax=ax
- )
- ax.set_title(f"group difference {mod}")
- ax.set_xlabel("Cohen's d (PC1)")
- ax.set_ylabel("Cohen's d (PC2)")
- plt.tight_layout()
- plt.savefig(os.path.join(fig_dir, f'{mod}_ttest_pca.svg'),format='svg')
- plt.show()
- # %% [markdown]
- # # 2) Visualize Case-control differences in PC scores
- # %%
- for mod in modality:
- # Load data
- scores_all = pd.read_csv(os.path.join(out_dir, f'z_PCA_scores_{mod}.csv'))
- control_label = 'control'
- disorders = disorder_order_pat
- pcs = ['PC1', 'PC2']
- # Setup figure
- sns.set(style="white", font_scale=1.2)
- fig, axes = plt.subplots(2, 1, figsize=(5, 6), sharex=True)
- # Plot both PCs
- demo_data = df_te_Z[df_te_Z['disorder']!= 'Developmental'] # exclude PNC adn HBN patients
- helpers.plot_pc(demo_data, 'PC1', axes[0],scores_all)
- helpers.plot_pc(demo_data, 'PC2', axes[1],scores_all)
- # Final figure formatting
- axes[1].set_xlabel('Disorder')
- for ax in axes:
- ax.tick_params(axis='x', rotation=45)
- plt.tight_layout()
- plt.savefig(os.path.join(fig_dir, f'PC_scores_boxplot_{mod}.svg'),format='svg')
- plt.show()
- # %% [markdown]
- # # 3) Contextualizing the axes with normative principles of cortical organization
- #
- # Including: Connectivity, S-A axis and Cytoarchitecture
- # %% [markdown]
- # 1st Contextualization: HCP connectome hubs
- # %%
- # -----------------------------------------------------
- # Load HCP structural and functional connectivity
- # -----------------------------------------------------
- # get normative / HCP-YA connectome from ENIGMA toolbox
- fc_ctx, fc_ctx_labels, _, _ = load_fc()
- sc_ctx, sc_ctx_labels, _, _ = load_sc()
- # Multiply SC and FC to get a weighted connectome,
- # then threshold top 20% per node, then compute degree centrality
- network_hcp = fc_ctx * sc_ctx
- network_hcp_bin = np.zeros(network_hcp.shape)
- for i in range(len(network_hcp)):
- threshold = np.percentile(network_hcp[i], 80)
- network_hcp_bin[i, network_hcp[i] > threshold] = 1
- network_hubs_hcp = network_hcp_bin.sum(axis=0)
- # Compute correlations and variogram test for PC1 and PC2
- pcs = ['PC1', 'PC2']
- mods = ['CT', 'SA']
- colors = {'PC1': '#2E4757', 'PC2': '#438477'}
- ylims = { #for CT only
- 'PC1': (0.0505, 0.185),
- 'PC2': (-0.255, 0.205)
- }
- for mod in mods:
- pc_loadings = pd.read_csv(os.path.join(out_dir, f'z_pca_loadings_{mod}.csv'))
- # run variogram permutation to control for spatial auto-correlation
- results = {}
- for pc in pcs:
- r_val = spearmanr(network_hubs_hcp, pc_loadings[pc])[0]
- p_spin = helpers.brainsmash_pvalue_spearman(network_hubs_hcp, pc_loadings[pc], cortical_distmat, nsurr=n_perm, seed=SEED)
- results[pc] = {'r': r_val, 'p_spin': p_spin}
- print(f"{mod} {pc}: r = {r_val:.3f}, p_spin = {p_spin:.3f}")
- # create 1 x 2 figure
- fig, axes = plt.subplots(1, 2, figsize=(10, 5), sharex=False, sharey=False)
- for i, pc in enumerate(pcs):
- ax = axes[i]
- sns.regplot(
- x=network_hubs_hcp,
- y=pc_loadings[pc],
- scatter_kws={'s': 12, 'alpha': 1, 'color': colors[pc]},
- line_kws={'color': colors[pc], 'lw': 1.5},
- ax=ax
- )
- if mod == 'CT':
- ax.set_ylim(ylims[pc])
- ax.set_title(
- f"{mod} {pc}\nr = {results[pc]['r']:.2f}, p_spin = {results[pc]['p_spin']:.3f}"
- )
- ax.set_xlabel("HCP Network Hub Degree (top 20%)")
- ax.set_ylabel("PC Loading")
- ax.set_box_aspect(1)
- plt.tight_layout()
- plt.savefig(os.path.join(fig_dir, f'PC_loadings_vs_HCP_hubs_{mod}_1x2.svg'), format='svg')
- plt.show()
- # %% [markdown]
- # B) 2nd contextualization: SA axis
- # %%
- for mod in mods:
- pc_loadings = pd.read_csv(os.path.join(out_dir, f'z_pca_loadings_{mod}.csv'))
- # run variogram permutation to control for spatial auto-correlation
- results = {}
- for pc in pcs:
- r_val = spearmanr(SA_dk, pc_loadings[pc])[0]
- p_spin = helpers.brainsmash_pvalue_spearman(SA_dk, pc_loadings[pc], cortical_distmat, nsurr=n_perm, seed=SEED)
- results[pc] = {'r': r_val, 'p_spin': p_spin}
- print(f"{mod} {pc}: r = {r_val:.3f}, p_spin = {p_spin:.3f}")
- fig, axes = plt.subplots(1, 2, figsize=(10, 5), sharex=False, sharey=False)
- for i, pc in enumerate(pcs):
- ax = axes[i]
- sns.regplot(
- x=SA_dk,
- y=pc_loadings[pc],
- scatter_kws={'s': 12, 'alpha': 1, 'color': colors[pc]},
- line_kws={'color': colors[pc], 'lw': 1.5},
- ax=ax
- )
- ax.set_title(
- f"{mod} {pc}\nr = {results[pc]['r']:.2f}, p_spin = {results[pc]['p_spin']:.3f}"
- )
- ax.set_xlabel("S-A rank")
- ax.set_ylabel("PC Loading")
- ax.set_box_aspect(1)
- if mod == 'CT':
- ax.set_ylim(ylims[pc])
- plt.tight_layout()
- plt.savefig(os.path.join(fig_dir, f'PC_loadings_vs_SA_rank_{mod}_1x2.svg'), format='svg')
- plt.show()
- # %% [markdown]
- # C) 3rd contextualization: Cytoarchitecture (using the Mesulam atlas)
- # %%
- xlims = { #for CT only - add a bit of space to make sure whisters are visible
- 'PC1': (0.051, 0.19),
- 'PC2': (-0.26, 0.21)
- }
- for mod in ['CT','SA']:
- # load data
- pc_loadings = pd.read_csv(os.path.join(out_dir, f'z_pca_loadings_{mod}.csv'))
- # prepare dataframe to stratify loadings by mesulam class
- pc1_mesulam = pd.DataFrame({'PC': pc_loadings['PC1'], 'Mesulam': mesulam_dk})
- pc2_mesulam = pd.DataFrame({'PC': pc_loadings['PC2'], 'Mesulam': mesulam_dk})
- # plot
- fig, axes = plt.subplots(1, 2, figsize=(5, 2.5), sharey=True)
- y_labels = ['Paralimbic', 'Heteromodal', 'Unimodal', 'Idiotypic']
- # PC1 RainCloud
- pt.RainCloud(
- x='Mesulam', y='PC',
- data=pc1_mesulam,
- orient='h',
- ax=axes[0],
- palette=cork4_colors,
- bw=0.3,
- width_viol=1,
- move=0.01,
- alpha=0.6,
- pointplot=False,
- dodge=False
- )
- axes[0].set_title('PC1', fontsize=16)
- axes[0].set_yticks(range(4))
- axes[0].set_yticklabels(y_labels, fontsize=12)
- axes[0].set_xlabel('')
- if mod == 'CT':
- axes[0].set_xlim(xlims['PC1'])
- # PC2 RainCloud
- pt.RainCloud(
- x='Mesulam', y='PC',
- data=pc2_mesulam,
- orient='h',
- ax=axes[1],
- palette=cork4_colors,
- bw=0.3,
- width_viol=1,
- move=0.01,
- alpha=0.6,
- pointplot=False,
- dodge=False
- )
- axes[1].set_title('PC2', fontsize=16)
- axes[1].set_yticks(range(4))
- axes[1].set_xlabel('')
- axes[1].set_ylabel('')
- if mod == 'CT':
- axes[1].set_xlim(xlims['PC2'])
- y_ticks = range(4)
- for ax in axes:
- ax.set_yticks(y_ticks)
- ax.set_yticklabels(y_labels, fontsize=12)
- plt.xticks(fontsize=12)
- plt.tight_layout()
- plt.savefig(os.path.join(fig_dir, f'{mod}_Z_pc1_pc2_Mesulam.svg'), type='svg')
- plt.show()
- # %% [markdown]
- # # Association of the PCs of deviation with main axes of Group shift (Cohen's d) and variability
- # %%
- # For main manuscript / CT
- pc = pd.read_csv(os.path.join(out_dir, 'z_pca_loadings_CT.csv'), index_col=0)
- cohen = pd.read_csv(os.path.join(out_dir, 'CT_Cohens_d_supplement.csv'), index_col=0)
- variance = pd.read_csv(os.path.join(out_dir, 'CT_Std_supplement.csv'), index_col=0)
- pc1 = pc["PC1"]
- pc2 = pc["PC2"]
- # use helper functions to extract data
- cohen_cols = helpers.get_disorder_columns(cohen, disorders=disorder_order_pat, coltype="Cohen")
- variance_cols = helpers.get_disorder_columns(variance, disorders=disorder_order_pat, coltype="Std")
- # Build Cohen's d matrix: ROIs × Disorders
- cohens_df = pd.DataFrame({
- dis: cohen[cohen_cols[dis]].values
- for dis in cohen_cols.keys()
- })
- # Use ROI names as index
- cohens_df.index = cohen['Structure'] if 'Structure' in cohen.columns else cohen.index
- variance_df = pd.DataFrame({
- dis: variance[variance_cols[dis]].values
- for dis in variance_cols.keys()
- })
- variance_df.index = variance['Structure'] if 'Structure' in variance.columns else variance.index
- ## apply PCAs
- # Align ROIs
- cohens_df = cohens_df.loc[pc1.index]
- variance_df = variance_df.loc[pc1.index]
- # Standardize across disorders (column-wise)
- scaler = StandardScaler()
- # PCA on Cohen's d
- cohen_scaled = scaler.fit_transform(cohens_df.values)
- pca_d = PCA(n_components=5)
- cohen_components = pca_d.fit_transform(cohen_scaled)
- print("Cohen PCA explained variance ratio:")
- print(pca_d.explained_variance_ratio_)
- # First component (dominant shared pattern)
- cohen_pc1_map = pd.Series(
- cohen_components[:, 0],
- index=cohens_df.index
- )
- # PCA on variance
- # Standardize across disorders (column-wise)
- scaler = StandardScaler()
- variance_scaled = scaler.fit_transform(variance_df.values)
- # PCA on Variability
- pca_var = PCA(n_components=5)
- variance_components = pca_var.fit_transform(variance_scaled)
- print("Variance PCA explained variance ratio:")
- print(pca_var.explained_variance_ratio_)
- # First component (dominant shared pattern)
- variance_pc1_map = pd.Series(
- variance_components[:, 0],
- index=variance_df.index
- )
- results = []
- # Ensure alignment
- pc1 = pc1.loc[cohen_pc1_map.index]
- pc2 = pc2.loc[cohen_pc1_map.index]
- # Align PCA signs, as the sign is arbitrary and may be flipped
- if spearmanr(cohen_pc1_map, pc1)[0] < 0:
- cohen_pc1_map *= -1
- if spearmanr(variance_pc1_map, pc1)[0] < 0:
- variance_pc1_map *= -1
- # %%
- # Load CT PCs
- pc_loadings_ct = pd.read_csv(os.path.join(out_dir, 'z_pca_loadings_CT.csv'), index_col=0)
- colors = {
- 'PC1': '#2E4757',
- 'PC2': '#438477'
- }
- maps = {
- 'Cohen': cohen_pc1_map,
- 'Variability': variance_pc1_map
- }
- # Compute correlations + brainsmash permutations
- results = {}
- for label, cortical_map in maps.items():
- results[label] = {}
- x = cortical_map.loc[pc_loadings_ct.index]
- for pc in pcs:
- y = pc_loadings_ct[pc]
- r_val, _ = spearmanr(x, y)
- p_spin = helpers.brainsmash_pvalue_spearman(x.values, y.values, cortical_distmat, nsurr=n_perm, seed=SEED)
- results[label][pc] = {
- 'r': r_val,
- 'p_spin': p_spin
- }
- print(f"{label} vs {pc}: r = {r_val:.3f}, p_spin = {p_spin:.4f}")
- fig, axes = plt.subplots(2, 2, figsize=(6, 6), sharey=False)
- for row, (label, cortical_map) in enumerate(maps.items()):
- x = cortical_map.loc[pc_loadings_ct.index]
- for col, pc in enumerate(pcs):
- ax = axes[row, col]
- y = pc_loadings_ct[pc]
- sns.regplot(
- x=x,
- y=y,
- scatter_kws={'s': 18, 'alpha': 0.8, 'color': colors[pc]},
- line_kws={'color': colors[pc], 'lw': 1.5},
- ax=ax)
- ax.set_title(
- f"{label} vs {pc}\n"
- f"r = {results[label][pc]['r']:.2f}, "
- f"p_spin = {results[label][pc]['p_spin']:.3f}",
- fontsize=10)
- ax.set_xlabel("Group PC")
- ax.set_ylabel("CT deviation PC loading")
- ax.set_box_aspect(1)
- if mod == 'CT':
- ax.set_ylim(ylims[pc])
- plt.tight_layout()
- plt.savefig(
- os.path.join(fig_dir, 'Cohen_vs_Variability_CT_PCs_2x2.svg'),
- format='svg'
- )
- plt.show()
- # %% [markdown]
- # # Visualize on the cortex
- # %%
- # Convert to surface space
- cohen_pc1_surface = parcel_to_surface(cohen_pc1_map.values, 'aparc_conte69')
- # mask midbrain
- cohen_pc1_surface[mask]=np.nan
- variance_pc1_surface = parcel_to_surface(variance_pc1_map.values, 'aparc_conte69')
- variance_pc1_surface[mask]=np.nan
- # plot group shift axis
- save_dir = os.path.join(fig_dir, 'Cohensd_PC1.png')
- plot_hemispheres(
- surf_lh,
- surf_rh,
- array_name=cohen_pc1_surface,
- size=(1200, 800),
- cmap='OrRd',
- color_bar=True,
- zoom=1.2,
- interactive=False,
- embed_nb=True,
- screenshot=True,
- background=(1, 1, 1),
- color_range=(-4.5, 3.5),
- transparent_bg=True,
- nan_color=nan_color,
- filename=save_dir
- )
- # plot variability
- save_dir = os.path.join(fig_dir, 'Variability_PC1.png')
- plot_hemispheres(
- surf_lh,
- surf_rh,
- array_name=variance_pc1_surface,
- size=(1200, 800),
- cmap='Crameri Lapaz',
- color_bar=True,
- zoom=1.2,
- interactive=False,
- embed_nb=True,
- screenshot=True,
- background=(1, 1, 1),
- color_range=(-3.8, 3.1),
- transparent_bg=True,
- nan_color=nan_color,
- filename=save_dir)
- # %% [markdown]
- # Plot the PC components for SA and SCTX
- # %%
- SA_pcs = pd.read_csv(os.path.join(out_dir, 'z_pca_loadings_SA.csv'),index_col=0)
- mod_PC12 = [None]*2
- mod_PC1_conte = parcel_to_surface(SA_pcs.loc[enigma_order]['PC1'].values, 'aparc_conte69')
- mod_PC1_conte[mask] = np.nan
- mod_PC2_conte = parcel_to_surface(SA_pcs.loc[enigma_order]['PC2'].values, 'aparc_conte69')
- mod_PC2_conte[mask] = np.nan
- mod_PC12[0] = mod_PC1_conte
- mod_PC12[1] = mod_PC2_conte
- save_dir = os.path.join(fig_dir, 'SA_unimodal_pc_z_loadings_pat.png')
- plot_hemispheres(surf_lh, surf_rh, array_name=mod_PC12, size=(1200*2,800*2), cmap=['BuPu','magma_r'],label_text=['PC1','PC2'],
- color_bar=True, zoom=1.2, interactive=False, embed_nb=True, filename=save_dir,
- nan_color=nan_color, screenshot=True, background=(1,1,1), color_range=[(0.06,0.18), (-0.13,0.47)],
- transparent_bg=True)
- plot_hemispheres(surf_lh, surf_rh, array_name=mod_PC12, size=(1200,500), cmap=['BuPu','magma_r'],label_text=['PC1','PC2'],
- color_bar=True, zoom=1.2, interactive=False, embed_nb=True, filename=save_dir,
- nan_color=nan_color, screenshot=False, background=(1,1,1), color_range=[(0.06,0.18), (-0.13,0.47)],
- transparent_bg=True)
- # %%
- # and for the subcortex
- sctx_pcs = pd.read_csv(os.path.join(out_dir, 'z_pca_loadings_sctx.csv'),index_col=0)
- sctx_pcs
- for pc in ['PC1','PC2']:
- this_pc = sctx_pcs[pc].T
- this_pc['LLatVent'] = np.nan
- this_pc['RLatVent'] = np.nan
- if pc == 'PC1':
- cmap = 'BuPu'
- color_range=(0.19, 0.32)
- if pc == 'PC2':
- cmap='magma_r'
- color_range=(-0.29, 0.43)
- this_pc = this_pc[sctx_order]
- this_pc_plot = this_pc.values.T.flatten().astype(float)
- # Save figure
- save_dir = os.path.join(fig_dir, f'Sctx_unimodal_{pc}_z_loadings.png')
- plot_subcortical(
- array_name=this_pc_plot,
- size=(1600, 800),
- cmap=cmap,
- screenshot=True,
- color_bar=True,
- color_range=color_range,
- ventricles=True,
- embed_nb=True,
- interactive=False,
- filename=save_dir
- )
- # %% [markdown]
- # Fit PCA in 50% of HCS and apply it to patients and remaining HCs
- #
- # Aim: To see if our derived axes capture normative patterns of covarying deviations that are also present in the unaffected reference cohort. We will use 50% of the HC sample to fit the PCA - sampled across 5 age bins and approx. sex + site balanced across the 2 HC splits
- # %%
- disorder_cmap = ['#2E4757', '#438477', '#FFC487', '#E9735B', '#D3436E', '#6D2D51', '#AEAEAE']
- fit_sample = 'hc'
- for mod in modality:
- print(mod)
- os.chdir(out_dir)
- # Load the deviation scores for the current modality
- df_te_Z = pd.read_csv(os.path.join(z_dir, f'{mod}_Z_enigma_test.csv'))
- # extract subsamples
- imaging_dev = df_te_Z[df_te_Z['disorder']=='Developmental']
- imaging_pat = df_te_Z[(df_te_Z['diagnosis'] == 1) & (df_te_Z['disorder'] != 'Developmental')]
- imaging_hc = df_te_Z[df_te_Z['diagnosis']==-1].copy()
- imaging_enigma = df_te_Z[df_te_Z['disorder']!='Developmental'] #exclude only patients from developmental datasets (HBN, PNC)
- if mod in ['CT', 'SA']:
- imaging_cols = enigma_order
- else:
- imaging_cols = sctx_order_no_vent
- # compute PCA in all individuals
- if fit_sample == 'pat':
- continue
- elif fit_sample == 'hc':
- # split the HC data into 2 subsample, matched by age, sex and site
- # Create age bins to stratify continuous age
- imaging_hc['Age_bin'] = pd.qcut(imaging_hc['Age'], q=5, labels=False) # 5 quantile bins
- # We'll stratify by Age_bin, Sex, and Site
- imaging_hc['strata'] = imaging_hc['Age_bin'].astype(str) + '_' + imaging_hc['Sex'].astype(str) + '_' + imaging_hc['Site']
- # Split, allowing small imbalances
- try:
- train_idx, test_idx = train_test_split(
- imaging_hc.index,
- test_size=0.5,
- stratify=imaging_hc['strata'], # stratify on age_bin + sex
- random_state=42
- )
- except ValueError:
- # fallback: stratify on Site only if some strata have only 1 subject
- train_idx, test_idx = train_test_split(
- imaging_hc.index,
- test_size=0.5,
- stratify=imaging_hc['Site'],
- random_state=42
- )
- group1 = imaging_hc.loc[train_idx].copy()
- group2 = imaging_hc.loc[test_idx].copy()
- # 4. Check balance
- print("Group1 distributions:")
- print(group1[['Age', 'Sex', 'Site']].describe(include='all'))
- print("Group2 distributions:")
- print(group2[['Age', 'Sex', 'Site']].describe(include='all'))
- # Drop helper columns
- group1 = group1.drop(columns=['Age_bin', 'strata'])
- group2 = group2.drop(columns=['Age_bin', 'strata'])
- # 1. Fit PCA on HC Group 1
- n_components = 10
- pca = PCA(n_components=n_components)
- scaler = StandardScaler()
- # Fit scaler on Group1 and transform
- #X_group1_scaled = scaler.fit_transform(group1[imaging_cols].abs())
- if pca_abs == True:
- X_group1_scaled = scaler.fit_transform(group1[imaging_cols].abs())
- elif pca_abs == False:
- X_group1_scaled = scaler.fit_transform(group1[imaging_cols])
- # Fit PCA in Group1 (HC)
- X_group1_pcs = pca.fit_transform(X_group1_scaled)
- if pca_abs == True:
- # 2. Apply same Scaler and PCA to Group2 (HC)
- X_group2_scaled = scaler.transform(group2[imaging_cols].abs())
- X_group2_pcs = pca.transform(X_group2_scaled)
- # 3. Apply same PCA to patient data
- X_pat_scaled = scaler.transform(imaging_pat[imaging_cols].abs())
- X_pat_pcs = pca.transform(X_pat_scaled)
- elif pca_abs == False:
- # 2. Apply same Scaler and PCA to Group2 (HC)
- X_group2_scaled = scaler.transform(group2[imaging_cols])
- X_group2_pcs = pca.transform(X_group2_scaled)
- # 3. Apply same PCA to patient data
- X_pat_scaled = scaler.transform(imaging_pat[imaging_cols])
- X_pat_pcs = pca.transform(X_pat_scaled)
- # build dfs
- pc_columns = [f'PC{i+1}' for i in range(n_components)]
- group1_pcs_df = pd.DataFrame(X_group1_pcs, columns=pc_columns, index=group1['participant_id'])
- group2_pcs_df = pd.DataFrame(X_group2_pcs, columns=pc_columns, index=group2['participant_id'])
- pat_pcs_df = pd.DataFrame(X_pat_pcs, columns=pc_columns, index=imaging_pat['participant_id'])
- # Get loadings (components)
- # Each row is a PC, each column is a feature
- pca_loadings = pd.DataFrame(pca.components_.T, # transpose to get features x PCs
- index=imaging_cols,
- columns=[f'PC{i+1}' for i in range(n_components)])
- pca_loadings.to_csv(os.path.join(out_dir, f'z_pca_loadings_{mod}_fit_in_hc.csv'))
- ## Scree plot
- explained_var = pca.explained_variance_ratio_ *100 #in % for plotting
- plt.figure(figsize=(4, 4))
- plt.plot(np.arange(1, len(explained_var)+1), explained_var , marker='o', linestyle='-')
- plt.title(f'Scree Plot {mod}')
- plt.xlabel('Principal Component')
- plt.ylabel('Variance Explained (%)')
- plt.xticks(np.arange(1, len(explained_var)+1, step=1))
- plt.grid(False)
- plt.tight_layout()
- plt.savefig(os.path.join(fig_dir, f"screeplot_pca_{mod}_fit_in_hc.svg"),format="svg")
- plt.show()
- # 1. Combine PCA scores for patients with demographic data
- scores_combined_pat = imaging_pat[['participant_id', 'disorder', 'Age', 'Sex', 'Site']].merge(
- pat_pcs_df.reset_index().rename(columns={'index':'participant_id'}),
- on='participant_id'
- )
- # 2. Or look at HCs (HC_test)
- hc_scores_df = group2_pcs_df
- hc_metadata = group2[['participant_id','disorder','Age','Sex','Site']]
- scores_combined_hc = hc_metadata.merge(
- hc_scores_df.reset_index().rename(columns={'index':'participant_id'}),
- on='participant_id'
- )
- # 3. Merge both
- all_scores = pd.concat([scores_combined_hc, scores_combined_pat], ignore_index=True)
- all_scores.head()
- # plot the first component
- if mod in ['CT', 'SA']:
- mod_PC12 = [None]*2
- mod_PC1_conte = parcel_to_surface(pca_loadings.loc[enigma_order]['PC1'].values, 'aparc_conte69')
- mod_PC1_conte[mask] = np.nan
- mod_PC2_conte = parcel_to_surface(pca_loadings.loc[enigma_order]['PC2'].values, 'aparc_conte69')
- mod_PC2_conte[mask] = np.nan
- mod_PC12[0] = mod_PC1_conte
- mod_PC12[1] = mod_PC2_conte
- save_dir = os.path.join(fig_dir, f'{mod}_unimodal_pc_z_scores_fit_in_hc.png')
- plot_hemispheres(surf_lh, surf_rh, array_name=mod_PC12, size=(1200*2,800*2), cmap='BuPu',label_text=['PC1','PC2'],
- color_bar=True, zoom=1.2, interactive=False, embed_nb=True, filename=save_dir,
- nan_color=nan_color, screenshot=True, background=(1,1,1), color_range=[(0.05,0.18), (-0.25,0.18)],
- transparent_bg=True)
- all_scores.to_csv(os.path.join(out_dir, f'z_pca_scores_{mod}_fit_in_hc.csv'))
- # %% [markdown]
- # Check if PCs fit in HCs correlate with those computed in the full sample
- # %%
- fig, axes = plt.subplots(1, 3, figsize=(9, 3), sharex=False, sharey=False)
- for ax, mod in zip(axes, modality):
- # Load data
- pca_hc = pd.read_csv(
- os.path.join(out_dir, f'z_pca_loadings_{mod}_fit_in_hc.csv'),
- index_col=0)
- pca_all = pd.read_csv(
- os.path.join(out_dir, f'z_pca_loadings_{mod}.csv'),
- index_col=0)
- rois = enigma_order
- pcs = ['PC1', 'PC2']
- colors = ['#2E4757', '#438477']
- results = {}
- # Compute correlations + determine flipping per PC
- for pc in pcs:
- r_val = spearmanr(pca_hc[pc], pca_all[pc])[0]
- flip_value = -1 if r_val < 0 else 1
- r_val = r_val*-1 if r_val < 0 else r_val
- if mod in ['CT', 'SA']:
- p_spin = helpers.brainsmash_pvalue_spearman(pca_hc[pc] * flip_value, pca_all[pc], cortical_distmat, nsurr=n_perm, seed=SEED)
- elif mod == 'sctx':
- p_spin = helpers.brainsmash_pvalue_spearman(pca_hc[pc] * flip_value, pca_all[pc], distmat, nsurr=n_perm, seed=SEED)
- else:
- p_spin = float('nan')
- results[pc] = {
- 'r': r_val,
- 'p_spin': p_spin,
- 'flip': flip_value
- }
- # Plot PCs
- for pc, color in zip(pcs, colors):
- flip = results[pc]['flip']
- sns.regplot(
- x=pca_hc[pc] * flip,
- y=pca_all[pc],
- scatter_kws={'s': 1, 'alpha': 1, 'color': color},
- line_kws={'lw': 1, 'color': color},
- ax=ax
- )
- # Legend handle
- ax.plot([], [], color=color,
- label=f"{pc}: r={results[pc]['r']:.2f}, "
- f"p={results[pc]['p_spin']:.3f}")
- # Axis formatting
- ax.set_title(mod)
- ax.set_box_aspect(1)
- ax.set_xlabel("HC only")
- ax.legend(frameon=False, fontsize=8)
- # Shared y-label
- axes[0].set_ylabel("Full sample")
- plt.tight_layout()
- plt.savefig(
- os.path.join(fig_dir, 'PC_loadings_vs_fit_in_hc_vs_fit_in_all.svg'),
- format='svg'
- )
- plt.show()
- # %% [markdown]
- # # Principal angle analysis:
- #
- # 1. Principal angles (compares eigenspaces): Are the dominant axes of healthy and pathological variation alignedd?
- # 2. Does healthy variation explain patient variation? (Projection / reconstruction error - compare manifolds)
- # %%
- # Settings
- K = 2
- n_components = 10
- try:
- pca_abs
- except NameError:
- pca_abs = False
- projection_rows = []
- angle_rows = []
- for mod in ["CT"]:
- print(f"\nProcessing {mod}")
- # Load Z data and extract samples
- df_te_Z = pd.read_csv(os.path.join(z_dir, f'{mod}_Z_enigma_test.csv'))
- imaging_dev = df_te_Z[df_te_Z['disorder'] == 'Developmental']
- imaging_pat = df_te_Z[
- (df_te_Z['diagnosis'] == 1) &
- (df_te_Z['disorder'] != 'Developmental')
- ].copy()
- imaging_hc = df_te_Z[df_te_Z['diagnosis'] == -1].copy()
- imaging_enigma = df_te_Z[df_te_Z['disorder'] != 'Developmental'].copy()
- if mod in ['CT', 'SA']:
- imaging_cols = enigma_order
- else:
- imaging_cols = sctx_order_no_vent
- # Fit HC-only PCA
- X_hc = imaging_hc[imaging_cols].apply(pd.to_numeric, errors='coerce').dropna()
- if pca_abs:
- X_hc = X_hc.abs()
- scaler = StandardScaler()
- X_hc_scaled = scaler.fit_transform(X_hc)
- pca_hc = PCA(n_components=n_components)
- pca_hc.fit(X_hc_scaled)
- # HC normative PC1-PC2 subspace
- U_norm = pca_hc.components_[:K].T # ROIs x 2
- # Save HC-only loadings
- hc_loadings = pd.DataFrame(
- pca_hc.components_.T,
- index=imaging_cols,
- columns=[f"PC{i+1}" for i in range(n_components)]
- )
- hc_loadings.to_csv(
- os.path.join(out_dir, f"{mod}_HC_only_PCA_loadings.csv")
- )
- # load Cohen's d maps
- cohen = pd.read_csv(os.path.join(out_dir, f'{mod}_Cohens_d_supplement.csv'), index_col=0)
- cohen_cols = helpers.get_disorder_columns(
- cohen,
- disorders=disorder_order_pat,
- coltype="Cohen"
- )
- cohens_df = pd.DataFrame({
- dis: cohen[cohen_cols[dis]].values
- for dis in cohen_cols.keys()
- })
- cohens_df.index = cohen['Structure'] if 'Structure' in cohen.columns else cohen.index
- # Match ROI order to PCA feature order
- common_rois = [roi for roi in imaging_cols if roi in cohens_df.index]
- if len(common_rois) != len(imaging_cols):
- print(f"Warning: only {len(common_rois)} / {len(imaging_cols)} ROIs matched.")
- cohens_df = cohens_df.loc[common_rois]
- U_norm_matched = pd.DataFrame(
- U_norm,
- index=imaging_cols,
- columns=["PC1", "PC2"]
- ).loc[common_rois].values
- disorders = [
- d for d in disorder_order_pat
- if d in cohens_df.columns
- ]
- D = cohens_df[disorders].values # ROIs x disorders
- # =====================================================
- # 1: Projection test
- # How much of each Cohen's d map is captured by HC PC1-PC2?
- # =====================================================
- for disorder in disorders:
- d_vec = cohens_df[disorder].values
- d_proj = U_norm_matched @ (U_norm_matched.T @ d_vec) # orthogonal projection, finds the best possible approximation of disease map by only using normative PCs. this computes U^T d. telling us how much of PC1 and PC2 are present in the disease map, e.g. d=1.2*PC1 - 0.4*PC2
- total_energy = np.sum(d_vec ** 2) # original 'energy' (= squared norm), nonnegative and additive across orthogonal components (hence the name energy)
- projected_energy = np.sum(d_proj ** 2) # amount of disease energy inside the normative subspace
- residual_energy = np.sum((d_vec - d_proj) ** 2) # amount of energy not inside normative subspace / cannot be explained by it
- r2_k = projected_energy / total_energy
- projection_rows.append({
- "modality": mod,
- "disorder": disorder,
- "K": K,
- "R2_normative_PC1_PC2": r2_k,
- "projected_energy": projected_energy,
- "residual_energy": residual_energy,
- "total_energy": total_energy,
- "residual_fraction": residual_energy / total_energy
- })
- # =====================================================
- # 2: Disease-effect matrix SVD + principal angles
- # Compare HC PC1-PC2 subspace with disease-effect subspace
- # =====================================================
- U_disease, S_disease, Vt_disease = np.linalg.svd(
- D,
- full_matrices=False
- )
- U_dis = U_disease[:, :K]
- angles = np.degrees(
- subspace_angles(U_norm_matched, U_dis)
- )
- angles = np.sort(angles)
- angle_rows.append({
- "modality": mod,
- "K": K,
- "angle_1_deg": angles[0],
- "angle_2_deg": angles[1],
- "max_angle_deg": np.max(angles),
- "mean_angle_deg": np.mean(angles),
- "min_cos_angle": np.min(np.cos(np.radians(angles))),
- "mean_cos_angle": np.mean(np.cos(np.radians(angles))),
- "sin_max_angle": np.sin(np.radians(np.max(angles))),
- "disease_singular_value_1": S_disease[0],
- "disease_singular_value_2": S_disease[1],
- "disease_variance_fraction_K2": np.sum(S_disease[:K] ** 2) / np.sum(S_disease ** 2)
- })
- # Save results
- projection_df = pd.DataFrame(projection_rows)
- angle_df = pd.DataFrame(angle_rows)
- projection_df.to_csv(
- os.path.join(out_dir, "CT_Cohens_d_projection_onto_HC_PC1_PC2.csv"),
- index=False
- )
- angle_df.to_csv(
- os.path.join(out_dir, "CT_Cohens_d_principal_angles_HC_PC1_PC2.csv"),
- index=False
- )
- print("\nProjection test:")
- print(projection_df)
- print("\nPrincipal angles:")
- print(angle_df)
- # %% [markdown]
- # # Individual level principal angle (HC vs full)
- #
- # HC-only PCA vs full-sample PCA using individual-level data
- # Tests whether adding patients perturbs PC1/PC2
- # %%
- K = 2
- n_components = 3 # need PC3 for lambda_2 - lambda_3 eigengap
- try:
- pca_abs
- except NameError:
- pca_abs = False
- angle_rows = []
- dk_rows = []
- for mod in modality:
- print(f"\nProcessing {mod}")
- df_te_Z = pd.read_csv(os.path.join(z_dir, f'{mod}_Z_enigma_test.csv'))
- # extract subsamples
- imaging_dev = df_te_Z[df_te_Z['disorder'] == 'Developmental']
- imaging_pat = df_te_Z[
- (df_te_Z['diagnosis'] == 1) &
- (df_te_Z['disorder'] != 'Developmental')].copy()
- imaging_hc = df_te_Z[df_te_Z['diagnosis'] == -1].copy()
- imaging_enigma = df_te_Z[
- df_te_Z['disorder'] != 'Developmental'].copy()
- if mod in ['CT', 'SA']:
- imaging_cols = enigma_order
- else:
- imaging_cols = sctx_order_no_vent
- # Prepare individual-level matrices
- X_hc = imaging_hc[imaging_cols].apply(pd.to_numeric, errors='coerce').dropna()
- X_full = imaging_enigma[imaging_cols].apply(pd.to_numeric, errors='coerce').dropna()
- if pca_abs:
- X_hc = X_hc.abs()
- X_full = X_full.abs()
- print(f"HC n = {X_hc.shape[0]}")
- print(f"Full n = {X_full.shape[0]}")
- # PCA in HC only
- scaler_hc = StandardScaler()
- X_hc_scaled = scaler_hc.fit_transform(X_hc)
- pca_hc = PCA(n_components=n_components)
- pca_hc.fit(X_hc_scaled)
- # PCA in full sample: HC + patients
- scaler_full = StandardScaler()
- X_full_scaled = scaler_full.fit_transform(X_full)
- pca_full = PCA(n_components=n_components)
- pca_full.fit(X_full_scaled)
- # Save loadings
- hc_loadings = pd.DataFrame(
- pca_hc.components_.T,
- index=imaging_cols,
- columns=[f"PC{i+1}" for i in range(n_components)])
- full_loadings = pd.DataFrame(
- pca_full.components_.T,
- index=imaging_cols,
- columns=[f"PC{i+1}" for i in range(n_components)])
- hc_loadings.to_csv(os.path.join(out_dir, f"{mod}_HC_only_individual_PCA_loadings.csv"))
- full_loadings.to_csv(os.path.join(out_dir, f"{mod}_full_sample_individual_PCA_loadings.csv"))
- # 1. PC-wise angles: PC1 vs PC1, PC2 vs PC2 (sign-invariant because PCA sign is arbitrary)
- for i in [0, 1]:
- u = pca_hc.components_[i]
- v = pca_full.components_[i]
- u = u / np.linalg.norm(u)
- v = v / np.linalg.norm(v)
- cos_angle = np.abs(np.dot(u, v))
- cos_angle = np.clip(cos_angle, -1, 1)
- angle_deg = np.degrees(np.arccos(cos_angle))
- angle_rows.append({
- "modality": mod,
- "comparison": "matched_PC_vector",
- "PC": f"PC{i+1}",
- "angle_deg": angle_deg,
- "cos_angle": cos_angle,
- "sin_angle": np.sin(np.radians(angle_deg)),
- "hc_var_ratio": pca_hc.explained_variance_ratio_[i],
- "full_var_ratio": pca_full.explained_variance_ratio_[i]
- })
- # 2. Principal angles between HC PC1-PC2 and full PC1-PC2
- U_hc = pca_hc.components_[:K].T
- U_full = pca_full.components_[:K].T
- angles = np.degrees(subspace_angles(U_hc, U_full))
- angles = np.sort(angles)
- angle_rows.append({
- "modality": mod,
- "comparison": "PC1_PC2_subspace",
- "PC": "PC1-PC2",
- "angle_1_deg": angles[0],
- "angle_2_deg": angles[1],
- "max_angle_deg": np.max(angles),
- "mean_angle_deg": np.mean(angles),
- "min_cos_angle": np.min(np.cos(np.radians(angles))),
- "mean_cos_angle": np.mean(np.cos(np.radians(angles))),
- "sin_max_angle": np.sin(np.radians(np.max(angles))),
- "hc_PC1_var_ratio": pca_hc.explained_variance_ratio_[0],
- "hc_PC2_var_ratio": pca_hc.explained_variance_ratio_[1],
- "full_PC1_var_ratio": pca_full.explained_variance_ratio_[0],
- "full_PC2_var_ratio": pca_full.explained_variance_ratio_[1]
- })
- # 3. Davis-Kahan-style perturbation diagnostic
- # For the PC1-PC2 subspace, relevant eigengap is lambda_2 - lambda_3
- C_hc = np.cov(X_hc_scaled, rowvar=False)
- C_full = np.cov(X_full_scaled, rowvar=False)
- E = C_full - C_hc
- E_norm = np.linalg.norm(E, ord=2)
- lambda_2 = pca_hc.explained_variance_[1]
- lambda_3 = pca_hc.explained_variance_[2]
- eigengap_2_3 = lambda_2 - lambda_3
- dk_ratio = E_norm / eigengap_2_3 if eigengap_2_3 > 0 else np.nan
- dk_rows.append({
- "modality": mod,
- "subspace": "PC1-PC2",
- "lambda_2": lambda_2,
- "lambda_3": lambda_3,
- "eigengap_lambda2_lambda3": eigengap_2_3,
- "perturbation_norm": E_norm,
- "sin_max_angle_observed": np.sin(np.radians(np.max(angles))),
- "davis_kahan_ratio_E_over_gap": dk_ratio
- })
- # Save outputs
- individual_angle_df = pd.DataFrame(angle_rows)
- individual_dk_df = pd.DataFrame(dk_rows)
- individual_angle_df.to_csv(
- os.path.join(out_dir, "individual_HC_vs_full_PC1_PC2_angles.csv"),
- index=False
- )
- individual_dk_df.to_csv(
- os.path.join(out_dir, "individual_HC_vs_full_PC1_PC2_Davis_Kahan.csv"),
- index=False
- )
- print("\nPrincipal angles:")
- print(individual_angle_df)
- print("\nDavis-Kahan diagnostic:")
- print(individual_dk_df)
- # %%
- n_components = 10
- try:
- pca_abs
- except NameError:
- pca_abs = False
- angle_results = []
- dk_results = []
- for mod in modality:
- print(f"\nProcessing {mod}")
- df_te_Z = pd.read_csv(os.path.join(z_dir, f'{mod}_Z_enigma_test.csv'))
- # extract subsamples
- imaging_dev = df_te_Z[df_te_Z['disorder'] == 'Developmental']
- imaging_pat = df_te_Z[
- (df_te_Z['diagnosis'] == 1) &
- (df_te_Z['disorder'] != 'Developmental')
- ].copy()
- imaging_hc = df_te_Z[df_te_Z['diagnosis'] == -1].copy()
- imaging_enigma = df_te_Z[df_te_Z['disorder'] != 'Developmental'].copy()
- if mod in ['CT', 'SA']:
- imaging_cols = enigma_order
- else:
- imaging_cols = sctx_order_no_vent
- # Prepare data
- X_hc = imaging_hc[imaging_cols].apply(pd.to_numeric, errors='coerce').dropna()
- X_full = imaging_enigma[imaging_cols].apply(pd.to_numeric, errors='coerce').dropna()
- if pca_abs:
- X_hc = X_hc.abs()
- X_full = X_full.abs()
- print(f"HC n = {X_hc.shape[0]}")
- print(f"Full n = {X_full.shape[0]}")
- # Fit PCA in HC only
- scaler_hc = StandardScaler()
- X_hc_scaled = scaler_hc.fit_transform(X_hc)
- pca_hc = PCA(n_components=n_components)
- pca_hc.fit(X_hc_scaled)
- # Fit PCA in full sample
- scaler_full = StandardScaler()
- X_full_scaled = scaler_full.fit_transform(X_full)
- pca_full = PCA(n_components=n_components)
- pca_full.fit(X_full_scaled)
- # Save loadings
- hc_loadings = pd.DataFrame(
- pca_hc.components_.T,
- index=imaging_cols,
- columns=[f'PC{i+1}' for i in range(n_components)])
- full_loadings = pd.DataFrame(
- pca_full.components_.T,
- index=imaging_cols,
- columns=[f'PC{i+1}' for i in range(n_components)])
- # =====================================================
- # 1. PC-wise angles
- # =====================================================
- for i in range(n_components):
- u = pca_hc.components_[i]
- v = pca_full.components_[i]
- # normalize
- u = u / np.linalg.norm(u)
- v = v / np.linalg.norm(v)
- # sign-invariant angle
- cos_angle = np.abs(np.dot(u, v))
- cos_angle = np.clip(cos_angle, -1, 1)
- angle_deg = np.degrees(np.arccos(cos_angle))
- sin_angle = np.sin(np.radians(angle_deg))
- angle_results.append({
- 'modality': mod,
- 'comparison': 'matched_PC_vector',
- 'PC': f'PC{i+1}',
- 'k': i + 1,
- 'angle_deg': angle_deg,
- 'cos_angle': cos_angle,
- 'sin_angle': sin_angle,
- 'hc_var_ratio': pca_hc.explained_variance_ratio_[i],
- 'full_var_ratio': pca_full.explained_variance_ratio_[i]
- })
- # =====================================================
- # 2. Subspace principal angles
- # =====================================================
- for k in range(1, n_components + 1):
- U_hc = pca_hc.components_[:k].T
- U_full = pca_full.components_[:k].T
- angles = np.degrees(subspace_angles(U_hc, U_full))
- angles = np.sort(angles)
- angle_results.append({
- 'modality': mod,
- 'comparison': 'subspace',
- 'PC': f'PC1-PC{k}',
- 'k': k,
- 'max_angle_deg': np.max(angles),
- 'mean_angle_deg': np.mean(angles),
- 'min_angle_deg': np.min(angles),
- 'min_cos_angle': np.min(np.cos(np.radians(angles))),
- 'mean_cos_angle': np.mean(np.cos(np.radians(angles))),
- 'sin_max_angle': np.sin(np.radians(np.max(angles)))
- })
- # Save results
- angle_df = pd.DataFrame(angle_results)
- dk_df = pd.DataFrame(dk_results)
- angle_df.to_csv(
- os.path.join(out_dir, 'HC_vs_full_sample_principal_angles.csv'),
- index=False
- )
- print("Saved:")
- print(os.path.join(out_dir, 'HC_vs_full_sample_principal_angles.csv'))
- # %% [markdown]
- # # Leave one site out stability check
- # %%
- # parameters
- site_col = "Site"
- n_folds = 10
- # get sites once (using CT here just for reference, could use any)
- dummy_data = pd.read_csv(os.path.join(z_dir, "CT_Z_enigma_test.csv"))
- sites = np.array(dummy_data[site_col].unique())
- # deterministic split into 10 folds
- sites_sorted = np.sort(sites)
- site_folds = np.array_split(sites_sorted, n_folds)
- for mod in modality:
- print(f"\nRunning robustness checks for modality: {mod}")
- pcs_to_check = ["PC1", "PC2"]
- results = []
- # reference PCA loadings (full sample)
- ref_loadings = pd.read_csv(os.path.join(out_dir, f'z_pca_loadings_{mod}.csv'), index_col=0)
- # Load data
- df_te_Z = pd.read_csv(os.path.join(z_dir, f"{mod}_Z_enigma_test.csv"))
- imaging_enigma = df_te_Z[df_te_Z['disorder'] != 'Developmental']
- imaging_cols = list(regions_by_modality[mod])
- missing_cols = sorted(set(imaging_cols) - set(imaging_enigma.columns))
- if missing_cols:
- raise KeyError(f"Missing expected columns for {mod}: {missing_cols}")
- # ==========================================================
- # 1. Leave-One-Site-Out (LOSO)
- # ==========================================================
- for site in sites:
- print(f" LOSO – leaving out site: {site}")
- df_sub = imaging_enigma[imaging_enigma[site_col] != site]
- scaler = StandardScaler()
- X_scaled = scaler.fit_transform(df_sub[imaging_cols].abs())
- pca = PCA(n_components=n_components, random_state=0)
- pca.fit(X_scaled)
- loadings = pd.DataFrame(
- pca.components_.T,
- index=imaging_cols,
- columns=[f'PC{i+1}' for i in range(n_components)]
- )
- for pc in pcs_to_check:
- ref_vec = ref_loadings[pc].values
- vec = loadings[pc].values
- # sign alignment
- if spearmanr(ref_vec, vec)[0] < 0:
- vec = -vec
- rho, pval = spearmanr(ref_vec, vec)
- results.append({
- "modality": mod,
- "condition": "Leave-1-site-out",
- "left_out": site,
- "PC": pc,
- "spearman_r": rho,
- "p": pval
- })
- # ==========================================================
- # 2. Leave-10%-of-Sites-Out (10-fold site CV)
- # ==========================================================
- for fold_idx, fold_sites in enumerate(site_folds, start=1):
- print(f" L10SO – fold {fold_idx}, leaving out {len(fold_sites)} sites")
- df_sub = imaging_enigma[~imaging_enigma[site_col].isin(fold_sites)]
- scaler = StandardScaler()
- if pca_abs == True:
- X_scaled = scaler.fit_transform(df_sub[imaging_cols].abs())
- if pca_abs == False:
- X_scaled = scaler.fit_transform(df_sub[imaging_cols])
- pca = PCA(n_components=n_components, random_state=0)
- pca.fit(X_scaled)
- loadings = pd.DataFrame(
- pca.components_.T,
- index=imaging_cols,
- columns=[f'PC{i+1}' for i in range(n_components)]
- )
- for pc in pcs_to_check:
- ref_vec = ref_loadings[pc].values
- vec = loadings[pc].values
- # sign alignment
- if spearmanr(ref_vec, vec)[0] < 0:
- vec = -vec
- rho, pval = spearmanr(ref_vec, vec)
- results.append({
- "modality": mod,
- "condition": "Leave-10%-sites-out",
- "left_out": f"fold_{fold_idx}",
- "PC": pc,
- "spearman_r": rho,
- "p": pval
- })
- # Results dataframe
- results_df = pd.DataFrame(results)
- results_df.to_csv(
- os.path.join(out_dir, f"robustness_pca_loso_l10so_folds_{mod}.csv"),
- index=False
- )
- # Plot
- plt.figure(figsize=(4.5, 4))
- sns.stripplot(
- data=results_df,
- x="PC",
- y="spearman_r",
- hue="condition",
- dodge=True,
- jitter=True,
- size=6,
- alpha=0.8,
- palette='flare'
- )
- plt.ylim(0.7, 1.05)
- plt.ylabel("Spatial Spearman r")
- plt.title(f"PCA robustness ({mod})")
- plt.legend(title="", frameon=False)
- plt.tight_layout()
- plt.savefig(
- os.path.join(fig_dir, f"pca_robustness_loso_l10so_folds_{mod}.svg"),
- format="svg"
- )
- plt.show()
- summary_df = (
- results_df
- .groupby(["modality", "condition", "PC"])
- .agg(
- spearman_min=("spearman_r", "min"),
- spearman_max=("spearman_r", "max"),
- spearman_mean=("spearman_r", "mean"),
- spearman_std=("spearman_r", "std"),
- n_runs=("spearman_r", "count")
- ).round(2)
- .reset_index()
- )
- # save table
- summary_df.to_csv(
- os.path.join(out_dir, f"pca_robustness_summary_loso_l10so_{mod}.csv"),
- index=False
- )
- # %% [markdown]
- # # Association between PCs and Symptom scores
- # %%
- pc_list = ['PC1', 'PC2']
- # Define disorders and symptom columns
- disorders_symptoms = {
- 'ANX': ['STAI_T'],
- 'ASD': ['ADOS_CSS'],
- 'BP': None, #has to be merged below
- 'MDD': ['HDRS'],
- 'OCD': ['Sev'],
- 'SCZ': None #has to be merged below
- }
- all_results = []
- # Loop over modalities
- for mod in modality:
- # Load PCA scores
- scores_file = os.path.join(out_dir, f'z_PCA_scores_{mod}.csv')
- if not os.path.exists(scores_file):
- print(f" - Missing scores file: {scores_file} (skipping modality)")
- continue
- scores_combined = pd.read_csv(scores_file, index_col=0)
- if 'participant_id' not in scores_combined.columns:
- scores_combined = scores_combined.reset_index().rename(columns={'index': 'participant_id'})
- # Loop over disorders
- for disorder, symp_columns in disorders_symptoms.items():
- print(f"\nProcessing disorder: {disorder} (modality={mod})")
- # Load disorder-specific covariates/symptoms
- if disorder == 'ASD':
- cov_file = os.path.join(raw_dir,'ASD','standardized','symptoms.csv')
- cov_df = pd.read_csv(cov_file)
- cov_df['participant_id'] = (
- 'ASD_' +
- cov_df['Site_Scanner'].astype(str).str.lower() +
- '_' +
- cov_df['participant_id'].astype(str).str.lower()
- )
- else:
- cov_file = os.path.join(raw_dir,f'{disorder}','standardized', 'Covariates.csv')
- cov_df = pd.read_csv(cov_file)
- cov_df['participant_id'] = f'{disorder}_' + cov_df['participant_id'].astype(str)
- # SCZ/BP symptom merging - combine different variable names
- if disorder in ['SCZ', 'BP']:
- column_groups = {"PANSS_Total": ["PANSS_Total", "PANSS_TOTAL", "PANSSTOT"]}
- for new_col, synonyms in column_groups.items():
- existing_cols = [c for c in synonyms if c in cov_df.columns]
- if existing_cols:
- cov_df[new_col + "_combined"] = cov_df[existing_cols].bfill(axis=1).iloc[:, 0]
- else:
- cov_df[new_col + "_combined"] = pd.NA
- symp_columns = [c for c in cov_df.columns if c.endswith("_combined")]
- if not symp_columns:
- print(f"No symptom columns defined for {disorder}; skipping.")
- continue
- # merge
- merged_df = scores_combined.merge(cov_df, on='participant_id', how='inner')
- # Keep only patients if diagnosis present
- if 'diagnosis' in merged_df.columns:
- merged_df = merged_df[merged_df['diagnosis'] == 1].copy()
- else:
- print("Warning: 'diagnosis' not found; proceeding without filtering on diagnosis.")
- # Loop through symptoms
- for col in symp_columns:
- if col not in merged_df.columns:
- print(f" - {col} not found for {disorder}, skipping.")
- continue
- print(f" - Running analysis for symptom: {col}")
- # Need symptom + PCs + covariates (Age/Sex)
- required_cols = [col] + pc_list + ['Age', 'Sex']
- df_all_dis = merged_df.dropna(subset=required_cols).copy()
- if df_all_dis.shape[0] < 10:
- print(f" - Too few subjects after dropna for {disorder} {col} (n={df_all_dis.shape[0]}), skipping.")
- continue
- # symptom magnitude
- df_all_dis[col] = pd.to_numeric(df_all_dis[col], errors='coerce')
- df_all_dis = df_all_dis.dropna(subset=[col])
- if df_all_dis.shape[0] < 10:
- print(f" - Too few valid symptom values for {disorder} {col} (n={df_all_dis.shape[0]}), skipping.")
- continue
- # histogram
- if mod == 'CT':
- plt.figure(figsize=(3, 2))
- plt.hist(df_all_dis[col].values, bins=20)
- plt.title(f'{disorder} – {col} distribution (n={len(df_all_dis)}) [{mod}]')
- plt.xlabel(col)
- plt.ylabel('Count')
- plt.tight_layout()
- plt.show()
- # -----------------------
- # For each PC: standardized multiple regression
- # symptom_z ~ PC_z + Age_z + Sex(dummies)
- # and extract beta for PC_z (standardized beta)
- # -----------------------
- # Standardize symptom
- y_raw = df_all_dis[col].astype(float)
- y_mean = y_raw.mean()
- y_sd = y_raw.std(ddof=0)
- if y_sd == 0 or np.isnan(y_sd):
- print(f" - Symptom {col} has zero variance; skipping.")
- continue
- df_all_dis['symptom_z'] = (y_raw - y_mean) / y_sd
- # Standardize Age
- age_raw = df_all_dis['Age'].astype(float)
- age_sd = age_raw.std(ddof=0)
- if age_sd == 0 or np.isnan(age_sd):
- print(f" - Age has zero variance; skipping.")
- continue
- df_all_dis['Age_z'] = (age_raw - age_raw.mean()) / age_sd
- # Sex dummies
- sex_dummies = pd.get_dummies(df_all_dis['Sex'].astype(str), drop_first=True)
- for pc in pc_list:
- if pc not in df_all_dis.columns:
- print(f" - {pc} missing; skipping.")
- continue
- pc_raw = df_all_dis[pc].astype(float)
- pc_sd = pc_raw.std(ddof=0)
- if pc_sd == 0 or np.isnan(pc_sd):
- print(f" - {pc} has zero variance for {disorder} {col}, skipping.")
- continue
- df_all_dis[f'{pc}_z'] = (pc_raw - pc_raw.mean()) / pc_sd
- # Design matrix: PC_z + Age_z + Sex dummies (+ intercept)
- X = pd.concat(
- [df_all_dis[[f'{pc}_z', 'Age_z']], sex_dummies],
- axis=1
- )
- X = sm.add_constant(X, has_constant='add')
- y = df_all_dis['symptom_z']
- try:
- model = sm.OLS(y, X).fit()
- except Exception as e:
- print(f" - Multiple regression failed for {disorder} {col} {pc}: {e}")
- continue
- # standardized beta for PC is just coef on PC_z
- beta_pc_std = model.params.get(f'{pc}_z', np.nan)
- se_pc_std = model.bse.get(f'{pc}_z', np.nan)
- t_pc_std = model.tvalues.get(f'{pc}_z', np.nan)
- p_pc_std = model.pvalues.get(f'{pc}_z', np.nan)
- r2 = model.rsquared
- n_obs = int(model.nobs)
- all_results.append({
- 'modality': str(mod),
- 'disorder': disorder,
- 'symptom': col,
- 'pc': pc,
- 'n': n_obs,
- 'beta_pc_std': float(beta_pc_std) if np.isfinite(beta_pc_std) else np.nan,
- 'se_pc_std': float(se_pc_std) if np.isfinite(se_pc_std) else np.nan,
- 't_pc_std': float(t_pc_std) if np.isfinite(t_pc_std) else np.nan,
- 'p_value_pc_std': float(p_pc_std) if np.isfinite(p_pc_std) else np.nan,
- 'R2': float(r2) if np.isfinite(r2) else np.nan,
- })
- # Convert results
- results_df = pd.DataFrame(all_results)
- if results_df.empty:
- print("No results were produced.")
- else:
- results_df['modality'] = results_df['modality'].astype(str)
- results_df['p_fdr_pc_std'] = np.nan
- results_df['sig_pc_std'] = False
- # Apply BH-FDR within each modality
- for mod_name in results_df['modality'].dropna().unique():
- msk = results_df['modality'] == mod_name
- pvals = results_df.loc[msk, 'p_value_pc_std'].fillna(1.0).to_numpy()
- reject, pvals_corr, _, _ = multipletests(pvals, method='fdr_bh')
- results_df.loc[msk, 'p_fdr_pc_std'] = pvals_corr
- results_df.loc[msk, 'sig_pc_std'] = reject
- display_cols = [
- 'modality', 'disorder', 'symptom', 'pc', 'n',
- 'beta_pc_std', 'se_pc_std', 't_pc_std', 'p_value_pc_std',
- 'p_fdr_pc_std', 'sig_pc_std',
- 'R2']
- print("\nSymptom ~ PC_z + Age_z + Sex (standardized beta for PC), FDR within modality:")
- print(results_df[display_cols].sort_values(['modality','disorder','symptom','pc']).reset_index(drop=True))
- results_df = results_df.round(3)
- results_df.to_csv(os.path.join(out_dir, 'Symptom_PC_associations.csv'))
- # %%
- disorder_color_map = {
- 'ANX': '#2E4757',
- 'ASD': '#438477',
- 'BP': '#FFC487',
- 'MDD': '#E9735B',
- 'OCD': '#D3436E',
- 'SCZ': '#6D2D51'
- }
- helpers.plot_symptom_forest(
- results_df=results_df,
- disorder_order_pat=disorder_order_pat,
- disorder_cmap=disorder_color_map,
- fig_dir=fig_dir,
- filename="symptom_PC_forest.svg",
- modalities=modality,
- xlim=(-0.35, 0.35)
- )
2_Principal_axes.ipynb at commit b273325, no license · at the source
Overview
and 236 other authors
Karina Blair36, Sven Bölte37,38,39, Stefan Borgwardt20, Paolo Bosco33, Paolo Brambilla40,41, Beatrice Bravi42, Brian P. Brennan43, Willem B. Bruin44,45,46, Geraldo F. Busatto47, Murray J. Cairns48,49, Sara Calderoni33,50, Vince Calhoun51, Rosa Calvo52,53,54,55, Marta Cano15,56, Vaughan J. Carr57,58, Sean P. Carruthers59, Georgia F. Caruana60, Xavier Caseras61, Stanley V. Catts62, I-Jou Chi63,64, Derin Cobia65, Federica Colombo28, Maria Beatriz Couto66,67, Benedicto Crespo-Facorro15,68,69, Kathryn R. Cullen70, Udo Dannlowski32,71,72,73, Mirella Dapretto74,75,76, Adriana Di Martino77, Gretchen J. Diefenbach19,78, Annemiek Dols44,79, Fabio Duran80, Nadza Dzinalija81,82, Christine Ecker83, Stefan Ehrlich84, Goi Khia Eng85,86, Damien A. Fair24,87,88, Afonso Fernandes66, Jamie D. Feusner37,89,90, Gregory A. Fonzo91, Paola Fuentes-Claramonte30,92, Nadine Gaab93,94, Beata R. Godlewska95,96, Benjamin I. Goldstein90, Ali Saffet Gonul97, Ian H. Gotlib98, Hans J. Grabe99,100, Melissa J. Green57, Dominik Grotegerd71, Oliver Gruber101, Patricia Gruner19, Abha R. Gupta102,103,104, Ruben C. Gur4,105, Raquel E. Gur4,105, Shlomi Haar106, Jarold P. Hamilton107, Unn K. Haukvik108,109, Frans A. Henskens110,111, Asli C. Hinc97,112, Yoshiyuki Hirano113,114, Hao Hu115, Matthew E. Hughes59,116, Felice Iasevoli117, Yanghee Im118, Jonathan Ipser119, Hammza Jabbar Abdl Sattar Hamoudi120, Allison Jack121, Delfina Janiri122,123, Joost Janssen124, Fern Jaspers-Fayer125, Kyle M. Jensen126, Jingwen Jin127, Stefan Kaiser128, Toshiharu Kamishikiryo129, Melody J. Y. Kang118, Andriana Karuk30,92, Norbert Kathmann130, Kody G. Kennedy131, Minah Kim132,133,134, Joseph A. King84, Tilo Kircher135, Anna Luisa Klahn136, Daniel N. Klein137, Kathrin Koch138, Peter Kochunov139, Azadeh Kushki89,140, Jun Soo Kwon141,142, Marilyn T. Lake119,143, Mikael Landén136,144, Luisa Lazaro15,52,53,54, Irina Lebedeva145, Nabulsi Leila118, Meng Li31, Christine Lochner146, Carmel M. Loughland147, Beatriz Luna148,149, Karl Lundin Remnélius37,150, Bradley J. MacIntosh151,152, Matteo Mancini153,154,155, Gisele G. Manfro156,157, Rachel Marsh158,159, Ignacio Martinez-Zalacain12,160, David Mataix-Cols161, Colm McDonald162, Jane McGrath163, Jose M. Menchon12,14,30, Pedro Morgado66,67,164, Bryan J. Mowry165,166, Lilianne R. Mujica-Parodi167,168, Emma Muñoz169, Filippo Muratori33, Declan Murphy170,171, Benson Mwangi172, Janardhanan C. Narayanaswamy173,174,175, Jin Narumoto176, Stener Nerland177,178, Janina Neufeld37,179, Benjamin T. Newman180,181, Jared A. Nielsen65, Erika L. Nurmi182, Joseph O’Neill183,184, Kirsten M. OHearn185, Go Okada129, Bob Oranje186, Christos Pantelis60,187,188, Nadine Parker10, Kevin A. Pelphrey189, Mary L. Phillips190, John Piacentini76, Maria Picó-Pérez66,191, Rosanne Picotin101, Alessandro Pigoni192, Fabrizio Piras22, Federica Piras22, Edith Pomarol-Clotet30,92, Giuseppe Pontillo117, Daniel Porta-Casteràs56, Maria J. Portella15,56,193, Rebecca B. Price194, Yann Quidé195,196, Joaquim Radua197,198, Elysha Ringin60, Elena Rodriguez-Cano30,199, Jaroslav Rokicki200,201, Rafael Romero-Garcia202,203, Susan Rossell204,205, Hanyang Ruan138,206, Katya Rubia207, Matthew D. Sacchet208, Yuki Sakai209,210,211, Raymond Salvador30,92, Gabriele Sani122,123, Joao R. Sato212, André Schmidt213, Rodney J. Scott49,147,214, Carl M. Sellgren161,215, Lukas Sempach213,216, Eiji Shimizu113,114, Venkataram Shivakumar217, Kang Sim218,219,220, Jair C. Soares172, Noam Soreni221,222, Carles Soriano-Mas13,223,224, Nuno Sousa66,225,226,227, Frederike Stein135, Jonas L. Steinhäuser-Meerz228,229,230, Emily R. Stern85,86,231, Thomas Straube232, Jeffrey R. Strawn233, Philip J. Sumner59, Ibrahim Sungur97, Philip R. Szeszko234,235, Kristiina Tammimies37,236, Alexander S. Tomyshev145, Michela Tosetti33, Laurens A. van de Mortel44,45, John D. van Horn180,237, Helena van Nieuwenhuizen137, Tamsyn E. van Rheenen59,60, Guido van Wingen44,45, Daniela Vecchio238, Ganesan Venkatasubramanian21, Eduard Vieta197,239, Enric Vilajosana52,54,240, Yolanda Vives-Gilabert241, Henry Völzke242, Chris Vriend82,243,244, Gregory L. Wallace245, Zhen Wang115, Martin Walter31,32, Lei Wang246, Sara Jane Webb247, Lars T. Westlye10,11,248, Sarah Whittle249,250, Mark O. Wielpütz251, Katharina Wittfeld99, Will Woods252, Mon-Ju Wu172, Tony T. Yang253,254,255,256, Lakshmi N. Yatham125,257, Tokiko Yoshida114,258, Abe Yoshinari210,259, Je-Yeon Yun141,260, Qing Zhao115, Giovana B. Zunta-Soares172, ENIGMA Autism Working Group:, ENIGMA Anxiety Working Group:, ENIGMA Bipolar Disorder Working Group:, ENIGMA Major Depression Working Group:, ENIGMA OCD Working Group:, ENIGMA Schizophrenia Working Group:, Odile A. van den Heuvel81,82, Lianne Schmaal261,262, Elena Pozzi261,262, Ole A. Andreassen10,248, Christopher R. K. Ching118, Katherine E. Lawrence118, Gaon S. Kim118, Jan K. Buitelaar263, Theo G.M. van Erp264,265, Dan J. Stein266, Daniel S. Pine267, Anderson M. Winkler268, Janna Marie Bas-Hoogendam269,270,271, Andre Zugman272, Nic J.A. van der Wee270, Nynke A. Groenewold119, Andre Marquand8, Boris C. Bernhardt273, Neda Jahanshad274, Tyler M. Moore4,6, Paul M. Thompson118, Sophia I. Thomopoulos118, Simon B. Eickhoff3,5, Matthias Kirschner128,275,276, Theodore D. Satterthwaite2,4,6, Sofie L. Valk1,3,5276 affiliations
- Max Planck Institute for Human Cognitive and Brain Sciences, Leipzig, Germany
- Penn Lifespan Informatics and Neuroimaging Center, University of Pennsylvania, Philadelphia, PA, USA
- Institute of Neuroscience and Medicine, Brain and Behaviour (INM-7), Research Center Jülich, Jülich, Germany
- Brain Behavior Laboratory, Department of Psychiatry, University of Pennsylvania Perelman School of Medicine, Philadelphia, PA, USA
- Institute of Systems Neuroscience, Medical Faculty and University Hospital Düsseldorf, Heinrich Heine University Düsseldorf, Düsseldorf, Germany
- Lifespan Brain Institute (LiBI) of Penn Medicine and CHOP, University of Pennsylvania, Philadelphia, PA, USA
- Faculty of Medicine, Leipzig University, Leipzig, Germany
- Donders Institute for Brain, Cognition and Behaviour, Radboud University Medical Centre, Nijmegen, the Netherlands
- Radboud University Medical Center, Nijmegen, the Netherlands
- Centre for Precision Psychiatry, Division of Mental Health and Addiction, Oslo University Hospital and University of Oslo, Oslo, Norway
- Department of Psychology, University of Oslo, Oslo, Norway
- Department of Psychiatry, Bellvitge Biomedical Research Institute, Bellvitge University Hospital, Barcelona, Spain
- Psychiatry and Mental Health Group, Institut d’Investigació Biomèrica de Bellvitge (IDIBELL), Bellvitge University Hospital, Barcelona, Spain
- Department of Clinical Sciences, Faculty of Medicine, University of Barcelona, Barcelona, Spain
- Centro de Investigación Biomédica en Red de Salud Mental (CIBERSAM), Instituto de Salud Carlos III, Madrid, Spain
- Instituto de Investigación del Hospital Universitario La Paz (IdiPAZ), Madrid, Spain
- School of Medicine, Universidad Autónoma de Madrid, Madrid, Spain
- Olin Neuropsychiatry Research Center, Institute of Living, Hartford Hospital, Hartford, CN, USA
- Department of Psychiatry, Yale School of Medicine, New Haven, CN, USA
- University of Luebeck, Department of Psychiatry and Psychotherapy, Luebeck, Germany
- Department of Psychiatry, National Institute of Mental Health and Neuro Sciences (NIMHANS), Bengaluru, India
- Laboratory of Neuropsychiatry, Department of Clinical Neuroscience and Neurorehabilitation, Santa Lucia Foundation Istituto di Ricovero e Cura a Carattere Scientifico (IRCCS), Rome, Italy
- University of Minnesota Medical School, Department of Psychiatry and Behavioral Sciences, Minneapolis, MN, USA
- University of Minnesota, Masonic Institute for the Developing Brain (MIDB), Minneapolis, MN, USA
- Department of Psychiatry, Faculdade de Medicina, Universidade de São Paulo, São Paulo, Brazil
- Department of Methods and Techniques in Psychology, Pontifical Catholic University, São Paulo, SP, Brazil
- Leiden University Medical Center (LUMC), Department of Psychiatry, Leiden, the Netherlands
- Psychiatry and Clinical Psychobiology Unit, Division of Neuroscience, Istituto di Ricovero e Cura a Carattere Scientifico (IRCCS), Ospedale San Raffaele, Milan, Italy
- University Vita-Salute San Raffaele, Milan, Italy
- Centro de Investigación Biomédica en Red de Salud Mental (CIBERSAM), Instituto de Salud Carlos III, Barcelona, Spain
- Department of Psychiatry and Psychotherapy, Jena University Hospital, Friedrich-Schiller-University Jena, Jena, Germany
- German Center for Mental Health (DZPG), partner site Halle-Jena-Magdeburg, Germany
- Istituto di Ricovero e Cura a Carattere Scientifico (IRCCS), Fondazione Stella Maris, Pisa, Italy
- Virginia Commonwealth University, Richmond, VA, USA
- Department of Clinical Medicine, Child and Adolescent Psychiatry, University of Copenhagen, Copenhagen, Denmark
- KabScientific
- Center of Neurodevelopmental Disorders (KIND), Department of Women’s and Children’s Health, Centre for Psychiatry Research, Karolinska Institutet and Region Stockholm, Stockholm, Sweden
- Child and Adolescent Psychiatry, Stockholm Health Care Services, Stockholm, Sweden
- Curtin Autism Research Group, Curtin School of Allied Health, Curtin University, Perth, Australia
- Department of Pathophysiology and Transplantation, University of Milan, Milan, Italy
- Department of Neurosciences and Mental Health, Istituto di Ricovero e Cura a Carattere Scientifico (IRCCS) Fondazione Ca’ Granda Ospedale Maggiore Policlinico, Milan, Italy
- Psychiatry and Clinical Psychobiology Unit, Institute of Experimental Neuroscience, Istituto di Ricovero e Cura a Carattere Scientifico (IRCCS) San Raffaele Hospital, Milan, Italy
- McLean Hospital, Harvard Medical School, Belmont, MA, USA
- Amsterdam University Medical Center, University of Amsterdam, Department of Psychiatry, Amsterdam, The Netherlands
- Amsterdam Neuroscience, Amsterdam, The Netherlands
- Section Forensic Family and Youth Care, Institute of Education and Child Studies, Leiden University, Leiden, the Netherlands
- Hospital das Clinicas HCFMUSP, Faculdade de Medicina, Universidade de Sao Paulo, Sao Paulo, SP, Brazil
- School of Biomedical Sciences and Pharmacy, The University of Newcastle, Callaghan, Australia
- Hunter Medical Research Institute, New Lambton, Australia
- Department of Clinical and Experimental Medicine, University of Pisa, Pisa (Italy)
- Tri-institutional Center for Translational Research in Neuroimaging and Data Science (TReNDS), Georgia State University/Georgia Institute of Technology/Emory University, Atlanta, GA, USA
- Department of Medicine, Faculty of Medicine and Health Sciences, Institute of Neurosciences, University of Barcelona, Barcelona, Spain
- Department of Child and Adolescent Psychiatry and Psychology, Hospital Clinic of Barcelona, Barcelona, Spain
- Institut d’Investigacions Biomèdiques August Pi i Sunyer (IDIBAPS), Barcelona, Spain
- Centro de Investigación Biomédica en Red de Salud Mental (CIBERSAM), Madrid, Spain
- Sant Pau Mental Health Research Group, Institut de Recerca Sant Pau (IR SANT PAU), Barcelona, Spain
- School of Clinical Medicine, University of New South Wales, Sydney, Australia
- Monash University, Melbourne, Australia
- Centre for Mental Health and Brain Sciences, Swinburne University of Technology, Melbourne, Australia
- Department of Psychiatry, Faculty of Medicine, Dentistry, and Health Sciences, University of Melbourne, Parkville, Australia
- Centre for Neuropsychiatric Genetics and Genomics, Division of Psychological Medicine and Clinical Neurosciences, Cardiff University, Cardiff, UK
- Faculty of Health, Medicine and Behavioural Sciences, University of Queensland, Brisbane, Australia
- Department of Occupational Therapy, College of Health Sciences, Kaohsiung Medical University, Kaohsiung, Taiwan
- Biomedical Artificial Intelligence Academy, Kaohsiung Medical University, Kaohsiung, Taiwan
- Department of Psychology and Neuroscience, Brigham Young University, Provo, UT, USA
- Life and Health Sciences Research Institute (ICVS), School of Medicine, University of Minho, Braga, Portugal
- ICVS/3B’s, PT Government Associate Laboratory, Braga/Guimarães, Portugal
- University hospital virgen del Rocío, ibis / CSIC, Sevilla, Spain
- University of Sevilla, Sevilla, Spain
- University of Minnesota, Child and Adolescent Mental Health (CAMH) Division, Minneapolis, MN, USA
- Institute for Translational Psychiatry, University of Münster, Münster, Germany
- Department of Psychiatry, Medical School and University Medical Center OWL, Protestant Hospital of the Bethel Foundation, Bielefeld University, Bielefeld, Germany
- Center for Intervention and Research on Adaptive and Maladaptive Brain Circuits Underlying Mental Health (C-I-R-C), partner site Halle-Jena-Magdeburg, Germany
- The Ahmanson Lovelace Brain Mapping Center, University of California, Los Angeles, CA, USA
- Department of Psychiatry and Biobehavioral Sciences, University of California, Los Angeles (UCLA) School of Medicine, Los Angeles, CA, USA
- Semel Institute for Neuroscience and Human Behavior, University of California, Los Angeles, CA, USA
- Child Mind Institute, Autism Center, New York, NY, USA
- Anxiety Disorders Center, Institute of Living, Hartford, CN, USA
- Department of Psychiatry, Utrecht University Medical Center (UMC), Utrecht, the Netherlands
- Laboratory of Psychiatric Neuroimaging (LIM-21), Departamento e Instituto de Psiquiatria, Hospital das Clinicas, Faculdade de Medicina Universidade de São Paulo (HCFMUSP), Faculdade de Medicina Universidade de São Paulo, Brazil
- Amsterdam University Medical Center, Department of Psychiatry, Department of Anatomy and Neuroscience, Vrije Universiteit Amsterdam, Amsterdam, The Netherlands
- Amsterdam Neuroscience, Compulsivity, Impulsivity and Attention program, Amsterdam, The Netherlands
- Department of Child and Adolescent Psychiatry, Psychosomatic Medicine and Psychotherapy, University Hospital Frankfurt, Goethe University, Frankfurt am Main, Germany
- Translational Developmental Neuroscience Section, Division of Psychological and Social Medicine and Developmental Neurosciences, Faculty of Medicine, Technische Universität Dresden, Dresden, Germany
- Clinical Research, Nathan Kline Institute for Psychiatric Research, Orangeburg, NY, USA
- Department of Psychiatry, New York University Grossman School of Medicine, New York, NY, USA
- Institute of Child Development, University of Minnesota, Minneapolis, MN, USA
- Department of Pediatrics, University of Minnesota, Minneapolis, MN, USA
- University of Toronto, Toronto, ON, Canada
- The Centre for Addiction and Mental Health, Hospital for Sick Children, Toronto, ON, Canada
- Charmaine and Gordon McGill Center for Psychedelic Research and Therapy, Department of Psychiatry and Behavioral Sciences, The University of Texas at Austin Dell Medical School, Austin, TX, USA
- FIDMAG Sisters Hospitallers Research Foundation, Barcelona, Spain
- Harvard Graduate School of Education, Cambridge, MA, USA
- Harvard University, Cambridge, MA, USA
- Department of Psychiatry, University of Oxford, Oxford, UK
- Oxford Health NHS Foundation Trust, Oxford, UK
- Standardization of Computational Anatomy Techniques for Cognitive and Behavioral Sciences (SoCAT) Lab, Department of Psychiatry, Faculty of the Medicine, Ege University, Izmir, Türkiye
- Department of Psychology, Stanford University, Stanford, CA, USA
- Department of Psychiatry and Psychotherapy, University Medicine Greifswald, Greifswald, Germany
- German Center of Neurodegenerative Diseases (DZNE) Site Rostock/Greifswald, Greifswald, Germany
- Section for Experimental Psychopathology and Neuroimaging, Department of General Psychiatry, Heidelberg University, Heidelberg, Germany
- Department of Pediatrics, Yale University School of Medicine, New Haven, CT, USA
- Yale Child Study Center, Yale University School of Medicine, New Haven, CT, USA
- Department of Neuroscience, Yale University School of Medicine, New Haven, CT, USA
- Lifespan Brain Institute, Children’s Hospital of Philadelphia (CHOP), Philadelphia, PA, USA
- School of Psychology, University of Surrey, Guildford, UK
- Department of Clinical and Biological Psychology, University of Bergen, Bergen, Norway
- Centre for Research and Education in Forensic Psychiatry, Department of Mental Health and Addiction, Oslo University Hospital, Oslo, Norway
- Department of Adult Psychiatry, Institute of Clinical Medicine, University of Oslo, Norway
- ASRB University of Newcastle, NSW, Australia
- School of Medicine and Public Health, University of Newcastle, NSW, Australia
- Izmir City Hospital, Izmir, Turkey
- Research Center for Child Mental Development, Chiba University, Chiba, Japan
- United Graduate School of Child Development, The University of Osaka, Suita, Japan
- Shanghai Mental Health Center, Shanghai Jiao Tong University School of Medicine, Shanghai, China
- Australian National Imaging Facility, The University of Queensland, St Lucia, Australia
- School of Psychiatry, Department of Neuroscience, University of Naples “Federico II”, Naples, Italy
- Imaging Genetics Center, Mark and Mary Stevens Neuroimaging and Informatics Institute, Keck School of Medicine of USC, University of Southern California, Marina del Rey, CA, USA
- Department of Psychiatry and Mental Health, Neuroscience Institute, University of Cape Town, Cape Town, South Africa
- Center of Excellence on Mood Disorders, Louis A. Faillace, MD, Department of Psychiatry and Behavioral Sciences at McGovern Medical School, UTHealth, Houston, TX, USA
- Department of Psychology, George Mason University, Fairfax, VA, USA
- Department of Neuroscience, Section of Psychiatry, Università Cattolica del Sacro Cuore, Rome, Italy
- Department of Neuroscience, Head-Neck and Chest, Section of Psychiatry, Fondazione Policlinico Universitario Agostino Gemelli IRCCS, Rome, Italy
- Instituto de Investigación Sanitaria del Hospital Gregorio Marañón (IISGM), Madrid, Spain
- Department of Psychiatry, Faculty of Medicine, University of British Columbia, Vancouver, Canada
- Psychology Department, Georgia State University, Atlanta, GA, USA
- Department of Psychology, The University of Hong Kong, Hong Kong
- Division of Adult Psychiatry, Department of Psychiatry, Geneva University Hospitals, Geneva, Switzerland
- Department of Psychiatry and Neurosciences, Graduate School of Biomedical and Health Sciences, Hiroshima University, Hiroshima, Japan
- Department of Psychology, Humboldt University of Berlin, Berlin, Germany
- Centre for Youth Bipolar Disorder, Centre for Addiction and Mental Health, Toronto, ON, Canada
- Department of Psychiatry, Seoul National University College of Medicine, Seoul, South Korea
- Department of Neuropsychiatry, Seoul National University Hospital, Seoul, South Korea
- Institute of Human Behavioral Medicine, SNU-MRC, Seoul, South Korea
- University of Marburg, School of Medicine, Department of Psychiatry and Psychotherapy, Marburg, Germany
- Department of Psychiatry and Neurochemistry, Institute of Neuroscience and Physiology, University of Gothenburg, Gothenburg, Sweden
- Department of Psychology, Stony Brook University, Stony Brook, NY, USA
- Department of Neuroradiology, TUM University Hospital, School of Medicine and Health, Technical University of Munich (TUM), Munich, Germany
- The University of Texas Health Science Center Houston, TX, USA
- Holland Bloorview Kids Rehabilitation Hospital, Toronto, ON, Canada
- Seoul National University Hospital, Seoul, Republic of Korea
- Hanyang University Hospital, Seoul, South Korea
- Department of Paediatrics and Child Health, University of Cape Town, Cape Town, South Africa
- Department of Medical Epidemiology and Biostatistics, Karolinska Institutet, Stockholm, Sweden
- Russian Mental Health Research Center (RMHRC), Moscow, Russia
- SA MRC Unit on Risk and Resilience in Mental Disorders, Department of Psychiatry, Stellenbosch University, Stellenbosch, South Africa
- University of Newcastle, NSW, Australia
- Department of Psychology, University of Pittsburgh, Pittsburgh, PA, USA
- Department of Psychiatry, University of Pittsburgh Medical Center, University of Pittsburgh, Pittsburgh, PA, USA
- Child and Adolescent Psychiatry Unit, Department of Medical Sciences, Uppsala University, Uppsala, Sweden
- Sunnybrook Research Institute, Toronto, ON, Canada
- Centre for Addiction and Mental Health, Toronto, ON, Canada
- Enrico Fermi Research Center, Rome, Italy
- Neuroimaging Laboratory, Santa Lucia Foundation, Rome, Italy
- Cardiff University, Brain Research Imaging Centre (CUBRIC), Cardiff University, Cardiff, UK
- Department of Psychiatry, School of Medicine, Universidade Federal do Rio Grande do Sul, Porto Alegre, Brazil
- Anxiety outpatient Unit, Hospital de Clínicas de Porto Alegre, Porto Alegre, Brazil
- Columbia University Irving Medical Center, New York, NY, USA
- The New York State Psychiatric Institute, New York, NY, USA
- Department of Radiology, Bellvitge University Hospital, Barcelona, Spain
- Centre for Psychiatry Research, Department of Clinical Neuroscience, Karolinska Institutet, and Stockholm Health Care Services, Stockholm, Sweden
- Centre for Neuroimaging, Cognition and Genomics (NICOG), Clinical Neuroimaging Laboratory, College of Medicine Nursing and Health Sciences, University of Galway, Galway, Ireland
- Department of Psychiatry, Trinity College Dublin, Dublin, Ireland
- 2CA-Braga, Hospital de Braga, Braga, Portugal
- Queensland Brain Institute, The University of Queensland, Brisbane, Australia
- Queensland Centre for Mental Health Research, The University of Queensland, Brisbane, Australia
- Department of Biomedical Engineering, State University of New York at Stony Brook, Stony Brook, NY, USA
- Martinos Center for Biomedical Imaging, Massachusetts General Hospital, Charlestown, MA, USA
- MRI Core Facility, IDIBAPS, Barcelona, Spain
- Institute of Psychiatry Psychology and Neuroscience, King’s College London, London, UK
- NIHR Maudsley Biomedical Research Centre, King’s College London, London, UK
- Center of Excellence on Mood Disorders, Louis A. Faillace, MD, Department of Psychiatry and Behavioral Sciences at McGovern Medical School, UTHealth, Houston, Texas, USA
- Monash Health and Department of Psychiatry, School of Clinical Sciences, Monash University, Melbourne, VIC, Australia
- OCD Clinic, National Institute of Mental Health And Neurosciences (NIMHANS), India
- Deakin Institute for Mental and Physical Health and Clinical Translation, School of Medicine, Deakin University, Australia
- Kyoto Prefectural University of Medicine, Kyoto, Japan
- Division of Mental Health and Substance Abuse, Diakonhjemmet Hospital, Oslo, Norway
- Division of Mental Health and Addiction, Institute of Clinical Medicine, University of Oslo, Oslo, Norway
- Swedish Collegium for Advanced Study, Uppsala, Sweden
- Department of Psychology, University of Virginia, Charlottesville, VA, USA
- Department of Radiology and Medical Imaging, University of Virginia, Charlottesville, VA, USA
- University of California, Los Angeles, CA, USA
- Division of Child and Adolescent Psychiatry, UCLA Semel Institute for Neuroscience, Los Angeles, CA, USA
- UCLA Brain Research Institute, Los Angeles, CA, USA
- Department of Physiology and Pharmacology, Wake Forest University School of Medicine, Winston-Salem, NC, USA
- Center for Neuropsychiatric Schizophrenia Research (CNSR), Mental Health Center, Glostrup, Copenhagen University Hospital, Mental Health Services CPH, Copenhagen, Denmark
- Monash Institute of Pharmaceutical Sciences (MIPS), Monash University, Parkville, Australia
- Western Centre for Health Research and Education (WCHRE), University of Melbourne and Western Health, Sunshine Hospital, St Albans, Australia
- University of Virginia, Charlottesville, VA, USA
- University of Pittsburgh, Pittsburgh, PA, USA
- Department of Basic and Clinical Psychology and Psychobiology, Jaume I University, Castelló de la Plana, Spain
- Department of Neurosciences and Mental Health, Fondazione IRCCS Ca’ Granda, Ospedale Maggiore Policlinico, Milan, Italy
- Department of Psychiatry and Legal Medicine, Universitat Autonoma de Barcelona, Barcelona, Spain
- University of Pittsburgh, PA, USA
- NeuroRecovery Research Hub, School of Psychology, University of New South Wales (UNSW) Sydney, Sydney, Australia
- Centre for Pain IMPACT, Neuroscience Research Australia, Randwick, Australia
- Institut d’Investigacions Biomèdiques August Pi i Sunyer (IDIBAPS), Centro de Investigación Biomédica en Red de Salud Mental (CIBERSAM), Barcelona, Spain
- Institute of Neurosciences, University of Barcelona, Barcelona, Spain
- Consorci Sanitari del Maresme, Barcelona, Spain
- Centre of Research and Education in Forensic Psychiatry (SIFER), Oslo University Hospital, Oslo, Norway
- Department of Electronic Systems, Vilnius Tech, Vilnius, Lithuania
- Department of Medical Physiology and Biophysics, Instituto de Biomedicina de Sevilla (IBiS), HUVR/CSIC/Universidad de Sevilla/CIBERSAM, ISCIII, Sevilla, Spain
- Department of Psychiatry, University of Cambridge, Cambridge, UK
- Centre for Mental Health and Brain Sciences, Faculty of Health, Arts & Design, Swinburne University of Technology, Melbourne, Australia
- University of Sydney, Sydney, Australia
- School of Medicine and Health, TUM-NIC Neuroimaging Center, Technical University of Munich, Munich, Germany
- School of Academic Psychiatry, Institute of Psychiatry, Psychology and Neuroscience, Department of Child & Adolescent Psychiatry, King’s College London, London, UK
- Meditation Research Program, Department of Psychiatry, Massachusetts General Hospital, Harvard Medical School, Boston, MA, USA
- ATR Brain Information Communication Research Laboratory Group, Kyoto, Japan
- Department of Psychiatry, Graduate School of Medical Science, Kyoto Prefectural University of Medicine, Kyoto, Japan
- XNef, Inc., Kyoto, Japan
- Center of Mathematics, Computing and Cognition, Universidade Federal do ABC, Santo Andre, Brazil
- University of Basel, Department of Clinical Research (DKF), Basel, Switzerland
- NSW Health Pathology, NSW, Australia
- Department of Physiology and Pharmacology, Karolinska Institutet, Stockholm, Sweden
- Center for Affective, Stress and Sleep Disorders, University Psychiatric Clinics (UPK) Basel, Basel, Switzerland
- Department of Integrative Medicine, National Institute of Mental Health and Neurosciences (NIMHANS), Bengaluru, India
- West Region, Institute of Mental Health, Singapore
- Yong Loo Lin School of Medicine, National University of Singapore, Singapore
- Lee Kong Chian School of Medicine, Nanyang Technological University, Singapore
- Department of Psychiatry and Behavioral Neurosciences, McMaster University, Hamilton, ON, Canada
- Pediatric OCD Consultation Clinic, Anxiety Treatment and Research Clinic, SJH Healthcare, Hamilton, ON, Canada
- Department of Social Psychology and Quantitative Psychology, Institute of Neurosciences, University of Barcelona, Barcelona, Spain
- Centro de Investigación Biomédica en Red de Salud Mental (CIBERSAM), Barcelona, Spain
- Centro Universitário Max Planck (UniMAX), São Paulo, Brazil
- Centro Universitários de Jaguaríuna (UniFAJ), São Paulo, Brazil
- Clinical Academic Center of Braga (2CA-Braga), Braga, Portugal
- Department of Medicine I, Faculty of Medicine and University Hospital Carl Gustav Carus, TUD Dresden University of Technology, Dresden, Germany
- Else Kröner-Fresenius Center for Digital Health, TUD Dresden University of Technology, Dresden, Germany
- Laureate Institute for Brain Research, Tulsa, OK, USA
- Neuroscience Institute, New York University School of Medicine, New York, NY, USA
- Institute of Medical Psychology and Systems Neuroscience, University Hospital Münster, Münster, Germany
- Department of Psychiatry and Behavioral Neuroscience, University of Cincinnati, College of Medicine, Cincinnati, OH, USA
- Icahn School of Medicine at Mount Sinai, New York, NY, USA
- James J. Peters VA Medical Center, Bronx, NY, USA
- Department of Highly Specialized Pediatric Orthopedics and Medicine, Astrid Lindgren Children’s Hospital, Karolinska University Hospital, Stockholm, Sweden
- School of Data Science, University of Virginia, Charlottesville, VA, USA
- Laboratory of Neuropsychiatry, Department of Clinical and Behavioral Neurology, Santa Lucia Foundation Istituto di Ricovero e Cura a Carattere Scientifico (IRCCS), Rome, Italy
- Clinical Institute of Neuroscience, University of Barcelona, Hospital Clinic, Barcelona, Spain
- University of Vic – Central University of Catalonia, Barcelona, Spain
- Intelligent Data Analysis Laboratory, Department of Electronic Engineering, University of Valencia (UV), Valencia, Spain
- Institute for Community Medicine, University Medicine Greifswald, Greifswald, Germany
- Amsterdam University Medical Center, Department of Psychiatry, Vrije Universiteit Amsterdam, Amsterdam, The Netherlands
- Amsterdam University Medical Center, Department of Anatomy and Neurosciences, Vrije Universiteit Amsterdam, Amsterdam, The Netherlands
- Department of Speech, Language, and Hearing Sciences, The George Washington University, Washington, D.C., USA
- Rotman Research Institute, Baycrest Academy for Research and Education, Toronto, ON, Canada
- Center for Child Health, Behavior and Development, Seattle Children’s Research Institute, Seattle, WA, USA
- K.G. Jebsen Centre for Neurodevelopmental Disorders, University of Oslo, Oslo, Norway
- School of Psychology, Deakin University, Melbourne, Australia
- Melbourne School of Psychological Sciences, The University of Melbourne, Melbourne, Australia
- Department of Diagnostic and Interventional Radiology, University Medicine Greifswald, Greifswald, Germany
- Swinburne University of Technology, Melbourne, Australia
- UCSF Department of Psychiatry and Behavioral Sciences, San Francisco, CA, USA
- Division of Child and Adolescent Psychiatry, UCSF, San Francisco, CA, USA
- Weill Institute for Neurosciences, UCSF, San Francisco, CA, USA
- UCSF School of Medicine, San Francisco, CA, USA
- Department of Psychiatry, Institute of Mental Health, Vancouver, BC, Canada
- Cognitive Behavioral Therapy Center, Chiba University Hospital, Chiba, Japan
- Sugimoto Psychiatric Clinic, Kyoto, Japan
- Yeongeon Student Support Center, Seoul National University College of Medicine, Seoul, Republic of Korea
- Centre for Youth Mental Health, The University of Melbourne, Parkville, Australia
- Orygen, The National Centre of Excellence in Youth Mental Health, Parkville, Australia
- Department of Medical Neuroscience, Donders Institute for Brain, Cognition and Behavior, Radboud University Medical Center, Nijmegen, The Netherlands
- Clinical Translational Neuroscience Laboratory, Department of Psychiatry and Human Behavior, University of California Irvine, Irvine, CA, USA
- Center for the Neurobiology of Learning and Memory, University of California Irvine, Irvine, CA, USA
- SAMRC Unit on Risk & Resilience in Mental Disorders, Department of Psychiatry & Neuroscience Institute, University of Cape Town, Cape Town, South Africa
- National Institute of Mental Health Intramural Research Program, Bethesda, MD, USA
- Department of Human Genetics, University of Texas Rio Grande Valley, Brownsville, Texas, USA
- Leiden University, Institute of Psychology, Leiden, The Netherlands
- Leiden University Medical Center (LUMC), Department of Psychiatry, Leiden, The Netherlands
- Leiden Institute for Brain and Cognition, Leiden, the Netherlands
- Section on Development and Affective Neuroscience (SDAN), National Institute of Mental Health (NIMH), Bethesda, Maryland, USA
- Montreal Neurological Institute and Hospital, McGill University, Montreal, QC, Canada
- Laboratory of Brain eScience, Mark and Mary Stevens Neuroimaging and Informatics Institute, Keck School of Medicine of USC, University of Southern California, Marina del Rey, CA, USA
- Psychiatric University Hospital Zurich, University of Zurich, Zurich, Switzerland
- Synapsy Center for Neuroscience and Mental Health Research, Faculty of Medicine, University of Geneva, Switzerland
Abstract
Elucidating the neurobiological basis of neurodevelopmental and psychiatric conditions (NDPCs) remains challenging because brain alterations vary within diagnoses and overlap across them. Whether diverse alterations follow a systematic organization that may reflect shared vulnerabilities remains unknown. Here, we assembled 10,135 individuals with schizophrenia, autism, bipolar, obsessive-compulsive, generalized anxiety, and major depressive disorders, and 11,998 reference participants across six continents through the ENIGMA consortium. Using normative modeling, we quantified individual deviations in cortical thickness, surface area, and subcortical volumes relative to lifespan reference trajectories (5 to 80 years). We show that structural deviations converged along cortical axes reflecting connectome organization, maturation, and cytoarchitectonic diversity. These axes mirrored typical population variation, but their expression differed across diagnoses and partly scaled with symptom severity. Even rare and highly individualized extreme deviations followed this organization, concentrating in densely connected regions. Finally, brain structural deviations overlapped substantially across diagnoses, while differences between them increased toward the association cortex. Together, we provide large-scale evidence that structural deviations across NDPCs are systematically constrained by the brain’s intrinsic architecture. This shared organization provides a framework for reconciling individual variability with transdiagnostic similarities and motivates an integrative, systems-level understanding of mental health.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 10 matches between paragraphs and lines of code.
Zenodo 21907827
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
1 file
- PCNToolkit_transfer_cort
ical_thickness_example.i , Jupyter, 594 lines, 1 matchpynb
CNG-LAB/Enigmatics
b273325f1c7f355b608f933054ec8239a91a9542, 17 August 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
11 files
- code/
hbr/ , Python, 214 lines, 1 matchNormModel_SHASH_parallel ized.py - code/
hbr/ , Jupyter, 591 lines, 1 matchPCNToolkit_transfer_cort ical_thickness_example.i pynb - code/
hbr/ , Shell, 20 linesgh_run_hbr_parcel.sh - code/
main/ , Jupyter, 316 lines0_collect_Z_scores_plot_ model_performance.ipynb - code/
main/ , Jupyter, 920 lines1_Group_shift_variabilit y.ipynb - code/
main/ , Jupyter, 2,074 lines, 4 matches2_Principal_axes.ipynb - code/
main/ , Jupyter, 1,291 lines, 2 matches3_Extreme_deviation_hubs .ipynb - code/
main/ , Jupyter, 783 lines4_Overlap.ipynb - code/
main/ , Python, 1,408 lines, 1 matchhelpers.py - setup.sh, Shell, 68 lines
- README.md, Text, 51 lines
pcntoolkit.readthedocs.io
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
Code availability
Custom code generated for this project was made publicly available under https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 11 scripts, each with its path and the digest of its content;
- 10 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- zenodo:2872624, at Zenodo; found in “Data availability”
Data availability
Data generated for this study, as well as atlases used for contextualization, were made publicly available under Github https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 2, 28 September 2026
- Language: n/a → en
- Authors: added Meike D. Hettwer (0000-0002-7973-6752); Dag Alnæs (0000-0001-7361-5418); Sven Bölte (0000-0002-4579-4970); Willem B. Bruin (0000-0002-0672-8903); Murray J. Cairns (0000-0003-2490-2538); Vince Calhoun (0000-0001-9058-0747); Derin Cobia (0000-0003-2339-958X); Federica Colombo (0000-0001-5853-9912); Ian H. Gotlib (0000-0002-3622-3199); Shlomi Haar (0000-0003-2213-6585); Unn K. Haukvik (0000-0002-0363-4127); Yanghee Im (0009-0005-1247-1445); Allison Jack (0000-0002-7792-6464); Kyle M. Jensen (0000-0001-7896-2232); Peter Kochunov (0000-0003-3656-4281); Bradley J. MacIntosh (0000-0001-7300-2355); Pedro Morgado (0000-0003-3880-3258); Lilianne R. Mujica-Parodi (0000-0002-3752-5519); Benson Mwangi (0000-0002-1717-4395); Stener Nerland (0000-0001-8771-8856); Benjamin T. Newman (0000-0002-0668-2853); Jared A. Nielsen (0000-0002-2717-193X); Christos Pantelis (0000-0002-9565-0238); Federica Piras (0000-0002-9546-7038); Giuseppe Pontillo (0000-0001-5425-1890); Yann Quidé (0000-0002-8569-7139); Yuki Sakai (0000-0003-2475-8548); John D. van Horn (0000-0003-1537-0816); Chris Vriend (0000-0003-3111-1304); Lars T. Westlye (0000-0001-8644-956X); and 7 others; removed Meike D. Hettwer; Dag Alnæs; Sven Bölte; Willem B. Bruin; Murray J. Cairns; Vince Calhoun; Derin Cobia; Federica Colombo; Ian H. Gotlib; Shlomi Haar; Unn K. Haukvik; Yanghee Im; Allison Jack; Kyle M. Jensen; Peter Kochunov; Bradley J. MacIntosh; Pedro Morgado; Lilianne R. Mujica-Parodi; Benson Mwangi; Stener Nerland; Benjamin T. Newman; Jared A. Nielsen; Christos Pantelis; Federica Piras; Giuseppe Pontillo; Yann Quidé; Yuki Sakai; John D. van Horn; Chris Vriend; Lars T. Westlye; and 7 others
Version 1, 27 September 2026: the first record
Recorded: type, journal, dates, 256 authors, 4 funders, 68 references.
Cite
This paper
Hettwer, M. D., Saberi, A., Shafiei, G., Manoli, A., De Boer, A. A., Alnæs, D., Alonso, P., Arango, C., Assaf, M., Avram, M., Balachander, S., Banaj, N., Başgöze, Z., Batistuzzo, M. C., Bauduin, S. E., Benedetti, F., Bertolin, S., Besteher, B., Biagi, L., . . . Valk, S. L. (2026). Lifespan brain structural variation reveals shared organization across mental health conditions. medRxiv (preprint). https://
BibTeX
@article{hettwer2026life
author = {Hettwer, Meike D. and Saberi, Amin and Shafiei, Golia and Manoli, Aikaterina and De Boer, Augustijn A. and Alnæs, Dag and Alonso, Pino and Arango, Celso and Assaf, Michal and Avram, Mihai and Balachander, Srinivas and Banaj, Nerisa and Başgöze, Zeynep and Batistuzzo, Marcelo C. and Bauduin, Stephanie E.E.C. and Benedetti, Francesco and Bertolin, Sara and Besteher, Bianca and Biagi, Laura and Blair, Robert J. and Blair, Karina and Bölte, Sven and Borgwardt, Stefan and Bosco, Paolo and Brambilla, Paolo and Bravi, Beatrice and Brennan, Brian P. and Bruin, Willem B. and Busatto, Geraldo F. and Cairns, Murray J. and Calderoni, Sara and Calhoun, Vince and Calvo, Rosa and Cano, Marta and Carr, Vaughan J. and Carruthers, Sean P. and Caruana, Georgia F. and Caseras, Xavier and Catts, Stanley V. and Chi, I-Jou and Cobia, Derin and Colombo, Federica and Couto, Maria Beatriz and Crespo-Facorro, Benedicto and Cullen, Kathryn R. and Dannlowski, Udo and Dapretto, Mirella and Di Martino, Adriana and Diefenbach, Gretchen J. and Dols, Annemiek and Duran, Fabio and Dzinalija, Nadza and Ecker, Christine and Ehrlich, Stefan and Eng, Goi Khia and Fair, Damien A. and Fernandes, Afonso and Feusner, Jamie D. and Fonzo, Gregory A. and Fuentes-Claramonte, Paola and Gaab, Nadine and Godlewska, Beata R. and Goldstein, Benjamin I. and Gonul, Ali Saffet and Gotlib, Ian H. and Grabe, Hans J. and Green, Melissa J. and Grotegerd, Dominik and Gruber, Oliver and Gruner, Patricia and Gupta, Abha R. and Gur, Ruben C. and Gur, Raquel E. and Haar, Shlomi and Hamilton, Jarold P. and Haukvik, Unn K. and Henskens, Frans A. and Hinc, Asli C. and Hirano, Yoshiyuki and Hu, Hao and Hughes, Matthew E. and Iasevoli, Felice and Im, Yanghee and Ipser, Jonathan and Hamoudi, Hammza Jabbar Abdl Sattar and Jack, Allison and Janiri, Delfina and Janssen, Joost and Jaspers-Fayer, Fern and Jensen, Kyle M. and Jin, Jingwen and Kaiser, Stefan and Kamishikiryo, Toshiharu and Kang, Melody J. Y. and Karuk, Andriana and Kathmann, Norbert and Kennedy, Kody G. and Kim, Minah and King, Joseph A. and Kircher, Tilo and Klahn, Anna Luisa and Klein, Daniel N. and Koch, Kathrin and Kochunov, Peter and Kushki, Azadeh and Kwon, Jun Soo and Lake, Marilyn T. and Landén, Mikael and Lazaro, Luisa and Lebedeva, Irina and Leila, Nabulsi and Li, Meng and Lochner, Christine and Loughland, Carmel M. and Luna, Beatriz and Remnélius, Karl Lundin and MacIntosh, Bradley J. and Mancini, Matteo and Manfro, Gisele G. and Marsh, Rachel and Martinez-Zalacain, Ignacio and Mataix-Cols, David and McDonald, Colm and McGrath, Jane and Menchon, Jose M. and Morgado, Pedro and Mowry, Bryan J. and Mujica-Parodi, Lilianne R. and Muñoz, Emma and Muratori, Filippo and Murphy, Declan and Mwangi, Benson and Narayanaswamy, Janardhanan C. and Narumoto, Jin and Nerland, Stener and Neufeld, Janina and Newman, Benjamin T. and Nielsen, Jared A. and Nurmi, Erika L. and O’Neill, Joseph and OHearn, Kirsten M. and Okada, Go and Oranje, Bob and Pantelis, Christos and Parker, Nadine and Pelphrey, Kevin A. and Phillips, Mary L. and Piacentini, John and Picó-Pérez, Maria and Picotin, Rosanne and Pigoni, Alessandro and Piras, Fabrizio and Piras, Federica and Pomarol-Clotet, Edith and Pontillo, Giuseppe and Porta-Casteràs, Daniel and Portella, Maria J. and Price, Rebecca B. and Quidé, Yann and Radua, Joaquim and Ringin, Elysha and Rodriguez-Cano, Elena and Rokicki, Jaroslav and Romero-Garcia, Rafael and Rossell, Susan and Ruan, Hanyang and Rubia, Katya and Sacchet, Matthew D. and Sakai, Yuki and Salvador, Raymond and Sani, Gabriele and Sato, Joao R. and Schmidt, André and Scott, Rodney J. and Sellgren, Carl M. and Sempach, Lukas and Shimizu, Eiji and Shivakumar, Venkataram and Sim, Kang and Soares, Jair C. and Soreni, Noam and Soriano-Mas, Carles and Sousa, Nuno and Stein, Frederike and Steinhäuser-Meerz, Jonas L. and Stern, Emily R. and Straube, Thomas and Strawn, Jeffrey R. and Sumner, Philip J. and Sungur, Ibrahim and Szeszko, Philip R. and Tammimies, Kristiina and Tomyshev, Alexander S. and Tosetti, Michela and van de Mortel, Laurens A. and van Horn, John D. and van Nieuwenhuizen, Helena and van Rheenen, Tamsyn E. and van Wingen, Guido and Vecchio, Daniela and Venkatasubramanian, Ganesan and Vieta, Eduard and Vilajosana, Enric and Vives-Gilabert, Yolanda and Völzke, Henry and Vriend, Chris and Wallace, Gregory L. and Wang, Zhen and Walter, Martin and Wang, Lei and Webb, Sara Jane and Westlye, Lars T. and Whittle, Sarah and Wielpütz, Mark O. and Wittfeld, Katharina and Woods, Will and Wu, Mon-Ju and Yang, Tony T. and Yatham, Lakshmi N. and Yoshida, Tokiko and Yoshinari, Abe and Yun, Je-Yeon and Zhao, Qing and Zunta-Soares, Giovana B. and {ENIGMA Autism Working Group:} and {ENIGMA Anxiety Working Group:} and {ENIGMA Bipolar Disorder Working Group:} and {ENIGMA Major Depression Working Group:} and {ENIGMA OCD Working Group:} and {ENIGMA Schizophrenia Working Group:} and van den Heuvel, Odile A. and Schmaal, Lianne and Pozzi, Elena and Andreassen, Ole A. and Ching, Christopher R. K. and Lawrence, Katherine E. and Kim, Gaon S. and Buitelaar, Jan K. and van Erp, Theo G.M. and Stein, Dan J. and Pine, Daniel S. and Winkler, Anderson M. and Bas-Hoogendam, Janna Marie and Zugman, Andre and van der Wee, Nic J.A. and Groenewold, Nynke A. and Marquand, Andre and Bernhardt, Boris C. and Jahanshad, Neda and Moore, Tyler M. and Thompson, Paul M. and Thomopoulos, Sophia I. and Eickhoff, Simon B. and Kirschner, Matthias and Satterthwaite, Theodore D. and Valk, Sofie L.},
title = {{Lifespan brain structural variation reveals shared organization across mental health conditions}},
journal = {medRxiv (preprint)},
year = {2026},
month = aug,
publisher = {medRxiv},
doi = {10.64898/
url = {https://
}
RIS
TY - JOUR
AU - Hettwer, Meike D.
AU - Saberi, Amin
AU - Shafiei, Golia
AU - Manoli, Aikaterina
AU - De Boer, Augustijn A.
AU - Alnæs, Dag
AU - Alonso, Pino
AU - Arango, Celso
AU - Assaf, Michal
AU - Avram, Mihai
AU - Balachander, Srinivas
AU - Banaj, Nerisa
AU - Başgöze, Zeynep
AU - Batistuzzo, Marcelo C.
AU - Bauduin, Stephanie E.E.C.
AU - Benedetti, Francesco
AU - Bertolin, Sara
AU - Besteher, Bianca
AU - Biagi, Laura
AU - Blair, Robert J.
AU - Blair, Karina
AU - Bölte, Sven
AU - Borgwardt, Stefan
AU - Bosco, Paolo
AU - Brambilla, Paolo
AU - Bravi, Beatrice
AU - Brennan, Brian P.
AU - Bruin, Willem B.
AU - Busatto, Geraldo F.
AU - Cairns, Murray J.
AU - Calderoni, Sara
AU - Calhoun, Vince
AU - Calvo, Rosa
AU - Cano, Marta
AU - Carr, Vaughan J.
AU - Carruthers, Sean P.
AU - Caruana, Georgia F.
AU - Caseras, Xavier
AU - Catts, Stanley V.
AU - Chi, I-Jou
AU - Cobia, Derin
AU - Colombo, Federica
AU - Couto, Maria Beatriz
AU - Crespo-Facorro, Benedicto
AU - Cullen, Kathryn R.
AU - Dannlowski, Udo
AU - Dapretto, Mirella
AU - Di Martino, Adriana
AU - Diefenbach, Gretchen J.
AU - Dols, Annemiek
AU - Duran, Fabio
AU - Dzinalija, Nadza
AU - Ecker, Christine
AU - Ehrlich, Stefan
AU - Eng, Goi Khia
AU - Fair, Damien A.
AU - Fernandes, Afonso
AU - Feusner, Jamie D.
AU - Fonzo, Gregory A.
AU - Fuentes-Claramonte, Paola
AU - Gaab, Nadine
AU - Godlewska, Beata R.
AU - Goldstein, Benjamin I.
AU - Gonul, Ali Saffet
AU - Gotlib, Ian H.
AU - Grabe, Hans J.
AU - Green, Melissa J.
AU - Grotegerd, Dominik
AU - Gruber, Oliver
AU - Gruner, Patricia
AU - Gupta, Abha R.
AU - Gur, Ruben C.
AU - Gur, Raquel E.
AU - Haar, Shlomi
AU - Hamilton, Jarold P.
AU - Haukvik, Unn K.
AU - Henskens, Frans A.
AU - Hinc, Asli C.
AU - Hirano, Yoshiyuki
AU - Hu, Hao
AU - Hughes, Matthew E.
AU - Iasevoli, Felice
AU - Im, Yanghee
AU - Ipser, Jonathan
AU - Hamoudi, Hammza Jabbar Abdl Sattar
AU - Jack, Allison
AU - Janiri, Delfina
AU - Janssen, Joost
AU - Jaspers-Fayer, Fern
AU - Jensen, Kyle M.
AU - Jin, Jingwen
AU - Kaiser, Stefan
AU - Kamishikiryo, Toshiharu
AU - Kang, Melody J. Y.
AU - Karuk, Andriana
AU - Kathmann, Norbert
AU - Kennedy, Kody G.
AU - Kim, Minah
AU - King, Joseph A.
AU - Kircher, Tilo
AU - Klahn, Anna Luisa
AU - Klein, Daniel N.
AU - Koch, Kathrin
AU - Kochunov, Peter
AU - Kushki, Azadeh
AU - Kwon, Jun Soo
AU - Lake, Marilyn T.
AU - Landén, Mikael
AU - Lazaro, Luisa
AU - Lebedeva, Irina
AU - Leila, Nabulsi
AU - Li, Meng
AU - Lochner, Christine
AU - Loughland, Carmel M.
AU - Luna, Beatriz
AU - Remnélius, Karl Lundin
AU - MacIntosh, Bradley J.
AU - Mancini, Matteo
AU - Manfro, Gisele G.
AU - Marsh, Rachel
AU - Martinez-Zalacain, Ignacio
AU - Mataix-Cols, David
AU - McDonald, Colm
AU - McGrath, Jane
AU - Menchon, Jose M.
AU - Morgado, Pedro
AU - Mowry, Bryan J.
AU - Mujica-Parodi, Lilianne R.
AU - Muñoz, Emma
AU - Muratori, Filippo
AU - Murphy, Declan
AU - Mwangi, Benson
AU - Narayanaswamy, Janardhanan C.
AU - Narumoto, Jin
AU - Nerland, Stener
AU - Neufeld, Janina
AU - Newman, Benjamin T.
AU - Nielsen, Jared A.
AU - Nurmi, Erika L.
AU - O’Neill, Joseph
AU - OHearn, Kirsten M.
AU - Okada, Go
AU - Oranje, Bob
AU - Pantelis, Christos
AU - Parker, Nadine
AU - Pelphrey, Kevin A.
AU - Phillips, Mary L.
AU - Piacentini, John
AU - Picó-Pérez, Maria
AU - Picotin, Rosanne
AU - Pigoni, Alessandro
AU - Piras, Fabrizio
AU - Piras, Federica
AU - Pomarol-Clotet, Edith
AU - Pontillo, Giuseppe
AU - Porta-Casteràs, Daniel
AU - Portella, Maria J.
AU - Price, Rebecca B.
AU - Quidé, Yann
AU - Radua, Joaquim
AU - Ringin, Elysha
AU - Rodriguez-Cano, Elena
AU - Rokicki, Jaroslav
AU - Romero-Garcia, Rafael
AU - Rossell, Susan
AU - Ruan, Hanyang
AU - Rubia, Katya
AU - Sacchet, Matthew D.
AU - Sakai, Yuki
AU - Salvador, Raymond
AU - Sani, Gabriele
AU - Sato, Joao R.
AU - Schmidt, André
AU - Scott, Rodney J.
AU - Sellgren, Carl M.
AU - Sempach, Lukas
AU - Shimizu, Eiji
AU - Shivakumar, Venkataram
AU - Sim, Kang
AU - Soares, Jair C.
AU - Soreni, Noam
AU - Soriano-Mas, Carles
AU - Sousa, Nuno
AU - Stein, Frederike
AU - Steinhäuser-Meerz, Jonas L.
AU - Stern, Emily R.
AU - Straube, Thomas
AU - Strawn, Jeffrey R.
AU - Sumner, Philip J.
AU - Sungur, Ibrahim
AU - Szeszko, Philip R.
AU - Tammimies, Kristiina
AU - Tomyshev, Alexander S.
AU - Tosetti, Michela
AU - van de Mortel, Laurens A.
AU - van Horn, John D.
AU - van Nieuwenhuizen, Helena
AU - van Rheenen, Tamsyn E.
AU - van Wingen, Guido
AU - Vecchio, Daniela
AU - Venkatasubramanian, Ganesan
AU - Vieta, Eduard
AU - Vilajosana, Enric
AU - Vives-Gilabert, Yolanda
AU - Völzke, Henry
AU - Vriend, Chris
AU - Wallace, Gregory L.
AU - Wang, Zhen
AU - Walter, Martin
AU - Wang, Lei
AU - Webb, Sara Jane
AU - Westlye, Lars T.
AU - Whittle, Sarah
AU - Wielpütz, Mark O.
AU - Wittfeld, Katharina
AU - Woods, Will
AU - Wu, Mon-Ju
AU - Yang, Tony T.
AU - Yatham, Lakshmi N.
AU - Yoshida, Tokiko
AU - Yoshinari, Abe
AU - Yun, Je-Yeon
AU - Zhao, Qing
AU - Zunta-Soares, Giovana B.
AU - ENIGMA Autism Working Group:
AU - ENIGMA Anxiety Working Group:
AU - ENIGMA Bipolar Disorder Working Group:
AU - ENIGMA Major Depression Working Group:
AU - ENIGMA OCD Working Group:
AU - ENIGMA Schizophrenia Working Group:
AU - van den Heuvel, Odile A.
AU - Schmaal, Lianne
AU - Pozzi, Elena
AU - Andreassen, Ole A.
AU - Ching, Christopher R. K.
AU - Lawrence, Katherine E.
AU - Kim, Gaon S.
AU - Buitelaar, Jan K.
AU - van Erp, Theo G.M.
AU - Stein, Dan J.
AU - Pine, Daniel S.
AU - Winkler, Anderson M.
AU - Bas-Hoogendam, Janna Marie
AU - Zugman, Andre
AU - van der Wee, Nic J.A.
AU - Groenewold, Nynke A.
AU - Marquand, Andre
AU - Bernhardt, Boris C.
AU - Jahanshad, Neda
AU - Moore, Tyler M.
AU - Thompson, Paul M.
AU - Thomopoulos, Sophia I.
AU - Eickhoff, Simon B.
AU - Kirschner, Matthias
AU - Satterthwaite, Theodore D.
AU - Valk, Sofie L.
TI - Lifespan brain structural variation reveals shared organization across mental health conditions
T2 - medRxiv (preprint)
J2 - medRxiv
PY - 2026
DA - 2026/
PB - medRxiv
DO - 10.64898/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.64898/
"type": "article",
"title": "Lifespan brain structural variation reveals shared organization across mental health conditions",
"container-title": "medRxiv (preprint)",
"author": [
{
"family": "Hettwer",
"given": "Meike D."
},
{
"family": "Saberi",
"given": "Amin"
},
{
"family": "Shafiei",
"given": "Golia"
},
{
"family": "Manoli",
"given": "Aikaterina"
},
{
"family": "De Boer",
"given": "Augustijn A."
},
{
"family": "Alnæs",
"given": "Dag"
},
{
"family": "Alonso",
"given": "Pino"
},
{
"family": "Arango",
"given": "Celso"
},
{
"family": "Assaf",
"given": "Michal"
},
{
"family": "Avram",
"given": "Mihai"
},
{
"family": "Balachander",
"given": "Srinivas"
},
{
"family": "Banaj",
"given": "Nerisa"
},
{
"family": "Başgöze",
"given": "Zeynep"
},
{
"family": "Batistuzzo",
"given": "Marcelo C."
},
{
"family": "Bauduin",
"given": "Stephanie E.E.C."
},
{
"family": "Benedetti",
"given": "Francesco"
},
{
"family": "Bertolin",
"given": "Sara"
},
{
"family": "Besteher",
"given": "Bianca"
},
{
"family": "Biagi",
"given": "Laura"
},
{
"family": "Blair",
"given": "Robert J."
},
{
"family": "Blair",
"given": "Karina"
},
{
"family": "Bölte",
"given": "Sven"
},
{
"family": "Borgwardt",
"given": "Stefan"
},
{
"family": "Bosco",
"given": "Paolo"
},
{
"family": "Brambilla",
"given": "Paolo"
},
{
"family": "Bravi",
"given": "Beatrice"
},
{
"family": "Brennan",
"given": "Brian P."
},
{
"family": "Bruin",
"given": "Willem B."
},
{
"family": "Busatto",
"given": "Geraldo F."
},
{
"family": "Cairns",
"given": "Murray J."
},
{
"family": "Calderoni",
"given": "Sara"
},
{
"family": "Calhoun",
"given": "Vince"
},
{
"family": "Calvo",
"given": "Rosa"
},
{
"family": "Cano",
"given": "Marta"
},
{
"family": "Carr",
"given": "Vaughan J."
},
{
"family": "Carruthers",
"given": "Sean P."
},
{
"family": "Caruana",
"given": "Georgia F."
},
{
"family": "Caseras",
"given": "Xavier"
},
{
"family": "Catts",
"given": "Stanley V."
},
{
"family": "Chi",
"given": "I-Jou"
},
{
"family": "Cobia",
"given": "Derin"
},
{
"family": "Colombo",
"given": "Federica"
},
{
"family": "Couto",
"given": "Maria Beatriz"
},
{
"family": "Crespo-Facorro",
"given": "Benedicto"
},
{
"family": "Cullen",
"given": "Kathryn R."
},
{
"family": "Dannlowski",
"given": "Udo"
},
{
"family": "Dapretto",
"given": "Mirella"
},
{
"family": "Di Martino",
"given": "Adriana"
},
{
"family": "Diefenbach",
"given": "Gretchen J."
},
{
"family": "Dols",
"given": "Annemiek"
},
{
"family": "Duran",
"given": "Fabio"
},
{
"family": "Dzinalija",
"given": "Nadza"
},
{
"family": "Ecker",
"given": "Christine"
},
{
"family": "Ehrlich",
"given": "Stefan"
},
{
"family": "Eng",
"given": "Goi Khia"
},
{
"family": "Fair",
"given": "Damien A."
},
{
"family": "Fernandes",
"given": "Afonso"
},
{
"family": "Feusner",
"given": "Jamie D."
},
{
"family": "Fonzo",
"given": "Gregory A."
},
{
"family": "Fuentes-Claramonte",
"given": "Paola"
},
{
"family": "Gaab",
"given": "Nadine"
},
{
"family": "Godlewska",
"given": "Beata R."
},
{
"family": "Goldstein",
"given": "Benjamin I."
},
{
"family": "Gonul",
"given": "Ali Saffet"
},
{
"family": "Gotlib",
"given": "Ian H."
},
{
"family": "Grabe",
"given": "Hans J."
},
{
"family": "Green",
"given": "Melissa J."
},
{
"family": "Grotegerd",
"given": "Dominik"
},
{
"family": "Gruber",
"given": "Oliver"
},
{
"family": "Gruner",
"given": "Patricia"
},
{
"family": "Gupta",
"given": "Abha R."
},
{
"family": "Gur",
"given": "Ruben C."
},
{
"family": "Gur",
"given": "Raquel E."
},
{
"family": "Haar",
"given": "Shlomi"
},
{
"family": "Hamilton",
"given": "Jarold P."
},
{
"family": "Haukvik",
"given": "Unn K."
},
{
"family": "Henskens",
"given": "Frans A."
},
{
"family": "Hinc",
"given": "Asli C."
},
{
"family": "Hirano",
"given": "Yoshiyuki"
},
{
"family": "Hu",
"given": "Hao"
},
{
"family": "Hughes",
"given": "Matthew E."
},
{
"family": "Iasevoli",
"given": "Felice"
},
{
"family": "Im",
"given": "Yanghee"
},
{
"family": "Ipser",
"given": "Jonathan"
},
{
"family": "Hamoudi",
"given": "Hammza Jabbar Abdl Sattar"
},
{
"family": "Jack",
"given": "Allison"
},
{
"family": "Janiri",
"given": "Delfina"
},
{
"family": "Janssen",
"given": "Joost"
},
{
"family": "Jaspers-Fayer",
"given": "Fern"
},
{
"family": "Jensen",
"given": "Kyle M."
},
{
"family": "Jin",
"given": "Jingwen"
},
{
"family": "Kaiser",
"given": "Stefan"
},
{
"family": "Kamishikiryo",
"given": "Toshiharu"
},
{
"family": "Kang",
"given": "Melody J. Y."
},
{
"family": "Karuk",
"given": "Andriana"
},
{
"family": "Kathmann",
"given": "Norbert"
},
{
"family": "Kennedy",
"given": "Kody G."
},
{
"family": "Kim",
"given": "Minah"
},
{
"family": "King",
"given": "Joseph A."
},
{
"family": "Kircher",
"given": "Tilo"
},
{
"family": "Klahn",
"given": "Anna Luisa"
},
{
"family": "Klein",
"given": "Daniel N."
},
{
"family": "Koch",
"given": "Kathrin"
},
{
"family": "Kochunov",
"given": "Peter"
},
{
"family": "Kushki",
"given": "Azadeh"
},
{
"family": "Kwon",
"given": "Jun Soo"
},
{
"family": "Lake",
"given": "Marilyn T."
},
{
"family": "Landén",
"given": "Mikael"
},
{
"family": "Lazaro",
"given": "Luisa"
},
{
"family": "Lebedeva",
"given": "Irina"
},
{
"family": "Leila",
"given": "Nabulsi"
},
{
"family": "Li",
"given": "Meng"
},
{
"family": "Lochner",
"given": "Christine"
},
{
"family": "Loughland",
"given": "Carmel M."
},
{
"family": "Luna",
"given": "Beatriz"
},
{
"family": "Remnélius",
"given": "Karl Lundin"
},
{
"family": "MacIntosh",
"given": "Bradley J."
},
{
"family": "Mancini",
"given": "Matteo"
},
{
"family": "Manfro",
"given": "Gisele G."
},
{
"family": "Marsh",
"given": "Rachel"
},
{
"family": "Martinez-Zalacain",
"given": "Ignacio"
},
{
"family": "Mataix-Cols",
"given": "David"
},
{
"family": "McDonald",
"given": "Colm"
},
{
"family": "McGrath",
"given": "Jane"
},
{
"family": "Menchon",
"given": "Jose M."
},
{
"family": "Morgado",
"given": "Pedro"
},
{
"family": "Mowry",
"given": "Bryan J."
},
{
"family": "Mujica-Parodi",
"given": "Lilianne R."
},
{
"family": "Muñoz",
"given": "Emma"
},
{
"family": "Muratori",
"given": "Filippo"
},
{
"family": "Murphy",
"given": "Declan"
},
{
"family": "Mwangi",
"given": "Benson"
},
{
"family": "Narayanaswamy",
"given": "Janardhanan C."
},
{
"family": "Narumoto",
"given": "Jin"
},
{
"family": "Nerland",
"given": "Stener"
},
{
"family": "Neufeld",
"given": "Janina"
},
{
"family": "Newman",
"given": "Benjamin T."
},
{
"family": "Nielsen",
"given": "Jared A."
},
{
"family": "Nurmi",
"given": "Erika L."
},
{
"family": "O’Neill",
"given": "Joseph"
},
{
"family": "OHearn",
"given": "Kirsten M."
},
{
"family": "Okada",
"given": "Go"
},
{
"family": "Oranje",
"given": "Bob"
},
{
"family": "Pantelis",
"given": "Christos"
},
{
"family": "Parker",
"given": "Nadine"
},
{
"family": "Pelphrey",
"given": "Kevin A."
},
{
"family": "Phillips",
"given": "Mary L."
},
{
"family": "Piacentini",
"given": "John"
},
{
"family": "Picó-Pérez",
"given": "Maria"
},
{
"family": "Picotin",
"given": "Rosanne"
},
{
"family": "Pigoni",
"given": "Alessandro"
},
{
"family": "Piras",
"given": "Fabrizio"
},
{
"family": "Piras",
"given": "Federica"
},
{
"family": "Pomarol-Clotet",
"given": "Edith"
},
{
"family": "Pontillo",
"given": "Giuseppe"
},
{
"family": "Porta-Casteràs",
"given": "Daniel"
},
{
"family": "Portella",
"given": "Maria J."
},
{
"family": "Price",
"given": "Rebecca B."
},
{
"family": "Quidé",
"given": "Yann"
},
{
"family": "Radua",
"given": "Joaquim"
},
{
"family": "Ringin",
"given": "Elysha"
},
{
"family": "Rodriguez-Cano",
"given": "Elena"
},
{
"family": "Rokicki",
"given": "Jaroslav"
},
{
"family": "Romero-Garcia",
"given": "Rafael"
},
{
"family": "Rossell",
"given": "Susan"
},
{
"family": "Ruan",
"given": "Hanyang"
},
{
"family": "Rubia",
"given": "Katya"
},
{
"family": "Sacchet",
"given": "Matthew D."
},
{
"family": "Sakai",
"given": "Yuki"
},
{
"family": "Salvador",
"given": "Raymond"
},
{
"family": "Sani",
"given": "Gabriele"
},
{
"family": "Sato",
"given": "Joao R."
},
{
"family": "Schmidt",
"given": "André"
},
{
"family": "Scott",
"given": "Rodney J."
},
{
"family": "Sellgren",
"given": "Carl M."
},
{
"family": "Sempach",
"given": "Lukas"
},
{
"family": "Shimizu",
"given": "Eiji"
},
{
"family": "Shivakumar",
"given": "Venkataram"
},
{
"family": "Sim",
"given": "Kang"
},
{
"family": "Soares",
"given": "Jair C."
},
{
"family": "Soreni",
"given": "Noam"
},
{
"family": "Soriano-Mas",
"given": "Carles"
},
{
"family": "Sousa",
"given": "Nuno"
},
{
"family": "Stein",
"given": "Frederike"
},
{
"family": "Steinhäuser-Meerz",
"given": "Jonas L."
},
{
"family": "Stern",
"given": "Emily R."
},
{
"family": "Straube",
"given": "Thomas"
},
{
"family": "Strawn",
"given": "Jeffrey R."
},
{
"family": "Sumner",
"given": "Philip J."
},
{
"family": "Sungur",
"given": "Ibrahim"
},
{
"family": "Szeszko",
"given": "Philip R."
},
{
"family": "Tammimies",
"given": "Kristiina"
},
{
"family": "Tomyshev",
"given": "Alexander S."
},
{
"family": "Tosetti",
"given": "Michela"
},
{
"family": "van de Mortel",
"given": "Laurens A."
},
{
"family": "van Horn",
"given": "John D."
},
{
"family": "van Nieuwenhuizen",
"given": "Helena"
},
{
"family": "van Rheenen",
"given": "Tamsyn E."
},
{
"family": "van Wingen",
"given": "Guido"
},
{
"family": "Vecchio",
"given": "Daniela"
},
{
"family": "Venkatasubramanian",
"given": "Ganesan"
},
{
"family": "Vieta",
"given": "Eduard"
},
{
"family": "Vilajosana",
"given": "Enric"
},
{
"family": "Vives-Gilabert",
"given": "Yolanda"
},
{
"family": "Völzke",
"given": "Henry"
},
{
"family": "Vriend",
"given": "Chris"
},
{
"family": "Wallace",
"given": "Gregory L."
},
{
"family": "Wang",
"given": "Zhen"
},
{
"family": "Walter",
"given": "Martin"
},
{
"family": "Wang",
"given": "Lei"
},
{
"family": "Webb",
"given": "Sara Jane"
},
{
"family": "Westlye",
"given": "Lars T."
},
{
"family": "Whittle",
"given": "Sarah"
},
{
"family": "Wielpütz",
"given": "Mark O."
},
{
"family": "Wittfeld",
"given": "Katharina"
},
{
"family": "Woods",
"given": "Will"
},
{
"family": "Wu",
"given": "Mon-Ju"
},
{
"family": "Yang",
"given": "Tony T."
},
{
"family": "Yatham",
"given": "Lakshmi N."
},
{
"family": "Yoshida",
"given": "Tokiko"
},
{
"family": "Yoshinari",
"given": "Abe"
},
{
"family": "Yun",
"given": "Je-Yeon"
},
{
"family": "Zhao",
"given": "Qing"
},
{
"family": "Zunta-Soares",
"given": "Giovana B."
},
{
"literal": "ENIGMA Autism Working Group:"
},
{
"literal": "ENIGMA Anxiety Working Group:"
},
{
"literal": "ENIGMA Bipolar Disorder Working Group:"
},
{
"literal": "ENIGMA Major Depression Working Group:"
},
{
"literal": "ENIGMA OCD Working Group:"
},
{
"literal": "ENIGMA Schizophrenia Working Group:"
},
{
"family": "van den Heuvel",
"given": "Odile A."
},
{
"family": "Schmaal",
"given": "Lianne"
},
{
"family": "Pozzi",
"given": "Elena"
},
{
"family": "Andreassen",
"given": "Ole A."
},
{
"family": "Ching",
"given": "Christopher R. K."
},
{
"family": "Lawrence",
"given": "Katherine E."
},
{
"family": "Kim",
"given": "Gaon S."
},
{
"family": "Buitelaar",
"given": "Jan K."
},
{
"family": "van Erp",
"given": "Theo G.M."
},
{
"family": "Stein",
"given": "Dan J."
},
{
"family": "Pine",
"given": "Daniel S."
},
{
"family": "Winkler",
"given": "Anderson M."
},
{
"family": "Bas-Hoogendam",
"given": "Janna Marie"
},
{
"family": "Zugman",
"given": "Andre"
},
{
"family": "van der Wee",
"given": "Nic J.A."
},
{
"family": "Groenewold",
"given": "Nynke A."
},
{
"family": "Marquand",
"given": "Andre"
},
{
"family": "Bernhardt",
"given": "Boris C."
},
{
"family": "Jahanshad",
"given": "Neda"
},
{
"family": "Moore",
"given": "Tyler M."
},
{
"family": "Thompson",
"given": "Paul M."
},
{
"family": "Thomopoulos",
"given": "Sophia I."
},
{
"family": "Eickhoff",
"given": "Simon B."
},
{
"family": "Kirschner",
"given": "Matthias"
},
{
"family": "Satterthwaite",
"given": "Theodore D."
},
{
"family": "Valk",
"given": "Sofie L."
}
],
"container-title-short":
"DOI": "10.64898/
"publisher": "medRxiv",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
18
]
]
}
}
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.64898/2026.03.04.709586 [code]
- Mapping Higher-Order Topology in OCD Brain Networks with Hodge LaplacianJournal: bioRxiv (preprint)In common: statsmodels, seaborn, scikit-learn, 4 other tools, 9 authors
- [2] doi:10.1038/s41467-026-74153-2 [code]
- Regional, functional and transcriptomic decoding of multidimensional brain structure alterations in obsessive-compulsive disorder.Journal: Nature communicationsIn common: BrainSMASH, BrainSpace, NiBabel, 6 other tools, 4 references, 6 authors
- [3] doi:10.1038/s41380-026-03641-0
- Cerebral cortical alterations in adolescent early-onset psychosis: a surface-based morphometry mega-analysis.Journal: Molecular psychiatryIn common: 5 references, 6 authors
- [4] doi:10.1038/s41380-026-03547-x [code]
- Multiscale characterization of cortical signatures in positive and negative schizotypy: a worldwide ENIGMA study.Journal: Molecular psychiatryIn common: 10 references, 3 authors
- [5] doi:10.1038/s41398-026-04078-3 [code]
- Brain age prediction in generalized anxiety disorder using a convolutional neural network.Journal: Translational psychiatryIn common: clinical / translational, 1 reference, 5 authors
- [6] doi:10.1038/s41398-026-04189-x [code]
- Decomposing neuroanatomical heterogeneity in depression: insights from an ENIGMA major depressive disorder working group study in 5146 individuals.Journal: Translational psychiatryIn common: clinical / translational, 5 references, 4 authors
- [7] doi:10.21203/rs.3.rs-9246968/v1 [code]
- Copy number variants reveal divergent genetic and diagnostic cortical signatures across psychiatric disordersJournal: Research Square (preprint)In common: pandas, NumPy, clinical / translational, 10 references, 2 authors
- [8] doi:10.1162/imag.a.1269 [code]
- From early to contemporary normative modeling: Mapping individual differences in neurophysiological signals.Journal: Imaging neuroscience (Cambridge, Mass.)In common: Nilearn, NiBabel, statsmodels, 6 other tools, 11 references
- [9] doi:10.1038/s41467-026-72875-x [code]
- Lifespan normative modeling of brain microstructure.Journal: Nature communicationsIn common: seaborn, scikit-learn, pandas, 3 other tools, 6 references, 2 authors
- [10] doi:10.1038/s41380-026-03500-y [code]
- Altered frontal and occipital cortical microstructure in obsessive-compulsive disorder - a multisite mega-analysis.Journal: Molecular psychiatryIn common: clinical / translational, 7 references, 2 authors
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.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 3 repositories of the authors' code, each at its verified commit and with its license, 11 scripts, and 10 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:cb08bd6634030ee0…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
