Skip to content

tfraa/msntranscript

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

45 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

msnpip β€” Morphometric Similarity Networks and Transcriptomics Pipeline

License: MIT Status: maintenance

🚧 Under maintenance

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.

πŸ“Œ Thesis snapshot

The exact version used for the MSc thesis is preserved on branch v1-april (tag v1.0-thesis, commit cc8c776). main is 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.

Pipeline Overview


What it does

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 kernel S = 1 / (1 + d / n_metrics), where d is 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 vasa surface-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. Set allow_null_fallback=False to hard-fail instead.
  • No pickle anywhere: outputs are CSV / Parquet / NPZ / JSON / PNG / PDF only.

Installation

# 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.txt

Verify 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).


Quick start

From FreeSurfer data

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 gsea

From a pre-merged DataFrame

msnpip 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 1234

Python API

from 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)

Resume / partial runs

# 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 tiv

Helpers: msnpip list-atlases, msnpip list-genesets.


Input data format

FreeSurfer directory layout

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).

Demographics / merged CSV

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.


Output tree

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

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 1234

The image bakes the neuromaps fsaverage cache so cortical plots and the spin null work offline.


Locked methodological decisions

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.


License

MIT β€” see LICENSE.

About

A pipeline for integrating neuroimaging data with transcriptomic analysis using morphometric similarity networks.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages