New Dynamic Modeler Tool: Select by Points

Select by points tool is available on the Dynamic Modeler module since end of October 2021 Slicer Preview Release

This tools allows you to create 2 types of output models from an input model, a fiducial list, a selection-distance and a selection-algorithm.

One of the possible outputs is copy of the input model with selection scalars (unselected=0, selected=1) according to the selection-algorithm and selection-distance using the fiducial points as seeds.

The other possible output crops out the part of the input model that is selected.

This tool was developed ad-honorem by:

  • Mauro I. Dominguez
  • Andras Lasso (Perklab)

This tool allows partial mesh registration workflows like weight-painting ICP on Blender.

Related: Partial Surface Registration Tutorial

4 Likes

Hi dear, thank you so much for sharing. Actually I am conducting a project to measure the distance of zygoma bone between T1 (taken after a week of operation) and T2 (taken after 6 months of operation).
I want to know if there is a displacement and if yes how much was in mm and in which direction.

My questions:

  1. I am using Pickā€™n paint, model to model distance, and mesh statistics to export the value in excel file: in the new release of the 3d slicer, I can not use pickā€™n paint properly: as when trying to add a fiducial point: automatically a lot of points are added!!! previously you send me this answer of using dynamic modeler tool: when I have watched this demo, it is on the same bone not in two models as my case! so how can I solve this problem?
    Thank you again and sorry to bother you.

You can consider your two bones at different timestamps as two different models

actually they are, I am doing the followings:

  1. import both DICOM, transformation, rigid registration with Elastix module, then segment each one as volume, saved each one independently.
  2. open again both models to start doing the steps mentioned in previous message.

My question:
how to solve the problem of automatic many points addition that I am facing with the new release version of the 3D Slicer?ā€™
How dynamic modeler could be used to add fiducial points on T1 model then measure the distance between these points and their matching ones on T2 model? as you mentioned in previous answer.
Thank you

thank you, but what do you mean by (at different timestampes)!

Please see this link

You just need to replace the deformed and normal bone from the video for your T1 and T2 bone modelsā€¦

If it is not clear enough please let me know

Thank you so much for your rapid reply.
Actually it is so clear and this is to do registration of two models.
My question actually was how to calculate the displacement amount after doing the registration step of the two models in regard to the ROI which is in my case the zygoma bone?

@manjula could you help?

I think you need to use the model2model distance extension

exactly, so you mean after doing the registration the next step is to do partial surface registration ( formed by the zygomatic bone of T1, in my case) in the dynamic modeler module then using model to model distance and then mesh statistics to export the values?

I think it is as you explained but I would only do the partial surface registration

Hello,

Thank you for this function! Though, I found that there are only two possibilities for output nodes at the moment: ā€œModel with selection scalarsā€ and ā€œModel of the selected cellsā€. Is there a way to obtain a ā€œmodel of the unselected cellsā€ as output? I tried multiple things, but canā€™t seem to obtain the required model.

What I tried: I can visualize the selection with the ā€œModel with selection scalarsā€ and even ā€œremove (i.e. turn invisible)ā€ the ā€œModel of the selected cellsā€ by lowering the scalar threshold under 1. So, it is only showing the unselected cells, but I donā€™t find how the export this visualisation/selection as a model.
I also tried to subtract the ā€œModel of the selected cellsā€ from the input node with the ā€œcombine modelsā€ function from the Sandbox extension. This gives me an error message, the one that is discussed on this page: Difference of meshes sometimes an empty mesh Ā· Issue #40 Ā· zippy84/vtkbool Ā· GitHub.

Is there another way to obtain this ā€œModel of the unselected cellsā€?
Thanks in advance!

Yes, you should use vtkThreshold and vtkGeometryFilter on the ā€œModel with selection scalarsā€ Polydata

