Repository: TheLabbingProject/django_mri (language: python)

Issue:
dMRIPrep interface
Would be helpful to have an interface for dMRI preprocessing pipeline.


Discussion / hints:

Fix patch:
diff --git a/django_mri/admin.py b/django_mri/admin.py
index b4bfbe10..9eb7c3a4 100644
--- a/django_mri/admin.py
+++ b/django_mri/admin.py
@@ -19,9 +19,9 @@
 from django.http import HttpResponse
 from django.urls import reverse
 from django.utils.safestring import mark_safe
-from django_analyses.models.run import Run
 from nonrelated_inlines.admin import NonrelatedStackedInline
 
+from django_analyses.models.run import Run
 from django_mri.models.data_directory import DataDirectory
 from django_mri.models.irb_approval import IrbApproval
 from django_mri.models.nifti import NIfTI
diff --git a/django_mri/analysis/analysis_definitions.py b/django_mri/analysis/analysis_definitions.py
index 769678f8..66f19e90 100644
--- a/django_mri/analysis/analysis_definitions.py
+++ b/django_mri/analysis/analysis_definitions.py
@@ -18,14 +18,22 @@
 
 import nipype
 from django.conf import settings
+from nipype.interfaces.freesurfer import ReconAll
+from nipype.interfaces.fsl import (BET, FAST, FLIRT, FNIRT, SUSAN, TOPUP,
+                                   ApplyTOPUP, BinaryMaths, Eddy, ExtractROI,
+                                   MeanImage, Merge, Reorient2Std, RobustFOV)
+from nipype.interfaces.fsl.base import no_fsl
+from nipype.interfaces.mrtrix3 import (ConstrainedSphericalDeconvolution,
+                                       DWIBiasCorrect, DWIDenoise, Generate5tt,
+                                       MRDeGibbs, ResponseSD)
+
 from django_mri.analysis import messages
-from django_mri.analysis.interfaces.fmriprep.fmriprep import (
-    FmriPrep2021,
-    FmriPrep2022,
-    FmriPrep2023,
-    FmriPrep2024,
-    FmriPrep2025,
-)
+from django_mri.analysis.interfaces.dmriprep.dmriprep import DmriPrep010
+from django_mri.analysis.interfaces.fmriprep.fmriprep import (FmriPrep2021,
+                                                              FmriPrep2022,
+                                                              FmriPrep2023,
+                                                              FmriPrep2024,
+                                                              FmriPrep2025)
 from django_mri.analysis.interfaces.fsl.fsl_anat import FslAnat
 from django_mri.analysis.interfaces.mrtrix3.dwi2tensor import Dwi2Tensor
 from django_mri.analysis.interfaces.mrtrix3.dwifslpreproc import DwiFslPreproc
@@ -33,156 +41,72 @@
 from django_mri.analysis.interfaces.mrtrix3.mrcat import MRCat
 from django_mri.analysis.interfaces.mrtrix3.mrconvert import MRConvert
 from django_mri.analysis.interfaces.mrtrix3.tensor2metric import Tensor2metric
+from django_mri.analysis.specifications.dmriprep.dmriprep import (
+    DMRIPREP_INPUT_SPECIFICATION, DMRIPREP_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fmriprep.fmriprep import (
-    FMRIPREP_INPUT_SPECIFICATION,
-    FMRIPREP_OUTPUT_SPECIFICATION,
-)
+    FMRIPREP_INPUT_SPECIFICATION, FMRIPREP_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.freesurfer.recon_all import (
-    RECON_ALL_INPUT_SPECIFICATION,
-    RECON_ALL_OUTPUT_SPECIFICATION,
-)
+    RECON_ALL_INPUT_SPECIFICATION, RECON_ALL_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.apply_topup import (
-    APPLY_TOPUP_INPUT_SPECIFICATION,
-    APPLY_TOPUP_OUTPUT_SPECIFICATION,
-)
+    APPLY_TOPUP_INPUT_SPECIFICATION, APPLY_TOPUP_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.bet import (
-    BET_INPUT_SPECIFICATION,
-    BET_OUTPUT_SPECIFICATION,
-)
+    BET_INPUT_SPECIFICATION, BET_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.binary_maths import (
-    BINARY_MATHS_INPUT_SPECIFICATION,
-    BINARY_MATHS_OUTPUT_SPECIFICATION,
-)
+    BINARY_MATHS_INPUT_SPECIFICATION, BINARY_MATHS_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.eddy import (
-    EDDY_INPUT_SPECIFICATION,
-    EDDY_OUTPUT_SPECIFICATION,
-)
+    EDDY_INPUT_SPECIFICATION, EDDY_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.fast import (
-    FAST_INPUT_SPECIFICATION,
-    FAST_OUTPUT_SPECIFICATION,
-)
+    FAST_INPUT_SPECIFICATION, FAST_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.flirt import (
-    FLIRT_INPUT_SPECIFICATION,
-    FLIRT_OUTPUT_SPECIFICATION,
-)
+    FLIRT_INPUT_SPECIFICATION, FLIRT_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.fnirt import (
-    FNIRT_INPUT_SPECIFICATION,
-    FNIRT_OUTPUT_SPECIFICATION,
-)
+    FNIRT_INPUT_SPECIFICATION, FNIRT_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.fsl_anat import (
-    FSL_ANAT_INPUT_SPECIFICATION,
-    FSL_ANAT_OUTPUT_SPECIFICATION,
-)
+    FSL_ANAT_INPUT_SPECIFICATION, FSL_ANAT_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.fslmerge import (
-    FSLMERGE_INPUT_SPECIFICATION,
-    FSLMERGE_OUTPUT_SPECIFICATION,
-)
+    FSLMERGE_INPUT_SPECIFICATION, FSLMERGE_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.fslroi import (
-    FSLROI_INPUT_SPECIFICATION,
-    FSLROI_OUTPUT_SPECIFICATION,
-)
+    FSLROI_INPUT_SPECIFICATION, FSLROI_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.mean_image import (
-    MEAN_IMAGE_INPUT_SPECIFICATION,
-    MEAN_IMAGE_OUTPUT_SPECIFICATION,
-)
+    MEAN_IMAGE_INPUT_SPECIFICATION, MEAN_IMAGE_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.reorient2std import (
-    REORIENT2STD_INPUT_SPECIFICATION,
-    REORIENT2STD_OUTPUT_SPECIFICATION,
-)
+    REORIENT2STD_INPUT_SPECIFICATION, REORIENT2STD_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.robustfov import (
-    ROBUSTFOV_INPUT_SPECIFICATION,
-    ROBUSTFOV_OUTPUT_SPECIFICATION,
-)
+    ROBUSTFOV_INPUT_SPECIFICATION, ROBUSTFOV_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.susan import (
-    SUSAN_INPUT_SPECIFICATION,
-    SUSAN_OUTPUT_SPECIFICATION,
-)
+    SUSAN_INPUT_SPECIFICATION, SUSAN_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.fsl.topup import (
-    TOPUP_INPUT_SPECIFICATION,
-    TOPUP_OUTPUT_SPECIFICATION,
-)
+    TOPUP_INPUT_SPECIFICATION, TOPUP_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.bias_correct import (
-    BIAS_CORRECT_INPUT_SPECIFICATION,
-    BIAS_CORRECT_OUTPUT_SPECIFICATION,
-)
+    BIAS_CORRECT_INPUT_SPECIFICATION, BIAS_CORRECT_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.compute_metrics import (
-    TENSOR2METRIC_OUTPUT_SPECIFICATION,
-    TENSOR2METRICS_INPUT_SPECIFICATION,
-)
+    TENSOR2METRIC_OUTPUT_SPECIFICATION, TENSOR2METRICS_INPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.degibbs import (
-    DEGIBBS_INPUT_SPECIFICATION,
-    DEGIBBS_OUTPUT_SPECIFICATION,
-)
+    DEGIBBS_INPUT_SPECIFICATION, DEGIBBS_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.denoise import (
-    DENOISE_INPUT_SPECIFICATION,
-    DENOISE_OUTPUT_SPECIFICATION,
-)
+    DENOISE_INPUT_SPECIFICATION, DENOISE_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.dwifslpreproc import (
-    DWIFSLPREPROC_INPUT_SPECIFICATION,
-    DWIFSLPREPROC_OUTPUT_SPECIFICATION,
-)
+    DWIFSLPREPROC_INPUT_SPECIFICATION, DWIFSLPREPROC_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.dwigradcheck import (
-    DWIGRADCHECK_INPUT_SPECIFICATION,
-    DWIGRADCHECK_OUTPUT_SPECIFICATION,
-)
+    DWIGRADCHECK_INPUT_SPECIFICATION, DWIGRADCHECK_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.estimate_fod import (
-    DWI2FOD_INPUT_SPECIFICATION,
-    DWI2FOD_OUTPUT_SPECIFICATION,
-)
+    DWI2FOD_INPUT_SPECIFICATION, DWI2FOD_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.estimate_response import (
-    DWI2RESPONSE_INPUT_SPECIFICATION,
-    DWI2RESPONSE_OUTPUT_SPECIFICATION,
-)
+    DWI2RESPONSE_INPUT_SPECIFICATION, DWI2RESPONSE_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.estimate_tensors import (
-    DWI2TENSOR_INPUT_SPECIFICATION,
-    DWI2TENSOR_OUTPUT_SPECIFICATION,
-)
+    DWI2TENSOR_INPUT_SPECIFICATION, DWI2TENSOR_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.generate_5tt import (
-    GENERATE_5TT_INPUT_SPECIFICATION,
-    GENERATE_5TT_OUTPUT_SPECIFICATION,
-)
+    GENERATE_5TT_INPUT_SPECIFICATION, GENERATE_5TT_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.mrcat import (
-    MRCAT_INPUT_SPECIFICATION,
-    MRCAT_OUTPUT_SPECIFICATION,
-)
+    MRCAT_INPUT_SPECIFICATION, MRCAT_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.mrtrix3.mrconvert import (
-    MRCONVERT_INPUT_SPECIFICATION,
-    MRCONVERT_OUTPUT_SPECIFICATION,
-)
+    MRCONVERT_INPUT_SPECIFICATION, MRCONVERT_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.spm.cat12.segmentation import (
     CAT12_SEGMENTATION_INPUT_SPECIFICATION,
-    CAT12_SEGMENTATION_OUTPUT_SPECIFICATION,
-)
+    CAT12_SEGMENTATION_OUTPUT_SPECIFICATION)
 from django_mri.analysis.specifications.yalab.mutual_information_score import (
     MUTUAL_INFORMATION_SCORE_INPUT_SPECIFICATION,
-    MUTUAL_INFORMATION_SCORE_OUTPUT_SPECIFICATION,
-)
-from nipype.interfaces.freesurfer import ReconAll
-from nipype.interfaces.fsl import (
-    BET,
-    FAST,
-    FLIRT,
-    FNIRT,
-    SUSAN,
-    TOPUP,
-    ApplyTOPUP,
-    BinaryMaths,
-    Eddy,
-    ExtractROI,
-    MeanImage,
-    Merge,
-    Reorient2Std,
-    RobustFOV,
-)
-from nipype.interfaces.fsl.base import no_fsl
-from nipype.interfaces.mrtrix3 import (
-    ConstrainedSphericalDeconvolution,
-    DWIBiasCorrect,
-    DWIDenoise,
-    Generate5tt,
-    MRDeGibbs,
-    ResponseSD,
-)
+    MUTUAL_INFORMATION_SCORE_OUTPUT_SPECIFICATION)
 
 #: Warn if FSL is not accessible.
 test_mode = getattr(settings, "TESTING_MODE", False)
@@ -612,4 +536,16 @@
             },
         ],
     },
+    {
+        "title": "dMRIPrep",
+        "description": "A robust preprocessing pipeline for dMRI data.",  # noqa: E501
+        "versions": [
+            {
+                "title": DmriPrep010.__version__,
+                "description": "Beta version",
+                "input": DMRIPREP_INPUT_SPECIFICATION,
+                "output": DMRIPREP_OUTPUT_SPECIFICATION,
+            },
+        ],
+    },
 ]
diff --git a/django_mri/analysis/automation/anatomical/cat12_segmentation.py b/django_mri/analysis/automation/anatomical/cat12_segmentation.py
index f2aef6fe..f3628a5a 100644
--- a/django_mri/analysis/automation/anatomical/cat12_segmentation.py
+++ b/django_mri/analysis/automation/anatomical/cat12_segmentation.py
@@ -2,9 +2,8 @@
 Definition of the :class:`Cat12SegmentationRunner` class.
 """
 from django_mri.analysis.automation.anatomical import messages
-from django_mri.analysis.automation.anatomical.preprocessing import (
-    AnatomicalPreprocessing,
-)
+from django_mri.analysis.automation.anatomical.preprocessing import \
+    AnatomicalPreprocessing
 
 
 class Cat12SegmentationRunner(AnatomicalPreprocessing):
diff --git a/django_mri/analysis/automation/anatomical/preprocessing.py b/django_mri/analysis/automation/anatomical/preprocessing.py
index b930a3dc..9ca2d114 100644
--- a/django_mri/analysis/automation/anatomical/preprocessing.py
+++ b/django_mri/analysis/automation/anatomical/preprocessing.py
@@ -4,6 +4,7 @@
 import logging
 
 from django.db.models import Q, QuerySet
+
 from django_analyses.runner.queryset_runner import QuerySetRunner
 from django_mri.analysis.automation.anatomical import messages
 from django_mri.models.scan import Scan
diff --git a/django_mri/analysis/automation/anatomical/recon_all.py b/django_mri/analysis/automation/anatomical/recon_all.py
index 78f903ef..4633295e 100644
--- a/django_mri/analysis/automation/anatomical/recon_all.py
+++ b/django_mri/analysis/automation/anatomical/recon_all.py
@@ -2,10 +2,11 @@
 Definition of the :class:`ReconAllRunner` class.
 """
 from typing import List
