Skip to content

Commit b491da4

Browse files
authored
Merge pull request #2785 from TheChymera/tran
ENH: CompositeTransformUtil, new ANTs interface
2 parents 799d3f3 + 09ae8ed commit b491da4

File tree

6 files changed

+127
-1
lines changed

6 files changed

+127
-1
lines changed

nipype/interfaces/ants/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
# Registraiton programs
77
from .registration import (ANTS, Registration, RegistrationSynQuick,
8-
MeasureImageSimilarity)
8+
CompositeTransformUtil, MeasureImageSimilarity)
99

1010
# Resampling Programs
1111
from .resampling import (ApplyTransforms, ApplyTransformsToPoints,

nipype/interfaces/ants/registration.py

+74
Original file line numberDiff line numberDiff line change
@@ -1596,3 +1596,77 @@ def _list_outputs(self):
15961596
outputs['forward_warp_field'] = out_base + '1Warp.nii.gz'
15971597
outputs['inverse_warp_field'] = out_base + '1InverseWarp.nii.gz'
15981598
return outputs
1599+
1600+
class CompositeTransformUtilInputSpec(ANTSCommandInputSpec):
1601+
process = traits.Enum('assemble', 'disassemble', argstr='--%s',
1602+
position=1, usedefault=True,
1603+
desc='What to do with the transform inputs (assemble or disassemble)',
1604+
)
1605+
out_file = File(exists=False, argstr='%s', position=2,
1606+
desc='Output file path (only used for disassembly).')
1607+
in_file = InputMultiPath(File(exists=True), mandatory=True, argstr='%s...',
1608+
position=3, desc='Input transform file(s)')
1609+
output_prefix = Str("transform", usedefault=True, argstr='%s', position=4,
1610+
desc="A prefix that is prepended to all output files (only used for assembly).")
1611+
1612+
class CompositeTransformUtilOutputSpec(TraitedSpec):
1613+
affine_transform = File(desc="Affine transform component")
1614+
displacement_field = File(desc="Displacement field component")
1615+
out_file = File(desc="Compound transformation file")
1616+
1617+
class CompositeTransformUtil(ANTSCommand):
1618+
"""
1619+
ANTs utility which can combine or break apart transform files into their individual
1620+
constituent components.
1621+
1622+
Examples
1623+
--------
1624+
1625+
>>> from nipype.interfaces.ants import CompositeTransformUtil
1626+
>>> tran = CompositeTransformUtil()
1627+
>>> tran.inputs.process = 'disassemble'
1628+
>>> tran.inputs.in_file = 'output_Composite.h5'
1629+
>>> tran.cmdline
1630+
'CompositeTransformUtil --disassemble output_Composite.h5 transform'
1631+
>>> tran.run() # doctest: +SKIP
1632+
1633+
example for assembling transformation files
1634+
1635+
>>> from nipype.interfaces.ants import CompositeTransformUtil
1636+
>>> tran = CompositeTransformUtil()
1637+
>>> tran.inputs.process = 'assemble'
1638+
>>> tran.inputs.out_file = 'my.h5'
1639+
>>> tran.inputs.in_file = ['AffineTransform.mat', 'DisplacementFieldTransform.nii.gz']
1640+
>>> tran.cmdline
1641+
'CompositeTransformUtil --assemble my.h5 AffineTransform.mat DisplacementFieldTransform.nii.gz '
1642+
>>> tran.run() # doctest: +SKIP
1643+
"""
1644+
1645+
_cmd = 'CompositeTransformUtil'
1646+
input_spec = CompositeTransformUtilInputSpec
1647+
output_spec = CompositeTransformUtilOutputSpec
1648+
1649+
def _num_threads_update(self):
1650+
"""
1651+
CompositeTransformUtil ignores environment variables,
1652+
so override environment update from ANTSCommand class
1653+
"""
1654+
pass
1655+
1656+
def _format_arg(self, name, spec, value):
1657+
if name == 'output_prefix' and self.inputs.process == 'assemble':
1658+
return ''
1659+
if name == 'out_file' and self.inputs.process == 'disassemble':
1660+
return ''
1661+
return super(CompositeTransformUtil, self)._format_arg(name, spec, value)
1662+
1663+
def _list_outputs(self):
1664+
outputs = self.output_spec().get()
1665+
if self.inputs.process == 'disassemble':
1666+
outputs['affine_transform'] = os.path.abspath(
1667+
'00_{}_AffineTransform.mat'.format(self.inputs.output_prefix))
1668+
outputs['displacement_field'] = os.path.abspath(
1669+
'01_{}_DisplacementFieldTransform.nii.gz'.format(self.inputs.output_prefix))
1670+
if self.inputs.process == 'assemble':
1671+
outputs['out_file'] = os.path.abspath(self.inputs.out_file)
1672+
return outputs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..registration import CompositeTransformUtil
4+
5+
6+
def test_CompositeTransformUtil_inputs():
7+
input_map = dict(
8+
args=dict(argstr='%s', ),
9+
environ=dict(
10+
nohash=True,
11+
usedefault=True,
12+
),
13+
in_file=dict(
14+
argstr='%s...',
15+
mandatory=True,
16+
position=3,
17+
),
18+
num_threads=dict(
19+
nohash=True,
20+
usedefault=True,
21+
),
22+
out_file=dict(
23+
argstr='%s',
24+
position=2,
25+
),
26+
output_prefix=dict(
27+
argstr='%s',
28+
position=4,
29+
usedefault=True,
30+
),
31+
process=dict(
32+
argstr='--%s',
33+
position=1,
34+
usedefault=True,
35+
),
36+
)
37+
inputs = CompositeTransformUtil.input_spec()
38+
39+
for key, metadata in list(input_map.items()):
40+
for metakey, value in list(metadata.items()):
41+
assert getattr(inputs.traits()[key], metakey) == value
42+
def test_CompositeTransformUtil_outputs():
43+
output_map = dict(
44+
affine_transform=dict(),
45+
displacement_field=dict(),
46+
out_file=dict(),
47+
)
48+
outputs = CompositeTransformUtil.output_spec()
49+
50+
for key, metadata in list(output_map.items()):
51+
for metakey, value in list(metadata.items()):
52+
assert getattr(outputs.traits()[key], metakey) == value

nipype/testing/data/AffineTransform.mat

Whitespace-only changes.

nipype/testing/data/DisplacementFieldTransform.nii.gz

Whitespace-only changes.

nipype/testing/data/output_Composite.h5

Whitespace-only changes.

0 commit comments

Comments
 (0)