This repository is actively being reworked (v2 rebuild in progress). The documentation below describes the intended v2 design; some interfaces, outputs, and instructions may change or break without notice while maintenance is ongoing. Treat it as a preview, not a stable release.
The exact version used for the MSc thesis is preserved on branch
v1-april(tagv1.0-thesis, commitcc8c776).mainis the current, improved v2.
A modular Python pipeline that builds Morphometric Similarity Networks (MSN) from FreeSurfer cortical data, contrasts node strength between groups, and links the regional patterns to gene expression from the Allen Human Brain Atlas via PLS and enrichment (ensemble-GCEA + GSEA). The transcriptomics engine is the Imaging Transcriptomics Toolbox (v2.0.0), pinned to a fixed commit.
LOAD β VALIDATE β MSN β CONTRAST β (CORRELATION) β TRANSCRIPTOMICS β FIGURES β REPORT
- MSN is a whole-cortex network: each region's 5 morphometric features
(
SurfArea, GrayVol, ThickAvg, MeanCurv, GausCurv) are z-scored within subject (robust modified z-score), and inter-regional similarity is the distance kernelS = 1 / (1 + d / n_metrics), wheredis the Euclidean distance between the two regions' standardized feature vectors. Node strength is the sum (default) or mean of a region's similarity edges. Both hemispheres are always used upstream. - Group contrast per region (Ξ² / t / Cohen's d), with covariates of your choosing; site/scanner are always one-hot encoded.
- Transcriptomics runs inside the pinned engine with the
vasasurface-spin null. By default a failed surface spin falls back (autoβ shuffle) with a warning; the resolved null is recorded and flagged on the report cover. Setallow_null_fallback=Falseto hard-fail instead. - No pickle anywhere: outputs are CSV / Parquet / NPZ / JSON / PNG / PDF only.
# Python 3.12 recommended. The engine installs from a pinned git commit, so git is required.
pip install -e . # add [dev] for the test/lint toolchain: pip install -e ".[dev]"
# For a reproducible, known-good dependency set (the versions the suite is verified against):
pip install -e ".[dev]" -c constraints.txtVerify the engine is wired up:
import imaging_transcriptomics as imt
assert any(a.id == "dk" for a in imt.list_atlases())The first run that needs cortical surfaces will fetch the neuromaps fsaverage meshes; in Docker these are baked at build time (see below).
msnpip full \
--input /path/to/freesurfer_subjects/ \
--demographics demographics.csv \
--output out/ \
--group-col group --case FTD --control HC \
--predictors age sex tiv \
--atlas dk --hemisphere left --regions cort \
--method pls --ncomp 1 --n-perm 10000 \
--enrichment ensemble gseamsnpip full \
--dataframe merged.csv \
--output out/ \
--group-col group --case FTD --control HC \
--predictors age sex tiv --exclude-covariate age \
--correlate-with age --corr-scope global \
--atlas dk --method pls --ncomp 1 --n-perm 1000 --enrichment ensemble --seed 1234from pathlib import Path
from msnpip.config import IOConfig, GLMConfig, EngineConfig, PipelineConfig
from msnpip.pipeline import run_pipeline
cfg = PipelineConfig(
io=IOConfig(dataframe=Path("merged.csv")),
output=Path("out/"),
group_col="group", case="FTD", control="HC",
glm=GLMConfig(predictors=("age", "sex", "tiv")),
engine=EngineConfig(methods=("pls", "corr"), n_components=1, n_permutations=10000),
)
run_pipeline(cfg)# Run only part of the pipeline:
msnpip full ... --stop-stage MSN
msnpip full ... --start-stage TRANSCRIPTOMICS # reuses persisted earlier stages
# Resume from a previous run's persisted strength maps:
msnpip from-strength --output out/ --case FTD --control HC --predictors age sex tivHelpers: msnpip list-atlases, msnpip list-genesets.
freesurfer_subjects/
βββ sub-001/stats/{lh,rh}.aparc.stats
βββ sub-002/stats/{lh,rh}.aparc.stats
βββ ...
Extracted metrics: SurfArea, GrayVol, ThickAvg, MeanCurv, GausCurv for the DesikanβKilliany
cortical regions (34 per hemisphere).
Roles are auto-detected by token matching (so subject_id is found, but region columns
like lh_middletemporal_* are never mistaken for an id):
| Role | Example column names |
|---|---|
| id | subject_id, participant_id, id |
| group | group, diagnosis, dx |
| age | age |
| sex | sex, gender |
| tiv | tiv, icv |
| site | site, scanner |
IDs are matched exactly after whitespace stripping β sub-001 and sub-1 are distinct.
Feature columns follow {hemisphere}_{region}_{metric}, e.g. lh_superiorfrontal_ThickAvg.
A curated, flat set β CSVs, a plots/ folder, and one report.pdf (<tag> is
<case>_vs_<ctrl>). The verbose engine bundle is staged to a temporary .engine/
folder, curated into these files, then deleted β no manifest.json, no pickle.
out/
merged_dataset.csv validated, merged input table
strength_maps.csv per-subject node strength per region
mean_msn_per_group.csv group-mean node strength per region
case_control_difference_maps.csv per-contrast regional contrast map
<tag>_region_stats.csv per-region beta/t/cohen_d/p/fdr
<tag>_pls.csv <tag>_pls_summary.csv PLS gene results + component variance
<tag>_corr.csv correlation gene results (only if --method corr)
<tag>_enrichment.csv enrichment terms per backend Γ gene set
plots/ violin, t-value bars, surfaces, matrices, enrichment
report.pdf assembled A4-portrait report
See docs/outputs.md for a column-by-column reference and docs/tutorial.md for a runnable first run on synthetic data.
docker build -f docker/Dockerfile -t msnpip:2.0 .
docker run --rm -v "$PWD/data:/data:ro" -v "$PWD/out:/out" msnpip:2.0 \
full --dataframe /data/merged.csv --output /out \
--group-col group --case FTD --control HC \
--predictors age sex tiv --method pls --ncomp 1 \
--n-perm 1000 --enrichment ensemble --seed 1234The image bakes the neuromaps fsaverage cache so cortical plots and the spin null work offline.
| Item | Value |
|---|---|
| Null model | vasa surface spin; fallback-with-warning by default (allow_null_fallback=False to hard-fail) |
| MSN | 5 features, within-subject robust z-score, distance kernel 1/(1+d/n), sum strength, both hemispheres |
| Contrast statistic | beta (default), t, or cohen_d |
| Enrichment | ensemble primary + gsea secondary |
| ID matching | exact after whitespace strip |
| Persistence | no pickle β CSV/Parquet/NPZ/JSON only |
| Site covariate | always one-hot |
| Defaults | atlas dk, engine hemisphere left, regions cort, n-perm 10,000 |
New here? Start with docs/tutorial.md (a runnable first run) and docs/outputs.md (what each output file means). See docs/statistics.md and docs/engine_contract.md for methods, and docs/adding_an_atlas.md to extend beyond DK.
MIT β see LICENSE.