Thank you for your fast reply! Could you tell me how should I use these vtkThreshold and vtkGeometryFilter? (My apologies, Iā€™m not familiar with coding in python and quite new to 3DSlicer).
I found how to call on my model (see under), but do not know how to apply the mentioned functions.

modelNode = slicer.util.getNode("Model")

I compilated this piece of code just now. While it gives me an output, this output is empty. Could you tell what Iā€™m doing wrong, please?

modelNode = slicer.util.getNode("Model")
threshold = vtk.vtkThreshold()
threshold.SetInputConnection(modelNode.GetPolyDataConnection())
threshold.SetThresholdFunction(threshold.THRESHOLD_UPPER)
threshold.SetUpperThreshold(0.9)
surface = vtk.vtkGeometryFilter()
surface.SetInputConnection(threshold.GetOutputPort())
thresholdedModel = slicer.modules.models.logic().AddModel(surface.GetOutputPort())

I think you need to do:

surface.SetInputConnection(threshold.GetOutputPort())
surface.Update() #This is needed on the last filter to chain execute them
thresholdedModel = slicer.modules.models.logic().AddModel(surface.GetOutput()) # GetOutput() returns Polydata while GetOutputPort() is a cable connection to the geometryFilter

Let me know how it goes

Thank you for the advice, but it still doesnā€™t work. The script returns a new Surface Mesh (vtkPolyData), but it is empty (surface area and such are still 0).

Please check here:

And use it as example

Iā€™ve been trying to use your script as an example, but it is hard for me (Iā€™m a newbie and not familiar with python or C++ (I think?) at all). So my apologies for the questions.

modelNode = slicer.util.getNode("Model")

#it seems these lines from your script may be useful here, but I don't know how to translate them to python
vtkPointData* pointScalars = vtkPointData::SafeDownCast(inputMesh_WorldWithSelection->GetPointData());
    pointScalars->AddArray(outputSelectionArray);
#inputMesh_WorldWithSelection should be replaced with modelNode

threshold = vtk.vtkThreshold()
threshold.SetInputConnection(modelNode.GetPolyDataConnection())
threshold.SetThresholdFunction(threshold.THRESHOLD_UPPER)
threshold.SetUpperThreshold(0.5)
threshold.Update() #added this line
surface = vtk.vtkGeometryFilter()
surface.SetInputConnection(threshold.GetOutputPort())
surface.Update()
thresholdedModel = slicer.modules.models.logic().AddModel(surface.GetOutput())

As this didnā€™t seem to work out (couldnā€™t figure out how to convert from one language to the other), I tried a different approach, but ran into another error message. Would this approach even be viable?

modelNode = slicer.util.getNode("Model")
scalars = arrayFromModelPointData(modelNode, 'Selection')
filter_arr = []
for element in scalars:
	if element > 1: 
		filter_arr.append(True)
	else: 
		filter_arr.append(False)
filtered = modelNode[filter_arr]
thresholdedModel = slicer.modules.models.logic().AddModel(filtered.GetOutput())
Error message: 
Traceback (most recent call last):
  File "<string>", line 9, in <module>
TypeError: 'MRMLCore.vtkMRMLModelNode' object is not subscriptable

Could you please help me out with this code? Iā€™m quite lost how to make this work.

I usually find vtk python examples here:

Thank you for the examples, they helped! Here is the updated code to get the ā€˜Model of the Unselected Cellsā€™.

modelNode = slicer.util.getNode("Model")
threshold = vtk.vtkThreshold()
threshold.SetInputConnection(modelNode.GetPolyDataConnection())
threshold.SetThresholdFunction(threshold.THRESHOLD_LOWER)
threshold.SetLowerThreshold(0.5)
threshold.SetInputArrayToProcess(0,0,0, vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS, "Selection")
threshold.Update()
surface = vtk.vtkGeometryFilter()
surface.SetInputConnection(threshold.GetOutputPort())
surface.Update() 
thresholdedModel = slicer.modules.models.logic().AddModel(surface.GetOutput())

1 Like