Skip to content

IPS-Stuttgart/NeuRepTrace

Repository files navigation

NeuRepTrace

Documentation

Probabilistic tracing of neural representations over time.

NeuRepTrace is an early-stage Python toolkit for benchmarking calibrated, time-resolved decoders on M/EEG data. The initial goal is to turn classifier outputs from non-invasive neural recordings into probability traces that are useful for studying representational dynamics, planning, and replay-like sequences.

Features

NeuRepTrace currently provides tools for:

  • time-resolved decoding from MNE Epochs files;
  • config-driven dataset loading from MNE Epochs files and FieldTrip-like MATLAB .mat files;
  • held-out trial/time probability observation exports for downstream state models;
  • onset-detection summaries from probability traces, with baseline-window thresholds, false-alarm rates, and detection latencies;
  • stream-level stimulus event detection for long probability traces with zero, one, or many stimulus occurrences;
  • continuous stimulus-scanning workflows that train an event-locked decoder on one raw run, scan a held-out raw stream, export P(class | time), and score detected events against held-out annotations;
  • conservative sticky switching models for probability traces with shuffled time, shuffled label, and baseline-window controls;
  • category-conditioned semantic stage summaries for asking whether decoded representations unfold in stable temporal stages;
  • calibrated-versus-uncalibrated emission comparisons for state-inference analyses;
  • calibrated classification metrics, including Brier score and expected calibration error;
  • calibration-aware reports and reliability-bin diagnostics;
  • standard decoder baselines, including logistic regression, LDA, and calibrated linear SVM;
  • grouped cross-validation for session- or run-aware benchmarks; and
  • CSV aggregation, plotting, reporting, and subject-level inference for downstream interpretation.

Dataset configuration and PyMEGDec migration

NeuRepTrace owns the dataset-independent M/EEG decoding layer. Keep reusable feature-matrix decoding, classifier calibration, temporal generalization, onset/state inference, confusion and per-class metrics, MNE Epochs decoding, and generic summary-table/reporting helpers here.

Dataset-specific projects should adapt their own file formats and experimental conventions into NeuRepTrace's feature-matrix, MNE Epochs, and probability-observation interfaces. Generic FieldTrip-style MATLAB loading is available in neureptrace.io.fieldtrip_mat; dataset-specific filename templates such as Part{participant}Data.mat and Part{participant}CueData.mat should be supplied by config files or thin project wrappers rather than hard-coded in NeuRepTrace. PyMEGDec-style paper-specific alpha analyses, stimulus defaults, and export scripts remain outside the core package unless they are generalized into reusable workflows.

Dataset-specific file naming and metadata conventions can also be expressed as versioned YAML or JSON dataset specs. Specs describe data roots, participant selection, split path templates, metadata files, labels, and workflow defaults; loader code remains normal Python. This makes the PyMEGDec Part*Data.mat and Part*CueData.mat conventions portable while PyMEGDec remains a compatibility wrapper for paper-specific alpha, CTF geometry, and legacy export scripts.

Config-driven dataset specs

Dataset specs can be validated and expanded from the grouped CLI:

neureptrace dataset validate examples/configs/pymegdec_bushmeg.yml
neureptrace dataset manifest examples/configs/pymegdec_bushmeg.yml \
  --workflow stimulus_transfer \
  --out results/bushmeg_stimulus_manifest.csv

Use YAML for hand-written configs and JSON for generated or CI-controlled configs. See docs/dataset-specs.md for the schema and loader contract.

Installation

NeuRepTrace requires Python 3.11 or newer and earlier than Python 3.15.

For development from a source checkout, use Poetry:

poetry install --with dev

Alternatively, install the package in editable mode with pip:

python -m pip install -e .

Installed environments expose both a grouped neureptrace command and focused workflow commands such as neureptrace-benchmark, neureptrace-mne-time-decode, neureptrace-decode-from-config, neureptrace-validate-dataset-config, neureptrace-onset-detect, neureptrace-continuous-stimulus-scan, neureptrace-stimulus-detect, and neureptrace-temporal-model. The equivalent python -m neureptrace.<module> forms remain available for source-checkout debugging.

