Questions about Sandbox/Segment Cross-segment Area

Hello. I´m an absolute newbie to Slicer so forgive me if my questions are a bit daft.
I found 3D Slicer by chance searching for a solution to a problem I have.
We have a lot of different cylindrical “connectors” that we need to spot weld in place. In an effort to pre select welding parameters, and to find possible troublesome connectors, I´m trying to estimate the total resistivity of all our connectors (hundreds of different) and one way I found to do that is to calculate the average cross section area through the components z-axis and then divide the total height of the components with this average area.
Enter 3D Slicer…
I found that the module Segment Cross-section Area gives me a table with the area of a bunch of slices if used on our STL-files. This table I copy to excel for further calculations.
Now, a few questions.

If I do this on components with the same height but different diameters I seem to get different amount of rows in the table. I guess based of it being sliced in different slice thickness? What sets this “thickness”? Can I set it somehow?
I open the STL-file by drag and drop and then state “Segmentation” in the pop-up.

I have a lot of these models to analyze. Is it possible to do it in batch?
Preferably with the average slice area of each file as the only output.

Thank you in advance!

Hello again.
I started to do some learning by trail and error in Python Console.
Managed to select module by:
slicer.util.selectModule(“SegmentCrossSectionArea”)
and then load my stl-file by:
segmentNode = slicer.util.loadSegmentation(r"C:\Swep\00070105.ipt.stl")
Now, trying to actually execute the module, I got stuck:
slicer.util.getModuleLogic(‘SegmentCrossSectionArea’).run(segmentNode, “None”, “slice”, “Create”, “Create”)
Following the error I found that it probably misses a table and a chart to put the result in but I´m very new to python and do not have a clue on how to create those.
If someone could point me in the right direction, maybe have some example to refer to, I would be very thankful!

Oh, well.
After quite a bit of trial and error I got where I wanted.

slicer.util.selectModule(“SegmentCrossSectionArea”)
segmentNode = slicer.util.loadSegmentation(r"C:\Anslutningar STL\00070105.ipt.stl")
tableNode = slicer.mrmlScene.AddNewNodeByClass(“vtkMRMLTableNode”)
chartNode = slicer.mrmlScene.AddNewNodeByClass(“vtkMRMLPlotChartNode”)
slicer.util.getModuleLogic(‘SegmentCrossSectionArea’).run(segmentNode, None, “slice”, tableNode, chartNode)
slicer.util.getModuleLogic(‘SegmentCrossSectionArea’).showTable(tableNode)
numCols = tableNode.GetNumberOfColumns()
numRows = tableNode.GetNumberOfRows()
print("Number of Columns: ", numCols)
print("Number of Rows: ", numRows)
print("First Row: ", tableNode.GetCellText(0,2))
print("Last Row: ", tableNode.GetCellText(numRows-1,2))

sumAv = 0.0
for x in range(numRows):
sumAv = sumAv + float(tableNode.GetCellText(x,2))

AverageArea = sumAv/(numRows)
print("Sum Area: ", sumAv)
print("Average Area: ", AverageArea)

But I still wonder if I could state the thickness of the segments/slices and thus set how many rows my table will get, somehow?
Also I wonder if I can preview my posts before posting them…?

Sorry for the long wait! Interesting project.

It would really help if you could share one of these STL files so that I can try your script and see where we are at.

Great progress from an “absolute newbie”! I am happy to help with this, but let’s have a concrete case I can try and you can approve the results for.

Thanks for your patience. The whole community is preparing for the project week (next week) and the new 5.8 release so support is a bit slower I guess.

Thank you @cpinter!
I understand there can be periods of low activity in these kind of forums. No problem!
But I have come a long way. Now my script can scan a whole folder and iterate through all STL-files in there, building a new table with the information I need. Next step will be to export that table to a file (in a format I have yet not decided…).

I still wonder about the difference in number of rows between STL-files even though the height (z-axis) is the same.
But it is not a big issue, I have concluded, as there is normally enough rows to get a average with descent accuracy.

I am not allowed to share our models (STL). What I could do is to make rough dummies of models that will behave the same.
But I do not know what is the best way to share them as the upload function in this system does not allow STL-files.

I have also noticed that if I copy the code I posted from here into the Python Console it will not work as several characters will be misinterpreted…
But I guess you guys already now that.

That would be great too, the point is to have a case to try it on!

Normally we share using our own drives, everyone these days has some online storage…

I don’t yet understand this, but once being able to try, maybe I’ll see.

Ok. Lets try!
Dummy File 1
Dummy File 2

Don´t bother with script at this point.
If File 1 is dragged and dropped into Slicer, Loaded as Segmentation, and Module Segment Cross-section Area is run, it will get a table with 258 rows.
If File 2 is used, the table will get 158 rows.
Segmentation is done in Z-axis, as I can understand, and both models has the same height of 22 mm.

See if you get access to the files, and come back if not.
Thank you!

Thanks a lot! It might take me a good while until I can actually try, but I have an idea based on this description.

If you do this without specifying geometry, the default image geometry will be used (1mm x 1mm x 1mm).
After loading it as segmentation, first make sure that the default representation is Closed surface. This means that the Representations section in the Segmentations module (not Segment Editor) looks like this:

If so, click on the advanced conversion (arrow next to create) in the row of Binary labelmap, you can specify the geometry. Here you can exactly give the slice thickness, i.e. the distance of the per-slice evaluation.

You seem to be absolutely right @cpinter (of course…)!
Changing the last spacing (z-axis I guess) to 0,1 mm gives me the result I want.
Exact 220 rows when height is 22 mm.

Now, how can I implement this by script?
Can I set this some how before Load as Segmentation?
Or do I have to do a conversion after each loaded model, some how?
Is it even possible?

Thank you again!

Yes it is possible. Unfortunately I cannot help with an actual script right now (all day meetings, next week the Slicer project week that we are organizing).

But here’s some sample code that may help you get started:

slicer.vtkSlicerSegmentationsModuleLogic.ImportModelToSegmentationNode(modelNode, segmentationNode)
# Set computed reference image geometry to the segmentation
extent = [0, 1, 0, 1, 0, 1]  # Arbitrary extent
geometryString = slicer.vtkSegmentationConverter.SerializeImageGeometry(referenceGeometryMatrix, extent)
segmentationNode.GetSegmentation().SetConversionParameter(
  slicer.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), geometryString)
# Use geometry to convert to binary labelmap
segmentationNode.CreateBinaryLabelmapRepresentation()
# Set binary labelmap representation as source
segmentationNode.SetSourceRepresentationToBinaryLabelmap()

Thank you!
This one was a bit harder to get into my head… And I still don´t understand all of it.

extent = [0, 1, 0, 1, 0, 1] # Arbitrary extent

Arbitrary is in my world, as an engineer, regarded as a curse… :wink:
What does those six numbers do or represent?
Anyway, I got it to work the way I wanted. By taking a shortcut, going directly to:

geometryString = “0.1;0;0;0;0;0.1;0;0;0;0;0.1;0;0;0;0;0.1;0;1;0;1;0;1;”

:+1:

It is the extent in format [xMin, xMax, yMin, yMax, zMin, zMax]. Arbitrary initialization is fine because it will be automatically calculated based on the origin and the labelmap content (only the region of the image data is allocated that contains non-background).