Canonical neurodevelopmental trajectories of structural and functional manifolds.
The 40 matches · 5 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
- [1] § Results › Dimensions of cognition, but not psychopathology, are developmentally sensitive predictors of structure-function coupling ↔ code/structure_function_coupling_and_psychopathology.py, lines 114–185 · score 0.98 · backward digit recall, varimax rotation, letter switching, motor speed, Executive Function, peer relations
- [2] § Methods › Statistical analyses and data processing › Measures of psychopathology and cognition ↔ code/structure_function_coupling_and_psychopathology.py, lines 114–185 · score 0.96 · nearest neighbours, letter switching, motor speed, executive function, peer relations, visual scanning
- [3] § Methods › Statistical analyses and data processing › Measures of psychopathology and cognition ↔ code/gradient_developmental_sensitivity.py, lines 470–487 · score 0.95 · elevated score, Fisher Pearson, psychopathology scores, executive functioning, peer relations, high motion
- [4] § Methods › Missing data ↔ code/structure_function_coupling_and_psychopathology.py, lines 279–357 · score 0.94 · KNN imputation, Conners peer relations, squared error, imputation accuracy, uniform weights, missingness
- [5] § Methods › Statistical analyses and data processing › Procrustes rotation ↔ code/deriving_group_and_individual_gradients_v2.py, lines 27–153 · score 0.93 · Procrustes rotation, rotated eigenvectors, gradients explaining, right hemisphere, left hemisphere, affinity matrix
- [6] § Methods › Statistical analyses and data processing › Manifold generation ↔ code/deriving_group_and_individual_gradients_v2.py, lines 27–153 · score 0.93 · anisotropic diffusion, dimensionality reduction technique, left right hemisphere, affinity matrices, principal component, diffusion map
- [7] § Methods › GAMM cross-validation ↔ code/gamm_coupling_crossvalidation.R, lines 51–136 · score 0.92 · compared empirical prediction, cross validation, prediction accuracies, leakage, blocks, fold
- [8] § Results › Dimensions of cognition, but not psychopathology, are developmentally sensitive predictors of structure-function coupling ↔ code/NKI_and_CALM_cognitive_behavioural_V3.py, lines 61–107 · score 0.91 · backward digit recall, letter switching, motor speed, Executive Function, peer relations, visual scanning
- [9] § Methods › Statistical analyses and data processing › Measures of psychopathology and cognition ↔ code/NKI_and_CALM_cognitive_behavioural_V3.py, lines 61–107 · score 0.90 · letter switching, motor speed, executive function, peer relations, visual scanning, achievement
- [10] § Results ↔ code/deriving_group_and_individual_gradients_v2.py, lines 1–26 · score 0.89 · magnetic resonance imaging, Nathan Kline Institute, Sample Longitudinal Discovery, Brain Development Trajectories, Rockland, UK
- [11] § Methods › Missing data › GAMMs ↔ code/GAMM.functions.v3.R, lines 555–613 · score 0.88 · maximum absolute standardised, simultaneous confidence intervals, predicted manifold eccentricity, covariance matrix, multivariate, gaussian
- [12] § Results › Structure-function coupling follows a unimodal-transmodal axis, with developmental effects concentrated within higher-order association networks ↔ code/structure_function_coupling_sensitivity.py, lines 43–102 · score 0.86 · nodal coupling coefficient, linear regression, raw functional connectivity, CALM neurotypical, Euclidean distance, structure function coupling
- [13] § Methods › MRI data processing › DWI ↔ connectome_cleaning_construction/connectome_construction_selection_thresholding_nki.m, lines 279–423 · score 0.86 · conducted distance dependent, weighted communicability matrices, thresholded connectomes, representative connectome, functional connectivity networks, binary
- [14] § Results ↔ code/deriving_group_and_individual_gradients_v2.py, lines 330–381 · score 0.85 · Diffusion map embedding, normalised angle, dimensionality reduction, affinity matrices, network parcellation, cosine
- [15] § Methods › Harmonising CALM neuroimaging data ↔ code/nkir_calm_descriptives_v2.R, lines 272–325 · score 0.85 · backward digit recall, matrix reasoning, dot matrix, standardised scores, March, alliteration
- [16] § Methods › Statistical analyses and data processing › Procrustes rotation ↔ code/gradient_developmental_sensitivity.py, lines 29–59 · score 0.84 · Procrustes rotation, rotated eigenvectors, diffusion map embedding, normalised angle, left hemisphere, kernel
- [17] § Methods › MRI data processing › Resting-state functional image processing ↔ connectome_cleaning_construction/clean_and_parcellate_fmri_nki.py, the whole file · a weak match · score 0.83 · AROMA denoised, temporal degrees, fMRIPrep, CSF, signal, freedom
- [18] § Methods › MRI data processing › Resting-state functional image processing ↔ connectome_cleaning_construction/clean_and_parcellate_fmri_calm.py, the whole file · a weak match · score 0.83 · AROMA denoised, temporal degrees, fMRI, WM, CSF, signal
- [19] § Methods › Pre-processing of behavioural and cognitive data ↔ code/nkir_calm_descriptives_v2.R, lines 272–325 · score 0.82 · AWMA digit recall, backward digit, standardised scores, longitudinal CALM, mice, alliteration
- [20] § Methods › MRI data processing › DWI ↔ code/deriving_group_and_individual_gradients_v2.py, lines 330–381 · score 0.81 · dependent consensus thresholding, affinity matrices, thresholded connectomes, Brainnetome, resolution, Streamlines
- [21] § Results › Manifold eccentricity as a measure of individual variability in gradient organisation ↔ code/eccentricity_graph_theory.m, lines 51–71 · score 0.81 · weighted clustering coefficient, graph theory metrics, module degree, participation coefficient, modular, eccentricity
- [22] § Results › Dimensions of cognition, but not psychopathology, are developmentally sensitive predictors of structure-function coupling ↔ code/gamm_coupling_crossvalidation.R, lines 51–136 · score 0.79 · empirical prediction accuracies, participant blocks, cross validation, structure function coupling, permuted, stratified
- [23] § Results › Dimensions of cognition, but not psychopathology, are developmentally sensitive predictors of structure-function coupling ↔ code/eLife_revisions_plots.R, lines 25–95 · score 0.79 · empirical prediction accuracies, FDR correction, global coupling, cognitive factor, default mode network, structure function coupling
- [24] § Results › Structure-function coupling follows a unimodal-transmodal axis, with developmental effects concentrated within higher-order association networks ↔ code/structure_function_coupling_sensitivity.py, lines 43–102 · score 0.78 · multi linear regression, raw connectomic, novel metric, Structure function coupling, referred CALM, nodal
- [25] § Results › Stability of individual-level gradients across developmental time ↔ code/gradient_developmental_sensitivity.py, lines 258–346 · score 0.76 · Procrustes alignment, negatively correlated, gradient development, functional scans, head motion, scan age
- [26] § Methods › Participants ↔ connectome_cleaning_construction/clean_and_parcellate_fmri_nki.py, the whole file · a weak match · score 0.76 · NKI Rockland Sample, Longitudinal Discovery, Trajectories sub, Brain Development
- [27] § Results › Dimensions of cognition, but not psychopathology, are developmentally sensitive predictors of structure-function coupling ↔ code/psychopathology_cognition_dimensions_structure_function.R, lines 181–204 · score 0.75 · age interactions, somato motor, cognitive dimension, dorsal attention, default mode network, split
- [28] § Results › Dimensions of cognition, but not psychopathology, are developmentally sensitive predictors of structure-function coupling ↔ code/psychopathology_cognition_dimensions_structure_function.R, lines 181–204 · score 0.74 · somato motor, cognitive dimension, cognitive factor, dorsal attention, default mode network, psychopathology
- [29] § Results › Manifold eccentricity as a measure of individual variability in gradient organisation ↔ code/eLife_revisions_plots.R, lines 25–95 · score 0.74 · weighted clustering, module degree, participation coefficient, dominance, nodal, adolescents
- [30] § Methods › Harmonising CALM neuroimaging data ↔ connectome_cleaning_construction/calm_harmonisation_effects.m, lines 6–25 · score 0.73 · Brain Connectivity Toolbox, graph theory metrics, assortativity, efficiency, status, modularity
- [31] § Results › Dimensions of cognition, but not psychopathology, are developmentally sensitive predictors of structure-function coupling ↔ code/developmental_effects_on_structure_function_relationships.R, lines 251–309 · score 0.70 · age interactions, coupling globally, dorsal attention, default mode network, structure function coupling, parse
- [32] § Results › Stability of individual-level gradients across developmental time ↔ code/gradient_developmental_sensitivity.py, lines 94–106 · score 0.69 · Frobenius norm, scalar projection, variance explained, square, magnitude, matrix
- [33] § Results › Structure-function coupling follows a unimodal-transmodal axis, with developmental effects concentrated within higher-order association networks ↔ code/developmental_effects_on_structure_function_relationships.R, lines 466–521 · score 0.69 · skewness coefficient, kurtosis, CV, skewed, structure function coupling, smallest
- [34] § Results › Structure-function coupling follows a unimodal-transmodal axis, with developmental effects concentrated within higher-order association networks ↔ code/GAMM.functions.v3.R, lines 333–455 · score 0.67 · intrinsic connectivity networks, Spearman rank correlation, confidence intervals, cohort, vectors, variable
- [35] § Methods › MRI data processing › Resting-state functional image processing ↔ connectome_cleaning_construction/clean_and_parcellate_fmri_calm.py, the whole file · a weak match · score 0.66 · edge weights, Pearson correlations, transformed, Schaefer, row, parcellation
- [36] § Methods › Missing data › GAMMs ↔ code/psychopathology_cognition_dimensions_structure_function.R, lines 110–179 · score 0.66 · random intercepts, discovery rate, tensors, framewise, displacement, GAMMs
- [37] § Methods › MRI data acquisition › CALM ↔ code/neurotypical.coupling.development.R, the whole file · a weak match · score 0.65 · Brain Sciences Unit, MRC Cognition, head motion, slices, game, scans
- [38] § Methods › MRI data acquisition › NKI-Rockland sample longitudinal discovery of brain development trajectories ↔ code/deriving_group_and_individual_gradients_v2.py, lines 1–26 · score 0.64 · Nathan Kline Institute, Rockland, discovery, diffusion, trajectories, longitudinal
- [39] § Results › Developmental trajectories of structural manifold contraction and functional manifold expansion ↔ code/GAMM.functions.v3.R, lines 333–455 · score 0.64 · simultaneous confidence intervals, intrinsic connectivity network, global manifold eccentricity, cohort, GAMM, smooth
- [40] § Results › Dimensions of cognition, but not psychopathology, are developmentally sensitive predictors of structure-function coupling ↔ code/developmental_effects_on_structure_function_relationships.R, lines 251–309 · score 0.63 · dorsal attention, default mode network, structure function coupling, parse, partition, EDF
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
Python · 529 lines · 35 KB · CC-BY-4.0 · 6 matches
- # This python script details conducting diffusion map embedding (DME) on structural (weighted communicability) and
- # functional connectomes from 3 time points in the nathan kline institute rockland (nki) sample longitudinal discovery
- # of brain development trajectories sub-study, and 2 time points from the centre for attention, learning, and memory
- # (calm). First, log onto a cluster node, activate neuroconda v2 and load python3. Written by Alicja Monaghan - MRC CBU,
- # University of Cambridge. All correspondence to [email hidden]
- # PART 1 - Importing Packages and Setting Up Work Space #
- import scipy
- from scipy.io import savemat
- from scipy.stats import spearmanr, pearsonr, t
- import os
- import numpy as np
- import rpy2.robjects as robjects
- from brainspace.gradient import diffusion_mapping, compute_affinity, laplacian_eigenmaps, GradientMaps
- from brainspace.gradient.alignment import procrustes
- from scipy.io import loadmat
- import mat73
- os.chdir('/Users/alicjamonaghan/Desktop/neurodevelopmental_gradients')
- # PART 2 - Specify functions!
- # This function conducts diffusion map embedding (DME), using the Brain Space library, across different data sets,
- # DME parameters (the anisotropic diffusion parameter alpha, diffusion time t, and kernels), modalities (streamline
- # counts from probabilistic tractography converted into communicability matrices, alongside resting-state functional
- # magnetic resonance imaging connectomes).
- def run_group_dimensionality_reduction(dataset, modality, parcellation, ncomp, user_kernel, user_alpha, user_t,
- embedding_approach, subset):
- # The data set argument has two options - CALM or NKI. Load the thresholded connectomes for the given modality
- # (sc or fc).
- thresholded_connectomes = mat73.loadmat(
- os.getcwd() + '/data/' + dataset +
- '/connectomes/thresholded_structural_and_functional_connectomes.mat')['thresholded'][modality]
- # Format modality names for output
- if modality == 'sc':
- modality_name = 'structural'
- else:
- modality_name = 'functional'
- # If the data set is calm, extract the harmonised connectomes. We didn't do any harmonisation for NKI as all neuro-
- # imaging data was collected on the same scanner without any software changes.
- if dataset == 'calm':
- thresholded_connectomes = thresholded_connectomes['harmonised']
- group_thresholded_connectome = thresholded_connectomes['group']
- # Load the parcellated group connectomes, using one of 3 options: schaefer100x7, schaefer200x7, or brainnetome246.
- # If using CALM, specify whether we want the referred or non-referred subset using the 'subset' argument.
- if dataset == 'calm':
- group_thresholded_connectome = group_thresholded_connectome[subset][parcellation]
- else:
- group_thresholded_connectome = group_thresholded_connectome[parcellation]
- # Find the number of regions of interest and initialise output arrays for eigenvectors for each hemisphere (left
- # collected first, then right). The user specifies how many components to extract using ncomp.
- nroi = group_thresholded_connectome.shape[0]
- eigenvectors = np.zeros([nroi, ncomp])
- eigenvalues = np.zeros([ncomp, 2])
- # Conduct dimensionality reduction separately for each hemisphere as, otherwise, a left-right hemisphere split
- # would be detected as the principal eigenvector.
- hemi_variance_explained_array = np.zeros(shape=(2, ncomp))
- for hemi_id in range(0, 2):
- if hemi_id == 0:
- hemi_name = "left"
- # Set the region limits
- nroi_range = range(0, int(nroi / 2))
- else:
- hemi_name = "right"
- nroi_range = range(int(nroi / 2), nroi)
- # Construct the affinity matrix using the brainspace module! user_kernel describes the kernel for the affinity.
- affinity = compute_affinity(group_thresholded_connectome[np.ix_(nroi_range, nroi_range)],
- kernel=user_kernel, sparsity=None)
- # Check that there are no missing values in the affinity matrix, and raise a warning if there is!
- if np.isnan(affinity).any():
- print("Missing values in {} {} hemisphere affinity in the {} data set.".
- format(modality_name, hemi_name, dataset))
- # Conduct the dimensionality reduction technique specified in the approach argument: this is diffusion-map
- # embedding ('dm'), laplacian eigenmaps ('le'), or principal components analysis ('pca').
- if embedding_approach == 'dm':
- # For DME, use the specified anisotropic diffusion (user_alpha) and diffusion times (user_t).
- eigenvectors[nroi_range, :], eigenvalues[:, hemi_id] = \
- diffusion_mapping(affinity, n_components=ncomp, alpha=user_alpha,
- diffusion_time=user_t, random_state=10)
- elif embedding_approach == 'le':
- # Using default parameters i.e. normalised laplacian
- eigenvectors[nroi_range, :], eigenvalues[:, hemi_id] = \
- laplacian_eigenmaps(affinity, n_components=ncomp, random_state=10)
- else:
- # Also use default parameters for PCA!
- gm_object_fitted = GradientMaps(n_components=ncomp, approach='pca', random_state=10).fit(affinity)
- eigenvectors[nroi_range, :], eigenvalues[:, hemi_id] = \
- gm_object_fitted.gradients_, gm_object_fitted.lambdas_
- # Find how much variance each component explains for each hemisphere!
- for comp in range(0, ncomp):
- hemi_variance_explained_array[hemi_id, comp] = eigenvalues[comp, hemi_id] / sum(eigenvalues[:, hemi_id])
- print("For the {} hemisphere, component {} explains {} percent of variance.".
- format(hemi_name, comp, hemi_variance_explained_array[hemi_id, comp] * 100))
- # And find the variance explained averaged across both hemispheres
- for comp in range(0, ncomp):
- print("Across hemispheres, component {} explains {} percent of variance.".format(
- comp + 1, round(np.mean(hemi_variance_explained_array[:, comp]) * 100, 2)))
- # When processing structural gradients in CALM, swap the first and second gradient around in the left hemisphere.
- # This is because in CALM, the first and second principal gradients explain a very similar amount of variance,
- # meaning that their order can be switched. We know this because the left and right hemispheres should be mirror
- # images of each other. We don't see this effect in the non-referred subset.
- if dataset == 'calm' and modality == 'sc':
- # Align the first component in the left hemisphere to the second component in the right
- lh_component_1 = procrustes(eigenvectors[range(0, int(nroi / 2)), 0].reshape(100, 1),
- eigenvectors[range(int(nroi / 2), nroi), 1].reshape(100, 1))
- lh_component_2 = procrustes(eigenvectors[range(0, int(nroi / 2)), 1].reshape(100, 1),
- eigenvectors[range(int(nroi / 2), nroi), 0].reshape(100, 1))
- lh_component_3 = procrustes(eigenvectors[range(0, int(nroi / 2)), 2].reshape(100, 1),
- eigenvectors[range(int(nroi / 2), nroi), 2].reshape(100, 1))
- rotated_eigenvectors = np.hstack((lh_component_1, lh_component_2, lh_component_3))
- # Append the rotated left hemisphere eigenvectors to the right hemisphere.
- rotated_eigenvectors = np.concatenate(
- [rotated_eigenvectors, eigenvectors[range(int(nroi / 2), nroi), :]])
- else:
- # Align the left hemisphere to the right using a Procrustes rotation.
- rotated_eigenvectors = \
- procrustes(eigenvectors[range(0, int(nroi / 2)), :], eigenvectors[range(int(nroi / 2), nroi), :])
- # Append the rotated left hemisphere eigenvectors to the right hemisphere.
- rotated_eigenvectors = np.concatenate([rotated_eigenvectors, eigenvectors[range(int(nroi / 2), nroi), :]])
- if dataset == 'calm':
- print("For the {} subset...".format(subset))
- if embedding_approach == 'dm':
- print("Conducted {} {} in the {} data set in the {} parcellation, with alpha of {}, diffusion time of {}, "
- "and {} kernel.".format(modality_name, embedding_approach, dataset, parcellation, user_alpha, user_t,
- user_kernel))
- else:
- print("Conducted {} {} in the {} data set in the {} parcellation.".
- format(modality_name, embedding_approach, dataset, parcellation))
- # Now find which regions anchor the gradients! Start by loading the parcellation meta-data
- if parcellation is 'schaefer100x7' or 'schaefer200x7':
- parcellation_metadata = scipy.io.loadmat(
- 'data/' + parcellation + '_1mm_info.mat', simplify_cells=True)[parcellation + '_1mm_info']['name']
- else:
- parcellation_metadata = scipy.io.loadmat(
- '/imaging/astle/users/da04/PhD/qsiprep_data/data/' + parcellation + '_info.mat',
- simplify_cells=True)[parcellation]['name']
- # Loop through each component. Find the top 3 regions with the largest positive and negative eigenvectors,
- # respectively.
- nroi = len(parcellation_metadata)
- # The parcellation names are sorted by increasing eigenvector values i.e. largest negative eigenvectors are first,
- # and largest positive eigenvectors are last.
- for comp in range(0, ncomp):
- sorted_parcellation_metadata = parcellation_metadata[np.argsort(rotated_eigenvectors[:, comp])]
- print('{} gradient for component {}: anchored at one end by {}, and at the other by {}.'.format(
- modality_name, comp + 1, ','.join(sorted_parcellation_metadata[0:5]),
- ','.join(sorted_parcellation_metadata[nroi - 5:nroi])))
- del thresholded_connectomes, group_thresholded_connectome, hemi_variance_explained_array
- return rotated_eigenvectors, eigenvalues
- # This is a Python translation of a spin-test for parcellated brain data, initially developed by Dr. Frantisek Vasa in
- # R (see 'Adolescent Turning of Association Cortex in Human Structural Brain Networks' in Cerebral Cortex, 2018). For
- # the toolbox in R, see https://github.com/frantisekvasa/rotate_parcellation
- def perm_sphere(x, y, corr_type):
- # perm_id describes the array of permutations from regions to themselves on the sphere, and was generated using the
- # rotate.parcellation function in R. we've saved these mappings as a .csv file, so load this now! Subtract 1 from
- # each perm_id value to account for zero-indexing in Python
- perm_id = np.array(robjects.r.readRDS('data/rotated.parcellation.rds')).astype(int) - 1
- # Get the number of regions of interest (nroi) and permutations
- nroi = perm_id.shape[0]
- nperm = perm_id.shape[1]
- # Empirical correlation between the two parcellated cortical maps X and Y, using inputted correlation method
- if corr_type == 'spearman':
- corr_function = spearmanr
- else:
- corr_function = pearsonr
- empirical_correlation = corr_function(x, y)[0]
- # Initialise array to hold the permuted x values
- x_perm = np.zeros((nroi, nperm))
- y_perm = np.zeros((nroi, nperm))
- # Loop across permutations. For each, loop across each region of interest, and calculate the correlation between the
- # randomly-shuffled region
- for r in range(0, nperm):
- for i in range(0, nroi):
- x_perm[i, r] = x[perm_id[i, r]]
- y_perm[i, r] = y[perm_id[i, r]]
- # Correlation to un-permuted measures
- rho_null_xy = np.zeros(nperm)
- rho_null_yx = np.zeros(nperm)
- for r in range(0, nperm):
- rho_null_xy[r] = corr_function(x_perm[:, r], y)[0]
- rho_null_yx[r] = corr_function(y_perm[:, r], x)[0]
- # Depending on the sign of the empirical correlation, find the permuted p-values for x mapped onto y and vice versa
- if empirical_correlation > 0:
- p_perm_xy = sum(rho_null_xy > empirical_correlation) / nperm
- p_perm_yx = sum(rho_null_yx > empirical_correlation) / nperm
- else:
- p_perm_xy = sum(rho_null_xy < empirical_correlation) / nperm
- p_perm_yx = sum(rho_null_yx < empirical_correlation) / nperm
- # Return average p-value and empirical correlation coefficient
- return list([empirical_correlation, (p_perm_xy + p_perm_yx) / 2])
- # This function conducts diffusion map embedding (DME), using the Brain Space library, for each participant for two
- # modalities (structural connectivity measured by communicability, and functional connectivity measured by resting-
- # state functional magnetic resonance imaging), in the user-define data set (CALM or NKI).
- def run_individual_diffusion_map_embedding(dataset, modality, parcellation, ncomp, timepoint, subset, return_affinity):
- # Set the modality index for the input modality ('sc' or 'fc')
- if modality == "sc":
- modality_idx = 0
- formatted_modality_name = "structural"
- else:
- modality_idx = 1
- formatted_modality_name = "functional"
- # Load the group-level diffusion-map embeddings for this data set.
- group_level_dme = loadmat(os.getcwd() + '/data/calm.nki.group.gradients.mat')[dataset]
- # Extract the correct modality, If working with CALM, load the appropriate subset first
- if dataset == 'calm':
- group_level_dme = group_level_dme[subset].item()[modality_idx, :, :]
- else:
- group_level_dme = group_level_dme[modality_idx, :, :]
- # Load the individual-level thresholded connectomes for this data set and modality
- filename = os.getcwd() + '/data/' + dataset + '/connectomes/thresholded_structural_and_functional_connectomes.mat'
- individual_connectomes = mat73.loadmat(filename)['thresholded'][modality]
- # If we're processing CALM, ensure we select the harmonised individual-level connectomes. Further, at baseline only,
- # select the correct subset (referred or non-referred).
- if dataset == 'calm':
- individual_connectomes = individual_connectomes['harmonised']
- if dataset == 'calm' and subset == 'non-referred':
- # Needs to be slightly differently formatted to index into the group gradient structure
- subset = 'nonreferred'
- if dataset == 'calm' and timepoint == 'baseline':
- participant_list = individual_connectomes[timepoint][subset]['sub']
- print('For the {} subset of CALM...'.format(subset))
- else:
- participant_list = individual_connectomes[timepoint]['sub']
- print('{} participants have {} connectomes for the {} time point of {}.'.
- format(len(participant_list), formatted_modality_name, timepoint, dataset))
- # Initialise output arrays for the eigenvectors and variance explained for the parcellation inputted (
- # 'schaefer100x7', 'schaefer200x7', or 'brainnetome246') and components (ncomp)
- if dataset == 'calm' and timepoint == 'baseline' and subset == 'referred':
- nroi = individual_connectomes[timepoint][subset][parcellation]['individual'].shape[1]
- elif dataset == 'calm' and subset == 'nonreferred':
- nroi = individual_connectomes['baseline']['nonreferred']['schaefer200x7']['individual'].shape[1]
- else:
- nroi = individual_connectomes[timepoint][parcellation]['individual'].shape[1]
- individual_eigenvectors = np.zeros([nroi, ncomp, len(participant_list)])
- variance_explained = np.zeros([len(participant_list), 2, ncomp])
- affinity_array = np.zeros([len(participant_list), 2, int(nroi / 2), int(nroi / 2)])
- print('About to start looping across participants...')
- # Note that we specify two hemispheres when collecting the eigen-values because we rotate the eigen vectors to
- # ensure that both hemispheres are aligned, but cannot do this for the eigen values (which are scalar and direction-
- # invariant anyway). Loop across participants...
- for participant_idx, participant_id in enumerate(participant_list):
- # Extract connectome for this participant, modality, time point, and data set. If we're extracting structural
- # connectomes from CALM, then we must select the first index (not noughth) of the fourth dimension, as these
- # are the communicability matrices! Further, select the correct subset for CALM (referred vs non-referred)
- if dataset == "calm" and timepoint == 'baseline' and modality == "sc" and subset == 'referred':
- participant_connectome = \
- individual_connectomes[timepoint][subset][parcellation]['individual'][participant_idx, :, :]
- elif dataset == "calm" and subset == "nonreferred" and modality == "sc":
- participant_connectome = \
- individual_connectomes[subset][parcellation]['individual'][participant_idx, :, :]
- elif dataset == 'calm' and timepoint == 'followup' and modality == 'sc':
- participant_connectome = \
- individual_connectomes[timepoint][parcellation]['individual'][participant_idx, :, :]
- elif dataset == "calm" and timepoint == 'baseline' and modality == "fc":
- participant_connectome = \
- individual_connectomes[timepoint][subset][parcellation]['individual'][participant_idx, :, :]
- elif dataset == "nki" and modality == "sc":
- participant_connectome = individual_connectomes[timepoint][parcellation]['individual'][participant_idx, :,
- :, 1]
- else:
- participant_connectome = \
- individual_connectomes[timepoint][parcellation]['individual'][participant_idx, :, :]
- # Initialise output array for rotated eigenvectors
- rotated_eigenvectors = np.zeros([nroi, ncomp])
- for hemi_id in range(0, 2):
- if hemi_id == 0:
- nroi_range = range(0, int(nroi / 2))
- else:
- nroi_range = range(int(nroi / 2), nroi)
- # Construct the affinity matrix using a normalised angle kernel (in line with Park et al., 2021, eLife)
- affinity = compute_affinity(participant_connectome[np.ix_(nroi_range, nroi_range)],
- kernel='normalized_angle', sparsity=None)
- # Append the affinity to the output array
- affinity_array[participant_idx, hemi_id, :, :] = affinity
- # Now apply DME (using default parameters) and assign outputs to relevant arrays
- individual_eigenvectors[nroi_range, :, participant_idx], individual_eigenvalues = \
- diffusion_mapping(affinity, n_components=ncomp, random_state=None)
- # Calculate the variance explained by each component and assign to output
- variance_explained[participant_idx, hemi_id, :] = \
- [i / individual_eigenvalues.sum() for i in individual_eigenvalues]
- # Align the individual's hemispheric eigen-vectors to the corresponding group-level hemisphere DME.
- rotated_eigenvectors[nroi_range, :] = procrustes(individual_eigenvectors[nroi_range, :, participant_idx],
- group_level_dme[nroi_range, :])
- # After processing both hemispheres, check that the rotation and DME has worked!
- if np.isnan(rotated_eigenvectors).any():
- print("{} {} connectivity DME failed, for {} {}.".format(
- participant_id[0], formatted_modality_name, timepoint, dataset))
- # If there is no warning, then assign the rotated eigenvectors to the group output array
- individual_eigenvectors[:, :, participant_idx] = rotated_eigenvectors
- print("{} {} connectivity DME complete, for {} {}.".format(
- participant_id[0], formatted_modality_name, timepoint, dataset))
- # After looping through all participants, return the eigen-vectors, variance explained, and participant lists.
- # Return the affinity matrices too if requested.
- if return_affinity:
- return individual_eigenvectors, variance_explained, participant_list, affinity_array
- else:
- return individual_eigenvectors, variance_explained, participant_list
- # This function implements Steiger's (1980) z-test for dependent correlations (Steiger, 1980, Tests for comparing
- # elements of a correlation matrix. Psychological Bulletin, 87(2), 245-251, https://doi.org/10.1037/0033-2909.87.2.245).
- # This is based on a script developed by Philipp Singer:
- # https://github.com/psinger/CorrelationStats/blob/master/corrstats.py
- def steiger(xy, xz, yz, n, twotailed):
- """
- INPUTS:
- xy: correlation between X and Y
- xz: correlation between X and Z
- yz: correlation between Y and Z
- n: number of observations used to compute correlations
- OUTPUTS:
- t = t-statistic assessing equality of correlation coefficients.
- p = p-value from one or two-tailed test
- """
- d = xy - xz
- determin = 1 - xy * xy - xz * xz - yz * yz + 2 * xy * xz * yz
- av = (xy + xz) / 2
- cube = (1 - yz) * (1 - yz) * (1 - yz)
- t2 = d * np.sqrt((n - 1) * (1 + yz) / ((2 * (n - 1) / (n - 3)) * determin + av * av * cube))
- p = 1 - t.cdf(abs(t2), n - 3)
- if twotailed is True:
- p *= 2
- return t2, p
- # PART 3 - Deriving Group Gradients! #
- """
- OPEN-ACCESS NOTE: Since both CALM and NKI are managed-access, we cannot provide thresholded connectomes. Therefore, the
- following section's code is provided for transparency only. Further, variations in DME parameters are coded in case
- reviewers ask to see the effect of DME parameters or further sensitivity analyses.
- """
- # The function run_group_dimensionality_reduction takes the following arguments:
- # * dataset = calm or nki
- datasets = ['nki', 'calm']
- # * modality = sc or fc. sc denotes structural connectivity, comprised of streamline counts from probabilistic
- # tractography, thresholded to retain the strongest 10% connections in each row, then transformed into weighted
- # communicability matrices. To derive group-representative structural connectomes, we used Betzel's (2019) distance-
- # dependent consensus thresholding, for each data set. fc denotes functional connectivity, namely pair-wise
- # z-transformed pearson time-series correlations, with the top 10% connections in each row retained.
- # Group-representative fc are simply individual-level functional connectomes averaged across participants.
- modalities = ['sc', 'fc']
- # * parcellation = We focus our analysis on the Schaefer 200-node 7-network parcellation, in line with prior work
- # (Park et al., 2021). For sensitivity, we derive group gradients in a structural parcellation of equivalent spatial
- # resolution (Brainnetome 246-node), and a coarser functional parcellation (Schaefer 200-node 7-network).
- parcellations = ['schaefer100x7', 'schaefer200x7', 'brainnetome246']
- # * ncomp = Number of components to extract. We use the default 10.
- # * user_kernel = We assess differences in kernels used to construct the affinity matrix based on recent evidence
- # (Watson and Andrews, 2023) that different kernels, particularly cosine, normalized angle, and correlation-based
- # kernels, can produce qualitatively different components.
- kernels = ['pearson', 'spearman', 'cosine', 'gaussian', 'normalized_angle']
- # * user_alpha = Anisotropic diffusion for diffusion-map embedding (DME).
- alpha_vector = [0, 0.25, 0.5, 0.75, 1]
- # * user_t = Diffusion time for DME.
- t_vector = [0, 1, 2, 3]
- # * embedding_approach = We consider 3 embedding approaches, namely diffusion-map embedding ('dm'), laplacian eigen-maps
- # ('le'), and principal components analysis ('pca').
- embedding_approaches = ['dm', 'le', 'pca']
- # Using default DME parameters, we'll derive 3 sets of group-level gradients: NKI, referred CALM, and non-referred CALM.
- all_subsets = ['nki', 'calm referred', 'calm nonreferred']
- default_dme_eigenvectors = np.zeros([len(all_subsets), len(modalities), 200, 3])
- for subset_idx, dataset_and_subset in enumerate(all_subsets):
- # If dataset_and_subset contains the string 'calm', split into two and extract the subset name.
- if 'calm' in dataset_and_subset.split():
- dataset, subset = dataset_and_subset.split()
- else:
- dataset = dataset_and_subset.split()[0]
- subset = []
- # Now loop across modalities
- for modality_idx, modality in enumerate(modalities):
- default_dme_eigenvectors[subset_idx, modality_idx, :, :] = \
- run_group_dimensionality_reduction(dataset, subset=subset, modality=modality, parcellation='schaefer200x7',
- ncomp=3, user_kernel='normalized_angle', user_alpha=0.5, user_t=0,
- embedding_approach='dm')[0]
- # Save the group gradients as a MATLAB file for easier importing into R for visualisation.
- group_gradients = {"nki": default_dme_eigenvectors[0, :, :, :],
- "calm": {"referred": default_dme_eigenvectors[1, :, :, :],
- "non-referred": default_dme_eigenvectors[2, :, :, :]}}
- scipy.io.savemat("data/calm.nki.group.gradients.mat", group_gradients)
- # PART 4 - Comparing Group-Level CALM and NKI Gradients #
- # Load the labels for the schaefer 200-node 7-network parcellation
- schaefer200x7_metadata = scipy.io.loadmat('data/schaefer200x7_1mm_info.mat', simplify_cells=True)
- schaefer200x7_labels = schaefer200x7_metadata['schaefer200x7_1mm_info']['name']
- # Load the group-level gradients, and conduct a spearman-rank correlation for corresponding CALM and NKI gradients.
- group_gradients = scipy.io.loadmat('data/calm.nki.group.gradients.mat')
- # Note, since NKI functional gradient 1 and CALM functional gradient 1 are strongly inversely correlated, we will
- # invert the CALM gradient for consistency. This is because the direction of the eigenvectors is arbitrary.
- group_gradients['calm']['referred'].item()[1, :, 0] = group_gradients['calm']['referred'].item()[1, :, 0] * -1
- # We also need to flip the left hemisphere of the first two structural components for CALM (i.e. reversing direction)
- # so that they're aligned with NKI. Both of these modifications don't make a difference for manifold eccentricity, as
- # this is calculated with respect to the manifold origin.
- group_gradients['calm']['referred'].item()[0, 0:100, 0] = group_gradients['calm']['referred'].item()[0, 0:100, 0] * -1
- group_gradients['calm']['referred'].item()[0, 0:100, 1] = group_gradients['calm']['referred'].item()[0, 0:100, 1] * -1
- # Do the same for the non-referred subset...
- group_gradients['calm']['non-referred'].item()[1, :, 0] = group_gradients['calm']['non-referred'].item()[1, :, 0] * -1
- group_gradients['calm']['non-referred'].item()[0, 0:100, 0] = group_gradients['calm']['non-referred'].item()[0, 0:100,
- 0] * -1
- group_gradients['calm']['non-referred'].item()[0, 0:100, 1] = group_gradients['calm']['non-referred'].item()[0, 0:100,
- 1] * -1
- # And save the updated version
- group_gradients = {'nki': group_gradients['nki'], 'calm':
- {'referred': group_gradients['calm']['referred'].item(),
- 'non-referred': group_gradients['calm']['non-referred'].item()}}
- scipy.io.savemat('data/calm.nki.group.gradients.mat', group_gradients)
- # Now loop through each modality and component, and calculate correspondence between the referred CALM subset and NKI.
- for modality_idx, modality in enumerate(modalities):
- for comp in range(0, 3):
- calm_gradient = group_gradients['calm']['referred'][modality_idx, :, comp]
- nki_gradient = group_gradients['nki'][modality_idx, :, comp]
- # For each data set, report which regions are anchoring the gradient
- calm_gradient_sorted = np.argsort(calm_gradient)
- print("Gradient {} of {} in CALM is anchored at one end by {}, and at the other end by {}.".
- format(comp + 1, modality, ','.join(schaefer200x7_labels[calm_gradient_sorted[0:4]]),
- ','.join(schaefer200x7_labels[calm_gradient_sorted[-4:]])))
- nki_gradient_sorted = np.argsort(nki_gradient)
- print("Gradient {} of {} in NKI is anchored at one end by {}, and at the other end by {}.".
- format(comp + 1, modality, ','.join(schaefer200x7_labels[nki_gradient_sorted[0:4]]),
- ','.join(schaefer200x7_labels[nki_gradient_sorted[-4:]])))
- rho, pval = perm_sphere(calm_gradient, nki_gradient, corr_type='spearman')
- # Note that the absolute value of the correlation is considered - the sign of eigenvectors is arbitrary
- print("Spearman-rank correlation of {:}, with p-value of {:}, for {:} gradient {:} between CALM and NKI.".
- format(round(rho, 3), round(pval, 3), modality, comp + 1))
- # Find the regions with the smallest and largest absolute dissimilarity in eigenvectors
- diff = abs(calm_gradient - nki_gradient)
- most_similar_regions = schaefer200x7_labels[np.argsort(diff)[0:5:]]
- print("Regions with the largest similarity between CALM and NKI included {}.".format(
- ', '.join(most_similar_regions)))
- most_dissimilar_regions = schaefer200x7_labels[np.argsort(diff)[-5:]]
- print("Regions with the largest dissimilarity between CALM and NKI included {}.".format(
- ', '.join(most_dissimilar_regions)))
- # PART 5 - Testing equality of group-level gradients between referred and non-referred CALM samples and NKI
- for modality_idx in range(len(modalities)):
- for comp in range(3):
- calm_referred_gradient = group_gradients['calm']['referred'][modality_idx, :, comp]
- calm_nonreferred_gradient = group_gradients['calm']['non-referred'][modality_idx, :, comp]
- nki_gradient = group_gradients['nki'][modality_idx, :, comp]
- # Extract correlation coefficient for relationship between NKI and referred CALM
- xy = perm_sphere(nki_gradient, calm_referred_gradient, 'spearman')[0]
- print('Correlation between NKI and referred CALM for {} component {}: r = {}'.
- format(modalities[modality_idx], comp + 1, round(xy, 3)))
- # Correlation coefficient for relationship between NKI and non-referred CALM
- xz = perm_sphere(nki_gradient, calm_nonreferred_gradient, 'spearman')[0]
- print('Correlation between NKI and non-referred CALM for {} component {}: r = {}'.
- format(modalities[modality_idx], comp + 1, round(xz, 3)))
- # Correlation between referred and non-referred CALM
- yz = perm_sphere(calm_referred_gradient, calm_nonreferred_gradient, 'spearman')[0]
- print('Correlation between referred and non-referred CALM for {} component {}: r = {}'.
- format(modalities[modality_idx], comp + 1, round(yz, 3)))
- # Steieger's test (Steiger, 1980) to assess whether non-referred CALM are more aligned to NKI than referred CALM
- # is. n is the number of nodes. A negative Z-score indicates that the non-referred group is more similar to NKI
- # than the referred group is.
- stat, p = steiger(xy, xz, yz, n=200, twotailed=False)
- print('Referred CALM and NKI correlation vs non-referred CALM and NKI correlation for {} gradient,'
- ' component {}: z = {}, p = {}'.format(modalities[modality_idx], comp + 1, round(stat, 2), round(p, 3)))
- # PART 6 - Deriving Individual Gradients and Calculating Manifold Eccentricity #
- parcellation = 'schaefer200x7'
- # Update datasets so that we can calculate manifold eccentricity for the non-referred subset of CALM too.
- datasets = ['nki', 'calm referred', 'calm non-referred']
- # We shall calculate manifold eccentricity for NKI and the referred CALM subset.
- for dataset_idx, dataset in enumerate(datasets):
- # Specify time points for each data set, and extract the group gradient. Specify the relevant sub sets, leaving a
- # blank subset variable for NKI.
- if dataset == "calm referred":
- dataset_only = "calm"
- timepoints = ["baseline", "followup"]
- subset = 'referred'
- dataset_group_gradient = group_gradients[dataset_only][subset].item()
- elif dataset == "calm non-referred":
- timepoints = ['baseline']
- dataset_only = "calm"
- subset = "non-referred"
- dataset_group_gradient = group_gradients[dataset_only][subset].item()
- else:
- timepoints = ["bas1", "flu1", "flu2"]
- dataset_group_gradient = group_gradients[dataset]
- subset = []
- dataset_only = "nki"
- # Loop across time points
- for timepoint_idx, timepoint in enumerate(timepoints):
- mdic_list = []
- # Specify the file name to which we'll save the DME outputs
- if subset:
- save_filename = 'data/' + dataset_only + '/dme/' + subset + '_' + parcellation + '_' + timepoint + '.mat'
- else:
- save_filename = 'data/' + dataset + '/dme/' + parcellation + '_' + timepoint + '.mat'
- # Now loop across modalities
- for modality_idx, modality in enumerate(modalities):
- # Format the modality name nicely for saving
- if modality == "sc":
- formatted_modality_name = "structural"
- else:
- formatted_modality_name = "functional"
- # Calculate the group-manifold origin
- group_manifold_origin = np.mean(dataset_group_gradient[modality_idx, :, :], axis=0)
- # Conduct DME for each participant. For CALM, we use the referred subset. Entering this for NKI will not
- # affect results.
- individual_eigenvectors, variance_explained, participants, affinity = \
- run_individual_diffusion_map_embedding(
- dataset=dataset_only, modality=modality, parcellation=parcellation, ncomp=3, timepoint=timepoint,
- subset=subset, return_affinity=True)
- # For each participant's node, calculate the euclidean distance with the group manifold origin i.e. the
- # manifold eccentricity
- nroi = individual_eigenvectors.shape[0]
- nsub = individual_eigenvectors.shape[2]
- manifold_eccentricity = np.zeros([nsub, nroi])
- for sub_idx in range(0, nsub):
- for roi in range(0, nroi):
- manifold_eccentricity[sub_idx, roi] = np.linalg.norm(
- group_manifold_origin - individual_eigenvectors[roi, :, sub_idx])
- print("Individual-level {} DME and eccentricities complete for {} {}.".format(modality, timepoint, dataset))
- # After processing all eigenvectors for this modality and time point, create a dictionary
- mdic_modality = {formatted_modality_name + '_eigenvectors': individual_eigenvectors,
- formatted_modality_name + '_manifold_eccentricity': manifold_eccentricity,
- formatted_modality_name + '_sub_list': sum(participants, []),
- formatted_modality_name + '_variance_explained': variance_explained,
- formatted_modality_name + '_affinity': affinity}
- # Assign this dictionary to the list and delete other variables
- mdic_list.append(mdic_modality)
- print("Appended output to list.")
- del individual_eigenvectors, manifold_eccentricity, mdic_modality, variance_explained, affinity
- # After processing both modalities, concatenate the two dictionaries, and save as a MATLAB file
- savemat(save_filename, mdict={**mdic_list[0], **mdic_list[1]})
deriving_group_and_individual_gradients_v2.py at commit 4d4ab95, under CC-BY-4.0 · at the source
Overview
- MRC Cognition and Brain Sciences Unit, University of Cambridge, Cambridge, United Kingdom
- The Alan Turing Institute, London, United Kingdom
- Department of Psychology, University of Cambridge, Cambridge, United Kingdom
- Department of Electrical and Electronic Engineering, Imperial College London, London, United Kingdom
- Oxford Centre for Integrative Neuroimaging (OxCIN), FMRIB, Nuffield Department of Clinical Neurosciences, University of Oxford, Oxford, United Kingdom
- Centre National de la Recherche Scientifique (CNRS), UAR 3129, Paris, France
- Department of Psychiatry, University of Cambridge, Cambridge, United Kingdom
Abstract
Organisational gradients refer to a continuous low-dimensional embedding of brain regions and can quantify core organisational principles of complex systems like the human brain. Mapping how these organisational principles are altered or refined across development and phenotypes is essential to understanding the relationship between brain and behaviour. Taking a developmental approach and leveraging longitudinal and cross-sectional data from two multi-modal neuroimaging datasets, spanning the full neurotypical-neurodiverg
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 40 matches between paragraphs and lines of code.
alicjamonaghan/neurodevelopmental_gradients
4d4ab951fcc0c22bb4a0c42b7a0d424e8f6cf448, 23 April 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
30 files
- code/
Figure_1_open.access.R , R, 320 lines - code/
GAMM.functions.v3.R , R, 865 lines, 3 matches - code/
NKI_and_CALM_cognitive_b , Python, 107 lines, 2 matchesehavioural_V3.py - code/
communicability.m , MATLAB, 12 lines - code/
corrstats.py , Python, 112 lines - code/
deriving_group_and_indiv , Python, 529 lines, 6 matchesidual_gradients_v2.py - code/
developmental_effects_on , R, 521 lines, 3 matches_structure_function_rela tionships.R - code/
dme_and_metadata.R , R, 285 lines - code/
dominance.m , MATLAB, 47 lines - code/
eLife_revisions_plots.R , R, 259 lines, 2 matches - code/
eccentricity_graph_theor , MATLAB, 111 lines, 1 matchy.m - code/
gamm_coupling_crossvalid , R, 172 lines, 2 matchesation.R - code/
gradient_developmental_s , Python, 554 lines, 4 matchesensitivity.py - code/
neurotypical.coupling.de , R, 37 lines, 1 matchvelopment.R - code/
nkir_calm_descriptives_v , R, 628 lines, 2 matches2.R - code/
perm.sphere.p.R , R, 52 lines - code/
psychopathology_cognitio , R, 204 lines, 3 matchesn_dimensions_structure_f unction.R - code/
structural_and_functiona , R, 214 linesl_gamms.R - code/
structure_function_coupl , Python, 358 lines, 3 matchesing_and_psychopathology. py - code/
structure_function_coupl , Python, 235 lines, 2 matchesing_sensitivity.py - connectome_cleaning_cons
truction/ , MATLAB, 145 lines, 1 matchcalm_harmonisation_effec ts.m - connectome_cleaning_cons
truction/ , Python, 85 lines, 2 matchesclean_and_parcellate_fmr i_calm.py - connectome_cleaning_cons
truction/ , Python, 81 lines, 2 matchesclean_and_parcellate_fmr i_nki.py - connectome_cleaning_cons
truction/ , MATLAB, 705 linesconnectome_construction_ selection_thresholding_c alm_v3_da2.m - connectome_cleaning_cons
truction/ , MATLAB, 423 lines, 1 matchconnectome_construction_ selection_thresholding_n ki.m - connectome_cleaning_cons
truction/ , MATLAB, 49 linesextracting_unthresholded _baseline_connectomes_nk i.m - connectome_cleaning_cons
truction/ , MATLAB, 320 linespull_baseline_calm_qsipr ep_probabilistic.m - connectome_cleaning_cons
truction/ , MATLAB, 277 linespull_cleaned_functional_ connectomes.m - connectome_cleaning_cons
truction/ , MATLAB, 275 linespull_longitudinal_calm_q siprep_probabilistic.m - README.md, Text, 77 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 29 scripts, each with its path and the digest of its content;
- 40 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Code/data availability
Detailed documentation about how to implement these analyses is available here (https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Data availability
Detailed documentation about how to implement these analyses, including de-identified derivatives from diffusion-map embedding, are available at: 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 1, 28 September 2026: the first record
Recorded: type, language, journal, volume, pages, dates, 6 authors, 1 keyword, 19 MeSH terms, 10 funders, 97 references.
Cite
This paper
Monaghan, A., Bethlehem, R. A., Akarca, D., Margulies, D. S., the CALM Team, & Astle, D. E. (2026). Canonical neurodevelopmental trajectories of structural and functional manifolds. eLife, 14, RP103097. https://
BibTeX
@article{monaghan2026can
author = {Monaghan, Alicja and Bethlehem, Richard AI and Akarca, Danyal and Margulies, Daniel S and {the CALM Team} and Astle, Duncan E},
title = {{Canonical neurodevelopmental trajectories of structural and functional manifolds}},
journal = {eLife},
year = {2026},
month = may,
volume = {14},
pages = {RP103097},
publisher = {eLife Sciences Publications, Ltd},
issn = {2050-084X},
doi = {10.7554/
url = {https://
pmid = {42089485},
pmcid = {PMC13148822}
}
RIS
TY - JOUR
AU - Monaghan, Alicja
AU - Bethlehem, Richard AI
AU - Akarca, Danyal
AU - Margulies, Daniel S
AU - the CALM Team
AU - Astle, Duncan E
TI - Canonical neurodevelopmental trajectories of structural and functional manifolds
T2 - eLife
J2 - Elife
PY - 2026
DA - 2026/
VL - 14
SP - RP103097
SN - 2050-084X
PB - eLife Sciences Publications, Ltd
DO - 10.7554/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.7554/
"type": "article-journal",
"title": "Canonical neurodevelopmental trajectories of structural and functional manifolds",
"container-title": "eLife",
"author": [
{
"family": "Monaghan",
"given": "Alicja"
},
{
"family": "Bethlehem",
"given": "Richard AI"
},
{
"family": "Akarca",
"given": "Danyal"
},
{
"family": "Margulies",
"given": "Daniel S"
},
{
"literal": "the CALM Team"
},
{
"family": "Astle",
"given": "Duncan E"
}
],
"container-title-short":
"volume": "14",
"page": "RP103097",
"DOI": "10.7554/
"PMID": "42089485",
"PMCID": "PMC13148822",
"ISSN": "2050-084X",
"publisher": "eLife Sciences Publications, Ltd",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
6
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1371/journal.pbio.3003684 [code]
- The retrieval of previously learned motor memories is facilitated by the reinstatement of default mode network manifold structures.Journal: PLoS biologyIn common: neuromaps, BrainSpace, Brain Connectivity Toolbox, 7 other tools, 18 references
- [2] doi:10.1038/s41467-026-71270-w [code]
- Spatiotemporal dynamics of the human cortical functional hierarchy across the lifespan.Journal: Nature communicationsIn common: BrainSpace, Nilearn, h5py, 7 other tools, developmental, 16 references
- [3] doi:10.1038/s41467-026-71719-y [code]
- Brain functional-structural gradient coupling reflects development, behavior and genetic influences.Journal: Nature communicationsIn common: BrainSpace, Nilearn, h5py, 8 other tools, developmental, 14 references
- [4] doi:10.1038/s41467-026-73072-6 [code]
- Mapping the spatiotemporal continuum of structural connectivity development across the human connectome in youth.Journal: Nature communicationsIn common: rpy2, mgcv, reshape2, 6 other tools, developmental, structural MRI / diffusion, 15 references
- [5] doi:10.1126/sciadv.aef2894 [code]
- Human cortical networks trade communication efficiency for computational reliability.Journal: Science advancesIn common: netneurotools, SciPy, NumPy, 11 references, 2 authors
- [6] doi:10.1038/s42003-025-09444-3 [code]
- Decoupling of neurophysiological activity from structure mirrors global microarchitectural and neuromodulatory trends.Journal: Communications biologyIn common: netneurotools, neuromaps, Brain Connectivity Toolbox, 7 other tools, 13 references
- [7] doi:10.1038/s41467-026-76011-7 [code]
- Human cortex organizes dynamic co-fluctuations along the sensorimotor-association
axis. Journal: Nature communicationsIn common: ggseg, BrainSpace, mgcv, 7 other tools, 12 references - [8] doi:10.1016/j.nicl.2026.104012 [code]
- Structural-functional multilayer brain network properties and outcome of combined repetitive transcranial magnetic stimulation and psychotherapy for obsessive-compulsive disorder.Journal: NeuroImage. ClinicalIn common: Brain Connectivity Toolbox, Pingouin, reshape2, 10 other tools, structural MRI / diffusion, 10 references
- [9] doi:10.1038/s41467-026-74466-2 [code]
- Neuromorphic hierarchical modular reservoirs.Journal: Nature communicationsIn common: netneurotools, neuromaps, Brain Connectivity Toolbox, 8 other tools, 8 references
- [10] doi:10.1038/s42003-026-10276-y [code]
- The cellular correlates and adolescent reorganisation of cortical myelination networks in the common marmoset.Journal: Communications biologyIn common: BrainSpace, mgcv, Brain Connectivity Toolbox, 9 other tools, structural MRI / diffusion, 4 references, author Richard Bethlehem
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: 1 repository of the authors' code, each at its verified commit and with its license, 29 scripts, and 40 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:d01b9c13a9b74125…
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.