Use neureptrace --list-commands to inspect the grouped command inventory, or neureptrace help <command> to open command-specific help without remembering whether a workflow also has a direct console-script entry point.

Quickstart

Run the pilot NOD-EEG benchmark from a manifest:

neureptrace-validate-manifest \
  benchmarks/nod_animate_sub01.csv \
  --report-out results/nod_animate_sub01_validation.csv

neureptrace-benchmark \
  benchmarks/nod_animate_sub01.csv \
  --out-dir results/nod_animate_sub01 \
  --aggregate-out results/nod_animate_sub01_summary.csv \
  --plot-out results/nod_animate_sub01_summary.png \
  --chance 0.5

The grouped CLI provides the same workflows:

neureptrace validate-manifest \
  benchmarks/nod_animate_sub01.csv \
  --report-out results/nod_animate_sub01_validation.csv

neureptrace benchmark \
  benchmarks/nod_animate_sub01.csv \
  --out-dir results/nod_animate_sub01 \
  --aggregate-out results/nod_animate_sub01_summary.csv \
  --plot-out results/nod_animate_sub01_summary.png \
  --chance 0.5

Run time-resolved decoding directly on an MNE epochs file with metadata:

neureptrace-mne-time-decode \
  --epochs path/to/sub-01_epo.fif \
  --metadata-csv path/to/sub-01_events.csv \
  --label-column stim_is_animate \
  --group-column session \
  --out results/nod_sub-01_animate.csv \
  --observations-out results/nod_sub-01_animate_observations.csv

Run the same style of workflow from a dataset config:

neureptrace-validate-dataset-config configs/bush_meg/stimulus_decoding.yml
neureptrace-decode-from-config configs/bush_meg/stimulus_decoding.yml

Plot the resulting time course:

neureptrace-plot-time-decode \
  results/nod_sub-01_animate.csv \
  --chance 0.5 \
  --out results/nod_sub-01_animate.png

Detect the first threshold-crossing representation time from probability observations:

neureptrace-onset-detect \
  results/nod_sub-01_animate_observations.csv \
  --threshold-window -0.35 -0.05 \
  --threshold-quantile 0.95 \
  --threshold-method max_run \
  --min-consecutive 2 \
  --require-stable-prediction \
  --out-events results/nod_sub-01_animate_onset_events.csv \
  --out-summary results/nod_sub-01_animate_onset_summary.csv \
  --out-threshold-summary results/nod_sub-01_animate_threshold_summary.csv

The threshold summary reports baseline false-positive rates separately from post-stimulus threshold-crossing rates.

Detect zero, one, or many stimulus events in a long probability stream:

python -m neureptrace.stimulus_detection \
  results/sub-01_stream_observations.csv \
  --stream-column sequence_id \
  --score-mode class_probability \
  --threshold-window -0.35 -0.05 \
  --threshold-method max_run \
  --threshold-quantile 0.95 \
  --min-consecutive 2 \
  --merge-gap 0.05 \
  --refractory 0.20 \
  --out-events results/stimulus_events.csv \
  --out-summary results/stimulus_event_summary.csv

With annotation matching and latency summaries:

neureptrace-stimulus-detect \
  results/sub-01_stream_observations.csv \
  --annotations results/sub-01_stimulus_annotations.csv \
  --stream-column stream_id \
  --score-mode class_probability \
  --threshold-window -0.35 -0.05 \
  --threshold-method max_run \
  --threshold-quantile 0.95 \
  --detection-window 0.0 inf \
  --min-consecutive 2 \
  --merge-gap 0.05 \
  --refractory 0.20 \
  --match-tolerance 0.10 \
  --out-events results/sub-01_stimulus_events.csv \
  --out-summary results/sub-01_stimulus_event_summary.csv \
  --out-thresholds results/sub-01_stimulus_thresholds.csv

This stream-oriented detector returns one row per detected event, including the stimulus class, onset, offset, peak, confirmed detection time, and optional annotation match.

Train an event-locked decoder on one raw run and scan a held-out raw run for face-like events:

