Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
02ca314
tools/scaling/scaling.py: Use one data folder for every workflow
AymericGaudin Jun 3, 2026
72215a0
tools/scaling/scaling.py: Change config.toml for group level (avoid d…
AymericGaudin Jun 4, 2026
ba83e76
brainprep/interfaces/fmriprep: fix fmriprep parameters + output names.
AGrigis Jul 10, 2026
7193020
faster quasiraw pipeline + mask interpolation fixed
Duplums Jul 22, 2026
c9f4957
brainprep/workflow/quasiraw: add a 'quick' option to speed up process…
AGrigis Aug 3, 2026
9b57c84
brainprep: fix pydoclint CI.
AGrigis Aug 3, 2026
b8adbf2
brainprep/interfaces/freesurfer: write the brain file to disk.
AGrigis Aug 4, 2026
ed3167f
brainprep/workflow/defacing: update new brainmask interface.
AGrigis Aug 4, 2026
e7f7f95
brainprep/interfaces/fsl: allow rigid body alignment.
AGrigis Aug 4, 2026
27d3cba
brainprep/workflow/quasiraw: refactor workflow + use 2mm space for qu…
AGrigis Aug 4, 2026
799cf83
doc/user_guide/quasiraw: update documentation.
AGrigis Aug 4, 2026
e29a0c0
brainprep/resources/MNI152_T1_2mm_brain: add template in 2mm space.
AGrigis Aug 4, 2026
51d8848
brainprep/tests/test_workflow: fix interface testing.
AGrigis Aug 4, 2026
ca7729d
brainprep/workflow/quasiraw: return unmasked image.
AGrigis Aug 5, 2026
114f636
brainprep/tests/test_workflow: remove slow interface testing.
AGrigis Aug 5, 2026
074e99e
brainprep/workflow/quasiraw: support T2w and FLAIR modalities in Quas…
AGrigis Aug 5, 2026
63d86c6
brainprep/workflow/defacing: add T2w and FLAIR support in defacing wo…
AGrigis Aug 7, 2026
47571ff
brainprep/tests: clear rst report before each test.
AGrigis Aug 7, 2026
c1f871f
brainprep/workflow/defacing: fix enum.
AGrigis Aug 7, 2026
bb789e7
[test]: Isolate longitudinal error per modality
AymericGaudin Aug 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
# .. code-block:: bash
#
# $ nosetests --with-coverage --cover-package=brainprep --verbosity=2
# --with-doctest --doctest-options='+ELLIPSIS,+NORMALIZE_WHITESPACE'
###
name: "testing[nosetests]"

Expand Down Expand Up @@ -48,7 +47,7 @@ jobs:
python -m pip install --progress-bar off ".[ci]"
- name: Run unit tests
run: |
nosetests --with-coverage --cover-package=brainprep --verbosity=2 --with-doctest --doctest-options='+ELLIPSIS,+NORMALIZE_WHITESPACE'
nosetests --with-coverage --cover-package=brainprep --verbosity=2
- name: Coveralls
if: matrix.python-version == 3.12
env:
Expand Down
9 changes: 7 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ NEW
---

- :bdg-success:`Enhancement` Add the dmriprep workflow.
- :bdg-success:`Enhancement` Add the mrophologist workflow.
- :bdg-success:`Enhancement` Add the morphologist workflow.

Fixes
-----

- :bdg-danger:`Deprecation` Fix the containers that are using mri_synthstrip.
- :bdg-danger:`Deprecation` Fix the containers that are using `mri_synthstrip`.
- :bdg-danger:`Deprecation` The run mapping file has been moved to avoid
conflicts with FreeSurfer.

Expand All @@ -24,10 +24,15 @@ Enhancements

- :bdg-success:`Enhancement` Add signature hook.
- :bdg-success:`Enhancement` Add live comand line monitoring support.
- :bdg-success:`Enhancement` Support multi-modality in Quasi-Raw workflow.
- :bdg-success:`Enhancement` Add `quick` mode in Quasi-Raw workflow.
- :bdg-success:`Enhancement` Support multi-modality in Deface workflow.

Changes
-------

- :bdg-danger:`Deprecation` Optimize the Quasi-Raw workflow steps.


2.0.0
=====
Expand Down
22 changes: 10 additions & 12 deletions brainprep/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,6 @@ class Hook:
``before_call`` returns the inputs unchanged, and ``after_call`` returns
the outputs unchanged.

Methods
-------
before_call(func, inputs)
Hook executed before the wrapped function is called.
Must return a dictionary of (possibly modified) inputs.

after_call(func, outputs)
Hook executed after the wrapped function returns.
Must return the (possibly modified) output value.

Notes
-----
Subclasses may override one or both methods. If a method is not
Expand All @@ -87,14 +77,22 @@ def before_call(
func: Callable,
inputs: dict[str, Any],
) -> dict[str, Any]:
"""Transform and inspect inputs before the function call."""
"""
Hook executed before the wrapped function is called.
Transform and/or inspect inputs.
Must return a dictionary of (possibly modified) inputs.
"""
return inputs

def after_call(
self,
outputs: Any,
) -> Any:
"""Transform and inspect outputs after the function call."""
"""
Hook executed after the wrapped function returns.
Transform and/or inspect outputs.
Must return the (possibly modified) output value.
"""
return outputs


Expand Down
2 changes: 1 addition & 1 deletion brainprep/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
fmriprep_metrics,
incremental_pca,
mask_overlap,
maskdiff,
mean_correlation,
mriqc_metrics,
network_entropy,
Expand All @@ -91,7 +92,6 @@
from .utils import (
anonfile,
copyfiles,
maskdiff,
movedir,
ungzfile,
write_uuid_mapping,
Expand Down
9 changes: 7 additions & 2 deletions brainprep/interfaces/ants.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ def biasfield(
image_file: File,
mask_file: File,
output_dir: Directory,
entities: dict) -> tuple[list[str], tuple[File]]:
entities: dict,
quick: bool = False) -> tuple[list[str], tuple[File]]:
"""
Bias field correction of a BIDS-compliant anatomical image using ANTs's
`N4BiasFieldCorrection`.
Expand All @@ -55,6 +56,10 @@ def biasfield(
Directory where the reoriented image will be saved.
entities : dict
A dictionary of parsed BIDS entities including modality.
quick : bool
Increased shrink factor from `1` to `4`, which downsamples the image
before estimating the bias field.
Default False.

Returns
-------
Expand All @@ -73,7 +78,7 @@ def biasfield(
"N4BiasFieldCorrection",
"-d", "3",
"-i", str(image_file),
"-s", "1",
"-s", "4" if quick else "1",
"-b", "[1x1x1,3]",
"-c", "[50x50x50x50,0.001]",
"-t", "[0.15,0.01,200]",
Expand Down
104 changes: 77 additions & 27 deletions brainprep/interfaces/fmriprep.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import json
import os
import shutil
import tempfile
from pathlib import Path

import numpy as np
Expand All @@ -40,6 +41,7 @@
File,
)
from ..utils import (
print_warn,
sidecar_from_file,
)

Expand Down Expand Up @@ -106,14 +108,33 @@ def fmriprep_wf(
Notes
-----
- Creates BIDS subject specific working directory using copy in
'rawdata'.
'rawdata' folder.
- Create FreeSurfer subject directory using copy in 'freesurfer' folder.
- To avoid paths that are too long and not allowed by FreeSurfer, use the
'/tmp' directory. To prevent data leakage, please bind '/tmp' to a
secure location.
- Store intermediate pre-processing outputs in 'work'.
- Use as many CPUs as available.
"""
rawdata_dir = workspace_dir / "rawdata"
anat_dir = rawdata_dir / "anat"
func_dir = rawdata_dir / "func"
work_dir = workspace_dir / "work"
for path in (anat_dir, func_dir, work_dir):
work_freesurfer_dir = workspace_dir / "freesurfer"
tmp_dir = Path(tempfile.TemporaryDirectory().name)
work_tmp_dir = tmp_dir / "work"
print_warn(
"To avoid paths that are too long and not allowed by FreeSurfer, we "
"use the '/tmp' directory. To prevent data leakage, please bind "
"'/tmp' to a secure location. Current temporary directory: "
f"{tmp_dir}."
)
for path in (
anat_dir,
func_dir,
work_freesurfer_dir,
work_tmp_dir,
):
path.mkdir(parents=True, exist_ok=True)
subject, session = entities["sub"], entities["ses"]
fshome_dir = os.getenv("FREESURFER_HOME")
Expand All @@ -122,6 +143,8 @@ def fmriprep_wf(
"You must define the 'FREESURFER_HOME' environment variable."
)
fshome_dir = Path(fshome_dir)
fssubject_dir = freesurfer_dir / f"sub-{subject}"
fssubject_local_dir = work_freesurfer_dir / f"sub-{subject}_ses-{session}"

for source_file, target_dir in zip(
[t1_file, *func_files],
Expand Down Expand Up @@ -174,10 +197,18 @@ def fmriprep_wf(
(
fmriprep_dir /
"func" /
f"{basename}_space-{template}_den-91k_bold.dtseries.nii",
f"{basename}_hemi-L_space-fsnative_bold.func.gii",
),
(
fmriprep_dir /
"func" /
f"{basename}_hemi-R_space-fsnative_bold.func.gii",
),
(
fmriprep_dir /
"func" /
f"{basename}_space-fsLR_den-91k_bold.dtseries.nii",
)
for template in ("fsnative",
"fsLR")
]
confounds_file = (
fmriprep_dir /
Expand All @@ -191,30 +222,49 @@ def fmriprep_wf(
confounds_file,
])

command = [
"fmriprep",
str(rawdata_dir),
str(output_dir.parent.parent),
"participant",
"--fs-subjects-dir", str(freesurfer_dir),
"--work-dir", str(work_dir),
"--n-cpus", str(os.cpu_count()),
"--stop-on-first-crash",
"--fs-license-file", str(fshome_dir / "license.txt"),
"--skip-bids-validation",
"--fs-no-reconall",
"--fs-no-resume",
"--force", "bbr", "syn-sdc",
"--no-msm",
"--cifti-output", "91k",
"--output-spaces",
"T1w", "MNI152NLin2009cAsym", "MNI152NLin2009cAsym:res-2",
"fsnative", "fsLR",
"--ignore", "slicetiming",
"--participant-label", subject,
commands = [
[
"cp",
"-r",
str(fssubject_dir),
str(fssubject_local_dir),
],
[
"fmriprep",
str(rawdata_dir),
str(output_dir.parent.parent),
"participant",
"--notrack",
"--skip-bids-validation",
"--stop-on-first-crash",
"--n-cpus", str(os.cpu_count()),
"--fs-license-file", str(fshome_dir / "license.txt"),
"--fs-subjects-dir", str(work_freesurfer_dir),
"--work-dir", str(work_tmp_dir),
"--fs-no-resume",
"--force", "bbr", "syn-sdc",
"--no-msm",
"--cifti-output", "91k",
"--output-spaces",
"T1w", "MNI152NLin2009cAsym", "MNI152NLin2009cAsym:res-2",
"fsnative", "fsLR",
"--ignore", "slicetiming",
"--participant-label", subject,
],
[
"cp",
"-r",
str(work_tmp_dir),
str(work_dir.parent),
],
[
"rm",
"-r",
str(tmp_dir),
],
]

return command, (rfmri_outputs, qc_file)
return commands, (rfmri_outputs, qc_file)


@step(
Expand Down
12 changes: 8 additions & 4 deletions brainprep/interfaces/freesurfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,25 +77,29 @@ def brainmask(
command : list[str]
Skull-stripping command-line.
outputs : tuple[File]
- mask_file : File - Skull-stripped brain image file.
-brain_file : File - Skull-stripped brain image file.
-mask_file : File - Binary brain mask image file.

References
----------

.. footbibliography::
"""
basename = "sub-{sub}_ses-{ses}_run-{run}_mod-{mod}_brainmask".format(
basename = "sub-{sub}_ses-{ses}_run-{run}_mod-{mod}".format(
**entities)
mask_file = output_dir / f"{basename}.nii.gz"
brain_file = output_dir / f"{basename}_brain.nii.gz"
mask_file = output_dir / f"{basename}_brainmask.nii.gz"

command = [
"mri_synthstrip",
"-i", str(image_file),
"-o", str(brain_file),
"-m", str(mask_file),
"-f", "0",
"--no-csf",
]

return command, (mask_file, )
return command, (brain_file, mask_file, )


@step(
Expand Down
Loading