Skip to content

ENH: Makes ReconAll workflow backwards compatible with FreeSurfer 5.3.0. #1434

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 61 commits into from
Apr 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
2ce38f4
FIX: Fixes a few flags in for FreeSurfer 5.3
Apr 1, 2016
7a43049
ENH: Print FS version.
Apr 1, 2016
ee7ab69
FIX: Fixes elif syntax error.
Apr 1, 2016
dc8fec3
FIX: Adds stop and shrink to autorecon1.
Apr 1, 2016
c79f559
FIX: Removes entorhinal BA maps for 5.3.
Apr 1, 2016
bfa3c29
FIX: Adds entorhinal to autorecon3
Apr 1, 2016
291bafd
FIX: Removes thresh.perirhinal from 5.3
Apr 1, 2016
4bd4962
FIX: Allows for changing of RB atlas
Apr 1, 2016
c8ddf6d
FIX: Fixes input to config for rb_date
Apr 1, 2016
e81d637
FIX: config function.
Apr 1, 2016
97e1021
FIX: Switches around the intensity normalization for 5.3
Apr 1, 2016
c1f8aed
FIX: fixes connections ar1
Apr 1, 2016
4d16008
FIX: corrects the output for copy_transform
Apr 1, 2016
3d60d7d
FIX: adds item to outpus for autorecon1
Apr 1, 2016
06d5fbc
FIX: Connects 'nu' of autorecon1 to autorecon2.
ellisdg Apr 4, 2016
759f52e
FIX: Takes out new inputs to CALabel.
ellisdg Apr 4, 2016
a6850ce
FIX: Removes in_aseg from ribbon masking.
ellisdg Apr 5, 2016
cd7dc15
ENH: Allows for implicit aseg input in ribbon masking.
ellisdg Apr 5, 2016
c0cf40f
FIX: Fixes typo.
ellisdg Apr 5, 2016
37fd56c
FIX: Fixes source subject for BAMaps thresh.
Apr 6, 2016
1b95329
FIX: Temporary fix for apas2aseg. Will still need to fix what is goin…
Apr 6, 2016
2daa8c1
FIX: Changes reference of labels to source_fields.
Apr 6, 2016
25b7e96
Fix: turns the mandatory flag off for aseg.
Apr 6, 2016
ac60065
FIX: Fixes failure to copy rh.white
Apr 6, 2016
d6560f1
FIX: Adds filled input to Aparc2Aseg.
Apr 6, 2016
9057ffa
FIX: Allows for aseg to be copied in segstats for 5.3.
Apr 6, 2016
1ec5bf0
FIX: Changes presurf_seg to not being mandatory.
Apr 6, 2016
0b6eb84
FIX: Updates WM_Parcellation_Stats to take aseg as input.
Apr 6, 2016
987427a
FIX: Fixes typo when connecting workflows.
Apr 6, 2016
2c1c045
FIX: Fixes error causing sphere.reg to be passed as a label.
Apr 6, 2016
ce8a0df
FIX: Changes orig_nu.mgz to nu.mgz for the input to EM_register.
Apr 7, 2016
7959d40
ENH: Makes mris_make_surfaces compatable with the 5.3 recon-all.
Apr 11, 2016
2c9cb25
FIX: Removes unnecessary step in autorecon2.
Apr 11, 2016
490446e
ENH: Adds in_white to Make Surfaces.
Apr 11, 2016
e262e78
FIX: Switches the format of arguments for mris_make_surfaces to basen…
Apr 11, 2016
5060fdc
FIX: Adds inputs to the copying of aseg_presurf to aseg.mgz.
Apr 11, 2016
6c63ded
FIX: Changes .rsplit to os.path.splittext.
Apr 11, 2016
848442b
FIX: Removes the unnecessary inputs to MakeSurfaces for 53.
Apr 11, 2016
1857064
FIX: Allows the interface wrapper to know it is making a pial surface…
Apr 12, 2016
ede459f
FIX: Adds import statement to output aseg function.
Apr 12, 2016
a2672c8
FIX: Fixes import statement.
Apr 12, 2016
775f1f9
FIX: Adds shutil to import for out_aseg function.
Apr 12, 2016
44f1e29
FIX: Imports os for out_aseg function.
Apr 12, 2016
022352c
FIX: fixes bugs in recoding table workflow.
Apr 12, 2016
f3acecc
FIX: Changes nipype.pipeline.Node to pe.Node
Apr 12, 2016
7050d57
FIX: Changes nipype.Node to pe.Node.
Apr 12, 2016
ccb4b16
FIX: Changes nipype.Function to Function.
Apr 12, 2016
6c9886f
FIX: Replaces nipype.IdentityInterface with niu.IdentityInterface.
Apr 12, 2016
01b84a9
ENH: Removes the relabels hypointensities for 5.3.
Apr 13, 2016
89e208c
FIX: Switches the presurf labelmap name back to aseg.presurf.mgz.
Apr 13, 2016
aaf3b05
FIX: make check-before-commit
Apr 13, 2016
959c57e
FIX: switches incorrect if statement.
Apr 13, 2016
56fbd21
FIX: Fixes aseg input for Aparc2Aseg.
Apr 13, 2016
3cd2fd0
FIX: Adds aseg input for a2009s Aparc2Aseg.
Apr 13, 2016
5644aa2
FIX: Adds stop and shrink values to autorecon2.py to ensure that the
Apr 13, 2016
095e359
FIX: Adds distance to autorecon2.py.
Apr 13, 2016
3f1926c
FIX: Corrected fsvernum if statements to fix 6.0beta workflow.
Apr 14, 2016
f88204e
FIX: Removes duplicate connection.
Apr 14, 2016
58cfc19
FIX: Changes list position of entorhinal.
Apr 15, 2016
816f787
DOC: Updates CHANGES
Apr 15, 2016
9faf6f8
Merge remote-tracking branch 'nipype_proper/master' into FreeSurfer53
ellisdg Apr 16, 2016
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
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Next release
* FIX: Correct linking/copying fallback behavior (https://github.com/nipy/nipype/pull/1391)
* ENH: Nipype workflow and interfaces for FreeSurfer's recon-all (https://github.com/nipy/nipype/pull/1326)
* FIX: Permit relative path for concatenated_file input to Concatenate() (https://github.com/nipy/nipype/pull/1411)
* ENH: Makes ReconAll workflow backwards compatible with FreeSurfer 5.3.0 (https://github.com/nipy/nipype/pull/1434)

Release 0.11.0 (September 15, 2015)
============
Expand Down
11 changes: 7 additions & 4 deletions nipype/interfaces/freesurfer/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ class SegStatsReconAllInputSpec(SegStatsInputSpec):
# implicit
ribbon = traits.File(mandatory=True, exists=True,
desc="Input file mri/ribbon.mgz")
presurf_seg = File(mandatory=True, exists=True,
presurf_seg = File(exists=True,
desc="Input segmentation volume")
transform = File(mandatory=True, exists=True,
desc="Input transform file")
Expand All @@ -796,6 +796,8 @@ class SegStatsReconAllInputSpec(SegStatsInputSpec):
desc="Input file must be <subject_id>/surf/lh.pial")
rh_pial = File(mandatory=True, exists=True,
desc="Input file must be <subject_id>/surf/rh.pial")
aseg = File(exists=True,
desc="Mandatory implicit input in 5.3")
copy_inputs = traits.Bool(desc="If running as a node, set this to True " +
"otherwise, this will copy the implicit inputs " +
"to the node directory.")
Expand Down Expand Up @@ -859,7 +861,7 @@ def run(self, **inputs):
copy2subjdir(self, self.inputs.lh_white,
'surf', 'lh.white')
copy2subjdir(self, self.inputs.rh_white,
'Surf', 'Rh.White')
'surf', 'rh.white')
copy2subjdir(self, self.inputs.lh_pial,
'surf', 'lh.pial')
copy2subjdir(self, self.inputs.rh_pial,
Expand All @@ -868,12 +870,13 @@ def run(self, **inputs):
'mri', 'ribbon.mgz')
copy2subjdir(self, self.inputs.presurf_seg,
'mri', 'aseg.presurf.mgz')
copy2subjdir(self, self.inputs.aseg,
'mri', 'aseg.mgz')
copy2subjdir(self, self.inputs.transform,
os.path.join('mri', 'transforms'),
'talairach.xfm')
copy2subjdir(self, self.inputs.in_intensity, 'mri')
if isdefined(self.inputs.brainmask_file):
copy2subjdir(self, self.inputs.brainmask_file, 'mri')
copy2subjdir(self, self.inputs.brainmask_file, 'mri')
return super(SegStatsReconAll, self).run(**inputs)


Expand Down
1 change: 1 addition & 0 deletions nipype/interfaces/freesurfer/tests/test_auto_Aparc2Aseg.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def test_Aparc2Aseg_inputs():
environ=dict(nohash=True,
usedefault=True,
),
filled=dict(),
hypo_wm=dict(argstr='--hypo-as-wm',
mandatory=False,
),
Expand Down
1 change: 1 addition & 0 deletions nipype/interfaces/freesurfer/tests/test_auto_Curvature.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def test_Curvature_inputs():
usedefault=True,
),
in_file=dict(argstr='%s',
copyfile=True,
mandatory=True,
position=-2,
),
Expand Down
3 changes: 3 additions & 0 deletions nipype/interfaces/freesurfer/tests/test_auto_MakeSurfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def test_MakeSurfaces_inputs():
in_orig=dict(argstr='-orig %s',
mandatory=True,
),
in_white=dict(),
in_wm=dict(mandatory=True,
),
longitudinal=dict(argstr='-long',
Expand Down Expand Up @@ -66,6 +67,8 @@ def test_MakeSurfaces_inputs():
subjects_dir=dict(),
terminal_output=dict(nohash=True,
),
white=dict(argstr='-white %s',
),
white_only=dict(argstr='-whiteonly',
mandatory=False,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def test_SegStatsReconAll_inputs():
),
args=dict(argstr='%s',
),
aseg=dict(),
avgwf_file=dict(argstr='--avgwfvol %s',
),
avgwf_txt_file=dict(argstr='--avgwf %s',
Expand Down Expand Up @@ -85,8 +86,7 @@ def test_SegStatsReconAll_inputs():
),
partial_volume_file=dict(argstr='--pv %s',
),
presurf_seg=dict(mandatory=True,
),
presurf_seg=dict(),
rh_orig_nofix=dict(mandatory=True,
),
rh_pial=dict(mandatory=True,
Expand Down
3 changes: 3 additions & 0 deletions nipype/interfaces/freesurfer/tests/test_auto_VolumeMask.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
def test_VolumeMask_inputs():
input_map = dict(args=dict(argstr='%s',
),
aseg=dict(xor=['in_aseg'],
),
copy_inputs=dict(mandatory=False,
),
environ=dict(nohash=True,
Expand All @@ -16,6 +18,7 @@ def test_VolumeMask_inputs():
),
in_aseg=dict(argstr='--aseg_name %s',
mandatory=False,
xor=['aseg'],
),
left_ribbonlabel=dict(argstr='--label_left_ribbon %d',
mandatory=True,
Expand Down
52 changes: 38 additions & 14 deletions nipype/interfaces/freesurfer/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,30 @@


def copy2subjdir(cls, in_file, folder=None, basename=None, subject_id=None):
"""Method to copy an input to the subjects directory"""
# check that the input is defined
if not isdefined(in_file):
return in_file
# check that subjects_dir is defined
if isdefined(cls.inputs.subjects_dir):
subjects_dir = cls.inputs.subjects_dir
else:
subjects_dir = os.getcwd()
subjects_dir = os.getcwd() #if not use cwd
# check for subject_id
if not subject_id:
if isdefined(cls.inputs.subject_id):
subject_id = cls.inputs.subject_id
else:
subject_id = 'subject_id'
subject_id = 'subject_id' #default
# check for basename
if basename == None:
basename = os.path.basename(in_file)
# check which folder to put the file in
if folder != None:
out_dir = os.path.join(subjects_dir, subject_id, folder)
else:
out_dir = os.path.join(subjects_dir, subject_id)
# make the output folder if it does not exist
if not os.path.isdir(out_dir):
os.makedirs(out_dir)
out_file = os.path.join(out_dir, basename)
Expand All @@ -58,7 +67,7 @@ def copy2subjdir(cls, in_file, folder=None, basename=None, subject_id=None):
return out_file

def createoutputdirs(outputs):
"""create an output directories. If not created, some freesurfer interfaces fail"""
"""create all output directories. If not created, some freesurfer interfaces fail"""
for output in outputs.itervalues():
dirname = os.path.dirname(output)
if not os.path.isdir(dirname):
Expand Down Expand Up @@ -1867,6 +1876,7 @@ class MakeSurfacesInputSpec(FSTraitedSpec):
in_filled = File(exists=True, mandatory=True,
desc="Implicit input file filled.mgz")
# optional
in_white = File(exists=True, desc="Implicit input that is sometimes used")
in_label = File(exists=True, mandatory=False, xor=['noaparc'],
desc="Implicit input label/<hemisphere>.aparc.annot")
orig_white = File(argstr="-orig_white %s", exists=True, mandatory=False,
Expand All @@ -1893,6 +1903,8 @@ class MakeSurfacesInputSpec(FSTraitedSpec):
argstr="-max %.1f", desc="No documentation (used for longitudinal processing)")
longitudinal = traits.Bool(
argstr="-long", desc="No documentation (used for longitudinal processing)")
white = traits.String(argstr="-white %s",
desc="White surface name")
copy_inputs = traits.Bool(mandatory=False,
desc="If running as a node, set this to True." +
"This will copy the input files to the node " +
Expand Down Expand Up @@ -1947,15 +1959,15 @@ def run(self, **inputs):
folder='mri', basename='wm.mgz')
copy2subjdir(self, self.inputs.in_filled,
folder='mri', basename='filled.mgz')
copy2subjdir(self, self.inputs.in_white,
'surf', '{0}.white'.format(self.inputs.hemisphere))
for originalfile in [self.inputs.in_aseg,
self.inputs.in_T1]:
if isdefined(originalfile):
copy2subjdir(self, originalfile, folder='mri')
copy2subjdir(self, originalfile, folder='mri')
for originalfile in [self.inputs.orig_white,
self.inputs.orig_pial,
self.inputs.in_orig]:
if isdefined(originalfile):
copy2subjdir(self, originalfile, folder='surf')
copy2subjdir(self, originalfile, folder='surf')
if isdefined(self.inputs.in_label):
copy2subjdir(self, self.inputs.in_label, 'label',
'{0}.aparc.annot'.format(self.inputs.hemisphere))
Expand All @@ -1972,9 +1984,11 @@ def _format_arg(self, name, spec, value):
basename = os.path.basename(value)
# whent the -mgz flag is specified, it assumes the mgz extension
if self.inputs.mgz:
prefix = basename.rstrip('.mgz')
prefix = os.path.splitext(basename)[0]
else:
prefix = basename
if prefix == 'aseg':
return # aseg is already the default
return spec.argstr % prefix
elif name in ['orig_white', 'orig_pial']:
# these inputs do take full file paths or even basenames
Expand Down Expand Up @@ -2011,8 +2025,8 @@ def _list_outputs(self):
dest_dir, str(self.inputs.hemisphere) + '.area')
# Something determines when a pial surface and thickness file is generated
# but documentation doesn't say what.
# The orig_pial flag is just a guess
if isdefined(self.inputs.orig_pial):
# The orig_pial input is just a guess
if isdefined(self.inputs.orig_pial) or self.inputs.white == 'NOWRITE':
outputs["out_curv"] = outputs["out_curv"] + ".pial"
outputs["out_area"] = outputs["out_area"] + ".pial"
outputs["out_pial"] = os.path.join(
Expand All @@ -2029,7 +2043,7 @@ def _list_outputs(self):

class CurvatureInputSpec(FSTraitedSpec):
in_file = File(argstr="%s", position=-2, mandatory=True, exists=True,
desc="Input file for Curvature")
copyfile=True, desc="Input file for Curvature")
# optional
threshold = traits.Float(
argstr="-thresh %.3f", mandatory=False, desc="Undocumented input threshold")
Expand Down Expand Up @@ -2073,7 +2087,6 @@ def _format_arg(self, name, spec, value):
if self.inputs.copy_input:
if name == 'in_file':
basename = os.path.basename(value)
shutil.copy(value, basename)
return spec.argstr % basename
return super(Curvature, self)._format_arg(name, spec, value)

Expand Down Expand Up @@ -2301,11 +2314,16 @@ class VolumeMaskInputSpec(FSTraitedSpec):
desc="Implicit input left white matter surface")
rh_white = File(mandatory=True, exists=True,
desc="Implicit input right white matter surface")
aseg = File(exists=True,
xor=['in_aseg'],
desc="Implicit aseg.mgz segmentation. " +
"Specify a different aseg by using the 'in_aseg' input.")
subject_id = traits.String('subject_id', usedefault=True,
position=-1, argstr="%s", mandatory=True,
desc="Subject being processed")
# optional
in_aseg = File(argstr="--aseg_name %s", mandatory=False, exists=True,
in_aseg = File(argstr="--aseg_name %s", mandatory=False,
exists=True, xor=['aseg'],
desc="Input aseg file for VolumeMask")
save_ribbon = traits.Bool(argstr="--save_ribbon", mandatory=False,
desc="option to save just the ribbon for the " +
Expand Down Expand Up @@ -2364,6 +2382,8 @@ def run(self, **inputs):
copy2subjdir(self, self.inputs.lh_white, 'surf', 'lh.white')
copy2subjdir(self, self.inputs.rh_white, 'surf', 'rh.white')
copy2subjdir(self, self.inputs.in_aseg, 'mri')
copy2subjdir(self, self.inputs.aseg, 'mri', 'aseg.mgz')

return super(VolumeMask, self).run(**inputs)

def _format_arg(self, name, spec, value):
Expand Down Expand Up @@ -2726,6 +2746,8 @@ class Aparc2AsegInputSpec(FSTraitedSpec):
rh_annotation = File(mandatory=True, exists=True,
desc="Input file must be <subject_id>/label/rh.aparc.annot")
# optional
filled = File(exists=True,
desc="Implicit input filled file. Only required with FS v5.3.")
aseg = File(argstr="--aseg %s", mandatory=False, exists=True,
desc="Input aseg file")
volmask = traits.Bool(argstr="--volmask", mandatory=False,
Expand Down Expand Up @@ -2808,6 +2830,7 @@ def run(self, **inputs):
copy2subjdir(self, self.inputs.rh_ribbon, 'mri', 'rh.ribbon.mgz')
copy2subjdir(self, self.inputs.ribbon, 'mri', 'ribbon.mgz')
copy2subjdir(self, self.inputs.aseg, 'mri')
copy2subjdir(self, self.inputs.filled, 'mri', 'filled.mgz')
copy2subjdir(self, self.inputs.lh_annotation, 'label')
copy2subjdir(self, self.inputs.rh_annotation, 'label')

Expand All @@ -2816,7 +2839,8 @@ def run(self, **inputs):
def _format_arg(self, name, spec, value):
if name == 'aseg':
# aseg does not take a full filename
return spec.argstr % os.path.basename(value).replace('.mgz', '')
basename = os.path.basename(value).replace('.mgz', '')
return spec.argstr % basename
elif name == 'out_file':
return spec.argstr % os.path.abspath(value)

Expand Down
Loading