Problems with Python and meshtolabelmap with Slicer 4.11 (python module worked on Slicer 4.10)

I am scripting a module in 3D Slicer using python and the script worked on Slicer 4.10 but now that I’ve updated to the new version 4.11 part of the script is not working. Specifically, a part where I create a handle for a keychain and it is added to the new keychain image. Here is the part I think is not working, which is the call to meshtolabelmap. I don’t know if the new version of python is different with the function call parameters or what it is. I’ve included some surrounding code to give some insight into what is going on. The tempDirectory “saves” has the handle path but the file itself is empty. Again, this worked on Slicer 4.10 with the exact same code.

handle = makeHandle()
handleNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode', "handle")
handleNode.SetAndObservePolyData(handle)
handleNode.CreateDefaultDisplayNodes()
handleNode.CreateDefaultStorageNode()

path = slicer.util.tempDirectory("saves")
handlePath = path + "/handle.nrrd"

handleParams = {'reference' : blankVolumeNode.GetID(), 'mesh' : handleNode.GetID(), 'labelMap': handleBLM.GetID(), 'value' : 255}
process = slicer.cli.run(slicer.modules.meshtolabelmap, None, handleParams, wait_for_completion=True)
slicer.util.saveNode(handleBLM,handlePath)

############################################
############################################
# Save surfaces and then load via simpleITK
############################################
############################################


left = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(leftBLM.GetName()))
right = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(rightBLM.GetName()))
handleVol = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(handleBLM.GetName()))



############################################
############################################
# Use simpleITK to combine, smooth and fill holes
############################################
############################################

orFilter = sitk.OrImageFilter()
brain = orFilter.Execute(right,left)
or2Filter = sitk.OrImageFilter()
keychain = or2Filter.Execute(brain,handleVol)

I’ve added the make handle function as well just incase (even though it creates a handle and shows it in slicer).

def makeHandle():
    fn = vtk.vtkParametricTorus()
    fn.SetRingRadius((rightBound-leftBound)/5)
    fn.SetCrossSectionRadius((rightBound-leftBound)/15)
    #vtk.FlipNormalsOn()
    source = vtk.vtkParametricFunctionSource()
    source.SetParametricFunction(fn)
    source.Update()

    trans = vtk.vtkTransform()
    trans.RotateX(90)
    trans.Translate(midline,topBound + handleShift,halfway)
    # vtk generate normals
    # communicate with SLACK
    rotate = vtk.vtkTransformPolyDataFilter()
    rotate.SetTransform(trans)
    rotate.SetInputConnection(source.GetOutputPort())
    rotate.Update()

    return rotate.GetOutput()

I would recommend to import all meshes, labelmaps, etc. into a segmentation node as segments, combine everything there, and export the results to model. You can find examples for all kinds of processing in the script repository.

There are many things you can do with Segment editor, such as add text (if you install SegmentEditorExtraEffects extension), do some local smoothing or other touch-up.

Automatic creation of brain keychain sounds cool, by the way. Can you attach a photo of a 3D-printed end result?

Sure, here you go. There is another script I made that makes nametags for the keychains and places them in a dynamically sized print scene based on how big the printer is. Here is an example of what it looks like. Also, I will try what you said and let you know how it goes. Thank you for the response!

1 Like