Programatically use "Specify Geometry" (Python)

Hello

I want to control programatically this option “Specify Geometry”

Basically reassign a new source volume to the segmentation
image

I have tried to use

            newsegmNode = shNode.GetItemDataNode(newsegmID)
            newsegmNode.SetReferenceImageGeometryParameterFromVolumeNode(
                DERSNode.data)
            newsegmNode.CreateDefaultDisplayNodes()
            newsegmNode.CreateBinaryLabelmapRepresentation()

But it just changes the Master Volume, not the source volume. I want the segmentation to be revoxelized in the new source volume.

Is there a way to achieve this?

Regards

If you already have a binary labelmap then setting a reference image geometry will have no effect.

One option is to create closed surface representation, delete the binary labelmap representation, then create binary labelmap representation (it will be generated from the closed surface representation, using the reference image geometry).

Another option is to resample the labelmap representation as it is done here. I’ll add this code as a method to the vtkSlicerSegmentationGeometryLogic class to make it more easily accessible from Python.

OK, I have tried the first approach

newsegmNode.CreateClosedSurfaceRepresentation()
newsegmNode.GetSegmentation().SetMasterRepresentationName(closedSurfaceReprName)
newsegmNode.SetReferenceImageGeometryParameterFromVolumeNode(DERSNode.data)
newsegmNode.CreateBinaryLabelmapRepresentation()
newsegmNode.GetSegmentation().SetMasterRepresentationName(binaryLabelmapReprName)

But it doesn’t worked, it still has the old voxelization, is there something wrong here in this code snippet?

You missed the step of deleting the labelmap representation.

I though that setting the master representation would delete any other representation. OK I have tried this

newsegmNode.CreateClosedSurfaceRepresentation()
newsegmNode.GetSegmentation().SetMasterRepresentationName(closedSurfaceReprName)
newsegmNode.RemoveBinaryLabelmapRepresentation()
newsegmNode.SetReferenceImageGeometryParameterFromVolumeNode(DERSNode.data)
newsegmNode.CreateBinaryLabelmapRepresentation()
newsegmNode.GetSegmentation().SetMasterRepresentationName(binaryLabelmapReprName)

But still no success, I mean the master representation has changed, but
doing with the code I get these volumes

Segment Number of voxels [voxels] Volume [cm3]
1-Anterior 758 65.3669
2-Lateral 80 6.89889
3-Posterior 220 18.9719
4-Inferior 137 11.8143

Now doing it manually I get (the correct values)

Segment Number of voxels [voxels] Volume [cm3]
1-Anterior 788 67.954
2-Lateral 113 9.74468
3-Posterior 254 21.904
4-Inferior 165 14.229

What steps do you do manually and how?

click on specify geometry
select a diferent node
click OK

Usually the new node has been modified by registration so I need the segmentation to account for the grid deformation

OK, I will describe more the steps

take two (n>1 actually but lets take 2 for simplicity) same patient CT, obtained at different days, segment a structure in one of them.
Purpose: obtain the volume evolution in time of the structure.

  • Option 1:
    Segment the same structure in the second CT.
    Advantage: Each segmentation has the geometry of the respective time CT
    Disadvantage: Not scalable for many time points and many structures

  • Option 2:
    Segment in the first CT; Elastic transform the second; measure
    Advantage: Easily scalable
    Disadvantage: The volume does not change in time because the original segmentation is not recalculated for the geometry of the rest of the time points

  • Option 3:
    Segment in the first CT; get the elastic transformation without modifying the second; get the inverse of that transformation and apply to the respective segmentation; measure
    Advantage: Easily scalable
    Disadvantage: The volume does not change in time because the original segmentation is not recalculated for the geometry of the rest of the time points

I tried to do options 2 and 3 without success, because the lines above doesn’t produce the same result as the option 1 (I can live with some % difference due to difference in segmentation, but not more than 20% as showed).
Doing the master geometry change manually does the trick in both 2 and 3 as showed. So I need to reproduce this programatically.

Do you mean that you use Segment Statistics to compute the volume, but the transform is only taken into account if you harden it?

In recent Slicer Preview Releases, you can use vtkSlicerSegmentationGeometryLogic::ResampleLabelmapsInSegmentationNode method to resample the labelmap. However, in recent Slicer Preview Releases, Segment Statistics module already hardens any transforms on a copy of the segmentation node, so the volume computation should be correct.

Hello,

how to access the
vtkSlicerSegmentationGeometryLogic
and ResampleLabelmapsInSegmentationNode from python?

Thank you

found a good example about it here:

Hi,

I have a dataset of 65 patients, each with a CT volume and its segmentation node (containing two labels: pancreas and lesion).

I’m preprocessing this dataset using Python.

I have cropped and resized the original CT images to the bounding box of the pancreas + lesion area. This cropping and resizing was performed using the Radiomics library with a BSpline interpolator.

Next, I’m trying to generate a segmentation scene with this new volume and its segmentation node. I call Slicer with a subprocess, load the segmentation node and the cropped volume in Slicer, and then associate the segmentation node with the cropped volume. This is to resize the segmentations to match the spacing of the cropped volume. I specify the geometry using the SetReferenceImageGeometryParameterFromVolumeNode(volume) command, which works well for most cases. However, for 2 cases, I encounter issues:


[Here I show an example of 3 cases preproceessed with python, reading the volume and segmentation node with sitk: 1 works correctly and the next 2 cases have a half spacing of the reference volume after appliying this:

]

When I open the Slicer scene and perform this process manually, I get the correct results.

Why might this be happening? Is there another command I need to include?

Thanks for your help.