Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
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
70 changes: 54 additions & 16 deletions brainprep/interfaces/fsl.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"""

import os
from pathlib import Path

from ..decorators import (
CoerceparamsHook,
Expand Down Expand Up @@ -61,7 +62,7 @@ def reorient(
outputs : tuple[File]
- reorient_image_file : File - Reoriented input image file.
"""
basename = "sub-{sub}_ses-{ses}_run-{run}_mod-T1w_reorient".format(
basename = "sub-{sub}_ses-{ses}_run-{run}_mod-{mod}_reorient".format(
**entities)
reorient_image_file = output_dir / f"{basename}.nii.gz"

Expand Down Expand Up @@ -109,7 +110,8 @@ def deface(
outputs : tuple[File | list[File]]
- deface_file : File - Defaced input T1w image file.
- mask_file : File - Defacing binary mask.
- vol_files : list[File] - Defacing 3d rendering.
- transform_file : File - Affine transformation from original space to
MNI152 space.

Raises
------
Expand All @@ -126,17 +128,29 @@ def deface(
**entities)
deface_file = output_dir / f"{basename}.nii.gz"
mask_file = output_dir / f"{basename}mask.nii.gz"

command = [
"fsl_deface",
str(t1_file),
str(deface_file),
"-d", str(mask_file),
"-f", "0.5",
"-B",
transform_file = output_dir / f"{basename}affine.mat"

resource_dir = Path(__file__).parent.parent / "resources"
bigfov_transfrom_file = resource_dir / "MNI_BigFov_to_MNI.mat"

commands = [
[
"fsl_deface",
str(t1_file),
str(deface_file),
"-d", str(mask_file),
"-m13", str(transform_file),
"-f", "0.5",
"-B",
],
[
"convert_xfm",
"-omat", str(transform_file),
"-concat", str(bigfov_transfrom_file), str(transform_file),
]
]

return command, (deface_file, mask_file, )
return commands, (deface_file, mask_file, transform_file)


@step(
Expand Down Expand Up @@ -206,7 +220,8 @@ def scale(
image_file: File,
scale: int,
output_dir: Directory,
entities: dict) -> tuple[list[str], tuple[File]]:
entities: dict,
interpolation: str = "spline") -> tuple[list[str], tuple[File]]:
"""
Apply an isotropic resampling transformation to a BIDS-compliant image
file using FSL's `flirt`.
Expand All @@ -221,6 +236,10 @@ def scale(
Directory where the scaled image will be saved.
entities : dict
A dictionary of parsed BIDS entities including modality.
interpolation: str
The interpolation method: 'trilinear', 'nearestneighbour', 'sinc', or
'spline'.
Default 'spline'.

Returns
-------
Expand All @@ -240,6 +259,7 @@ def scale(
"-in", str(image_file),
"-ref", str(image_file),
"-applyisoxfm", str(scale),
"-interp", interpolation,
"-out", str(scaled_anatomical_file),
"-omat", str(transform_file),
"-verbose", "1",
Expand All @@ -263,7 +283,9 @@ def affine(
anatomical_file: File,
template_file: File,
output_dir: Directory,
entities: dict) -> tuple[list[str], tuple[File]]:
entities: dict,
rigid: bool = False,
quick: bool = False) -> tuple[list[str], tuple[File]]:
"""
Affinely register a BIDS-compliant anatomical image to a template file
using FSL's `flirt`.
Expand All @@ -278,6 +300,15 @@ def affine(
Directory where the affine transformation will be saved.
entities : dict
A dictionary of parsed BIDS entities including modality.
rigid : bool
Estimate a 6 DOF transformation that maintains the original size and
shape of the brain. By default a 9 DOF transformation allows for
additional scaling in the x, y, and z directions, adjusting the size
and shape of the brain during the alignment process.
Default False.
quick : bool
Restricted rotation search range to +/-30° on all three axes.
Default False.

Returns
-------
Expand All @@ -301,11 +332,17 @@ def affine(
"-anglerep", "euler",
"-bins", "256",
"-interp", "trilinear",
"-dof", "9",
"-dof", "6" if rigid else "9",
"-out", str(aligned_anatomical_file),
"-omat", str(transform_file),
"-verbose", "1"
]
if quick:
command += [
"-searchrx", "-30", "30",
"-searchry", "-30", "30",
"-searchrz", "-30", "30",
]

return command, (aligned_anatomical_file, transform_file)

Expand Down Expand Up @@ -346,7 +383,8 @@ def applyaffine(
A dictionary of parsed BIDS entities including modality.
interpolation: str
The interpolation method: 'trilinear', 'nearestneighbour', 'sinc', or
'spline'. Default 'spline'.
'spline'.
Default 'spline'.

Returns
-------
Expand All @@ -364,7 +402,7 @@ def applyaffine(
"-in", str(image_file),
"-ref", str(template_file),
"-init", str(transform_file),
"-interp", str(interpolation),
"-interp", interpolation,
"-applyxfm",
"-out", str(aligned_image_file),
]
Expand Down
Loading
Loading