Skip to content

Commit 8c4e602

Browse files
authored
Merge pull request #1893 from effigies/mris_expand
ENH: Add mris_expand interface
2 parents 0547f67 + 39a1e3d commit 8c4e602

File tree

4 files changed

+189
-1
lines changed

4 files changed

+189
-1
lines changed

nipype/interfaces/freesurfer/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
MRIFill, MRIsInflate, Sphere, FixTopology, EulerNumber,
2222
RemoveIntersection, MakeSurfaces, Curvature, CurvatureStats,
2323
Jacobian, MRIsCalc, VolumeMask, ParcellationStats, Contrast,
24-
RelabelHypointensities, Aparc2Aseg, Apas2Aseg)
24+
RelabelHypointensities, Aparc2Aseg, Apas2Aseg, MRIsExpand)
2525
from .longitudinal import (RobustTemplate, FuseSegmentations)
2626
from .registration import (MPRtoMNI305, RegisterAVItoTalairach, EMRegister, Register,
2727
Paint)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..utils import MRIsExpand
4+
5+
6+
def test_MRIsExpand_inputs():
7+
input_map = dict(args=dict(argstr='%s',
8+
),
9+
distance=dict(argstr='%g',
10+
mandatory=True,
11+
position=-2,
12+
),
13+
dt=dict(argstr='-T %g',
14+
),
15+
environ=dict(nohash=True,
16+
usedefault=True,
17+
),
18+
ignore_exception=dict(nohash=True,
19+
usedefault=True,
20+
),
21+
in_file=dict(argstr='%s',
22+
copyfile=False,
23+
mandatory=True,
24+
position=-3,
25+
),
26+
navgs=dict(argstr='-navgs %d %d',
27+
),
28+
nsurfaces=dict(argstr='-N %d',
29+
),
30+
out_name=dict(argstr='%s',
31+
position=-1,
32+
usedefault=True,
33+
),
34+
pial=dict(argstr='-pial %s',
35+
copyfile=False,
36+
),
37+
smooth_averages=dict(argstr='-A %d',
38+
),
39+
sphere=dict(copyfile=False,
40+
usedefault=True,
41+
),
42+
spring=dict(argstr='-S %g',
43+
),
44+
subjects_dir=dict(),
45+
terminal_output=dict(nohash=True,
46+
),
47+
thickness=dict(argstr='-thickness',
48+
),
49+
thickness_name=dict(argstr='-thickness_name %s',
50+
copyfile=False,
51+
),
52+
write_iterations=dict(argstr='-W %d',
53+
),
54+
)
55+
inputs = MRIsExpand.input_spec()
56+
57+
for key, metadata in list(input_map.items()):
58+
for metakey, value in list(metadata.items()):
59+
assert getattr(inputs.traits()[key], metakey) == value
60+
61+
62+
def test_MRIsExpand_outputs():
63+
output_map = dict(out_file=dict(),
64+
)
65+
outputs = MRIsExpand.output_spec()
66+
67+
for key, metadata in list(output_map.items()):
68+
for metakey, value in list(metadata.items()):
69+
assert getattr(outputs.traits()[key], metakey) == value

