Run ANTs in Slicer Python Interactor

@simonoxen, @lassoan

Hi all,

I tried Ants extension in Slicer, the registration worked very good. However, I want to write a script and run ANTs from Slicer Python interactor. I am able to import antsRegistration, but can’t find a way to input all the parameters.

The following command generates syntax error. VolumeNodes fix, move, outTrans, outVolume can be defined and used successfully.
antsRegistration --dimensionality 3 --use-histogram-matching 1 --winsorize-image-intensities [0.005,0.995] --float 0 --verbose 1 --interpolation LanczosWindowedSinc --output [outTrans,outVolume] --write-composite-transform 1 --collapse-output-transforms 1 --initial-moving-transform [fix,move,1] --transform Rigid[0.1] --metric MI[fix,move,0.25] --convergence [1000x500x250,1e-6,10] --smoothing-sigmas 3x2x1vox --shrink-factors 8x4x2

Thank you.

Hi, the logic from antsRegistration (scripted) module calls the antsRegistrationCLI module. You can run a registration and see in the log file how the command to antsRegistrationCLI is generated.

You could also mimic how the scripted module works from python. You can see a small test in the module to see how to do this.

Hi Simon,

Thank you for your reply. The code I posted is actually copied from the log file of a successful registration, but when entered in Slicer python interactor it not works. The antsRegistrationCLI module you mentioned, did you mean slicer.cli.run(antsCommand (“parameters here”))? This is not working neither. Could you please provide an example code for testing? Really appreciate your help!

how do you enter it?

no, see SlicerANTs/antsRegistration.py at master · netstim/SlicerANTs · GitHub on how the CLI is run.

Thank you for the GitHub example, I finally got it to work! Last question, when I run the CLI (antsRegistrationLogic().process()), is there a way to add this argument “wait_for_completion=True”?

I include two steps, ANTs registration and feature extraction in one function. I found that the extraction get no data because it starts before registration complete.

Thanks.

Right now, from process(), this is hardcoded. You can specify the CLI params and then run the CLI module with wait_for_completion=True.

I couldn’t find any CLI params can change “wait_for_completion” status, looks like slicer.cli.run was implemented inside “antsRegistrationLogic().process()”, how could you control it from outside? I changed it to true in the source code and it worked fine, but I wish to find a better way so others can replicate the method. Thank you.

yes, as mentioned, this is hardcoded. You can run slicer.cli.run from python interactor, specifying the cli params.

Hi @simonoxen and @hotsen ,

Could you please provide a sample code to run the registration from Python interactor? How do we pass the arguments to the process() function?

I am passing the following parameters,

sampleParams = {'stages': [{'transformParameters': {'transform': 'Rigid', 'settings': '0.1'}, 'metrics': [{'type': 'MI', 'fixed': '/media/srivathsan/Vol_011_20220119_144127_3D.nii.gz', 'moving': '/media/srivathsan/Vol_005_20220119_143403_3D.nii.gz', 'settings': '1,32,Regular,0.25'}], 'levels': {'steps': [{'convergence': 1000, 'smoothingSigmas': 4, 'shrinkFactors': 12}, {'convergence': 500, 'smoothingSigmas': 3, 'shrinkFactors': 8}, {'convergence': 250, 'smoothingSigmas': 2, 'shrinkFactors': 4}, {'convergence': 0, 'smoothingSigmas': 1, 'shrinkFactors': 2}], 'smoothingSigmasUnit': 'vox', 'convergenceThreshold': 6, 'convergenceWindowSize': 10}, 'masks': {'fixed': None, 'moving': None}}, {'transformParameters': {'transform': 'Affine', 'settings': '0.1'}, 'metrics': [{'type': 'MI', 'fixed': None, 'moving': None, 'settings': '1,32,Regular,0.25'}], 'levels': {'steps': [{'convergence': 1000, 'smoothingSigmas': 4, 'shrinkFactors': 12}, {'convergence': 500, 'smoothingSigmas': 3, 'shrinkFactors': 8}, {'convergence': 250, 'smoothingSigmas': 2, 'shrinkFactors': 4}, {'convergence': 0, 'smoothingSigmas': 1, 'shrinkFactors': 2}], 'smoothingSigmasUnit': 'vox', 'convergenceThreshold': 6, 'convergenceWindowSize': 10}, 'masks': {'fixed': None, 'moving': None}}, {'transformParameters': {'transform': 'SyN', 'settings': '0.1,3,0'}, 'metrics': [{'type': 'MI', 'fixed': None, 'moving': None, 'settings': '1,32'}], 'levels': {'steps': [{'convergence': 100, 'smoothingSigmas': 5, 'shrinkFactors': 10}, {'convergence': 100, 'smoothingSigmas': 3, 'shrinkFactors': 6}, {'convergence': 70, 'smoothingSigmas': 2, 'shrinkFactors': 4}, {'convergence': 50, 'smoothingSigmas': 1, 'shrinkFactors': 2}, {'convergence': 0, 'smoothingSigmas': 0, 'shrinkFactors': 1}], 'smoothingSigmasUnit': 'vox', 'convergenceThreshold': 6, 'convergenceWindowSize': 10}, 'masks': {'fixed': None, 'moving': None}}], 'outputSettings': {'transform': None, 'volume': '/media/srivathsan/antsCli/cliOutput.nii.gz', 'interpolation': 'Linear'}, 'initialTransformSettings': {'initializationFeature': 1}, 'generalSettings': {'dimensionality': 3, 'histogramMatching': 0, 'winsorizeImageIntensities': [0.005, 0.995], 'computationPrecision': 'float'}}