+
 from nipype.interfaces.freesurfer import ReconAll
-from django_mri.analysis.automation.anatomical.preprocessing import (
-    AnatomicalPreprocessing,
-)
+
+from django_mri.analysis.automation.anatomical.preprocessing import \
+    AnatomicalPreprocessing
 from django_mri.models.scan import Scan
 
 
diff --git a/django_mri/analysis/automation/cat12_segmentation/__init__.py b/django_mri/analysis/automation/cat12_segmentation/__init__.py
index ee37b70a..714588f2 100644
--- a/django_mri/analysis/automation/cat12_segmentation/__init__.py
+++ b/django_mri/analysis/automation/cat12_segmentation/__init__.py
@@ -1,8 +1,7 @@
 """
 CAT12 segmentation automation.
 """
-from django_mri.analysis.automation.cat12_segmentation.run_cat12_segmentation import (
-    run_cat12_segmentation,
-)
+from django_mri.analysis.automation.cat12_segmentation.run_cat12_segmentation import \
+    run_cat12_segmentation
 
 # flake8: noqa: E501
diff --git a/django_mri/analysis/automation/cat12_segmentation/export.py b/django_mri/analysis/automation/cat12_segmentation/export.py
index be7d78e8..04ce25b9 100644
--- a/django_mri/analysis/automation/cat12_segmentation/export.py
+++ b/django_mri/analysis/automation/cat12_segmentation/export.py
@@ -8,11 +8,9 @@
 import pandas as pd
 import xarray as xr
 from django.db.models import QuerySet
+
 from django_mri.analysis.automation.cat12_segmentation.utils import (
-    get_node,
-    get_run_set,
-    read_nifti,
-)
+    get_node, get_run_set, read_nifti)
 
 OUTPUT_KEYS = "modulated_grey_matter", "modulated_white_matter", "warped_image"
 OUTPUT_DIMS = "Run ID", "x", "y", "z"
diff --git a/django_mri/analysis/automation/cat12_segmentation/utils.py b/django_mri/analysis/automation/cat12_segmentation/utils.py
index b74f8750..797cd152 100644
--- a/django_mri/analysis/automation/cat12_segmentation/utils.py
+++ b/django_mri/analysis/automation/cat12_segmentation/utils.py
@@ -7,10 +7,10 @@
 import nibabel as nib
 import numpy as np
 from django.db.models import QuerySet
+
 from django_analyses.models.analysis_version import AnalysisVersion
-from django_analyses.models.input.definitions.input_definition import (
-    InputDefinition,
-)
+from django_analyses.models.input.definitions.input_definition import \
+    InputDefinition
 from django_analyses.models.pipeline.node import Node
 from django_mri.analysis.automation.cat12_segmentation import messages
 from django_mri.models.scan import Scan
diff --git a/django_mri/analysis/automation/dmriprep/dmriprep.py b/django_mri/analysis/automation/dmriprep/dmriprep.py
new file mode 100644
index 00000000..dd533055
--- /dev/null
+++ b/django_mri/analysis/automation/dmriprep/dmriprep.py
@@ -0,0 +1,74 @@
+"""
+Definition of the :class:`fMRIPrepRunner` class.
+"""
+from typing import List
+
+from django.db.models import Q, QuerySet
+
+from django_analyses.runner.queryset_runner import QuerySetRunner
+from django_mri.analysis.interfaces.dmriprep.dmriprep import DmriPrep010
+from django_mri.models.scan import Scan
+from django_mri.utils.utils import get_subject_model
+
+#: Associated subject model.
+Subject = get_subject_model()
+
+
+class dMRIPrepRunner(QuerySetRunner):
+    """
+    Automates the execution of dMRIPrep over a queryset of subjects.
+    """
+
+    #: :class:`~django_analyses.models.analysis.Analysis` instance title.
+    ANALYSIS_TITLE = "dMRIPrep"
+
+    #: :class:`~django_analyses.models.analysis_version.AnalysisVersion`
+    #: instance title.
+    ANALYSIS_VERSION_TITLE = DmriPrep010.__version__
+
+    #: :class:`~django_analyses.models.pipeline.node.Node` instance
+
+    #: Input definition key.
+    INPUT_KEY = "participant_label"
+
+    #: The database model for scans (the base input class).
+    DATA_MODEL = Subject
+
+    #: Customize input preprocessing progressbar text.
+    INPUT_GENERATION_PROGRESSBAR_KWARGS = {
+        "unit": "subject",
+        "desc": "Converting MRI scans to NIfTI",
+    }
+
+    def get_base_queryset(self) -> QuerySet:
+        """
+        Overrides
+        :func:`~django_analyses.runner.queryset_runner.QuerySetRunner.get_base_queryset`
+        to return only subjects with functional MRI data.
+
+        Returns
+        -------
+        QuerySet
+            Subjects with fMRI data
+        """
+        queryset = super().get_base_queryset()
+        q = Q(mri_session_set__scan__dicom__sequence_type="dwi") & Q(
+            mri_session_set__scan__dicom__sequence_type="mprage"
+        )
+        return queryset.filter(q)
+
+    def get_instance_representation(self, instance: Subject) -> List[str]:
+        """
+        Returns the expected :attr:`INPUT_KEY` value for the given subject.
+
+        Parameters
+        ----------
+        instance : Subject
+            Subject instance
+
+        Returns
+        -------
+        List[str]
+            List containing subject ID string
+        """
+        return [str(instance.id)]
diff --git a/django_mri/analysis/automation/fmriprep/fmriprep.py b/django_mri/analysis/automation/fmriprep/fmriprep.py
index 2a6e4cea..2cd9e8d1 100644
--- a/django_mri/analysis/automation/fmriprep/fmriprep.py
+++ b/django_mri/analysis/automation/fmriprep/fmriprep.py
@@ -4,6 +4,7 @@
 from typing import List
 
 from django.db.models import Q, QuerySet
+
 from django_analyses.runner.queryset_runner import QuerySetRunner
 from django_mri.analysis.interfaces.fmriprep.fmriprep import FmriPrep2025
 from django_mri.models.scan import Scan
diff --git a/django_mri/analysis/automation/fmriprep/fmriprep_anat.py b/django_mri/analysis/automation/fmriprep/fmriprep_anat.py
index 90a66350..9f123fd9 100644
--- a/django_mri/analysis/automation/fmriprep/fmriprep_anat.py
+++ b/django_mri/analysis/automation/fmriprep/fmriprep_anat.py
@@ -1,4 +1,5 @@
 from django.db.models import QuerySet
+
 from django_mri.analysis.automation.fmriprep.fmriprep import fMRIPrepRunner
 from django_mri.models.scan import Scan
 
diff --git a/django_mri/analysis/automation/fsl_anat/run_fsl_anat.py b/django_mri/analysis/automation/fsl_anat/run_fsl_anat.py
index 1903c3dd..0a22ac0c 100644
--- a/django_mri/analysis/automation/fsl_anat/run_fsl_anat.py
+++ b/django_mri/analysis/automation/fsl_anat/run_fsl_anat.py
@@ -2,11 +2,11 @@
 
 from celery.result import AsyncResult
 from django.db.models import QuerySet
+
 from django_analyses.models.analysis import Analysis
 from django_analyses.models.analysis_version import AnalysisVersion
-from django_analyses.models.input.definitions.input_definition import (
-    InputDefinition,
-)
+from django_analyses.models.input.definitions.input_definition import \
+    InputDefinition
 from django_analyses.models.pipeline.node import Node
 from django_analyses.tasks import execute_node
 from django_mri.models.scan import Scan
diff --git a/django_mri/analysis/automation/recon_all/__init__.py b/django_mri/analysis/automation/recon_all/__init__.py
index 9810dd00..d746b555 100644
--- a/django_mri/analysis/automation/recon_all/__init__.py
+++ b/django_mri/analysis/automation/recon_all/__init__.py
@@ -1,6 +1,5 @@
-from django_mri.analysis.automation.recon_all.recon_all_results import (
-    ReconAllResults,
-)
+from django_mri.analysis.automation.recon_all.recon_all_results import \
+    ReconAllResults
 from django_mri.analysis.automation.recon_all.stats import ReconAllStats
 
 # flake8: noqa: F401
diff --git a/django_mri/analysis/automation/recon_all/recon_all_results.py b/django_mri/analysis/automation/recon_all/recon_all_results.py
index 9fce26ef..035e5a47 100644
--- a/django_mri/analysis/automation/recon_all/recon_all_results.py
+++ b/django_mri/analysis/automation/recon_all/recon_all_results.py
@@ -2,6 +2,7 @@
 from typing import List, Union
 
 import pandas as pd
+
 from django_mri.analysis.automation.recon_all.stats import ReconAllStats
 
 
diff --git a/django_mri/analysis/automation/recon_all/utils.py b/django_mri/analysis/automation/recon_all/utils.py
index 701f4f9f..904c84b7 100644
--- a/django_mri/analysis/automation/recon_all/utils.py
+++ b/django_mri/analysis/automation/recon_all/utils.py
@@ -7,10 +7,10 @@
 import numpy as np
 import pandas as pd
 import seaborn as sns
+
 from django_analyses.models.analysis_version import AnalysisVersion
-from django_analyses.models.input.definitions.input_definition import (
-    InputDefinition,
-)
+from django_analyses.models.input.definitions.input_definition import \
+    InputDefinition
 from django_analyses.models.pipeline.node import Node
 from django_analyses.models.run import Run
 from django_mri.analysis.automation.recon_all import messages