nipype/interfaces/freesurfer/utils.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2906,3 +2906,122 @@ def _list_outputs(self):
29062906
outputs = self._outputs().get()
29072907
outputs["out_file"] = os.path.abspath(self.inputs.out_file)
29082908
return outputs
2909+
2910+
2911+
class MRIsExpandInputSpec(FSTraitedSpec):
2912+
# Input spec derived from
2913+
# https://github.com/freesurfer/freesurfer/blob/102e053/mris_expand/mris_expand.c
2914+
in_file = File(
2915+
exists=True, mandatory=True, argstr='%s', position=-3, copyfile=False,
2916+
desc='Surface to expand')
2917+
distance = traits.Float(
2918+
mandatory=True, argstr='%g', position=-2,
2919+
desc='Distance in mm or fraction of cortical thickness')
2920+
out_name = traits.Str(
2921+
'expanded', argstr='%s', position=-1, usedefault=True,
2922+
desc=('Output surface file\n'
2923+
'If no path, uses directory of `in_file`\n'
2924+
'If no path AND missing "lh." or "rh.", derive from `in_file`'))
2925+
thickness = traits.Bool(
2926+
argstr='-thickness',
2927+
desc='Expand by fraction of cortical thickness, not mm')
2928+
thickness_name = traits.Str(
2929+
argstr="-thickness_name %s", copyfile=False,
2930+
desc=('Name of thickness file (implicit: "thickness")\n'
2931+
'If no path, uses directory of `in_file`\n'
2932+
'If no path AND missing "lh." or "rh.", derive from `in_file`'))
2933+
navgs = traits.Tuple(
2934+
traits.Int, traits.Int,
2935+
argstr='-navgs %d %d',
2936+
desc=('Tuple of (n_averages, min_averages) parameters '
2937+
'(implicit: (16, 0))'))
2938+
pial = traits.Str(
2939+
argstr='-pial %s', copyfile=False,
2940+
desc=('Name of pial file (implicit: "pial")\n'
2941+
'If no path, uses directory of `in_file`\n'
2942+
'If no path AND missing "lh." or "rh.", derive from `in_file`'))
2943+
sphere = traits.Str(
2944+
'sphere', copyfile=False, usedefault=True,
2945+
desc='WARNING: Do not change this trait')
2946+
spring = traits.Float(argstr='-S %g', desc="Spring term (implicit: 0.05)")
2947+
dt = traits.Float(argstr='-T %g', desc='dt (implicit: 0.25)')
2948+
write_iterations = traits.Int(
2949+
argstr='-W %d',
2950+
desc='Write snapshots of expansion every N iterations')
2951+
smooth_averages = traits.Int(
2952+
argstr='-A %d',
2953+
desc='Smooth surface with N iterations after expansion')
2954+
nsurfaces = traits.Int(
2955+
argstr='-N %d',
2956+
desc='Number of surfacces to write during expansion')
2957+
# # Requires dev version - Re-add when min_ver/max_ver support this
2958+
# # https://github.com/freesurfer/freesurfer/blob/9730cb9/mris_expand/mris_expand.c
2959+
# target_intensity = traits.Tuple(
2960+
# traits.Float, traits.File(exists=True),
2961+
# argstr='-intensity %g %s',
2962+
# desc='Tuple of intensity and brain volume to crop to target intensity')
2963+
2964+
2965+
class MRIsExpandOutputSpec(TraitedSpec):
2966+
out_file = File(desc='Output surface file')
2967+
2968+
2969+
class MRIsExpand(FSCommand):
2970+
"""
2971+
Expands a surface (typically ?h.white) outwards while maintaining
2972+
smoothness and self-intersection constraints.
2973+
2974+
Examples
2975+
========
2976+
>>> from nipype.interfaces.freesurfer import MRIsExpand
2977+
>>> mris_expand = MRIsExpand(thickness=True, distance=0.5)
2978+
>>> mris_expand.inputs.in_file = 'lh.white'
2979+
>>> mris_expand.cmdline # doctest: +ALLOW_UNICODE
2980+
'mris_expand -thickness lh.white 0.5 expanded'
2981+
>>> mris_expand.inputs.out_name = 'graymid'
2982+
>>> mris_expand.cmdline # doctest: +ALLOW_UNICODE
2983+
'mris_expand -thickness lh.white 0.5 graymid'
2984+
"""
2985+
_cmd = 'mris_expand'
2986+
input_spec = MRIsExpandInputSpec
2987+
output_spec = MRIsExpandOutputSpec
2988+
2989+
def _list_outputs(self):
2990+
outputs = self._outputs().get()
2991+
outputs['out_file'] = self._associated_file(self.inputs.in_file,
2992+
self.inputs.out_name)
2993+
return outputs
2994+
2995+
def _get_filecopy_info(self):
2996+
in_file = self.inputs.in_file
2997+
2998+
pial = self.inputs.pial
2999+
if not isdefined(pial):
3000+
pial = 'pial'
3001+
self.inputs.pial = self._associated_file(in_file, pial)
3002+
3003+
if isdefined(self.inputs.thickness) and self.inputs.thickness:
3004+
thickness_name = self.inputs.thickness_name
3005+
if not isdefined(thickness_name):
3006+
thickness_name = 'thickness'
3007+
self.inputs.thickness_name = self._associated_file(in_file,
3008+
thickness_name)
3009+
3010+
self.inputs.sphere = self._associated_file(in_file, self.inputs.sphere)
3011+
3012+
return super(MRIsExpand, self)._get_filecopy_info()
3013+
3014+
@staticmethod
3015+
def _associated_file(in_file, out_name):
3016+
"""Based on MRIsBuildFileName in freesurfer/utils/mrisurf.c
3017+
3018+
Use file prefix to indicate hemisphere, rather than inspecting the
3019+
surface data structure
3020+
"""
3021+
path, base = os.path.split(out_name)
3022+
if path == '':
3023+
path, in_file = os.path.split(in_file)
3024+
hemis = ('lh.', 'rh.')
3025+
if in_file[:3] in hemis and base[:3] not in hemis:
3026+
base = in_file[:3] + base
3027+
return os.path.join(path, base)

nipype/testing/data/lh.white

Whitespace-only changes.

0 commit comments

Comments
 (0)