Cross section analysis in VMTK module


I can convert a cross section and convert to a segmentation and then convert it back to a model; then go to the next cross section by browsing in the cross sectional analysis module. Finally, I can save them to STL. This is tedious. Is there is way to export multiple cross sections at a time? Say, I want to resample the centerline to have 20 control points, then export all the cross sections at these control points.

Also, how to get the center (coordinates) of a cross section?

If I have fully understood your requirements, this step can be done through scripting. A good start is as follows:

import CrossSectionAnalysis
logic = CrossSectionAnalysis.CrossSectionAnalysisLogic()
centerline = getNode("Centerline curve (0)")
segmentation = getNode("Segmentation")
logic.setInputCenterlineNode(centerline)
logic.setLumenSurface(segmentation, "Segment_1")
logic.run()
for i in range(20):
    crossSectionPolyData = logic.computeCrossSectionPolydata(i)
    # Add your export code to STL here

You must add more code to export the crossSectionPolyData to STL.

For me, ‘centre’ refers to a regular geometry, like circle, rectangle, cube… Do you mean the control point coordinates of your resampled curve? They are available in the ‘Markups’ module.

@chir.set, thank you so much! Your method seems promising. I’m not familiar with script, but I get your code run in the python console and it seems working. Can you tell me how to export crossSectionPolyData to STL, how to convert them to models so that I can view them in Slicer?

For the second question about the center, if the sections are exactly extracted at the centerline control points, then I can get the coordinates from the centerline table.

As you can see in the snapshot, I have the centerline extracted and resampled.

To create a model from polydata:

model = slicer.modules.models.logic().AddModel(crossSectionPolyData)

As for the STL thing, I’m not familiar with it. May be someone else could kick in.


Cool. I got 20 cross sections in a second. Unfortunately, they are not at the control points. Did I miss something with my centerline curve? I just resampled it to have 20 control points.

Not really, the code works on curve points while you are expecting a result at control points. The update below should do:

import CrossSectionAnalysis
logic = CrossSectionAnalysis.CrossSectionAnalysisLogic()
centerline = getNode("Centerline curve (0)")
segmentation = getNode("Segmentation")
logic.setInputCenterlineNode(centerline)
logic.setLumenSurface(segmentation, "Segment_1")
logic.run()
numberOfControlPoints = centerline.GetNumberOfControlPoints()
controlPointCoordinates = [0.0, 0.0, 0.0]
for i in range(numberOfControlPoints):
    centerline.GetNthControlPointPositionWorld(i, controlPointCoordinates)
    pointId = centerline.GetCurveWorld().FindPoint(controlPointCoordinates)
    crossSectionPolyData = logic.computeCrossSectionPolydata(pointId)
    model = slicer.modules.models.logic().AddModel(crossSectionPolyData)
1 Like

I really appreciate your great help. It works perfectly. I got the cross sections at the desired positions.

I would like to share the complete code with renaming and saving the models here in case it is of interest to other people.

import CrossSectionAnalysis
logic = CrossSectionAnalysis.CrossSectionAnalysisLogic()
centerline = getNode("Centerline curve (0)")
segmentation = getNode("Segmentation")
logic.setInputCenterlineNode(centerline)
logic.setLumenSurface(segmentation, "Segment_1")
logic.run()
numberOfControlPoints = centerline.GetNumberOfControlPoints()
controlPointCoordinates = [0.0, 0.0, 0.0]
for i in range(numberOfControlPoints):
    centerline.GetNthControlPointPositionWorld(i, controlPointCoordinates)
    pointId = centerline.GetCurveWorld().FindPoint(controlPointCoordinates)
    crossSectionPolyData = logic.computeCrossSectionPolydata(pointId)
    model = slicer.modules.models.logic().AddModel(crossSectionPolyData)
    
    model.SetName(f"Secion{i}")
    
    filename = os.path.basename(model.GetName())
    filepath =  filename + ".stl"
    slicer.util.exportNode(model, filepath)