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.
NeuRepTrace currently provides tools for:
- time-resolved decoding from MNE
Epochsfiles; - config-driven dataset loading from MNE
Epochsfiles and FieldTrip-like MATLAB.matfiles; - 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.
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.
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.csvUse YAML for hand-written configs and JSON for generated or CI-controlled
configs. See docs/dataset-specs.md for the schema and loader contract.
NeuRepTrace requires Python 3.11 or newer and earlier than Python 3.15.
For development from a source checkout, use Poetry:
poetry install --with devAlternatively, 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.
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.5The 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.5Run 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.csvRun 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.ymlPlot the resulting time course:
neureptrace-plot-time-decode \
results/nod_sub-01_animate.csv \
--chance 0.5 \
--out results/nod_sub-01_animate.pngDetect 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.csvThe 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.csvWith 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.csvThis 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_scanThe 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.csvAfter running several subjects, aggregate them:
neureptrace-results \
results/nod_sub-01_animate.csv \
results/nod_sub-02_animate.csv \
--out results/nod_animate_summary.csvThe 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.
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 100Use --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.
The documentation site is published at https://ips-stuttgart.github.io/NeuRepTrace/.
The docs/ directory contains the project documentation:
- Getting started covers installation and the first decoding run.
- Data staging describes the public NOD files to place
under
data/. - Benchmarking describes the initial NOD pilot.
- API overview maps the main public modules.
- Examples lists executable examples.
Build the documentation site locally with:
poetry install --with docs --without dev
poetry run mkdocs build --strictRun the test suite from a development environment:
python -m pytestIf 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}
}NeuRepTrace is licensed under the MIT License.