diff --git a/dmriprep/cli/run.py b/dmriprep/cli/run.py new file mode 100755 index 00000000..fb78cd5d --- /dev/null +++ b/dmriprep/cli/run.py @@ -0,0 +1,685 @@ +#!/usr/bin/env python +"""dMRI preprocessing workflow.""" + +import os +from pathlib import Path +import logging +import sys +import gc +import uuid +import warnings +from argparse import ArgumentParser +from argparse import ArgumentDefaultsHelpFormatter +from multiprocessing import cpu_count +from time import strftime + +logging.addLevelName(25, 'IMPORTANT') # Add a new level between INFO and WARNING +logging.addLevelName(15, 'VERBOSE') # Add a new level between INFO and DEBUG +logger = logging.getLogger('cli') + + +def _warn_redirect(message, category, filename, lineno, file=None, line=None): + logger.warning('Captured warning (%s): %s', category, message) + + +def check_deps(workflow): + from nipype.utils.filemanip import which + return sorted( + (node.interface.__class__.__name__, node.interface._cmd) + for node in workflow._get_all_nodes() + if (hasattr(node.interface, '_cmd') and + which(node.interface._cmd.split()[0]) is None)) + + +def get_parser(): + """Build parser object""" + from smriprep.cli.utils import ParseTemplates, output_space as _output_space + from templateflow.api import templates + from packaging.version import Version + from ..__about__ import __version__ + from ..workflows.bold.resampling import NONSTANDARD_REFERENCES + from .version import check_latest, is_flagged + + verstr = 'dmriprep v{}'.format(__version__) + currentv = Version(__version__) + is_release = not any((currentv.is_devrelease, currentv.is_prerelease, currentv.is_postrelease)) + + parser = ArgumentParser(description='dMRIPrep: dMRI PREProcessing workflows', + formatter_class=ArgumentDefaultsHelpFormatter) + + # Arguments as specified by BIDS-Apps + # required, positional arguments + # IMPORTANT: they must go directly with the parser object + parser.add_argument('bids_dir', action='store', type=Path, + 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') + parser.add_argument('analysis_level', choices=['participant'], + help='processing stage to be run, only "participant" in the case of ' + 'dMRIPrep (see BIDS-Apps specification).') + + # optional arguments + parser.add_argument('--version', action='version', version=verstr) + + g_bids = parser.add_argument_group('Options for filtering BIDS queries') + g_bids.add_argument('--skip_bids_validation', '--skip-bids-validation', action='store_true', + default=False, + help='assume the input dataset is BIDS compliant and skip the validation') + g_bids.add_argument('--participant_label', '--participant-label', action='store', nargs='+', + 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') + # 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') + + g_perfm = parser.add_argument_group('Options to handle performance') + g_perfm.add_argument('--nprocs', '--n_cpus', '-n-cpus', action='store', type=int, + help='maximum number of threads across all processes') + g_perfm.add_argument('--omp-nthreads', action='store', type=int, default=0, + help='maximum number of threads per-process') + g_perfm.add_argument('--mem_mb', '--mem-mb', action='store', default=0, type=int, + help='upper bound memory limit for dMRIPrep processes') + g_perfm.add_argument('--low-mem', action='store_true', + help='attempt to reduce memory usage (will increase disk usage ' + 'in working directory)') + g_perfm.add_argument('--use-plugin', action='store', default=None, + help='nipype plugin configuration file') + g_perfm.add_argument('--anat-only', action='store_true', + help='run anatomical workflows only') + g_perfm.add_argument('--boilerplate', action='store_true', + help='generate boilerplate only') + g_perfm.add_argument("-v", "--verbose", dest="verbose_count", action="count", default=0, + help="increases log verbosity for each occurence, debug level is -vvv") + + g_conf = parser.add_argument_group('Workflow configuration') + g_conf.add_argument( + '--ignore', required=False, action='store', nargs="+", default=[], choices=['sdc'], + 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') + g_conf.add_argument( + '--output-spaces', nargs='+', action=ParseTemplates, + help="""\ +Standard and non-standard spaces to resample anatomical and functional images to. \ +Standard spaces may be specified by the form \ +``