After a week, I arrived to this script. It runs TotalSegmentator on “Total” and “Appendicular bones” and keeps only the interested bones. Finally, it changes the name of certain bones to uniform the names.
Here it is for future reference :
import slicer
from qt import QProgressDialog
slicer.app.pythonConsole().clear()
def show_progress(message):
“”“Display modal progress dialog.”“”
progress = QProgressDialog()
progress.setLabelText(message)
progress.setCancelButton(None)
progress.setWindowModality(2) # ApplicationModal
progress.setMinimum(0)
progress.setMaximum(0)
progress.show()
slicer.app.processEvents()
return progress
def run_total_segmentator(volumeNode, task, segmentationName, fast=True):
logic = slicer.modules.totalsegmentator.widgetRepresentation().self().logic
segmentationNode = slicer.mrmlScene.AddNewNodeByClass(“vtkMRMLSegmentationNode”, segmentationName)
progress = show_progress(f"Running TotalSegmentator: {task}...")
logic.process(
inputVolume=volumeNode,
outputSegmentation=segmentationNode,
task=task,
fast=fast
)
progress.close()
print(f"✅ Finished: {segmentationName}")
return segmentationNode
Step 1 – Get the first scalar volume in the scene
volumeNode = slicer.mrmlScene.GetFirstNodeByClass(“vtkMRMLScalarVolumeNode”)
if not volumeNode:
raise RuntimeError(“
No scalar volume found in the scene.”)
Step 2 – Run first segmentation with task=“total”
seg1 = run_total_segmentator(volumeNode, task=“total”, segmentationName=“Seg_Total”, fast=False)
Step 3 – Run second segmentation with task=“appendicular_bones”
seg2 = run_total_segmentator(volumeNode, task=“appendicular_bones”, segmentationName=“Seg_Appendicular”, fast=False)
print(“
Both segmentations complete. ‘Seg_Appendicular’ is now visible.”)
Step 4 - Remove all unnecessary segments except Fibula, Tibia, Fémur and Patella
Keywords to keep (case-insensitive)
keywords_to_keep = [‘left femur’, ‘patella’, ‘tibia’, ‘fibula’]
Create new segmentation node to collect matching segments
newSegNode = slicer.mrmlScene.AddNewNodeByClass(“vtkMRMLSegmentationNode”, “FilteredSegments”)
Ensure it has a display node
if not newSegNode.GetDisplayNode():
newSegNode.CreateDefaultDisplayNodes()
Get all existing segmentation nodes BEFORE creating the new one
existingSegmentNodes = list(slicer.util.getNodes(‘vtkMRMLSegmentationNode*’).values())
Loop through original segmentation nodes only
for segNode in existingSegmentNodes:
if segNode == newSegNode:
continue
segmentation = segNode.GetSegmentation()
segmentIdsToCopy = []
# Identify segments to keep
for i in range(segmentation.GetNumberOfSegments()):
segmentId = segmentation.GetNthSegmentID(i)
segmentName = segmentation.GetSegment(segmentId).GetName()
segmentNameLower = segmentName.lower()
if any(keyword in segmentNameLower for keyword in keywords_to_keep):
print(f"Keeping segment: {segmentName}")
segmentIdsToCopy.append(segmentId)
else:
print(f"Discarding segment: {segmentName}")
# Copy segments to new node and rename if needed
for segmentId in segmentIdsToCopy:
existingSegmentIds = set(newSegNode.GetSegmentation().GetSegmentIDs())
success = newSegNode.GetSegmentation().CopySegmentFromSegmentation(segmentation, segmentId)
if success:
newSegmentIds = set(newSegNode.GetSegmentation().GetSegmentIDs()) - existingSegmentIds
if newSegmentIds:
newSegmentId = newSegmentIds.pop()
originalName = segmentation.GetSegment(segmentId).GetName().lower()
if 'left femur' in originalName:
newSegNode.GetSegmentation().GetSegment(newSegmentId).SetName('Femur')
elif 'tibia' in originalName:
newSegNode.GetSegmentation().GetSegment(newSegmentId).SetName('Tibia')
# Remove original segmentation node from scene
print(f"Removing original segmentation node: {segNode.GetName()}")
slicer.mrmlScene.RemoveNode(segNode)