@@ -26,6 +26,26 @@ class ANTSInputSpec(ANTSCommandInputSpec):
26
26
desc = ('image to apply transformation to (generally a coregistered '
27
27
'functional)' ))
28
28
29
+ # Not all metrics are appropriate for all modalities. Also, not all metrics
30
+ # are efficeint or appropriate at all resolution levels, Some metrics perform
31
+ # well for gross global registraiton, but do poorly for small changes (i.e.
32
+ # Mattes), and some metrics do well for small changes but don't work well for
33
+ # gross level changes (i.e. 'CC').
34
+ #
35
+ # This is a two stage registration. in the first stage
36
+ # [ 'Mattes', .................]
37
+ # ^^^^^^ <- First stage
38
+ # Do a unimodal registration of the first elements of the fixed/moving input
39
+ # list use the"CC" as the metric.
40
+ #
41
+ # In the second stage
42
+ # [ ....., ['Mattes','CC'] ]
43
+ # ^^^^^^^^^^^^^^^ <- Second stage
44
+ # Do a multi-modal registration where the first elements of fixed/moving
45
+ # input list use 'CC' metric and that is added to 'Mattes' metric result of
46
+ # the second elements of the fixed/moving input.
47
+ #
48
+ # Cost = Sum_i ( metricweight[i] Metric_i ( fixedimage[i], movingimage[i]) )
29
49
metric = traits .List (traits .Enum ('CC' , 'MI' , 'SMI' , 'PR' , 'SSD' ,
30
50
'MSQ' , 'PSE' ), mandatory = True , desc = '' )
31
51
@@ -438,13 +458,15 @@ class Registration(ANTSCommand):
438
458
439
459
>>> # Test multiple metrics per stage
440
460
>>> reg5 = copy.deepcopy(reg)
441
- >>> reg5.inputs.metric = ['CC', ['CC', 'Mattes']]
442
- >>> reg5.inputs.metric_weight = [1, [.5]*2]
443
- >>> reg5.inputs.radius_or_number_of_bins = [4, [32]*2]
461
+ >>> reg5.inputs.fixed_image = [ 'fixed1.nii', 'fixed2.nii' ]
462
+ >>> reg5.inputs.moving_image = [ 'moving1.nii', 'moving2.nii' ]
463
+ >>> reg5.inputs.metric = ['Mattes', ['Mattes', 'CC']]
464
+ >>> reg5.inputs.metric_weight = [1, [.5,.5]]
465
+ >>> reg5.inputs.radius_or_number_of_bins = [32, [32,4] ]
444
466
>>> reg5.inputs.sampling_strategy = ['Random', None] # use default strategy in second stage
445
467
>>> reg5.inputs.sampling_percentage = [0.05, [0.05, 0.10]]
446
468
>>> reg5.cmdline
447
- 'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --initialize-transforms-per-stage 0 --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --restore-state trans.mat --save-state trans.mat --transform Affine[ 2.0 ] --metric CC [ fixed1.nii, moving1.nii, 1, 4 , Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric CC [ fixed1.nii, moving1.nii, 0.5, 32, None, 0.05 ] --metric Mattes[ fixed1 .nii, moving1 .nii, 0.5, 32 , None, 0.1 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
469
+ 'antsRegistration --collapse-output-transforms 0 --dimensionality 3 --initial-moving-transform [ trans.mat, 1 ] --initialize-transforms-per-stage 0 --interpolation Linear --output [ output_, output_warped_image.nii.gz ] --restore-state trans.mat --save-state trans.mat --transform Affine[ 2.0 ] --metric Mattes [ fixed1.nii, moving1.nii, 1, 32 , Random, 0.05 ] --convergence [ 1500x200, 1e-08, 20 ] --smoothing-sigmas 1.0x0.0vox --shrink-factors 2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --transform SyN[ 0.25, 3.0, 0.0 ] --metric Mattes [ fixed1.nii, moving1.nii, 0.5, 32, None, 0.05 ] --metric CC[ fixed2 .nii, moving2 .nii, 0.5, 4 , None, 0.1 ] --convergence [ 100x50x30, 1e-09, 20 ] --smoothing-sigmas 2.0x1.0x0.0vox --shrink-factors 3x2x1 --use-estimate-learning-rate-once 1 --use-histogram-matching 1 --winsorize-image-intensities [ 0.0, 1.0 ] --write-composite-transform 1'
448
470
"""
449
471
DEF_SAMPLING_STRATEGY = 'None'
450
472
"""The default sampling strategy argument."""
@@ -464,14 +486,12 @@ def _formatMetric(self, index):
464
486
----------
465
487
index: the stage index
466
488
"""
467
- # The common fixed image.
468
- fixed = self .inputs .fixed_image [0 ]
469
- # The common moving image.
470
- moving = self .inputs .moving_image [0 ]
471
489
# The metric name input for the current stage.
472
490
name_input = self .inputs .metric [index ]
473
491
# The stage-specific input dictionary.
474
492
stage_inputs = dict (
493
+ fixed_image = self .inputs .fixed_image [0 ],
494
+ moving_image = self .inputs .moving_image [0 ],
475
495
metric = name_input ,
476
496
weight = self .inputs .metric_weight [index ],
477
497
radius_or_bins = self .inputs .radius_or_number_of_bins [index ],
@@ -497,19 +517,32 @@ def _formatMetric(self, index):
497
517
if isinstance (name_input , list ):
498
518
items = stage_inputs .items ()
499
519
indexes = range (0 , len (name_input ))
500
- # dict-comprehension only works with python 2.7 and up
501
- # specs = [{k: v[i] for k, v in items} for i in indexes]
502
- specs = [dict ([(k , v [i ]) for k , v in items ]) for i in indexes ]
520
+ specs = list ()
521
+ for i in indexes :
522
+ temp = dict ([(k , v [i ]) for k , v in items ])
523
+ if i > len ( self .inputs .fixed_image ):
524
+ temp ["fixed_image" ] = self .inputs .fixed_image [0 ]
525
+ else :
526
+ temp ["fixed_image" ] = self .inputs .fixed_image [i ]
527
+
528
+ if i > len ( self .inputs .moving_image ):
529
+ temp ["moving_image" ] = self .inputs .moving_image [0 ]
530
+ else :
531
+ temp ["moving_image" ] = self .inputs .moving_image [i ]
532
+
533
+ specs .append ( temp )
503
534
else :
504
535
specs = [stage_inputs ]
505
536
506
537
# Format the --metric command line metric arguments, one per
507
538
# specification.
508
- return [self ._formatMetricArgument (fixed , moving , ** spec ) for spec in specs ]
539
+ return [self ._formatMetricArgument (** spec ) for spec in specs ]
509
540
510
- def _formatMetricArgument (self , fixed , moving , ** kwargs ):
541
+ def _formatMetricArgument (self , ** kwargs ):
511
542
retval = '%s[ %s, %s, %g, %d' % (kwargs ['metric' ],
512
- fixed , moving , kwargs ['weight' ],
543
+ kwargs ['fixed_image' ],
544
+ kwargs ['moving_image' ],
545
+ kwargs ['weight' ],
513
546
kwargs ['radius_or_bins' ])
514
547
515
548
# The optional sampling strategy.
@@ -548,17 +581,17 @@ def _formatRegistration(self):
548
581
retval .append ('--metric %s' % metric )
549
582
retval .append ('--convergence %s' % self ._formatConvergence (ii ))
550
583
if isdefined (self .inputs .sigma_units ):
551
- retval .append ('--smoothing-sigmas %s%s' %
584
+ retval .append ('--smoothing-sigmas %s%s' %
552
585
(self ._antsJoinList (self .inputs .smoothing_sigmas [
553
586
ii ]),
554
587
self .inputs .sigma_units [ii ]))
555
588
else :
556
- retval .append ('--smoothing-sigmas %s' %
589
+ retval .append ('--smoothing-sigmas %s' %
557
590
self ._antsJoinList (self .inputs .smoothing_sigmas [ii ]))
558
- retval .append ('--shrink-factors %s' %
591
+ retval .append ('--shrink-factors %s' %
559
592
self ._antsJoinList (self .inputs .shrink_factors [ii ]))
560
593
if isdefined (self .inputs .use_estimate_learning_rate_once ):
561
- retval .append ('--use-estimate-learning-rate-once %d' %
594
+ retval .append ('--use-estimate-learning-rate-once %d' %
562
595
self .inputs .use_estimate_learning_rate_once [ii ])
563
596
if isdefined (self .inputs .use_histogram_matching ):
564
597
# use_histogram_matching is either a common flag for all transforms
0 commit comments