import antsRegistration
antsRegistration.antsRegistrationLogic().process(sampleParams)

But it generates the following error,

Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: process() missing 1 required positional argument: 'outputSettings'

Thank you.

I was passing the wrong arguments. I tried to pass the arguments as in the GitHub example.

antsRegistration.antsRegistrationLogic().process([{'transformParameters': {'transform': 'Rigid', 'settings': '0.1'}, 'metrics': [{'type': 'MI', 'fixed': '/tmp/Slicer-srivathsan/vtkMRMLScalarVolumeNode1.nrrd', 'moving': '/tmp/Slicer-srivathsan/vtkMRMLScalarVolumeNode2.nrrd', 'settings': '1,32,Regular,0.25'}], 'levels': {'steps': [{'convergence': 1000, 'smoothingSigmas': 4, 'shrinkFactors': 12}, {'convergence': 500, 'smoothingSigmas': 3, 'shrinkFactors': 8}, {'convergence': 250, 'smoothingSigmas': 2, 'shrinkFactors': 4}, {'convergence': 0, 'smoothingSigmas': 1, 'shrinkFactors': 2}], 'smoothingSigmasUnit': 'vox', 'convergenceThreshold': 6, 'convergenceWindowSize': 10}, 'masks': {'fixed': None, 'moving': None}}, {'transformParameters': {'transform': 'Affine', 'settings': '0.1'}, 'metrics': [{'type': 'MI', 'fixed': None, 'moving': None, 'settings': '1,32,Regular,0.25'}], 'levels': {'steps': [{'convergence': 1000, 'smoothingSigmas': 4, 'shrinkFactors': 12}, {'convergence': 500, 'smoothingSigmas': 3, 'shrinkFactors': 8}, {'convergence': 250, 'smoothingSigmas': 2, 'shrinkFactors': 4}, {'convergence': 0, 'smoothingSigmas': 1, 'shrinkFactors': 2}], 'smoothingSigmasUnit': 'vox', 'convergenceThreshold': 6, 'convergenceWindowSize': 10}, 'masks': {'fixed': None, 'moving': None}}, {'transformParameters': {'transform': 'SyN', 'settings': '0.1,3,0'}, 'metrics': [{'type': 'MI', 'fixed': None, 'moving': None, 'settings': '1,32'}], 'levels': {'steps': [{'convergence': 100, 'smoothingSigmas': 5, 'shrinkFactors': 10}, {'convergence': 100, 'smoothingSigmas': 3, 'shrinkFactors': 6}, {'convergence': 70, 'smoothingSigmas': 2, 'shrinkFactors': 4}, {'convergence': 50, 'smoothingSigmas': 1, 'shrinkFactors': 2}, {'convergence': 0, 'smoothingSigmas': 0, 'shrinkFactors': 1}], 'smoothingSigmasUnit': 'vox', 'convergenceThreshold': 6, 'convergenceWindowSize': 10}, 'masks': {'fixed': None, 'moving': None}}], {'transform': None, 'volume': '/tmp/Slicer-srivathsan/BFCDJ_vtkMRMLScalarVolumeNode3.nrrd', 'interpolation': 'Linear'}, {'initializationFeature': 1}, {'dimensionality': 3, 'histogramMatching': 0, 'winsorizeImageIntensities': [0.005, 0.995], 'computationPrecision': 'float'})

Though it fixed the previous issue, now I get the following error,
Traceback (most recent call last):

  File "<console>", line 1, in <module>
  File "/home/srivathsan/Slicer-4.13.0-2022-04-17-linux-amd64/NA-MIC/Extensions-30785/SlicerANTs/lib/Slicer-4.13/qt-scripted-modules/antsRegistration.py", line 517, in process
    self.getOrSetCLIParam(stages[0]['metrics'][0]['fixed']) # put in first position. will be used as reference in cli
  File "/home/srivathsan/Slicer-4.13.0-2022-04-17-linux-amd64/NA-MIC/Extensions-30785/SlicerANTs/lib/Slicer-4.13/qt-scripted-modules/antsRegistration.py", line 599, in getOrSetCLIParam
    nodeID = mrmlNode.GetID()
AttributeError: 'str' object has no attribute 'GetID'

Appreciate any help on this.

You need to provide a node object (you provided a filename). You can load a volume and get the node object using slicer.util.loadVolume.

1 Like

Hi Vathsan,
Sorry for the late reply. Just call
antsRegistration.antsRegistrationLogic().process(stages=stages, outputSettings=outputSettings, initialTransformSettings=initialTransformSettings, generalSettings=generalSettings)
and feed all your settings.
For example,
generalSettings = {
‘dimensionality’ : 3,
‘histogramMatching’ : True,
‘winsorizeImageIntensities’ : [0.005,0.995],
‘computationPrecision’ : ‘double’
}

I think the error you got is because you pass a string instead of slicer volume node. Try to create one using Volume = slicer.vtkMRMLScalarVolumeNode() or get an existing one using Volume = slicer.util.getNode(“NodeNameHere”).

Hope this helps.

Hotsen

1 Like