I try to replace `markups` with `model` in `MarkupsToModel` , but

I try to replace markups with model in MarkupsToModel , but…:point_down:, what’s wrong?

def fids2Mod(fids, curve=True):
#     if isinstance(fids,str):
    fids = slicer.util.getNode(fids)

    outputModel = slicer.mrmlScene.AddNode(slicer.vtkMRMLModelNode())
    outputModel.CreateDefaultDisplayNodes()
    outputModel.GetDisplayNode().SetSliceIntersectionVisibility(True)
    outputModel.GetDisplayNode().SetColor(1,0,0)

    markupsToModel = slicer.mrmlScene.AddNode(slicer.vtkMRMLMarkupsToModelNode())

    markupsToModel.SetAutoUpdateOutput(True)
    markupsToModel.SetAndObserveModelNodeID(outputModel.GetID())
    markupsToModel.SetAndObserveMarkupsNodeID(fids.GetID())
    if curve:
        markupsToModel.SetModelType(0)
        markupsToModel.SetTubeRadius(0.05)
        markupsToModel.SetTubeLoop(1)
        markupsToModel.SetCurveType(0)
# while mn is model
fids2Mod(mn,curve=False)

:point_down:? got None???

# mn is model
fids2Mod(mn,curve=True)

# fids is markups
fids2Mod(f"{mn}s",curve=False)

Regardless of input node type (markups fiducial or model node), you’ll get the same output model for the same input points. If you get empty results for model node input then most likely the input model node points are not set correctly. If you provide example data (saved as a .mrb file, uploaded to dropbox/onedrive) and the code snippet that you expect to work after loading that scene, then I can have a closer look.

@lassoan theFile

Everything works well for me, I just had to delete the extra points (for example, in 3_xPMods keep only 31 to 61). If you are reconstructing a tool trajectory path then I would recommend to only start recording when you start pulling back the tool.

If I copy the point coordinates into a model then “Markups to model” module creates the exact same tube from that.

markupsPoints = getNode('3_xPMods')

# Get point coordinates as numpy array
coords = arrayFromMarkupsControlPoints(markupsPoints)

# Create new model node and allocate points
modelNode=slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode')
pts = vtk.vtkPoints()
pts.SetNumberOfPoints(len(coords))
pd = vtk.vtkPolyData()
pd.SetPoints(pts)
modelNode.SetAndObservePolyData(pd)

# Copy point coordinates from markup to model
outCoords = arrayFromModelPoints(modelNode)
outCoords[:] = coords

Closed surface reconstruction worked well, too:

outputModel = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
outputModel.CreateDefaultDisplayNodes()
outputModel.GetDisplayNode().SetSliceIntersectionVisibility(True)
outputModel.GetDisplayNode().SetColor(1,0,0)

markupsToModel = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsToModelNode")
markupsToModel.SetAndObserveInputNodeID(fids.GetID())
markupsToModel.SetAndObserveOutputModelNodeID(outputModel.GetID())
slicer.modules.markupstomodel.logic().UpdateOutputModel(markupsToModel)

If you want to reconstruct an open surface then the simplest is to use a closed curve:

# Convert any markup node type into a closed curve node
outputCurve = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsClosedCurveNode")
outputCurve.SetCurveTypeToLinear()
updateMarkupsControlPointsFromArray(outputCurve, arrayFromMarkupsControlPoints(fids))

# Get surface area
areaMeasurement = outputCurve.GetMeasurement('area')
areaMeasurement.SetEnabled(True)
slicer.modules.models.logic().AddModel(areaMeasurement.GetMeshValue())

@lassoan Is there a way to sort the index of the points (np.array) according to the clockwise or counterclockwise and adjacent nearest points?

Sorting is only available for polynomial fitting, along an approximately linear trajectory. You would need to implement sorting for a circular trajectory yourself.

What is your overall goal?