Skip to content

Commit 0c6d3f8

Browse files
authored
Merge pull request #2453 from djarecka/ants_regsynquick
antsRegistrationSyNQuick (continuation of #1392 and #2347)
2 parents ae10756 + 5cd952f commit 0c6d3f8

File tree

3 files changed

+178
-2
lines changed

3 files changed

+178
-2
lines changed

nipype/interfaces/ants/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"""Top-level namespace for ants."""
55

66
# Registraiton programs
7-
from .registration import ANTS, Registration, MeasureImageSimilarity
7+
from .registration import (ANTS, Registration, RegistrationSynQuick,
8+
MeasureImageSimilarity)
89

910
# Resampling Programs
1011
from .resampling import (ApplyTransforms, ApplyTransformsToPoints,

nipype/interfaces/ants/registration.py

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from ...utils.filemanip import filename_to_list
1717
from ..base import TraitedSpec, File, Str, traits, InputMultiPath, isdefined
18-
from .base import ANTSCommand, ANTSCommandInputSpec
18+
from .base import ANTSCommand, ANTSCommandInputSpec, LOCAL_DEFAULT_NUMBER_OF_THREADS
1919

2020

2121
class ANTSInputSpec(ANTSCommandInputSpec):
@@ -1505,3 +1505,107 @@ def aggregate_outputs(self, runtime=None, needed_outputs=None):
15051505
stdout = runtime.stdout.split('\n')
15061506
outputs.similarity = float(stdout[0])
15071507
return outputs
1508+
1509+
1510+
class RegistrationSynQuickInputSpec(ANTSCommandInputSpec):
1511+
dimension = traits.Enum(3, 2, argstr='-d %d',
1512+
usedefault=True, desc='image dimension (2 or 3)')
1513+
fixed_image = InputMultiPath(File(exists=True), mandatory=True, argstr='-f %s...',
1514+
desc='Fixed image or source image or reference image')
1515+
moving_image = InputMultiPath(File(exists=True), mandatory=True, argstr='-m %s...',
1516+
desc='Moving image or target image')
1517+
output_prefix = Str("transform", usedefault=True, argstr='-o %s',
1518+
desc="A prefix that is prepended to all output files")
1519+
num_threads = traits.Int(default_value=LOCAL_DEFAULT_NUMBER_OF_THREADS, usedefault=True,
1520+
desc='Number of threads (default = 1)', argstr='-n %d')
1521+
1522+
transform_type = traits.Enum('s', 't', 'r', 'a', 'sr', 'b', 'br', argstr='-t %s',
1523+
desc="""
1524+
transform type
1525+
t: translation
1526+
r: rigid
1527+
a: rigid + affine
1528+
s: rigid + affine + deformable syn (default)
1529+
sr: rigid + deformable syn
1530+
b: rigid + affine + deformable b-spline syn
1531+
br: rigid + deformable b-spline syn""",
1532+
usedefault=True)
1533+
1534+
use_histogram_matching = traits.Bool(False, argstr='-j %d',
1535+
desc='use histogram matching')
1536+
histogram_bins = traits.Int(default_value=32, argstr='-r %d',
1537+
desc='histogram bins for mutual information in SyN stage \
1538+
(default = 32)')
1539+
spline_distance = traits.Int(default_value=26, argstr='-s %d',
1540+
desc='spline distance for deformable B-spline SyN transform \
1541+
(default = 26)')
1542+
precision_type = traits.Enum('double', 'float', argstr='-p %s',
1543+
desc='precision type (default = double)', usedefault=True)
1544+
1545+
1546+
class RegistrationSynQuickOutputSpec(TraitedSpec):
1547+
warped_image = File(exists=True, desc="Warped image")
1548+
inverse_warped_image = File(exists=True, desc="Inverse warped image")
1549+
out_matrix = File(exists=True, desc='Affine matrix')
1550+
forward_warp_field = File(exists=True, desc='Forward warp field')
1551+
inverse_warp_field = File(exists=True, desc='Inverse warp field')
1552+
1553+
1554+
class RegistrationSynQuick(ANTSCommand):
1555+
"""
1556+
Registration using a symmetric image normalization method (SyN).
1557+
You can read more in Avants et al.; Med Image Anal., 2008
1558+
(https://www.ncbi.nlm.nih.gov/pubmed/17659998).
1559+
1560+
Examples
1561+
--------
1562+
1563+
>>> from nipype.interfaces.ants import RegistrationSynQuick
1564+
>>> reg = RegistrationSynQuick()
1565+
>>> reg.inputs.fixed_image = 'fixed1.nii'
1566+
>>> reg.inputs.moving_image = 'moving1.nii'
1567+
>>> reg.inputs.num_threads = 2
1568+
>>> reg.cmdline
1569+
'antsRegistrationSynQuick.sh -d 3 -f fixed1.nii -m moving1.nii -n 2 -o transform -p d -t s'
1570+
>>> reg.run() # doctest: +SKIP
1571+
1572+
example for multiple images
1573+
1574+
>>> from nipype.interfaces.ants import RegistrationSynQuick
1575+
>>> reg = RegistrationSynQuick()
1576+
>>> reg.inputs.fixed_image = ['fixed1.nii', 'fixed2.nii']
1577+
>>> reg.inputs.moving_image = ['moving1.nii', 'moving2.nii']
1578+
>>> reg.inputs.num_threads = 2
1579+
>>> reg.cmdline
1580+
'antsRegistrationSynQuick.sh -d 3 -f fixed1.nii -f fixed2.nii -m moving1.nii -m moving2.nii -n 2 -o transform -p d -t s'
1581+
>>> reg.run() # doctest: +SKIP
1582+
"""
1583+
1584+
1585+
_cmd = 'antsRegistrationSynQuick.sh'
1586+
input_spec = RegistrationSynQuickInputSpec
1587+
output_spec = RegistrationSynQuickOutputSpec
1588+
1589+
def _num_threads_update(self):
1590+
"""
1591+
antsRegistrationSynQuick.sh ignores environment variables,
1592+
so override environment update frm ANTSCommand class
1593+
"""
1594+
pass
1595+
1596+
def _format_arg(self, name, spec, value):
1597+
if name == 'precision_type':
1598+
return spec.argstr % value[0]
1599+
return super(RegistrationSynQuick, self)._format_arg(name, spec, value)
1600+
1601+
def _list_outputs(self):
1602+
outputs = self.output_spec().get()
1603+
out_base = os.path.abspath(self.inputs.output_prefix)
1604+
outputs['warped_image'] = out_base + 'Warped.nii.gz'
1605+
outputs['inverse_warped_image'] = out_base + 'InverseWarped.nii.gz'
1606+
outputs['out_matrix'] = out_base + '0GenericAffine.mat'
1607+
1608+
if self.inputs.transform_type not in ('t', 'r', 'a'):
1609+
outputs['forward_warp_field'] = out_base + '1Warp.nii.gz'
1610+
outputs['inverse_warp_field'] = out_base + '1InverseWarp.nii.gz'
1611+
return outputs
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..registration import RegistrationSynQuick
4+
5+
6+
def test_RegistrationSynQuick_inputs():
7+
input_map = dict(
8+
args=dict(argstr='%s', ),
9+
dimension=dict(
10+
argstr='-d %d',
11+
usedefault=True,
12+
),
13+
environ=dict(
14+
nohash=True,
15+
usedefault=True,
16+
),
17+
fixed_image=dict(
18+
argstr='-f %s...',
19+
mandatory=True,
20+
),
21+
histogram_bins=dict(argstr='-r %d', ),
22+
ignore_exception=dict(
23+
deprecated='1.0.0',
24+
nohash=True,
25+
usedefault=True,
26+
),
27+
moving_image=dict(
28+
argstr='-m %s...',
29+
mandatory=True,
30+
),
31+
num_threads=dict(
32+
argstr='-n %d',
33+
usedefault=True,
34+
),
35+
output_prefix=dict(
36+
argstr='-o %s',
37+
usedefault=True,
38+
),
39+
precision_type=dict(
40+
argstr='-p %s',
41+
usedefault=True,
42+
),
43+
spline_distance=dict(argstr='-s %d', ),
44+
terminal_output=dict(
45+
deprecated='1.0.0',
46+
nohash=True,
47+
),
48+
transform_type=dict(
49+
argstr='-t %s',
50+
usedefault=True,
51+
),
52+
use_histogram_matching=dict(argstr='-j %d', ),
53+
)
54+
inputs = RegistrationSynQuick.input_spec()
55+
56+
for key, metadata in list(input_map.items()):
57+
for metakey, value in list(metadata.items()):
58+
assert getattr(inputs.traits()[key], metakey) == value
59+
def test_RegistrationSynQuick_outputs():
60+
output_map = dict(
61+
forward_warp_field=dict(),
62+
inverse_warp_field=dict(),
63+
inverse_warped_image=dict(),
64+
out_matrix=dict(),
65+
warped_image=dict(),
66+
)
67+
outputs = RegistrationSynQuick.output_spec()
68+
69+
for key, metadata in list(output_map.items()):
70+
for metakey, value in list(metadata.items()):
71+
assert getattr(outputs.traits()[key], metakey) == value

0 commit comments

Comments
 (0)