diff --git a/django_mri/analysis/interfaces/dmriprep/__init__.py b/django_mri/analysis/interfaces/dmriprep/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/django_mri/analysis/interfaces/dmriprep/dmriprep.py b/django_mri/analysis/interfaces/dmriprep/dmriprep.py
new file mode 100644
index 00000000..983fca3f
--- /dev/null
+++ b/django_mri/analysis/interfaces/dmriprep/dmriprep.py
@@ -0,0 +1,298 @@
+"""
+Definition of the :class:`DmriPrep` interface.
+"""
+import os
+from pathlib import Path
+from typing import Iterable, Tuple
+
+import bids
+from django.conf import settings
+from dwiprep.dwiprep import DmriPrepManager
+
+from django_mri.analysis.interfaces.dmriprep.utils import (
+    OUTPUTS, THE_BASE_BIDS_IDENTIFIERS, THE_BASE_SMRIPREP_KWARGS)
+from django_mri.analysis.interfaces.fmriprep.messages import (
+    FS_LICENSE_MISSING, RUN_FAILURE)
+from django_mri.analysis.interfaces.fmriprep.utils import FREESURFER_HOME
+
+bids.config.set_option("extension_initial_dot", True)
+
+
+class DmriPrep:
+    """
+    An interface for the *dwiprep* preprocessing pipeline.
+
+    References
+    ----------
+    * dmriprep_
+
+    .. _dmriprep:
+       https://github.com/GalBenZvi/dwiprep
+    """
+
+    #: Expected outputs.
+    OUTPUTS = OUTPUTS
+
+    #: Default FreeSurfer home directory.
+    DEFAULT_FREESURFER_HOME: Path = Path(FREESURFER_HOME)
+
+    #: DmriPrep output pattern.
+    DMRIPREP_OUTPUT_PATTERN: str = (
+        "{main_dir}/**/{sub_dir}/sub-{subject_id}_{session_id}_{output_id}"
+    )
+
+    #: FreeSurfer output pattern.
+    FS_OUTPUT_PATTERN: str = "{main_dir}/**/*{output_id}"
+
+    #: Session results pattern.
+    SESSION_PATTERN: str = "dmriprep/sub-{subject_id}/ses-*"
+
+    __version__ = None
+
+    def __init__(
+        self,
+        bids_identifiers: dict = None,
+        smriprep_kwargs: dict = None,
+        **kwargs,
+    ):
+        """
+        Initializes a new :class:`DmriPrep` interface instance.
+        """
+        (
+            self.bids_directory,
+            self.analysis_root,
+        ) = self.set_input_and_output_roots()
+        self.destination = self.analysis_root / kwargs.pop("destination")
+        self.bids_identifiers = (
+            bids_identifiers or THE_BASE_BIDS_IDENTIFIERS.copy()
+        )
+        self.smriprep_kwargs = (
+            smriprep_kwargs or THE_BASE_SMRIPREP_KWARGS.copy()
+        )
+        self.configuration = kwargs
+
+    def set_input_and_output_roots(self) -> Tuple[Path, Path]:
+        """
+        Sets the input and output directories to be mounted by singularity
+
+        Returns
+        -------
+        Tuple[Path, Path]
+            Paths to input and output directories, accordingly
+        """
+        from django_mri.utils import get_mri_root
+
+        mri_root = get_mri_root()
+        return mri_root / "rawdata", mri_root.parent / "analysis"
+
+    def find_fs_license(self) -> Path:
+        """
+        Returns the provided or located FreeSurfer license path.
+
+        Returns
+        -------
+        Path
+            Path to FreeSurfer license file
+
+        Raises
+        ------
+        FileNotFoundError
+            No FreeSurfer license file could be found
+        """
+        try:
+            return self.configuration.pop("fs-license-file")
+        except KeyError:
+            fs_home = os.getenv(
+                "FREESURFER_HOME", self.DEFAULT_FREESURFER_HOME
+            )
+            license_file = Path(fs_home) / "license.txt"
+            if license_file.exists():
+                return license_file
+            else:
+                raise FileNotFoundError(FS_LICENSE_MISSING)
+
+    def set_configuration_by_keys(self):
+        """
+        Builds command for fmriprep CLI (via singularity) based on user's
+        specifications.
+
+        Returns
+        -------
+        str
+            CLI-compatible command
+        """
+        key_command = ""
+        for key, value in self.configuration.items():
+            key_addition = f" --{key}"
+            if isinstance(value, list):
+                for val in value:
+                    key_addition += f" {val}"
+            elif key in self.FLAGS and value:
+                pass
+            else:
+                key_addition += f" {value}"
+            key_command += key_addition
+        return key_command
+
+    def generate_fs_outputs(
+        self, main_dir: str, output_id: str
+    ) -> Iterable[Path]:
+        """
+        Generate FreeSurfer output paths.
+
+        Parameters
+        ----------
+        main_dir : str
+            Main output directory
+        output_id : str
+            Output file name pattern
+
+        Yields
+        -------
+        Path
+            Output paths
+        """
+        pattern = self.FS_OUTPUT_PATTERN.format(
+            main_dir=main_dir, output_id=output_id
+        )
+        return self.destination.rglob(pattern)
+
+    def generate_dmriprep_outputs(
+        self,
+        main_dir: str,
+        sub_dir: str,
+        subject_id: str,
+        session_id: str,
+        output_id: str,
+    ) -> Iterable[Path]:
+        """
+        Generate fmriprep output paths.
+
+        Parameters
+        ----------
+        main_dir : str
+            Main output directory
+        sub_dir : str
+            Results sub-directory name
+        subject_id : str
+            String subject ID
+        session_id : str
+            String session ID
+        output_id : str
+            Output file name pattern
+
+        Yields
+        -------
+        Path
+            Output paths
+        """
+        pattern = self.DMRIPREP_OUTPUT_PATTERN.format(
+            main_dir=main_dir,
+            sub_dir=sub_dir,
+            subject_id=subject_id,
+            session_id=session_id,
+            output_id=output_id,
+        )
+        return self.destination.rglob(pattern)
+
+    def find_output(
+        self, partial_output: str, subject_id: str, session_id: str
+    ):
+        """
+        uses the destination and some default dictionary to locate specific
+        output files of *fmriprep*.
+
+        Parameters
+        ----------
+        partial_output : str
+            A string that identifies a specific output
+        subject_id : str
+            Subject string ID
+        session_id : str
+            Session string ID
+        """
+        main_dir, sub_dir, output_id = self.OUTPUTS.get(partial_output)
+        if main_dir == "freesurfer":
+            outputs = list(self.generate_fs_outputs(main_dir, output_id))
+        elif main_dir == "dmriprep":
+            outputs = list(
+                self.generate_dmriprep_outputs(
+                    main_dir, sub_dir, subject_id, session_id, output_id
+                )
+            )
+        # if len(outputs) == 1:
+        #     return str(outputs[0])
+        # elif len(outputs) > 1:
+        if "native" in partial_output:
+            return [str(f) for f in outputs if ("MNI" not in f.name)]
+        return [str(f) for f in outputs]
+
+    def generate_output_dict(self) -> dict:
+        """
+        Generates a dictionary of the expected output file paths by key.
+
+        Returns
+        -------
+        dict
+            Output files by key
+        """
+        output_dict = {}
+        subject_ids = self.configuration.get("participant_label")
+        for subject_id in subject_ids:
+            output_dict[subject_id] = {}
+            # session_pattern = self.SESSION_PATTERN.format(
+            #     subject_id=subject_id
+            # )
+            for key in self.OUTPUTS:
+                output_dict[subject_id][key] = self.find_output(
+                    key, subject_id, "*"
+                )
+        if len(output_dict) == 1:
+            return output_dict.get(subject_id)
+        return output_dict
+
+    def init_dmriprep_instance(self) -> DmriPrepManager:
+        """
+        Initiates a *DmriPrepMangager* instance to build preprocessing workflow.
+
+        Returns
+        -------
+        DmriPrep
+            An instanciated *DmriPrepManager*
+        """
+        particpant_label = self.configuration.get("participant_label")
+        dmriprep = DmriPrepManager(
+            bids_dir=self.bids_directory,
+            destination=self.destination,
+            participant_label=particpant_label,
+            smriprep_kwargs=self.smriprep_kwargs,
+            **self.bids_identifiers,
+        )
+        return dmriprep
+
+    def run(self) -> dict:
+        """
+        Runs *dmriprep* with the provided *bids_dir* as input.
+        If *destination* is not specified, output files will be created within
+        *bids_dir*\'s parent directory.
+
+        Returns
+        -------
+        dict
+            Dictionary with keys and values corresponding to descriptions and
+            files of *dmriprep*\'s outputs accordingly
+
+        Raises
+        ------
+        RuntimeError
+            In case of failed execution, raises an appropriate error
+        """
+        manager = self.init_dmriprep_instance()
+        workflows = manager.preprocess_subjects()
+        for pariticipant_label, workflow in workflows.items():
+            workflow.run()
+        return self.generate_output_dict()
+
+
+class DmriPrep010(DmriPrep):
+    __version__ = "0.1.0"
diff --git a/django_mri/analysis/interfaces/dmriprep/messages.py b/django_mri/analysis/interfaces/dmriprep/messages.py
new file mode 100644
index 00000000..4d228448
--- /dev/null
+++ b/django_mri/analysis/interfaces/dmriprep/messages.py
@@ -0,0 +1,12 @@
+"""
+Messages for the
+:class:`~django_mri.analysis.interfaces.fmriprep.fmriprep.FmriPrep` interface.
+"""
+
+#: FreeSurfer license could not be found.
+FS_LICENSE_MISSING: str = "FreeSurfer license file could not be found!\nPlease either provide the 'fs-license-file' argument to the interface, or make sure $FREESURFER_HOME is set and the license is found within it."
+
+#: Run failure.
+RUN_FAILURE: str = "Failed to run fmriprep!\nExecuted command:\t{command}\nRaised exception:\t{exception}"
+
+# flake8: noqa: E501
diff --git a/django_mri/analysis/interfaces/dmriprep/utils.py b/django_mri/analysis/interfaces/dmriprep/utils.py
new file mode 100644
index 00000000..856fb314
--- /dev/null
+++ b/django_mri/analysis/interfaces/dmriprep/utils.py
@@ -0,0 +1,184 @@
+"""
+Utilities for the
+:class:`~django_mri.analysis.interfaces.dmriprep.dmriprep.DmriPrep` interface.
+"""
+from niworkflows.utils.spaces import Reference, SpatialReferences
+
+#: TheBase-specific KWARGS
+THE_BASE_BIDS_IDENTIFIERS = dict(
+    dwi_identifier={"direction": "ap"},
+    fmap_identifier={"acquisition": "dwi"},
+    t1w_identifier={"ceagent": "corrected"},
+    t2w_identifier={"ceagent": "corrected"},
+)
+
+THE_BASE_SMRIPREP_KWARGS = dict(
+    freesurfer=True,
+    hires=True,
+    longitudinal=False,
+    omp_nthreads=1,
+    skull_strip_mode="force",
+    skull_strip_template=Reference("OASIS30ANTs"),
+    spaces=SpatialReferences(
+        spaces=["MNI152NLin2009cAsym", "fsaverage5", "anat"]
+    ),
+)
+
+#: Outputs
+OUTPUTS = {
+    # Anatomicals
+    "native_T1w": ["dmriprep", "anat", "desc-preproc_T1w.nii.gz"],
+    "native_brain_mask": ["dmriprep", "anat", "desc-brain_mask.nii.gz"],
+    "native_parcellation": ["dmriprep", "anat", "*dseg.nii.gz"],
+    "native_csf": ["dmriprep", "anat", "label-CSF_probseg.nii.gz"],
+    "native_gm": ["dmriprep", "anat", "label-GM_probseg.nii.gz"],
+    "native_wm": ["dmriprep", "anat", "label-WM_probseg.nii.gz"],
+    "standard_T1w": [
+        "dmriprep",
+        "anat",
+        "space-MNI152NLin2009cAsym_desc-preproc_T1w.nii.gz",
+    ],
+    "standard_brain_mask": [
+        "dmriprep",
+        "anat",
+        "space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz",
+    ],
+    "standard_parcellation": [
+        "dmriprep",
+        "anat",
+        "space-MNI152NLin2009cAsym_dseg.nii.gz",
+    ],
+    "standard_csf": [
+        "dmriprep",
+        "anat",
+        "space-MNI152NLin2009cAsym_label-CSF_probseg.nii.gz",
+    ],
+    "standard_gm": [
+        "dmriprep",
+        "anat",
+        "space-MNI152NLin2009cAsym_label-GM_probseg.nii.gz",
+    ],
+    "standard_wm": [
+        "dmriprep",
+        "anat",
+        "space-MNI152NLin2009cAsym_label-WM_probseg.nii.gz",
+    ],
+    "native_to_mni_transform": [
+        "dmriprep",
+        "anat",
+        "from-T1w_to-MNI152NLin2009cAsym_mode-image_xfm.h5",
+    ],
+    "mni_to_native_transform": [
+        "dmriprep",
+        "anat",
+        "from-MNI152NLin2009cAsym_to-T1w_mode-image_xfm.h5",
+    ],
+    "native_to_fsnative_transform": [
+        "dmriprep",
+        "anat",
+        "from-T1w_to-fsnative_mode-image_xfm.txt",
+    ],
+    "fsnative_to_native_transform": [
+        "dmriprep",
+        "anat",
+        "from-fsnative_to-T1w_mode-image_xfm.txt",
+    ],
+    "smoothwm": ["dmriprep", "anat", "hemi-*_smoothwm.surf.gii"],
+    "pial": ["dmriprep", "anat", "hemi-*_pial.surf.gii"],
+    "midthickness": ["dmriprep", "anat", "hemi-*_midthickness.surf.gii"],
+    "inflated": ["dmriprep", "anat", "hemi-*_inflated.surf.gii"],
+    # dmri
+    "native_preproc_dwi_nii": [
+        "dmriprep",
+        "dwi",
+        "space-orig_desc-preproc_dwi.nii.gz",
+    ],
+    "native_preproc_dwi_json": [
+        "dmriprep",
+        "dwi",
+        "space-orig_desc-preproc_dwi.json",
+    ],
+    "native_preproc_dwi_bvec": [
+        "dmriprep",
+        "dwi",
+        "space-orig_desc-preproc_dwi.bvec",
+    ],
+    "native_preproc_dwi_bval": [
+        "dmriprep",
+        "dwi",
+        "space-orig_desc-preproc_dwi.bval",
+    ],
+    "native_preproc_epi_ref_file": [
+        "dmriprep",
+        "dwi",
+        "space-orig_desc-preproc_epiref.nii.gz",
+    ],
+    "native_preproc_epiref_json": [
+        "dmriprep",
+        "dwi",
+        "space-orig_desc-preproc_epiref.json",
+    ],
+    "coreg_preproc_dwi_nii": [
+        "dmriprep",
+        "dwi",
+        "space-anat_desc-preproc_dwi.nii.gz",
+    ],
+    "coreg_preproc_epiref_nii": [
+        "dmriprep",
+        "dwi",
+        "space-anat_desc-preproc_epiref.nii.gz",
+    ],
+    "native_to_anat_transform": [
+        "dmriprep",
+        "dwi",
+        "from-epiref_to-T1w_mode-image_xfm.txt",
+    ],
+    "anat_to_native_transform": [
+        "dmriprep",
+        "dwi",
+        "from-epiref_to-T1w_mode-image_xfm.txt",
+    ],
+    "phasediff_fmap_nii": [
+        "dmriprep",
+        "fmap",
+        "desc-phasediff_fieldmap.nii.gz",
+    ],
+    "phasediff_fmap_json": [
+        "dmriprep",
+        "fmap",
+        "desc-phasediff_fieldmap.json",
+    ],
+    "native_fa": ["dmriprep", "tensor", "space-orig_fa.nii.gz",],
+    "native_adc": ["dmriprep", "tensor", "space-orig_adc.nii.gz",],
+    "native_ad": ["dmriprep", "tensor", "space-orig_ad.nii.gz",],
+    "native_rd": ["dmriprep", "tensor", "space-orig_rd.nii.gz",],
+    "native_cl": ["dmriprep", "tensor", "space-orig_cl.nii.gz",],
+    "native_cp": ["dmriprep", "tensor", "space-orig_cp.nii.gz",],
+    "native_cs": ["dmriprep", "tensor", "space-orig_cs.nii.gz",],
+    "native_evec": ["dmriprep", "tensor", "space-orig_evec.nii.gz",],
+    "native_eval": ["dmriprep", "tensor", "space-orig_eval.nii.gz",],
+    "coreg_fa": ["dmriprep", "tensor", "space-anat_fa.nii.gz",],
+    "coreg_adc": ["dmriprep", "tensor", "space-anat_adc.nii.gz",],
+    "coreg_ad": ["dmriprep", "tensor", "space-anat_ad.nii.gz",],
+    "coreg_rd": ["dmriprep", "tensor", "space-anat_rd.nii.gz",],
+    "coreg_cl": ["dmriprep", "tensor", "space-anat_cl.nii.gz",],
+    "coreg_cp": ["dmriprep", "tensor", "space-anat_cp.nii.gz",],
+    "coreg_cs": ["dmriprep", "tensor", "space-anat_cs.nii.gz",],
+    "coreg_evec": ["dmriprep", "tensor", "space-anat_evec.nii.gz",],
+    "coreg_eval": ["dmriprep", "tensor", "space-anat_eval.nii.gz",],
+    # Freesurfer
+    "freesurfer_T1": ["freesurfer", "mri", "T1.mgz"],
+    "freesurfer_rawavg": ["freesurfer", "mri", "rawavg.mgz"],
+    "freesurfer_orig": ["freesurfer", "mri", "orig.mgz"],
+    "freesurfer_nu": ["freesurfer", "mri", "nu.mgz"],
+    "freesurfer_norm": ["freesurfer", "mri", "norm.mgz"],
+    "freesurfer_aseg": ["freesurfer", "mri", "aseg.mgz"],
+    "freesurfer_aseg_stats": ["freesurfer", "stats", "aseg.stats"],
+    "freesurfer_brain": ["freesurfer", "mri", "brain.mgz"],
+    "freesurfer_brainmask": ["freesurfer", "mri", "brainmask.mgz"],
+    "freesurfer_filled": ["freesurfer", "mri", "filled.mgz"],
+    "freesurfer_wm": ["freesurfer", "mri", "wm.mgz"],
+    "freesurfer_wmparc": ["freesurfer", "mri", "wmparc.mgz"],
+    "freesurfer_wmparc_stats": ["freesurfer", "stats", "wmparc.stats"],
+    "freesurfer_BA_stats": ["freesurfer", "stats", ".BA_exvivo*.stats"],
+}
diff --git a/django_mri/analysis/interfaces/fmriprep/fmriprep.py b/django_mri/analysis/interfaces/fmriprep/fmriprep.py
index f8aaa9ed..581e9d3c 100644
--- a/django_mri/analysis/interfaces/fmriprep/fmriprep.py
+++ b/django_mri/analysis/interfaces/fmriprep/fmriprep.py
@@ -6,16 +6,12 @@
 from typing import Iterable, Tuple
 
 from django.conf import settings
