Skip to content

ENH: ReconAll handle less common cases #1966

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 59 additions & 3 deletions nipype/interfaces/freesurfer/preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,8 +630,26 @@ class ReconAllInputSpec(CommandLineInputSpec):
desc="Enable parallel execution")
hires = traits.Bool(argstr="-hires", min_ver='6.0.0',
desc="Conform to minimum voxel size (for voxels < 1mm)")
mprage = traits.Bool(argstr='-mprage',
desc=('Assume scan parameters are MGH MP-RAGE '
'protocol, which produces darker gray matter'))
big_ventricles = traits.Bool(argstr='-bigventricles',
desc=('For use in subjects with enlarged '
'ventricles'))
brainstem = traits.Bool(argstr='-brainstem-structures',
desc='Segment brainstem structures')
hippocampal_subfields_T1 = traits.Bool(
argstr='-hippocampal-subfields-T1', min_ver='6.0.0',
desc='segment hippocampal subfields using input T1 scan')
hippocampal_subfields_T2 = traits.Tuple(
File(exists=True), traits.Str(),
argstr='-hippocampal-subfields-T2 %s %s', min_ver='6.0.0',
desc=('segment hippocampal subfields using T2 scan, identified by '
'ID (may be combined with hippocampal_subfields_T1)'))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@satra What do you think of this implementation? The tuple might be a little awkward; if you'd prefer, I could make a hippocampal_subfields_id that gets pulled in in _format_arg. If so, is there a reasonable default ID name?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the file here the same as the T2 input, in which case, should we simply say this field requires T2?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. A separate filename is parsed. I don't know enough about these processes to know if you'd use the same T2 for hippocampal subfields as for pial surface refinement, but certainly it's not required by their code that they be the same file.

expert = File(exists=True, argstr='-expert %s',
desc="Set parameters using expert file")
xopts = traits.Enum("use", "clean", "overwrite", argstr='-xopts-%s',
desc="Use, delete or overwrite existing expert options file")
subjects_dir = Directory(exists=True, argstr='-sd %s', hash_files=False,
desc='path to subjects directory', genfile=True)
flags = traits.Str(argstr='%s', desc='additional parameters')
Expand Down Expand Up @@ -933,6 +951,13 @@ def _format_arg(self, name, trait_spec, value):
if name == 'T1_files':
if self._is_resuming():
return ''
if name == 'hippocampal_subfields_T1' and \
isdefined(self.inputs.hippocampal_subfields_T2):
return ''
if all((name == 'hippocampal_subfields_T2',
isdefined(self.inputs.hippocampal_subfields_T1) and
self.inputs.hippocampal_subfields_T1)):
trait_spec.argstr = trait_spec.argstr.replace('T2', 'T1T2')
return super(ReconAll, self)._format_arg(name, trait_spec, value)

@property
Expand All @@ -949,10 +974,22 @@ def cmdline(self):
if not isdefined(subjects_dir):
subjects_dir = self._gen_subjects_dir()

# Check only relevant steps
directive = self.inputs.directive
if not isdefined(directive):
steps = []
elif directive == 'autorecon1':
steps = self._autorecon1_steps
elif directive.startswith('autorecon2'):
steps = self._autorecon2_steps
elif directive == 'autorecon3':
steps = self._autorecon3_steps
else:
steps = self._steps

no_run = True
flags = []
for idx, step in enumerate(self._steps):
step, outfiles, infiles = step
for step, outfiles, infiles in steps:
flag = '-{}'.format(step)
noflag = '-no{}'.format(step)
if noflag in cmd:
Expand Down Expand Up @@ -989,11 +1026,30 @@ def _prep_expert_file(self):
if lines == []:
return ''

contents = ''.join(lines)
if not isdefined(self.inputs.xopts) and \
self.get_expert_file() == contents:
return ' -xopts-use'

expert_fname = os.path.abspath('expert.opts')
with open(expert_fname, 'w') as fobj:
fobj.write(''.join(lines))
fobj.write(contents)
return ' -expert {}'.format(expert_fname)

def _get_expert_file(self):
# Read pre-existing options file, if it exists
if isdefined(self.inputs.subjects_dir):
subjects_dir = self.inputs.subjects_dir
else:
subjects_dir = self._gen_subjects_dir()

xopts_file = os.path.join(subjects_dir, self.inputs.subject_id,
'scripts', 'expert-options')
if not os.path.exists(xopts_file):
return ''
with open(xopts_file, 'r') as fobj:
return fobj.read()


class BBRegisterInputSpec(FSTraitedSpec):
subject_id = traits.Str(argstr='--s %s',
Expand Down
14 changes: 14 additions & 0 deletions nipype/interfaces/freesurfer/tests/test_auto_ReconAll.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ def test_ReconAll_inputs():
),
args=dict(argstr='%s',
),
big_ventricles=dict(argstr='-bigventricles',
),
brainstem=dict(argstr='-brainstem-structures',
),
directive=dict(argstr='-%s',
position=0,
usedefault=True,
Expand All @@ -24,12 +28,20 @@ def test_ReconAll_inputs():
),
hemi=dict(argstr='-hemi %s',
),
hippocampal_subfields_T1=dict(argstr='-hippocampal-subfields-T1',
min_ver='6.0.0',
),
hippocampal_subfields_T2=dict(argstr='-hippocampal-subfields-T2 %s %s',
min_ver='6.0.0',
),
hires=dict(argstr='-hires',
min_ver='6.0.0',
),
ignore_exception=dict(nohash=True,
usedefault=True,
),
mprage=dict(argstr='-mprage',
),
mri_aparc2aseg=dict(xor=['expert'],
),
mri_ca_label=dict(xor=['expert'],
Expand Down Expand Up @@ -98,6 +110,8 @@ def test_ReconAll_inputs():
use_T2=dict(argstr='-T2pial',
min_ver='5.3.0',
),
xopts=dict(argstr='-xopts-%s',
),
)
inputs = ReconAll.input_spec()

Expand Down