diff --git a/README.rst b/README.rst index 116e0f9c1..06f1d7b7d 100644 --- a/README.rst +++ b/README.rst @@ -42,10 +42,10 @@ state-of-the-art interface that is robust to variations in scan acquisition protocols and that requires minimal user input, while providing easily interpretable and comprehensive error and output reporting. It performs basic processing steps (coregistration, normalization, unwarping, -noise component extraction, segmentation, skullstripping etc.) providing +noise component extraction, segmentation, skull-stripping, etc.) providing outputs that can be easily submitted to a variety of group level analyses, -including task-based or resting-state fMRI, graph theory measures, surface or -volume-based statistics, etc. +including task-based or resting-state fMRI, graph theory measures, and surface +or volume-based statistics. .. note:: @@ -71,7 +71,7 @@ This tool allows you to easily do the following: - Receive verbose output concerning the stage of preprocessing for each subject, including meaningful errors. - Automate and parallelize processing steps, which provides a significant - speed-up from typical linear, manual processing. + speed-up from manual processing or shell-scripted pipelines. More information and documentation can be found at https://fmriprep.readthedocs.io/ diff --git a/docs/_static/brainextraction.svg b/docs/_static/brainextraction.svg deleted file mode 100644 index 528a79e87..000000000 --- a/docs/_static/brainextraction.svg +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_static/brainextraction_t1.svg b/docs/_static/brainextraction_t1.svg deleted file mode 100644 index 1cc87169b..000000000 --- a/docs/_static/brainextraction_t1.svg +++ /dev/null @@ -1,1780 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/sub-01_dseg.svg b/docs/_static/sub-01_dseg.svg new file mode 100644 index 000000000..f9252bec4 --- /dev/null +++ b/docs/_static/sub-01_dseg.svg @@ -0,0 +1,1068 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/sub-01_task-balloonanalogrisktask_run-1_desc-rois_bold.svg b/docs/_static/sub-01_task-balloonanalogrisktask_run-1_desc-rois_bold.svg new file mode 100644 index 000000000..423eccbc0 --- /dev/null +++ b/docs/_static/sub-01_task-balloonanalogrisktask_run-1_desc-rois_bold.svg @@ -0,0 +1,656 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/faq.rst b/docs/faq.rst index f1149814d..ab66346c1 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -205,23 +205,23 @@ will be used. Finally, both the ``--cifti-output`` and ``--use-aroma`` arguments require ``MNI152NLin6Asym``. To do so, follow the next steps. - 1. By default, a mirror of *TemplateFlow* to store the resources will be - created in ``$HOME/.cache/templateflow``. - You can modify such a configuration with the ``TEMPLATEFLOW_HOME`` - environment variable, e.g.:: +1. By default, a mirror of *TemplateFlow* to store the resources will be + created in ``$HOME/.cache/templateflow``. + You can modify such a configuration with the ``TEMPLATEFLOW_HOME`` + environment variable, e.g.:: - $ export TEMPLATEFLOW_HOME=$HOME/.templateflow + $ export TEMPLATEFLOW_HOME=$HOME/.templateflow - 2. Install the client within your favorite Python 3 environment (this can - be done in your login-node, or in a host with Internet access, - without need for Docker/Singularity):: +2. Install the client within your favorite Python 3 environment (this can + be done in your login-node, or in a host with Internet access, + without need for Docker/Singularity):: - $ python -m pip install -U templateflow + $ python -m pip install -U templateflow - 3. Use the ``get()`` utility of the client to pull down all the templates you'll - want to use. For example:: +3. Use the ``get()`` utility of the client to pull down all the templates you'll + want to use. For example:: - $ python -c "from templateflow.api import get; get(['MNI152NLin2009cAsym', 'MNI152NLin6Asym', 'OASIS30ANTs', 'MNIPediatricAsym', 'MNIInfant'])" + $ python -c "from templateflow.api import get; get(['MNI152NLin2009cAsym', 'MNI152NLin6Asym', 'OASIS30ANTs', 'MNIPediatricAsym', 'MNIInfant'])" After getting the resources you'll need, you will just need to make sure your runtime environment is able to access the filesystem, at the location of your @@ -287,17 +287,17 @@ across sessions. When substantial changes are expected, special considerations must be taken. Some examples follow: - * Surgery: use only pre-operation sessions for the anatomical data. This will typically be done - by omitting post-operation sessions from the inputs to *fMRIPrep*. - * Developing and elderly populations: there is currently no standard way of processing these. - However, `as suggested by U. Tooley at NeuroStars.org - `__, - it is theoretically possible to leverage the *anatomical fast-track* along with the - ``--bids-filters`` option to process sessions fully independently, or grouped by some study-design - criteria. - Please check the `link - `__ - for further information on this approach. +* Surgery: use only pre-operation sessions for the anatomical data. This will typically be done + by omitting post-operation sessions from the inputs to *fMRIPrep*. +* Developing and elderly populations: there is currently no standard way of processing these. + However, `as suggested by U. Tooley at NeuroStars.org + `__, + it is theoretically possible to leverage the *anatomical fast-track* along with the + ``--bids-filters`` option to process sessions fully independently, or grouped by some study-design + criteria. + Please check the `link + `__ + for further information on this approach. How to decrease *fMRIPrep* runtime when working with large datasets? diff --git a/docs/installation.rst b/docs/installation.rst index d168d5490..249307f64 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -3,29 +3,27 @@ ------------ Installation ------------ -There are two ways to get *fMRIPrep* installed: +There are two ways to install *fMRIPrep*: -* within a `Manually Prepared Environment (Python 3.7+)`_, also known as - *bare-metal installation*; or -* using container technologies (RECOMMENDED). +* using container technologies (RECOMMENDED); or +* within a `Manually Prepared Environment (Python 3.8+)`_, also known as + *bare-metal installation*. -Once you have your *bare-metal* environment set-up (first option above), -the next step is executing the ``fmriprep`` command-line. -The ``fmriprep`` command-line options are documented in the :ref:`usage` -section. The ``fmriprep`` command-line adheres to the `BIDS-Apps recommendations for the user interface `__. -Therefore, the command-line has the following structure: -:: +Therefore, the command-line has the following structure:: $ fmriprep -On the other hand, if you chose a container infrastructure, then +The ``fmriprep`` command-line options are documented in the :ref:`usage` +section. + +The command as shown works for a *bare-metal* environment set-up (second option above). +If you choose the recommended container-based installation, then the command-line will be composed of a preamble to configure the container execution followed by the ``fmriprep`` command-line options as if you were running it on a *bare-metal* installation. -The command-line structure above is then modified as follows: -:: +The command-line structure above is then modified as follows:: $ \ @@ -44,12 +42,12 @@ or `Singularity `__ subsections. The *NiPreps* portal also containes `extended details of execution with the Docker wrapper `__. -Manually Prepared Environment (Python 3.7+) +Manually Prepared Environment (Python 3.8+) =========================================== .. warning:: - This method is not recommended! Please checkout container alternatives. + This method is not recommended! Please consider using containers. Make sure all of *fMRIPrep*'s `External Dependencies`_ are installed. These tools must be installed and their binaries available in the @@ -58,7 +56,7 @@ A relatively interpretable description of how your environment can be set-up is found in the `Dockerfile `_. As an additional installation setting, FreeSurfer requires a license file (see :ref:`fs_license`). -On a functional Python 3.7 (or above) environment with ``pip`` installed, +On a functional Python 3.8 (or above) environment with ``pip`` installed, *fMRIPrep* can be installed using the habitual command :: $ python -m pip install fmriprep @@ -70,18 +68,18 @@ Check your installation with the ``--version`` argument :: External Dependencies --------------------- -*fMRIPrep* is written using Python 3.7 (or above), and is based on +*fMRIPrep* is written using Python 3.8 (or above), and is based on nipype_. *fMRIPrep* requires some other neuroimaging software tools that are not handled by the Python's packaging system (Pypi) used to deploy the ``fmriprep`` package: -- FSL_ (version 6.0.6.2) +- FSL_ (version 6.0.5.1) - ANTs_ (version 2.3.3 - NeuroDocker build) -- AFNI_ (version Debian-23.0.00) +- AFNI_ (version 22.3.06) - `C3D `_ (version 1.3.0) -- FreeSurfer_ (version 7.2.3) +- FreeSurfer_ (version 7.3.2) - `ICA-AROMA `_ (version 0.4.5) - `bids-validator `_ (version 1.8.0) - `connectome-workbench `_ (version 1.5.0) diff --git a/docs/outputs.rst b/docs/outputs.rst index a51d65d26..f7f8e3cb8 100644 --- a/docs/outputs.rst +++ b/docs/outputs.rst @@ -33,8 +33,8 @@ upcoming `BEP 011`_ and `BEP 012`_). There are two exceptions to this principle (described in their corresponding sections below): - - ICA-AROMA's *non-aggressive* denoised outputs, and - - CompCor regressors, which are calculated after temporal high-pass filtering. + - ICA-AROMA's *non-aggressive* denoised outputs, and + - CompCor regressors, which are calculated after temporal high-pass filtering. Layout ------ @@ -61,7 +61,7 @@ records metadata recommended by the BIDS standard. This layout, now the default, may be explicitly specified with the ``--output-layout bids`` command-line option. For compatibility with versions of fMRIPrep prior to 21.0, the -`legacy layout`_ is available via ``-output-layout legacy``. +`legacy layout`_ is available via ``--output-layout legacy``. Visual Reports -------------- @@ -279,9 +279,9 @@ to perform more advanced denoising or alternative combination strategies. For example, when specifying a first-level model, you should set parameters in your software package or first-level model function accordingly (e.g., select the middle slice as reference). - Alternatively, you could manually adjust the volume onsets (e.g. as mentioned in + Alternatively, you could manually adjust the volume onsets (e.g. as mentioned in the example above from [0, 2, 4] to [1, 3, 5]) or the event onsets accordingly. - + Further information on this issue is found at `this blog post (with thanks to Russell Poldrack and Jeanette Mumford) `__. @@ -562,10 +562,10 @@ An example of these plots follows: and framewise-displacement ('FD'). At the bottom, a 'carpetplot' summarizing the BOLD series [Power2016]_. The carpet plot rows correspond to voxelwise time series, - and are separated into regions: cortical gray matter, deep - gray matter, white matter and cerebrospinal fluid, cerebellum + and are separated into regions: cortical gray matter, deep + gray matter, white matter and cerebrospinal fluid, cerebellum and the brain-edge or “crown” [Provins2022]_. - The crown corresponds to the voxels located on a + The crown corresponds to the voxels located on a closed band around the brain [Patriat2015]_. Noise components computed during each CompCor decomposition are evaluated according @@ -676,8 +676,8 @@ the following invocation:: and sensitivity of motion correction strategies for resting-state functional MRI. NeuroImage. 2018. doi:`10.1016/j.neuroimage.2017.12.073 `_ - .. [Patriat2015] Patriat R, EK Molloy, RM Birn, T. Guitchev, and A. Popov. ,Using Edge Voxel Information to - Improve Motion Regression for Rs-FMRI Connectivity Studies. Brain Connectivity. 2015. + .. [Patriat2015] Patriat R, EK Molloy, RM Birn, T. Guitchev, and A. Popov. ,Using Edge Voxel Information to + Improve Motion Regression for Rs-FMRI Connectivity Studies. Brain Connectivity. 2015. doi:`10.1089/brain.2014.0321 `_. .. [Patriat2017] Patriat R, Reynolds RC, Birn RM, An improved model of motion-related signal diff --git a/docs/spaces.rst b/docs/spaces.rst index e3dd19bb2..12a1992e8 100644 --- a/docs/spaces.rst +++ b/docs/spaces.rst @@ -80,10 +80,10 @@ Space modifiers such as ``res`` are combinatorial: ``--output-spaces MNIPediatricAsym:cohort-1:cohort-2:res-native:res-1`` will generate conversions for the following combinations: - * cohort ``1`` and "native" resolution (meaning, the original BOLD resolution), - * cohort ``1`` and resolution ``1`` of the template, - * cohort ``2`` and "native" resolution (meaning, the original BOLD resolution), and - * cohort ``2`` and resolution ``1`` of the template. +* cohort ``1`` and "native" resolution (meaning, the original BOLD resolution), +* cohort ``1`` and resolution ``1`` of the template, +* cohort ``2`` and "native" resolution (meaning, the original BOLD resolution), and +* cohort ``2`` and resolution ``1`` of the template. Please mind that the selected resolutions specified must exist within TemplateFlow. @@ -120,19 +120,19 @@ Nonstandard spaces Additionally, ``--output-spaces`` accepts identifiers of spatial references that do not generate *standardized* coordinate spaces: - * ``T1w`` or ``anat``: data are resampled into the individual's anatomical - reference generated with the T1w and T2w images available within the - BIDS structure. - * ``fsnative``: similarly to the ``anat`` space for volumetric references, - including the ``fsnative`` space will instruct *fMRIPrep* to sample the - original BOLD data onto FreeSurfer's reconstructed surfaces for this - individual. - * ``func``, ``bold``, ``run``, ``boldref`` or ``sbref`` can be used to - generate BOLD data in their original grid, after slice-timing, - head-motion, and susceptibility-distortion corrections. - These keywords are experimental, and expected to change because - **additional nonstandard spaces** are currently being discussed - `here `__. +* ``T1w`` or ``anat``: data are resampled into the individual's anatomical + reference generated with the T1w and T2w images available within the + BIDS structure. +* ``fsnative``: similarly to the ``anat`` space for volumetric references, + including the ``fsnative`` space will instruct *fMRIPrep* to sample the + original BOLD data onto FreeSurfer's reconstructed surfaces for this + individual. +* ``func``, ``bold``, ``run``, ``boldref`` or ``sbref`` can be used to + generate BOLD data in their original grid, after slice-timing, + head-motion, and susceptibility-distortion corrections. + These keywords are experimental, and expected to change because + **additional nonstandard spaces** are currently being discussed + `here `__. Modifiers are not allowed when providing nonstandard spaces. diff --git a/docs/usage.rst b/docs/usage.rst index 36893478b..942040658 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -43,7 +43,7 @@ The command-line interface of the docker wrapper ------------------------------------------------ .. argparse:: - :ref: fmriprep_docker.get_parser + :ref: fmriprep_docker.__main__.get_parser :prog: fmriprep-docker :nodefault: :nodefaultconst: @@ -212,4 +212,4 @@ following mailing list: http://mail.python.org/mailman/listinfo/neuroimaging Please add *[fmriprep]* to the subject line when posting on the mailing list. -.. include:: license.rst \ No newline at end of file +.. include:: license.rst diff --git a/docs/workflows.rst b/docs/workflows.rst index ed2053169..d30058e13 100644 --- a/docs/workflows.rst +++ b/docs/workflows.rst @@ -22,6 +22,33 @@ is presented below: with mock_config(): wf = init_single_subject_wf('01') +.. note:: + + Each node in this workflow is either a processing node or a sub-workflow. + Several conventions appear in this workflow that will be apparent throughout + fMRIPrep. + + * ``inputnode``\s are special nodes that provide the runtime-generated inputs + to a workflow. These are like function "arguments". There are corresponding + ``outputnode``\s in most other workflows, which are like function return + values. + * Workflows end with ``_wf``, and are generated by a function of the form + ``init_{workflow}_wf``. + For example, ``anat_preproc_wf`` is a sub-workflow that is generated by the + :func:`~smriprep.workflows.anatomical.init_anat_preproc_wf` (see below). + Because each task and run of functional data is processed separately, + :func:`~fmriprep.workflows.bold.base.init_func_preproc_wf` names the + resulting workflows using input parameters, resulting in + ``func_preproc_task_{task}_run_{run}_wf``. + * Datasinks begin with ``ds_``, and save files to the output directory. + This is in contrast to most nodes, which save their outputs to the working + directory. ``ds_report_`` nodes indicate that the node is saving text and + figures for generating reports, rather than processed data. + * When a name appears in parentheses, such as ``(reports)`` in ``about (reports)`` + it is the module where the interface is defined. In this case, ``about`` + is an :class:`~fmriprep.interfaces.reports.AboutSummary`, found in the + :mod:`fmriprep.interfaces.reports` module. + Preprocessing of structural MRI ------------------------------- The anatomical sub-workflow begins by constructing an average image by @@ -88,26 +115,20 @@ brain extraction workflow: wf = init_brain_extraction_wf() -An example of brain extraction is shown below: - -.. figure:: _static/brainextraction_t1.svg - - Brain extraction - - Once the brain mask is computed, FSL ``fast`` is utilized for brain tissue segmentation. -.. figure:: _static/segmentation.svg +fMRIPrep includes a single figure overlaying the brain mask (red), and tissue boundaries +(blue = gray/white; magenta = tissue/CSF): - Brain tissue segmentation. +.. figure:: _static/sub-01_dseg.svg + Brain extraction and segmentation report Finally, spatial normalization to standard spaces is performed using ANTs' ``antsRegistration`` in a multiscale, mutual-information based, nonlinear registration scheme. See :ref:`output-spaces` for information about how standard and nonstandard spaces can be set to resample the preprocessed data onto the final output spaces. - .. figure:: _static/T1MNINormalization.svg Animation showing spatial normalization of T1w onto the ``MNI152NLin2009cAsym`` template. @@ -166,14 +187,14 @@ All surface preprocessing may be disabled with the ``--fs-no-reconall`` flag. Surface processing will be skipped if the outputs already exist. In order to bypass reconstruction in *fMRIPrep*, place existing reconstructed - subjects in ``/freesurfer`` prior to the run, or specify an external - subjects directory with the ``--fs-subjects-dir`` flag. + subjects in ``/sourcedata/freesurfer`` prior to the run, or specify + an external subjects directory with the ``--fs-subjects-dir`` flag. *fMRIPrep* will perform any missing ``recon-all`` steps, but will not perform any steps whose outputs already exist. If FreeSurfer reconstruction is performed, the reconstructed subject is placed in -``/freesurfer/sub-/`` (see :ref:`fsderivs`). +``/sourcedata/freesurfer/sub-/`` (see :ref:`fsderivs`). Surface reconstruction is performed in three phases. The first phase initializes the subject with T1w and T2w (if available) @@ -219,7 +240,7 @@ converted to GIFTI_ format and adjusted to be compatible with multiple software packages, including FreeSurfer and the `Connectome Workbench`_. .. note:: - GIFTI surface outputs are aligned to the FreeSurfer T1.mgz image, which + GIFTI surface outputs are aligned to the FreeSurfer ``T1.mgz`` image, which may differ from the T1w space in some cases, to maintain compatibility with the FreeSurfer directory. Any measures sampled to the surface take into account any difference in @@ -296,9 +317,11 @@ Further, the reference is fed to the :ref:`head-motion estimation workflow ` and the :ref:`registration workflow to map BOLD series into the T1w image of the same subject `. -.. figure:: _static/brainextraction.svg +.. figure:: _static/sub-01_task-balloonanalogrisktask_run-1_desc-rois_bold.svg - Calculation of a brain mask from the BOLD series. + The red contour shows the brain mask estimated for a BOLD reference volume. + The blue and magenta contours show the tCompCor and aCompCor masks, + respectively. (See :ref:`bold_confounds`, below.) .. _bold_hmc: @@ -420,6 +443,7 @@ EPI to T1w registration The alignment between the reference :abbr:`EPI (echo-planar imaging)` image of each run and the reconstructed subject using the gray/white matter boundary (FreeSurfer's ``?h.white`` surfaces) is calculated by the ``bbregister`` routine. +See :func:`fmriprep.workflows.bold.registration.init_bbreg_wf` for further details. .. figure:: _static/EPIT1Normalization.svg @@ -428,8 +452,12 @@ of each run and the reconstructed subject using the gray/white matter boundary If FreeSurfer processing is disabled, FSL ``flirt`` is run with the :abbr:`BBR (boundary-based registration)` cost function, using the ``fast`` segmentation to establish the gray/white matter boundary. -After :abbr:`BBR (boundary-based registration)` is run, the resulting affine transform will be compared to the initial transform found by FLIRT. -Excessive deviation will result in rejecting the BBR refinement and accepting the original, affine registration. +See :func:`fmriprep.workflows.bold.registration.init_fsl_bbr_wf` for further details. + +After either :abbr:`BBR (boundary-based registration)` workflow is run, the resulting affine +transform will be compared to the initial transform found by FLIRT. +Excessive deviation will result in rejecting the BBR refinement and accepting the +original, affine registration. Resampling BOLD runs onto standard spaces ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -448,6 +476,7 @@ Resampling BOLD runs onto standard spaces spaces=SpatialReferences( spaces=[('MNI152Lin', {}), ('MNIPediatricAsym', {'cohort': '6'})], checkpoint=True), + multiecho=False, ) This sub-workflow concatenates the transforms calculated upstream (see @@ -586,3 +615,14 @@ this workflow uses the `tedana`_ `T2* workflow`_ to generate an adaptive T2* map and optimally weighted combination of all supplied single echo time series. This optimally combined time series is then carried forward for all subsequent preprocessing steps. + +References +---------- + +.. [Power2017] Power JD, Plitt M, Kundu P, Bandettini PA, Martin A (2017) Temporal interpolation alters + motion in fMRI scans: Magnitudes and consequences for artifact detection. PLOS ONE 12(9): e0182939. + doi:`10.1371/journal.pone.0182939 `_. + +.. [Brett2001] Brett M, Leff AP, Rorden C, Ashburner J (2001) Spatial Normalization of Brain Images with + Focal Lesions Using Cost Function Masking. NeuroImage 14(2) + doi:`10.006/nimg.2001.0845 `_. diff --git a/fmriprep/cli/parser.py b/fmriprep/cli/parser.py index f5054f0c2..d0530449e 100644 --- a/fmriprep/cli/parser.py +++ b/fmriprep/cli/parser.py @@ -128,19 +128,19 @@ def _slice_time_ref(value, parser): "bids_dir", action="store", type=PathExists, - help="the root folder of a BIDS valid dataset (sub-XXXXX folders should " + help="The root folder of a BIDS valid dataset (sub-XXXXX folders should " "be found at the top level in this folder).", ) parser.add_argument( "output_dir", action="store", type=Path, - help="the output path for the outcomes of preprocessing and visual " "reports", + help="The output path for the outcomes of preprocessing and visual reports", ) parser.add_argument( "analysis_level", choices=["participant"], - help='processing stage to be run, only "participant" in the case of ' + help='Processing stage to be run, only "participant" in the case of ' "fMRIPrep (see BIDS-Apps specification).", ) @@ -153,7 +153,7 @@ def _slice_time_ref(value, parser): "--skip-bids-validation", action="store_true", default=False, - help="assume the input dataset is BIDS compliant and skip the validation", + help="Assume the input dataset is BIDS compliant and skip the validation", ) g_bids.add_argument( "--participant-label", @@ -161,23 +161,23 @@ def _slice_time_ref(value, parser): action="store", nargs="+", type=_drop_sub, - help="a space delimited list of participant identifiers or a single " + help="A space delimited list of participant identifiers or a single " "identifier (the sub- prefix can be removed)", ) # Re-enable when option is actually implemented # g_bids.add_argument('-s', '--session-id', action='store', default='single_session', - # help='select a specific session to be processed') + # help='Select a specific session to be processed') # Re-enable when option is actually implemented # g_bids.add_argument('-r', '--run-id', action='store', default='single_run', - # help='select a specific run to be processed') + # help='Select a specific run to be processed') g_bids.add_argument( - "-t", "--task-id", action="store", help="select a specific task to be processed" + "-t", "--task-id", action="store", help="Select a specific task to be processed" ) g_bids.add_argument( "--echo-idx", action="store", type=int, - help="select a specific echo to be processed in a multiecho series", + help="Select a specific echo to be processed in a multiecho series", ) g_bids.add_argument( "--bids-filter-file", @@ -185,7 +185,7 @@ def _slice_time_ref(value, parser): action="store", type=BIDSFilter, metavar="FILE", - help="a JSON file describing custom BIDS input filters using PyBIDS. " + help="A JSON file describing custom BIDS input filters using PyBIDS. " "For further details, please check out " "https://fmriprep.readthedocs.io/en/%s/faq.html#" "how-do-I-select-only-certain-files-to-be-input-to-fMRIPrep" @@ -216,13 +216,13 @@ def _slice_time_ref(value, parser): dest='nprocs', action="store", type=PositiveInt, - help="maximum number of threads across all processes", + help="Maximum number of threads across all processes", ) g_perfm.add_argument( "--omp-nthreads", action="store", type=PositiveInt, - help="maximum number of threads per-process", + help="Maximum number of threads per-process", ) g_perfm.add_argument( "--mem", @@ -232,12 +232,12 @@ def _slice_time_ref(value, parser): action="store", type=_to_gb, metavar="MEMORY_MB", - help="upper bound memory limit for fMRIPrep processes", + help="Upper bound memory limit for fMRIPrep processes", ) g_perfm.add_argument( "--low-mem", action="store_true", - help="attempt to reduce memory usage (will increase disk usage " "in working directory)", + help="Attempt to reduce memory usage (will increase disk usage in working directory)", ) g_perfm.add_argument( "--use-plugin", @@ -245,20 +245,20 @@ def _slice_time_ref(value, parser): action="store", metavar="FILE", type=IsFile, - help="nipype plugin configuration file", + help="Nipype plugin configuration file", ) - g_perfm.add_argument("--anat-only", action="store_true", help="run anatomical workflows only") + g_perfm.add_argument("--anat-only", action="store_true", help="Run anatomical workflows only") g_perfm.add_argument( "--boilerplate_only", action="store_true", default=False, - help="generate boilerplate only", + help="Generate boilerplate only", ) g_perfm.add_argument( "--md-only-boilerplate", action="store_true", default=False, - help="skip generation of HTML and LaTeX formatted citation with pandoc", + help="Skip generation of HTML and LaTeX formatted citation with pandoc", ) g_perfm.add_argument( "--error-on-aroma-warnings", @@ -274,7 +274,7 @@ def _slice_time_ref(value, parser): dest="verbose_count", action="count", default=0, - help="increases log verbosity for each occurence, debug level is -vvv", + help="Increases log verbosity for each occurence, debug level is -vvv", ) g_conf = parser.add_argument_group("Workflow configuration") @@ -285,13 +285,13 @@ def _slice_time_ref(value, parser): nargs="+", default=[], choices=["fieldmaps", "slicetiming", "sbref", "t2w", "flair"], - help="ignore selected aspects of the input dataset to disable corresponding " + help="Ignore selected aspects of the input dataset to disable corresponding " "parts of the workflow (a space delimited list)", ) g_conf.add_argument( "--longitudinal", action="store_true", - help="treat dataset as longitudinal - may increase runtime", + help="Treat dataset as longitudinal - may increase runtime", ) g_conf.add_argument( "--output-spaces", @@ -375,7 +375,7 @@ def _slice_time_ref(value, parser): action="store", default=None, type=int, - help="Number of nonsteady-state volumes.", + help="Number of nonsteady-state volumes. Overrides automatic detection.", ) g_conf.add_argument( "--random-seed", @@ -392,7 +392,7 @@ def _slice_time_ref(value, parser): "--use-aroma", action="store_true", default=False, - help="add ICA_AROMA to your preprocessing stream", + help="Add ICA-AROMA to your preprocessing stream", ) g_aroma.add_argument( "--aroma-melodic-dimensionality", @@ -405,7 +405,7 @@ def _slice_time_ref(value, parser): ) # Confounds options - g_confounds = parser.add_argument_group("Specific options for estimating confounds") + g_confounds = parser.add_argument_group("Specific options for generating confounds") g_confounds.add_argument( "--return-all-components", dest="regressors_all_comps", @@ -433,7 +433,7 @@ def _slice_time_ref(value, parser): action="store", default=1.5, type=float, - help="Threshold for flagging a frame as an outlier on the basis of standardised " "DVARS", + help="Threshold for flagging a frame as an outlier on the basis of standardised DVARS", ) # ANTs options @@ -442,12 +442,13 @@ def _slice_time_ref(value, parser): "--skull-strip-template", default="OASIS30ANTs", type=Reference.from_string, - help="select a template for skull-stripping with antsBrainExtraction", + help="Select a template for skull-stripping with antsBrainExtraction " + "(OASIS30ANTs, by default)", ) g_ants.add_argument( "--skull-strip-fixed-seed", action="store_true", - help="do not use a random seed for skull-stripping - will ensure " + help="Do not use a random seed for skull-stripping - will ensure " "run-to-run replicability when used with --omp-nthreads 1 and " "matching --random-seed ", ) @@ -456,33 +457,11 @@ def _slice_time_ref(value, parser): action="store", choices=("auto", "skip", "force"), default="force", - help="determiner for T1-weighted skull stripping ('force' ensures skull " + help="Perform T1-weighted skull stripping ('force' ensures skull " "stripping, 'skip' ignores skull stripping, and 'auto' applies brain extraction " "based on the outcome of a heuristic to check whether the brain is already masked).", ) - # Fieldmap options - g_fmap = parser.add_argument_group("Specific options for handling fieldmaps") - g_fmap.add_argument( - "--fmap-bspline", - action="store_true", - default=False, - help="fit a B-Spline field using least-squares (experimental)", - ) - g_fmap.add_argument( - "--fmap-no-demean", - action="store_false", - default=True, - help="do not remove median (within mask) from fieldmap", - ) - g_fmap.add_argument( - "--topup-max-vols", - action="store", - default=5, - type=int, - help="maximum number of volumes to use with TOPUP, per-series (EPI or BOLD)", - ) - # SyN-unwarp options g_syn = parser.add_argument_group("Specific options for SyN distortion correction") g_syn.add_argument( @@ -492,7 +471,7 @@ def _slice_time_ref(value, parser): action="store", const="error", default=False, - help="EXPERIMENTAL: Use fieldmap-free distortion correction; " + help="Use fieldmap-less distortion correction based on anatomical image; " "if unable, error (default) or warn based on optional argument.", ) g_syn.add_argument( @@ -520,14 +499,14 @@ def _slice_time_ref(value, parser): "(default: OUTPUT_DIR/freesurfer)", ) - # Surface generation xor g_surfs = parser.add_argument_group("Surface preprocessing options") g_surfs.add_argument( "--no-submm-recon", action="store_false", dest="hires", - help="disable sub-millimeter (hires) reconstruction", + help="Disable sub-millimeter (hires) reconstruction", ) + # Surface generation xor g_surfs_xor = g_surfs.add_mutually_exclusive_group() g_surfs_xor.add_argument( "--cifti-output", @@ -536,7 +515,7 @@ def _slice_time_ref(value, parser): default=False, choices=("91k", "170k"), type=str, - help="output preprocessed BOLD as a CIFTI dense timeseries. " + help="Output preprocessed BOLD as a CIFTI dense timeseries. " "Optionally, the number of grayordinate can be specified " "(default is 91k, which equates to 2mm resolution)", ) @@ -544,7 +523,7 @@ def _slice_time_ref(value, parser): "--fs-no-reconall", action="store_false", dest="run_reconall", - help="disable FreeSurfer surface preprocessing.", + help="Disable FreeSurfer surface preprocessing.", ) g_other = parser.add_argument_group("Other options") @@ -564,26 +543,26 @@ def _slice_time_ref(value, parser): action="store", type=Path, default=Path("work").absolute(), - help="path where intermediate results should be stored", + help="Path where intermediate results should be stored", ) g_other.add_argument( "--clean-workdir", action="store_true", default=False, - help="Clears working directory of contents. Use of this flag is not" + help="Clears working directory of contents. Use of this flag is not " "recommended when running concurrent processes of fMRIPrep.", ) g_other.add_argument( "--resource-monitor", action="store_true", default=False, - help="enable Nipype's resource monitoring to keep track of memory and CPU usage", + help="Enable Nipype's resource monitoring to keep track of memory and CPU usage", ) g_other.add_argument( "--reports-only", action="store_true", default=False, - help="only generate reports, don't run workflows. This will only rerun report " + help="Only generate reports, don't run workflows. This will only rerun report " "aggregation, not reportlet generation for specific nodes.", ) g_other.add_argument( @@ -603,7 +582,7 @@ def _slice_time_ref(value, parser): "--stop-on-first-crash", action="store_true", default=False, - help="Force stopping on first crash, even if a work directory" " was specified.", + help="Force stopping on first crash, even if a work directory was specified.", ) g_other.add_argument( "--notrack", @@ -679,13 +658,6 @@ def parse_args(args=None, namespace=None): parser = _build_parser() opts = parser.parse_args(args, namespace) - # Deprecations - if opts.topup_max_vols: - config.loggers.cli.warning( - "--topup-max-vols input is no longer used and " - "the flag will be removed in a future release." - ) - if opts.config_file: skip = {} if opts.reports_only else {"execution": ("run_uuid",)} config.load(opts.config_file, skip=skip, init=False) diff --git a/fmriprep/cli/tests/test_parser.py b/fmriprep/cli/tests/test_parser.py index 726b8c14b..3a5de6fe6 100644 --- a/fmriprep/cli/tests/test_parser.py +++ b/fmriprep/cli/tests/test_parser.py @@ -94,7 +94,7 @@ def test_memory_arg(tmp_path, argval, gb): _fs_file = tmp_path / "license.txt" _fs_file.write_text("") - args = MIN_ARGS + ["--fs-license-file", str(_fs_file)] + ["--mem", argval] + args = [str(datapath)] + MIN_ARGS[1:] + ["--fs-license-file", str(_fs_file), "--mem", argval] opts = _build_parser().parse_args(args) assert opts.memory_gb == gb diff --git a/fmriprep/data/tests/ds000005/sub-01/func/sub-01_task-mixedgamblestask_run-01_bold.nii.gz b/fmriprep/data/tests/ds000005/sub-01/func/sub-01_task-mixedgamblestask_run-01_bold.nii.gz index 03fccb15f..026e43c51 100644 Binary files a/fmriprep/data/tests/ds000005/sub-01/func/sub-01_task-mixedgamblestask_run-01_bold.nii.gz and b/fmriprep/data/tests/ds000005/sub-01/func/sub-01_task-mixedgamblestask_run-01_bold.nii.gz differ diff --git a/fmriprep/workflows/base.py b/fmriprep/workflows/base.py index 0e42cb347..2f1a4d3d8 100644 --- a/fmriprep/workflows/base.py +++ b/fmriprep/workflows/base.py @@ -110,7 +110,7 @@ def init_fmriprep_wf(): return fmriprep_wf -def init_single_subject_wf(subject_id): +def init_single_subject_wf(subject_id: str): """ Organize the preprocessing pipeline for a single subject. diff --git a/fmriprep/workflows/bold/base.py b/fmriprep/workflows/bold/base.py index 04a085ffa..e13e2004c 100644 --- a/fmriprep/workflows/bold/base.py +++ b/fmriprep/workflows/bold/base.py @@ -201,7 +201,8 @@ def init_func_preproc_wf(bold_file, has_fieldmap=False): ) from niworkflows.interfaces.utility import DictMerge, KeySelect - nvols = nb.load(bold_file[0] if isinstance(bold_file, (list, tuple)) else bold_file).shape[3] + img = nb.load(bold_file[0] if isinstance(bold_file, (list, tuple)) else bold_file) + nvols = 1 if img.ndim < 4 else img.shape[3] if nvols <= 5 - config.execution.sloppy: config.loggers.workflow.warning( f"Too short BOLD series (<= 5 timepoints). Skipping processing of <{bold_file}>." diff --git a/fmriprep/workflows/bold/confounds.py b/fmriprep/workflows/bold/confounds.py index e5799ea40..9a4fee9b2 100644 --- a/fmriprep/workflows/bold/confounds.py +++ b/fmriprep/workflows/bold/confounds.py @@ -50,13 +50,13 @@ def init_bold_confs_wf( - mem_gb, - metadata, - regressors_all_comps, - regressors_dvars_th, - regressors_fd_th, - freesurfer=False, - name="bold_confs_wf", + mem_gb: float, + metadata: dict, + regressors_all_comps: bool, + regressors_dvars_th: float, + regressors_fd_th: float, + freesurfer: bool = False, + name: str = "bold_confs_wf", ): """ Build a workflow to generate and write out confounding signals. @@ -602,7 +602,9 @@ def _select_cols(table): return workflow -def init_carpetplot_wf(mem_gb, metadata, cifti_output, name="bold_carpet_wf"): +def init_carpetplot_wf( + mem_gb: float, metadata: dict, cifti_output: bool, name: str = "bold_carpet_wf" +): """ Build a workflow to generate *carpet* plots. @@ -740,13 +742,13 @@ def init_carpetplot_wf(mem_gb, metadata, cifti_output, name="bold_carpet_wf"): def init_ica_aroma_wf( - mem_gb, - metadata, - omp_nthreads, - aroma_melodic_dim=-200, - err_on_aroma_warn=False, - name="ica_aroma_wf", - susan_fwhm=6.0, + mem_gb: float, + metadata: dict, + omp_nthreads: int, + aroma_melodic_dim: int = -200, + err_on_aroma_warn: bool = False, + name: str = "ica_aroma_wf", + susan_fwhm: float = 6.0, ): """ Build a workflow that runs `ICA-AROMA`_. diff --git a/fmriprep/workflows/bold/hmc.py b/fmriprep/workflows/bold/hmc.py index cc9e5134c..b1de41f33 100644 --- a/fmriprep/workflows/bold/hmc.py +++ b/fmriprep/workflows/bold/hmc.py @@ -35,7 +35,7 @@ from ...config import DEFAULT_MEMORY_MIN_GB -def init_bold_hmc_wf(mem_gb, omp_nthreads, name='bold_hmc_wf'): +def init_bold_hmc_wf(mem_gb: float, omp_nthreads: int, name: str = 'bold_hmc_wf'): """ Build a workflow to estimate head-motion parameters. diff --git a/fmriprep/workflows/bold/outputs.py b/fmriprep/workflows/bold/outputs.py index f5da5fac8..1f6585c84 100644 --- a/fmriprep/workflows/bold/outputs.py +++ b/fmriprep/workflows/bold/outputs.py @@ -21,6 +21,10 @@ # https://www.nipreps.org/community/licensing/ # """Writing out derivative files.""" +from __future__ import annotations + +import typing as ty + import numpy as np from nipype.interfaces import utility as niu from nipype.pipeline import engine as pe @@ -29,8 +33,11 @@ from fmriprep.config import DEFAULT_MEMORY_MIN_GB from fmriprep.interfaces import DerivativesDataSink +if ty.TYPE_CHECKING: + from niworkflows.utils.spaces import SpatialReferences -def prepare_timing_parameters(metadata): + +def prepare_timing_parameters(metadata: dict): """Convert initial timing metadata to post-realignment timing metadata In particular, SliceTiming metadata is invalid once STC or any realignment is applied, @@ -133,14 +140,14 @@ def prepare_timing_parameters(metadata): def init_func_derivatives_wf( - bids_root, - cifti_output, - freesurfer, - all_metadata, - multiecho, - output_dir, - spaces, - use_aroma, + bids_root: str, + cifti_output: bool, + freesurfer: bool, + all_metadata: ty.List[dict], + multiecho: bool, + output_dir: str, + spaces: SpatialReferences, + use_aroma: bool, name='func_derivatives_wf', ): """ @@ -836,7 +843,11 @@ def init_func_derivatives_wf( return workflow -def init_bold_preproc_report_wf(mem_gb, reportlets_dir, name='bold_preproc_report_wf'): +def init_bold_preproc_report_wf( + mem_gb: float, + reportlets_dir: str, + name: str = 'bold_preproc_report_wf', +): """ Generate a visual report. diff --git a/fmriprep/workflows/bold/registration.py b/fmriprep/workflows/bold/registration.py index cd4f416c8..c643bc7cf 100644 --- a/fmriprep/workflows/bold/registration.py +++ b/fmriprep/workflows/bold/registration.py @@ -32,6 +32,7 @@ """ import os import os.path as op +import typing as ty import pkg_resources as pkgr from nipype.interfaces import c3, fsl @@ -44,18 +45,21 @@ DEFAULT_MEMORY_MIN_GB = config.DEFAULT_MEMORY_MIN_GB LOGGER = config.loggers.workflow +AffineDOF = ty.Literal[6, 9, 12] +RegistrationInit = ty.Literal['register', 'header'] + def init_bold_reg_wf( - freesurfer, - use_bbr, - bold2t1w_dof, - bold2t1w_init, - mem_gb, - omp_nthreads, - name='bold_reg_wf', - sloppy=False, - use_compression=True, - write_report=True, + freesurfer: bool, + use_bbr: bool, + bold2t1w_dof: AffineDOF, + bold2t1w_init: RegistrationInit, + mem_gb: float, + omp_nthreads: int, + name: str = 'bold_reg_wf', + sloppy: bool = False, + use_compression: bool = True, + write_report: bool = True, ): """ Build a workflow to run same-subject, BOLD-to-T1w image-registration. @@ -215,7 +219,11 @@ def _bold_reg_suffix(fallback, freesurfer): def init_bold_t1_trans_wf( - freesurfer, mem_gb, omp_nthreads, use_compression=True, name='bold_t1_trans_wf' + freesurfer: bool, + mem_gb: float, + omp_nthreads: int, + use_compression: bool = True, + name: str = 'bold_t1_trans_wf', ): """ Co-register the reference BOLD image to T1w-space. @@ -419,7 +427,13 @@ def init_bold_t1_trans_wf( return workflow -def init_bbreg_wf(use_bbr, bold2t1w_dof, bold2t1w_init, omp_nthreads, name='bbreg_wf'): +def init_bbreg_wf( + use_bbr: bool, + bold2t1w_dof: AffineDOF, + bold2t1w_init: RegistrationInit, + omp_nthreads: int, + name: str = 'bbreg_wf', +): """ Build a workflow to run FreeSurfer's ``bbregister``. @@ -646,7 +660,12 @@ def init_bbreg_wf(use_bbr, bold2t1w_dof, bold2t1w_init, omp_nthreads, name='bbre def init_fsl_bbr_wf( - use_bbr, bold2t1w_dof, bold2t1w_init, omp_nthreads, sloppy=False, name='fsl_bbr_wf' + use_bbr: bool, + bold2t1w_dof: AffineDOF, + bold2t1w_init: RegistrationInit, + omp_nthreads: int, + sloppy: bool = False, + name: str = 'fsl_bbr_wf', ): """ Build a workflow to run FSL's ``flirt``. @@ -671,7 +690,7 @@ def init_fsl_bbr_wf( :simple_form: yes from fmriprep.workflows.bold.registration import init_fsl_bbr_wf - wf = init_fsl_bbr_wf(use_bbr=True, bold2t1w_dof=9, bold2t1w_init='register') + wf = init_fsl_bbr_wf(use_bbr=True, bold2t1w_dof=9, bold2t1w_init='register', omp_nthreads=1) Parameters diff --git a/fmriprep/workflows/bold/resampling.py b/fmriprep/workflows/bold/resampling.py index a71ef1838..0a311adb1 100644 --- a/fmriprep/workflows/bold/resampling.py +++ b/fmriprep/workflows/bold/resampling.py @@ -29,6 +29,10 @@ .. autofunction:: init_bold_preproc_trans_wf """ +from __future__ import annotations + +import typing as ty + import nipype.interfaces.workbench as wb from nipype.interfaces import freesurfer as fs from nipype.interfaces import utility as niu @@ -36,8 +40,17 @@ from ...config import DEFAULT_MEMORY_MIN_GB +if ty.TYPE_CHECKING: + from niworkflows.utils.spaces import SpatialReferences + -def init_bold_surf_wf(*, mem_gb, surface_spaces, medial_surface_nan, name="bold_surf_wf"): +def init_bold_surf_wf( + *, + mem_gb: float, + surface_spaces: ty.List[str], + medial_surface_nan: bool, + name: str = "bold_surf_wf", +): """ Sample functional images to FreeSurfer surfaces. @@ -200,13 +213,13 @@ def select_target(subject_id, space): def init_bold_std_trans_wf( - freesurfer, - mem_gb, - omp_nthreads, - spaces, - multiecho, - name="bold_std_trans_wf", - use_compression=True, + freesurfer: bool, + mem_gb: float, + omp_nthreads: int, + spaces: SpatialReferences, + multiecho: bool, + name: str = "bold_std_trans_wf", + use_compression: bool = True, ): """ Sample fMRI into standard space with a single-step resampling of the original BOLD series. @@ -234,6 +247,7 @@ def init_bold_std_trans_wf( spaces=["MNI152Lin", ("MNIPediatricAsym", {"cohort": "6"})], checkpoint=True), + multiecho=False, ) Parameters @@ -532,12 +546,12 @@ def init_bold_std_trans_wf( def init_bold_preproc_trans_wf( - mem_gb, - omp_nthreads, - name="bold_preproc_trans_wf", - use_compression=True, - use_fieldwarp=False, - interpolation="LanczosWindowedSinc", + mem_gb: float, + omp_nthreads: int, + name: str = "bold_preproc_trans_wf", + use_compression: bool = True, + use_fieldwarp: bool = False, + interpolation: str = "LanczosWindowedSinc", ): """ Resample in native (original) space. @@ -656,7 +670,12 @@ def init_bold_preproc_trans_wf( return workflow -def init_bold_grayords_wf(grayord_density, mem_gb, repetition_time, name="bold_grayords_wf"): +def init_bold_grayords_wf( + grayord_density: ty.Literal['91k', '170k'], + mem_gb: float, + repetition_time: float, + name: str = "bold_grayords_wf", +): """ Sample Grayordinates files onto the fsLR atlas. diff --git a/fmriprep/workflows/bold/stc.py b/fmriprep/workflows/bold/stc.py index 8ae26f0e1..ffdcf7b22 100644 --- a/fmriprep/workflows/bold/stc.py +++ b/fmriprep/workflows/bold/stc.py @@ -53,7 +53,7 @@ def _pre_run_hook(self, runtime): return runtime -def init_bold_stc_wf(metadata, name='bold_stc_wf'): +def init_bold_stc_wf(metadata: dict, name='bold_stc_wf'): """ Create a workflow for :abbr:`STC (slice-timing correction)`. diff --git a/fmriprep/workflows/bold/t2s.py b/fmriprep/workflows/bold/t2s.py index d6403e590..200599fe3 100644 --- a/fmriprep/workflows/bold/t2s.py +++ b/fmriprep/workflows/bold/t2s.py @@ -27,6 +27,8 @@ .. autofunction:: init_bold_t2s_wf """ +import typing as ty + from nipype.interfaces import utility as niu from nipype.pipeline import engine as pe @@ -39,7 +41,12 @@ # pylint: disable=R0914 -def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads, name='bold_t2s_wf'): +def init_bold_t2s_wf( + echo_times: ty.Sequence[float], + mem_gb: float, + omp_nthreads: int, + name: str = 'bold_t2s_wf', +): r""" Combine multiple echos of :abbr:`ME-EPI (multi-echo echo-planar imaging)`. @@ -115,7 +122,7 @@ def init_bold_t2s_wf(echo_times, mem_gb, omp_nthreads, name='bold_t2s_wf'): return workflow -def init_t2s_reporting_wf(name='t2s_reporting_wf'): +def init_t2s_reporting_wf(name: str = 't2s_reporting_wf'): r""" Generate T2\*-map reports. diff --git a/fmriprep/workflows/tests.py b/fmriprep/workflows/tests.py index 2b1b2c2d2..c173c2209 100644 --- a/fmriprep/workflows/tests.py +++ b/fmriprep/workflows/tests.py @@ -22,6 +22,7 @@ # """Utilities and mocks for testing and documentation building.""" import os +import shutil from contextlib import contextmanager from pathlib import Path from tempfile import mkdtemp @@ -45,15 +46,20 @@ def mock_config(): if sectionname != 'environment': section = getattr(config, sectionname) section.load(configs, init=False) + config.nipype.omp_nthreads = 1 config.nipype.init() config.loggers.init() config.init_spaces() config.execution.work_dir = Path(mkdtemp()) config.execution.bids_dir = Path(pkgrf('fmriprep', 'data/tests/ds000005')).absolute() + config.execution.fmriprep_dir = Path(mkdtemp()) config.execution.init() yield + shutil.rmtree(config.execution.work_dir) + shutil.rmtree(config.execution.fmriprep_dir) + if not _old_fs: del os.environ["FREESURFER_HOME"] diff --git a/pyproject.toml b/pyproject.toml index 68d6de36a..f7cc41e57 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ doc = [ "pydot >= 1.2.3", "sphinx >= 1.8", "sphinx-argparse", - "sphinx_rtd_theme", + "sphinx_rtd_theme>=0.5.2", ] dev = [ "black ~= 22.3.0", diff --git a/wrapper/src/fmriprep_docker/__main__.py b/wrapper/src/fmriprep_docker/__main__.py index 1ea5606c3..9b83470b4 100755 --- a/wrapper/src/fmriprep_docker/__main__.py +++ b/wrapper/src/fmriprep_docker/__main__.py @@ -307,29 +307,19 @@ def _is_file(path, parser): # Options for mapping files and directories into container # Update `expected_overlap` variable in merge_help() when adding to this g_wrap = parser.add_argument_group( - 'Wrapper options', 'Standard options that require mapping files into the container' + 'Wrapper options', + 'Standard options that require mapping files into the container; see fmriprep ' + 'usage for complete descriptions', ) g_wrap.add_argument( '-w', '--work-dir', action='store', type=os.path.abspath, - help='path where intermediate results should be stored', ) g_wrap.add_argument( '--output-spaces', nargs="*", - help="""\ -Standard and non-standard spaces to resample anatomical and functional images to. \ -Standard spaces may be specified by the form \ -``