+
 from django_mri.analysis.interfaces.fmriprep.messages import (
-    FS_LICENSE_MISSING,
-    RUN_FAILURE,
-)
-from django_mri.analysis.interfaces.fmriprep.utils import (
-    COMMAND,
-    FLAGS,
-    FREESURFER_HOME,
-    OUTPUTS,
-)
+    FS_LICENSE_MISSING, RUN_FAILURE)
+from django_mri.analysis.interfaces.fmriprep.utils import (COMMAND, FLAGS,
+                                                           FREESURFER_HOME,
+                                                           OUTPUTS)
 
 
 class FmriPrep:
diff --git a/django_mri/analysis/interfaces/yalab/intensity_correction.py b/django_mri/analysis/interfaces/yalab/intensity_correction.py
index 6f0617be..e077177b 100644
--- a/django_mri/analysis/interfaces/yalab/intensity_correction.py
+++ b/django_mri/analysis/interfaces/yalab/intensity_correction.py
@@ -2,9 +2,10 @@
 
 import matplotlib.pyplot as plt
 import numpy as np
-from django_mri.analysis.utils import get_mni
 from skimage.exposure import match_histograms
 
+from django_mri.analysis.utils import get_mni
+
 
 class IntensityCorrection:
     STEPS = "saturate_extremes", "stretch_histogram"
diff --git a/django_mri/analysis/interfaces/yalab/mutual_information_score.py b/django_mri/analysis/interfaces/yalab/mutual_information_score.py
index 30d16d0d..7e191493 100644
--- a/django_mri/analysis/interfaces/yalab/mutual_information_score.py
+++ b/django_mri/analysis/interfaces/yalab/mutual_information_score.py
@@ -8,15 +8,14 @@
 import nibabel as nib
 import numpy as np
 import pandas as pd
-
 # from dask.dataframe import from_pandas
 from django.db.models import QuerySet
-from django_mri.analysis.interfaces.yalab import messages
-from django_mri.analysis.interfaces.yalab.utils import (
-    get_cat12_segmentation_node,
-)
 from sklearn.metrics import mutual_info_score
 
+from django_mri.analysis.interfaces.yalab import messages
+from django_mri.analysis.interfaces.yalab.utils import \
+    get_cat12_segmentation_node
+
 SECONDS_IN_DAY = 60 * 60 * 24
 
 