neureptrace-continuous-stimulus-scan \
  --train-raw data/ds000117/sub-01/ses-meg/meg/sub-01_ses-meg_task-facerecognition_run-01_meg.fif \
  --train-events data/ds000117/sub-01/ses-meg/meg/sub-01_ses-meg_task-facerecognition_run-01_events.tsv \
  --scan-raw data/ds000117/sub-01/ses-meg/meg/sub-01_ses-meg_task-facerecognition_run-02_meg.fif \
  --scan-events data/ds000117/sub-01/ses-meg/meg/sub-01_ses-meg_task-facerecognition_run-02_events.tsv \
  --source-column stim_type \
  --positive-pattern "Famous|Unfamiliar" \
  --negative-pattern "Scrambled" \
  --positive-label face \
  --negative-label scrambled \
  --target-class face \
  --train-window 0.15 0.25 \
  --picks meg \
  --demean-window \
  --slice-duration 6.0 \
  --slice-count 10 \
  --require-target-event \
  --exclude-events-from-threshold-window \
  --threshold-window 0.0 0.8 \
  --detection-window 0.8 6.0 \
  --threshold-method max_run \
  --threshold-quantile 0.975 \
  --min-consecutive 2 \
  --min-duration 0.05 \
  --merge-gap 0.05 \
  --refractory 0.30 \
  --match-tolerance 0.35 \
  --out-dir results/ds000117_continuous_scan

The workflow writes stream_observations.csv, stimulus_events.csv, stimulus_summary.csv, stimulus_thresholds.csv, stimulus_annotations.csv, and heldout_event_metrics.csv.

If the events CSV has the NOD stim_is_animate column but no named decoding condition yet, create one:

neureptrace-metadata \
  --events-csv data/nod/sub-01_events.csv \
  --source-column stim_is_animate \
  --positive-pattern "True" \
  --label-column condition \
  --positive-label animate \
  --negative-label inanimate \
  --out data/nod/sub-01_metadata_animate.csv

After running several subjects, aggregate them:

neureptrace-results \
  results/nod_sub-01_animate.csv \
  results/nod_sub-02_animate.csv \
  --out results/nod_animate_summary.csv

Benchmark Plan

The first public benchmark target is NOD-MEG/NOD-EEG because the dataset provides preprocessed MNE epochs and metadata for natural-image decoding. The recommended first task is animate-versus-inanimate decoding from the NOD-EEG stim_is_animate metadata. The second staged task is superclass decoding between canine and device trials, which keeps the same public dataset and reporting workflow while testing a different semantic contrast.

THINGS-EEG and THINGS-MEG are natural follow-up benchmarks for larger visual object representation experiments. Lab data with task localizers and planning periods should come after these public baselines are reproducible.

Temporal State Workflow

The calibration-aware temporal-state workflow runs the three staged NOD tasks as a reusable downstream-state inference evidence pass. It exports probability observations with matched calibrated and uncalibrated emissions, fits conservative sticky switching models, compares controls, summarizes semantic stages, and writes compact artifacts:

neureptrace-temporal-state-workflow \
  --data-root data/nod \
  --out-dir results/temporal_state_inference \
  --compact-export-dir ../NeuRepTrace-Compact-Results/results/temporal_state_inference \
  --decoders logistic linear_svm \
  --n-permutations 100

Use --max-subjects 1 --task nod_animate --n-permutations 5 for a local smoke test before launching the full run. Resume is enabled by default; pass --no-resume only when existing subject-decoder outputs should be overwritten.

Documentation

The documentation site is published at https://ips-stuttgart.github.io/NeuRepTrace/.

The docs/ directory contains the project documentation:

Build the documentation site locally with:

poetry install --with docs --without dev
poetry run mkdocs build --strict

Tests

Run the test suite from a development environment:

python -m pytest

Citation

If you use NeuRepTrace in your research, please cite the repository for now:

@software{pfaff_neureptrace_2026,
  author = {Florian Pfaff},
  title = {NeuRepTrace: Probabilistic Tracing of Neural Representations over Time},
  year = {2026},
  url = {https://github.com/IPS-Stuttgart/NeuRepTrace},
  license = {MIT}
}

License

NeuRepTrace is licensed under the MIT License.

Packages

 
 
 

Contributors

Languages