@@ -26,6 +26,26 @@ class ANTSInputSpec(ANTSCommandInputSpec):
2626 desc = ('image to apply transformation to (generally a coregistered '
2727 'functional)' ))
2828
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]) )
2949 metric = traits .List (traits .Enum ('CC' , 'MI' , 'SMI' , 'PR' , 'SSD' ,
3050 'MSQ' , 'PSE' ), mandatory = True , desc = '' )
3151
@@ -440,13 +460,15 @@ class Registration(ANTSCommand):
440460
441461 >>> # Test multiple metrics per stage
442462 >>> reg5 = copy.deepcopy(reg)
443- >>> reg5.inputs.metric = ['CC', ['CC', 'Mattes']]
444- >>> reg5.inputs.metric_weight = [1, [.5]*2]
445- >>> reg5.inputs.radius_or_number_of_bins = [4, [32]*2]
463+ >>> reg5.inputs.fixed_image = [ 'fixed1.nii', 'fixed2.nii' ]
464+ >>> reg5.inputs.moving_image = [ 'moving1.nii', 'moving2.nii' ]
465+ >>> reg5.inputs.metric = ['Mattes', ['Mattes', 'CC']]
466+ >>> reg5.inputs.metric_weight = [1, [.5,.5]]
467+ >>> reg5.inputs.radius_or_number_of_bins = [32, [32,4] ]
446468 >>> reg5.inputs.sampling_strategy = ['Random', None] # use default strategy in second stage
447469 >>> reg5.inputs.sampling_percentage = [0.05, [0.05, 0.10]]
448470 >>> reg5.cmdline
449- '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'
471+ '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'
450472 """
451473 DEF_SAMPLING_STRATEGY = 'None'
452474 """The default sampling strategy argument."""
@@ -466,14 +488,12 @@ def _formatMetric(self, index):
466488 ----------
467489 index: the stage index
468490 """
469- # The common fixed image.
470- fixed = self .inputs .fixed_image [0 ]
471- # The common moving image.
472- moving = self .inputs .moving_image [0 ]
473491 # The metric name input for the current stage.
474492 name_input = self .inputs .metric [index ]
475493 # The stage-specific input dictionary.
476494 stage_inputs = dict (
495+ fixed_image = self .inputs .fixed_image [0 ],
496+ moving_image = self .inputs .moving_image [0 ],
477497 metric = name_input ,
478498 weight = self .inputs .metric_weight [index ],
479499 radius_or_bins = self .inputs .radius_or_number_of_bins [index ],
@@ -499,19 +519,32 @@ def _formatMetric(self, index):
499519 if isinstance (name_input , list ):
500520 items = stage_inputs .items ()
501521 indexes = range (0 , len (name_input ))
502- # dict-comprehension only works with python 2.7 and up
503- #specs = [{k: v[i] for k, v in items} for i in indexes]
504- specs = [dict ([(k , v [i ]) for k , v in items ]) for i in indexes ]
522+ specs = list ()
523+ for i in indexes :
524+ temp = dict ([(k , v [i ]) for k , v in items ])
525+ if i > len ( self .inputs .fixed_image ):
526+ temp ["fixed_image" ] = self .inputs .fixed_image [0 ]
527+ else :
528+ temp ["fixed_image" ] = self .inputs .fixed_image [i ]
529+
530+ if i > len ( self .inputs .moving_image ):
531+ temp ["moving_image" ] = self .inputs .moving_image [0 ]
532+ else :
533+ temp ["moving_image" ] = self .inputs .moving_image [i ]
534+
535+ specs .append ( temp )
505536 else :
506537 specs = [stage_inputs ]
507538
508539 # Format the --metric command line metric arguments, one per
509540 # specification.
510- return [self ._formatMetricArgument (fixed , moving , ** spec ) for spec in specs ]
541+ return [self ._formatMetricArgument (** spec ) for spec in specs ]
511542
512- def _formatMetricArgument (self , fixed , moving , ** kwargs ):
543+ def _formatMetricArgument (self , ** kwargs ):
513544 retval = '%s[ %s, %s, %g, %d' % (kwargs ['metric' ],
514- fixed , moving , kwargs ['weight' ],
545+ kwargs ['fixed_image' ],
546+ kwargs ['moving_image' ],
547+ kwargs ['weight' ],
515548 kwargs ['radius_or_bins' ])
516549
517550 # The optional sampling strategy.
0 commit comments