diff --git a/django_mri/analysis/mri_interfaces.py b/django_mri/analysis/mri_interfaces.py
index 1accb825..4f511561 100644
--- a/django_mri/analysis/mri_interfaces.py
+++ b/django_mri/analysis/mri_interfaces.py
@@ -14,51 +14,33 @@
 .. _Simplified Analysis Integration Example:
    https://django-analyses.readthedocs.io/en/latest/user_guide/analysis_integration/simplified_example.html
 """
-from django_mri.analysis.interfaces.fmriprep.fmriprep import (
-    FmriPrep2021,
-    FmriPrep2022,
-    FmriPrep2023,
-    FmriPrep2024,
-    FmriPrep2025,
-)
+from nipype.interfaces.freesurfer import ReconAll
+from nipype.interfaces.fsl import (BET, FLIRT, FNIRT, SUSAN, ApplyTOPUP,
+                                   BinaryMaths, Eddy, ExtractROI, MeanImage,
+                                   Merge, Reorient2Std, RobustFOV)
+from nipype.interfaces.mrtrix3 import (ConstrainedSphericalDeconvolution,
+                                       DWIBiasCorrect, DWIDenoise, Generate5tt,
+                                       MRDeGibbs, ResponseSD)
+
+from django_mri.analysis.interfaces.dmriprep.dmriprep import DmriPrep010
+from django_mri.analysis.interfaces.fmriprep.fmriprep import (FmriPrep2021,
+                                                              FmriPrep2022,
+                                                              FmriPrep2023,
+                                                              FmriPrep2024,
+                                                              FmriPrep2025)
 from django_mri.analysis.interfaces.fsl.fast import FastWrapper
 from django_mri.analysis.interfaces.fsl.fsl_anat import FslAnat
 from django_mri.analysis.interfaces.fsl.topup import TopupWrapper
-from django_mri.analysis.interfaces.matlab.spm.cat12.segmentation import (
-    Segmentation as Cat12Segmentation,
-)
+from django_mri.analysis.interfaces.matlab.spm.cat12.segmentation import \
+    Segmentation as Cat12Segmentation
 from django_mri.analysis.interfaces.mrtrix3.dwi2tensor import Dwi2Tensor
 from django_mri.analysis.interfaces.mrtrix3.dwifslpreproc import DwiFslPreproc
 from django_mri.analysis.interfaces.mrtrix3.dwigradcheck import DwiGradCheck
 from django_mri.analysis.interfaces.mrtrix3.mrcat import MRCat
 from django_mri.analysis.interfaces.mrtrix3.mrconvert import MRConvert
 from django_mri.analysis.interfaces.mrtrix3.tensor2metric import Tensor2metric
-from django_mri.analysis.interfaces.yalab.mutual_information_score import (
-    MutualInformationScore,
-)
-from nipype.interfaces.freesurfer import ReconAll
-from nipype.interfaces.fsl import (
-    BET,
-    FLIRT,
-    FNIRT,
-    SUSAN,
-    ApplyTOPUP,
-    BinaryMaths,
-    Eddy,
-    ExtractROI,
-    MeanImage,
-    Merge,
-    Reorient2Std,
-    RobustFOV,
-)
-from nipype.interfaces.mrtrix3 import (
-    ConstrainedSphericalDeconvolution,
-    DWIBiasCorrect,
-    DWIDenoise,
-    Generate5tt,
-    MRDeGibbs,
-    ResponseSD,
-)
+from django_mri.analysis.interfaces.yalab.mutual_information_score import \
+    MutualInformationScore
 
 #: A dictionary that should be imported in the project's settings and included
 #: within the *ANALYSIS_INTERFACES* setting.
@@ -102,4 +84,5 @@
         FmriPrep2024.__version__: FmriPrep2024,
         FmriPrep2025.__version__: FmriPrep2025,
     },
+    "dMRIPrep": {DmriPrep010.__version__: DmriPrep010},
 }
diff --git a/django_mri/analysis/specifications/dmriprep/__init__.py b/django_mri/analysis/specifications/dmriprep/__init__.py
new file mode 100644
index 00000000..5e049317
--- /dev/null
+++ b/django_mri/analysis/specifications/dmriprep/__init__.py
@@ -0,0 +1,6 @@
+"""
+Input and output specification dictionaries for dMRIPrep_ analyses.
+
+.. _dMRIPrep:
+   https://github.com/GalBenZvi/dwiprep/
+"""
diff --git a/django_mri/analysis/specifications/dmriprep/dmriprep.py b/django_mri/analysis/specifications/dmriprep/dmriprep.py
new file mode 100644
index 00000000..6be2f570
--- /dev/null
+++ b/django_mri/analysis/specifications/dmriprep/dmriprep.py
@@ -0,0 +1,539 @@
+"""
+Input and output specification dictionaries for FreeSurfer's recon_all_ script.
+
+.. _recon_all:
+   https://surfer.nmr.mgh.harvard.edu/fswiki/recon-all
+"""
+
+from django.conf import settings
+from traits.trait_types import String
+
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      DirectoryInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
+from django_analyses.models.output.definitions import (FileOutputDefinition,
+                                                       ListOutputDefinition)
+
+#: *dmriprep* input specification.
+DMRIPREP_INPUT_SPECIFICATION = {
+    "destination": {
+        "type": StringInputDefinition,
+        "dynamic_default": "{run_id}",
+        "required": True,
+        "description": "Path to output directory",
+    },
+    ### Options to handle performance ###
+    "bids_validate": {
+        "type": BooleanInputDefinition,
+        "description": "assume the input dataset is BIDS compliant and skip the validation",  # noqa: E501
+        "default": True,
+    },
+    "participant_label": {
+        "type": ListInputDefinition,
+        "element_type": "STR",
+        "required": True,
+        "description": "a space delimited list of participant identifiers or a single identifier (the sub- prefix can be removed)",  # noqa: E501
+        "is_configuration": False,
+    },
+    ### Specific options for FreeSurfer preprocessing ###
+    "fs_subjects_dir": {
+        "type": DirectoryInputDefinition,
+        "description": "Path to existing FreeSurfer subjects directory to reuse.",
+    },
+    "work_dir": {
+        "type": DirectoryInputDefinition,
+        "description": "path where intermediate results should be stored",
+    },
+}
+#: *dMRIprep* output specification.
+DMRIPREP_OUTPUT_SPECIFICATION = {
+    # fmriprep
+    # native
+    # anat/*desc-preproc_T1w.nii.gz
+    "native_T1w": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed anatomical image in native space.",
+    },
+    # anat/*desc-brain_mask.nii.gz
+    "native_brain_mask": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed anatomical brain mask in native space.",
+    },
+    # anat/*dseg.nii.gz
+    "native_parcellation": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed anatomical brain parcellation in native space.",
+    },
+    # anat/*CSF_probseg.nii.gz
+    "native_csf": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "CSF mask in native space.",
+    },
+    # anat/*GM_probseg.nii.gz
+    "native_gm": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "GM mask in native space.",
+    },
+    # anat/*WM_probseg.nii.gz
+    "native_wm": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "WM mask in native space.",
+    },
+    ## standard
+    # anat/*desc-preproc_T1w.nii.gz
+    "standard_T1w": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed anatomical image in standard space.",
+    },
+    # anat/*desc-brain_mask.nii.gz
+    "standard_brain_mask": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed anatomical brain mask in standard space.",
+    },
+    # anat/*dseg.nii.gz
+    "standard_parcellation": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed anatomical brain parcellation in standard space.",
+    },
+    # anat/*CSF_probseg.nii.gz
+    "standard_csf": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "CSF mask in standard space.",
+    },
+    # anat/*GM_probseg.nii.gz
+    "standard_gm": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "GM mask in standard space.",
+    },
+    # anat/*WM_probseg.nii.gz
+    "standard_wm": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "WM mask in standard space.",
+    },
+    # anat/*from-T1wto-MNI..._mode-image_xfm.h5
+    "native_to_mni_transform": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Transformation file from native to standard space.",
+    },
+    # anat/*from-MNI...to-T1w_mode-image_xfm.h5
+    "mni_to_native_transform": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Transformation file from standard to native space.",
+    },
+    # anat/*from-fsnative...to-T1w_mode-image_xfm.txt
+    "native_to_fsnative_transform": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Transformation file from native to freesurfer's standard space.",
+    },
+    # anat/*from-fsnative...to-T1w_mode-image_xfm.txt
+    "fsnative_to_native_transform": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Transformation file from freesurfer's  standard to native space.",
+    },
+    ## surfaces
+    # anat/*smoothwm.surf.gii
+    "smoothwm": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Smoothed original surface meshes.",
+    },
+    # anat/*pial.surf.gii
+    "pial": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Gray matter/pia mater surface meshes.",
+    },
+    # anat/*midthickness.surf.gii
+    "midthickness": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Graymid/midthickness surface meshes.",
+    },
+    # anat/*inflated.surf.gii
+    "inflated": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Inflated surface meshes.",
+    },
+    ## diffusion
+    # native
+    # preproc
+    "native_preproc_dwi_nii": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed dMRI NIfTI series in native space.",
+    },
+    "native_preproc_dwi_json": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed dMRI's json.",
+    },
+    "native_preproc_dwi_bvec": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed dMRI's .bvec.",
+    },
+    "native_preproc_dwi_bval": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed dMRI's .bval.",
+    },
+    # epi reference
+    "native_preproc_epi_ref_nii": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed single volume (EPI reference) NIfTI file.",
+    },
+    "native_preproc_epiref_json": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed EPI-ref's json.",
+    },
+    # Coreg
+    "coreg_preproc_dwi_nii": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed dMRI NIfTI series in anatomical space.",
+    },
+    "coreg_preproc_epiref_nii": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Preprocessed single volume EPI reference NIfTI in anatomical space.",
+    },
+    # Transforms
+    "native_to_anat_transform": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "dMRI-to-anatomical transformation matrix.",
+    },
+    "anat_to_native_transform": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Anatomical-to-dMRI transformation matrix.",
+    },
+    # phasediff
+    "phasediff_fmap_nii": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Phase-opposite NIfTI file.",
+    },
+    "phasediff_fmap_json": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Phase-opposite json file.",
+    },
+    # native tensor-derived metrics
+    "native_fa": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived Fractional Anisotropy (FA) in native dMRI space.",
+    },
+    "native_adc": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived Apperent Diffusion Coefficient (ADC) in native dMRI space.",
+    },
+    "native_ad": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived Axial Diffusivity (AD) in native dMRI space.",
+    },
+    "native_rd": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived Radial Diffusivity (RD) in native dMRI space.",
+    },
+    "native_cl": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived linearity metric in native dMRI space.",
+    },
+    "native_cp": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived planarity metric in native dMRI space.",
+    },
+    "native_cs": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived sphericiry metric in native dMRI space.",
+    },
+    "native_evec": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived eigenvector(s) in native dMRI space.",
+    },
+    "native_eval": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived eigenvalue(s) in native dMRI space.",
+    },
+    # coregistered tensor-derived metrics
+    "coreg_fa": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived Fractional Anisotropy (FA) in anatomical space.",
+    },
+    "coreg_adc": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived Apperent Diffusion Coefficient (ADC) in anatomical space.",
+    },
+    "coreg_ad": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived Axial Diffusivity (AD) in anatomical space.",
+    },
+    "coreg_rd": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived Radial Diffusivity (RD) in anatomical space.",
+    },
+    "coreg_cl": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived linearity metric in anatomical space.",
+    },
+    "coreg_cp": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived planarity metric in anatomical space.",
+    },
+    "coreg_cs": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived sphericiry metric in anatomical space.",
+    },
+    "coreg_evec": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived eigenvector(s) in anatomical space.",
+    },
+    "coreg_eval": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Tensor-derived eigenvalue(s) in anatomical space.",
+    },
+    # freesurfer/
+    # mri/T1.mgz
+    "freesurfer_T1": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Intensity normalized whole-head volume.",
+    },
+    # mri/rawavg.mgz
+    "freesurfer_rawavg": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "An average volume of the raw input data (if there is only one input volume, they will be identical). This volume is unconformed (i.e. to 256^3, 1mm isotropic)",  # noqa: E501
+    },
+    # mri/orig.mgz
+    "freesurfer_orig": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "A conformed (i.e. to 256^3, 1mm isotropic) average volume of the raw input data.",
+    },
+    # mri/nu.mgz
+    "freesurfer_nu": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "This is an intensity normalized volume generated after correcting for non-uniformity in conformed raw average (saved as 'mri/orig.mgz'). If there are any errors in later steps, it sometimes helps to check if the intensity values don't look normal in this file. If the values are too high, then scaling down the intensity a little bit and re-running recon-all usually corrects that error. In some cases, this scaling down can also be done for the orig.mgz volume.",  # noqa: E501
+    },
+    # mri/norm.mgz
+    "freesurfer_norm": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Normalized skull-stripped volume.",
+    },
+    # mri/aseg.mgz
+    "freesurfer_aseg": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Volumetric map of regions from automatic segmentation.",
+    },
+    # stats/aseg.stats
+    "freesurfer_aseg_stats": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Automated segmentation statistics file.",
+    },
+    # mri/brain.mgz
+    "freesurfer_brain": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Intensity normalized brain-only volume.",
+    },
+    # mri/brainmask.mgz
+    "freesurfer_brainmask": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Skull-stripped (brain-only) volume.",
+    },
+    # mri/filled.mgz
+    "freesurfer_filled": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Subcortical mass volume.",
+    },
+    # mri/wm.mgz
+    "freesurfer_wm": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Segmented white-matter volume.",
+    },
+    # mri/wmparc.mgz
+    "freesurfer_wmparc": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Aparc parcellation projected into subcortical white matter.",
+    },
+    # mri/wmparc_stats.mgz
+    "freesurfer_wmparc_stats": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "White matter parcellation statistics file.",
+    },
+    "freesurfer_BA_stats": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Brodmann Area statistics files.",
+    },
+    "freesurfer_annot": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Surface annotation files.",
+    },
+    "freesurfer_aparc_a2009s_stats": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Aparc a2009s parcellation statistics files.",
+    },
+    "freesurfer_aparc_aseg": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Aparc parcellation projected into aseg volume.",
+    },
+    "freesurfer_aparc_stats": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Aparc parcellation statistics files.",
+    },
+    "freesurfer_area_pial": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Mean area of triangles each vertex on the pial surface is associated with.",
+    },
+    "freesurfer_avg_curv": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Average atlas curvature, sampled to subject.",
+    },
+    "freesurfer_curv": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Maps of surface curvature.",
+    },
+    "freesurfer_curv_pial": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Curvature of pial surface.",
+    },
+    "freesurfer_curv_stats": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Curvature statistics files.",
+    },
+    "freesurfer_entorhinal_exvivo_stats": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Entorhinal exvivo statistics files.",
+    },
+    "freesurfer_graymid": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Graymid/midthickness surface meshes.",
+    },
+    "freesurfer_inflated": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Inflated surface meshes.",
+    },
+    "freesurfer_jacobian_white": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Distortion required to register to spherical atlas.",
+    },
+    "freesurfer_label": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Volume and surface label files.",
+    },
+    "freesurfer_pial": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Gray matter/pia mater surface meshes.",
+    },
+    "freesurfer_ribbon": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Volumetric maps of cortical ribbons.",
+    },
+    "freesurfer_smoothwm": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Smoothed original surface meshes.",
+    },
+    "freesurfer_sphere": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Spherical surface meshes.",
+    },
+    "freesurfer_sphere_reg": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Spherical registration file.",
+    },
+    "freesurfer_sulc": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Surface maps of sulcal depth.",
+    },
+    "freesurfer_thickness": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Surface maps of cortical thickness.",
+    },
+    "freesurfer_volume": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "Surface maps of cortical volume.",
+    },
+    "freesurfer_white": {
+        "type": ListOutputDefinition,
+        "element_type": "FIL",
+        "description": "White/gray matter surface meshes.",
+    },
+}
+
+
+# flake8: noqa: E501
diff --git a/django_mri/analysis/specifications/fmriprep/fmriprep.py b/django_mri/analysis/specifications/fmriprep/fmriprep.py
index 852ecfd9..69628512 100644
--- a/django_mri/analysis/specifications/fmriprep/fmriprep.py
+++ b/django_mri/analysis/specifications/fmriprep/fmriprep.py
@@ -6,21 +6,17 @@
 """
 
 from django.conf import settings
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    DirectoryInputDefinition,
-    FileInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-    FloatInputDefinition,
-)
-from django_analyses.models.output.definitions import (
-    FileOutputDefinition,
-    ListOutputDefinition,
-)
 from traits.trait_types import String
 
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      DirectoryInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
+from django_analyses.models.output.definitions import (FileOutputDefinition,
+                                                       ListOutputDefinition)
 
 #: *fmriprep* input specification.
 FMRIPREP_INPUT_SPECIFICATION = {
diff --git a/django_mri/analysis/specifications/freesurfer/recon_all.py b/django_mri/analysis/specifications/freesurfer/recon_all.py
index 8603a88e..f789b86b 100644
--- a/django_mri/analysis/specifications/freesurfer/recon_all.py
+++ b/django_mri/analysis/specifications/freesurfer/recon_all.py
@@ -6,18 +6,15 @@
 """
 
 from django.conf import settings
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    DirectoryInputDefinition,
-    FileInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
-from django_analyses.models.output.definitions import (
-    FileOutputDefinition,
-    ListOutputDefinition,
-)
+
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      DirectoryInputDefinition,
+                                                      FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
+from django_analyses.models.output.definitions import (FileOutputDefinition,
+                                                       ListOutputDefinition)
 
 #: *recon_all* input specification.
 RECON_ALL_INPUT_SPECIFICATION = {
diff --git a/django_mri/analysis/specifications/fsl/apply_topup.py b/django_mri/analysis/specifications/fsl/apply_topup.py
index 08eb254a..ca5643c2 100644
--- a/django_mri/analysis/specifications/fsl/apply_topup.py
+++ b/django_mri/analysis/specifications/fsl/apply_topup.py
@@ -16,11 +16,9 @@
    https://nipype.readthedocs.io/en/1.1.7/interfaces/generated/interfaces.fsl/epi.html#applytopup
 """
 
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *applytopup* input specification.
diff --git a/django_mri/analysis/specifications/fsl/bet.py b/django_mri/analysis/specifications/fsl/bet.py
index b2068983..92f2dfe1 100644
--- a/django_mri/analysis/specifications/fsl/bet.py
+++ b/django_mri/analysis/specifications/fsl/bet.py
@@ -16,14 +16,12 @@
 """
 
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    FloatInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *BET* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/binary_maths.py b/django_mri/analysis/specifications/fsl/binary_maths.py
index 4f244494..c789cc19 100644
--- a/django_mri/analysis/specifications/fsl/binary_maths.py
+++ b/django_mri/analysis/specifications/fsl/binary_maths.py
@@ -8,12 +8,10 @@
    https://nipype.readthedocs.io/en/latest/api/generated/nipype.interfaces.fsl.maths.html#binarymaths
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    FloatInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *BinaryMaths* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/eddy.py b/django_mri/analysis/specifications/fsl/eddy.py
index cfd8595e..3fdafe70 100644
--- a/django_mri/analysis/specifications/fsl/eddy.py
+++ b/django_mri/analysis/specifications/fsl/eddy.py
@@ -5,13 +5,11 @@
    https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/eddy
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    FloatInputDefinition,
-    IntegerInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *eddy* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/flirt.py b/django_mri/analysis/specifications/fsl/flirt.py
index 67d86cbd..e3206121 100644
--- a/django_mri/analysis/specifications/fsl/flirt.py
+++ b/django_mri/analysis/specifications/fsl/flirt.py
@@ -5,14 +5,12 @@
    https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FLIRT
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    FloatInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *FLIRT* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/fnirt.py b/django_mri/analysis/specifications/fsl/fnirt.py
index b14c8979..75ce37c4 100644
--- a/django_mri/analysis/specifications/fsl/fnirt.py
+++ b/django_mri/analysis/specifications/fsl/fnirt.py
@@ -5,14 +5,12 @@
    https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FNIRT
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    FloatInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *FNIRT* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/fsl_anat.py b/django_mri/analysis/specifications/fsl/fsl_anat.py
index 3afd5e32..ab39105f 100644
--- a/django_mri/analysis/specifications/fsl/fsl_anat.py
+++ b/django_mri/analysis/specifications/fsl/fsl_anat.py
@@ -5,24 +5,18 @@
    https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/fsl_anat
 """
 
-from django_analyses.models.input.definitions.boolean_input_definition import (
-    BooleanInputDefinition,
-)
-from django_analyses.models.input.definitions.directory_input_definition import (
-    DirectoryInputDefinition,
-)
-from django_analyses.models.input.definitions.file_input_definition import (
-    FileInputDefinition,
-)
-from django_analyses.models.input.definitions.float_input_definition import (
-    FloatInputDefinition,
-)
-from django_analyses.models.input.definitions.string_input_definition import (
-    StringInputDefinition,
-)
-from django_analyses.models.output.definitions.file_output_definition import (
-    FileOutputDefinition,
-)
+from django_analyses.models.input.definitions.boolean_input_definition import \
+    BooleanInputDefinition
+from django_analyses.models.input.definitions.directory_input_definition import \
+    DirectoryInputDefinition
+from django_analyses.models.input.definitions.file_input_definition import \
+    FileInputDefinition
+from django_analyses.models.input.definitions.float_input_definition import \
+    FloatInputDefinition
+from django_analyses.models.input.definitions.string_input_definition import \
+    StringInputDefinition
+from django_analyses.models.output.definitions.file_output_definition import \
+    FileOutputDefinition
 
 #: *fsl_anat* input specification dictionary.
 FSL_ANAT_INPUT_SPECIFICATION = {
diff --git a/django_mri/analysis/specifications/fsl/fslmerge.py b/django_mri/analysis/specifications/fsl/fslmerge.py
index 7993c88f..b00a5a85 100644
--- a/django_mri/analysis/specifications/fsl/fslmerge.py
+++ b/django_mri/analysis/specifications/fsl/fslmerge.py
@@ -5,11 +5,9 @@
    https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/fslmerge
 """
 
-from django_analyses.models.input.definitions import (
-    FloatInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FloatInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *fslmerge* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/fslroi.py b/django_mri/analysis/specifications/fsl/fslroi.py
index 4f06fccc..0cb0670d 100644
--- a/django_mri/analysis/specifications/fsl/fslroi.py
+++ b/django_mri/analysis/specifications/fsl/fslroi.py
@@ -5,13 +5,11 @@
    https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/fslroi
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *fslroi* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/mean_image.py b/django_mri/analysis/specifications/fsl/mean_image.py
index 2fa30508..f4bb607a 100644
--- a/django_mri/analysis/specifications/fsl/mean_image.py
+++ b/django_mri/analysis/specifications/fsl/mean_image.py
@@ -8,11 +8,9 @@
    https://nipype.readthedocs.io/en/latest/api/generated/nipype.interfaces.fsl.maths.html#meanimage
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *MeanImage* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/reorient2std.py b/django_mri/analysis/specifications/fsl/reorient2std.py
index 1bc84a6d..c99281af 100644
--- a/django_mri/analysis/specifications/fsl/reorient2std.py
+++ b/django_mri/analysis/specifications/fsl/reorient2std.py
@@ -8,10 +8,8 @@
    https://nipype.readthedocs.io/en/latest/api/generated/nipype.interfaces.fsl.utils.html#reorient2std
 """
 
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *Reorient2Std* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/robustfov.py b/django_mri/analysis/specifications/fsl/robustfov.py
index f5e76b7e..97314bbb 100644
--- a/django_mri/analysis/specifications/fsl/robustfov.py
+++ b/django_mri/analysis/specifications/fsl/robustfov.py
@@ -6,11 +6,9 @@
    https://nipype.readthedocs.io/en/latest/api/generated/nipype.interfaces.fsl.utils.html#robustfov
 """
 
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    IntegerInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *RobustFOV* input specification dictionary.
diff --git a/django_mri/analysis/specifications/fsl/susan.py b/django_mri/analysis/specifications/fsl/susan.py
index b8a53273..47965151 100644
--- a/django_mri/analysis/specifications/fsl/susan.py
+++ b/django_mri/analysis/specifications/fsl/susan.py
@@ -6,13 +6,11 @@
 """
 
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    FloatInputDefinition,
-    IntegerInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *SUSAN* input specification dictionary.
diff --git a/django_mri/analysis/specifications/mrtrix3/bias_correct.py b/django_mri/analysis/specifications/mrtrix3/bias_correct.py
index f8d90abd..bc7a5a05 100644
--- a/django_mri/analysis/specifications/mrtrix3/bias_correct.py
+++ b/django_mri/analysis/specifications/mrtrix3/bias_correct.py
@@ -16,12 +16,10 @@
    https://nipype.readthedocs.io/en/1.4.1/api/generated/nipype.interfaces.mrtrix3.preprocess.html#dwibiascorrect
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    FileInputDefinition,
-    IntegerInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *DWIBiasCorrect* input specification dictionary.
diff --git a/django_mri/analysis/specifications/mrtrix3/degibbs.py b/django_mri/analysis/specifications/mrtrix3/degibbs.py
index fedc2285..45a55547 100644
--- a/django_mri/analysis/specifications/mrtrix3/degibbs.py
+++ b/django_mri/analysis/specifications/mrtrix3/degibbs.py
@@ -15,12 +15,10 @@
    https://nipype.readthedocs.io/en/1.4.1/api/generated/nipype.interfaces.mrtrix3.preprocess.html#mrdegibbs
 """
 
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *MRDeGibbs* input specification.
diff --git a/django_mri/analysis/specifications/mrtrix3/dwifslpreproc.py b/django_mri/analysis/specifications/mrtrix3/dwifslpreproc.py
index e6c62247..943a0a76 100644
--- a/django_mri/analysis/specifications/mrtrix3/dwifslpreproc.py
+++ b/django_mri/analysis/specifications/mrtrix3/dwifslpreproc.py
@@ -14,15 +14,13 @@
    https://mrtrix.readthedocs.io/en/latest/reference/commands/dwifslpreproc.html
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    DirectoryInputDefinition,
-    FileInputDefinition,
-    FloatInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      DirectoryInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *DwiFslPreproc* input specification dictionary.
diff --git a/django_mri/analysis/specifications/mrtrix3/dwigradcheck.py b/django_mri/analysis/specifications/mrtrix3/dwigradcheck.py
index 937977f4..ab8e1b34 100644
--- a/django_mri/analysis/specifications/mrtrix3/dwigradcheck.py
+++ b/django_mri/analysis/specifications/mrtrix3/dwigradcheck.py
@@ -9,12 +9,10 @@
    https://mrtrix.readthedocs.io/en/latest/reference/commands/dwigradcheck.html
 """
 
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *dwigradcheck* input specification dictionary.
diff --git a/django_mri/analysis/specifications/mrtrix3/estimate_fod.py b/django_mri/analysis/specifications/mrtrix3/estimate_fod.py
index bf403ea1..3144368f 100644
--- a/django_mri/analysis/specifications/mrtrix3/estimate_fod.py
+++ b/django_mri/analysis/specifications/mrtrix3/estimate_fod.py
@@ -14,12 +14,10 @@
 .. _nipype.interfaces.mrtrix3.preprocess.ConstrainedSphericalDeconvolution:
     https://nipype.readthedocs.io/en/latest/api/generated/nipype.interfaces.mrtrix3.reconst.html#constrainedsphericaldeconvolution
 """
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 DWI2FOD_INPUT_SPECIFICATION = {
diff --git a/django_mri/analysis/specifications/mrtrix3/estimate_response.py b/django_mri/analysis/specifications/mrtrix3/estimate_response.py
index 8ae4aa8a..fec4fff8 100644
--- a/django_mri/analysis/specifications/mrtrix3/estimate_response.py
+++ b/django_mri/analysis/specifications/mrtrix3/estimate_response.py
@@ -14,12 +14,10 @@
 .. _nipype.interfaces.mrtrix3.preprocess.ConstrainedSphericalDeconvolution:
     https://nipype.readthedocs.io/en/latest/api/generated/nipype.interfaces.mrtrix3.preprocess.html#responsesd
 """
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 DWI2RESPONSE_INPUT_SPECIFICATION = {
diff --git a/django_mri/analysis/specifications/mrtrix3/generate_5tt.py b/django_mri/analysis/specifications/mrtrix3/generate_5tt.py
index 8eb85e9a..9946f953 100644
--- a/django_mri/analysis/specifications/mrtrix3/generate_5tt.py
+++ b/django_mri/analysis/specifications/mrtrix3/generate_5tt.py
@@ -14,11 +14,9 @@
 .. _nipype.interfaces.mrtrix3.preprocess.ConstrainedSphericalDeconvolution:
     https://nipype.readthedocs.io/en/latest/api/generated/nipype.interfaces.mrtrix3.utils.html#generate5tt
 """
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    IntegerInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 GENERATE_5TT_INPUT_SPECIFICATION = {
diff --git a/django_mri/analysis/specifications/mrtrix3/mrcat.py b/django_mri/analysis/specifications/mrtrix3/mrcat.py
index e8185a61..416c9ce6 100644
--- a/django_mri/analysis/specifications/mrtrix3/mrcat.py
+++ b/django_mri/analysis/specifications/mrtrix3/mrcat.py
@@ -10,11 +10,9 @@
    https://mrtrix.readthedocs.io/en/latest/reference/commands/mrcat.html
 """
 
-from django_analyses.models.input.definitions import (
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *MRCat* input specification dictionary.
diff --git a/django_mri/analysis/specifications/mrtrix3/mrconvert.py b/django_mri/analysis/specifications/mrtrix3/mrconvert.py
index 329ff997..52b64db6 100644
--- a/django_mri/analysis/specifications/mrtrix3/mrconvert.py
+++ b/django_mri/analysis/specifications/mrtrix3/mrconvert.py
@@ -15,12 +15,10 @@
    https://nipype.readthedocs.io/en/1.5.0/api/generated/nipype.interfaces.mrtrix3.utils.html#mrconvert
 """
 
-from django_analyses.models.input.definitions import (
-    FileInputDefinition,
-    IntegerInputDefinition,
-    ListInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (FileInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      ListInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: *MRConvert* input specification dictionary.
diff --git a/django_mri/analysis/specifications/spm/cat12/segmentation.py b/django_mri/analysis/specifications/spm/cat12/segmentation.py
index 4380cb5f..18565278 100644
--- a/django_mri/analysis/specifications/spm/cat12/segmentation.py
+++ b/django_mri/analysis/specifications/spm/cat12/segmentation.py
@@ -8,14 +8,12 @@
 
 """
 
-from django_analyses.models.input.definitions import (
-    BooleanInputDefinition,
-    DirectoryInputDefinition,
-    FileInputDefinition,
-    FloatInputDefinition,
-    IntegerInputDefinition,
-    StringInputDefinition,
-)
+from django_analyses.models.input.definitions import (BooleanInputDefinition,
+                                                      DirectoryInputDefinition,
+                                                      FileInputDefinition,
+                                                      FloatInputDefinition,
+                                                      IntegerInputDefinition,
+                                                      StringInputDefinition)
 from django_analyses.models.output.definitions import FileOutputDefinition
 
 #: CAT12 segmentation interface input specification dictionary.
diff --git a/django_mri/analysis/visualizers/cat_segmentation.py b/django_mri/analysis/visualizers/cat_segmentation.py
index 311d8291..abc0376c 100644
--- a/django_mri/analysis/visualizers/cat_segmentation.py
+++ b/django_mri/analysis/visualizers/cat_segmentation.py
@@ -2,9 +2,10 @@
 
 import nibabel as nib
 import numpy as np
+from nilearn.plotting import view_img
+
 from django_analyses.models.run import Run
 from django_mri.analysis.visualizers.segmentation import SegmentationVisualizer
-from nilearn.plotting import view_img
 
 
 class CatSegmentationVisualizer(SegmentationVisualizer):
diff --git a/django_mri/filters/irb_approval_filter.py b/django_mri/filters/irb_approval_filter.py
index 03e7fc7f..8b5a2c79 100644
--- a/django_mri/filters/irb_approval_filter.py
+++ b/django_mri/filters/irb_approval_filter.py
@@ -3,6 +3,7 @@
 """
 
 from django_filters import rest_framework as filters
+
 from django_mri.filters.utils import LOOKUP_CHOICES
 from django_mri.models.irb_approval import IrbApproval
 
diff --git a/django_mri/filters/scan_filter.py b/django_mri/filters/scan_filter.py
index 0c6b9a72..fa553d62 100644
--- a/django_mri/filters/scan_filter.py
+++ b/django_mri/filters/scan_filter.py
@@ -1,8 +1,9 @@
 """
 Definition of the :class:`ScanFilter` class.
 """
-from django_dicom.models.utils.sequence_type import SEQUENCE_TYPE_CHOICES
 from django_filters import rest_framework as filters
+
+from django_dicom.models.utils.sequence_type import SEQUENCE_TYPE_CHOICES
 from django_mri.filters.utils import LOOKUP_CHOICES, NumberInFilter
 from django_mri.models.scan import Scan
 from django_mri.utils.utils import get_group_model
diff --git a/django_mri/filters/session_filter.py b/django_mri/filters/session_filter.py
index ca1e7951..db42e4d5 100644
--- a/django_mri/filters/session_filter.py
+++ b/django_mri/filters/session_filter.py
@@ -5,6 +5,7 @@
 
 from django.db.models import Q, QuerySet
 from django_filters import rest_framework as filters
+
 from django_mri.filters.scan_filter import NumberInFilter
 from django_mri.filters.utils import LOOKUP_CHOICES
 from django_mri.models.session import Session
diff --git a/django_mri/migrations/0001_initial.py b/django_mri/migrations/0001_initial.py
index f5931957..416c4ba8 100644
--- a/django_mri/migrations/0001_initial.py
+++ b/django_mri/migrations/0001_initial.py
@@ -4,10 +4,11 @@
 import django.core.validators
 import django.db.models.deletion
 import django_extensions.db.fields
-import django_mri.models.fields
 from django.conf import settings
 from django.db import migrations, models
 
+import django_mri.models.fields
+
 
 class Migration(migrations.Migration):
 
diff --git a/django_mri/migrations/0002_auto_20200714_0504.py b/django_mri/migrations/0002_auto_20200714_0504.py
index 4961ceb7..3376c138 100644
--- a/django_mri/migrations/0002_auto_20200714_0504.py
+++ b/django_mri/migrations/0002_auto_20200714_0504.py
@@ -3,9 +3,10 @@
 import django.db.models.deletion
 import django.utils.timezone
 import django_extensions.db.fields
-import django_mri.models.fields
 from django.db import migrations, models
 
+import django_mri.models.fields
+
 
 class Migration(migrations.Migration):
 
diff --git a/django_mri/migrations/0007_migrate_subject_to_session.py b/django_mri/migrations/0007_migrate_subject_to_session.py
index edadc513..f88a9735 100644
--- a/django_mri/migrations/0007_migrate_subject_to_session.py
+++ b/django_mri/migrations/0007_migrate_subject_to_session.py
@@ -3,6 +3,7 @@
 
 from dicom_parser.header import Header as DicomHeader
 from django.db import IntegrityError, migrations
+
 from django_mri.utils.utils import get_subject_model
 
 
diff --git a/django_mri/migrations/0012_auto_20201125_1733.py b/django_mri/migrations/0012_auto_20201125_1733.py
index 50777421..26603bca 100644
--- a/django_mri/migrations/0012_auto_20201125_1733.py
+++ b/django_mri/migrations/0012_auto_20201125_1733.py
@@ -1,8 +1,9 @@
 # Generated by Django 3.1.3 on 2020-11-25 15:33
 
-import django_mri.utils.utils
 from django.db import migrations, models
 
+import django_mri.utils.utils
+
 
 class Migration(migrations.Migration):
 
diff --git a/django_mri/migrations/0018_auto_20210420_1606.py b/django_mri/migrations/0018_auto_20210420_1606.py
index 36da931c..544f2b80 100644
--- a/django_mri/migrations/0018_auto_20210420_1606.py
+++ b/django_mri/migrations/0018_auto_20210420_1606.py
@@ -1,7 +1,7 @@
 # Generated by Django 3.1.3 on 2021-04-20 13:06
 
-from django.db import migrations, models
 import django.db.models.deletion
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
diff --git a/django_mri/models/__init__.py b/django_mri/models/__init__.py
index 26eeeb82..25e30df2 100644
--- a/django_mri/models/__init__.py
+++ b/django_mri/models/__init__.py
@@ -7,17 +7,15 @@
 
 from django_mri.models.data_directory import DataDirectory
 from django_mri.models.inputs.nifti_input import NiftiInput
-from django_mri.models.inputs.nifti_input_definition import (
-    NiftiInputDefinition,
-)
+from django_mri.models.inputs.nifti_input_definition import \
+    NiftiInputDefinition
 from django_mri.models.inputs.scan_input import ScanInput
 from django_mri.models.inputs.scan_input_definition import ScanInputDefinition
 from django_mri.models.irb_approval import IrbApproval
 from django_mri.models.nifti import NIfTI
 from django_mri.models.outputs.nifti_output import NiftiOutput
-from django_mri.models.outputs.nifti_output_definition import (
-    NiftiOutputDefinition,
-)
+from django_mri.models.outputs.nifti_output_definition import \
+    NiftiOutputDefinition
 from django_mri.models.scan import Scan
 from django_mri.models.session import Session
 
diff --git a/django_mri/models/data_directory.py b/django_mri/models/data_directory.py
index 8c518607..e18bb10d 100644
--- a/django_mri/models/data_directory.py
+++ b/django_mri/models/data_directory.py
@@ -6,6 +6,7 @@
 from django.db import models
 from django.urls import reverse
 from django_extensions.db.models import TimeStampedModel, TitleDescriptionModel
+
 from django_mri.models.scan import Scan
 from django_mri.utils.utils import get_data_share_root
 
diff --git a/django_mri/models/inputs/nifti_input.py b/django_mri/models/inputs/nifti_input.py
index c5fcd415..96e6edc0 100644
--- a/django_mri/models/inputs/nifti_input.py
+++ b/django_mri/models/inputs/nifti_input.py
@@ -1,4 +1,5 @@
 from django.db import models
+
 from django_analyses.models.input.input import Input
 
 
diff --git a/django_mri/models/inputs/scan_input.py b/django_mri/models/inputs/scan_input.py
index fc0ef7a9..c12217df 100644
--- a/django_mri/models/inputs/scan_input.py
+++ b/django_mri/models/inputs/scan_input.py
@@ -1,4 +1,5 @@
 from django.db import models
+
 from django_analyses.models.input.input import Input
 
 
diff --git a/django_mri/models/managers/scan.py b/django_mri/models/managers/scan.py
index a88e8b62..a2d16b27 100644
--- a/django_mri/models/managers/scan.py
+++ b/django_mri/models/managers/scan.py
@@ -7,9 +7,10 @@
 from typing import Iterable, Union
 
 from django.db.models import QuerySet
+from tqdm import tqdm
+
 from django_dicom.models.image import Image as DicomImage
 from django_mri.utils.scan_type import ScanType
-from tqdm import tqdm
 
 
 class ScanQuerySet(QuerySet):
diff --git a/django_mri/models/managers/session.py b/django_mri/models/managers/session.py
index bcf68a33..e21f6832 100644
--- a/django_mri/models/managers/session.py
+++ b/django_mri/models/managers/session.py
@@ -5,6 +5,7 @@
 from bokeh.plotting import Figure
 from django.db.models import Count
 from django.db.models.query import QuerySet
+
 from django_mri.plots.session import plot_measurement_by_month
 
 #: Session fields to include in an exported DataFrame.
diff --git a/django_mri/models/nifti.py b/django_mri/models/nifti.py
index abf33fc8..5c109724 100644
--- a/django_mri/models/nifti.py
+++ b/django_mri/models/nifti.py
@@ -11,6 +11,8 @@
 from django.db import IntegrityError, models
 from django_analyses.models.input import FileInput, ListInput
 from django_extensions.db.models import TimeStampedModel
+
+from django_analyses.models.input import FileInput, ListInput
 from django_mri.models.messages import NIFTI_FILE_MISSING
 from django_mri.utils.compression import compress, uncompress
 
diff --git a/django_mri/models/outputs/nifti_output.py b/django_mri/models/outputs/nifti_output.py
index 012e4e97..a5c50f43 100644
--- a/django_mri/models/outputs/nifti_output.py
+++ b/django_mri/models/outputs/nifti_output.py
@@ -1,4 +1,5 @@
 from django.db import models
+
 from django_analyses.models.output.output import Output
 
 
diff --git a/django_mri/models/scan.py b/django_mri/models/scan.py
index 4426e20e..e172eebe 100644
--- a/django_mri/models/scan.py
+++ b/django_mri/models/scan.py
@@ -289,7 +289,7 @@ def compile_to_bids(self, bids_path: Path):
         """
         if self.sequence_type in ["bold", "func_sbref"]:
             self.bids_manager.fix_functional_json(bids_path)
-        if self.sequence_type in ["func_fieldmap", "dwi_fieldmap"]:
+        if self.sequence_type in ["func_fieldmap", "dwi_sbref"]:
             self.bids_manager.modify_fieldmaps(bids_path)
         self.bids_manager.set_participant_tsv_and_json(self)
 
diff --git a/django_mri/models/session.py b/django_mri/models/session.py
index cf459a7d..9390ad5b 100644
--- a/django_mri/models/session.py
+++ b/django_mri/models/session.py
@@ -6,14 +6,11 @@
 
 from django.db import models
 from django_extensions.db.models import TimeStampedModel
+
 from django_mri.models import help_text
 from django_mri.models.managers.session import SessionQuerySet
-from django_mri.utils import (
-    get_group_model,
-    get_measurement_model,
-    get_study_model,
-    get_subject_model,
-)
+from django_mri.utils import (get_group_model, get_measurement_model,
+                              get_study_model, get_subject_model)
 
 Group = get_group_model()
 MeasurementDefinition = get_measurement_model()
diff --git a/django_mri/plots/session/__init__.py b/django_mri/plots/session/__init__.py
index a13740a6..7b57ff53 100644
--- a/django_mri/plots/session/__init__.py
+++ b/django_mri/plots/session/__init__.py
@@ -2,8 +2,7 @@
 Plots to visualize :class:`~django_mri.models.sessions.Session` instances and
 querysets.
 """
-from django_mri.plots.session.measurement_distribution import (
-    plot_measurement_by_month,
-)
+from django_mri.plots.session.measurement_distribution import \
+    plot_measurement_by_month
 
 # flake8: noqa: F401
diff --git a/django_mri/plots/session/measurement_distribution.py b/django_mri/plots/session/measurement_distribution.py
index cc9f8d9f..306e9c3a 100644
--- a/django_mri/plots/session/measurement_distribution.py
+++ b/django_mri/plots/session/measurement_distribution.py
@@ -6,16 +6,9 @@
 from typing import List, Tuple
 
 import pandas as pd
-from bokeh.models import (
-    ColumnDataSource,
-    FactorRange,
-    FuncTickFormatter,
-    GlyphRenderer,
-    HoverTool,
-    Legend,
-    LinearAxis,
-    Range1d,
-)
+from bokeh.models import (ColumnDataSource, FactorRange, FuncTickFormatter,
+                          GlyphRenderer, HoverTool, Legend, LinearAxis,
+                          Range1d)
 from bokeh.palettes import Category20_20
 from bokeh.plotting import Figure, figure
 from django.db.models import QuerySet
diff --git a/django_mri/serializers/__init__.py b/django_mri/serializers/__init__.py
index 42c1e4a4..84e63b74 100644
--- a/django_mri/serializers/__init__.py
+++ b/django_mri/serializers/__init__.py
@@ -12,10 +12,8 @@
 from django_mri.serializers.irb_approval import IrbApprovalSerializer
 from django_mri.serializers.nifti import NiftiSerializer
 from django_mri.serializers.scan import ScanSerializer
-from django_mri.serializers.session import (
-    AdminSessionReadSerializer,
-    SessionReadSerializer,
-    SessionWriteSerializer,
-)
+from django_mri.serializers.session import (AdminSessionReadSerializer,
+                                            SessionReadSerializer,
+                                            SessionWriteSerializer)
 
 # flake8: noqa: F401
diff --git a/django_mri/serializers/input/nifti_input.py b/django_mri/serializers/input/nifti_input.py
index 37ad731a..951e4cc7 100644
--- a/django_mri/serializers/input/nifti_input.py
+++ b/django_mri/serializers/input/nifti_input.py
@@ -4,9 +4,10 @@
 class.
 """
 
+from rest_framework import serializers
+
 from django_mri.models.inputs.nifti_input import NiftiInput
 from django_mri.models.nifti import NIfTI
-from rest_framework import serializers
 
 
 class NiftiInputSerializer(serializers.ModelSerializer):
diff --git a/django_mri/serializers/input/nifti_input_definition.py b/django_mri/serializers/input/nifti_input_definition.py
index f6fe1a61..44ebb0e8 100644
--- a/django_mri/serializers/input/nifti_input_definition.py
+++ b/django_mri/serializers/input/nifti_input_definition.py
@@ -4,9 +4,10 @@
 class.
 """
 
+from rest_framework import serializers
+
 from django_mri.models.inputs.nifti_input_definition import \
     NiftiInputDefinition
-from rest_framework import serializers
 
 
 class NiftiInputDefinitionSerializer(serializers.ModelSerializer):
diff --git a/django_mri/serializers/input/scan_input.py b/django_mri/serializers/input/scan_input.py
index ed69d9d0..5254a23d 100644
--- a/django_mri/serializers/input/scan_input.py
+++ b/django_mri/serializers/input/scan_input.py
@@ -4,9 +4,10 @@
 class.
 """
 
+from rest_framework import serializers
+
 from django_mri.models.inputs.scan_input import ScanInput
 from django_mri.models.scan import Scan
-from rest_framework import serializers
 
 
 class ScanInputSerializer(serializers.ModelSerializer):
diff --git a/django_mri/serializers/input/scan_input_definition.py b/django_mri/serializers/input/scan_input_definition.py
index a2dbe8b7..859d33c6 100644
--- a/django_mri/serializers/input/scan_input_definition.py
+++ b/django_mri/serializers/input/scan_input_definition.py
@@ -4,9 +4,10 @@
 class.
 """
 
-from django_mri.models.inputs.scan_input_definition import ScanInputDefinition
 from rest_framework import serializers
 
+from django_mri.models.inputs.scan_input_definition import ScanInputDefinition
+
 
 class ScanInputDefinitionSerializer(serializers.ModelSerializer):
     """
diff --git a/django_mri/serializers/irb_approval.py b/django_mri/serializers/irb_approval.py
index d2f8c099..f53253b8 100644
--- a/django_mri/serializers/irb_approval.py
+++ b/django_mri/serializers/irb_approval.py
@@ -1,9 +1,10 @@
 """
 Definition of the :class:`IrbApprovalSerializer` class.
 """
-from django_mri.models.irb_approval import IrbApproval
 from rest_framework import serializers
 
+from django_mri.models.irb_approval import IrbApproval
+
 
 class IrbApprovalSerializer(serializers.HyperlinkedModelSerializer):
     """
diff --git a/django_mri/serializers/nifti.py b/django_mri/serializers/nifti.py
index 2b563a69..53a92daf 100644
--- a/django_mri/serializers/nifti.py
+++ b/django_mri/serializers/nifti.py
@@ -2,9 +2,10 @@
 Definition of the :class:`~django_mri.serializers.nifti.NiftiSerializer` class.
 """
 
-from django_mri.models import NIfTI
 from rest_framework import serializers
 
+from django_mri.models import NIfTI
+
 
 class NiftiSerializer(serializers.HyperlinkedModelSerializer):
     """
diff --git a/django_mri/serializers/output/nifti_output.py b/django_mri/serializers/output/nifti_output.py
index c54d7200..74f00094 100644
--- a/django_mri/serializers/output/nifti_output.py
+++ b/django_mri/serializers/output/nifti_output.py
@@ -4,9 +4,10 @@
 class.
 """
 
+from rest_framework import serializers
+
 from django_mri.models.nifti import NIfTI
 from django_mri.models.outputs.nifti_output import NiftiOutput
-from rest_framework import serializers
 
 
 class NiftiOutputSerializer(serializers.ModelSerializer):
diff --git a/django_mri/serializers/output/nifti_output_definition.py b/django_mri/serializers/output/nifti_output_definition.py
index fb4c6fd0..c7f88c6c 100644
--- a/django_mri/serializers/output/nifti_output_definition.py
+++ b/django_mri/serializers/output/nifti_output_definition.py
@@ -4,9 +4,10 @@
 class.
 """
 
+from rest_framework import serializers
+
 from django_mri.models.outputs.nifti_output_definition import \
     NiftiOutputDefinition
-from rest_framework import serializers
 
 
 class NiftiOutputDefinitionSerializer(serializers.ModelSerializer):
diff --git a/django_mri/serializers/scan.py b/django_mri/serializers/scan.py
index 6fff6537..60c32f12 100644
--- a/django_mri/serializers/scan.py
+++ b/django_mri/serializers/scan.py
@@ -1,13 +1,14 @@
 """
 Definition of the :class:`ScanSerializer` class.
 """
+from rest_framework import serializers
+
 from django_dicom.models import Series
 from django_mri.models.nifti import NIfTI
 from django_mri.models.scan import Scan
 from django_mri.models.session import Session
 from django_mri.serializers.utils import MiniSubjectSerializer
 from django_mri.utils.utils import get_group_model
-from rest_framework import serializers
 
 Group = get_group_model()
 
diff --git a/django_mri/serializers/session.py b/django_mri/serializers/session.py
index cee32389..d8217799 100644
--- a/django_mri/serializers/session.py
+++ b/django_mri/serializers/session.py
@@ -5,16 +5,15 @@
 from typing import Tuple
 
 from django.urls import reverse
+from rest_framework import serializers
+
 from django_mri.models.irb_approval import IrbApproval
 from django_mri.models.session import Session
 from django_mri.serializers.irb_approval import IrbApprovalSerializer
-from django_mri.serializers.utils import (
-    MiniGroupSerializer,
-    MiniMeasurementSerializer,
-    MiniSubjectSerializer,
-)
+from django_mri.serializers.utils import (MiniGroupSerializer,
+                                          MiniMeasurementSerializer,
+                                          MiniSubjectSerializer)
 from django_mri.utils import get_measurement_model, get_subject_model
-from rest_framework import serializers
 
 Measurement = get_measurement_model()
 Subject = get_subject_model()
diff --git a/django_mri/serializers/utils.py b/django_mri/serializers/utils.py
index 6a298d51..4bbbc92b 100644
--- a/django_mri/serializers/utils.py
+++ b/django_mri/serializers/utils.py
@@ -1,11 +1,8 @@
-from django_mri.utils.utils import (
-    get_group_model,
-    get_measurement_model,
-    get_study_model,
-    get_subject_model,
-)
 from rest_framework import serializers
 
+from django_mri.utils.utils import (get_group_model, get_measurement_model,
+                                    get_study_model, get_subject_model)
+
 Group = get_group_model()
 Measurement = get_measurement_model()
 Subject = get_subject_model()
diff --git a/django_mri/tasks.py b/django_mri/tasks.py
index 2589c264..0d06358f 100644
--- a/django_mri/tasks.py
+++ b/django_mri/tasks.py
@@ -2,6 +2,7 @@
 from typing import Union
 
 from celery import shared_task
+
 from django_mri.models.data_directory import DataDirectory
 from django_mri.models.scan import Scan
 
diff --git a/django_mri/utils/__init__.py b/django_mri/utils/__init__.py
index b9a0f15e..d56bc8cb 100644
--- a/django_mri/utils/__init__.py
+++ b/django_mri/utils/__init__.py
@@ -2,12 +2,7 @@
 General app utilities.
 """
 
-from django_mri.utils.utils import (
-    get_dicom_root,
-    get_group_model,
-    get_measurement_model,
-    get_mri_root,
-    get_session_by_series,
-    get_study_model,
-    get_subject_model,
-)
+from django_mri.utils.utils import (get_dicom_root, get_group_model,
+                                    get_measurement_model, get_mri_root,
+                                    get_session_by_series, get_study_model,
+                                    get_subject_model)
diff --git a/django_mri/utils/the_base.py b/django_mri/utils/the_base.py
index c1f9d014..b6b75238 100644
--- a/django_mri/utils/the_base.py
+++ b/django_mri/utils/the_base.py
@@ -1,6 +1,5 @@
 from enum import Enum
 
-
 NAME_TO_LOC = {
     "dMRI_MB4_6dirs_d15D45_PA": {
         "data_type": "dwi",
diff --git a/django_mri/utils/utils.py b/django_mri/utils/utils.py
index bfe83430..ed9c6b07 100644
--- a/django_mri/utils/utils.py
+++ b/django_mri/utils/utils.py
@@ -8,6 +8,7 @@
 from django.apps import apps
 from django.conf import settings
 from django.db.models import ObjectDoesNotExist
+
 from django_mri.apps import DjangoMriConfig
 
 #: The name of the subdirectory under MEDIA_ROOT in which MRI data will be
diff --git a/django_mri/views/irb_approval.py b/django_mri/views/irb_approval.py
index 6812dc07..f90094e6 100644
--- a/django_mri/views/irb_approval.py
+++ b/django_mri/views/irb_approval.py
@@ -1,9 +1,10 @@
+from rest_framework import viewsets
+
 from django_mri.filters.irb_approval_filter import IrbApprovalFilter
 from django_mri.models.irb_approval import IrbApproval
 from django_mri.serializers.irb_approval import IrbApprovalSerializer
 from django_mri.views.defaults import DefaultsMixin
 from django_mri.views.pagination import StandardResultsSetPagination
-from rest_framework import viewsets
 
 
 class IrbApprovalViewSet(DefaultsMixin, viewsets.ModelViewSet):
diff --git a/django_mri/views/nifti.py b/django_mri/views/nifti.py
index 1cce87df..2b0a8577 100644
--- a/django_mri/views/nifti.py
+++ b/django_mri/views/nifti.py
@@ -3,13 +3,14 @@
 from pathlib import Path
 
 from django.http import HttpResponse
+from rest_framework import viewsets
+from rest_framework.decorators import action
+from rest_framework.request import Request
+
 from django_mri.models import NIfTI
 from django_mri.serializers import NiftiSerializer
 from django_mri.views.defaults import DefaultsMixin
 from django_mri.views.pagination import StandardResultsSetPagination
-from rest_framework import viewsets
-from rest_framework.decorators import action
-from rest_framework.request import Request
 
 CONTENT_DISPOSITION = "attachment; filename={instance_id}.zip"
 ZIP_CONTENT_TYPE = "application/x-zip-compressed"
diff --git a/django_mri/views/scan.py b/django_mri/views/scan.py
index 89715fd0..71b49a61 100644
--- a/django_mri/views/scan.py
+++ b/django_mri/views/scan.py
@@ -12,6 +12,12 @@
 from django.core.exceptions import ObjectDoesNotExist
 from django.db.models.query import QuerySet
 from django.http import HttpResponse, JsonResponse
+from nilearn.plotting.html_document import HTMLDocument
+from rest_framework import status, viewsets
+from rest_framework.decorators import action
+from rest_framework.request import Request
+from rest_framework.response import Response
+
 from django_analyses.serializers.run import RunSerializer
 from django_dicom.models import Series
 from django_mri.filters.scan_filter import ScanFilter
@@ -20,11 +26,6 @@
 from django_mri.views.defaults import DefaultsMixin
 from django_mri.views.pagination import StandardResultsSetPagination
 from django_mri.views.utils import fix_bokeh_script
-from nilearn.plotting.html_document import HTMLDocument
-from rest_framework import status, viewsets
-from rest_framework.decorators import action
-from rest_framework.request import Request
-from rest_framework.response import Response
 
 HOST_NAME: str = getattr(settings, "APP_IP", "localhost")
 BOKEH_URL: str = f"http://{HOST_NAME}:5006/series_viewer"
diff --git a/django_mri/views/session.py b/django_mri/views/session.py
index bf89ab20..a6642f5e 100644
--- a/django_mri/views/session.py
+++ b/django_mri/views/session.py
@@ -7,21 +7,20 @@
 from typing import Tuple
 
 from django.http import HttpResponse
+from rest_framework import viewsets
+from rest_framework.decorators import action
+from rest_framework.request import Request
+
 from django_dicom.views.utils import CONTENT_DISPOSITION, ZIP_CONTENT_TYPE
 from django_mri.filters.session_filter import SessionFilter
 from django_mri.models.session import Session
-from django_mri.serializers import (
-    AdminSessionReadSerializer,
-    SessionReadSerializer,
-    SessionWriteSerializer,
-)
+from django_mri.serializers import (AdminSessionReadSerializer,
+                                    SessionReadSerializer,
+                                    SessionWriteSerializer)
 from django_mri.utils.utils import get_mri_root
 from django_mri.views.defaults import DefaultsMixin
 from django_mri.views.pagination import StandardResultsSetPagination
 from django_mri.views.utils import ReadWriteSerializerMixin
-from rest_framework import viewsets
-from rest_framework.decorators import action
-from rest_framework.request import Request
 
 ORDERING_FIELDS: Tuple[str] = (
     "id",
diff --git a/requirements.txt b/requirements.txt
index 474f1ac4..974471c2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,11 +10,14 @@ django-filter~=2.4
 matplotlib~=3.3
 nibabel~=3.2
 nilearn~=0.7
-nipype~=1.5
+pybids~=0.14
 numpy~=1.20
 tqdm~=4.40
 scikit-learn~=0.22
+smriprep~=0.8
 git+https://github.com/celery/django-celery-results.git@master#egg=django-celery-results
 git+https://github.com/TheLabbingProject/django_analyses.git@master#egg=django_analyses
 git+https://github.com/TheLabbingProject/django_dicom.git@master#egg=django_dicom
-git+https://github.com/open-dicom/dicom_parser.git@master#egg=dicom_parser
\ No newline at end of file
+git+https://github.com/open-dicom/dicom_parser.git@master#egg=dicom_parser
+git+https://github.com/GalBenZvi/nipype@master#egg=nipype
+git+https://github.com/GalBenZvi/dwiprep@master#egg=dwiprep


Test patch:
diff --git a/tests/factories.py b/tests/factories.py
index 4ed5795d..682f111b 100644
--- a/tests/factories.py
+++ b/tests/factories.py
@@ -8,7 +8,6 @@
 
 
 import factory
-
 from tests.models import Subject
 
 
diff --git a/tests/managers.py b/tests/managers.py
index 16e1c4cf..59eca569 100644
--- a/tests/managers.py
+++ b/tests/managers.py
@@ -4,6 +4,7 @@
 """
 
 from django.db import models
+
 from django_dicom.models import Patient
 
 
diff --git a/tests/models_tests/input/test_scan_input.py b/tests/models_tests/input/test_scan_input.py
index e51bf329..70a1b07b 100644
--- a/tests/models_tests/input/test_scan_input.py
+++ b/tests/models_tests/input/test_scan_input.py
@@ -10,8 +10,9 @@
 from django_mri.models import Scan, Session
 from django_mri.models.inputs import ScanInput, ScanInputDefinition
 from django_mri.serializers.input import ScanInputSerializer
-from django_mri.serializers.input.scan_input_definition import \
-    ScanInputDefinitionSerializer
+from django_mri.serializers.input.scan_input_definition import (
+    ScanInputDefinitionSerializer,
+)
 from rest_framework.request import Request
 from rest_framework.test import APIRequestFactory
 from tests.fixtures import SIEMENS_DWI_SERIES_PATH
diff --git a/tests/models_tests/output/test_nifti_output.py b/tests/models_tests/output/test_nifti_output.py
index 21733253..30fa8aa6 100644
--- a/tests/models_tests/output/test_nifti_output.py
+++ b/tests/models_tests/output/test_nifti_output.py
@@ -4,6 +4,11 @@
 import pytz
 from django.db.models import signals
 from django.test import TestCase
+from rest_framework.request import Request
+from rest_framework.test import APIRequestFactory
+from tests.fixtures import NIFTI_TEST_FILE_PATH, SIEMENS_DWI_SERIES_PATH
+from tests.models import Subject
+
 from django_analyses.models import AnalysisVersion, Run
 from django_dicom.models import Image, Series
 from django_mri import serializers
@@ -11,13 +16,8 @@
 from django_mri.models.outputs import NiftiOutput, NiftiOutputDefinition
 from django_mri.models.outputs.output_definitions import OutputDefinitions
 from django_mri.serializers.output import NiftiOutputSerializer
-from django_mri.serializers.output.nifti_output_definition import (
-    NiftiOutputDefinitionSerializer,
-)
-from rest_framework.request import Request
-from rest_framework.test import APIRequestFactory
-from tests.fixtures import NIFTI_TEST_FILE_PATH, SIEMENS_DWI_SERIES_PATH
-from tests.models import Subject
+from django_mri.serializers.output.nifti_output_definition import \
+    NiftiOutputDefinitionSerializer
 
 
 class NiftiOutputModelTestCase(TestCase):
diff --git a/tests/models_tests/test_nifti.py b/tests/models_tests/test_nifti.py
index 820fd139..401e54b3 100644
--- a/tests/models_tests/test_nifti.py
+++ b/tests/models_tests/test_nifti.py
@@ -6,16 +6,14 @@
 import pytz
 from django.db.models import signals
 from django.test import TestCase
+from tests.fixtures import (DICOM_MPRAGE_PATH, SIEMENS_DWI_SERIES,
+                            SIEMENS_DWI_SERIES_PATH)
+from tests.models import Subject
+
 from django_dicom.models import Image
 from django_mri.models.nifti import NIfTI
 from django_mri.models.scan import Scan
 from django_mri.models.session import Session
-from tests.fixtures import (
-    DICOM_MPRAGE_PATH,
-    SIEMENS_DWI_SERIES,
-    SIEMENS_DWI_SERIES_PATH,
-)
-from tests.models import Subject
 
 
 class NIfTIModelTestCase(TestCase):
diff --git a/tests/models_tests/test_session.py b/tests/models_tests/test_session.py
index ac6724eb..ee6a0dae 100644
--- a/tests/models_tests/test_session.py
+++ b/tests/models_tests/test_session.py
@@ -4,11 +4,12 @@
 import pytz
 from django.db.models import signals
 from django.test import TestCase
-from django_dicom.models import Image, Series
-from django_mri.models import Scan, Session
 from tests.fixtures import SIEMENS_DWI_SERIES, SIEMENS_DWI_SERIES_PATH
 from tests.models import Subject
 
+from django_dicom.models import Image, Series
+from django_mri.models import Scan, Session
+
 
 class SessionModelTestCase(TestCase):
     @classmethod
diff --git a/tests/test_analysis.py b/tests/test_analysis.py
index 9a6bf2e9..08c4c0ca 100644
--- a/tests/test_analysis.py
+++ b/tests/test_analysis.py
@@ -1,4 +1,5 @@
 from django.test import TestCase
+
 from django_analyses.models import Analysis, Pipeline
 from django_mri.analysis.analysis_definitions import analysis_definitions
 from django_mri.models.nifti import NIfTI
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 8dcff82f..2e66b1bd 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,9 +1,10 @@
 from pathlib import Path
 
-import django_mri.utils.utils as utils
 from django.conf import settings
 from django.test import TestCase
 
+import django_mri.utils.utils as utils
+
 from .models import Group, Subject
 
 
diff --git a/tests/test_views.py b/tests/test_views.py
index 958ac72d..5a6bd6f9 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -7,15 +7,15 @@
 from django.db.models import signals
 from django.test import TestCase
 from django.urls import reverse
-from django_dicom.models import Image, Series
-from django_dicom.models.utils.utils import get_group_model
-from django_mri.models import Scan, Session
 from rest_framework import status
 from rest_framework.test import APITestCase
-
 from tests.fixtures import SIEMENS_DWI_SERIES_PATH
 from tests.models import Subject
 
+from django_dicom.models import Image, Series
+from django_dicom.models.utils.utils import get_group_model
+from django_mri.models import Scan, Session
+
 User = get_user_model()
 Group = get_group_model()
 
diff --git a/tests/utils.py b/tests/utils.py
index 88432cdc..00177f3d 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -2,6 +2,7 @@
 
 import pydicom
 from django.db import models
+
 from django_dicom.models import Image
 
 
diff --git a/tests/views.py b/tests/views.py
index 21b5e25e..e77f5cfc 100644
--- a/tests/views.py
+++ b/tests/views.py
@@ -1,6 +1,7 @@
-from django_mri.views.defaults import DefaultsMixin
 from rest_framework import viewsets
 
+from django_mri.views.defaults import DefaultsMixin
+
 from .models import Group, Subject
 from .serializers import SubjectSerializer