-
Notifications
You must be signed in to change notification settings - Fork 533
antsRegistrationSyNQuick (continuation of #1392 and #2347) #2453
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
Changes from 8 commits
83e0aa9
26aa5d5
ce5ba21
7af657a
d256a59
cc72fbe
66b28df
fbf24fa
16ed327
b1ea744
3403b0a
dbb84a3
5cd952f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,11 @@ | |
from ..base import TraitedSpec, File, Str, traits, InputMultiPath, isdefined | ||
from .base import ANTSCommand, ANTSCommandInputSpec | ||
|
||
try: | ||
LOCAL_DEFAULT_NUMBER_OF_THREADS = int(os.getenv("LOCAL_DEFAULT_NUMBER_OF_THREADS")) | ||
except TypeError: | ||
LOCAL_DEFAULT_NUMBER_OF_THREADS = 1 | ||
|
||
|
||
class ANTSInputSpec(ANTSCommandInputSpec): | ||
dimension = traits.Enum( | ||
|
@@ -1505,3 +1510,93 @@ def aggregate_outputs(self, runtime=None, needed_outputs=None): | |
stdout = runtime.stdout.split('\n') | ||
outputs.similarity = float(stdout[0]) | ||
return outputs | ||
|
||
|
||
class RegistrationSynQuickInputSpec(ANTSCommandInputSpec): | ||
dimension = traits.Enum(3, 2, argstr='-d %d', | ||
usedefault=True, desc='image dimension (2 or 3)') | ||
fixed_image = InputMultiPath(File(exists=True), mandatory=True, argstr='-f %s', | ||
desc='Fixed image or source image or reference image') | ||
moving_image = InputMultiPath(File(exists=True), mandatory=True, argstr='-m %s', | ||
desc='Moving image or target image') | ||
output_prefix = Str("transform", usedefault=True, argstr='-o %s', | ||
desc="A prefix that is prepended to all output files") | ||
num_threads = traits.Int(default_value=LOCAL_DEFAULT_NUMBER_OF_THREADS, usedefault=True, | ||
desc='Number of threads (default = 1)', argstr='-n %d') | ||
|
||
transform_type = traits.Enum('s', 't', 'r', 'a', 'sr', 'b', 'br', argstr='-t %s', | ||
desc=""" | ||
transform type | ||
t: translation | ||
r: rigid | ||
a: rigid + affine | ||
s: rigid + affine + deformable syn (default) | ||
sr: rigid + deformable syn | ||
b: rigid + affine + deformable b-spline syn | ||
br: rigid + deformable b-spline syn""", | ||
usedefault=True) | ||
|
||
use_histogram_matching = traits.Bool(False, argstr='-j %d', | ||
desc='use histogram matching') | ||
histogram_bins = traits.Int(default_value=32, argstr='-r %d', | ||
desc='histogram bins for mutual information in SyN stage \ | ||
(default = 32)') | ||
spline_distance = traits.Int(default_value=26, argstr='-s %d', | ||
desc='spline distance for deformable B-spline SyN transform \ | ||
(default = 26)') | ||
precision_type = traits.Enum('double', 'float', argstr='-p %s', | ||
desc='precision type (default = double)', usedefault=True) | ||
|
||
|
||
class RegistrationSynQuickOutputSpec(TraitedSpec): | ||
warped_image = File(exists=True, desc="Warped image") | ||
inverse_warped_image = File(exists=True, desc="Inverse warped image") | ||
out_matrix = File(exists=True, desc='Affine matrix') | ||
forward_warp_field = File(exists=True, desc='Forward warp field') | ||
inverse_warp_field = File(exists=True, desc='Inverse warp field') | ||
|
||
|
||
class RegistrationSynQuick(ANTSCommand): | ||
""" | ||
Reistration using a symmetric image normalization method (SyN). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Registration" (you're missing a "g"). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks :) |
||
You can read more in Avants et al.; Med Image Anal., 2008 | ||
(https://www.ncbi.nlm.nih.gov/pubmed/17659998). | ||
|
||
Examples | ||
-------- | ||
|
||
>>> import copy, pprint | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're not using these imports |
||
>>> from nipype.interfaces.ants import Registration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
>>> reg = RegistrationSynQuick() | ||
>>> reg.inputs.fixed_image = 'fixed1.nii' | ||
>>> reg.inputs.moving_image = 'moving1.nii' | ||
>>> reg.inputs.num_threads = 2 | ||
>>> reg.cmdline | ||
'antsRegistrationSynQuick.sh -d 3 -f fixed1.nii -m moving1.nii -n 2 -o transform -p d -t s' | ||
>>> reg.run() # doctest: +SKIP | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the help:
We should add a doctest to make sure that if It may be more trouble than it's worth to verify that the lists are of the same length. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it gives There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, then I think we want to change the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I pushed before reading this comment. But do you know this is correct syntax of command line? If yes, I can change it, but just wasn't sure what is the correct syntax There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. |
||
""" | ||
|
||
|
||
_cmd = 'antsRegistrationSynQuick.sh' | ||
input_spec = RegistrationSynQuickInputSpec | ||
output_spec = RegistrationSynQuickOutputSpec | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to avoid being affected by upstream changes, we should override def _num_threads_update(self):
"""antsRegistrationSynQuick.sh ignores environment variables, so override environment update""" |
||
def _format_arg(self, name, spec, value): | ||
if name == 'precision_type': | ||
return spec.argstr % value[0] | ||
return super(RegistrationSynQuick, self)._format_arg(name, spec, value) | ||
|
||
def _list_outputs(self): | ||
outputs = self.output_spec().get() | ||
outputs['warped_image'] = os.path.abspath(self.inputs.output_prefix + 'Warped.nii.gz') | ||
outputs['inverse_warped_image'] = os.path.abspath( | ||
self.inputs.output_prefix + 'InverseWarped.nii.gz') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be a little more concise, maybe we can do the following: out_base = os.path.abspath(self.inputs.output_prefix)
outputs['warped_image'] = out_base + 'Warped.nii.gz'
outputs['inverse_warped_image'] = out_base + 'InverseWarped.nii.gz' and so on... |
||
outputs['out_matrix'] = os.path.abspath(self.inputs.output_prefix + '0GenericAffine.mat') | ||
|
||
# todo in the case of linear transformation-only there won't be fields. is there a more elegant way to specify that? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What you have seems like a reasonable approach to me. |
||
if self.inputs.transform_type not in ('t', 'r', 'a'): | ||
outputs['forward_warp_field'] = os.path.abspath( | ||
self.inputs.output_prefix + '1Warp.nii.gz') | ||
outputs['inverse_warp_field'] = os.path.abspath( | ||
self.inputs.output_prefix + '1InverseWarp.nii.gz') | ||
return outputs |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT | ||
from __future__ import unicode_literals | ||
from ..registration import RegistrationSynQuick | ||
|
||
|
||
def test_RegistrationSynQuick_inputs(): | ||
input_map = dict( | ||
args=dict(argstr='%s', ), | ||
dimension=dict( | ||
argstr='-d %d', | ||
usedefault=True, | ||
), | ||
environ=dict( | ||
nohash=True, | ||
usedefault=True, | ||
), | ||
fixed_image=dict( | ||
argstr='-f %s', | ||
mandatory=True, | ||
), | ||
histogram_bins=dict(argstr='-r %d', ), | ||
ignore_exception=dict( | ||
deprecated='1.0.0', | ||
nohash=True, | ||
usedefault=True, | ||
), | ||
moving_image=dict( | ||
argstr='-m %s', | ||
mandatory=True, | ||
), | ||
num_threads=dict(argstr='-n %d', ), | ||
output_prefix=dict( | ||
argstr='-o %s', | ||
usedefault=True, | ||
), | ||
precision_type=dict( | ||
argstr='-p %s', | ||
usedefault=True, | ||
), | ||
spline_distance=dict(argstr='-s %d', ), | ||
terminal_output=dict( | ||
deprecated='1.0.0', | ||
nohash=True, | ||
), | ||
transform_type=dict( | ||
argstr='-t %s', | ||
usedefault=True, | ||
), | ||
use_histogram_matching=dict(argstr='-j %d', ), | ||
) | ||
inputs = RegistrationSynQuick.input_spec() | ||
|
||
for key, metadata in list(input_map.items()): | ||
for metakey, value in list(metadata.items()): | ||
assert getattr(inputs.traits()[key], metakey) == value | ||
def test_RegistrationSynQuick_outputs(): | ||
output_map = dict( | ||
forward_warp_field=dict(), | ||
inverse_warp_field=dict(), | ||
inverse_warped_image=dict(), | ||
out_matrix=dict(), | ||
warped_image=dict(), | ||
) | ||
outputs = RegistrationSynQuick.output_spec() | ||
|
||
for key, metadata in list(output_map.items()): | ||
for metakey, value in list(metadata.items()): | ||
assert getattr(outputs.traits()[key], metakey) == value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's just import
from .base import LOCAL_DEFAULT_NUMBER_OF_THREADS
.Also, I think in general this variable is kind of pointless, unless somebody's using a fork of nipype where it's defined as something other than 1. This isn't something that needs to be fixed in this PR, but just to flag it for others' attention.