From 269987dd80278b4cbcd88bf6bfafdf9b8b042c51 Mon Sep 17 00:00:00 2001 From: byvernault Date: Tue, 28 Mar 2017 12:58:41 +0100 Subject: [PATCH 01/17] Inital commit to add niftyseg --- nipype/interfaces/niftyseg/__init__.py | 18 + nipype/interfaces/niftyseg/base.py | 104 +++++ nipype/interfaces/niftyseg/em.py | 168 +++++++ nipype/interfaces/niftyseg/label_fusion.py | 316 +++++++++++++ nipype/interfaces/niftyseg/lesions.py | 132 ++++++ nipype/interfaces/niftyseg/maths.py | 422 ++++++++++++++++++ nipype/interfaces/niftyseg/patchmatch.py | 122 +++++ nipype/interfaces/niftyseg/stats.py | 195 ++++++++ nipype/interfaces/niftyseg/tests/__init__.py | 0 .../niftyseg/tests/test_Seg_CalcTopNCC.py | 38 ++ .../interfaces/niftyseg/tests/test_Seg_EM.py | 37 ++ .../niftyseg/tests/test_Seg_FillLesions.py | 36 ++ .../niftyseg/tests/test_Seg_LabFusion.py | 116 +++++ .../niftyseg/tests/test_Seg_Maths.py | 162 +++++++ .../niftyseg/tests/test_Seg_PatchMatch.py | 39 ++ .../niftyseg/tests/test_Seg_Stats.py | 57 +++ .../niftyseg/tests/test_auto_BinaryMaths.py | 62 +++ .../tests/test_auto_BinaryMathsInteger.py | 51 +++ .../niftyseg/tests/test_auto_BinaryStats.py | 58 +++ .../niftyseg/tests/test_auto_CalcTopNCC.py | 51 +++ .../interfaces/niftyseg/tests/test_auto_EM.py | 77 ++++ .../niftyseg/tests/test_auto_FillLesions.py | 78 ++++ .../niftyseg/tests/test_auto_LabelFusion.py | 75 ++++ .../niftyseg/tests/test_auto_MathsCommand.py | 43 ++ .../niftyseg/tests/test_auto_Merge.py | 49 ++ .../tests/test_auto_NiftySegCommand.py | 23 + .../niftyseg/tests/test_auto_PatchMatch.py | 64 +++ .../niftyseg/tests/test_auto_StatsCommand.py | 44 ++ .../niftyseg/tests/test_auto_TupleMaths.py | 67 +++ .../niftyseg/tests/test_auto_UnaryMaths.py | 47 ++ .../niftyseg/tests/test_auto_UnaryStats.py | 48 ++ nipype/interfaces/setup.py | 1 + 32 files changed, 2800 insertions(+) create mode 100644 nipype/interfaces/niftyseg/__init__.py create mode 100644 nipype/interfaces/niftyseg/base.py create mode 100644 nipype/interfaces/niftyseg/em.py create mode 100644 nipype/interfaces/niftyseg/label_fusion.py create mode 100644 nipype/interfaces/niftyseg/lesions.py create mode 100644 nipype/interfaces/niftyseg/maths.py create mode 100644 nipype/interfaces/niftyseg/patchmatch.py create mode 100644 nipype/interfaces/niftyseg/stats.py create mode 100644 nipype/interfaces/niftyseg/tests/__init__.py create mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_CalcTopNCC.py create mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_EM.py create mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_FillLesions.py create mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_LabFusion.py create mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_Maths.py create mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_PatchMatch.py create mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_Stats.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_BinaryMaths.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_BinaryMathsInteger.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_BinaryStats.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_CalcTopNCC.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_EM.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_LabelFusion.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_MathsCommand.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_Merge.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_PatchMatch.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_StatsCommand.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_TupleMaths.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_UnaryMaths.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_UnaryStats.py diff --git a/nipype/interfaces/niftyseg/__init__.py b/nipype/interfaces/niftyseg/__init__.py new file mode 100644 index 0000000000..c3992d827c --- /dev/null +++ b/nipype/interfaces/niftyseg/__init__.py @@ -0,0 +1,18 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +""" +The niftyseg module provides classes for interfacing with the `NIFTYSEG +`_ command line tools. + +Top-level namespace for niftyseg. +""" + +from .base import no_niftyseg, get_custom_path +from .em import EM +from .label_fusion import LabelFusion, CalcTopNCC +from .lesions import FillLesions +from .maths import (UnaryMaths, BinaryMaths, BinaryMathsInteger, TupleMaths, + Merge) +from .patchmatch import PatchMatch +from .stats import UnaryStats, BinaryStats diff --git a/nipype/interfaces/niftyseg/base.py b/nipype/interfaces/niftyseg/base.py new file mode 100644 index 0000000000..a5baa0759d --- /dev/null +++ b/nipype/interfaces/niftyseg/base.py @@ -0,0 +1,104 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +""" +The niftyseg module provides classes for interfacing with `niftyseg +`_ command line tools. + +These are the base tools for working with niftyseg. + +EM Statistical Segmentation tool is found in niftyseg/em.py +Fill lesions tool is found in niftyseg/lesions.py +Mathematical operation tool is found in niftyseg/maths.py +Patch Match tool is found in niftyseg/patchmatch.py +Statistical operation tool is found in niftyseg/stats.py +Label Fusion and CalcTopNcc tools are in niftyseg/steps.py + +Examples +-------- +See the docstrings of the individual classes for examples. + +""" + +from nipype.interfaces.base import CommandLine, isdefined +from nipype.utils.filemanip import split_filename +import os +import subprocess +import warnings + + +warn = warnings.warn +warnings.filterwarnings('always', category=UserWarning) + + +def get_custom_path(command): + """Get path of niftyseg.""" + try: + specific_dir = os.environ['NIFTYSEGDIR'] + command = os.path.join(specific_dir, command) + return command + except KeyError: + return command + + +def no_niftyseg(cmd='seg_LabFusion'): + """Check if niftyseg is installed.""" + if True in [os.path.isfile(os.path.join(path, cmd)) and + os.access(os.path.join(path, cmd), os.X_OK) + for path in os.environ["PATH"].split(os.pathsep)]: + return False + return True + + +class NiftySegCommand(CommandLine): + """ + Base support interface for NiftySeg commands. + """ + _suffix = '_ns' + + def __init__(self, **inputs): + super(NiftySegCommand, self).__init__(**inputs) + + def get_version(self): + if no_niftyseg(cmd=self.cmd): + return None + # exec_cmd = ''.join((self.cmd, ' --version')) + exec_cmd = 'seg_EM --version' + # Using seg_EM for version (E.G: seg_stats --version doesn't work) + return subprocess.check_output(exec_cmd, shell=True).strip('\n') + + @property + def version(self): + return self.get_version() + + def exists(self): + if self.get_version() is None: + return False + return True + + def _gen_fname(self, basename, out_dir=None, suffix=None, ext=None): + if basename == '': + msg = 'Unable to generate filename for command %s. ' % self.cmd + msg += 'basename is not set!' + raise ValueError(msg) + _, final_bn, final_ext = split_filename(basename) + if out_dir is None: + out_dir = os.getcwd() + if ext is not None: + final_ext = ext + if suffix is not None: + final_bn = ''.join((final_bn, suffix)) + return os.path.abspath(os.path.join(out_dir, final_bn + final_ext)) + + def _gen_filename(self, name): + if name == 'out_file': + return self._gen_fname(self.inputs.in_file, suffix=self._suffix) + return None + + def _list_outputs(self): + outputs = self.output_spec().get() + if isdefined(self.inputs.out_file): + outputs['out_file'] = self.inputs.out_file + else: + outputs['out_file'] = self._gen_filename('out_file') + return outputs diff --git a/nipype/interfaces/niftyseg/em.py b/nipype/interfaces/niftyseg/em.py new file mode 100644 index 0000000000..6d9964911d --- /dev/null +++ b/nipype/interfaces/niftyseg/em.py @@ -0,0 +1,168 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +""" +Nipype interface for seg_EM. + +The em module provides higher-level interfaces to some of the operations +that can be performed with the seg_em command-line program. + +Examples +-------- +See the docstrings of the individual classes for examples. +""" + +import os + +from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, + InputMultiPath) +from .base import NiftySegCommand, get_custom_path + + +class EMInputSpec(CommandLineInputSpec): + """Input Spec for EM.""" + in_file = File(argstr='-in %s', + exists=True, + mandatory=True, + desc='Input image to segment', + position=4) + + mask_file = File(argstr='-mask %s', + exists=True, + desc='Filename of the ROI for label fusion') + + # Priors + no_prior = traits.Int(argstr='-nopriors %s', + mandatory=True, + desc='Number of classes to use without prior', + xor=['prior_4D', 'priors']) + + prior_4D = File(argstr='-prior4D %s', + exists=True, + mandatory=True, + desc='4D file containing the priors', + xor=['no_prior', 'priors']) + + desc = 'List of priors filepaths.' + priors = InputMultiPath(argstr='%s', + mandatory=True, + desc=desc, + xor=['no_prior', 'prior_4D']) + + # iterations + max_iter = traits.Int(argstr='-max_iter %s', default=100, + desc='Maximum number of iterations') + + min_iter = traits.Int(argstr='-min_iter %s', default=0, + desc='Minimun number of iterations') + + # other options + bc_order_val = traits.Int(argstr='-bc_order %s', default=3, + desc='Polynomial order for the bias field') + + mrf_beta_val = traits.Float(argstr='-mrf_beta %s', + desc='Weight of the Markov Random Field') + + desc = 'Bias field correction will run only if the ratio of improvement \ +is below bc_thresh. (default=0 [OFF])' + bc_thresh_val = traits.Float(argstr='-bc_thresh %s', default=0, desc=desc) + + desc = 'Amount of regularization over the diagonal of the covariance \ +matrix [above 1]' + reg_val = traits.Float(argstr='-reg %s', desc=desc) + + desc = 'Outlier detection as in (Van Leemput TMI 2003). is the \ +Mahalanobis threshold [recommended between 3 and 7] is a convergence \ +ratio below which the outlier detection is going to be done [recommended 0.01]' + outlier_val = traits.Tuple(traits.Float(), traits.Float(), + argstr='-outlier %s %s', + desc=desc) + + desc = 'Relax Priors [relaxation factor: 00 (recommended=2.0)] /only 3D/' + relax_priors = traits.Tuple(traits.Float(), traits.Float(), + argstr='-rf %s %s', + desc=desc) + + # outputs + out_file = File(argstr='-out %s', + genfile=True, + desc='Output segmentation') + out_bc_file = File(argstr='-bc_out %s', + genfile=True, + desc='Output bias corrected image') + out_outlier_file = File(argstr='-out_outlier %s', + genfile=True, + desc='Output outlierness image') + + +class EMOutputSpec(TraitedSpec): + """Output Spec for EM.""" + out_file = File(desc="Output segmentation") + out_bc_file = File(desc="Output bias corrected image") + out_outlier_file = File(desc='Output outlierness image') + + +class EM(NiftySegCommand): + """Interface for executable seg_EM from NiftySeg platform. + + seg_EM is a general purpose intensity based image segmentation tool. In + it's simplest form, it takes in one 2D or 3D image and segments it in n + classes. + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import EM + >>> node = EM() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.no_prior = 4 + >>> node.cmdline # doctest: +SKIP + 'seg_EM -in im1.nii -nopriors 4 -bc_out im1_bc_em.nii -out im1_em.nii \ +-out_outlier im1_outlier_em.nii' + + """ + _cmd = get_custom_path('seg_EM') + _suffix = '_em' + input_spec = EMInputSpec + output_spec = EMOutputSpec + + def _format_arg(self, opt, spec, val): + """Convert input to appropriate format for seg_EM.""" + if opt == 'priors': + _nb_priors = len(self.inputs.priors) + return '-priors %d %s' % (_nb_priors, ' '.join(self.inputs.priors)) + else: + return super(EM, self)._format_arg(opt, spec, val) + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = self.inputs.out_file + if not isdefined(self.inputs.out_file): + outputs['out_file'] = self._gen_fname(self.inputs.in_file, + suffix=self._suffix) + outputs['out_file'] = os.path.abspath(outputs['out_file']) + outputs['out_bc_file'] = self.inputs.out_bc_file + if not isdefined(self.inputs.out_bc_file): + outputs['out_bc_file'] = self._gen_fname( + self.inputs.in_file, suffix=('_bc%s' % self._suffix)) + outputs['out_bc_file'] = os.path.abspath(outputs['out_bc_file']) + outputs['out_outlier_file'] = self.inputs.out_outlier_file + if not isdefined(self.inputs.out_outlier_file): + outputs['out_outlier_file'] = self._gen_fname( + self.inputs.in_file, suffix=('_outlier%s' % self._suffix)) + outputs['out_outlier_file'] = os.path.abspath( + outputs['out_outlier_file']) + return outputs + + def _gen_filename(self, name): + if name == 'out_file': + return self._list_outputs()['out_file'] + if name == 'out_bc_file': + return self._list_outputs()['out_bc_file'] + if name == 'out_outlier_file': + return self._list_outputs()['out_outlier_file'] + return None diff --git a/nipype/interfaces/niftyseg/label_fusion.py b/nipype/interfaces/niftyseg/label_fusion.py new file mode 100644 index 0000000000..d00500592d --- /dev/null +++ b/nipype/interfaces/niftyseg/label_fusion.py @@ -0,0 +1,316 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +""" +The fusion module provides higher-level interfaces to some of the operations +that can be performed with the seg_LabFusion command-line program. +""" + +import os +import warnings + +from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, + NipypeInterfaceError) +from .base import NiftySegCommand, get_custom_path +from ...utils.filemanip import load_json, save_json + + +warn = warnings.warn +warnings.filterwarnings('always', category=UserWarning) + + +class LabelFusionInput(CommandLineInputSpec): + """Input Spec for LabelFusion.""" + in_file = File(argstr='-in %s', + exists=True, + mandatory=True, + position=1, + desc='Filename of the 4D integer label image.') + + template_file = File(exists=True, + desc='Registered templates (4D Image)') + + file_to_seg = File(exists=True, + mandatory=True, + desc='Original image to segment (3D Image)') + + mask_file = File(argstr='-mask %s', + exists=True, + desc='Filename of the ROI for label fusion') + + out_file = File(argstr='-out %s', + genfile=True, + desc='Output consensus segmentation') + + prob_flag = traits.Bool(desc='Probabilistic/Fuzzy segmented image', + argstr='-outProb') + + desc = 'Verbose level [0 = off, 1 = on, 2 = debug] (default = 0)' + verbose = traits.Enum('0', '1', '2', + desc=desc, + argstr='-v %s') + + desc = 'Only consider non-consensus voxels to calculate statistics' + unc = traits.Bool(desc=desc, argstr='-unc') + + classifier_type = traits.Enum('STEPS', 'STAPLE', 'MV', 'SBA', + argstr='-%s', + mandatory=True, + position=2, + desc='Type of Classifier Fusion.') + + desc = "Gaussian kernel size in mm to compute the local similarity" + kernel_size = traits.Float(desc=desc) + + template_num = traits.Int(desc='Number of labels to use') + + # STAPLE and MV options + sm_ranking = traits.Enum('ALL', 'GNCC', 'ROINCC', 'LNCC', + argstr='-%s', + usedefault=True, + position=3, + desc='Ranking for STAPLE and MV') + + dilation_roi = traits.Int(desc='Dilation of the ROI ( d>=1 )') + + # STAPLE and STEPS options + desc = 'Proportion of the label (only for single labels).' + proportion = traits.Float(argstr='-prop %s', desc=desc) + + desc = 'Update label proportions at each iteration' + prob_update_flag = traits.Bool(desc=desc, argstr='-prop_update') + + desc = 'Value of P and Q [ 0 < (P,Q) < 1 ] (default = 0.99 0.99)' + set_pq = traits.Tuple(traits.Float, traits.Float, + argstr='-setPQ %f %f', + desc=desc) + + mrf_value = traits.Float(argstr='-MRF_beta %f', + desc='MRF prior strength (between 0 and 5)') + + desc = 'Maximum number of iterations (default = 15).' + max_iter = traits.Int(argstr='-max_iter %d', desc=desc) + + desc = 'If percent of labels agree, then area is not uncertain.' + unc_thresh = traits.Float(argstr='-uncthres %f', desc=desc) + + desc = 'Ratio for convergence (default epsilon = 10^-5).' + conv = traits.Float(argstr='-conv %f', desc=desc) + + +class LabelFusionOutput(TraitedSpec): + """Output Spec for LabelFusion.""" + out_file = File(exists=True, desc='image written after calculations') + + +class LabelFusion(NiftySegCommand): + """Interface for executable seg_LabelFusion from NiftySeg platform using + type STEPS as classifier Fusion. + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import LabelFusion + >>> node = LabelFusion() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.kernel_size = 2.0 + >>> node.inputs.file_to_seg = 'im2.nii' # doctest: +SKIP + >>> node.inputs.template_file = 'im3.nii' # doctest: +SKIP + >>> node.inputs.template_num = 2 + >>> node.inputs.classifier_type = 'STEPS' + >>> node.cmdline # doctest: +SKIP + 'seg_LabFusion -in im1.nii -STEPS 2.000000 2 im2.nii im3.nii -out \ +im1_steps.nii' + + """ + _cmd = get_custom_path('seg_LabFusion') + input_spec = LabelFusionInput + output_spec = LabelFusionOutput + _suffix = '_label_fused' + + def _format_arg(self, opt, spec, val): + """Convert input to appropriate format for seg_maths.""" + # Remove options if not STAPLE or STEPS as fusion type: + if opt in ['proportion', 'prob_update_flag', 'set_pq', 'mrf_value', + 'max_iter', 'unc_thresh', 'conv'] and\ + self.inputs.classifier_type not in ['STAPLE', 'STEPS']: + return '' + + if opt == 'sm_ranking': + return self.get_staple_args(val) + + # Return options string if STEPS: + if opt == 'classifier_type' and val == 'STEPS': + return self.get_steps_args() + + return super(LabelFusion, self)._format_arg(opt, spec, val) + + def get_steps_args(self): + if not isdefined(self.inputs.template_file): + err = "LabelFusion requires a value for input 'template_file' \ +when 'classifier_type' is set to 'STEPS'." + raise NipypeInterfaceError(err) + if not isdefined(self.inputs.kernel_size): + err = "LabelFusion requires a value for input 'kernel_size' when \ +'classifier_type' is set to 'STEPS'." + raise NipypeInterfaceError(err) + if not isdefined(self.inputs.template_num): + err = "LabelFusion requires a value for input 'template_num' when \ +'classifier_type' is set to 'STEPS'." + raise NipypeInterfaceError(err) + return "-STEPS %f %d %s %s" % (self.inputs.kernel_size, + self.inputs.template_num, + self.inputs.file_to_seg, + self.inputs.template_file) + + def get_staple_args(self, ranking): + classtype = self.inputs.classifier_type + if classtype not in ['STAPLE', 'MV']: + return None + + if ranking == 'ALL': + return '-%s' % ranking + + if not isdefined(self.inputs.template_file): + err = "LabelFusion requires a value for input 'tramplate_file' \ +when 'classifier_type' is set to '%s' and 'sm_ranking' is set to '%s'." + raise NipypeInterfaceError(err % (classtype, ranking)) + if not isdefined(self.inputs.template_num): + err = "LabelFusion requires a value for input 'template-num' when \ +'classifier_type' is set to '%s' and 'sm_ranking' is set to '%s'." + raise NipypeInterfaceError(err % (classtype, ranking)) + + if ranking == 'GNCC': + if not isdefined(self.inputs.template_num): + err = "LabelFusion requires a value for input 'template_num' \ +when 'classifier_type' is set to '%s' and 'sm_ranking' is set to '%s'." + raise NipypeInterfaceError(err % (classtype, ranking)) + + return "-%s %d %s %s" % (ranking, + self.inputs.template_num, + self.inputs.file_to_seg, + self.inputs.template_file) + + elif ranking == 'ROINCC': + if not isdefined(self.inputs.dilation_roi): + err = "LabelFusion requires a value for input 'dilation_roi' \ +when 'classifier_type' is set to '%s' and 'sm_ranking' is set to '%s'." + raise NipypeInterfaceError(err % (classtype, ranking)) + + elif self.inputs.dilation_roi < 1: + err = "The 'dilation_roi' trait of a LabelFusionInput \ +instance must be an integer >= 1, but a value of '%s' was specified." + raise NipypeInterfaceError(err % self.inputs.dilation_roi) + + return "-%s %d %d %s %s" % (ranking, + self.inputs.dilation_roi, + self.inputs.template_num, + self.inputs.file_to_seg, + self.inputs.template_file) + elif ranking == 'LNCC': + if not isdefined(self.inputs.kernel_size): + err = "LabelFusion requires a value for input 'kernel_size' \ +when 'classifier_type' is set to '%s' and 'sm_ranking' is set to '%s'." + raise NipypeInterfaceError(err % (classtype, ranking)) + + return "-%s %f %d %s %s" % (ranking, + self.inputs.kernel_size, + self.inputs.template_num, + self.inputs.file_to_seg, + self.inputs.template_file) + + def _list_outputs(self): + outputs = self.output_spec().get() + if isdefined(self.inputs.out_file): + outputs['out_file'] = self.inputs.out_file + else: + outputs['out_file'] = self._gen_filename('out_file') + return outputs + + def _gen_filename(self, name): + _suffix = '_%s' % self.inputs.classifier_type.lower() + if name == 'out_file': + return self._gen_fname(self.inputs.in_file, suffix=_suffix) + return None + + +class CalcTopNCCInputSpec(CommandLineInputSpec): + """Input Spec for CalcTopNCC.""" + in_file = File(argstr='-target %s', + exists=True, + mandatory=True, + desc='Target file', + position=1) + + num_templates = traits.Int(argstr='-templates %s', + mandatory=True, + position=2, + desc='Number of Templates') + + in_templates = traits.List(File(exists=True), + argstr="%s", + position=3, + mandatory=True) + + top_templates = traits.Int(argstr='-n %s', + mandatory=True, + position=4, + desc='Number of Top Templates') + + mask_file = File(argstr='-mask %s', + exists=True, + mandatory=False, + desc='Filename of the ROI for label fusion') + + +class CalcTopNCCOutputSpec(TraitedSpec): + """Output Spec for CalcTopNCC.""" + out_files = traits.Any(File(exists=True)) + + +class CalcTopNCC(NiftySegCommand): + """Interface for executable seg_CalcTopNCC from NiftySeg platform. + + Examples + -------- + >>> from nipype.interfaces.niftyseg import CalcTopNCC + >>> node = CalcTopNCC() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.num_templates = 2 + >>> node.inputs.in_templates = ['im2.nii', 'im3.nii'] # doctest: +SKIP + >>> node.inputs.top_templates = 1 + >>> node.cmdline # doctest: +SKIP + 'seg_CalcTopNCC -target im1.nii -templates 2 im2.nii im3.nii -n 1' + + """ + _cmd = get_custom_path('seg_CalcTopNCC') + _suffix = '_topNCC' + input_spec = CalcTopNCCInputSpec + output_spec = CalcTopNCCOutputSpec + + def aggregate_outputs(self, runtime=None, needed_outputs=None): + outputs = self._outputs() + # local caching for backward compatibility + outfile = os.path.join(os.getcwd(), 'CalcTopNCC.json') + if runtime is None: + try: + out_files = load_json(outfile)['files'] + except IOError: + return self.run().outputs + else: + out_files = [] + for line in runtime.stdout.split('\n'): + if line: + values = line.split() + if len(values) > 1: + out_files.append([str(val) for val in values]) + else: + out_files.extend([str(val) for val in values]) + if len(out_files) == 1: + out_files = out_files[0] + save_json(outfile, dict(files=out_files)) + outputs.out_files = out_files + return outputs diff --git a/nipype/interfaces/niftyseg/lesions.py b/nipype/interfaces/niftyseg/lesions.py new file mode 100644 index 0000000000..edbfd978e7 --- /dev/null +++ b/nipype/interfaces/niftyseg/lesions.py @@ -0,0 +1,132 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +""" +Nipype interface for seg_FillLesions. + +The fusion module provides higher-level interfaces to some of the operations +that can be performed with the seg_FillLesions command-line program. + +Examples +-------- +See the docstrings of the individual classes for examples. +""" + +import os +import warnings + +from ..base import TraitedSpec, File, traits, isdefined, CommandLineInputSpec +from .base import NiftySegCommand, get_custom_path + + +warn = warnings.warn +warnings.filterwarnings('always', category=UserWarning) + + +class FillLesionsInputSpec(CommandLineInputSpec): + """Input Spec for FillLesions.""" + # Mandatory input arguments + in_file = File(argstr='-i %s', exists=True, mandatory=True, + desc='Input image to fill lesions', position=1) + + lesion_mask = File(argstr='-l %s', exists=True, mandatory=True, + desc='Lesion mask', position=2) + + # Output file name + out_file = File(desc='The output filename of the fill lesions results', + argstr='-o %s', position=3) + + # Optional arguments + desc = "Dilate the mask times (in voxels, by default 0)" + in_dilation = traits.Int(desc=desc, argstr='-dil %d', mandatory=False) + + desc = 'Percentage of minimum number of voxels between patches \ +(by default 0.5).' + match = traits.Float(desc=desc, argstr='-match %f', mandatory=False) + + desc = 'Minimum percentage of valid voxels in target patch \ +(by default 0).' + search = traits.Float(desc=desc, argstr='-search %f', mandatory=False) + + desc = 'Smoothing by (in minimal 6-neighbourhood voxels \ +(by default 0.1)).' + smooth = traits.Float(desc=desc, argstr='-smo %f', mandatory=False) + + desc = 'Search regions size respect biggest patch size (by default 4).' + size = traits.Int(desc=desc, argstr='-size %d', mandatory=False) + + desc = 'Patch cardinality weighting factor (by default 2).' + cwf = traits.Float(desc=desc, argstr='-cwf %f', mandatory=False) + + desc = 'Give a binary mask with the valid search areas.' + bin_mask = File(desc=desc, argstr='-mask %s', mandatory=False) + + desc = "Guizard et al. (FIN 2015) method, it doesn't include the \ +multiresolution/hierarchical inpainting part, this part needs to be done \ +with some external software such as reg_tools and reg_resample from NiftyReg. \ +By default it uses the method presented in Prados et al. (Neuroimage 2016)." + other = traits.Bool(desc=desc, argstr='-other', mandatory=False) + + debug = traits.Bool(desc='Save all intermidium files (by default OFF).', + argstr='-debug', mandatory=False) + + desc = 'Set output (char, short, int, uchar, ushort, uint, \ +float, double).' + out_datatype = traits.String(desc=desc, argstr='-odt %s', mandatory=False) + + verbose = traits.Bool(desc='Verbose (by default OFF).', + argstr='-v', mandatory=False) + + # Set the number of omp thread to use + omp_core = traits.Int(desc='Number of openmp thread to use. Default: 4', + argstr='-omp %d') + + +class FillLesionsOutputSpec(TraitedSpec): + """Output Spec for FillLesions.""" + out_file = File(desc="Output segmentation") + + +class FillLesions(NiftySegCommand): + """Interface for executable seg_FillLesions from NiftySeg platform. + + Fill all the masked lesions with WM intensity average. + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import FillLesions + >>> node = FillLesions() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.lesion_mask = 'im2.nii' # doctest: +SKIP + >>> node.cmdline # doctest: +SKIP + 'seg_FillLesions -i im1.nii -l im2.nii -o im1_lesions_filled.nii' + + """ + _cmd = get_custom_path('seg_FillLesions') + input_spec = FillLesionsInputSpec + output_spec = FillLesionsOutputSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = self.inputs.out_file + if not isdefined(self.inputs.out_file): + outputs['out_file'] = self._gen_filename('out_file') + outputs['out_file'] = os.path.abspath(outputs['out_file']) + return outputs + + def _parse_inputs(self, skip=None): + """Set non-mandatory inputs if not given by user.""" + skip = [] + if not isdefined(self.inputs.out_file): + self.inputs.out_file = self._gen_filename('out_file') + return super(FillLesions, self)._parse_inputs(skip=skip) + + def _gen_filename(self, name): + if name == 'out_file': + return self._gen_fname(self.inputs.in_file, + suffix='_lesions_filled') + return None diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py new file mode 100644 index 0000000000..3a6e69c461 --- /dev/null +++ b/nipype/interfaces/niftyseg/maths.py @@ -0,0 +1,422 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +""" +Nipype interface for seg_maths. + +The maths module provides higher-level interfaces to some of the operations +that can be performed with the niftysegmaths (seg_maths) command-line program. + +Examples +-------- +See the docstrings of the individual classes for examples. +""" +import os + +from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, + NipypeInterfaceError) +from .base import NiftySegCommand, get_custom_path + + +class MathsInput(CommandLineInputSpec): + """Input Spec for seg_maths interfaces.""" + in_file = File(position=2, + argstr='%s', + exists=True, + mandatory=True, + desc='image to operate on') + + out_file = File(genfile=True, + position=-2, + argstr='%s', + desc='image to write') + + _dtypes = ['float', 'char', 'int', 'short', 'double', 'input'] + + desc = 'datatype to use for output (default uses input type)' + output_datatype = traits.Enum(*_dtypes, + position=-3, + argstr='-odt %s', + desc=desc) + + +class MathsOutput(TraitedSpec): + """Output Spec for seg_maths interfaces.""" + out_file = File(exists=True, desc='image written after calculations') + + +class MathsCommand(NiftySegCommand): + """ + Base Command Interface for seg_maths interfaces. + """ + _cmd = get_custom_path('seg_maths') + input_spec = MathsInput + output_spec = MathsOutput + + def _list_outputs(self): + outputs = self.output_spec().get() + + suffix = self._suffix + if suffix != '_merged' and isdefined(self.inputs.operation): + suffix = '_' + self.inputs.operation + + outputs['out_file'] = self.inputs.out_file + if not isdefined(self.inputs.out_file): + outputs['out_file'] = self._gen_fname(self.inputs.in_file, + suffix=suffix) + outputs['out_file'] = os.path.abspath(outputs['out_file']) + return outputs + + def _gen_filename(self, name): + if name == 'out_file': + return self._list_outputs()['out_file'] + return None + + +class UnaryMathsInput(MathsInput): + """Input Spec for seg_maths Unary operations.""" + operation = traits.Enum('sqrt', 'exp', 'log', 'recip', 'abs', 'bin', + 'otsu', 'lconcomp', 'concomp6', 'concomp26', + 'fill', 'euc', 'tpmax', 'tmean', 'tmax', 'tmin', + 'splitlab', 'removenan', 'isnan', 'subsamp2', + 'scl', '4to5', 'range', + argstr='-%s', position=4, mandatory=True, + desc='operation to perform') + + +class UnaryMaths(MathsCommand): + """Interface for executable seg_maths from NiftySeg platform. + + Interface to use any unary mathematical operations that can be performed + with the seg_maths command-line program. See below for those operations: + -sqrt Square root of the image. + -exp Exponential root of the image. + -log Log of the image. + -recip Reciprocal (1/I) of the image. + -abs Absolute value of the image. + -bin Binarise the image. + -otsu Otsu thresholding of the current image. + -lconcomp Take the largest connected component + -concomp6 Label the different connected components with a 6NN + kernel + -concomp26 Label the different connected components with a 26NN + kernel + -fill Fill holes in binary object (e.g. fill ventricle in + brain mask). + -euc Euclidean distance trasnform + -tpmax Get the time point with the highest value (binarise 4D + probabilities) + -tmean Mean value of all time points. + -tmax Max value of all time points. + -tmin Mean value of all time points. + -splitlab Split the integer labels into multiple timepoints + -removenan Remove all NaNs and replace then with 0 + -isnan Binary image equal to 1 if the value is NaN and 0 + otherwise + -subsamp2 Subsample the image by 2 using NN sampling (qform and + sform scaled) + -scl Reset scale and slope info. + -4to5 Flip the 4th and 5th dimension. + -range Reset the image range to the min max + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import UnaryMaths + >>> node = UnaryMaths() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.operation = 'sqrt' + >>> node.inputs.output_datatype = 'float' + >>> node.cmdline # doctest: +SKIP + 'seg_maths im1.nii -sqrt -odt float im1_sqrt.nii.gz' + + """ + input_spec = UnaryMathsInput + + +class BinaryMathsInput(MathsInput): + """Input Spec for seg_maths Binary operations.""" + operation = traits.Enum('mul', 'div', 'add', 'sub', 'pow', 'thr', 'uthr', + 'smo', 'edge', 'sobel3', 'sobel5', 'min', 'smol', + 'geo', 'llsnorm', 'masknan', 'hdr_copy', + 'splitinter', + mandatory=True, + argstr='-%s', + position=4, + desc='operation to perform') + + operand_file = File(exists=True, + argstr='%s', + mandatory=True, + position=5, + xor=['operand_value', 'operand_str'], + desc='second image to perform operation with') + + operand_value = traits.Float(argstr='%.8f', + mandatory=True, + position=5, + xor=['operand_file', 'operand_str'], + desc='float value to perform operation with') + + desc = 'string value to perform operation splitinter' + operand_str = traits.Enum('x', 'y', 'z', + argstr='%s', + mandatory=True, + position=5, + xor=['operand_value', 'operand_file'], + desc=desc) + + +class BinaryMaths(MathsCommand): + """Interface for executable seg_maths from NiftySeg platform. + + Interface to use any binary mathematical operations that can be performed + with the seg_maths command-line program. See below for those operations: + -mul Multiply image value or by other image. + -div Divide image by or by other image. + -add Add image by or by other image. + -sub Subtract image by or by other image. + -pow Image to the power of . + -thr Threshold the image below . + -uthr Threshold image above . + -smo Gaussian smoothing by std (in voxels + and up to 4-D). + -edge Calculate the edges of the image using a + threshold . + -sobel3 Calculate the edges of all timepoints using a + Sobel filter with a 3x3x3 kernel and applying + gaussian smoothing. + -sobel5 Calculate the edges of all timepoints using a + Sobel filter with a 5x5x5 kernel and applying + gaussian smoothing. + -min Get the min per voxel between and + . + -smol Gaussian smoothing of a 3D label image. + -geo Geodesic distance according to the speed + function + -llsnorm Linear LS normalisation between current and + + -masknan Assign everything outside the mask (mask==0) + with NaNs + -hdr_copy Copy header from working image to and + save in . + -splitinter Split interleaved slices in direction + into separate time points + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import BinaryMaths + >>> node = BinaryMaths() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.operation = 'sub' + >>> node.inputs.operand_file = 'im2.nii' # doctest: +SKIP + >>> node.inputs.output_datatype = 'float' + >>> node.cmdline # doctest: +SKIP + 'seg_maths im1.nii -odt float -sub im2.nii im1_sub.nii.gz' + + """ + input_spec = BinaryMathsInput + + def _format_arg(self, opt, spec, val): + """Convert input to appropriate format for seg_maths.""" + if opt == 'operand_value' and float(val) == 0.0: + return '0' + + if opt == 'operand_str' and self.inputs.operation != 'splitinter': + err = 'operand_str set but with an operation different than \ +"splitinter"' + raise NipypeInterfaceError(err) + + return super(BinaryMaths, self)._format_arg(opt, spec, val) + + def _list_outputs(self): + outputs = self.output_spec().get() + self._suffix = '_' + self.inputs.operation + + outputs['out_file'] = self.inputs.out_file + if not isdefined(self.inputs.out_file): + if isdefined(self.inputs.operation) and \ + self.inputs.operation == 'hdr_copy': + outputs['out_file'] = self._gen_fname(self.inputs.operand_file, + suffix=self._suffix) + else: + outputs['out_file'] = self._gen_fname(self.inputs.in_file, + suffix=self._suffix) + outputs['out_file'] = os.path.abspath(outputs['out_file']) + return outputs + + +class BinaryMathsInputInteger(MathsInput): + """Input Spec for seg_maths Binary operations that require integer.""" + operation = traits.Enum('dil', 'ero', 'tp', 'equal', 'pad', 'crop', + mandatory=True, + argstr='-%s', + position=4, + desc='operation to perform') + + operand_value = traits.Int(argstr='%d', + mandatory=True, + position=5, + desc='int value to perform operation with') + + +class BinaryMathsInteger(MathsCommand): + """Interface for executable seg_maths from NiftySeg platform. + + Interface to use any integer mathematical operations that can be performed + with the seg_maths command-line program. See below for those operations: + (requiring integer values) + -equal Get voxels equal to + -dil Dilate the image times (in voxels). + -ero Erode the image times (in voxels). + -tp Extract time point + -crop Crop voxels around each 3D volume. + -pad Pad voxels with NaN value around each 3D + volume. + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import BinaryMathsInteger + >>> node = BinaryMathsInteger() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.operation = 'dil' + >>> node.inputs.operand_value = 2 + >>> node.inputs.output_datatype = 'float' + >>> node.cmdline # doctest: +SKIP + 'seg_maths im1.nii -dil 2 im1_dil.nii -odt float' + + """ + input_spec = BinaryMathsInputInteger + + +class TupleMathsInput(MathsInput): + """Input Spec for seg_maths Tuple operations.""" + operation = traits.Enum('lncc', 'lssd', 'lltsnorm', 'qlsnorm', + mandatory=True, + argstr='-%s', + position=4, + desc='operation to perform') + + operand_file1 = File(exists=True, + argstr='%s', + mandatory=True, + position=5, + xor=['operand_value1'], + desc='image to perform operation 1 with') + + desc = 'float value to perform operation 1 with' + operand_value1 = traits.Float(argstr='%.8f', + mandatory=True, + position=5, + xor=['operand_file1'], + desc=desc) + + operand_file2 = File(exists=True, + argstr='%s', + mandatory=True, + position=6, + xor=['operand_value2'], + desc='image to perform operation 2 with') + + desc = 'float value to perform operation 2 with' + operand_value2 = traits.Float(argstr='%.8f', + mandatory=True, + position=6, + xor=['operand_file2'], + desc=desc) + + +class TupleMaths(MathsCommand): + """Interface for executable seg_maths from NiftySeg platform. + + Interface to use any tuple mathematical operations that can be performed + with the seg_maths command-line program. See below for those operations: + -lncc Local CC between current img and + on a kernel with + -lssd Local SSD between current img and + on a kernel with + -lltsnorm Linear LTS normalisation assuming + percent outliers + -qlsnorm LS normalisation of + between current and + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import TupleMaths + >>> node = TupleMaths() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.operation = 'lncc' + >>> node.inputs.operand_file1 = 'im2.nii' # doctest: +SKIP + >>> node.inputs.operand_value2 = 2.0 + >>> node.inputs.output_datatype = 'float' + >>> node.cmdline # doctest: +SKIP + 'seg_maths im1.nii -lncc im2.nii 2.00000000 im1_lncc.nii -odt float' + + """ + input_spec = TupleMathsInput + + +class MergeInput(MathsInput): + """Input Spec for seg_maths merge operation.""" + dimension = traits.Int(mandatory=True, + desc='Dimension to merge the images.') + + desc = 'List of images to merge to the working image .' + merge_files = traits.List(File(exists=True), + argstr='%s', + mandatory=True, + position=4, + desc=desc) + + +class Merge(MathsCommand): + """Interface for executable seg_maths from NiftySeg platform. + + Interface to use the merge operation that can be performed + with the seg_maths command-line program. See below for this option: + -merge Merge images and the working image in the + dimension + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import Merge + >>> node = Merge() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> files = ['im2.nii', 'im3.nii'] + >>> node.inputs.merge_files = files # doctest: +SKIP + >>> node.inputs.dimension = 2 + >>> node.inputs.output_datatype = 'float' + >>> node.cmdline # doctest: +SKIP + 'seg_maths im1.nii -merge 2 2 im2.nii im3.nii -odt float im1_merged.nii' + + """ + input_spec = MergeInput + _suffix = '_merged' + + def _format_arg(self, opt, spec, val): + """Convert input to appropriate format for seg_maths.""" + print opt + if opt == 'merge_files': + return "-merge %d %d %s" % (len(val), self.inputs.dimension, + ' '.join(val)) + + return super(Merge, self)._format_arg(opt, spec, val) diff --git a/nipype/interfaces/niftyseg/patchmatch.py b/nipype/interfaces/niftyseg/patchmatch.py new file mode 100644 index 0000000000..50613758da --- /dev/null +++ b/nipype/interfaces/niftyseg/patchmatch.py @@ -0,0 +1,122 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +""" +The fusion module provides higher-level interfaces to some of the operations +that can be performed with the seg_DetectLesions command-line program. +""" +import os +import warnings + +from ..base import TraitedSpec, File, traits, isdefined, CommandLineInputSpec +from .base import NiftySegCommand, get_custom_path + + +warn = warnings.warn +warnings.filterwarnings('always', category=UserWarning) + + +class PatchMatchInputSpec(CommandLineInputSpec): + """Input Spec for PatchMatch.""" + # Mandatory input arguments + in_file = File(argstr='-i %s', + exists=True, + mandatory=True, + desc='Input image to segment', + position=1) + + mask_file = File(argstr='-m %s', + exists=True, + mandatory=True, + desc='Input mask for the area where applies PatchMatch', + position=2) + + database_file = File(argstr='-db %s', + genfile=True, + mandatory=True, + desc='Database with the segmentations', + position=3) + + # Output file name + out_file = File(desc='The output filename of the patchmatch results', + argstr='-o %s', + position=4, + genfile=True) + + # Optional arguments + patch_size = traits.Int(desc="Patch size, #voxels", + argstr='-size %i', + mandatory=False) + + desc = "Constrained search area size, number of times bigger than the \ +patchsize" + cs_size = traits.Int(desc=desc, + argstr='-cs %i', + mandatory=False) + + match_num = traits.Int(desc="Number of better matching", + argstr='-match %i', + mandatory=False) + + pm_num = traits.Int(desc="Number of patchmatch executions", + argstr='-pm %i', + mandatory=False) + + desc = "Number of iterations for the patchmatch algorithm" + it_num = traits.Int(desc=desc, + argstr='-it %i', + mandatory=False) + + +class PatchMatchOutputSpec(TraitedSpec): + """OutputSpec for PatchMatch.""" + out_file = File(desc="Output segmentation") + + +class PatchMatch(NiftySegCommand): + """Interface for executable seg_PatchMatch from NiftySeg platform. + + The database file is a text file and in each line we have a template + file, a mask with the search region to consider and a file with the + label to propagate. + + Input image, input mask, template images from database and masks from + database must have the same 4D resolution (same number of XxYxZ voxels, + modalities and/or time-points). + Label files from database must have the same 3D resolution + (XxYxZ voxels) than input image but can have different number of + volumes than the input image allowing to propagate multiple labels + in the same execution. + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import PatchMatch + >>> node = PatchMatch() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.mask_file = 'im2.nii' # doctest: +SKIP + >>> node.inputs.database_file = 'db.xml' # doctest: +SKIP + >>> node.cmdline # doctest: +SKIP + 'seg_PatchMatch -i im1.nii -m im2.nii -db db.xml -o im1_pm.nii' + + """ + _cmd = get_custom_path('seg_PatchMatch') + input_spec = PatchMatchInputSpec + output_spec = PatchMatchOutputSpec + _suffix = '_pm' + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['out_file'] = self.inputs.out_file + if not isdefined(self.inputs.out_file): + outputs['out_file'] = self._gen_fname(self.inputs.in_file, + suffix=self._suffix) + outputs['out_file'] = os.path.abspath(outputs['out_file']) + return outputs + + def _gen_filename(self, name): + if name == 'out_file': + return self._list_outputs()['out_file'] + return None diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py new file mode 100644 index 0000000000..a81c1d979e --- /dev/null +++ b/nipype/interfaces/niftyseg/stats.py @@ -0,0 +1,195 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +""" +The stats module provides higher-level interfaces to some of the operations +that can be performed with the niftysegstats (seg_stats) command-line program. +""" +import numpy as np + +from ..base import TraitedSpec, File, traits, CommandLineInputSpec +from .base import NiftySegCommand, get_custom_path + + +class StatsInput(CommandLineInputSpec): + """Input Spec for seg_stats interfaces.""" + in_file = File(position=2, + argstr='%s', + exists=True, + mandatory=True, + desc='image to operate on') + + # Constrains + mask_file = File(exists=True, + mandatory=False, + position=-2, + argstr='-m %s', + desc='statistics within the masked area') + + desc = 'Only estimate statistics if voxel is larger than ' + larger_voxel = traits.Float(argstr='-t %f', + mandatory=False, + position=-3, + desc=desc) + + +class StatsOutput(TraitedSpec): + """Output Spec for seg_stats interfaces.""" + output = traits.Array(desc='Output array from seg_stats') + + +class StatsCommand(NiftySegCommand): + """ + Base Command Interface for seg_stats interfaces. + """ + _cmd = get_custom_path('seg_stats') + input_spec = StatsInput + output_spec = StatsOutput + + def _parse_stdout(self, stdout): + out = [] + for string_line in stdout.split("\n"): + print('parsing line ' + string_line) + if string_line.startswith('#'): + continue + if len(string_line) <= 1: + continue + line = [float(s) for s in string_line.split()] + out.append(line) + return np.array(out).squeeze() + + def _run_interface(self, runtime): + print('parsing output in run_interface') + new_runtime = super(UnaryStats, self)._run_interface(runtime) + self.output = self._parse_stdout(new_runtime.stdout) + return new_runtime + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['output'] = self.output + return outputs + + +class UnaryStatsInput(StatsInput): + """Input Spec for seg_stats unary operations.""" + operation = traits.Enum('r', 'R', 'a', 's', 'v', 'vl', 'vp', 'n', 'np', + 'e', 'ne', 'x', 'X', 'c', 'B', 'xvox', 'xdim', + argstr='-%s', + position=4, + mandatory=True, + desc='operation to perform') + + +class UnaryStats(StatsCommand): + """ + Interface for executable seg_stats from NiftySeg platform. + + Interface to use any unary statistical operations that can be performed + with the seg_stats command-line program. See below for those operations: + -r | The range of all voxels. + -R | The robust range (assuming 2% outliers on both sides) + | of all voxels + -a | Average of all voxels + -s | Standard deviation of all voxels + -v | Volume of all voxels above 0 (<# voxels> * + | ) + -vl | Volume of each integer label (<# voxels per label> * + | ) + -vp | Volume of all probabilsitic voxels (sum() * + | ) + -n | Count of all voxels above 0 (<# voxels>) + -np | Sum of all fuzzy voxels (sum()) + -e | Entropy of all voxels + -ne | Normalized entropy of all voxels + -x | Location (i j k x y z) of the smallest value in the image + -X | Location (i j k x y z) of the largest value in the image + -c | Location (i j k x y z) of the centre of mass of the + | object + -B | Bounding box of all nonzero voxels + | [ xmin xsize ymin ysize zmin zsize ] + -xvox | Output the number of voxels in the x direction. + | Replace x with y/z for other directions. + -xdim | Output the voxel dimention in the x direction. + | Replace x with y/z for other directions. + + Note: All NaN or Inf are ignored for all stats. + The -m and -t options can be used in conjusction. + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import UnaryStats + >>> node = UnaryStats() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.operation = 'v' + >>> node.cmdline # doctest: +SKIP + 'seg_stats im1.nii -v' + + """ + input_spec = UnaryStatsInput + + +class BinaryStatsInput(StatsInput): + """Input Spec for seg_stats Binary operations.""" + operation = traits.Enum('p', 'sa', 'ss', 'svp', 'al', 'd', 'ncc', 'nmi', + 'Vl', 'Nl', + mandatory=True, + argstr='-%s', + position=4, + desc='operation to perform') + + operand_file = File(exists=True, + argstr="%s", + mandatory=True, + position=5, + xor=["operand_value"], + desc="second image to perform operation with") + + operand_value = traits.Float(argstr='%.8f', + mandatory=True, + position=5, + xor=["operand_file"], + desc='value to perform operation with') + + +class BinaryStats(StatsCommand): + """ + Interface for executable seg_stats from NiftySeg platform. + + Interface to use any binary statistical operations that can be performed + with the seg_stats command-line program. See below for those operations: + -p | The th percentile of all voxels intensity + | (float=[0,100]) + -sa | Average of all voxels + -ss | Standard deviation of all voxels + -svp | Volume of all probabilsitic voxels (sum() * + | ) + -al | Average value in for each label in + -d | Calculate the Dice score between all classes in + | and + -ncc | Normalized cross correlation between and + -nmi | Normalized Mutual Information between and + -Vl | Volume of each integer label . Save to file. + -Nl | Count of each label . Save to file. + + Note: All NaN or Inf are ignored for all stats. + The -m and -t options can be used in conjusction. + + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg + For Documentation, see: + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation + + Examples + -------- + >>> from nipype.interfaces.niftyseg import BinaryStats + >>> node = BinaryStats() + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.operation = 'sa' + >>> node.inputs.operand_value = 2.0 + >>> node.cmdline # doctest: +SKIP + 'seg_stats im1.nii -sa 2' + + """ + input_spec = BinaryStatsInput diff --git a/nipype/interfaces/niftyseg/tests/__init__.py b/nipype/interfaces/niftyseg/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_CalcTopNCC.py b/nipype/interfaces/niftyseg/tests/test_Seg_CalcTopNCC.py new file mode 100644 index 0000000000..d244a04774 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_Seg_CalcTopNCC.py @@ -0,0 +1,38 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, CalcTopNCC +from nipype.testing import skipif, example_data +import pytest + + +@skipif(no_niftyseg(cmd='seg_CalcTopNCC')) +def test_seg_calctopncc(): + + # Create a node object + calctopncc = CalcTopNCC() + + # Check if the command is properly defined + assert calctopncc.cmd == get_custom_path('seg_CalcTopNCC') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + calctopncc.run() + + # Assign some input data + in_file = example_data('im1.nii') + file1 = example_data('im2.nii') + file2 = example_data('im3.nii') + calctopncc.inputs.in_file = in_file + calctopncc.inputs.num_templates = 2 + calctopncc.inputs.in_templates = [file1, file2] + calctopncc.inputs.top_templates = 1 + + cmd_tmp = '{cmd} -target {in_file} -templates 2 {file1} {file2} -n 1' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_CalcTopNCC'), + in_file=in_file, + file1=file1, + file2=file2) + + assert calctopncc.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_EM.py b/nipype/interfaces/niftyseg/tests/test_Seg_EM.py new file mode 100644 index 0000000000..cda6b3edfa --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_Seg_EM.py @@ -0,0 +1,37 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, EM +from nipype.testing import skipif, example_data +import os +import pytest + + +@skipif(no_niftyseg(cmd='seg_EM')) +def test_seg_em(): + + # Create a node object + seg_em = EM() + + # Check if the command is properly defined + assert seg_em.cmd == get_custom_path('seg_EM') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + seg_em.run() + + # Assign some input data + in_file = example_data('im1.nii') + seg_em.inputs.in_file = in_file + seg_em.inputs.no_prior = 4 + + cmd_tmp = '{cmd} -in {in_file} -nopriors 4 -bc_out {bc_out} -out \ +{out_file} -out_outlier {out_outlier}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_EM'), + in_file=in_file, + out_file=os.path.join(os.getcwd(), 'im1_em.nii'), + bc_out=os.path.join(os.getcwd(), 'im1_bc_em.nii'), + out_outlier=os.path.join(os.getcwd(), 'im1_outlier_em.nii')) + + assert seg_em.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_FillLesions.py b/nipype/interfaces/niftyseg/tests/test_Seg_FillLesions.py new file mode 100644 index 0000000000..3f6e8f45c7 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_Seg_FillLesions.py @@ -0,0 +1,36 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, + FillLesions) +from nipype.testing import skipif, example_data +import os +import pytest + + +@skipif(no_niftyseg(cmd='seg_FillLesions')) +def test_seg_filllesions(): + + # Create a node object + seg_fill = FillLesions() + + # Check if the command is properly defined + assert seg_fill.cmd == get_custom_path('seg_FillLesions') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + seg_fill.run() + + # Assign some input data + in_file = example_data('im1.nii') + lesion_mask = example_data('im2.nii') + seg_fill.inputs.in_file = in_file + seg_fill.inputs.lesion_mask = lesion_mask + + expected_cmd = '{cmd} -i {in_file} -l {lesion_mask} -o {out_file}'.format( + cmd=get_custom_path('seg_FillLesions'), + in_file=in_file, + lesion_mask=lesion_mask, + out_file=os.path.join(os.getcwd(), 'im1_lesions_filled.nii')) + + assert seg_fill.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_LabFusion.py b/nipype/interfaces/niftyseg/tests/test_Seg_LabFusion.py new file mode 100644 index 0000000000..6cab2da474 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_Seg_LabFusion.py @@ -0,0 +1,116 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, + LabelFusion) +from nipype.testing import skipif, example_data +import os +import pytest + + +@skipif(no_niftyseg(cmd='seg_LabFusion')) +def test_steps(): + + # Create a node object + steps = LabelFusion() + + # Check if the command is properly defined + assert steps.cmd == get_custom_path('seg_LabFusion') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + steps.run() + + # Assign some input data + in_file = example_data('im1.nii') + file_to_seg = example_data('im2.nii') + template_file = example_data('im3.nii') + steps.inputs.in_file = in_file + steps.inputs.kernel_size = 2.0 + steps.inputs.file_to_seg = file_to_seg + steps.inputs.template_file = template_file + steps.inputs.template_num = 2 + steps.inputs.classifier_type = 'STEPS' + + cmd_tmp = '{cmd} -in {in_file} -STEPS 2.000000 2 {file_to_seg} \ +{template_file} -out {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_LabFusion'), + in_file=in_file, + file_to_seg=file_to_seg, + template_file=template_file, + out_file=os.path.join(os.getcwd(), 'im1_steps.nii')) + + assert steps.cmdline == expected_cmd + + +@skipif(no_niftyseg(cmd='seg_LabFusion')) +def test_staple(): + + # Create a node object + staple = LabelFusion() + + # Check if the command is properly defined + assert staple.cmd == get_custom_path('seg_LabFusion') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + staple.run() + + # Assign some input data + in_file = example_data('im1.nii') + file_to_seg = example_data('im2.nii') + template_file = example_data('im3.nii') + staple.inputs.in_file = in_file + staple.inputs.kernel_size = 2.0 + staple.inputs.file_to_seg = file_to_seg + staple.inputs.template_file = template_file + staple.inputs.template_num = 2 + staple.inputs.classifier_type = 'STAPLE' + + cmd_tmp = '{cmd} -in {in_file} -STAPLE -ALL -out {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_LabFusion'), + in_file=in_file, + file_to_seg=file_to_seg, + template_file=template_file, + out_file=os.path.join(os.getcwd(), 'im1_staple.nii')) + + assert staple.cmdline == expected_cmd + + +@skipif(no_niftyseg(cmd='seg_LabFusion')) +def test_mv(): + + # Create a node object + mv = LabelFusion() + + # Check if the command is properly defined + assert mv.cmd == get_custom_path('seg_LabFusion') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + mv.run() + + # Assign some input data + in_file = example_data('im1.nii') + file_to_seg = example_data('im2.nii') + template_file = example_data('im3.nii') + mv.inputs.in_file = in_file + mv.inputs.file_to_seg = file_to_seg + mv.inputs.template_file = template_file + mv.inputs.template_num = 2 + mv.inputs.classifier_type = 'MV' + mv.inputs.sm_ranking = 'ROINCC' + mv.inputs.dilation_roi = 2 + + cmd_tmp = '{cmd} -in {in_file} -MV -ROINCC 2 2 {file_to_seg} \ +{template_file} -out {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_LabFusion'), + in_file=in_file, + file_to_seg=file_to_seg, + template_file=template_file, + out_file=os.path.join(os.getcwd(), 'im1_mv.nii')) + + assert mv.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py b/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py new file mode 100644 index 0000000000..d07ac89076 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py @@ -0,0 +1,162 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, + UnaryMaths, BinaryMaths, + BinaryMathsInteger, TupleMaths, + Merge) +from nipype.testing import skipif, example_data +import os +import pytest + + +@skipif(no_niftyseg(cmd='seg_maths')) +def test_unary_maths(): + + # Create a node object + unarym = UnaryMaths() + + # Check if the command is properly defined + assert unarym.cmd == get_custom_path('seg_maths') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + unarym.run() + + # Assign some input data + in_file = example_data('im1.nii') + unarym.inputs.in_file = in_file + unarym.inputs.operation = 'otsu' + unarym.inputs.output_datatype = 'float' + + expected_cmd = '{cmd} {in_file} -otsu -odt float {out_file}'.format( + cmd=get_custom_path('seg_maths'), + in_file=in_file, + out_file=os.path.join(os.getcwd(), 'im1_otsu.nii')) + + assert unarym.cmdline == expected_cmd + + +@skipif(no_niftyseg(cmd='seg_maths')) +def test_binary_maths(): + + # Create a node object + binarym = BinaryMaths() + + # Check if the command is properly defined + assert binarym.cmd == get_custom_path('seg_maths') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + binarym.run() + + # Assign some input data + in_file = example_data('im1.nii') + binarym.inputs.in_file = in_file + binarym.inputs.operand_value = 2.0 + binarym.inputs.operation = 'sub' + binarym.inputs.output_datatype = 'float' + + cmd_tmp = '{cmd} {in_file} -sub 2.00000000 -odt float {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_maths'), + in_file=in_file, + out_file=os.path.join(os.getcwd(), 'im1_sub.nii')) + + assert binarym.cmdline == expected_cmd + + +@skipif(no_niftyseg(cmd='seg_maths')) +def test_int_binary_maths(): + + # Create a node object + ibinarym = BinaryMathsInteger() + + # Check if the command is properly defined + assert ibinarym.cmd == get_custom_path('seg_maths') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + ibinarym.run() + + # Assign some input data + in_file = example_data('im1.nii') + ibinarym.inputs.in_file = in_file + ibinarym.inputs.operand_value = 2 + ibinarym.inputs.operation = 'dil' + ibinarym.inputs.output_datatype = 'float' + + expected_cmd = '{cmd} {in_file} -dil 2 -odt float {out_file}'.format( + cmd=get_custom_path('seg_maths'), + in_file=in_file, + out_file=os.path.join(os.getcwd(), 'im1_dil.nii')) + + assert ibinarym.cmdline == expected_cmd + + +@skipif(no_niftyseg(cmd='seg_maths')) +def test_tuple_maths(): + + # Create a node object + tuplem = TupleMaths() + + # Check if the command is properly defined + assert tuplem.cmd == get_custom_path('seg_maths') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + tuplem.run() + + # Assign some input data + in_file = example_data('im1.nii') + op_file = example_data('im2.nii') + tuplem.inputs.in_file = in_file + tuplem.inputs.operation = 'lncc' + tuplem.inputs.operand_file1 = op_file + tuplem.inputs.operand_value2 = 2.0 + tuplem.inputs.output_datatype = 'float' + + cmd_tmp = '{cmd} {in_file} -lncc {op} 2.00000000 -odt float {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_maths'), + in_file=in_file, + op=op_file, + out_file=os.path.join(os.getcwd(), 'im1_lncc.nii')) + + assert tuplem.cmdline == expected_cmd + + +@skipif(no_niftyseg(cmd='seg_maths')) +def test_merge(): + + # Create a node object + merge = Merge() + + # Check if the command is properly defined + assert merge.cmd == get_custom_path('seg_maths') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + merge.run() + + # Assign some input data + in_file = example_data('im1.nii') + file1 = example_data('im2.nii') + file2 = example_data('im3.nii') + merge.inputs.in_file = in_file + merge.inputs.merge_files = [file1, file2] + merge.inputs.dimension = 2 + merge.inputs.output_datatype = 'float' + + cmd_tmp = '{cmd} {in_file} -merge 2 2 {f1} {f2} -odt float {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_maths'), + in_file=in_file, + f1=file1, + f2=file2, + out_file=os.path.join(os.getcwd(), 'im1_merged.nii')) + + print merge.cmdline + print '\n' + print expected_cmd + assert merge.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_PatchMatch.py b/nipype/interfaces/niftyseg/tests/test_Seg_PatchMatch.py new file mode 100644 index 0000000000..a3531f0635 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_Seg_PatchMatch.py @@ -0,0 +1,39 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, PatchMatch +from nipype.testing import skipif, example_data +import os +import pytest + + +@skipif(no_niftyseg(cmd='seg_PatchMatch')) +def test_seg_patchmatch(): + + # Create a node object + seg_patchmatch = PatchMatch() + + # Check if the command is properly defined + assert seg_patchmatch.cmd == get_custom_path('seg_PatchMatch') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + seg_patchmatch.run() + + # Assign some input data + in_file = example_data('im1.nii') + mask_file = example_data('im2.nii') + db_file = example_data('db.xml') + seg_patchmatch.inputs.in_file = in_file + seg_patchmatch.inputs.mask_file = mask_file + seg_patchmatch.inputs.database_file = db_file + + cmd_tmp = '{cmd} -i {in_file} -m {mask_file} -db {db} -o {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_PatchMatch'), + in_file=in_file, + mask_file=mask_file, + db=db_file, + out_file=os.path.join(os.getcwd(), 'im1_pm.nii')) + + assert seg_patchmatch.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_Stats.py b/nipype/interfaces/niftyseg/tests/test_Seg_Stats.py new file mode 100644 index 0000000000..d72dc94f29 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_Seg_Stats.py @@ -0,0 +1,57 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, + UnaryStats, BinaryStats) +from nipype.testing import skipif, example_data +import pytest + + +@skipif(no_niftyseg(cmd='seg_stats')) +def test_unary_stats(): + + # Create a node object + unarys = UnaryStats() + + # Check if the command is properly defined + assert unarys.cmd == get_custom_path('seg_stats') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + unarys.run() + + # Assign some input data + in_file = example_data('im1.nii') + unarys.inputs.in_file = in_file + unarys.inputs.operation = 'a' + + expected_cmd = '{cmd} {in_file} -a'.format( + cmd=get_custom_path('seg_stats'), + in_file=in_file) + + assert unarys.cmdline == expected_cmd + + +@skipif(no_niftyseg(cmd='seg_stats')) +def test_binary_stats(): + # Create a node object + binarys = BinaryStats() + + # Check if the command is properly defined + assert binarys.cmd == get_custom_path('seg_stats') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + binarys.run() + + # Assign some input data + in_file = example_data('im1.nii') + binarys.inputs.in_file = in_file + binarys.inputs.operand_value = 2 + binarys.inputs.operation = 'sa' + + expected_cmd = '{cmd} {in_file} -sa 2.00000000'.format( + cmd=get_custom_path('seg_stats'), + in_file=in_file) + + assert binarys.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_auto_BinaryMaths.py b/nipype/interfaces/niftyseg/tests/test_auto_BinaryMaths.py new file mode 100644 index 0000000000..1fb1531976 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_BinaryMaths.py @@ -0,0 +1,62 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..maths import BinaryMaths + + +def test_BinaryMaths_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + operand_file=dict(argstr='%s', + mandatory=True, + position=5, + xor=['operand_value', 'operand_str'], + ), + operand_str=dict(argstr='%s', + mandatory=True, + position=5, + xor=['operand_value', 'operand_file'], + ), + operand_value=dict(argstr='%.8f', + mandatory=True, + position=5, + xor=['operand_file', 'operand_str'], + ), + operation=dict(argstr='-%s', + mandatory=True, + position=4, + ), + out_file=dict(argstr='%s', + genfile=True, + position=-2, + ), + output_datatype=dict(argstr='-odt %s', + position=-3, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = BinaryMaths.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_BinaryMaths_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = BinaryMaths.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_BinaryMathsInteger.py b/nipype/interfaces/niftyseg/tests/test_auto_BinaryMathsInteger.py new file mode 100644 index 0000000000..b596d4f468 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_BinaryMathsInteger.py @@ -0,0 +1,51 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..maths import BinaryMathsInteger + + +def test_BinaryMathsInteger_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + operand_value=dict(argstr='%d', + mandatory=True, + position=5, + ), + operation=dict(argstr='-%s', + mandatory=True, + position=4, + ), + out_file=dict(argstr='%s', + genfile=True, + position=-2, + ), + output_datatype=dict(argstr='-odt %s', + position=-3, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = BinaryMathsInteger.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_BinaryMathsInteger_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = BinaryMathsInteger.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_BinaryStats.py b/nipype/interfaces/niftyseg/tests/test_auto_BinaryStats.py new file mode 100644 index 0000000000..9546286202 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_BinaryStats.py @@ -0,0 +1,58 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..stats import BinaryStats + + +def test_BinaryStats_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + larger_voxel=dict(argstr='-t %f', + mandatory=False, + position=-3, + ), + mask_file=dict(argstr='-m %s', + mandatory=False, + position=-2, + ), + operand_file=dict(argstr='%s', + mandatory=True, + position=5, + xor=['operand_value'], + ), + operand_value=dict(argstr='%.8f', + mandatory=True, + position=5, + xor=['operand_file'], + ), + operation=dict(argstr='-%s', + mandatory=True, + position=4, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = BinaryStats.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_BinaryStats_outputs(): + output_map = dict(output=dict(), + ) + outputs = BinaryStats.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_CalcTopNCC.py b/nipype/interfaces/niftyseg/tests/test_auto_CalcTopNCC.py new file mode 100644 index 0000000000..750426acc1 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_CalcTopNCC.py @@ -0,0 +1,51 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..label_fusion import CalcTopNCC + + +def test_CalcTopNCC_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='-target %s', + mandatory=True, + position=1, + ), + in_templates=dict(argstr='%s', + mandatory=True, + position=3, + ), + mask_file=dict(argstr='-mask %s', + mandatory=False, + ), + num_templates=dict(argstr='-templates %s', + mandatory=True, + position=2, + ), + terminal_output=dict(nohash=True, + ), + top_templates=dict(argstr='-n %s', + mandatory=True, + position=4, + ), + ) + inputs = CalcTopNCC.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_CalcTopNCC_outputs(): + output_map = dict(out_files=dict(), + ) + outputs = CalcTopNCC.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_EM.py b/nipype/interfaces/niftyseg/tests/test_auto_EM.py new file mode 100644 index 0000000000..c551e09536 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_EM.py @@ -0,0 +1,77 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..em import EM + + +def test_EM_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + bc_order_val=dict(argstr='-bc_order %s', + ), + bc_thresh_val=dict(argstr='-bc_thresh %s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='-in %s', + mandatory=True, + position=4, + ), + mask_file=dict(argstr='-mask %s', + ), + max_iter=dict(argstr='-max_iter %s', + ), + min_iter=dict(argstr='-min_iter %s', + ), + mrf_beta_val=dict(argstr='-mrf_beta %s', + ), + no_prior=dict(argstr='-nopriors %s', + mandatory=True, + xor=['prior_4D', 'priors'], + ), + out_bc_file=dict(argstr='-bc_out %s', + genfile=True, + ), + out_file=dict(argstr='-out %s', + genfile=True, + ), + out_outlier_file=dict(argstr='-out_outlier %s', + genfile=True, + ), + outlier_val=dict(argstr='-outlier %s %s', + ), + prior_4D=dict(argstr='-prior4D %s', + mandatory=True, + xor=['no_prior', 'priors'], + ), + priors=dict(argstr='%s', + mandatory=True, + xor=['no_prior', 'prior_4D'], + ), + reg_val=dict(argstr='-reg %s', + ), + relax_priors=dict(argstr='-rf %s %s', + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = EM.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_EM_outputs(): + output_map = dict(out_bc_file=dict(), + out_file=dict(), + out_outlier_file=dict(), + ) + outputs = EM.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py b/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py new file mode 100644 index 0000000000..0647153ecb --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py @@ -0,0 +1,78 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..lesions import FillLesions + + +def test_FillLesions_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + bin_mask=dict(argstr='-mask %s', + mandatory=False, + ), + cwf=dict(argstr='-cwf %f', + mandatory=False, + ), + debug=dict(argstr='-debug', + mandatory=False, + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_dilation=dict(argstr='-dil %d', + mandatory=False, + ), + in_file=dict(argstr='-i %s', + mandatory=True, + position=1, + ), + lesion_mask=dict(argstr='-l %s', + mandatory=True, + position=2, + ), + match=dict(argstr='-match %f', + mandatory=False, + ), + omp_core=dict(argstr='-omp %d', + ), + other=dict(argstr='-other', + mandatory=False, + ), + out_datatype=dict(argstr='-odt %s', + mandatory=False, + ), + out_file=dict(argstr='-o %s', + position=3, + ), + search=dict(argstr='-search %f', + mandatory=False, + ), + size=dict(argstr='-size %d', + mandatory=False, + ), + smooth=dict(argstr='-smo %f', + mandatory=False, + ), + terminal_output=dict(nohash=True, + ), + verbose=dict(argstr='-v', + mandatory=False, + ), + ) + inputs = FillLesions.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_FillLesions_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = FillLesions.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_LabelFusion.py b/nipype/interfaces/niftyseg/tests/test_auto_LabelFusion.py new file mode 100644 index 0000000000..0366f3e79c --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_LabelFusion.py @@ -0,0 +1,75 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..label_fusion import LabelFusion + + +def test_LabelFusion_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + classifier_type=dict(argstr='-%s', + mandatory=True, + position=2, + ), + conv=dict(argstr='-conv %f', + ), + dilation_roi=dict(), + environ=dict(nohash=True, + usedefault=True, + ), + file_to_seg=dict(mandatory=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='-in %s', + mandatory=True, + position=1, + ), + kernel_size=dict(), + mask_file=dict(argstr='-mask %s', + ), + max_iter=dict(argstr='-max_iter %d', + ), + mrf_value=dict(argstr='-MRF_beta %f', + ), + out_file=dict(argstr='-out %s', + genfile=True, + ), + prob_flag=dict(argstr='-outProb', + ), + prob_update_flag=dict(argstr='-prop_update', + ), + proportion=dict(argstr='-prop %s', + ), + set_pq=dict(argstr='-setPQ %f %f', + ), + sm_ranking=dict(argstr='-%s', + position=3, + usedefault=True, + ), + template_file=dict(), + template_num=dict(), + terminal_output=dict(nohash=True, + ), + unc=dict(argstr='-unc', + ), + unc_thresh=dict(argstr='-uncthres %f', + ), + verbose=dict(argstr='-v %s', + ), + ) + inputs = LabelFusion.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_LabelFusion_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = LabelFusion.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_MathsCommand.py b/nipype/interfaces/niftyseg/tests/test_auto_MathsCommand.py new file mode 100644 index 0000000000..8e22033d1b --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_MathsCommand.py @@ -0,0 +1,43 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..maths import MathsCommand + + +def test_MathsCommand_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + out_file=dict(argstr='%s', + genfile=True, + position=-2, + ), + output_datatype=dict(argstr='-odt %s', + position=-3, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = MathsCommand.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_MathsCommand_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = MathsCommand.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_Merge.py b/nipype/interfaces/niftyseg/tests/test_auto_Merge.py new file mode 100644 index 0000000000..a6c09b88f8 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_Merge.py @@ -0,0 +1,49 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..maths import Merge + + +def test_Merge_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + dimension=dict(mandatory=True, + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + merge_files=dict(argstr='%s', + mandatory=True, + position=4, + ), + out_file=dict(argstr='%s', + genfile=True, + position=-2, + ), + output_datatype=dict(argstr='-odt %s', + position=-3, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = Merge.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_Merge_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = Merge.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py b/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py new file mode 100644 index 0000000000..55dc5d9d1d --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py @@ -0,0 +1,23 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..base import NiftySegCommand + + +def test_NiftySegCommand_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = NiftySegCommand.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + diff --git a/nipype/interfaces/niftyseg/tests/test_auto_PatchMatch.py b/nipype/interfaces/niftyseg/tests/test_auto_PatchMatch.py new file mode 100644 index 0000000000..e9bae21fcc --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_PatchMatch.py @@ -0,0 +1,64 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..patchmatch import PatchMatch + + +def test_PatchMatch_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + cs_size=dict(argstr='-cs %i', + mandatory=False, + ), + database_file=dict(argstr='-db %s', + genfile=True, + mandatory=True, + position=3, + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='-i %s', + mandatory=True, + position=1, + ), + it_num=dict(argstr='-it %i', + mandatory=False, + ), + mask_file=dict(argstr='-m %s', + mandatory=True, + position=2, + ), + match_num=dict(argstr='-match %i', + mandatory=False, + ), + out_file=dict(argstr='-o %s', + genfile=True, + position=4, + ), + patch_size=dict(argstr='-size %i', + mandatory=False, + ), + pm_num=dict(argstr='-pm %i', + mandatory=False, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = PatchMatch.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_PatchMatch_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = PatchMatch.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_StatsCommand.py b/nipype/interfaces/niftyseg/tests/test_auto_StatsCommand.py new file mode 100644 index 0000000000..c7c7f2b364 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_StatsCommand.py @@ -0,0 +1,44 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..stats import StatsCommand + + +def test_StatsCommand_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + larger_voxel=dict(argstr='-t %f', + mandatory=False, + position=-3, + ), + mask_file=dict(argstr='-m %s', + mandatory=False, + position=-2, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = StatsCommand.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_StatsCommand_outputs(): + output_map = dict(output=dict(), + ) + outputs = StatsCommand.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_TupleMaths.py b/nipype/interfaces/niftyseg/tests/test_auto_TupleMaths.py new file mode 100644 index 0000000000..1e63c1fcb3 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_TupleMaths.py @@ -0,0 +1,67 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..maths import TupleMaths + + +def test_TupleMaths_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + operand_file1=dict(argstr='%s', + mandatory=True, + position=5, + xor=['operand_value1'], + ), + operand_file2=dict(argstr='%s', + mandatory=True, + position=6, + xor=['operand_value2'], + ), + operand_value1=dict(argstr='%.8f', + mandatory=True, + position=5, + xor=['operand_file1'], + ), + operand_value2=dict(argstr='%.8f', + mandatory=True, + position=6, + xor=['operand_file2'], + ), + operation=dict(argstr='-%s', + mandatory=True, + position=4, + ), + out_file=dict(argstr='%s', + genfile=True, + position=-2, + ), + output_datatype=dict(argstr='-odt %s', + position=-3, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = TupleMaths.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_TupleMaths_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = TupleMaths.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_UnaryMaths.py b/nipype/interfaces/niftyseg/tests/test_auto_UnaryMaths.py new file mode 100644 index 0000000000..500de81852 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_UnaryMaths.py @@ -0,0 +1,47 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..maths import UnaryMaths + + +def test_UnaryMaths_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + operation=dict(argstr='-%s', + mandatory=True, + position=4, + ), + out_file=dict(argstr='%s', + genfile=True, + position=-2, + ), + output_datatype=dict(argstr='-odt %s', + position=-3, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = UnaryMaths.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_UnaryMaths_outputs(): + output_map = dict(out_file=dict(), + ) + outputs = UnaryMaths.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_UnaryStats.py b/nipype/interfaces/niftyseg/tests/test_auto_UnaryStats.py new file mode 100644 index 0000000000..cfbde15114 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_UnaryStats.py @@ -0,0 +1,48 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..stats import UnaryStats + + +def test_UnaryStats_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='%s', + mandatory=True, + position=2, + ), + larger_voxel=dict(argstr='-t %f', + mandatory=False, + position=-3, + ), + mask_file=dict(argstr='-m %s', + mandatory=False, + position=-2, + ), + operation=dict(argstr='-%s', + mandatory=True, + position=4, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = UnaryStats.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_UnaryStats_outputs(): + output_map = dict(output=dict(), + ) + outputs = UnaryStats.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/setup.py b/nipype/interfaces/setup.py index 4c79456824..044ab02574 100644 --- a/nipype/interfaces/setup.py +++ b/nipype/interfaces/setup.py @@ -22,6 +22,7 @@ def configuration(parent_package='', top_path=None): config.add_subpackage('mne') config.add_subpackage('mrtrix') config.add_subpackage('mrtrix3') + config.add_subpackage('niftyseg') config.add_subpackage('nipy') config.add_subpackage('spm') config.add_subpackage('slicer') From 013bf72b28cb7472d1347764278c915fd3b0fd7b Mon Sep 17 00:00:00 2001 From: byvernault Date: Tue, 28 Mar 2017 13:08:39 +0100 Subject: [PATCH 02/17] Adding db.xml to data for testing purpose. --- nipype/testing/data/db.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 nipype/testing/data/db.xml diff --git a/nipype/testing/data/db.xml b/nipype/testing/data/db.xml new file mode 100644 index 0000000000..e69de29bb2 From f431e0c59c9dc09e5ac6bcceff805104d5ffd042 Mon Sep 17 00:00:00 2001 From: byvernault Date: Wed, 29 Mar 2017 11:47:14 +0100 Subject: [PATCH 03/17] Converting files to python2/3 compatibility --- nipype/interfaces/niftyseg/label_fusion.py | 1 + nipype/interfaces/niftyseg/maths.py | 1 - nipype/interfaces/niftyseg/stats.py | 3 ++- nipype/interfaces/niftyseg/tests/test_Seg_Maths.py | 3 --- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/nipype/interfaces/niftyseg/label_fusion.py b/nipype/interfaces/niftyseg/label_fusion.py index d00500592d..1db64dc4f4 100644 --- a/nipype/interfaces/niftyseg/label_fusion.py +++ b/nipype/interfaces/niftyseg/label_fusion.py @@ -6,6 +6,7 @@ that can be performed with the seg_LabFusion command-line program. """ +from builtins import str import os import warnings diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 3a6e69c461..4f798cfeac 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -414,7 +414,6 @@ class Merge(MathsCommand): def _format_arg(self, opt, spec, val): """Convert input to appropriate format for seg_maths.""" - print opt if opt == 'merge_files': return "-merge %d %d %s" % (len(val), self.inputs.dimension, ' '.join(val)) diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index a81c1d979e..d89fcce00d 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -4,6 +4,7 @@ The stats module provides higher-level interfaces to some of the operations that can be performed with the niftysegstats (seg_stats) command-line program. """ +from __future__ import print_function import numpy as np from ..base import TraitedSpec, File, traits, CommandLineInputSpec @@ -48,7 +49,7 @@ class StatsCommand(NiftySegCommand): def _parse_stdout(self, stdout): out = [] for string_line in stdout.split("\n"): - print('parsing line ' + string_line) + print('parsing line {0}'.format(string_line)) if string_line.startswith('#'): continue if len(string_line) <= 1: diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py b/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py index d07ac89076..cc18a4d5cd 100644 --- a/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py +++ b/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py @@ -156,7 +156,4 @@ def test_merge(): f2=file2, out_file=os.path.join(os.getcwd(), 'im1_merged.nii')) - print merge.cmdline - print '\n' - print expected_cmd assert merge.cmdline == expected_cmd From c7e43eada8f123be0ba24b45011f67348de7dda2 Mon Sep 17 00:00:00 2001 From: Benjamin Yvernault Date: Fri, 31 Mar 2017 15:58:23 +0200 Subject: [PATCH 04/17] Editing docstring to follow nipype template and add some tests. --- nipype/interfaces/niftyseg/em.py | 12 +- nipype/interfaces/niftyseg/label_fusion.py | 24 ++-- nipype/interfaces/niftyseg/lesions.py | 14 +- nipype/interfaces/niftyseg/maths.py | 38 +++--- nipype/interfaces/niftyseg/patchmatch.py | 17 ++- nipype/interfaces/niftyseg/stats.py | 21 ++- .../niftyseg/tests/test_Seg_CalcTopNCC.py | 38 ------ .../niftyseg/tests/test_Seg_LabFusion.py | 116 ----------------- .../tests/{test_Seg_EM.py => test_em.py} | 8 +- .../niftyseg/tests/test_label_fusion.py | 123 ++++++++++++++++++ ...est_Seg_FillLesions.py => test_lesions.py} | 14 +- .../{test_Seg_Maths.py => test_maths.py} | 17 ++- ...t_Seg_PatchMatch.py => test_patchmatch.py} | 16 ++- .../{test_Seg_Stats.py => test_stats.py} | 11 +- 14 files changed, 245 insertions(+), 224 deletions(-) delete mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_CalcTopNCC.py delete mode 100644 nipype/interfaces/niftyseg/tests/test_Seg_LabFusion.py rename nipype/interfaces/niftyseg/tests/{test_Seg_EM.py => test_em.py} (87%) create mode 100644 nipype/interfaces/niftyseg/tests/test_label_fusion.py rename nipype/interfaces/niftyseg/tests/{test_Seg_FillLesions.py => test_lesions.py} (72%) rename nipype/interfaces/niftyseg/tests/{test_Seg_Maths.py => test_maths.py} (88%) rename nipype/interfaces/niftyseg/tests/{test_Seg_PatchMatch.py => test_patchmatch.py} (73%) rename nipype/interfaces/niftyseg/tests/{test_Seg_Stats.py => test_stats.py} (81%) diff --git a/nipype/interfaces/niftyseg/em.py b/nipype/interfaces/niftyseg/em.py index 6d9964911d..20a0eeeb1d 100644 --- a/nipype/interfaces/niftyseg/em.py +++ b/nipype/interfaces/niftyseg/em.py @@ -10,6 +10,12 @@ Examples -------- See the docstrings of the individual classes for examples. + +Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) + >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) + >>> os.chdir(datadir) """ import os @@ -116,9 +122,9 @@ class EM(NiftySegCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import EM - >>> node = EM() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.EM() + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.no_prior = 4 >>> node.cmdline # doctest: +SKIP 'seg_EM -in im1.nii -nopriors 4 -bc_out im1_bc_em.nii -out im1_em.nii \ diff --git a/nipype/interfaces/niftyseg/label_fusion.py b/nipype/interfaces/niftyseg/label_fusion.py index 1db64dc4f4..cfeb58aaad 100644 --- a/nipype/interfaces/niftyseg/label_fusion.py +++ b/nipype/interfaces/niftyseg/label_fusion.py @@ -4,6 +4,12 @@ """ The fusion module provides higher-level interfaces to some of the operations that can be performed with the seg_LabFusion command-line program. + +Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) + >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) + >>> os.chdir(datadir) """ from builtins import str @@ -114,12 +120,12 @@ class LabelFusion(NiftySegCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import LabelFusion - >>> node = LabelFusion() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.LabelFusion() + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.kernel_size = 2.0 - >>> node.inputs.file_to_seg = 'im2.nii' # doctest: +SKIP - >>> node.inputs.template_file = 'im3.nii' # doctest: +SKIP + >>> node.inputs.file_to_seg = 'im2.nii' + >>> node.inputs.template_file = 'im3.nii' >>> node.inputs.template_num = 2 >>> node.inputs.classifier_type = 'STEPS' >>> node.cmdline # doctest: +SKIP @@ -277,11 +283,11 @@ class CalcTopNCC(NiftySegCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import CalcTopNCC - >>> node = CalcTopNCC() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.CalcTopNCC() + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.num_templates = 2 - >>> node.inputs.in_templates = ['im2.nii', 'im3.nii'] # doctest: +SKIP + >>> node.inputs.in_templates = ['im2.nii', 'im3.nii'] >>> node.inputs.top_templates = 1 >>> node.cmdline # doctest: +SKIP 'seg_CalcTopNCC -target im1.nii -templates 2 im2.nii im3.nii -n 1' diff --git a/nipype/interfaces/niftyseg/lesions.py b/nipype/interfaces/niftyseg/lesions.py index edbfd978e7..f2f07ee324 100644 --- a/nipype/interfaces/niftyseg/lesions.py +++ b/nipype/interfaces/niftyseg/lesions.py @@ -10,6 +10,12 @@ Examples -------- See the docstrings of the individual classes for examples. + +Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) + >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) + >>> os.chdir(datadir) """ import os @@ -98,10 +104,10 @@ class FillLesions(NiftySegCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import FillLesions - >>> node = FillLesions() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP - >>> node.inputs.lesion_mask = 'im2.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.FillLesions() + >>> node.inputs.in_file = 'im1.nii' + >>> node.inputs.lesion_mask = 'im2.nii' >>> node.cmdline # doctest: +SKIP 'seg_FillLesions -i im1.nii -l im2.nii -o im1_lesions_filled.nii' diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 4f798cfeac..1b1faad604 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -10,6 +10,12 @@ Examples -------- See the docstrings of the individual classes for examples. + +Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) + >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) + >>> os.chdir(datadir) """ import os @@ -125,9 +131,9 @@ class UnaryMaths(MathsCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import UnaryMaths - >>> node = UnaryMaths() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.UnaryMaths() + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'sqrt' >>> node.inputs.output_datatype = 'float' >>> node.cmdline # doctest: +SKIP @@ -212,11 +218,11 @@ class BinaryMaths(MathsCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import BinaryMaths - >>> node = BinaryMaths() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.BinaryMaths() + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'sub' - >>> node.inputs.operand_file = 'im2.nii' # doctest: +SKIP + >>> node.inputs.operand_file = 'im2.nii' >>> node.inputs.output_datatype = 'float' >>> node.cmdline # doctest: +SKIP 'seg_maths im1.nii -odt float -sub im2.nii im1_sub.nii.gz' @@ -289,7 +295,7 @@ class BinaryMathsInteger(MathsCommand): -------- >>> from nipype.interfaces.niftyseg import BinaryMathsInteger >>> node = BinaryMathsInteger() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'dil' >>> node.inputs.operand_value = 2 >>> node.inputs.output_datatype = 'float' @@ -357,11 +363,11 @@ class TupleMaths(MathsCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import TupleMaths - >>> node = TupleMaths() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.TupleMaths() + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'lncc' - >>> node.inputs.operand_file1 = 'im2.nii' # doctest: +SKIP + >>> node.inputs.operand_file1 = 'im2.nii' >>> node.inputs.operand_value2 = 2.0 >>> node.inputs.output_datatype = 'float' >>> node.cmdline # doctest: +SKIP @@ -398,11 +404,11 @@ class Merge(MathsCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import Merge - >>> node = Merge() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.Merge() + >>> node.inputs.in_file = 'im1.nii' >>> files = ['im2.nii', 'im3.nii'] - >>> node.inputs.merge_files = files # doctest: +SKIP + >>> node.inputs.merge_files = files >>> node.inputs.dimension = 2 >>> node.inputs.output_datatype = 'float' >>> node.cmdline # doctest: +SKIP diff --git a/nipype/interfaces/niftyseg/patchmatch.py b/nipype/interfaces/niftyseg/patchmatch.py index 50613758da..eea59d9be2 100644 --- a/nipype/interfaces/niftyseg/patchmatch.py +++ b/nipype/interfaces/niftyseg/patchmatch.py @@ -1,8 +1,15 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: + """ The fusion module provides higher-level interfaces to some of the operations that can be performed with the seg_DetectLesions command-line program. + +Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) + >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) + >>> os.chdir(datadir) """ import os import warnings @@ -93,11 +100,11 @@ class PatchMatch(NiftySegCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import PatchMatch - >>> node = PatchMatch() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP - >>> node.inputs.mask_file = 'im2.nii' # doctest: +SKIP - >>> node.inputs.database_file = 'db.xml' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.PatchMatch() + >>> node.inputs.in_file = 'im1.nii' + >>> node.inputs.mask_file = 'im2.nii' + >>> node.inputs.database_file = 'db.xml' >>> node.cmdline # doctest: +SKIP 'seg_PatchMatch -i im1.nii -m im2.nii -db db.xml -o im1_pm.nii' diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index d89fcce00d..4e5b8a5011 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -1,8 +1,15 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: + """ The stats module provides higher-level interfaces to some of the operations -that can be performed with the niftysegstats (seg_stats) command-line program. +that can be performed with the niftyseg stats (seg_stats) command-line program. + +Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) + >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) + >>> os.chdir(datadir) """ from __future__ import print_function import numpy as np @@ -121,9 +128,9 @@ class UnaryStats(StatsCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import UnaryStats - >>> node = UnaryStats() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.UnaryStats() + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'v' >>> node.cmdline # doctest: +SKIP 'seg_stats im1.nii -v' @@ -184,9 +191,9 @@ class BinaryStats(StatsCommand): Examples -------- - >>> from nipype.interfaces.niftyseg import BinaryStats - >>> node = BinaryStats() - >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP + >>> from nipype.interfaces import niftyseg + >>> node = niftyseg.BinaryStats() + >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'sa' >>> node.inputs.operand_value = 2.0 >>> node.cmdline # doctest: +SKIP diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_CalcTopNCC.py b/nipype/interfaces/niftyseg/tests/test_Seg_CalcTopNCC.py deleted file mode 100644 index d244a04774..0000000000 --- a/nipype/interfaces/niftyseg/tests/test_Seg_CalcTopNCC.py +++ /dev/null @@ -1,38 +0,0 @@ -# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- -# vi: set ft=python sts=4 ts=4 sw=4 et: - -from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, CalcTopNCC -from nipype.testing import skipif, example_data -import pytest - - -@skipif(no_niftyseg(cmd='seg_CalcTopNCC')) -def test_seg_calctopncc(): - - # Create a node object - calctopncc = CalcTopNCC() - - # Check if the command is properly defined - assert calctopncc.cmd == get_custom_path('seg_CalcTopNCC') - - # test raising error with mandatory args absent - with pytest.raises(ValueError): - calctopncc.run() - - # Assign some input data - in_file = example_data('im1.nii') - file1 = example_data('im2.nii') - file2 = example_data('im3.nii') - calctopncc.inputs.in_file = in_file - calctopncc.inputs.num_templates = 2 - calctopncc.inputs.in_templates = [file1, file2] - calctopncc.inputs.top_templates = 1 - - cmd_tmp = '{cmd} -target {in_file} -templates 2 {file1} {file2} -n 1' - expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_CalcTopNCC'), - in_file=in_file, - file1=file1, - file2=file2) - - assert calctopncc.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_LabFusion.py b/nipype/interfaces/niftyseg/tests/test_Seg_LabFusion.py deleted file mode 100644 index 6cab2da474..0000000000 --- a/nipype/interfaces/niftyseg/tests/test_Seg_LabFusion.py +++ /dev/null @@ -1,116 +0,0 @@ -# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- -# vi: set ft=python sts=4 ts=4 sw=4 et: - -from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, - LabelFusion) -from nipype.testing import skipif, example_data -import os -import pytest - - -@skipif(no_niftyseg(cmd='seg_LabFusion')) -def test_steps(): - - # Create a node object - steps = LabelFusion() - - # Check if the command is properly defined - assert steps.cmd == get_custom_path('seg_LabFusion') - - # test raising error with mandatory args absent - with pytest.raises(ValueError): - steps.run() - - # Assign some input data - in_file = example_data('im1.nii') - file_to_seg = example_data('im2.nii') - template_file = example_data('im3.nii') - steps.inputs.in_file = in_file - steps.inputs.kernel_size = 2.0 - steps.inputs.file_to_seg = file_to_seg - steps.inputs.template_file = template_file - steps.inputs.template_num = 2 - steps.inputs.classifier_type = 'STEPS' - - cmd_tmp = '{cmd} -in {in_file} -STEPS 2.000000 2 {file_to_seg} \ -{template_file} -out {out_file}' - expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_LabFusion'), - in_file=in_file, - file_to_seg=file_to_seg, - template_file=template_file, - out_file=os.path.join(os.getcwd(), 'im1_steps.nii')) - - assert steps.cmdline == expected_cmd - - -@skipif(no_niftyseg(cmd='seg_LabFusion')) -def test_staple(): - - # Create a node object - staple = LabelFusion() - - # Check if the command is properly defined - assert staple.cmd == get_custom_path('seg_LabFusion') - - # test raising error with mandatory args absent - with pytest.raises(ValueError): - staple.run() - - # Assign some input data - in_file = example_data('im1.nii') - file_to_seg = example_data('im2.nii') - template_file = example_data('im3.nii') - staple.inputs.in_file = in_file - staple.inputs.kernel_size = 2.0 - staple.inputs.file_to_seg = file_to_seg - staple.inputs.template_file = template_file - staple.inputs.template_num = 2 - staple.inputs.classifier_type = 'STAPLE' - - cmd_tmp = '{cmd} -in {in_file} -STAPLE -ALL -out {out_file}' - expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_LabFusion'), - in_file=in_file, - file_to_seg=file_to_seg, - template_file=template_file, - out_file=os.path.join(os.getcwd(), 'im1_staple.nii')) - - assert staple.cmdline == expected_cmd - - -@skipif(no_niftyseg(cmd='seg_LabFusion')) -def test_mv(): - - # Create a node object - mv = LabelFusion() - - # Check if the command is properly defined - assert mv.cmd == get_custom_path('seg_LabFusion') - - # test raising error with mandatory args absent - with pytest.raises(ValueError): - mv.run() - - # Assign some input data - in_file = example_data('im1.nii') - file_to_seg = example_data('im2.nii') - template_file = example_data('im3.nii') - mv.inputs.in_file = in_file - mv.inputs.file_to_seg = file_to_seg - mv.inputs.template_file = template_file - mv.inputs.template_num = 2 - mv.inputs.classifier_type = 'MV' - mv.inputs.sm_ranking = 'ROINCC' - mv.inputs.dilation_roi = 2 - - cmd_tmp = '{cmd} -in {in_file} -MV -ROINCC 2 2 {file_to_seg} \ -{template_file} -out {out_file}' - expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_LabFusion'), - in_file=in_file, - file_to_seg=file_to_seg, - template_file=template_file, - out_file=os.path.join(os.getcwd(), 'im1_mv.nii')) - - assert mv.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_EM.py b/nipype/interfaces/niftyseg/tests/test_em.py similarity index 87% rename from nipype/interfaces/niftyseg/tests/test_Seg_EM.py rename to nipype/interfaces/niftyseg/tests/test_em.py index cda6b3edfa..e9ab8b9347 100644 --- a/nipype/interfaces/niftyseg/tests/test_Seg_EM.py +++ b/nipype/interfaces/niftyseg/tests/test_em.py @@ -2,12 +2,13 @@ # vi: set ft=python sts=4 ts=4 sw=4 et: from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, EM -from nipype.testing import skipif, example_data +from nipype.testing import example_data import os import pytest -@skipif(no_niftyseg(cmd='seg_EM')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_EM'), + reason="niftyseg is not installed") def test_seg_em(): # Create a node object @@ -32,6 +33,7 @@ def test_seg_em(): in_file=in_file, out_file=os.path.join(os.getcwd(), 'im1_em.nii'), bc_out=os.path.join(os.getcwd(), 'im1_bc_em.nii'), - out_outlier=os.path.join(os.getcwd(), 'im1_outlier_em.nii')) + out_outlier=os.path.join(os.getcwd(), 'im1_outlier_em.nii') + ) assert seg_em.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_label_fusion.py b/nipype/interfaces/niftyseg/tests/test_label_fusion.py new file mode 100644 index 0000000000..fd0140c42b --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_label_fusion.py @@ -0,0 +1,123 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, + LabelFusion, CalcTopNCC) +from nipype.testing import example_data +import os +import pytest + + +@pytest.mark.skipif(no_niftyseg(cmd='seg_LabFusion'), + reason="niftyseg is not installed") +def test_seg_lab_fusion(): + """ Test interfaces for seg_labfusion""" + # Create a node object + steps = LabelFusion() + + # Check if the command is properly defined + assert steps.cmd == get_custom_path('seg_LabFusion') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + steps.run() + + # Assign some input data + in_file = example_data('im1.nii') + file_to_seg = example_data('im2.nii') + template_file = example_data('im3.nii') + steps.inputs.in_file = in_file + steps.inputs.kernel_size = 2.0 + steps.inputs.file_to_seg = file_to_seg + steps.inputs.template_file = template_file + steps.inputs.template_num = 2 + steps.inputs.classifier_type = 'STEPS' + + cmd_tmp = '{cmd} -in {in_file} -STEPS 2.000000 2 {file_to_seg} \ +{template_file} -out {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_LabFusion'), + in_file=in_file, + file_to_seg=file_to_seg, + template_file=template_file, + out_file=os.path.join(os.getcwd(), 'im1_steps.nii') + ) + + assert steps.cmdline == expected_cmd + + # Staple + staple = LabelFusion(kernel_size=2.0, template_num=2, + classifier_type='STAPLE') + in_file = example_data('im1.nii') + file_to_seg = example_data('im2.nii') + template_file = example_data('im3.nii') + staple.inputs.in_file = in_file + staple.inputs.file_to_seg = file_to_seg + staple.inputs.template_file = template_file + + cmd_tmp = '{cmd} -in {in_file} -STAPLE -ALL -out {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_LabFusion'), + in_file=in_file, + file_to_seg=file_to_seg, + template_file=template_file, + out_file=os.path.join(os.getcwd(), 'im1_staple.nii') + ) + + assert staple.cmdline == expected_cmd + + # Assign some input data + mv_node = LabelFusion(template_num=2, classifier_type='MV', + sm_ranking='ROINCC', dilation_roi=2) + in_file = example_data('im1.nii') + file_to_seg = example_data('im2.nii') + template_file = example_data('im3.nii') + mv_node.inputs.in_file = in_file + mv_node.inputs.file_to_seg = file_to_seg + mv_node.inputs.template_file = template_file + + cmd_tmp = '{cmd} -in {in_file} -MV -ROINCC 2 2 {file_to_seg} \ +{template_file} -out {out_file}' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_LabFusion'), + in_file=in_file, + file_to_seg=file_to_seg, + template_file=template_file, + out_file=os.path.join(os.getcwd(), 'im1_mv.nii') + ) + + assert mv_node.cmdline == expected_cmd + + +@pytest.mark.skipif(no_niftyseg(cmd='seg_CalcTopNCC'), + reason="niftyseg is not installed") +def test_seg_calctopncc(): + """ Test interfaces for seg_CalctoNCC""" + # Create a node object + calctopncc = CalcTopNCC() + + # Check if the command is properly defined + assert calctopncc.cmd == get_custom_path('seg_CalcTopNCC') + + # test raising error with mandatory args absent + with pytest.raises(ValueError): + calctopncc.run() + + # Assign some input data + in_file = example_data('im1.nii') + file1 = example_data('im2.nii') + file2 = example_data('im3.nii') + calctopncc.inputs.in_file = in_file + calctopncc.inputs.num_templates = 2 + calctopncc.inputs.in_templates = [file1, file2] + calctopncc.inputs.top_templates = 1 + + cmd_tmp = '{cmd} -target {in_file} -templates 2 {file1} {file2} -n 1' + expected_cmd = cmd_tmp.format( + cmd=get_custom_path('seg_CalcTopNCC'), + in_file=in_file, + file1=file1, + file2=file2 + ) + + assert calctopncc.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_FillLesions.py b/nipype/interfaces/niftyseg/tests/test_lesions.py similarity index 72% rename from nipype/interfaces/niftyseg/tests/test_Seg_FillLesions.py rename to nipype/interfaces/niftyseg/tests/test_lesions.py index 3f6e8f45c7..15b1d67189 100644 --- a/nipype/interfaces/niftyseg/tests/test_Seg_FillLesions.py +++ b/nipype/interfaces/niftyseg/tests/test_lesions.py @@ -3,12 +3,13 @@ from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, FillLesions) -from nipype.testing import skipif, example_data +from nipype.testing import example_data import os import pytest -@skipif(no_niftyseg(cmd='seg_FillLesions')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_FillLesions'), + reason="niftyseg is not installed") def test_seg_filllesions(): # Create a node object @@ -28,9 +29,10 @@ def test_seg_filllesions(): seg_fill.inputs.lesion_mask = lesion_mask expected_cmd = '{cmd} -i {in_file} -l {lesion_mask} -o {out_file}'.format( - cmd=get_custom_path('seg_FillLesions'), - in_file=in_file, - lesion_mask=lesion_mask, - out_file=os.path.join(os.getcwd(), 'im1_lesions_filled.nii')) + cmd=get_custom_path('seg_FillLesions'), + in_file=in_file, + lesion_mask=lesion_mask, + out_file=os.path.join(os.getcwd(), 'im1_lesions_filled.nii') + ) assert seg_fill.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py b/nipype/interfaces/niftyseg/tests/test_maths.py similarity index 88% rename from nipype/interfaces/niftyseg/tests/test_Seg_Maths.py rename to nipype/interfaces/niftyseg/tests/test_maths.py index cc18a4d5cd..04276d1fb5 100644 --- a/nipype/interfaces/niftyseg/tests/test_Seg_Maths.py +++ b/nipype/interfaces/niftyseg/tests/test_maths.py @@ -5,12 +5,13 @@ UnaryMaths, BinaryMaths, BinaryMathsInteger, TupleMaths, Merge) -from nipype.testing import skipif, example_data +from nipype.testing import example_data import os import pytest -@skipif(no_niftyseg(cmd='seg_maths')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), + reason="niftyseg is not installed") def test_unary_maths(): # Create a node object @@ -37,7 +38,8 @@ def test_unary_maths(): assert unarym.cmdline == expected_cmd -@skipif(no_niftyseg(cmd='seg_maths')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), + reason="niftyseg is not installed") def test_binary_maths(): # Create a node object @@ -66,7 +68,8 @@ def test_binary_maths(): assert binarym.cmdline == expected_cmd -@skipif(no_niftyseg(cmd='seg_maths')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), + reason="niftyseg is not installed") def test_int_binary_maths(): # Create a node object @@ -94,7 +97,8 @@ def test_int_binary_maths(): assert ibinarym.cmdline == expected_cmd -@skipif(no_niftyseg(cmd='seg_maths')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), + reason="niftyseg is not installed") def test_tuple_maths(): # Create a node object @@ -126,7 +130,8 @@ def test_tuple_maths(): assert tuplem.cmdline == expected_cmd -@skipif(no_niftyseg(cmd='seg_maths')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), + reason="niftyseg is not installed") def test_merge(): # Create a node object diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_PatchMatch.py b/nipype/interfaces/niftyseg/tests/test_patchmatch.py similarity index 73% rename from nipype/interfaces/niftyseg/tests/test_Seg_PatchMatch.py rename to nipype/interfaces/niftyseg/tests/test_patchmatch.py index a3531f0635..43f115c25e 100644 --- a/nipype/interfaces/niftyseg/tests/test_Seg_PatchMatch.py +++ b/nipype/interfaces/niftyseg/tests/test_patchmatch.py @@ -2,12 +2,13 @@ # vi: set ft=python sts=4 ts=4 sw=4 et: from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, PatchMatch -from nipype.testing import skipif, example_data +from nipype.testing import example_data import os import pytest -@skipif(no_niftyseg(cmd='seg_PatchMatch')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_PatchMatch'), + reason="niftyseg is not installed") def test_seg_patchmatch(): # Create a node object @@ -30,10 +31,11 @@ def test_seg_patchmatch(): cmd_tmp = '{cmd} -i {in_file} -m {mask_file} -db {db} -o {out_file}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_PatchMatch'), - in_file=in_file, - mask_file=mask_file, - db=db_file, - out_file=os.path.join(os.getcwd(), 'im1_pm.nii')) + cmd=get_custom_path('seg_PatchMatch'), + in_file=in_file, + mask_file=mask_file, + db=db_file, + out_file=os.path.join(os.getcwd(), 'im1_pm.nii') + ) assert seg_patchmatch.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_Seg_Stats.py b/nipype/interfaces/niftyseg/tests/test_stats.py similarity index 81% rename from nipype/interfaces/niftyseg/tests/test_Seg_Stats.py rename to nipype/interfaces/niftyseg/tests/test_stats.py index d72dc94f29..e33a915964 100644 --- a/nipype/interfaces/niftyseg/tests/test_Seg_Stats.py +++ b/nipype/interfaces/niftyseg/tests/test_stats.py @@ -3,13 +3,14 @@ from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, UnaryStats, BinaryStats) -from nipype.testing import skipif, example_data +from nipype.testing import example_data import pytest -@skipif(no_niftyseg(cmd='seg_stats')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_stats'), + reason="niftyseg is not installed") def test_unary_stats(): - + """ Test for the seg_stats interfaces """ # Create a node object unarys = UnaryStats() @@ -32,8 +33,10 @@ def test_unary_stats(): assert unarys.cmdline == expected_cmd -@skipif(no_niftyseg(cmd='seg_stats')) +@pytest.mark.skipif(no_niftyseg(cmd='seg_stats'), + reason="niftyseg is not installed") def test_binary_stats(): + """ Test for the seg_stats interfaces """ # Create a node object binarys = BinaryStats() From 135da5691231a2b2ee6482235b5170b5c14dfa80 Mon Sep 17 00:00:00 2001 From: byvernault Date: Mon, 3 Apr 2017 11:30:11 +0100 Subject: [PATCH 05/17] Adding to cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE --- nipype/interfaces/niftyseg/em.py | 6 +++--- nipype/interfaces/niftyseg/label_fusion.py | 6 +++--- nipype/interfaces/niftyseg/lesions.py | 4 ++-- nipype/interfaces/niftyseg/maths.py | 21 +++++++++++---------- nipype/interfaces/niftyseg/patchmatch.py | 4 ++-- nipype/interfaces/niftyseg/stats.py | 4 ++-- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/nipype/interfaces/niftyseg/em.py b/nipype/interfaces/niftyseg/em.py index 20a0eeeb1d..7d9851a38d 100644 --- a/nipype/interfaces/niftyseg/em.py +++ b/nipype/interfaces/niftyseg/em.py @@ -126,9 +126,9 @@ class EM(NiftySegCommand): >>> node = niftyseg.EM() >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.no_prior = 4 - >>> node.cmdline # doctest: +SKIP - 'seg_EM -in im1.nii -nopriors 4 -bc_out im1_bc_em.nii -out im1_em.nii \ --out_outlier im1_outlier_em.nii' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_EM -in im1.nii -nopriors 4 -bc_out .../im1_bc_em.nii \ +-out .../im1_em.nii -out_outlier .../im1_outlier_em.nii' """ _cmd = get_custom_path('seg_EM') diff --git a/nipype/interfaces/niftyseg/label_fusion.py b/nipype/interfaces/niftyseg/label_fusion.py index cfeb58aaad..03a71a677b 100644 --- a/nipype/interfaces/niftyseg/label_fusion.py +++ b/nipype/interfaces/niftyseg/label_fusion.py @@ -128,9 +128,9 @@ class LabelFusion(NiftySegCommand): >>> node.inputs.template_file = 'im3.nii' >>> node.inputs.template_num = 2 >>> node.inputs.classifier_type = 'STEPS' - >>> node.cmdline # doctest: +SKIP + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE 'seg_LabFusion -in im1.nii -STEPS 2.000000 2 im2.nii im3.nii -out \ -im1_steps.nii' +.../im1_steps.nii' """ _cmd = get_custom_path('seg_LabFusion') @@ -289,7 +289,7 @@ class CalcTopNCC(NiftySegCommand): >>> node.inputs.num_templates = 2 >>> node.inputs.in_templates = ['im2.nii', 'im3.nii'] >>> node.inputs.top_templates = 1 - >>> node.cmdline # doctest: +SKIP + >>> node.cmdline # doctest: +ALLOW_UNICODE 'seg_CalcTopNCC -target im1.nii -templates 2 im2.nii im3.nii -n 1' """ diff --git a/nipype/interfaces/niftyseg/lesions.py b/nipype/interfaces/niftyseg/lesions.py index f2f07ee324..1dd85ad98a 100644 --- a/nipype/interfaces/niftyseg/lesions.py +++ b/nipype/interfaces/niftyseg/lesions.py @@ -108,8 +108,8 @@ class FillLesions(NiftySegCommand): >>> node = niftyseg.FillLesions() >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.lesion_mask = 'im2.nii' - >>> node.cmdline # doctest: +SKIP - 'seg_FillLesions -i im1.nii -l im2.nii -o im1_lesions_filled.nii' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_FillLesions -i im1.nii -l im2.nii -o .../im1_lesions_filled.nii' """ _cmd = get_custom_path('seg_FillLesions') diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 1b1faad604..449f6c27a7 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -136,8 +136,8 @@ class UnaryMaths(MathsCommand): >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'sqrt' >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +SKIP - 'seg_maths im1.nii -sqrt -odt float im1_sqrt.nii.gz' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -sqrt -odt float .../im1_sqrt.nii.gz' """ input_spec = UnaryMathsInput @@ -224,8 +224,8 @@ class BinaryMaths(MathsCommand): >>> node.inputs.operation = 'sub' >>> node.inputs.operand_file = 'im2.nii' >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +SKIP - 'seg_maths im1.nii -odt float -sub im2.nii im1_sub.nii.gz' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -odt float -sub im2.nii .../im1_sub.nii.gz' """ input_spec = BinaryMathsInput @@ -299,8 +299,8 @@ class BinaryMathsInteger(MathsCommand): >>> node.inputs.operation = 'dil' >>> node.inputs.operand_value = 2 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +SKIP - 'seg_maths im1.nii -dil 2 im1_dil.nii -odt float' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -dil 2 .../im1_dil.nii -odt float' """ input_spec = BinaryMathsInputInteger @@ -370,8 +370,8 @@ class TupleMaths(MathsCommand): >>> node.inputs.operand_file1 = 'im2.nii' >>> node.inputs.operand_value2 = 2.0 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +SKIP - 'seg_maths im1.nii -lncc im2.nii 2.00000000 im1_lncc.nii -odt float' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -lncc im2.nii 2.00000000 .../im1_lncc.nii -odt float' """ input_spec = TupleMathsInput @@ -411,8 +411,9 @@ class Merge(MathsCommand): >>> node.inputs.merge_files = files >>> node.inputs.dimension = 2 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +SKIP - 'seg_maths im1.nii -merge 2 2 im2.nii im3.nii -odt float im1_merged.nii' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -merge 2 2 im2.nii im3.nii -odt float \ +.../im1_merged.nii' """ input_spec = MergeInput diff --git a/nipype/interfaces/niftyseg/patchmatch.py b/nipype/interfaces/niftyseg/patchmatch.py index eea59d9be2..f1551b28bc 100644 --- a/nipype/interfaces/niftyseg/patchmatch.py +++ b/nipype/interfaces/niftyseg/patchmatch.py @@ -105,8 +105,8 @@ class PatchMatch(NiftySegCommand): >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.mask_file = 'im2.nii' >>> node.inputs.database_file = 'db.xml' - >>> node.cmdline # doctest: +SKIP - 'seg_PatchMatch -i im1.nii -m im2.nii -db db.xml -o im1_pm.nii' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_PatchMatch -i im1.nii -m im2.nii -db db.xml -o .../im1_pm.nii' """ _cmd = get_custom_path('seg_PatchMatch') diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index 4e5b8a5011..5f73e4e287 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -132,7 +132,7 @@ class UnaryStats(StatsCommand): >>> node = niftyseg.UnaryStats() >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'v' - >>> node.cmdline # doctest: +SKIP + >>> node.cmdline # doctest: +ALLOW_UNICODE 'seg_stats im1.nii -v' """ @@ -196,7 +196,7 @@ class BinaryStats(StatsCommand): >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'sa' >>> node.inputs.operand_value = 2.0 - >>> node.cmdline # doctest: +SKIP + >>> node.cmdline # doctest: +ALLOW_UNICODE 'seg_stats im1.nii -sa 2' """ From b9610cbc613e10882b33a41e470949c7b8abe00e Mon Sep 17 00:00:00 2001 From: byvernault Date: Tue, 4 Apr 2017 10:22:05 +0100 Subject: [PATCH 06/17] Fixing the docstring --- nipype/interfaces/niftyseg/maths.py | 8 ++++---- nipype/interfaces/niftyseg/stats.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 449f6c27a7..abdaa21677 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -137,7 +137,7 @@ class UnaryMaths(MathsCommand): >>> node.inputs.operation = 'sqrt' >>> node.inputs.output_datatype = 'float' >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -sqrt -odt float .../im1_sqrt.nii.gz' + 'seg_maths im1.nii -sqrt -odt float .../im1_sqrt.nii' """ input_spec = UnaryMathsInput @@ -225,7 +225,7 @@ class BinaryMaths(MathsCommand): >>> node.inputs.operand_file = 'im2.nii' >>> node.inputs.output_datatype = 'float' >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -odt float -sub im2.nii .../im1_sub.nii.gz' + 'seg_maths im1.nii -sub im2.nii -odt float .../im1_sub.nii' """ input_spec = BinaryMathsInput @@ -300,7 +300,7 @@ class BinaryMathsInteger(MathsCommand): >>> node.inputs.operand_value = 2 >>> node.inputs.output_datatype = 'float' >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -dil 2 .../im1_dil.nii -odt float' + 'seg_maths im1.nii -dil 2 -odt float .../im1_dil.nii' """ input_spec = BinaryMathsInputInteger @@ -371,7 +371,7 @@ class TupleMaths(MathsCommand): >>> node.inputs.operand_value2 = 2.0 >>> node.inputs.output_datatype = 'float' >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -lncc im2.nii 2.00000000 .../im1_lncc.nii -odt float' + 'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float .../im1_lncc.nii' """ input_spec = TupleMathsInput diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index 5f73e4e287..ff535fc8ad 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -197,7 +197,7 @@ class BinaryStats(StatsCommand): >>> node.inputs.operation = 'sa' >>> node.inputs.operand_value = 2.0 >>> node.cmdline # doctest: +ALLOW_UNICODE - 'seg_stats im1.nii -sa 2' + 'seg_stats im1.nii -sa 2.00000000' """ input_spec = BinaryStatsInput From 55e555e5a2e8600aeff02b8bbfd133e215124c54 Mon Sep 17 00:00:00 2001 From: byvernault Date: Thu, 20 Apr 2017 09:50:32 +0100 Subject: [PATCH 07/17] adding documentation in docstring for segmaths, segstats, seglabfusion --- nipype/interfaces/niftyseg/label_fusion.py | 17 +++++++++++++++++ nipype/interfaces/niftyseg/maths.py | 13 +++++++++++++ nipype/interfaces/niftyseg/stats.py | 10 ++++++++++ 3 files changed, 40 insertions(+) diff --git a/nipype/interfaces/niftyseg/label_fusion.py b/nipype/interfaces/niftyseg/label_fusion.py index 03a71a677b..4936395bb7 100644 --- a/nipype/interfaces/niftyseg/label_fusion.py +++ b/nipype/interfaces/niftyseg/label_fusion.py @@ -114,6 +114,23 @@ class LabelFusion(NiftySegCommand): """Interface for executable seg_LabelFusion from NiftySeg platform using type STEPS as classifier Fusion. + This executable implements 4 fusion strategies (-STEPS, -STAPLE, -MV or + - SBA), all of them using either a global (-GNCC), ROI-based (-ROINCC), + local (-LNCC) or no image similarity (-ALL). Combinations of fusion + algorithms and similarity metrics give rise to different variants of known + algorithms. As an example, using LNCC and MV as options will run a locally + weighted voting strategy with LNCC derived weights, while using STAPLE and + LNCC is equivalent to running STEPS as per its original formulation. + A few other options pertaining the use of an MRF (-MRF beta), the initial + sensitivity and specificity estimates and the use of only non-consensus + voxels (-unc) for the STAPLE and STEPS algorithm. All processing can be + masked (-mask), greatly reducing memory consumption. + + As an example, the command to use STEPS should be: + seg_LabFusion -in 4D_Propragated_Labels_to_fuse.nii -out \ + FusedSegmentation.nii -STEPS 2 15 TargetImage.nii \ + 4D_Propagated_Intensities.nii + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg For Documentation, see: http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index abdaa21677..3c56d4bb4c 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -54,6 +54,19 @@ class MathsOutput(TraitedSpec): class MathsCommand(NiftySegCommand): """ Base Command Interface for seg_maths interfaces. + + The executable seg_maths enables the sequential execution of arithmetic + operations, like multiplication (-mul), division (-div) or addition + (-add), binarisation (-bin) or thresholding (-thr) operations and + convolution by a Gaussian kernel (-smo). It also alows mathematical + morphology based operations like dilation (-dil), erosion (-ero), + connected components (-lconcomp) and hole filling (-fill), Euclidean + (- euc) and geodesic (-geo) distance transforms, local image similarity + metric calculation (-lncc and -lssd). Finally, it allows multiple + operations over the dimensionality of the image, from merging 3D images + together as a 4D image (-merge) or splitting (-split or -tp) 4D images + into several 3D images, to estimating the maximum, minimum and average + over all time-points, etc. """ _cmd = get_custom_path('seg_maths') input_spec = MathsInput diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index ff535fc8ad..18c359f554 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -48,6 +48,16 @@ class StatsOutput(TraitedSpec): class StatsCommand(NiftySegCommand): """ Base Command Interface for seg_stats interfaces. + + The executable seg_stats enables the estimation of image statistics on + continuous voxel intensities (average, standard deviation, min/max, robust + range, percentiles, sum, probabilistic volume, entropy, etc) either over + the full image or on a per slice basis (slice axis can be specified), + statistics over voxel coordinates (location of max, min and centre of + mass, bounding box, etc) and statistics over categorical images (e.g. per + region volume, count, average, Dice scores, etc). These statistics are + robust to the presence of NaNs, and can be constrained by a mask and/or + thresholded at a certain level. """ _cmd = get_custom_path('seg_stats') input_spec = StatsInput From ee44a576b2a3e188c78b1f53e4ce6c44d28ff23a Mon Sep 17 00:00:00 2001 From: byvernault Date: Thu, 20 Apr 2017 18:24:48 +0100 Subject: [PATCH 08/17] Symplifying the interfaces when possible using name_source/name_template --- nipype/interfaces/niftyseg/base.py | 15 +--- nipype/interfaces/niftyseg/em.py | 54 ++++--------- nipype/interfaces/niftyseg/lesions.py | 32 ++------ nipype/interfaces/niftyseg/maths.py | 47 +++++------ nipype/interfaces/niftyseg/patchmatch.py | 27 ++----- .../interfaces/niftyseg/tests/test_auto_EM.py | 77 ------------------- .../niftyseg/tests/test_auto_FillLesions.py | 2 + .../niftyseg/tests/test_auto_PatchMatch.py | 64 --------------- nipype/interfaces/niftyseg/tests/test_em.py | 10 +-- .../niftyseg/tests/test_label_fusion.py | 5 +- .../interfaces/niftyseg/tests/test_lesions.py | 6 +- .../interfaces/niftyseg/tests/test_maths.py | 5 +- .../niftyseg/tests/test_patchmatch.py | 6 +- .../interfaces/niftyseg/tests/test_stats.py | 3 +- 14 files changed, 68 insertions(+), 285 deletions(-) delete mode 100644 nipype/interfaces/niftyseg/tests/test_auto_EM.py delete mode 100644 nipype/interfaces/niftyseg/tests/test_auto_PatchMatch.py diff --git a/nipype/interfaces/niftyseg/base.py b/nipype/interfaces/niftyseg/base.py index a5baa0759d..b77ba19007 100644 --- a/nipype/interfaces/niftyseg/base.py +++ b/nipype/interfaces/niftyseg/base.py @@ -20,7 +20,7 @@ """ -from nipype.interfaces.base import CommandLine, isdefined +from nipype.interfaces.base import CommandLine from nipype.utils.filemanip import split_filename import os import subprocess @@ -89,16 +89,3 @@ def _gen_fname(self, basename, out_dir=None, suffix=None, ext=None): if suffix is not None: final_bn = ''.join((final_bn, suffix)) return os.path.abspath(os.path.join(out_dir, final_bn + final_ext)) - - def _gen_filename(self, name): - if name == 'out_file': - return self._gen_fname(self.inputs.in_file, suffix=self._suffix) - return None - - def _list_outputs(self): - outputs = self.output_spec().get() - if isdefined(self.inputs.out_file): - outputs['out_file'] = self.inputs.out_file - else: - outputs['out_file'] = self._gen_filename('out_file') - return outputs diff --git a/nipype/interfaces/niftyseg/em.py b/nipype/interfaces/niftyseg/em.py index 7d9851a38d..5d322d3eb4 100644 --- a/nipype/interfaces/niftyseg/em.py +++ b/nipype/interfaces/niftyseg/em.py @@ -18,9 +18,7 @@ >>> os.chdir(datadir) """ -import os - -from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, +from ..base import (TraitedSpec, File, traits, CommandLineInputSpec, InputMultiPath) from .base import NiftySegCommand, get_custom_path @@ -91,14 +89,17 @@ class EMInputSpec(CommandLineInputSpec): desc=desc) # outputs - out_file = File(argstr='-out %s', - genfile=True, + out_file = File(name_source=['in_file'], + name_template='%s_em.nii.gz', + argstr='-out %s', desc='Output segmentation') - out_bc_file = File(argstr='-bc_out %s', - genfile=True, + out_bc_file = File(name_source=['in_file'], + name_template='%s_bc_em.nii.gz', + argstr='-bc_out %s', desc='Output bias corrected image') - out_outlier_file = File(argstr='-out_outlier %s', - genfile=True, + out_outlier_file = File(name_source=['in_file'], + name_template='%s_outlier_em.nii.gz', + argstr='-out_outlier %s', desc='Output outlierness image') @@ -126,9 +127,9 @@ class EM(NiftySegCommand): >>> node = niftyseg.EM() >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.no_prior = 4 - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_EM -in im1.nii -nopriors 4 -bc_out .../im1_bc_em.nii \ --out .../im1_em.nii -out_outlier .../im1_outlier_em.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_EM -in im1.nii -nopriors 4 -bc_out im1_bc_em.nii.gz \ +-out im1_em.nii.gz -out_outlier im1_outlier_em.nii.gz' """ _cmd = get_custom_path('seg_EM') @@ -143,32 +144,3 @@ def _format_arg(self, opt, spec, val): return '-priors %d %s' % (_nb_priors, ' '.join(self.inputs.priors)) else: return super(EM, self)._format_arg(opt, spec, val) - - def _list_outputs(self): - outputs = self.output_spec().get() - outputs['out_file'] = self.inputs.out_file - if not isdefined(self.inputs.out_file): - outputs['out_file'] = self._gen_fname(self.inputs.in_file, - suffix=self._suffix) - outputs['out_file'] = os.path.abspath(outputs['out_file']) - outputs['out_bc_file'] = self.inputs.out_bc_file - if not isdefined(self.inputs.out_bc_file): - outputs['out_bc_file'] = self._gen_fname( - self.inputs.in_file, suffix=('_bc%s' % self._suffix)) - outputs['out_bc_file'] = os.path.abspath(outputs['out_bc_file']) - outputs['out_outlier_file'] = self.inputs.out_outlier_file - if not isdefined(self.inputs.out_outlier_file): - outputs['out_outlier_file'] = self._gen_fname( - self.inputs.in_file, suffix=('_outlier%s' % self._suffix)) - outputs['out_outlier_file'] = os.path.abspath( - outputs['out_outlier_file']) - return outputs - - def _gen_filename(self, name): - if name == 'out_file': - return self._list_outputs()['out_file'] - if name == 'out_bc_file': - return self._list_outputs()['out_bc_file'] - if name == 'out_outlier_file': - return self._list_outputs()['out_outlier_file'] - return None diff --git a/nipype/interfaces/niftyseg/lesions.py b/nipype/interfaces/niftyseg/lesions.py index 1dd85ad98a..7c4bb4630b 100644 --- a/nipype/interfaces/niftyseg/lesions.py +++ b/nipype/interfaces/niftyseg/lesions.py @@ -18,10 +18,9 @@ >>> os.chdir(datadir) """ -import os import warnings -from ..base import TraitedSpec, File, traits, isdefined, CommandLineInputSpec +from ..base import TraitedSpec, File, traits, CommandLineInputSpec from .base import NiftySegCommand, get_custom_path @@ -39,7 +38,9 @@ class FillLesionsInputSpec(CommandLineInputSpec): desc='Lesion mask', position=2) # Output file name - out_file = File(desc='The output filename of the fill lesions results', + out_file = File(name_source=['in_file'], + name_template='%s_lesions_filled.nii.gz', + desc='The output filename of the fill lesions results', argstr='-o %s', position=3) # Optional arguments @@ -108,31 +109,10 @@ class FillLesions(NiftySegCommand): >>> node = niftyseg.FillLesions() >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.lesion_mask = 'im2.nii' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_FillLesions -i im1.nii -l im2.nii -o .../im1_lesions_filled.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_FillLesions -i im1.nii -l im2.nii -o im1_lesions_filled.nii.gz' """ _cmd = get_custom_path('seg_FillLesions') input_spec = FillLesionsInputSpec output_spec = FillLesionsOutputSpec - - def _list_outputs(self): - outputs = self.output_spec().get() - outputs['out_file'] = self.inputs.out_file - if not isdefined(self.inputs.out_file): - outputs['out_file'] = self._gen_filename('out_file') - outputs['out_file'] = os.path.abspath(outputs['out_file']) - return outputs - - def _parse_inputs(self, skip=None): - """Set non-mandatory inputs if not given by user.""" - skip = [] - if not isdefined(self.inputs.out_file): - self.inputs.out_file = self._gen_filename('out_file') - return super(FillLesions, self)._parse_inputs(skip=skip) - - def _gen_filename(self, name): - if name == 'out_file': - return self._gen_fname(self.inputs.in_file, - suffix='_lesions_filled') - return None diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 3c56d4bb4c..0ec20ad7a1 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -17,7 +17,6 @@ >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) >>> os.chdir(datadir) """ -import os from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, NipypeInterfaceError) @@ -71,6 +70,7 @@ class MathsCommand(NiftySegCommand): _cmd = get_custom_path('seg_maths') input_spec = MathsInput output_spec = MathsOutput + _suffix = '_maths' def _list_outputs(self): outputs = self.output_spec().get() @@ -79,11 +79,11 @@ def _list_outputs(self): if suffix != '_merged' and isdefined(self.inputs.operation): suffix = '_' + self.inputs.operation - outputs['out_file'] = self.inputs.out_file - if not isdefined(self.inputs.out_file): + if isdefined(self.inputs.out_file): + outputs['out_file'] = self.inputs.out_file + else: outputs['out_file'] = self._gen_fname(self.inputs.in_file, suffix=suffix) - outputs['out_file'] = os.path.abspath(outputs['out_file']) return outputs def _gen_filename(self, name): @@ -149,8 +149,8 @@ class UnaryMaths(MathsCommand): >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'sqrt' >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -sqrt -odt float .../im1_sqrt.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -sqrt -odt float im1_sqrt.nii' """ input_spec = UnaryMathsInput @@ -237,8 +237,8 @@ class BinaryMaths(MathsCommand): >>> node.inputs.operation = 'sub' >>> node.inputs.operand_file = 'im2.nii' >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -sub im2.nii -odt float .../im1_sub.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -sub im2.nii -odt float im1_sub.nii' """ input_spec = BinaryMathsInput @@ -256,19 +256,12 @@ def _format_arg(self, opt, spec, val): return super(BinaryMaths, self)._format_arg(opt, spec, val) def _list_outputs(self): - outputs = self.output_spec().get() - self._suffix = '_' + self.inputs.operation - - outputs['out_file'] = self.inputs.out_file - if not isdefined(self.inputs.out_file): - if isdefined(self.inputs.operation) and \ - self.inputs.operation == 'hdr_copy': - outputs['out_file'] = self._gen_fname(self.inputs.operand_file, - suffix=self._suffix) - else: - outputs['out_file'] = self._gen_fname(self.inputs.in_file, - suffix=self._suffix) - outputs['out_file'] = os.path.abspath(outputs['out_file']) + outputs = super(BinaryMaths, self)._list_outputs() + + if self.inputs.operation == 'hdr_copy': + outputs['out_file'] = self._gen_fname( + self.inputs.operand_file, + suffix='_{0}'.format(self.inputs.operation)) return outputs @@ -312,8 +305,8 @@ class BinaryMathsInteger(MathsCommand): >>> node.inputs.operation = 'dil' >>> node.inputs.operand_value = 2 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -dil 2 -odt float .../im1_dil.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -dil 2 -odt float im1_dil.nii' """ input_spec = BinaryMathsInputInteger @@ -383,8 +376,8 @@ class TupleMaths(MathsCommand): >>> node.inputs.operand_file1 = 'im2.nii' >>> node.inputs.operand_value2 = 2.0 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float .../im1_lncc.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float im1_lncc.nii' """ input_spec = TupleMathsInput @@ -424,9 +417,9 @@ class Merge(MathsCommand): >>> node.inputs.merge_files = files >>> node.inputs.dimension = 2 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + >>> node.cmdline # doctest: +ALLOW_UNICODE 'seg_maths im1.nii -merge 2 2 im2.nii im3.nii -odt float \ -.../im1_merged.nii' +im1_merged.nii' """ input_spec = MergeInput diff --git a/nipype/interfaces/niftyseg/patchmatch.py b/nipype/interfaces/niftyseg/patchmatch.py index f1551b28bc..c99ec54be5 100644 --- a/nipype/interfaces/niftyseg/patchmatch.py +++ b/nipype/interfaces/niftyseg/patchmatch.py @@ -38,16 +38,17 @@ class PatchMatchInputSpec(CommandLineInputSpec): position=2) database_file = File(argstr='-db %s', - genfile=True, + exists=True, mandatory=True, desc='Database with the segmentations', position=3) # Output file name - out_file = File(desc='The output filename of the patchmatch results', + out_file = File(name_source=['in_file'], + name_template='%s_pm.nii.gz', + desc='The output filename of the patchmatch results', argstr='-o %s', - position=4, - genfile=True) + position=4) # Optional arguments patch_size = traits.Int(desc="Patch size, #voxels", @@ -105,25 +106,11 @@ class PatchMatch(NiftySegCommand): >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.mask_file = 'im2.nii' >>> node.inputs.database_file = 'db.xml' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_PatchMatch -i im1.nii -m im2.nii -db db.xml -o .../im1_pm.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_PatchMatch -i im1.nii -m im2.nii -db db.xml -o im1_pm.nii.gz' """ _cmd = get_custom_path('seg_PatchMatch') input_spec = PatchMatchInputSpec output_spec = PatchMatchOutputSpec _suffix = '_pm' - - def _list_outputs(self): - outputs = self.output_spec().get() - outputs['out_file'] = self.inputs.out_file - if not isdefined(self.inputs.out_file): - outputs['out_file'] = self._gen_fname(self.inputs.in_file, - suffix=self._suffix) - outputs['out_file'] = os.path.abspath(outputs['out_file']) - return outputs - - def _gen_filename(self, name): - if name == 'out_file': - return self._list_outputs()['out_file'] - return None diff --git a/nipype/interfaces/niftyseg/tests/test_auto_EM.py b/nipype/interfaces/niftyseg/tests/test_auto_EM.py deleted file mode 100644 index c551e09536..0000000000 --- a/nipype/interfaces/niftyseg/tests/test_auto_EM.py +++ /dev/null @@ -1,77 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..em import EM - - -def test_EM_inputs(): - input_map = dict(args=dict(argstr='%s', - ), - bc_order_val=dict(argstr='-bc_order %s', - ), - bc_thresh_val=dict(argstr='-bc_thresh %s', - ), - environ=dict(nohash=True, - usedefault=True, - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - in_file=dict(argstr='-in %s', - mandatory=True, - position=4, - ), - mask_file=dict(argstr='-mask %s', - ), - max_iter=dict(argstr='-max_iter %s', - ), - min_iter=dict(argstr='-min_iter %s', - ), - mrf_beta_val=dict(argstr='-mrf_beta %s', - ), - no_prior=dict(argstr='-nopriors %s', - mandatory=True, - xor=['prior_4D', 'priors'], - ), - out_bc_file=dict(argstr='-bc_out %s', - genfile=True, - ), - out_file=dict(argstr='-out %s', - genfile=True, - ), - out_outlier_file=dict(argstr='-out_outlier %s', - genfile=True, - ), - outlier_val=dict(argstr='-outlier %s %s', - ), - prior_4D=dict(argstr='-prior4D %s', - mandatory=True, - xor=['no_prior', 'priors'], - ), - priors=dict(argstr='%s', - mandatory=True, - xor=['no_prior', 'prior_4D'], - ), - reg_val=dict(argstr='-reg %s', - ), - relax_priors=dict(argstr='-rf %s %s', - ), - terminal_output=dict(nohash=True, - ), - ) - inputs = EM.input_spec() - - for key, metadata in list(input_map.items()): - for metakey, value in list(metadata.items()): - assert getattr(inputs.traits()[key], metakey) == value - - -def test_EM_outputs(): - output_map = dict(out_bc_file=dict(), - out_file=dict(), - out_outlier_file=dict(), - ) - outputs = EM.output_spec() - - for key, metadata in list(output_map.items()): - for metakey, value in list(metadata.items()): - assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py b/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py index 0647153ecb..ed0cc42b0b 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py @@ -44,6 +44,8 @@ def test_FillLesions_inputs(): mandatory=False, ), out_file=dict(argstr='-o %s', + name_source=['in_file'], + name_template='%s_lesions_filled.nii.gz', position=3, ), search=dict(argstr='-search %f', diff --git a/nipype/interfaces/niftyseg/tests/test_auto_PatchMatch.py b/nipype/interfaces/niftyseg/tests/test_auto_PatchMatch.py deleted file mode 100644 index e9bae21fcc..0000000000 --- a/nipype/interfaces/niftyseg/tests/test_auto_PatchMatch.py +++ /dev/null @@ -1,64 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..patchmatch import PatchMatch - - -def test_PatchMatch_inputs(): - input_map = dict(args=dict(argstr='%s', - ), - cs_size=dict(argstr='-cs %i', - mandatory=False, - ), - database_file=dict(argstr='-db %s', - genfile=True, - mandatory=True, - position=3, - ), - environ=dict(nohash=True, - usedefault=True, - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - in_file=dict(argstr='-i %s', - mandatory=True, - position=1, - ), - it_num=dict(argstr='-it %i', - mandatory=False, - ), - mask_file=dict(argstr='-m %s', - mandatory=True, - position=2, - ), - match_num=dict(argstr='-match %i', - mandatory=False, - ), - out_file=dict(argstr='-o %s', - genfile=True, - position=4, - ), - patch_size=dict(argstr='-size %i', - mandatory=False, - ), - pm_num=dict(argstr='-pm %i', - mandatory=False, - ), - terminal_output=dict(nohash=True, - ), - ) - inputs = PatchMatch.input_spec() - - for key, metadata in list(input_map.items()): - for metakey, value in list(metadata.items()): - assert getattr(inputs.traits()[key], metakey) == value - - -def test_PatchMatch_outputs(): - output_map = dict(out_file=dict(), - ) - outputs = PatchMatch.output_spec() - - for key, metadata in list(output_map.items()): - for metakey, value in list(metadata.items()): - assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_em.py b/nipype/interfaces/niftyseg/tests/test_em.py index e9ab8b9347..54224ee623 100644 --- a/nipype/interfaces/niftyseg/tests/test_em.py +++ b/nipype/interfaces/niftyseg/tests/test_em.py @@ -1,10 +1,10 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: +import pytest + from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, EM from nipype.testing import example_data -import os -import pytest @pytest.mark.skipif(no_niftyseg(cmd='seg_EM'), @@ -31,9 +31,9 @@ def test_seg_em(): expected_cmd = cmd_tmp.format( cmd=get_custom_path('seg_EM'), in_file=in_file, - out_file=os.path.join(os.getcwd(), 'im1_em.nii'), - bc_out=os.path.join(os.getcwd(), 'im1_bc_em.nii'), - out_outlier=os.path.join(os.getcwd(), 'im1_outlier_em.nii') + out_file='im1_em.nii.gz', + bc_out='im1_bc_em.nii.gz', + out_outlier='im1_outlier_em.nii.gz', ) assert seg_em.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_label_fusion.py b/nipype/interfaces/niftyseg/tests/test_label_fusion.py index fd0140c42b..82645cda97 100644 --- a/nipype/interfaces/niftyseg/tests/test_label_fusion.py +++ b/nipype/interfaces/niftyseg/tests/test_label_fusion.py @@ -1,11 +1,12 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: +import os +import pytest + from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, LabelFusion, CalcTopNCC) from nipype.testing import example_data -import os -import pytest @pytest.mark.skipif(no_niftyseg(cmd='seg_LabFusion'), diff --git a/nipype/interfaces/niftyseg/tests/test_lesions.py b/nipype/interfaces/niftyseg/tests/test_lesions.py index 15b1d67189..d228030b4c 100644 --- a/nipype/interfaces/niftyseg/tests/test_lesions.py +++ b/nipype/interfaces/niftyseg/tests/test_lesions.py @@ -1,11 +1,11 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: +import pytest + from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, FillLesions) from nipype.testing import example_data -import os -import pytest @pytest.mark.skipif(no_niftyseg(cmd='seg_FillLesions'), @@ -32,7 +32,7 @@ def test_seg_filllesions(): cmd=get_custom_path('seg_FillLesions'), in_file=in_file, lesion_mask=lesion_mask, - out_file=os.path.join(os.getcwd(), 'im1_lesions_filled.nii') + out_file='im1_lesions_filled.nii.gz', ) assert seg_fill.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_maths.py b/nipype/interfaces/niftyseg/tests/test_maths.py index 04276d1fb5..163c5ab189 100644 --- a/nipype/interfaces/niftyseg/tests/test_maths.py +++ b/nipype/interfaces/niftyseg/tests/test_maths.py @@ -1,13 +1,14 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: +import os +import pytest + from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, UnaryMaths, BinaryMaths, BinaryMathsInteger, TupleMaths, Merge) from nipype.testing import example_data -import os -import pytest @pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), diff --git a/nipype/interfaces/niftyseg/tests/test_patchmatch.py b/nipype/interfaces/niftyseg/tests/test_patchmatch.py index 43f115c25e..e584ab6b93 100644 --- a/nipype/interfaces/niftyseg/tests/test_patchmatch.py +++ b/nipype/interfaces/niftyseg/tests/test_patchmatch.py @@ -1,10 +1,10 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: +import pytest + from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, PatchMatch from nipype.testing import example_data -import os -import pytest @pytest.mark.skipif(no_niftyseg(cmd='seg_PatchMatch'), @@ -35,7 +35,7 @@ def test_seg_patchmatch(): in_file=in_file, mask_file=mask_file, db=db_file, - out_file=os.path.join(os.getcwd(), 'im1_pm.nii') + out_file='im1_pm.nii.gz', ) assert seg_patchmatch.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_stats.py b/nipype/interfaces/niftyseg/tests/test_stats.py index e33a915964..c2378ff2a7 100644 --- a/nipype/interfaces/niftyseg/tests/test_stats.py +++ b/nipype/interfaces/niftyseg/tests/test_stats.py @@ -1,10 +1,11 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: +import pytest + from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, UnaryStats, BinaryStats) from nipype.testing import example_data -import pytest @pytest.mark.skipif(no_niftyseg(cmd='seg_stats'), From 3ab625038f5fb926abc6f9b5663459fc73f234f3 Mon Sep 17 00:00:00 2001 From: byvernault Date: Thu, 20 Apr 2017 18:26:21 +0100 Subject: [PATCH 09/17] renaming test to create test auto --- .../interfaces/niftyseg/tests/test_auto_EM.py | 80 +++++++++++++++++++ .../{test_em.py => test_em_interfaces.py} | 0 2 files changed, 80 insertions(+) create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_EM.py rename nipype/interfaces/niftyseg/tests/{test_em.py => test_em_interfaces.py} (100%) diff --git a/nipype/interfaces/niftyseg/tests/test_auto_EM.py b/nipype/interfaces/niftyseg/tests/test_auto_EM.py new file mode 100644 index 0000000000..c42acf6a70 --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_EM.py @@ -0,0 +1,80 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..em import EM + + +def test_EM_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + bc_order_val=dict(argstr='-bc_order %s', + ), + bc_thresh_val=dict(argstr='-bc_thresh %s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='-in %s', + mandatory=True, + position=4, + ), + mask_file=dict(argstr='-mask %s', + ), + max_iter=dict(argstr='-max_iter %s', + ), + min_iter=dict(argstr='-min_iter %s', + ), + mrf_beta_val=dict(argstr='-mrf_beta %s', + ), + no_prior=dict(argstr='-nopriors %s', + mandatory=True, + xor=['prior_4D', 'priors'], + ), + out_bc_file=dict(argstr='-bc_out %s', + name_source=['in_file'], + name_template='%s_bc_em.nii.gz', + ), + out_file=dict(argstr='-out %s', + name_source=['in_file'], + name_template='%s_em.nii.gz', + ), + out_outlier_file=dict(argstr='-out_outlier %s', + name_source=['in_file'], + name_template='%s_outlier_em.nii.gz', + ), + outlier_val=dict(argstr='-outlier %s %s', + ), + prior_4D=dict(argstr='-prior4D %s', + mandatory=True, + xor=['no_prior', 'priors'], + ), + priors=dict(argstr='%s', + mandatory=True, + xor=['no_prior', 'prior_4D'], + ), + reg_val=dict(argstr='-reg %s', + ), + relax_priors=dict(argstr='-rf %s %s', + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = EM.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_EM_outputs(): + output_map = dict(out_bc_file=dict(), + out_file=dict(), + out_outlier_file=dict(), + ) + outputs = EM.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/niftyseg/tests/test_em.py b/nipype/interfaces/niftyseg/tests/test_em_interfaces.py similarity index 100% rename from nipype/interfaces/niftyseg/tests/test_em.py rename to nipype/interfaces/niftyseg/tests/test_em_interfaces.py From 84adfcd8665115c9f7cda6aff7de61f2cf090bbf Mon Sep 17 00:00:00 2001 From: byvernault Date: Fri, 21 Apr 2017 10:55:56 +0100 Subject: [PATCH 10/17] fixing doctests --- nipype/interfaces/niftyseg/maths.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 0ec20ad7a1..24029f8cd8 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -149,8 +149,8 @@ class UnaryMaths(MathsCommand): >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'sqrt' >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE - 'seg_maths im1.nii -sqrt -odt float im1_sqrt.nii' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -sqrt -odt float .../im1_sqrt.nii' """ input_spec = UnaryMathsInput @@ -237,8 +237,8 @@ class BinaryMaths(MathsCommand): >>> node.inputs.operation = 'sub' >>> node.inputs.operand_file = 'im2.nii' >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE - 'seg_maths im1.nii -sub im2.nii -odt float im1_sub.nii' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -sub im2.nii -odt float .../im1_sub.nii' """ input_spec = BinaryMathsInput @@ -305,8 +305,8 @@ class BinaryMathsInteger(MathsCommand): >>> node.inputs.operation = 'dil' >>> node.inputs.operand_value = 2 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE - 'seg_maths im1.nii -dil 2 -odt float im1_dil.nii' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -dil 2 -odt float .../im1_dil.nii' """ input_spec = BinaryMathsInputInteger @@ -376,8 +376,8 @@ class TupleMaths(MathsCommand): >>> node.inputs.operand_file1 = 'im2.nii' >>> node.inputs.operand_value2 = 2.0 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE - 'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float im1_lncc.nii' + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + 'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float .../im1_lncc.nii' """ input_spec = TupleMathsInput @@ -417,9 +417,9 @@ class Merge(MathsCommand): >>> node.inputs.merge_files = files >>> node.inputs.dimension = 2 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE + >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE 'seg_maths im1.nii -merge 2 2 im2.nii im3.nii -odt float \ -im1_merged.nii' +.../im1_merged.nii' """ input_spec = MergeInput From 23dccd80b2b3d44523635ff83dc9f2806de2bb0e Mon Sep 17 00:00:00 2001 From: byvernault Date: Mon, 24 Apr 2017 17:01:48 +0100 Subject: [PATCH 11/17] Using overload_extension instead of list_output/gen_filename --- nipype/interfaces/niftyseg/label_fusion.py | 27 ++++----- nipype/interfaces/niftyseg/maths.py | 59 ++++++++----------- nipype/interfaces/niftyseg/patchmatch.py | 4 +- .../niftyseg/tests/test_auto_BinaryMaths.py | 3 +- .../tests/test_auto_BinaryMathsInteger.py | 3 +- .../niftyseg/tests/test_auto_LabelFusion.py | 3 +- .../niftyseg/tests/test_auto_MathsCommand.py | 3 +- .../niftyseg/tests/test_auto_Merge.py | 3 +- .../niftyseg/tests/test_auto_TupleMaths.py | 3 +- .../niftyseg/tests/test_auto_UnaryMaths.py | 3 +- .../niftyseg/tests/test_label_fusion.py | 9 ++- .../interfaces/niftyseg/tests/test_maths.py | 11 ++-- 12 files changed, 61 insertions(+), 70 deletions(-) diff --git a/nipype/interfaces/niftyseg/label_fusion.py b/nipype/interfaces/niftyseg/label_fusion.py index 4936395bb7..6095c3955b 100644 --- a/nipype/interfaces/niftyseg/label_fusion.py +++ b/nipype/interfaces/niftyseg/label_fusion.py @@ -19,7 +19,7 @@ from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, NipypeInterfaceError) from .base import NiftySegCommand, get_custom_path -from ...utils.filemanip import load_json, save_json +from ...utils.filemanip import load_json, save_json, split_filename warn = warnings.warn @@ -46,7 +46,8 @@ class LabelFusionInput(CommandLineInputSpec): desc='Filename of the ROI for label fusion') out_file = File(argstr='-out %s', - genfile=True, + name_source=['in_file'], + name_template='%s', desc='Output consensus segmentation') prob_flag = traits.Bool(desc='Probabilistic/Fuzzy segmented image', @@ -145,9 +146,9 @@ class LabelFusion(NiftySegCommand): >>> node.inputs.template_file = 'im3.nii' >>> node.inputs.template_num = 2 >>> node.inputs.classifier_type = 'STEPS' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE + >>> node.cmdline # doctest: +ALLOW_UNICODE 'seg_LabFusion -in im1.nii -STEPS 2.000000 2 im2.nii im3.nii -out \ -.../im1_steps.nii' +im1_steps.nii' """ _cmd = get_custom_path('seg_LabFusion') @@ -246,19 +247,11 @@ def get_staple_args(self, ranking): self.inputs.file_to_seg, self.inputs.template_file) - def _list_outputs(self): - outputs = self.output_spec().get() - if isdefined(self.inputs.out_file): - outputs['out_file'] = self.inputs.out_file - else: - outputs['out_file'] = self._gen_filename('out_file') - return outputs - - def _gen_filename(self, name): - _suffix = '_%s' % self.inputs.classifier_type.lower() - if name == 'out_file': - return self._gen_fname(self.inputs.in_file, suffix=_suffix) - return None + def _overload_extension(self, value, name=None): + path, base, _ = split_filename(value) + _, _, ext = split_filename(self.inputs.in_file) + suffix = self.inputs.classifier_type.lower() + return os.path.join(path, '{0}_{1}{2}'.format(base, suffix, ext)) class CalcTopNCCInputSpec(CommandLineInputSpec): diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 24029f8cd8..2d83df84ab 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -18,9 +18,12 @@ >>> os.chdir(datadir) """ +import os + from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, NipypeInterfaceError) from .base import NiftySegCommand, get_custom_path +from ...utils.filemanip import split_filename class MathsInput(CommandLineInputSpec): @@ -31,7 +34,8 @@ class MathsInput(CommandLineInputSpec): mandatory=True, desc='image to operate on') - out_file = File(genfile=True, + out_file = File(name_source=['in_file'], + name_template='%s', position=-2, argstr='%s', desc='image to write') @@ -47,7 +51,7 @@ class MathsInput(CommandLineInputSpec): class MathsOutput(TraitedSpec): """Output Spec for seg_maths interfaces.""" - out_file = File(exists=True, desc='image written after calculations') + out_file = File(desc='image written after calculations') class MathsCommand(NiftySegCommand): @@ -72,24 +76,15 @@ class MathsCommand(NiftySegCommand): output_spec = MathsOutput _suffix = '_maths' - def _list_outputs(self): - outputs = self.output_spec().get() + def _overload_extension(self, value, name=None): + path, base, _ = split_filename(value) + _, _, ext = split_filename(self.inputs.in_file) suffix = self._suffix if suffix != '_merged' and isdefined(self.inputs.operation): suffix = '_' + self.inputs.operation - if isdefined(self.inputs.out_file): - outputs['out_file'] = self.inputs.out_file - else: - outputs['out_file'] = self._gen_fname(self.inputs.in_file, - suffix=suffix) - return outputs - - def _gen_filename(self, name): - if name == 'out_file': - return self._list_outputs()['out_file'] - return None + return os.path.join(path, '{0}{1}{2}'.format(base, suffix, ext)) class UnaryMathsInput(MathsInput): @@ -149,8 +144,8 @@ class UnaryMaths(MathsCommand): >>> node.inputs.in_file = 'im1.nii' >>> node.inputs.operation = 'sqrt' >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -sqrt -odt float .../im1_sqrt.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -sqrt -odt float im1_sqrt.nii' """ input_spec = UnaryMathsInput @@ -237,8 +232,8 @@ class BinaryMaths(MathsCommand): >>> node.inputs.operation = 'sub' >>> node.inputs.operand_file = 'im2.nii' >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -sub im2.nii -odt float .../im1_sub.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -sub im2.nii -odt float im1_sub.nii' """ input_spec = BinaryMathsInput @@ -255,14 +250,13 @@ def _format_arg(self, opt, spec, val): return super(BinaryMaths, self)._format_arg(opt, spec, val) - def _list_outputs(self): - outputs = super(BinaryMaths, self)._list_outputs() - + def _overload_extension(self, value, name=None): + path = super(BinaryMaths, self)._overload_extension(value, name) if self.inputs.operation == 'hdr_copy': - outputs['out_file'] = self._gen_fname( - self.inputs.operand_file, - suffix='_{0}'.format(self.inputs.operation)) - return outputs + _, base, ext = split_filename(self.inputs.operand_file) + suffix = self.inputs.operation + path = os.path.join(path, '{0}{1}{2}'.format(base, suffix, ext)) + return path class BinaryMathsInputInteger(MathsInput): @@ -305,8 +299,8 @@ class BinaryMathsInteger(MathsCommand): >>> node.inputs.operation = 'dil' >>> node.inputs.operand_value = 2 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -dil 2 -odt float .../im1_dil.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -dil 2 -odt float im1_dil.nii' """ input_spec = BinaryMathsInputInteger @@ -376,8 +370,8 @@ class TupleMaths(MathsCommand): >>> node.inputs.operand_file1 = 'im2.nii' >>> node.inputs.operand_value2 = 2.0 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float .../im1_lncc.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float im1_lncc.nii' """ input_spec = TupleMathsInput @@ -417,9 +411,8 @@ class Merge(MathsCommand): >>> node.inputs.merge_files = files >>> node.inputs.dimension = 2 >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ELLIPSIS +ALLOW_UNICODE - 'seg_maths im1.nii -merge 2 2 im2.nii im3.nii -odt float \ -.../im1_merged.nii' + >>> node.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -merge 2 2 im2.nii im3.nii -odt float im1_merged.nii' """ input_spec = MergeInput diff --git a/nipype/interfaces/niftyseg/patchmatch.py b/nipype/interfaces/niftyseg/patchmatch.py index c99ec54be5..2f101a17af 100644 --- a/nipype/interfaces/niftyseg/patchmatch.py +++ b/nipype/interfaces/niftyseg/patchmatch.py @@ -11,10 +11,10 @@ >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) >>> os.chdir(datadir) """ -import os + import warnings -from ..base import TraitedSpec, File, traits, isdefined, CommandLineInputSpec +from ..base import TraitedSpec, File, traits, CommandLineInputSpec from .base import NiftySegCommand, get_custom_path diff --git a/nipype/interfaces/niftyseg/tests/test_auto_BinaryMaths.py b/nipype/interfaces/niftyseg/tests/test_auto_BinaryMaths.py index 1fb1531976..714e201fc3 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_BinaryMaths.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_BinaryMaths.py @@ -36,7 +36,8 @@ def test_BinaryMaths_inputs(): position=4, ), out_file=dict(argstr='%s', - genfile=True, + name_source=['in_file'], + name_template='%s', position=-2, ), output_datatype=dict(argstr='-odt %s', diff --git a/nipype/interfaces/niftyseg/tests/test_auto_BinaryMathsInteger.py b/nipype/interfaces/niftyseg/tests/test_auto_BinaryMathsInteger.py index b596d4f468..484f2ac3b4 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_BinaryMathsInteger.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_BinaryMathsInteger.py @@ -25,7 +25,8 @@ def test_BinaryMathsInteger_inputs(): position=4, ), out_file=dict(argstr='%s', - genfile=True, + name_source=['in_file'], + name_template='%s', position=-2, ), output_datatype=dict(argstr='-odt %s', diff --git a/nipype/interfaces/niftyseg/tests/test_auto_LabelFusion.py b/nipype/interfaces/niftyseg/tests/test_auto_LabelFusion.py index 0366f3e79c..b572ac940c 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_LabelFusion.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_LabelFusion.py @@ -33,7 +33,8 @@ def test_LabelFusion_inputs(): mrf_value=dict(argstr='-MRF_beta %f', ), out_file=dict(argstr='-out %s', - genfile=True, + name_source=['in_file'], + name_template='%s', ), prob_flag=dict(argstr='-outProb', ), diff --git a/nipype/interfaces/niftyseg/tests/test_auto_MathsCommand.py b/nipype/interfaces/niftyseg/tests/test_auto_MathsCommand.py index 8e22033d1b..640c7088bf 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_MathsCommand.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_MathsCommand.py @@ -17,7 +17,8 @@ def test_MathsCommand_inputs(): position=2, ), out_file=dict(argstr='%s', - genfile=True, + name_source=['in_file'], + name_template='%s', position=-2, ), output_datatype=dict(argstr='-odt %s', diff --git a/nipype/interfaces/niftyseg/tests/test_auto_Merge.py b/nipype/interfaces/niftyseg/tests/test_auto_Merge.py index a6c09b88f8..3980bc9ac3 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_Merge.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_Merge.py @@ -23,7 +23,8 @@ def test_Merge_inputs(): position=4, ), out_file=dict(argstr='%s', - genfile=True, + name_source=['in_file'], + name_template='%s', position=-2, ), output_datatype=dict(argstr='-odt %s', diff --git a/nipype/interfaces/niftyseg/tests/test_auto_TupleMaths.py b/nipype/interfaces/niftyseg/tests/test_auto_TupleMaths.py index 1e63c1fcb3..9bd5ca771d 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_TupleMaths.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_TupleMaths.py @@ -41,7 +41,8 @@ def test_TupleMaths_inputs(): position=4, ), out_file=dict(argstr='%s', - genfile=True, + name_source=['in_file'], + name_template='%s', position=-2, ), output_datatype=dict(argstr='-odt %s', diff --git a/nipype/interfaces/niftyseg/tests/test_auto_UnaryMaths.py b/nipype/interfaces/niftyseg/tests/test_auto_UnaryMaths.py index 500de81852..ed98de196f 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_UnaryMaths.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_UnaryMaths.py @@ -21,7 +21,8 @@ def test_UnaryMaths_inputs(): position=4, ), out_file=dict(argstr='%s', - genfile=True, + name_source=['in_file'], + name_template='%s', position=-2, ), output_datatype=dict(argstr='-odt %s', diff --git a/nipype/interfaces/niftyseg/tests/test_label_fusion.py b/nipype/interfaces/niftyseg/tests/test_label_fusion.py index 82645cda97..eb6330f732 100644 --- a/nipype/interfaces/niftyseg/tests/test_label_fusion.py +++ b/nipype/interfaces/niftyseg/tests/test_label_fusion.py @@ -1,7 +1,6 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: -import os import pytest from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, @@ -41,7 +40,7 @@ def test_seg_lab_fusion(): in_file=in_file, file_to_seg=file_to_seg, template_file=template_file, - out_file=os.path.join(os.getcwd(), 'im1_steps.nii') + out_file='im1_steps.nii', ) assert steps.cmdline == expected_cmd @@ -62,7 +61,7 @@ def test_seg_lab_fusion(): in_file=in_file, file_to_seg=file_to_seg, template_file=template_file, - out_file=os.path.join(os.getcwd(), 'im1_staple.nii') + out_file='im1_staple.nii', ) assert staple.cmdline == expected_cmd @@ -84,7 +83,7 @@ def test_seg_lab_fusion(): in_file=in_file, file_to_seg=file_to_seg, template_file=template_file, - out_file=os.path.join(os.getcwd(), 'im1_mv.nii') + out_file='im1_mv.nii', ) assert mv_node.cmdline == expected_cmd @@ -118,7 +117,7 @@ def test_seg_calctopncc(): cmd=get_custom_path('seg_CalcTopNCC'), in_file=in_file, file1=file1, - file2=file2 + file2=file2, ) assert calctopncc.cmdline == expected_cmd diff --git a/nipype/interfaces/niftyseg/tests/test_maths.py b/nipype/interfaces/niftyseg/tests/test_maths.py index 163c5ab189..0f32177a8f 100644 --- a/nipype/interfaces/niftyseg/tests/test_maths.py +++ b/nipype/interfaces/niftyseg/tests/test_maths.py @@ -1,7 +1,6 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: -import os import pytest from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, @@ -34,7 +33,7 @@ def test_unary_maths(): expected_cmd = '{cmd} {in_file} -otsu -odt float {out_file}'.format( cmd=get_custom_path('seg_maths'), in_file=in_file, - out_file=os.path.join(os.getcwd(), 'im1_otsu.nii')) + out_file='im1_otsu.nii') assert unarym.cmdline == expected_cmd @@ -64,7 +63,7 @@ def test_binary_maths(): expected_cmd = cmd_tmp.format( cmd=get_custom_path('seg_maths'), in_file=in_file, - out_file=os.path.join(os.getcwd(), 'im1_sub.nii')) + out_file='im1_sub.nii') assert binarym.cmdline == expected_cmd @@ -93,7 +92,7 @@ def test_int_binary_maths(): expected_cmd = '{cmd} {in_file} -dil 2 -odt float {out_file}'.format( cmd=get_custom_path('seg_maths'), in_file=in_file, - out_file=os.path.join(os.getcwd(), 'im1_dil.nii')) + out_file='im1_dil.nii') assert ibinarym.cmdline == expected_cmd @@ -126,7 +125,7 @@ def test_tuple_maths(): cmd=get_custom_path('seg_maths'), in_file=in_file, op=op_file, - out_file=os.path.join(os.getcwd(), 'im1_lncc.nii')) + out_file='im1_lncc.nii') assert tuplem.cmdline == expected_cmd @@ -160,6 +159,6 @@ def test_merge(): in_file=in_file, f1=file1, f2=file2, - out_file=os.path.join(os.getcwd(), 'im1_merged.nii')) + out_file='im1_merged.nii') assert merge.cmdline == expected_cmd From be7c4893fc035369275d097b09e8761d57e8d697 Mon Sep 17 00:00:00 2001 From: byvernault Date: Mon, 24 Apr 2017 17:10:36 +0100 Subject: [PATCH 12/17] Editing few options on the interface FillLesions --- nipype/interfaces/niftyseg/lesions.py | 29 +++++++++---------- .../niftyseg/tests/test_auto_FillLesions.py | 15 ++-------- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/nipype/interfaces/niftyseg/lesions.py b/nipype/interfaces/niftyseg/lesions.py index 7c4bb4630b..03241137c5 100644 --- a/nipype/interfaces/niftyseg/lesions.py +++ b/nipype/interfaces/niftyseg/lesions.py @@ -45,48 +45,47 @@ class FillLesionsInputSpec(CommandLineInputSpec): # Optional arguments desc = "Dilate the mask times (in voxels, by default 0)" - in_dilation = traits.Int(desc=desc, argstr='-dil %d', mandatory=False) + in_dilation = traits.Int(desc=desc, argstr='-dil %d') desc = 'Percentage of minimum number of voxels between patches \ (by default 0.5).' - match = traits.Float(desc=desc, argstr='-match %f', mandatory=False) + match = traits.Float(desc=desc, argstr='-match %f') desc = 'Minimum percentage of valid voxels in target patch \ (by default 0).' - search = traits.Float(desc=desc, argstr='-search %f', mandatory=False) + search = traits.Float(desc=desc, argstr='-search %f') desc = 'Smoothing by (in minimal 6-neighbourhood voxels \ (by default 0.1)).' - smooth = traits.Float(desc=desc, argstr='-smo %f', mandatory=False) + smooth = traits.Float(desc=desc, argstr='-smo %f') desc = 'Search regions size respect biggest patch size (by default 4).' - size = traits.Int(desc=desc, argstr='-size %d', mandatory=False) + size = traits.Int(desc=desc, argstr='-size %d') desc = 'Patch cardinality weighting factor (by default 2).' - cwf = traits.Float(desc=desc, argstr='-cwf %f', mandatory=False) + cwf = traits.Float(desc=desc, argstr='-cwf %f') desc = 'Give a binary mask with the valid search areas.' - bin_mask = File(desc=desc, argstr='-mask %s', mandatory=False) + bin_mask = File(desc=desc, argstr='-mask %s') desc = "Guizard et al. (FIN 2015) method, it doesn't include the \ multiresolution/hierarchical inpainting part, this part needs to be done \ with some external software such as reg_tools and reg_resample from NiftyReg. \ By default it uses the method presented in Prados et al. (Neuroimage 2016)." - other = traits.Bool(desc=desc, argstr='-other', mandatory=False) + other = traits.Bool(desc=desc, argstr='-other') + + use_2d = traits.Bool(desc='Uses 2D patches in the Z axis, by default 3D.', + argstr='-2D') debug = traits.Bool(desc='Save all intermidium files (by default OFF).', - argstr='-debug', mandatory=False) + argstr='-debug') desc = 'Set output (char, short, int, uchar, ushort, uint, \ float, double).' - out_datatype = traits.String(desc=desc, argstr='-odt %s', mandatory=False) + out_datatype = traits.String(desc=desc, argstr='-odt %s') verbose = traits.Bool(desc='Verbose (by default OFF).', - argstr='-v', mandatory=False) - - # Set the number of omp thread to use - omp_core = traits.Int(desc='Number of openmp thread to use. Default: 4', - argstr='-omp %d') + argstr='-v') class FillLesionsOutputSpec(TraitedSpec): diff --git a/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py b/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py index ed0cc42b0b..aae126636a 100644 --- a/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py +++ b/nipype/interfaces/niftyseg/tests/test_auto_FillLesions.py @@ -7,13 +7,10 @@ def test_FillLesions_inputs(): input_map = dict(args=dict(argstr='%s', ), bin_mask=dict(argstr='-mask %s', - mandatory=False, ), cwf=dict(argstr='-cwf %f', - mandatory=False, ), debug=dict(argstr='-debug', - mandatory=False, ), environ=dict(nohash=True, usedefault=True, @@ -22,7 +19,6 @@ def test_FillLesions_inputs(): usedefault=True, ), in_dilation=dict(argstr='-dil %d', - mandatory=False, ), in_file=dict(argstr='-i %s', mandatory=True, @@ -33,15 +29,10 @@ def test_FillLesions_inputs(): position=2, ), match=dict(argstr='-match %f', - mandatory=False, - ), - omp_core=dict(argstr='-omp %d', ), other=dict(argstr='-other', - mandatory=False, ), out_datatype=dict(argstr='-odt %s', - mandatory=False, ), out_file=dict(argstr='-o %s', name_source=['in_file'], @@ -49,18 +40,16 @@ def test_FillLesions_inputs(): position=3, ), search=dict(argstr='-search %f', - mandatory=False, ), size=dict(argstr='-size %d', - mandatory=False, ), smooth=dict(argstr='-smo %f', - mandatory=False, ), terminal_output=dict(nohash=True, ), + use_2d=dict(argstr='-2D', + ), verbose=dict(argstr='-v', - mandatory=False, ), ) inputs = FillLesions.input_spec() From c40b6734a610fda87505bc681dfce1b7a584e2d0 Mon Sep 17 00:00:00 2001 From: byvernault Date: Mon, 1 May 2017 17:35:12 +0100 Subject: [PATCH 13/17] removing base.py and using niftyreg base.py class/fct. Renaming functions as well --- nipype/interfaces/niftyreg/__init__.py | 2 +- nipype/interfaces/niftyreg/base.py | 8 +- nipype/interfaces/niftyreg/tests/test_reg.py | 6 +- .../niftyreg/tests/test_regutils.py | 14 +-- nipype/interfaces/niftyseg/__init__.py | 1 - nipype/interfaces/niftyseg/base.py | 91 ------------------- nipype/interfaces/niftyseg/em.py | 9 +- nipype/interfaces/niftyseg/label_fusion.py | 14 +-- nipype/interfaces/niftyseg/lesions.py | 6 +- nipype/interfaces/niftyseg/maths.py | 11 +-- nipype/interfaces/niftyseg/patchmatch.py | 6 +- nipype/interfaces/niftyseg/stats.py | 6 +- .../tests/test_auto_NiftySegCommand.py | 23 ----- .../niftyseg/tests/test_em_interfaces.py | 5 +- .../niftyseg/tests/test_label_fusion.py | 8 +- .../interfaces/niftyseg/tests/test_lesions.py | 6 +- .../interfaces/niftyseg/tests/test_maths.py | 13 +-- .../niftyseg/tests/test_patchmatch.py | 5 +- .../interfaces/niftyseg/tests/test_stats.py | 9 +- 19 files changed, 65 insertions(+), 178 deletions(-) delete mode 100644 nipype/interfaces/niftyseg/base.py delete mode 100644 nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py diff --git a/nipype/interfaces/niftyreg/__init__.py b/nipype/interfaces/niftyreg/__init__.py index 9c0feeb2fb..64cc60a0ab 100644 --- a/nipype/interfaces/niftyreg/__init__.py +++ b/nipype/interfaces/niftyreg/__init__.py @@ -9,7 +9,7 @@ Top-level namespace for niftyreg. """ -from .base import no_niftyreg, get_custom_path +from .base import no_nifty_package, get_custom_path from .reg import RegAladin, RegF3D from .regutils import (RegResample, RegJacobian, RegAverage, RegTools, RegTransform, RegMeasure) diff --git a/nipype/interfaces/niftyreg/base.py b/nipype/interfaces/niftyreg/base.py index 9a21fcfd2e..45757cb453 100644 --- a/nipype/interfaces/niftyreg/base.py +++ b/nipype/interfaces/niftyreg/base.py @@ -30,11 +30,11 @@ from ...utils.filemanip import split_filename -def get_custom_path(command): - return os.path.join(os.getenv('NIFTYREGDIR', ''), command) +def get_custom_path(command, env_dir='NIFTYREGDIR'): + return os.path.join(os.getenv(env_dir, ''), command) -def no_niftyreg(cmd='reg_f3d'): +def no_nifty_package(cmd='reg_f3d'): try: return shutil.which(cmd) is None except AttributeError: # Python < 3.3 @@ -89,7 +89,7 @@ def check_version(self): raise ValueError(err % (_version, self.required_version)) def get_version(self): - if no_niftyreg(cmd=self.cmd): + if no_nifty_package(cmd=self.cmd): return None exec_cmd = ''.join((self.cmd, ' -v')) return subprocess.check_output(exec_cmd, shell=True).strip() diff --git a/nipype/interfaces/niftyreg/tests/test_reg.py b/nipype/interfaces/niftyreg/tests/test_reg.py index 8f9a8eb886..9a3705fba7 100644 --- a/nipype/interfaces/niftyreg/tests/test_reg.py +++ b/nipype/interfaces/niftyreg/tests/test_reg.py @@ -4,13 +4,13 @@ import pytest -from nipype.interfaces.niftyreg import (no_niftyreg, get_custom_path, +from nipype.interfaces.niftyreg import (no_nifty_package, get_custom_path, RegAladin, RegF3D) from nipype.testing import example_data @pytest.mark.skipif( - no_niftyreg(cmd='reg_aladin'), + no_nifty_package(cmd='reg_aladin'), reason="niftyreg is not installed. reg_aladin not found.") def test_reg_aladin(): """ tests for reg_aladin interface""" @@ -48,7 +48,7 @@ def test_reg_aladin(): @pytest.mark.skipif( - no_niftyreg(cmd='reg_f3d'), + no_nifty_package(cmd='reg_f3d'), reason="niftyreg is not installed. reg_f3d not found.") def test_reg_f3d(): """ tests for reg_f3d interface""" diff --git a/nipype/interfaces/niftyreg/tests/test_regutils.py b/nipype/interfaces/niftyreg/tests/test_regutils.py index b2e1357811..4ad7973683 100644 --- a/nipype/interfaces/niftyreg/tests/test_regutils.py +++ b/nipype/interfaces/niftyreg/tests/test_regutils.py @@ -2,7 +2,7 @@ # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- # vi: set ft=python sts=4 ts=4 sw=4 et: -from nipype.interfaces.niftyreg import (no_niftyreg, get_custom_path, +from nipype.interfaces.niftyreg import (no_nifty_package, get_custom_path, RegAverage, RegResample, RegJacobian, RegTools, RegMeasure, RegTransform) from nipype.testing import example_data @@ -11,7 +11,7 @@ @pytest.mark.skipif( - no_niftyreg(cmd='reg_resample'), + no_nifty_package(cmd='reg_resample'), reason="niftyreg is not installed. reg_resample not found.") def test_reg_resample_res(): """ tests for reg_resample interface """ @@ -68,7 +68,7 @@ def test_reg_resample_res(): @pytest.mark.skipif( - no_niftyreg(cmd='reg_jacobian'), + no_nifty_package(cmd='reg_jacobian'), reason="niftyreg is not installed. reg_jacobian not found.") def test_reg_jacobian_jac(): """ Test interface for RegJacobian """ @@ -132,7 +132,7 @@ def test_reg_jacobian_jac(): @pytest.mark.skipif( - no_niftyreg(cmd='reg_tools'), + no_nifty_package(cmd='reg_tools'), reason="niftyreg is not installed. reg_tools not found.") def test_reg_tools_mul(): """ tests for reg_tools interface """ @@ -175,7 +175,7 @@ def test_reg_tools_mul(): @pytest.mark.skipif( - no_niftyreg(cmd='reg_average'), + no_nifty_package(cmd='reg_average'), reason="niftyreg is not installed. reg_average not found.") def test_reg_average(): """ tests for reg_average interface """ @@ -318,7 +318,7 @@ def test_reg_average(): @pytest.mark.skipif( - no_niftyreg(cmd='reg_transform'), + no_nifty_package(cmd='reg_transform'), reason="niftyreg is not installed. reg_transform not found.") def test_reg_transform_def(): """ tests for reg_transform interface """ @@ -427,7 +427,7 @@ def test_reg_transform_def(): @pytest.mark.skipif( - no_niftyreg(cmd='reg_measure'), + no_nifty_package(cmd='reg_measure'), reason="niftyreg is not installed. reg_measure not found.") def test_reg_measure(): """ tests for reg_measure interface """ diff --git a/nipype/interfaces/niftyseg/__init__.py b/nipype/interfaces/niftyseg/__init__.py index c3992d827c..0cbb101aba 100644 --- a/nipype/interfaces/niftyseg/__init__.py +++ b/nipype/interfaces/niftyseg/__init__.py @@ -8,7 +8,6 @@ Top-level namespace for niftyseg. """ -from .base import no_niftyseg, get_custom_path from .em import EM from .label_fusion import LabelFusion, CalcTopNCC from .lesions import FillLesions diff --git a/nipype/interfaces/niftyseg/base.py b/nipype/interfaces/niftyseg/base.py deleted file mode 100644 index b77ba19007..0000000000 --- a/nipype/interfaces/niftyseg/base.py +++ /dev/null @@ -1,91 +0,0 @@ -# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- -# vi: set ft=python sts=4 ts=4 sw=4 et: - -""" -The niftyseg module provides classes for interfacing with `niftyseg -`_ command line tools. - -These are the base tools for working with niftyseg. - -EM Statistical Segmentation tool is found in niftyseg/em.py -Fill lesions tool is found in niftyseg/lesions.py -Mathematical operation tool is found in niftyseg/maths.py -Patch Match tool is found in niftyseg/patchmatch.py -Statistical operation tool is found in niftyseg/stats.py -Label Fusion and CalcTopNcc tools are in niftyseg/steps.py - -Examples --------- -See the docstrings of the individual classes for examples. - -""" - -from nipype.interfaces.base import CommandLine -from nipype.utils.filemanip import split_filename -import os -import subprocess -import warnings - - -warn = warnings.warn -warnings.filterwarnings('always', category=UserWarning) - - -def get_custom_path(command): - """Get path of niftyseg.""" - try: - specific_dir = os.environ['NIFTYSEGDIR'] - command = os.path.join(specific_dir, command) - return command - except KeyError: - return command - - -def no_niftyseg(cmd='seg_LabFusion'): - """Check if niftyseg is installed.""" - if True in [os.path.isfile(os.path.join(path, cmd)) and - os.access(os.path.join(path, cmd), os.X_OK) - for path in os.environ["PATH"].split(os.pathsep)]: - return False - return True - - -class NiftySegCommand(CommandLine): - """ - Base support interface for NiftySeg commands. - """ - _suffix = '_ns' - - def __init__(self, **inputs): - super(NiftySegCommand, self).__init__(**inputs) - - def get_version(self): - if no_niftyseg(cmd=self.cmd): - return None - # exec_cmd = ''.join((self.cmd, ' --version')) - exec_cmd = 'seg_EM --version' - # Using seg_EM for version (E.G: seg_stats --version doesn't work) - return subprocess.check_output(exec_cmd, shell=True).strip('\n') - - @property - def version(self): - return self.get_version() - - def exists(self): - if self.get_version() is None: - return False - return True - - def _gen_fname(self, basename, out_dir=None, suffix=None, ext=None): - if basename == '': - msg = 'Unable to generate filename for command %s. ' % self.cmd - msg += 'basename is not set!' - raise ValueError(msg) - _, final_bn, final_ext = split_filename(basename) - if out_dir is None: - out_dir = os.getcwd() - if ext is not None: - final_ext = ext - if suffix is not None: - final_bn = ''.join((final_bn, suffix)) - return os.path.abspath(os.path.join(out_dir, final_bn + final_ext)) diff --git a/nipype/interfaces/niftyseg/em.py b/nipype/interfaces/niftyseg/em.py index 5d322d3eb4..e75404f015 100644 --- a/nipype/interfaces/niftyseg/em.py +++ b/nipype/interfaces/niftyseg/em.py @@ -20,7 +20,7 @@ from ..base import (TraitedSpec, File, traits, CommandLineInputSpec, InputMultiPath) -from .base import NiftySegCommand, get_custom_path +from ..niftyreg.base import NiftyRegCommand, get_custom_path class EMInputSpec(CommandLineInputSpec): @@ -47,10 +47,9 @@ class EMInputSpec(CommandLineInputSpec): desc='4D file containing the priors', xor=['no_prior', 'priors']) - desc = 'List of priors filepaths.' priors = InputMultiPath(argstr='%s', mandatory=True, - desc=desc, + desc='List of priors filepaths.', xor=['no_prior', 'prior_4D']) # iterations @@ -110,7 +109,7 @@ class EMOutputSpec(TraitedSpec): out_outlier_file = File(desc='Output outlierness image') -class EM(NiftySegCommand): +class EM(NiftyRegCommand): """Interface for executable seg_EM from NiftySeg platform. seg_EM is a general purpose intensity based image segmentation tool. In @@ -132,7 +131,7 @@ class EM(NiftySegCommand): -out im1_em.nii.gz -out_outlier im1_outlier_em.nii.gz' """ - _cmd = get_custom_path('seg_EM') + _cmd = get_custom_path('seg_EM', env_dir='NIFTYSEGDIR') _suffix = '_em' input_spec = EMInputSpec output_spec = EMOutputSpec diff --git a/nipype/interfaces/niftyseg/label_fusion.py b/nipype/interfaces/niftyseg/label_fusion.py index 6095c3955b..c89b36818a 100644 --- a/nipype/interfaces/niftyseg/label_fusion.py +++ b/nipype/interfaces/niftyseg/label_fusion.py @@ -18,7 +18,7 @@ from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, NipypeInterfaceError) -from .base import NiftySegCommand, get_custom_path +from ..niftyreg.base import get_custom_path, NiftyRegCommand from ...utils.filemanip import load_json, save_json, split_filename @@ -111,7 +111,7 @@ class LabelFusionOutput(TraitedSpec): out_file = File(exists=True, desc='image written after calculations') -class LabelFusion(NiftySegCommand): +class LabelFusion(NiftyRegCommand): """Interface for executable seg_LabelFusion from NiftySeg platform using type STEPS as classifier Fusion. @@ -151,7 +151,7 @@ class LabelFusion(NiftySegCommand): im1_steps.nii' """ - _cmd = get_custom_path('seg_LabFusion') + _cmd = get_custom_path('seg_LabFusion', env_dir='NIFTYSEGDIR') input_spec = LabelFusionInput output_spec = LabelFusionOutput _suffix = '_label_fused' @@ -197,7 +197,7 @@ def get_staple_args(self, ranking): return None if ranking == 'ALL': - return '-%s' % ranking + return '-ALL' if not isdefined(self.inputs.template_file): err = "LabelFusion requires a value for input 'tramplate_file' \ @@ -288,7 +288,7 @@ class CalcTopNCCOutputSpec(TraitedSpec): out_files = traits.Any(File(exists=True)) -class CalcTopNCC(NiftySegCommand): +class CalcTopNCC(NiftyRegCommand): """Interface for executable seg_CalcTopNCC from NiftySeg platform. Examples @@ -303,7 +303,7 @@ class CalcTopNCC(NiftySegCommand): 'seg_CalcTopNCC -target im1.nii -templates 2 im2.nii im3.nii -n 1' """ - _cmd = get_custom_path('seg_CalcTopNCC') + _cmd = get_custom_path('seg_CalcTopNCC', env_dir='NIFTYSEGDIR') _suffix = '_topNCC' input_spec = CalcTopNCCInputSpec output_spec = CalcTopNCCOutputSpec @@ -312,7 +312,7 @@ def aggregate_outputs(self, runtime=None, needed_outputs=None): outputs = self._outputs() # local caching for backward compatibility outfile = os.path.join(os.getcwd(), 'CalcTopNCC.json') - if runtime is None: + if runtime is None or not runtime.stdout: try: out_files = load_json(outfile)['files'] except IOError: diff --git a/nipype/interfaces/niftyseg/lesions.py b/nipype/interfaces/niftyseg/lesions.py index 03241137c5..ff23860257 100644 --- a/nipype/interfaces/niftyseg/lesions.py +++ b/nipype/interfaces/niftyseg/lesions.py @@ -21,7 +21,7 @@ import warnings from ..base import TraitedSpec, File, traits, CommandLineInputSpec -from .base import NiftySegCommand, get_custom_path +from ..niftyreg.base import NiftyRegCommand, get_custom_path warn = warnings.warn @@ -93,7 +93,7 @@ class FillLesionsOutputSpec(TraitedSpec): out_file = File(desc="Output segmentation") -class FillLesions(NiftySegCommand): +class FillLesions(NiftyRegCommand): """Interface for executable seg_FillLesions from NiftySeg platform. Fill all the masked lesions with WM intensity average. @@ -112,6 +112,6 @@ class FillLesions(NiftySegCommand): 'seg_FillLesions -i im1.nii -l im2.nii -o im1_lesions_filled.nii.gz' """ - _cmd = get_custom_path('seg_FillLesions') + _cmd = get_custom_path('seg_FillLesions', env_dir='NIFTYSEGDIR') input_spec = FillLesionsInputSpec output_spec = FillLesionsOutputSpec diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 2d83df84ab..b890a8a776 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -22,7 +22,7 @@ from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, NipypeInterfaceError) -from .base import NiftySegCommand, get_custom_path +from ..niftyreg.base import NiftyRegCommand, get_custom_path from ...utils.filemanip import split_filename @@ -40,10 +40,9 @@ class MathsInput(CommandLineInputSpec): argstr='%s', desc='image to write') - _dtypes = ['float', 'char', 'int', 'short', 'double', 'input'] - desc = 'datatype to use for output (default uses input type)' - output_datatype = traits.Enum(*_dtypes, + output_datatype = traits.Enum('float', 'char', 'int', 'short', + 'double', 'input', position=-3, argstr='-odt %s', desc=desc) @@ -54,7 +53,7 @@ class MathsOutput(TraitedSpec): out_file = File(desc='image written after calculations') -class MathsCommand(NiftySegCommand): +class MathsCommand(NiftyRegCommand): """ Base Command Interface for seg_maths interfaces. @@ -71,7 +70,7 @@ class MathsCommand(NiftySegCommand): into several 3D images, to estimating the maximum, minimum and average over all time-points, etc. """ - _cmd = get_custom_path('seg_maths') + _cmd = get_custom_path('seg_maths', env_dir='NIFTYSEGDIR') input_spec = MathsInput output_spec = MathsOutput _suffix = '_maths' diff --git a/nipype/interfaces/niftyseg/patchmatch.py b/nipype/interfaces/niftyseg/patchmatch.py index 2f101a17af..35e4cc2639 100644 --- a/nipype/interfaces/niftyseg/patchmatch.py +++ b/nipype/interfaces/niftyseg/patchmatch.py @@ -15,7 +15,7 @@ import warnings from ..base import TraitedSpec, File, traits, CommandLineInputSpec -from .base import NiftySegCommand, get_custom_path +from ..niftyreg.base import NiftyRegCommand, get_custom_path warn = warnings.warn @@ -80,7 +80,7 @@ class PatchMatchOutputSpec(TraitedSpec): out_file = File(desc="Output segmentation") -class PatchMatch(NiftySegCommand): +class PatchMatch(NiftyRegCommand): """Interface for executable seg_PatchMatch from NiftySeg platform. The database file is a text file and in each line we have a template @@ -110,7 +110,7 @@ class PatchMatch(NiftySegCommand): 'seg_PatchMatch -i im1.nii -m im2.nii -db db.xml -o im1_pm.nii.gz' """ - _cmd = get_custom_path('seg_PatchMatch') + _cmd = get_custom_path('seg_PatchMatch', env_dir='NIFTYSEGDIR') input_spec = PatchMatchInputSpec output_spec = PatchMatchOutputSpec _suffix = '_pm' diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index 18c359f554..2d5d87eb30 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -15,7 +15,7 @@ import numpy as np from ..base import TraitedSpec, File, traits, CommandLineInputSpec -from .base import NiftySegCommand, get_custom_path +from ..niftyreg.base import NiftyRegCommand, get_custom_path class StatsInput(CommandLineInputSpec): @@ -45,7 +45,7 @@ class StatsOutput(TraitedSpec): output = traits.Array(desc='Output array from seg_stats') -class StatsCommand(NiftySegCommand): +class StatsCommand(NiftyRegCommand): """ Base Command Interface for seg_stats interfaces. @@ -59,7 +59,7 @@ class StatsCommand(NiftySegCommand): robust to the presence of NaNs, and can be constrained by a mask and/or thresholded at a certain level. """ - _cmd = get_custom_path('seg_stats') + _cmd = get_custom_path('seg_stats', env_dir='NIFTYSEGDIR') input_spec = StatsInput output_spec = StatsOutput diff --git a/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py b/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py deleted file mode 100644 index 55dc5d9d1d..0000000000 --- a/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py +++ /dev/null @@ -1,23 +0,0 @@ -# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT -from __future__ import unicode_literals -from ..base import NiftySegCommand - - -def test_NiftySegCommand_inputs(): - input_map = dict(args=dict(argstr='%s', - ), - environ=dict(nohash=True, - usedefault=True, - ), - ignore_exception=dict(nohash=True, - usedefault=True, - ), - terminal_output=dict(nohash=True, - ), - ) - inputs = NiftySegCommand.input_spec() - - for key, metadata in list(input_map.items()): - for metakey, value in list(metadata.items()): - assert getattr(inputs.traits()[key], metakey) == value - diff --git a/nipype/interfaces/niftyseg/tests/test_em_interfaces.py b/nipype/interfaces/niftyseg/tests/test_em_interfaces.py index 54224ee623..19da48e81d 100644 --- a/nipype/interfaces/niftyseg/tests/test_em_interfaces.py +++ b/nipype/interfaces/niftyseg/tests/test_em_interfaces.py @@ -3,11 +3,12 @@ import pytest -from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, EM +from nipype.interfaces.niftyreg import no_nifty_package +from nipype.interfaces.niftyseg import get_custom_path, EM from nipype.testing import example_data -@pytest.mark.skipif(no_niftyseg(cmd='seg_EM'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_EM'), reason="niftyseg is not installed") def test_seg_em(): diff --git a/nipype/interfaces/niftyseg/tests/test_label_fusion.py b/nipype/interfaces/niftyseg/tests/test_label_fusion.py index eb6330f732..35f13a3876 100644 --- a/nipype/interfaces/niftyseg/tests/test_label_fusion.py +++ b/nipype/interfaces/niftyseg/tests/test_label_fusion.py @@ -3,12 +3,12 @@ import pytest -from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, - LabelFusion, CalcTopNCC) +from nipype.interfaces.niftyreg import no_nifty_package +from nipype.interfaces.niftyseg import get_custom_path, LabelFusion, CalcTopNCC from nipype.testing import example_data -@pytest.mark.skipif(no_niftyseg(cmd='seg_LabFusion'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_LabFusion'), reason="niftyseg is not installed") def test_seg_lab_fusion(): """ Test interfaces for seg_labfusion""" @@ -89,7 +89,7 @@ def test_seg_lab_fusion(): assert mv_node.cmdline == expected_cmd -@pytest.mark.skipif(no_niftyseg(cmd='seg_CalcTopNCC'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_CalcTopNCC'), reason="niftyseg is not installed") def test_seg_calctopncc(): """ Test interfaces for seg_CalctoNCC""" diff --git a/nipype/interfaces/niftyseg/tests/test_lesions.py b/nipype/interfaces/niftyseg/tests/test_lesions.py index d228030b4c..fa7307c085 100644 --- a/nipype/interfaces/niftyseg/tests/test_lesions.py +++ b/nipype/interfaces/niftyseg/tests/test_lesions.py @@ -3,12 +3,12 @@ import pytest -from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, - FillLesions) +from nipype.interfaces.niftyreg import no_nifty_package +from nipype.interfaces.niftyseg import get_custom_path, FillLesions from nipype.testing import example_data -@pytest.mark.skipif(no_niftyseg(cmd='seg_FillLesions'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_FillLesions'), reason="niftyseg is not installed") def test_seg_filllesions(): diff --git a/nipype/interfaces/niftyseg/tests/test_maths.py b/nipype/interfaces/niftyseg/tests/test_maths.py index 0f32177a8f..640e53aa9e 100644 --- a/nipype/interfaces/niftyseg/tests/test_maths.py +++ b/nipype/interfaces/niftyseg/tests/test_maths.py @@ -3,14 +3,15 @@ import pytest -from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, +from nipype.interfaces.niftyreg import no_nifty_package +from nipype.interfaces.niftyseg import (get_custom_path, UnaryMaths, BinaryMaths, BinaryMathsInteger, TupleMaths, Merge) from nipype.testing import example_data -@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_maths'), reason="niftyseg is not installed") def test_unary_maths(): @@ -38,7 +39,7 @@ def test_unary_maths(): assert unarym.cmdline == expected_cmd -@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_maths'), reason="niftyseg is not installed") def test_binary_maths(): @@ -68,7 +69,7 @@ def test_binary_maths(): assert binarym.cmdline == expected_cmd -@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_maths'), reason="niftyseg is not installed") def test_int_binary_maths(): @@ -97,7 +98,7 @@ def test_int_binary_maths(): assert ibinarym.cmdline == expected_cmd -@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_maths'), reason="niftyseg is not installed") def test_tuple_maths(): @@ -130,7 +131,7 @@ def test_tuple_maths(): assert tuplem.cmdline == expected_cmd -@pytest.mark.skipif(no_niftyseg(cmd='seg_maths'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_maths'), reason="niftyseg is not installed") def test_merge(): diff --git a/nipype/interfaces/niftyseg/tests/test_patchmatch.py b/nipype/interfaces/niftyseg/tests/test_patchmatch.py index e584ab6b93..8e61599cec 100644 --- a/nipype/interfaces/niftyseg/tests/test_patchmatch.py +++ b/nipype/interfaces/niftyseg/tests/test_patchmatch.py @@ -3,11 +3,12 @@ import pytest -from nipype.interfaces.niftyseg import no_niftyseg, get_custom_path, PatchMatch +from nipype.interfaces.niftyreg import no_nifty_package +from nipype.interfaces.niftyseg import get_custom_path, PatchMatch from nipype.testing import example_data -@pytest.mark.skipif(no_niftyseg(cmd='seg_PatchMatch'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_PatchMatch'), reason="niftyseg is not installed") def test_seg_patchmatch(): diff --git a/nipype/interfaces/niftyseg/tests/test_stats.py b/nipype/interfaces/niftyseg/tests/test_stats.py index c2378ff2a7..a31f79c416 100644 --- a/nipype/interfaces/niftyseg/tests/test_stats.py +++ b/nipype/interfaces/niftyseg/tests/test_stats.py @@ -3,12 +3,13 @@ import pytest -from nipype.interfaces.niftyseg import (no_niftyseg, get_custom_path, - UnaryStats, BinaryStats) +from nipype.interfaces.niftyreg import no_nifty_package +from nipype.interfaces.niftyseg import (get_custom_path, UnaryStats, + BinaryStats) from nipype.testing import example_data -@pytest.mark.skipif(no_niftyseg(cmd='seg_stats'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_stats'), reason="niftyseg is not installed") def test_unary_stats(): """ Test for the seg_stats interfaces """ @@ -34,7 +35,7 @@ def test_unary_stats(): assert unarys.cmdline == expected_cmd -@pytest.mark.skipif(no_niftyseg(cmd='seg_stats'), +@pytest.mark.skipif(no_nifty_package(cmd='seg_stats'), reason="niftyseg is not installed") def test_binary_stats(): """ Test for the seg_stats interfaces """ From 3389a28afa2ebc857b8ca627b1fe5dabcc201876 Mon Sep 17 00:00:00 2001 From: byvernault Date: Mon, 1 May 2017 22:13:51 +0100 Subject: [PATCH 14/17] Adding back base.py for NiftySegCommand because of version control on the software. --- nipype/interfaces/niftyreg/base.py | 3 +- nipype/interfaces/niftyseg/base.py | 44 +++++++++++++++++++ nipype/interfaces/niftyseg/em.py | 5 ++- nipype/interfaces/niftyseg/label_fusion.py | 7 +-- nipype/interfaces/niftyseg/lesions.py | 5 ++- nipype/interfaces/niftyseg/maths.py | 5 ++- nipype/interfaces/niftyseg/patchmatch.py | 5 ++- nipype/interfaces/niftyseg/stats.py | 5 ++- .../tests/test_auto_NiftySegCommand.py | 23 ++++++++++ .../niftyseg/tests/test_em_interfaces.py | 9 ++-- .../niftyseg/tests/test_label_fusion.py | 18 ++++---- .../interfaces/niftyseg/tests/test_lesions.py | 9 ++-- .../interfaces/niftyseg/tests/test_maths.py | 30 +++++++------ .../niftyseg/tests/test_patchmatch.py | 9 ++-- .../interfaces/niftyseg/tests/test_stats.py | 15 ++++--- 15 files changed, 138 insertions(+), 54 deletions(-) create mode 100644 nipype/interfaces/niftyseg/base.py create mode 100644 nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py diff --git a/nipype/interfaces/niftyreg/base.py b/nipype/interfaces/niftyreg/base.py index 45757cb453..a7672166fc 100644 --- a/nipype/interfaces/niftyreg/base.py +++ b/nipype/interfaces/niftyreg/base.py @@ -64,7 +64,8 @@ def __init__(self, required_version=None, **inputs): _version = self.get_version() if _version: _version = _version.decode("utf-8") - if StrictVersion(_version) < StrictVersion(self._min_version): + if self._min_version is not None and \ + StrictVersion(_version) < StrictVersion(self._min_version): msg = 'A later version of Niftyreg is required (%s < %s)' warn(msg % (_version, self._min_version)) if required_version is not None: diff --git a/nipype/interfaces/niftyseg/base.py b/nipype/interfaces/niftyseg/base.py new file mode 100644 index 0000000000..80376a57c8 --- /dev/null +++ b/nipype/interfaces/niftyseg/base.py @@ -0,0 +1,44 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: + +""" +The niftyseg module provides classes for interfacing with `niftyseg +`_ command line tools. +These are the base tools for working with niftyseg. +EM Statistical Segmentation tool is found in niftyseg/em.py +Fill lesions tool is found in niftyseg/lesions.py +Mathematical operation tool is found in niftyseg/maths.py +Patch Match tool is found in niftyseg/patchmatch.py +Statistical operation tool is found in niftyseg/stats.py +Label Fusion and CalcTopNcc tools are in niftyseg/steps.py +Examples +-------- +See the docstrings of the individual classes for examples. +""" + +from nipype.interfaces.niftyreg.base import NiftyRegCommand, no_nifty_package +import subprocess +import warnings + + +warn = warnings.warn +warnings.filterwarnings('always', category=UserWarning) + + +class NiftySegCommand(NiftyRegCommand): + """ + Base support interface for NiftySeg commands. + """ + _suffix = '_ns' + _min_version = None + + def __init__(self, **inputs): + super(NiftySegCommand, self).__init__(**inputs) + + def get_version(self): + if no_nifty_package(cmd=self.cmd): + return None + # exec_cmd = ''.join((self.cmd, ' --version')) + exec_cmd = 'seg_EM --version' + # Using seg_EM for version (E.G: seg_stats --version doesn't work) + return subprocess.check_output(exec_cmd, shell=True).strip('\n') diff --git a/nipype/interfaces/niftyseg/em.py b/nipype/interfaces/niftyseg/em.py index e75404f015..102ee4d111 100644 --- a/nipype/interfaces/niftyseg/em.py +++ b/nipype/interfaces/niftyseg/em.py @@ -20,7 +20,8 @@ from ..base import (TraitedSpec, File, traits, CommandLineInputSpec, InputMultiPath) -from ..niftyreg.base import NiftyRegCommand, get_custom_path +from .base import NiftySegCommand +from ..niftyreg.base import get_custom_path class EMInputSpec(CommandLineInputSpec): @@ -109,7 +110,7 @@ class EMOutputSpec(TraitedSpec): out_outlier_file = File(desc='Output outlierness image') -class EM(NiftyRegCommand): +class EM(NiftySegCommand): """Interface for executable seg_EM from NiftySeg platform. seg_EM is a general purpose intensity based image segmentation tool. In diff --git a/nipype/interfaces/niftyseg/label_fusion.py b/nipype/interfaces/niftyseg/label_fusion.py index c89b36818a..e3173d96bd 100644 --- a/nipype/interfaces/niftyseg/label_fusion.py +++ b/nipype/interfaces/niftyseg/label_fusion.py @@ -18,7 +18,8 @@ from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, NipypeInterfaceError) -from ..niftyreg.base import get_custom_path, NiftyRegCommand +from .base import NiftySegCommand +from ..niftyreg.base import get_custom_path from ...utils.filemanip import load_json, save_json, split_filename @@ -111,7 +112,7 @@ class LabelFusionOutput(TraitedSpec): out_file = File(exists=True, desc='image written after calculations') -class LabelFusion(NiftyRegCommand): +class LabelFusion(NiftySegCommand): """Interface for executable seg_LabelFusion from NiftySeg platform using type STEPS as classifier Fusion. @@ -288,7 +289,7 @@ class CalcTopNCCOutputSpec(TraitedSpec): out_files = traits.Any(File(exists=True)) -class CalcTopNCC(NiftyRegCommand): +class CalcTopNCC(NiftySegCommand): """Interface for executable seg_CalcTopNCC from NiftySeg platform. Examples diff --git a/nipype/interfaces/niftyseg/lesions.py b/nipype/interfaces/niftyseg/lesions.py index ff23860257..69d616181b 100644 --- a/nipype/interfaces/niftyseg/lesions.py +++ b/nipype/interfaces/niftyseg/lesions.py @@ -21,7 +21,8 @@ import warnings from ..base import TraitedSpec, File, traits, CommandLineInputSpec -from ..niftyreg.base import NiftyRegCommand, get_custom_path +from .base import NiftySegCommand +from ..niftyreg.base import get_custom_path warn = warnings.warn @@ -93,7 +94,7 @@ class FillLesionsOutputSpec(TraitedSpec): out_file = File(desc="Output segmentation") -class FillLesions(NiftyRegCommand): +class FillLesions(NiftySegCommand): """Interface for executable seg_FillLesions from NiftySeg platform. Fill all the masked lesions with WM intensity average. diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index b890a8a776..650cb63604 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -22,7 +22,8 @@ from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, NipypeInterfaceError) -from ..niftyreg.base import NiftyRegCommand, get_custom_path +from .base import NiftySegCommand +from ..niftyreg.base import get_custom_path from ...utils.filemanip import split_filename @@ -53,7 +54,7 @@ class MathsOutput(TraitedSpec): out_file = File(desc='image written after calculations') -class MathsCommand(NiftyRegCommand): +class MathsCommand(NiftySegCommand): """ Base Command Interface for seg_maths interfaces. diff --git a/nipype/interfaces/niftyseg/patchmatch.py b/nipype/interfaces/niftyseg/patchmatch.py index 35e4cc2639..5a81583dc7 100644 --- a/nipype/interfaces/niftyseg/patchmatch.py +++ b/nipype/interfaces/niftyseg/patchmatch.py @@ -15,7 +15,8 @@ import warnings from ..base import TraitedSpec, File, traits, CommandLineInputSpec -from ..niftyreg.base import NiftyRegCommand, get_custom_path +from .base import NiftySegCommand +from ..niftyreg.base import get_custom_path warn = warnings.warn @@ -80,7 +81,7 @@ class PatchMatchOutputSpec(TraitedSpec): out_file = File(desc="Output segmentation") -class PatchMatch(NiftyRegCommand): +class PatchMatch(NiftySegCommand): """Interface for executable seg_PatchMatch from NiftySeg platform. The database file is a text file and in each line we have a template diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index 2d5d87eb30..2e7cdcde95 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -15,7 +15,8 @@ import numpy as np from ..base import TraitedSpec, File, traits, CommandLineInputSpec -from ..niftyreg.base import NiftyRegCommand, get_custom_path +from .base import NiftySegCommand +from ..niftyreg.base import get_custom_path class StatsInput(CommandLineInputSpec): @@ -45,7 +46,7 @@ class StatsOutput(TraitedSpec): output = traits.Array(desc='Output array from seg_stats') -class StatsCommand(NiftyRegCommand): +class StatsCommand(NiftySegCommand): """ Base Command Interface for seg_stats interfaces. diff --git a/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py b/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py new file mode 100644 index 0000000000..55dc5d9d1d --- /dev/null +++ b/nipype/interfaces/niftyseg/tests/test_auto_NiftySegCommand.py @@ -0,0 +1,23 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..base import NiftySegCommand + + +def test_NiftySegCommand_inputs(): + input_map = dict(args=dict(argstr='%s', + ), + environ=dict(nohash=True, + usedefault=True, + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = NiftySegCommand.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + diff --git a/nipype/interfaces/niftyseg/tests/test_em_interfaces.py b/nipype/interfaces/niftyseg/tests/test_em_interfaces.py index 19da48e81d..810a782b63 100644 --- a/nipype/interfaces/niftyseg/tests/test_em_interfaces.py +++ b/nipype/interfaces/niftyseg/tests/test_em_interfaces.py @@ -3,8 +3,8 @@ import pytest -from nipype.interfaces.niftyreg import no_nifty_package -from nipype.interfaces.niftyseg import get_custom_path, EM +from nipype.interfaces.niftyreg import no_nifty_package, get_custom_path +from nipype.interfaces.niftyseg import EM from nipype.testing import example_data @@ -16,7 +16,8 @@ def test_seg_em(): seg_em = EM() # Check if the command is properly defined - assert seg_em.cmd == get_custom_path('seg_EM') + cmd = get_custom_path('seg_EM', env_dir='NIFTYSEGDIR') + assert seg_em.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -30,7 +31,7 @@ def test_seg_em(): cmd_tmp = '{cmd} -in {in_file} -nopriors 4 -bc_out {bc_out} -out \ {out_file} -out_outlier {out_outlier}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_EM'), + cmd=cmd, in_file=in_file, out_file='im1_em.nii.gz', bc_out='im1_bc_em.nii.gz', diff --git a/nipype/interfaces/niftyseg/tests/test_label_fusion.py b/nipype/interfaces/niftyseg/tests/test_label_fusion.py index 35f13a3876..f34fc9149f 100644 --- a/nipype/interfaces/niftyseg/tests/test_label_fusion.py +++ b/nipype/interfaces/niftyseg/tests/test_label_fusion.py @@ -3,8 +3,8 @@ import pytest -from nipype.interfaces.niftyreg import no_nifty_package -from nipype.interfaces.niftyseg import get_custom_path, LabelFusion, CalcTopNCC +from nipype.interfaces.niftyreg import no_nifty_package, get_custom_path +from nipype.interfaces.niftyseg import LabelFusion, CalcTopNCC from nipype.testing import example_data @@ -16,7 +16,8 @@ def test_seg_lab_fusion(): steps = LabelFusion() # Check if the command is properly defined - assert steps.cmd == get_custom_path('seg_LabFusion') + cmd = get_custom_path('seg_LabFusion', env_dir='NIFTYSEGDIR') + assert steps.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -36,7 +37,7 @@ def test_seg_lab_fusion(): cmd_tmp = '{cmd} -in {in_file} -STEPS 2.000000 2 {file_to_seg} \ {template_file} -out {out_file}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_LabFusion'), + cmd=cmd, in_file=in_file, file_to_seg=file_to_seg, template_file=template_file, @@ -57,7 +58,7 @@ def test_seg_lab_fusion(): cmd_tmp = '{cmd} -in {in_file} -STAPLE -ALL -out {out_file}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_LabFusion'), + cmd=cmd, in_file=in_file, file_to_seg=file_to_seg, template_file=template_file, @@ -79,7 +80,7 @@ def test_seg_lab_fusion(): cmd_tmp = '{cmd} -in {in_file} -MV -ROINCC 2 2 {file_to_seg} \ {template_file} -out {out_file}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_LabFusion'), + cmd=cmd, in_file=in_file, file_to_seg=file_to_seg, template_file=template_file, @@ -97,7 +98,8 @@ def test_seg_calctopncc(): calctopncc = CalcTopNCC() # Check if the command is properly defined - assert calctopncc.cmd == get_custom_path('seg_CalcTopNCC') + cmd = get_custom_path('seg_CalcTopNCC', env_dir='NIFTYSEGDIR') + assert calctopncc.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -114,7 +116,7 @@ def test_seg_calctopncc(): cmd_tmp = '{cmd} -target {in_file} -templates 2 {file1} {file2} -n 1' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_CalcTopNCC'), + cmd=cmd, in_file=in_file, file1=file1, file2=file2, diff --git a/nipype/interfaces/niftyseg/tests/test_lesions.py b/nipype/interfaces/niftyseg/tests/test_lesions.py index fa7307c085..55250bde92 100644 --- a/nipype/interfaces/niftyseg/tests/test_lesions.py +++ b/nipype/interfaces/niftyseg/tests/test_lesions.py @@ -3,8 +3,8 @@ import pytest -from nipype.interfaces.niftyreg import no_nifty_package -from nipype.interfaces.niftyseg import get_custom_path, FillLesions +from nipype.interfaces.niftyreg import no_nifty_package, get_custom_path +from nipype.interfaces.niftyseg import FillLesions from nipype.testing import example_data @@ -16,7 +16,8 @@ def test_seg_filllesions(): seg_fill = FillLesions() # Check if the command is properly defined - assert seg_fill.cmd == get_custom_path('seg_FillLesions') + cmd = get_custom_path('seg_FillLesions', env_dir='NIFTYSEGDIR') + assert seg_fill.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -29,7 +30,7 @@ def test_seg_filllesions(): seg_fill.inputs.lesion_mask = lesion_mask expected_cmd = '{cmd} -i {in_file} -l {lesion_mask} -o {out_file}'.format( - cmd=get_custom_path('seg_FillLesions'), + cmd=cmd, in_file=in_file, lesion_mask=lesion_mask, out_file='im1_lesions_filled.nii.gz', diff --git a/nipype/interfaces/niftyseg/tests/test_maths.py b/nipype/interfaces/niftyseg/tests/test_maths.py index 640e53aa9e..307adb503d 100644 --- a/nipype/interfaces/niftyseg/tests/test_maths.py +++ b/nipype/interfaces/niftyseg/tests/test_maths.py @@ -3,9 +3,8 @@ import pytest -from nipype.interfaces.niftyreg import no_nifty_package -from nipype.interfaces.niftyseg import (get_custom_path, - UnaryMaths, BinaryMaths, +from nipype.interfaces.niftyreg import no_nifty_package, get_custom_path +from nipype.interfaces.niftyseg import (UnaryMaths, BinaryMaths, BinaryMathsInteger, TupleMaths, Merge) from nipype.testing import example_data @@ -19,7 +18,8 @@ def test_unary_maths(): unarym = UnaryMaths() # Check if the command is properly defined - assert unarym.cmd == get_custom_path('seg_maths') + cmd = get_custom_path('seg_maths', env_dir='NIFTYSEGDIR') + assert unarym.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -32,7 +32,7 @@ def test_unary_maths(): unarym.inputs.output_datatype = 'float' expected_cmd = '{cmd} {in_file} -otsu -odt float {out_file}'.format( - cmd=get_custom_path('seg_maths'), + cmd=cmd, in_file=in_file, out_file='im1_otsu.nii') @@ -47,7 +47,8 @@ def test_binary_maths(): binarym = BinaryMaths() # Check if the command is properly defined - assert binarym.cmd == get_custom_path('seg_maths') + cmd = get_custom_path('seg_maths', env_dir='NIFTYSEGDIR') + assert binarym.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -62,7 +63,7 @@ def test_binary_maths(): cmd_tmp = '{cmd} {in_file} -sub 2.00000000 -odt float {out_file}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_maths'), + cmd=cmd, in_file=in_file, out_file='im1_sub.nii') @@ -77,7 +78,8 @@ def test_int_binary_maths(): ibinarym = BinaryMathsInteger() # Check if the command is properly defined - assert ibinarym.cmd == get_custom_path('seg_maths') + cmd = get_custom_path('seg_maths', env_dir='NIFTYSEGDIR') + assert ibinarym.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -91,7 +93,7 @@ def test_int_binary_maths(): ibinarym.inputs.output_datatype = 'float' expected_cmd = '{cmd} {in_file} -dil 2 -odt float {out_file}'.format( - cmd=get_custom_path('seg_maths'), + cmd=cmd, in_file=in_file, out_file='im1_dil.nii') @@ -106,7 +108,8 @@ def test_tuple_maths(): tuplem = TupleMaths() # Check if the command is properly defined - assert tuplem.cmd == get_custom_path('seg_maths') + cmd = get_custom_path('seg_maths', env_dir='NIFTYSEGDIR') + assert tuplem.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -123,7 +126,7 @@ def test_tuple_maths(): cmd_tmp = '{cmd} {in_file} -lncc {op} 2.00000000 -odt float {out_file}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_maths'), + cmd=cmd, in_file=in_file, op=op_file, out_file='im1_lncc.nii') @@ -139,7 +142,8 @@ def test_merge(): merge = Merge() # Check if the command is properly defined - assert merge.cmd == get_custom_path('seg_maths') + cmd = get_custom_path('seg_maths', env_dir='NIFTYSEGDIR') + assert merge.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -156,7 +160,7 @@ def test_merge(): cmd_tmp = '{cmd} {in_file} -merge 2 2 {f1} {f2} -odt float {out_file}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_maths'), + cmd=cmd, in_file=in_file, f1=file1, f2=file2, diff --git a/nipype/interfaces/niftyseg/tests/test_patchmatch.py b/nipype/interfaces/niftyseg/tests/test_patchmatch.py index 8e61599cec..b88552fb0d 100644 --- a/nipype/interfaces/niftyseg/tests/test_patchmatch.py +++ b/nipype/interfaces/niftyseg/tests/test_patchmatch.py @@ -3,8 +3,8 @@ import pytest -from nipype.interfaces.niftyreg import no_nifty_package -from nipype.interfaces.niftyseg import get_custom_path, PatchMatch +from nipype.interfaces.niftyreg import no_nifty_package, get_custom_path +from nipype.interfaces.niftyseg import PatchMatch from nipype.testing import example_data @@ -16,7 +16,8 @@ def test_seg_patchmatch(): seg_patchmatch = PatchMatch() # Check if the command is properly defined - assert seg_patchmatch.cmd == get_custom_path('seg_PatchMatch') + cmd = get_custom_path('seg_PatchMatch', env_dir='NIFTYSEGDIR') + assert seg_patchmatch.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -32,7 +33,7 @@ def test_seg_patchmatch(): cmd_tmp = '{cmd} -i {in_file} -m {mask_file} -db {db} -o {out_file}' expected_cmd = cmd_tmp.format( - cmd=get_custom_path('seg_PatchMatch'), + cmd=cmd, in_file=in_file, mask_file=mask_file, db=db_file, diff --git a/nipype/interfaces/niftyseg/tests/test_stats.py b/nipype/interfaces/niftyseg/tests/test_stats.py index a31f79c416..ae3cfbfc6e 100644 --- a/nipype/interfaces/niftyseg/tests/test_stats.py +++ b/nipype/interfaces/niftyseg/tests/test_stats.py @@ -3,9 +3,8 @@ import pytest -from nipype.interfaces.niftyreg import no_nifty_package -from nipype.interfaces.niftyseg import (get_custom_path, UnaryStats, - BinaryStats) +from nipype.interfaces.niftyreg import no_nifty_package, get_custom_path +from nipype.interfaces.niftyseg import UnaryStats, BinaryStats from nipype.testing import example_data @@ -17,7 +16,8 @@ def test_unary_stats(): unarys = UnaryStats() # Check if the command is properly defined - assert unarys.cmd == get_custom_path('seg_stats') + cmd = get_custom_path('seg_stats', env_dir='NIFTYSEGDIR') + assert unarys.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -29,7 +29,7 @@ def test_unary_stats(): unarys.inputs.operation = 'a' expected_cmd = '{cmd} {in_file} -a'.format( - cmd=get_custom_path('seg_stats'), + cmd=cmd, in_file=in_file) assert unarys.cmdline == expected_cmd @@ -43,7 +43,8 @@ def test_binary_stats(): binarys = BinaryStats() # Check if the command is properly defined - assert binarys.cmd == get_custom_path('seg_stats') + cmd = get_custom_path('seg_stats', env_dir='NIFTYSEGDIR') + assert binarys.cmd == cmd # test raising error with mandatory args absent with pytest.raises(ValueError): @@ -56,7 +57,7 @@ def test_binary_stats(): binarys.inputs.operation = 'sa' expected_cmd = '{cmd} {in_file} -sa 2.00000000'.format( - cmd=get_custom_path('seg_stats'), + cmd=cmd, in_file=in_file) assert binarys.cmdline == expected_cmd From cf30734f890972672c37ca54e78c53ec1c868315 Mon Sep 17 00:00:00 2001 From: byvernault Date: Tue, 2 May 2017 16:37:26 +0100 Subject: [PATCH 15/17] adding more tests in docstring for seg_maths and seg_stats --- nipype/interfaces/niftyseg/maths.py | 171 +++++++++++++++++++++++----- nipype/interfaces/niftyseg/stats.py | 61 +++++++--- nipype/testing/data/output.csv | 0 3 files changed, 186 insertions(+), 46 deletions(-) create mode 100644 nipype/testing/data/output.csv diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 650cb63604..0c6d48ac21 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -139,13 +139,41 @@ class UnaryMaths(MathsCommand): Examples -------- + >>> import copy >>> from nipype.interfaces import niftyseg - >>> node = niftyseg.UnaryMaths() - >>> node.inputs.in_file = 'im1.nii' - >>> node.inputs.operation = 'sqrt' - >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE + >>> unary = niftyseg.UnaryMaths() + >>> unary.inputs.output_datatype = 'float' + >>> unary.inputs.in_file = 'im1.nii' + >>> # Test sqrt operation + >>> unary_sqrt = copy.deepcopy(unary) + >>> unary_sqrt.inputs.operation = 'sqrt' + >>> unary_sqrt.cmdline # doctest: +ALLOW_UNICODE 'seg_maths im1.nii -sqrt -odt float im1_sqrt.nii' + >>> unary_sqrt.run() # doctest: +SKIP + >>> # Test sqrt operation + >>> unary_abs = copy.deepcopy(unary) + >>> unary_abs.inputs.operation = 'abs' + >>> unary_abs.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -abs -odt float im1_abs.nii' + >>> unary_abs.run() # doctest: +SKIP + >>> # Test bin operation + >>> unary_bin = copy.deepcopy(unary) + >>> unary_bin.inputs.operation = 'bin' + >>> unary_bin.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -bin -odt float im1_bin.nii' + >>> unary_bin.run() # doctest: +SKIP + >>> # Test otsu operation + >>> unary_otsu = copy.deepcopy(unary) + >>> unary_otsu.inputs.operation = 'otsu' + >>> unary_otsu.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -otsu -odt float im1_otsu.nii' + >>> unary_otsu.run() # doctest: +SKIP + >>> # Test isnan operation + >>> unary_isnan = copy.deepcopy(unary) + >>> unary_isnan.inputs.operation = 'isnan' + >>> unary_isnan.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -isnan -odt float im1_isnan.nii' + >>> unary_isnan.run() # doctest: +SKIP """ input_spec = UnaryMathsInput @@ -226,28 +254,71 @@ class BinaryMaths(MathsCommand): Examples -------- + >>> import copy >>> from nipype.interfaces import niftyseg - >>> node = niftyseg.BinaryMaths() - >>> node.inputs.in_file = 'im1.nii' - >>> node.inputs.operation = 'sub' - >>> node.inputs.operand_file = 'im2.nii' - >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE + >>> binary = niftyseg.BinaryMaths() + >>> binary.inputs.in_file = 'im1.nii' + >>> binary.inputs.output_datatype = 'float' + >>> # Test sub operation + >>> binary_sub = copy.deepcopy(binary) + >>> binary_sub.inputs.operation = 'sub' + >>> binary_sub.inputs.operand_file = 'im2.nii' + >>> binary_sub.cmdline # doctest: +ALLOW_UNICODE 'seg_maths im1.nii -sub im2.nii -odt float im1_sub.nii' + >>> binary_sub.run() # doctest: +SKIP + >>> # Test mul operation + >>> binary_mul = copy.deepcopy(binary) + >>> binary_mul.inputs.operation = 'mul' + >>> binary_mul.inputs.operand_value = 2.0 + >>> binary_mul.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -mul 2.0 -odt float im1_mul.nii' + >>> binary_mul.run() # doctest: +SKIP + >>> # Test llsnorm operation + >>> binary_llsnorm = copy.deepcopy(binary) + >>> binary_llsnorm.inputs.operation = 'llsnorm' + >>> binary_llsnorm.inputs.operand_file = 'im2.nii' + >>> binary_llsnorm.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -llsnorm im2.nii -odt float im1_llsnorm.nii' + >>> binary_llsnorm.run() # doctest: +SKIP + >>> # Test splitinter operation + >>> binary_splitinter = copy.deepcopy(binary) + >>> binary_splitinter.inputs.operation = 'llsnorm' + >>> binary_splitinter.inputs.operand_str = 'z' + >>> binary_splitinter.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -splitinter z -odt float im1_splitinter.nii' + >>> binary_splitinter.run() # doctest: +SKIP """ input_spec = BinaryMathsInput def _format_arg(self, opt, spec, val): """Convert input to appropriate format for seg_maths.""" - if opt == 'operand_value' and float(val) == 0.0: - return '0' - if opt == 'operand_str' and self.inputs.operation != 'splitinter': err = 'operand_str set but with an operation different than \ "splitinter"' raise NipypeInterfaceError(err) + if opt == 'operation': + # Only float + if val in ['pow', 'thr', 'uthr', 'smo', 'edge', 'sobel3', 'sobel5', + 'smol']: + if not isdefined(self.inputs.operand_value): + err = 'operand_value not set for {0}.'.format(val) + raise NipypeInterfaceError(err) + # only files + elif val in ['min', 'llsnorm', 'masknan', 'hdr_copy']: + if not isdefined(self.inputs.operand_file): + err = 'operand_file not set for {0}.'.format(val) + raise NipypeInterfaceError(err) + # splitinter: + elif val == 'splitinter': + if not isdefined(self.inputs.operand_str): + err = 'operand_str not set for splitinter.' + raise NipypeInterfaceError(err) + + if opt == 'operand_value' and float(val) == 0.0: + return '0' + return super(BinaryMaths, self)._format_arg(opt, spec, val) def _overload_extension(self, value, name=None): @@ -293,14 +364,32 @@ class BinaryMathsInteger(MathsCommand): Examples -------- + >>> import copy >>> from nipype.interfaces.niftyseg import BinaryMathsInteger - >>> node = BinaryMathsInteger() - >>> node.inputs.in_file = 'im1.nii' - >>> node.inputs.operation = 'dil' - >>> node.inputs.operand_value = 2 - >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE + >>> binaryi = BinaryMathsInteger() + >>> binaryi.inputs.in_file = 'im1.nii' + >>> binaryi.inputs.output_datatype = 'float' + >>> # Test dil operation + >>> binaryi_dil = copy.deepcopy(binaryi) + >>> binaryi_dil.inputs.operation = 'dil' + >>> binaryi_dil.inputs.operand_value = 2 + >>> binaryi_dil.cmdline # doctest: +ALLOW_UNICODE 'seg_maths im1.nii -dil 2 -odt float im1_dil.nii' + >>> binaryi_dil.run() # doctest: +SKIP + >>> # Test dil operation + >>> binaryi_ero = copy.deepcopy(binaryi) + >>> binaryi_ero.inputs.operation = 'ero' + >>> binaryi_ero.inputs.operand_value = 1 + >>> binaryi_ero.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -ero 1 -odt float im1_ero.nii' + >>> binaryi_ero.run() # doctest: +SKIP + >>> # Test pad operation + >>> binaryi_pad = copy.deepcopy(binaryi) + >>> binaryi_pad.inputs.operation = 'pad' + >>> binaryi_pad.inputs.operand_value = 4 + >>> binaryi_pad.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -pad 4 -odt float im1_pad.nii' + >>> binaryi_pad.run() # doctest: +SKIP """ input_spec = BinaryMathsInputInteger @@ -308,7 +397,7 @@ class BinaryMathsInteger(MathsCommand): class TupleMathsInput(MathsInput): """Input Spec for seg_maths Tuple operations.""" - operation = traits.Enum('lncc', 'lssd', 'lltsnorm', 'qlsnorm', + operation = traits.Enum('lncc', 'lssd', 'lltsnorm', mandatory=True, argstr='-%s', position=4, @@ -354,8 +443,6 @@ class TupleMaths(MathsCommand): on a kernel with -lltsnorm Linear LTS normalisation assuming percent outliers - -qlsnorm LS normalisation of - between current and For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg For Documentation, see: @@ -363,16 +450,38 @@ class TupleMaths(MathsCommand): Examples -------- + >>> import copy >>> from nipype.interfaces import niftyseg - >>> node = niftyseg.TupleMaths() - >>> node.inputs.in_file = 'im1.nii' - >>> node.inputs.operation = 'lncc' - >>> node.inputs.operand_file1 = 'im2.nii' - >>> node.inputs.operand_value2 = 2.0 - >>> node.inputs.output_datatype = 'float' - >>> node.cmdline # doctest: +ALLOW_UNICODE + >>> tuple = niftyseg.TupleMaths() + >>> tuple.inputs.in_file = 'im1.nii' + >>> tuple.inputs.output_datatype = 'float' + + >>> # Test lncc operation + >>> tuple_lncc = copy.deepcopy(binary) + >>> tuple_lncc.inputs.operation = 'lncc' + >>> tuple_lncc.inputs.operand_file1 = 'im2.nii' + >>> tuple_lncc.inputs.operand_value2 = 2.0 + >>> tuple_lncc.cmdline # doctest: +ALLOW_UNICODE 'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float im1_lncc.nii' - + >>> tuple_lncc.run() # doctest: +SKIP + + >>> # Test lssd operation + >>> tuple_lssd = copy.deepcopy(binary) + >>> tuple_lssd.inputs.operation = 'lssd' + >>> tuple_lssd.inputs.operand_file1 = 'im2.nii' + >>> tuple_lssd.inputs.operand_value2 = 1.0 + >>> tuple_lssd.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -lssd im2.nii 1.00000000 -odt float im1_lssd.nii' + >>> tuple_lssd.run() # doctest: +SKIP + + >>> # Test lltsnorm operation + >>> tuple_lltsnorm = copy.deepcopy(binary) + >>> tuple_lltsnorm.inputs.operation = 'lltsnorm' + >>> tuple_lltsnorm.inputs.operand_file1 = 'im2.nii' + >>> tuple_lltsnorm.inputs.operand_value2 = 0.01 + >>> tuple_lltsnorm.cmdline # doctest: +ALLOW_UNICODE + 'seg_maths im1.nii -lltsnorm im2.nii 0.01 -odt float im1_lltsnorm.nii' + >>> tuple_lltsnorm.run() # doctest: +SKIP """ input_spec = TupleMathsInput diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index 2e7cdcde95..e9193f2666 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -130,21 +130,34 @@ class UnaryStats(StatsCommand): -xdim | Output the voxel dimention in the x direction. | Replace x with y/z for other directions. - Note: All NaN or Inf are ignored for all stats. - The -m and -t options can be used in conjusction. - For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg For Documentation, see: http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation Examples -------- + >>> import copy >>> from nipype.interfaces import niftyseg - >>> node = niftyseg.UnaryStats() - >>> node.inputs.in_file = 'im1.nii' - >>> node.inputs.operation = 'v' - >>> node.cmdline # doctest: +ALLOW_UNICODE + >>> unary = niftyseg.UnaryStats() + >>> unary.inputs.in_file = 'im1.nii' + >>> # Test v operation + >>> unary_v = copy.deepcopy(unary) + >>> unary_v.inputs.operation = 'v' + >>> unary_v.cmdline # doctest: +ALLOW_UNICODE 'seg_stats im1.nii -v' + >>> unary_v.run() # doctest: +SKIP + >>> # Test vl operation + >>> unary_vl = copy.deepcopy(unary) + >>> unary_vl.inputs.operation = 'vl' + >>> unary_vl.cmdline # doctest: +ALLOW_UNICODE + 'seg_stats im1.nii -vl' + >>> unary_vl.run() # doctest: +SKIP + >>> # Test x operation + >>> unary_x = copy.deepcopy(unary) + >>> unary_x.inputs.operation = 'x' + >>> unary_x.cmdline # doctest: +ALLOW_UNICODE + 'seg_stats im1.nii -x' + >>> unary_x.run() # doctest: +SKIP """ input_spec = UnaryStatsInput @@ -193,22 +206,40 @@ class BinaryStats(StatsCommand): -Vl | Volume of each integer label . Save to file. -Nl | Count of each label . Save to file. - Note: All NaN or Inf are ignored for all stats. - The -m and -t options can be used in conjusction. - For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg For Documentation, see: http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation Examples -------- + >>> import copy >>> from nipype.interfaces import niftyseg - >>> node = niftyseg.BinaryStats() - >>> node.inputs.in_file = 'im1.nii' - >>> node.inputs.operation = 'sa' - >>> node.inputs.operand_value = 2.0 - >>> node.cmdline # doctest: +ALLOW_UNICODE + >>> binary = niftyseg.BinaryStats() + >>> binary.inputs.in_file = 'im1.nii' + >>> # Test sa operation + >>> binary_sa = copy.deepcopy(binary) + >>> binary_sa = niftyseg.BinaryStats() + >>> binary_sa.inputs.operation = 'sa' + >>> binary_sa.inputs.operand_value = 2.0 + >>> binary_sa.cmdline # doctest: +ALLOW_UNICODE 'seg_stats im1.nii -sa 2.00000000' + >>> binary_sa.run() # doctest: +SKIP + >>> # Test ncc operation + >>> binary_ncc = copy.deepcopy(binary) + >>> binary_ncc = niftyseg.BinaryStats() + >>> binary_ncc.inputs.operation = 'ncc' + >>> binary_ncc.inputs.operand_file = 'im2.nii' + >>> binary_ncc.cmdline # doctest: +ALLOW_UNICODE + 'seg_stats im1.nii -ncc im2.nii' + >>> binary_ncc.run() # doctest: +SKIP + >>> # Test Nl operation + >>> binary_nl = copy.deepcopy(binary) + >>> binary_nl = niftyseg.BinaryStats() + >>> binary_nl.inputs.operation = 'Nl' + >>> binary_nl.inputs.operand_file = 'output.csv' + >>> binary_nl.cmdline # doctest: +ALLOW_UNICODE + 'seg_stats im1.nii -Nl output.csv' + >>> binary_nl.run() # doctest: +SKIP """ input_spec = BinaryStatsInput diff --git a/nipype/testing/data/output.csv b/nipype/testing/data/output.csv new file mode 100644 index 0000000000..e69de29bb2 From 617eb483508e8d5d18364340840e0567ebe39fa1 Mon Sep 17 00:00:00 2001 From: byvernault Date: Wed, 3 May 2017 10:12:11 +0100 Subject: [PATCH 16/17] fixing doctest --- nipype/interfaces/niftyseg/maths.py | 8 ++++---- nipype/interfaces/niftyseg/stats.py | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 0c6d48ac21..5acad69395 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -271,7 +271,7 @@ class BinaryMaths(MathsCommand): >>> binary_mul.inputs.operation = 'mul' >>> binary_mul.inputs.operand_value = 2.0 >>> binary_mul.cmdline # doctest: +ALLOW_UNICODE - 'seg_maths im1.nii -mul 2.0 -odt float im1_mul.nii' + 'seg_maths im1.nii -mul 2.00000000 -odt float im1_mul.nii' >>> binary_mul.run() # doctest: +SKIP >>> # Test llsnorm operation >>> binary_llsnorm = copy.deepcopy(binary) @@ -457,7 +457,7 @@ class TupleMaths(MathsCommand): >>> tuple.inputs.output_datatype = 'float' >>> # Test lncc operation - >>> tuple_lncc = copy.deepcopy(binary) + >>> tuple_lncc = copy.deepcopy(tuple) >>> tuple_lncc.inputs.operation = 'lncc' >>> tuple_lncc.inputs.operand_file1 = 'im2.nii' >>> tuple_lncc.inputs.operand_value2 = 2.0 @@ -466,7 +466,7 @@ class TupleMaths(MathsCommand): >>> tuple_lncc.run() # doctest: +SKIP >>> # Test lssd operation - >>> tuple_lssd = copy.deepcopy(binary) + >>> tuple_lssd = copy.deepcopy(tuple) >>> tuple_lssd.inputs.operation = 'lssd' >>> tuple_lssd.inputs.operand_file1 = 'im2.nii' >>> tuple_lssd.inputs.operand_value2 = 1.0 @@ -475,7 +475,7 @@ class TupleMaths(MathsCommand): >>> tuple_lssd.run() # doctest: +SKIP >>> # Test lltsnorm operation - >>> tuple_lltsnorm = copy.deepcopy(binary) + >>> tuple_lltsnorm = copy.deepcopy(tuple) >>> tuple_lltsnorm.inputs.operation = 'lltsnorm' >>> tuple_lltsnorm.inputs.operand_file1 = 'im2.nii' >>> tuple_lltsnorm.inputs.operand_value2 = 0.01 diff --git a/nipype/interfaces/niftyseg/stats.py b/nipype/interfaces/niftyseg/stats.py index e9193f2666..b587392d29 100644 --- a/nipype/interfaces/niftyseg/stats.py +++ b/nipype/interfaces/niftyseg/stats.py @@ -218,7 +218,6 @@ class BinaryStats(StatsCommand): >>> binary.inputs.in_file = 'im1.nii' >>> # Test sa operation >>> binary_sa = copy.deepcopy(binary) - >>> binary_sa = niftyseg.BinaryStats() >>> binary_sa.inputs.operation = 'sa' >>> binary_sa.inputs.operand_value = 2.0 >>> binary_sa.cmdline # doctest: +ALLOW_UNICODE @@ -226,7 +225,6 @@ class BinaryStats(StatsCommand): >>> binary_sa.run() # doctest: +SKIP >>> # Test ncc operation >>> binary_ncc = copy.deepcopy(binary) - >>> binary_ncc = niftyseg.BinaryStats() >>> binary_ncc.inputs.operation = 'ncc' >>> binary_ncc.inputs.operand_file = 'im2.nii' >>> binary_ncc.cmdline # doctest: +ALLOW_UNICODE @@ -234,7 +232,6 @@ class BinaryStats(StatsCommand): >>> binary_ncc.run() # doctest: +SKIP >>> # Test Nl operation >>> binary_nl = copy.deepcopy(binary) - >>> binary_nl = niftyseg.BinaryStats() >>> binary_nl.inputs.operation = 'Nl' >>> binary_nl.inputs.operand_file = 'output.csv' >>> binary_nl.cmdline # doctest: +ALLOW_UNICODE From 3fb818fc0cc51314477c293cbc04998c37b32301 Mon Sep 17 00:00:00 2001 From: byvernault Date: Wed, 3 May 2017 11:04:37 +0100 Subject: [PATCH 17/17] few more errors in doctest to fix --- nipype/interfaces/niftyseg/maths.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/niftyseg/maths.py b/nipype/interfaces/niftyseg/maths.py index 5acad69395..852fe699ce 100644 --- a/nipype/interfaces/niftyseg/maths.py +++ b/nipype/interfaces/niftyseg/maths.py @@ -282,7 +282,7 @@ class BinaryMaths(MathsCommand): >>> binary_llsnorm.run() # doctest: +SKIP >>> # Test splitinter operation >>> binary_splitinter = copy.deepcopy(binary) - >>> binary_splitinter.inputs.operation = 'llsnorm' + >>> binary_splitinter.inputs.operation = 'splitinter' >>> binary_splitinter.inputs.operand_str = 'z' >>> binary_splitinter.cmdline # doctest: +ALLOW_UNICODE 'seg_maths im1.nii -splitinter z -odt float im1_splitinter.nii' @@ -480,7 +480,8 @@ class TupleMaths(MathsCommand): >>> tuple_lltsnorm.inputs.operand_file1 = 'im2.nii' >>> tuple_lltsnorm.inputs.operand_value2 = 0.01 >>> tuple_lltsnorm.cmdline # doctest: +ALLOW_UNICODE - 'seg_maths im1.nii -lltsnorm im2.nii 0.01 -odt float im1_lltsnorm.nii' + 'seg_maths im1.nii -lltsnorm im2.nii 0.01000000 -odt float \ +im1_lltsnorm.nii' >>> tuple_lltsnorm.run() # doctest: +SKIP """ input_spec = TupleMathsInput