@@ -219,37 +219,51 @@ class RegistrationInputSpec(ANTSCommandInputSpec):
219
219
dimension = traits .Enum (3 , 2 , argstr = '--dimensionality %d' ,
220
220
usedefault = True , desc = 'image dimension (2 or 3)' )
221
221
fixed_image = InputMultiPath (File (exists = True ), mandatory = True ,
222
- desc = 'image to apply transformation to (generally a coregistered functional)' )
222
+ desc = 'Image to which the moving_image should be transformed'
223
+ '(usually a structural image)' )
223
224
fixed_image_mask = File (
224
225
exists = True , argstr = '%s' , max_ver = '2.1.0' , xor = ['fixed_image_masks' ],
225
- desc = 'mask used to limit metric sampling region of the fixed image' )
226
+ desc = 'Mask used to limit metric sampling region of the fixed image'
227
+ 'in all stages' )
226
228
fixed_image_masks = InputMultiPath (
227
229
traits .Either ('NULL' , File (exists = True )), min_ver = '2.2.0' , xor = ['fixed_image_mask' ],
228
- desc = 'mask used to limit metric sampling region of the fixed image '
230
+ desc = 'Masks used to limit metric sampling region of the fixed image, defined per registration stage '
229
231
'(Use "NULL" to omit a mask at a given stage)' )
230
232
moving_image = InputMultiPath (File (exists = True ), mandatory = True ,
231
- desc = 'image to apply transformation to (generally a coregistered functional)' )
233
+ desc = 'Image that will be registered to the space of fixed_image. This is the'
234
+ 'image on which the transformations will be applied to' )
232
235
moving_image_mask = File (
233
236
exists = True , requires = ['fixed_image_mask' ], max_ver = '2.1.0' , xor = ['moving_image_masks' ],
234
- desc = 'mask used to limit metric sampling region of the moving image' )
237
+ desc = 'mask used to limit metric sampling region of the moving image'
238
+ 'in all stages' )
235
239
moving_image_masks = InputMultiPath (
236
240
traits .Either ('NULL' , File (exists = True )), min_ver = '2.2.0' , xor = ['moving_image_mask' ],
237
- desc = 'mask used to limit metric sampling region of the moving image '
241
+ desc = 'Masks used to limit metric sampling region of the moving image, defined per registration stage '
238
242
'(Use "NULL" to omit a mask at a given stage)' )
239
243
240
244
save_state = File (argstr = '--save-state %s' , exists = False ,
241
245
desc = 'Filename for saving the internal restorable state of the registration' )
242
246
restore_state = File (argstr = '--restore-state %s' , exists = True ,
243
247
desc = 'Filename for restoring the internal restorable state of the registration' )
244
248
245
- initial_moving_transform = InputMultiPath (argstr = '%s' , exists = True , desc = '' ,
249
+ initial_moving_transform = InputMultiPath (argstr = '%s' ,
250
+ exists = True ,
251
+ desc = 'A transform or a list of transforms that should be applied'
252
+ 'before the registration begins. Note that, when a list is given,'
253
+ 'the transformations are applied in reverse order.' ,
246
254
xor = ['initial_moving_transform_com' ])
247
- invert_initial_moving_transform = InputMultiPath (traits .Bool (), requires = ["initial_moving_transform" ],
248
- desc = '' , xor = ['initial_moving_transform_com' ])
255
+ invert_initial_moving_transform = InputMultiPath (traits .Bool (),
256
+ requires = ["initial_moving_transform" ],
257
+ desc = 'One boolean or a list of booleans that indicate'
258
+ 'whether the inverse(s) of the transform(s) defined'
259
+ 'in initial_moving_transform should be used.' ,
260
+ xor = ['initial_moving_transform_com' ])
249
261
250
262
initial_moving_transform_com = traits .Enum (0 , 1 , 2 , argstr = '%s' ,
251
263
default = 0 , xor = ['initial_moving_transform' ],
252
- desc = "Use center of mass for moving transform" )
264
+ desc = "Align the moving_image nad fixed_image befor registration using"
265
+ "the geometric center of the images (=0), the image intensities (=1),"
266
+ "or the origin of the images (=2)" )
253
267
metric_item_trait = traits .Enum ("CC" , "MeanSquares" , "Demons" , "GC" , "MI" ,
254
268
"Mattes" )
255
269
metric_stage_trait = traits .Either (
@@ -291,7 +305,8 @@ class RegistrationInputSpec(ANTSCommandInputSpec):
291
305
use_estimate_learning_rate_once = traits .List (traits .Bool (), desc = '' )
292
306
use_histogram_matching = traits .Either (
293
307
traits .Bool , traits .List (traits .Bool (argstr = '%s' )),
294
- default = True , usedefault = True )
308
+ default = True , usedefault = True ,
309
+ desc = 'Histogram match the images before registration.' )
295
310
interpolation = traits .Enum (
296
311
'Linear' , 'NearestNeighbor' , 'CosineWindowedSinc' , 'WelchWindowedSinc' ,
297
312
'HammingWindowedSinc' , 'LanczosWindowedSinc' , 'BSpline' , 'MultiLabel' , 'Gaussian' ,
@@ -421,8 +436,57 @@ class RegistrationOutputSpec(TraitedSpec):
421
436
class Registration (ANTSCommand ):
422
437
423
438
"""
439
+ `antsRegister <http://stnava.github.io/ANTs/>`_ registers a 'moving_image' to a 'fixed_image',
440
+ using a predefined (sequence of) cost function(s) and transformation operattions.
441
+ The cost function is defined using one or more 'metrics', specifically
442
+ local cross-correlation ('CC'), Mean Squares ('MeanSquares'), Demons ('Demons'),
443
+ global correlation ('GC'), or Mutual Information ('Mattes' or 'MI').
444
+
445
+ ANTS can use both linear ('Translation, 'Rigid', 'Affine', 'CompositeAffine',
446
+ or 'Translation') and non-linear transformations ('BSpline', 'GaussianDisplacementField',
447
+ 'TimeVaryingVelocityField', 'TimeVaryingBSplineVelocityField', 'SyN', 'BSplineSyN',
448
+ 'Exponential', or 'BSplineExponential'). Usually, registration is done in multiple
449
+ *stages*. For example first an Affine, then a Rigid, and ultimately a non-linear
450
+ (Syn)-transformation.
451
+
452
+ antsRegistration can be initialized using one ore more transforms from moving_image
453
+ to fixed_image with the 'initial_moving_transform'-input. For example, when you
454
+ already have a warpfield that corrects for geometrical distortions in an EPI (functional) image,
455
+ that you want to apply before an Affine registration to a structural image.
456
+ You could put this transform into 'intial_moving_transform'.
457
+
458
+ The Registration-interface can output the resulting transform(s) that map moving_image to
459
+ fixed_image in a single file as a 'composite_transform' (if write_composite_transform
460
+ is set to True), or a list of transforms as 'forwards_transforms'. It can also output
461
+ inverse transforms (from fixed_image to moving_image) in a similar fashion using
462
+ inverse_composite_transform. Note that the order of forward_transforms is in 'natural'
463
+ order: the first element should be applied first, the last element should be applied last.
464
+
465
+ Note, however, that ANTS tools always apply lists of transformations in reverse order (the last
466
+ transformation in the list is applied first). Therefore, if the output forward_transforms
467
+ is a list, one can not directly feed it into, for example, ants.ApplyTransforms. To
468
+ make ants.ApplyTransforms apply the transformations in the same order as ants.Registration,
469
+ you have to provide the list of transformations in reverse order from forward_transforms.
470
+ reverse_forward_transforms outputs forward_transforms in reverse order and can be used for t
471
+ this purpose. Note also that, because composite_transform is always only a single file, this
472
+ output is preferred for most use-cases.
473
+
474
+ More information can be found in the `ANTS
475
+ manual<https://sourceforge.net/projects/advants/files/Documentation/ants.pdf/download>`.
476
+
477
+ See below for some useful examples.
478
+
424
479
Examples
425
480
--------
481
+
482
+ Set up a Registation node with some default settings. This Node registers
483
+ 'fixed1.nii' to 'moving1.nii' by first fitting a linear 'Affine' transformation, and
484
+ then a non-linear 'SyN' transformation, both using the Mutual Information-cost
485
+ metric.
486
+
487
+ The registration is initailized by first applying the (linear) transform
488
+ trans.mat.
489
+
426
490
>>> import copy, pprint
427
491
>>> from nipype.interfaces.ants import Registration
428
492
>>> reg = Registration()
@@ -461,6 +525,8 @@ class Registration(ANTSCommand):
461
525
--use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
462
526
>>> reg.run() # doctest: +SKIP
463
527
528
+ Same as reg1, but first invert the initial transform ('trans.mat') before applying it.
529
+
464
530
>>> reg.inputs.invert_initial_moving_transform = True
465
531
>>> reg1 = copy.deepcopy(reg)
466
532
>>> reg1.inputs.winsorize_lower_quantile = 0.025
@@ -475,6 +541,9 @@ class Registration(ANTSCommand):
475
541
--use-histogram-matching 1 --winsorize-image-intensities [ 0.025, 1.0 ] --write-composite-transform 1'
476
542
>>> reg1.run() # doctest: +SKIP
477
543
544
+ Clip extremely high intensity data points using winsorize_upper_quantile. All data points
545
+ higher than the 0.975 quantile are set to the value of the 0.975 quantile.
546
+
478
547
>>> reg2 = copy.deepcopy(reg)
479
548
>>> reg2.inputs.winsorize_upper_quantile = 0.975
480
549
>>> reg2.cmdline # doctest: +ALLOW_UNICODE
@@ -487,6 +556,10 @@ class Registration(ANTSCommand):
487
556
--smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 \
488
557
--use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 0.975 ] --write-composite-transform 1'
489
558
559
+ Clip extremely low intensity data points using winsorize_lower_quantile. All data points
560
+ lower than the 0.025 quantile are set to the original value at the 0.025 quantile.
561
+
562
+
490
563
>>> reg3 = copy.deepcopy(reg)
491
564
>>> reg3.inputs.winsorize_lower_quantile = 0.025
492
565
>>> reg3.inputs.winsorize_upper_quantile = 0.975
@@ -500,6 +573,8 @@ class Registration(ANTSCommand):
500
573
--smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 \
501
574
--use-histogram-matching 1 --winsorize-image-intensities [ 0.025, 0.975 ] --write-composite-transform 1'
502
575
576
+ Use float instead of double for computations (saves memory usage)
577
+
503
578
>>> reg3a = copy.deepcopy(reg)
504
579
>>> reg3a.inputs.float = True
505
580
>>> reg3a.cmdline # doctest: +ALLOW_UNICODE
@@ -513,6 +588,8 @@ class Registration(ANTSCommand):
513
588
--use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] \
514
589
--write-composite-transform 1'
515
590
591
+ Force to use double instead of float for computations (more precision and memory usage).
592
+
516
593
>>> reg3b = copy.deepcopy(reg)
517
594
>>> reg3b.inputs.float = False
518
595
>>> reg3b.cmdline # doctest: +ALLOW_UNICODE
@@ -526,6 +603,9 @@ class Registration(ANTSCommand):
526
603
--use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] \
527
604
--write-composite-transform 1'
528
605
606
+ 'collapse_output_transforms' can be used to put all transformation in a single 'composite_transform'-
607
+ file. Note that forward_transforms will now be an empty list.
608
+
529
609
>>> # Test collapse transforms flag
530
610
>>> reg4 = copy.deepcopy(reg)
531
611
>>> reg4.inputs.save_state = 'trans.mat'
@@ -554,6 +634,7 @@ class Registration(ANTSCommand):
554
634
--use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] \
555
635
--write-composite-transform 1'
556
636
637
+
557
638
>>> # Test collapse transforms flag
558
639
>>> reg4b = copy.deepcopy(reg4)
559
640
>>> reg4b.inputs.write_composite_transform = False
@@ -567,7 +648,7 @@ class Registration(ANTSCommand):
567
648
'inverse_warped_image': <undefined>,
568
649
'reverse_invert_flags': [True, False],
569
650
'reverse_transforms': ['.../nipype/testing/data/output_0GenericAffine.mat', \
570
- '.../nipype/testing/data/output_1InverseWarp.nii.gz'],
651
+ '.../nipype/testing/data/output_1InverseWarp.nii.gz'],
571
652
'save_state': '.../nipype/testing/data/trans.mat',
572
653
'warped_image': '.../nipype/testing/data/output_warped_image.nii.gz'}
573
654
>>> reg4b.aggregate_outputs() # doctest: +SKIP
@@ -582,6 +663,14 @@ class Registration(ANTSCommand):
582
663
--use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] \
583
664
--write-composite-transform 0'
584
665
666
+ One can use multiple similarity metrics in a single registration stage.The Node below first
667
+ performs a linear registation using only the Mutual Information ('Mattes')-metric.
668
+ In a second stage, it performs a non-linear registration ('Syn') using both a
669
+ Mutual Information and a local cross-correlation ('CC')-metric. Both metrics are weighted
670
+ equally ('metric_weight' is .5 for both). The Mutual Information- metric uses 32 bins.
671
+ The local cross-correlations (correlations between every voxel's neighborhoods) is computed
672
+ with a radius of 4.
673
+
585
674
>>> # Test multiple metrics per stage
586
675
>>> reg5 = copy.deepcopy(reg)
587
676
>>> reg5.inputs.fixed_image = 'fixed1.nii'
@@ -602,7 +691,13 @@ class Registration(ANTSCommand):
602
691
--smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 \
603
692
--use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
604
693
605
- >>> # Test multiple inputs
694
+ ANTS Registration can also use multiple modalities to perform the registration. Here it is assumed
695
+ that fixed1.nii and fixed2.nii are in the same space, and so are moving1.nii and
696
+ moving2.nii. First, a linear registration is performed matching fixed1.nii to moving1.nii,
697
+ then a non-linear registration is performed to match fixed2.nii to moving2.nii, starting from
698
+ the transformation of the first step.
699
+
700
+ >>> # Test multiple inputS
606
701
>>> reg6 = copy.deepcopy(reg5)
607
702
>>> reg6.inputs.fixed_image = ['fixed1.nii', 'fixed2.nii']
608
703
>>> reg6.inputs.moving_image = ['moving1.nii', 'moving2.nii']
@@ -617,6 +712,8 @@ class Registration(ANTSCommand):
617
712
--smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 \
618
713
--use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
619
714
715
+ Different methods can be used for the interpolation when applying transformations.
716
+
620
717
>>> # Test Interpolation Parameters (BSpline)
621
718
>>> reg7a = copy.deepcopy(reg)
622
719
>>> reg7a.inputs.interpolation = 'BSpline'
@@ -646,6 +743,8 @@ class Registration(ANTSCommand):
646
743
--use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] \
647
744
--write-composite-transform 1'
648
745
746
+ BSplineSyN non-linear registration with custom parameters.
747
+
649
748
>>> # Test Extended Transform Parameters
650
749
>>> reg8 = copy.deepcopy(reg)
651
750
>>> reg8.inputs.transforms = ['Affine', 'BSplineSyN']
@@ -660,6 +759,8 @@ class Registration(ANTSCommand):
660
759
--smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 \
661
760
--use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
662
761
762
+ Mask the fixed image in the second stage of the registration (but not the first).
763
+
663
764
>>> # Test masking
664
765
>>> reg9 = copy.deepcopy(reg)
665
766
>>> reg9.inputs.fixed_image_masks = ['NULL', 'fixed1.nii']
@@ -674,6 +775,10 @@ class Registration(ANTSCommand):
674
775
--use-estimate-learning-rate-once 1 --use-histogram-matching 1 --masks [ fixed1.nii, NULL ] \
675
776
--winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
676
777
778
+ Here we use both a warpfield and a linear transformation, before registration commences. Note that
779
+ the first transformation that needs to be applied ('ants_Warp.nii.gz') is last in the list of
780
+ 'initial_moving_transform'.
781
+
677
782
>>> # Test initialization with multiple transforms matrices (e.g., unwarp and affine transform)
678
783
>>> reg10 = copy.deepcopy(reg)
679
784
>>> reg10.inputs.initial_moving_transform = ['func_to_struct.mat', 'ants_Warp.nii.gz']
0 commit comments