MReyeXtract: eye-voxel extraction for fMRI
MReyeXtract extracts the eyeballs from 4D BOLD images so they can be fed to DeepMReye or other gaze-decoding models. Each run is registered to a DeepMReye eye template with ANTsPy, cropped to the eye masks, and saved alongside an interactive HTML quality-control report. It runs on BIDS datasets out of the box, and on arbitrary directory trees via a glob pattern.
If you have questions or comments, please reach out (see Correspondence).
Installation
MReyeXtract requires Python 3.11.
From PyPI
Install the latest release from PyPI into a virtual environment:
python3.11 -m venv .venv
source .venv/bin/activate
pip install mreyextract
Or into a conda environment:
conda create --name mreyextract python=3.11
conda activate mreyextract
pip install mreyextract
If ANTsPy does not resolve a wheel for your platform, install it manually first (see the ANTsPy installation guide) and then re-run the install above.
From source
To modify or contribute to MReyeXtract, install an editable checkout with the development extras — see CONTRIBUTING.md.
Usage
Installing the package exposes the mreyextract command-line tool. Run
mreyextract --help for the full list of options.
BIDS datasets (default)
mreyextract --root /path/to/bids_dataset
To extract from a derivatives pipeline (e.g. fMRIPrep outputs):
mreyextract --root /path/to/bids_dataset --derivatives-dir fmriprep
Restrict which BOLD files are processed with BIDS entities. Each accepts one or
more values; '*' matches any value and 'none'/'null' matches files where
the entity is absent:
mreyextract --root /path/to/bids_dataset \
--subject 01 02 --task rest --run '*'
Filters can also be supplied as a JSON file via --bids-filter-file (the
BIDS-App convention). Precedence, lowest to highest, is: YAML config (see later) →
JSON BIDS filter file → explicit CLI entity flags, so the command line always
wins.
Non-BIDS directories
Point --no-bids-compatible at any tree and provide a glob pattern:
mreyextract --root /path/to/data --no-bids-compatible \
--glob-pattern 'sub-*/**/func/*_bold.nii*'
Options
| Option | Description |
|---|---|
--root |
Root directory to search for BOLD files (required). |
--bids-compatible / --no-bids-compatible |
Treat --root as a BIDS dataset. Default: BIDS. |
--derivatives-dir |
Relative derivatives directory to extract from (e.g. fmriprep). |
--glob-pattern |
Glob for non-BIDS mode. Default: sub-*/**/func/*_bold.nii*. |
--force |
Overwrite existing outputs instead of skipping them. |
--as-pickle |
Save the masked eye voxels as a pickled array instead of NIfTI. |
--n-jobs |
Number of runs to process in parallel. 1 (default) is serial; -1 uses all cores. |
--threads-per-job |
ITK/ANTs threads per parallel job. Default: cores // n_jobs. |
--log-level |
Logging verbosity: DEBUG, INFO, WARNING, ERROR. Default: INFO. |
--bids-filter-file |
Path to a JSON file of BIDS entity filters. |
--config |
Path to a YAML config file that seeds the options above. |
Config file
Rather than passing many flags, the run can be described in a YAML file and
loaded with --config. Keys under extract mirror the CLI options (with
underscores); explicit flags on the command line override the file:
# run.yaml
extract:
root: /abs/path/to/bids_dataset
derivatives_dir: fmriprep
n_jobs: 4
threads_per_job: 2
filters:
task: [rest] # "*" -> any, "none"/"null" -> absent
mreyextract --config run.yaml # everything from the file
mreyextract --config run.yaml --force # override a single option
Parallel processing
Runs are independent, so they can be processed in parallel across a loky process pool:
mreyextract --root /path/to/bids_dataset --n-jobs 8
Registration (ANTsPy/ITK) is itself multithreaded, so the tool splits the
available cores between across-run parallelism (--n-jobs) and each run's own
threads (--threads-per-job) to avoid oversubscription. By default
threads-per-job is set to cores // n_jobs, where cores respects the CPU
allocation (SLURM/cgroup affinity), not just the physical node — so the default
is safe when running interactively inside an allocation. Tune both together on a
shared server, and keep an eye on memory — each concurrent run holds a full 4D
BOLD volume in RAM.
Reviewing the reports
Installing the package also exposes mreyextract-view, a small local web app for
paging through the QC reports and marking each one good or bad:
mreyextract-view --root /path/to/bids_dataset
It serves the reports under <root>/derivatives/mreyextract at
http://127.0.0.1:8000 and opens a browser. The sidebar groups every report by
subject and colours it by verdict, and notes can be attached to any report.
Reviewing a whole dataset is one keypress per report. With advance
ticked (the default), g marks the report good and b marks it bad, and either
immediately moves on to the next one — so a dataset can be worked through
without touching the mouse: look at the report, press one key, look at the next.
u clears a verdict, and the up/down arrow keys move between reports without
rating one. The next report is loaded in the background while the current one is
on screen, so it is ready the moment you advance.
The counts in the header and the status light beside each report change only
once the verdict is in qc_ratings.tsv. A light stays dimmed while its write
is still in flight, so a solid colour and a rising count confirm the file on
disk was actually updated; a write that fails says so and leaves the report at
its previous verdict rather than a colour that was never saved.
Point it at reports written by another tool (e.g. DeepMReye's report_*.html)
with --review-dir:
mreyextract-view --review-dir /path/to/reports
| Option | Description |
|---|---|
--root |
Dataset root whose derivatives/mreyextract reports are reviewed. |
--review-dir |
Review this directory instead of a dataset's derivatives. |
--pattern |
Glob(s) selecting report files. Default: **/*_report.html **/report_*.html. |
--host |
Interface to bind. Default: 127.0.0.1. |
--port |
Port to serve on. Default: 8000; 0 picks a free port. |
--browser / --no-browser |
Open a browser on startup. Default: open. |
--log-level |
Logging verbosity. Default: INFO. |
Verdicts are written to qc_ratings.tsv in the reviewed directory — next to the
reports and eye voxels they describe — as they are made, so a review can be
interrupted and resumed, and two people can review the same dataset at once. The
file is a plain table, ready for the analysis that follows:
import pandas as pd
ratings = pd.read_csv("derivatives/mreyextract/qc_ratings.tsv", sep="\t")
usable = ratings.loc[ratings["status"] == "good", "path"]
Reports on a remote machine can be reviewed over an SSH tunnel
(ssh -L 8000:127.0.0.1:8000 user@host) without copying anything down; the
viewer binds to localhost only, and everything it serves is read from that
directory.
Python API
The extraction entry point can also be called directly:
from mreyextract.extract import extract_eyeball_voxels
extract_eyeball_voxels(
root="/path/to/bids_dataset",
glob_pattern="sub-*/**/func/*_bold.nii*",
bids_compatible=True,
filters={"task": "rest"},
)
Data formats
Inputs are 4D BOLD images in NIfTI format (.nii / .nii.gz).
Outputs are written to a BIDS-style derivatives folder under the dataset root:
<root>/derivatives/mreyextract/
dataset_description.json
qc_ratings.tsv # QC verdicts, if reviewed
sub-01/func/
sub-01_task-rest_run-1_desc-eye_bold.nii.gz # masked eye voxels
sub-01_task-rest_run-1_desc-eye_report.html # QC report
With --as-pickle, the eye voxels are saved as a pickled NumPy array
(*_desc-eye_timeseries.p) instead of NIfTI. Existing outputs are skipped
unless --force is passed.
Hardware requirements
Registration is CPU-based and runs per BOLD run. A standard workstation is sufficient; no GPU is required. Memory scales with image size — 4D BOLD runs are held in memory during registration, so allow several GB of free RAM for high-resolution or long acquisitions.
Software requirements
MReyeXtract is developed and tested on Python 3.11. Core dependencies (installed automatically):
numpy (<2.0.0)
nibabel (>=5.3.2)
antspyx (>=0.6.1)
scipy (>=1.15.1)
plotly (>=6.5.0)
pybids (>=0.22.0)
joblib (>=1.3)
pyyaml (>=6.0)
Running on a cluster (SLURM)
The slurm/ directory contains a ready-to-adapt job-array template
(submit.sbatch) and an example config.yaml. The pattern is one array task
per subject: SLURM provides the across-subject parallelism, and each task lets
ANTs use all of its allocated cores.
mkdir -p logs
sbatch slurm/submit.sbatch slurm/config.yaml
The template reads the subject list from the config's slurm.subjects, injects
the right subject per array index, and caps ITK/OpenMP threads to
--cpus-per-task. Edit the #SBATCH resource directives (and the --array
range to match the number of subjects), the module load line (must be a
Python 3.11 build), and the virtual-environment path before submitting.
Tests
pytest
Development
Contributions are welcome. For development setup, the check suite, PR conventions, and how releases are automated, see CONTRIBUTING.md.
BIDS app
MReyeXtract reads and writes BIDS-compatible layouts: it queries BOLD files with
PyBIDS, honours BIDS entity filters,
and emits a derivatives/mreyextract/ folder with a dataset_description.json.
Correspondence
If you have questions, comments or inquiries, please reach out to us: z.b.nudelman[at]vu.nl; m.nau[at]vu.nl
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mreyextract-0.2.0.tar.gz.
File metadata
- Download URL: mreyextract-0.2.0.tar.gz
- Upload date:
- Size: 2.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c1e5442cb8e22544adb37f052c9ed4eee6e6e77989dccbab7c8626092b8b9a4
|
|
| MD5 |
fa5831995985db05a0965742ee6a4a58
|
|
| BLAKE2b-256 |
fc7da5920add0ef328120d1a7eee2f0d8eca0607491bdf5173b04434907ce561
|
Provenance
The following attestation bundles were made for mreyextract-0.2.0.tar.gz:
Publisher:
release.yml on DeepMReye/MReyeXtract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mreyextract-0.2.0.tar.gz -
Subject digest:
2c1e5442cb8e22544adb37f052c9ed4eee6e6e77989dccbab7c8626092b8b9a4 - Sigstore transparency entry: 2625638050
- Sigstore integration time:
-
Permalink:
DeepMReye/MReyeXtract@b64886fc11e35689f566c4fe9b89bbdea6a7f5df -
Branch / Tag:
refs/heads/main - Owner: https://github.com/DeepMReye
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b64886fc11e35689f566c4fe9b89bbdea6a7f5df -
Trigger Event:
push
-
Statement type:
File details
Details for the file mreyextract-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mreyextract-0.2.0-py3-none-any.whl
- Upload date:
- Size: 2.9 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29dc3eafb67e3c103508deec9f0ad01e861dc9d555375e697cbf62d0a31bd3b6
|
|
| MD5 |
24c98b92c43b7beb4194d87856a6b2cd
|
|
| BLAKE2b-256 |
1048b05d158130b795804d1ac6ec9437b8fa1f24c6a9b92c2f6faa4dd2e3c22e
|
Provenance
The following attestation bundles were made for mreyextract-0.2.0-py3-none-any.whl:
Publisher:
release.yml on DeepMReye/MReyeXtract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mreyextract-0.2.0-py3-none-any.whl -
Subject digest:
29dc3eafb67e3c103508deec9f0ad01e861dc9d555375e697cbf62d0a31bd3b6 - Sigstore transparency entry: 2625638101
- Sigstore integration time:
-
Permalink:
DeepMReye/MReyeXtract@b64886fc11e35689f566c4fe9b89bbdea6a7f5df -
Branch / Tag:
refs/heads/main - Owner: https://github.com/DeepMReye
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b64886fc11e35689f566c4fe9b89bbdea6a7f5df -
Trigger Event:
push
-
Statement type: