|
| 1 | +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- |
| 2 | +# vi: set ft=python sts=4 ts=4 sw=4 et: |
| 3 | + |
| 4 | +""" |
| 5 | +Nipype interface for seg_EM. |
| 6 | +
|
| 7 | +The em module provides higher-level interfaces to some of the operations |
| 8 | +that can be performed with the seg_em command-line program. |
| 9 | +
|
| 10 | +Examples |
| 11 | +-------- |
| 12 | +See the docstrings of the individual classes for examples. |
| 13 | +""" |
| 14 | + |
| 15 | +import os |
| 16 | + |
| 17 | +from ..base import (TraitedSpec, File, traits, isdefined, CommandLineInputSpec, |
| 18 | + InputMultiPath) |
| 19 | +from .base import NiftySegCommand, get_custom_path |
| 20 | + |
| 21 | + |
| 22 | +class EMInputSpec(CommandLineInputSpec): |
| 23 | + """Input Spec for EM.""" |
| 24 | + in_file = File(argstr='-in %s', |
| 25 | + exists=True, |
| 26 | + mandatory=True, |
| 27 | + desc='Input image to segment', |
| 28 | + position=4) |
| 29 | + |
| 30 | + mask_file = File(argstr='-mask %s', |
| 31 | + exists=True, |
| 32 | + desc='Filename of the ROI for label fusion') |
| 33 | + |
| 34 | + # Priors |
| 35 | + no_prior = traits.Int(argstr='-nopriors %s', |
| 36 | + mandatory=True, |
| 37 | + desc='Number of classes to use without prior', |
| 38 | + xor=['prior_4D', 'priors']) |
| 39 | + |
| 40 | + prior_4D = File(argstr='-prior4D %s', |
| 41 | + exists=True, |
| 42 | + mandatory=True, |
| 43 | + desc='4D file containing the priors', |
| 44 | + xor=['no_prior', 'priors']) |
| 45 | + |
| 46 | + desc = 'List of priors filepaths.' |
| 47 | + priors = InputMultiPath(argstr='%s', |
| 48 | + mandatory=True, |
| 49 | + desc=desc, |
| 50 | + xor=['no_prior', 'prior_4D']) |
| 51 | + |
| 52 | + # iterations |
| 53 | + max_iter = traits.Int(argstr='-max_iter %s', default=100, |
| 54 | + desc='Maximum number of iterations') |
| 55 | + |
| 56 | + min_iter = traits.Int(argstr='-min_iter %s', default=0, |
| 57 | + desc='Minimun number of iterations') |
| 58 | + |
| 59 | + # other options |
| 60 | + bc_order_val = traits.Int(argstr='-bc_order %s', default=3, |
| 61 | + desc='Polynomial order for the bias field') |
| 62 | + |
| 63 | + mrf_beta_val = traits.Float(argstr='-mrf_beta %s', |
| 64 | + desc='Weight of the Markov Random Field') |
| 65 | + |
| 66 | + desc = 'Bias field correction will run only if the ratio of improvement \ |
| 67 | +is below bc_thresh. (default=0 [OFF])' |
| 68 | + bc_thresh_val = traits.Float(argstr='-bc_thresh %s', default=0, desc=desc) |
| 69 | + |
| 70 | + desc = 'Amount of regularization over the diagonal of the covariance \ |
| 71 | +matrix [above 1]' |
| 72 | + reg_val = traits.Float(argstr='-reg %s', desc=desc) |
| 73 | + |
| 74 | + desc = 'Outlier detection as in (Van Leemput TMI 2003). <fl1> is the \ |
| 75 | +Mahalanobis threshold [recommended between 3 and 7] <fl2> is a convergence \ |
| 76 | +ratio below which the outlier detection is going to be done [recommended 0.01]' |
| 77 | + outlier_val = traits.Tuple(traits.Float(), traits.Float(), |
| 78 | + argstr='-outlier %s %s', |
| 79 | + desc=desc) |
| 80 | + |
| 81 | + desc = 'Relax Priors [relaxation factor: 0<rf<1 (recommended=0.5), \ |
| 82 | +gaussian regularization: gstd>0 (recommended=2.0)] /only 3D/' |
| 83 | + relax_priors = traits.Tuple(traits.Float(), traits.Float(), |
| 84 | + argstr='-rf %s %s', |
| 85 | + desc=desc) |
| 86 | + |
| 87 | + # outputs |
| 88 | + out_file = File(argstr='-out %s', |
| 89 | + genfile=True, |
| 90 | + desc='Output segmentation') |
| 91 | + out_bc_file = File(argstr='-bc_out %s', |
| 92 | + genfile=True, |
| 93 | + desc='Output bias corrected image') |
| 94 | + out_outlier_file = File(argstr='-out_outlier %s', |
| 95 | + genfile=True, |
| 96 | + desc='Output outlierness image') |
| 97 | + |
| 98 | + |
| 99 | +class EMOutputSpec(TraitedSpec): |
| 100 | + """Output Spec for EM.""" |
| 101 | + out_file = File(desc="Output segmentation") |
| 102 | + out_bc_file = File(desc="Output bias corrected image") |
| 103 | + out_outlier_file = File(desc='Output outlierness image') |
| 104 | + |
| 105 | + |
| 106 | +class EM(NiftySegCommand): |
| 107 | + """Interface for executable seg_EM from NiftySeg platform. |
| 108 | +
|
| 109 | + seg_EM is a general purpose intensity based image segmentation tool. In |
| 110 | + it's simplest form, it takes in one 2D or 3D image and segments it in n |
| 111 | + classes. |
| 112 | +
|
| 113 | + For source code, see http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg |
| 114 | + For Documentation, see: |
| 115 | + http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation |
| 116 | +
|
| 117 | + Examples |
| 118 | + -------- |
| 119 | + >>> from nipype.interfaces.niftyseg import EM |
| 120 | + >>> node = EM() |
| 121 | + >>> node.inputs.in_file = 'im1.nii' # doctest: +SKIP |
| 122 | + >>> node.inputs.no_prior = 4 |
| 123 | + >>> node.cmdline # doctest: +SKIP |
| 124 | + 'seg_EM -in im1.nii -nopriors 4 -bc_out im1_bc_em.nii -out im1_em.nii \ |
| 125 | +-out_outlier im1_outlier_em.nii' |
| 126 | +
|
| 127 | + """ |
| 128 | + _cmd = get_custom_path('seg_EM') |
| 129 | + _suffix = '_em' |
| 130 | + input_spec = EMInputSpec |
| 131 | + output_spec = EMOutputSpec |
| 132 | + |
| 133 | + def _format_arg(self, opt, spec, val): |
| 134 | + """Convert input to appropriate format for seg_EM.""" |
| 135 | + if opt == 'priors': |
| 136 | + _nb_priors = len(self.inputs.priors) |
| 137 | + return '-priors %d %s' % (_nb_priors, ' '.join(self.inputs.priors)) |
| 138 | + else: |
| 139 | + return super(EM, self)._format_arg(opt, spec, val) |
| 140 | + |
| 141 | + def _list_outputs(self): |
| 142 | + outputs = self.output_spec().get() |
| 143 | + outputs['out_file'] = self.inputs.out_file |
| 144 | + if not isdefined(self.inputs.out_file): |
| 145 | + outputs['out_file'] = self._gen_fname(self.inputs.in_file, |
| 146 | + suffix=self._suffix) |
| 147 | + outputs['out_file'] = os.path.abspath(outputs['out_file']) |
| 148 | + outputs['out_bc_file'] = self.inputs.out_bc_file |
| 149 | + if not isdefined(self.inputs.out_bc_file): |
| 150 | + outputs['out_bc_file'] = self._gen_fname( |
| 151 | + self.inputs.in_file, suffix=('_bc%s' % self._suffix)) |
| 152 | + outputs['out_bc_file'] = os.path.abspath(outputs['out_bc_file']) |
| 153 | + outputs['out_outlier_file'] = self.inputs.out_outlier_file |
| 154 | + if not isdefined(self.inputs.out_outlier_file): |
| 155 | + outputs['out_outlier_file'] = self._gen_fname( |
| 156 | + self.inputs.in_file, suffix=('_outlier%s' % self._suffix)) |
| 157 | + outputs['out_outlier_file'] = os.path.abspath( |
| 158 | + outputs['out_outlier_file']) |
| 159 | + return outputs |
| 160 | + |
| 161 | + def _gen_filename(self, name): |
| 162 | + if name == 'out_file': |
| 163 | + return self._list_outputs()['out_file'] |
| 164 | + if name == 'out_bc_file': |
| 165 | + return self._list_outputs()['out_bc_file'] |
| 166 | + if name == 'out_outlier_file': |
| 167 | + return self._list_outputs()['out_outlier_file'] |
| 168 | + return None |
0 commit comments