Select cells of a 3D model

how to create a mouse event inside the 3d slicer view. Need to pick cells from a mesh object from within the 3d slice view of the slicer.

Need help

You can get 3D position from views as shown in these examples:

If you want to select several cells, you can use markups fiducials : drop a fiducials on the cells you want to select and then use FindCell to get the cell IDs. If you don’t want the fiducials to stay there then you can remove them immediately after you retrieved their position. In recent Slicer Preview builds, markups points slide on visible surfaces, so you can make position adjustments quite easily.

1 Like

Hi andras,
I wrote the following to get the cell using fiducial

def onMouseMoved(self, observer,eventid):
ras=[0,0,0]
crosshairNode.GetCursorPositionRAS(ras)
if markupsNode.GetNumberOfFiducials() == 0:
markupsNode.AddFiducial(*ras)
else:
markupsNode.SetNthFiducialPosition(0,*ras)
closestCell = cell.FindCell(ras)
closestPointValue = modelPointValues.GetTuple(closestCell)
print("RAS = " + repr(ras) + " value = " + repr(closestPointValue))

calling this within a scripted module in the run function as
global cell, modelPointValues, crosshairNode, markupsNode
modelNode = slicer.util.getNode(‘Model_1’)
#modelPointValues = modelNode.GetPolyData().GetPointData().GetArray(“Normals”)
modelPointValues = modelNode.GetMesh().GetCells()
markupsNode = slicer.util.getNode(‘F’)

if not markupsNode:
 markupsNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode","F")

#pointsLocator = vtk.vtkPointLocator() # could try using vtk.vtkStaticPointLocator() if need to optimize
#pointsLocator.SetDataSet(modelNode.GetPolyData())
#pointsLocator.BuildLocator()

cell = vtk.vtkCellLocator()
cell.SetDataSet(modelNode.GetMesh())
cell.BuildLocator

crosshairNode=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLCrosshairNode")
crosshairNodeObserverTag = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, self.onMouseMoved)

The application stoped working. although there was no error. the mouse cursor was paused. Could you tell me whats wrong with the code.

I replaced the crosshair node part with

crosshairNode=slicer.util.getNode(‘Crosshair’)
crosshairNodeObserverTag = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, self.onMouseMoved)

but still the program doessnt work. What is wrong in the code. could you please tell me. because the program haults and then the slicer application closes.

Modify crosshair examples of the script repository step by step. If you encounter any problems then post the script, describe what you do, what you expect to happen, and what happens instead.

I need cells to be selected with mouse of the mesh in attached pic. The script gives me the position of mousecursor. I defined the celllocator and using the findcell to locate the cell. Could you please guide in this respect. What I need to look at.

I need to get the pcoords of tetra cell rather then the mousecursorpoint. what should I do.

global cell, modelPointValues, crosshairNode, markupsNode
modelNode = slicer.util.getNode('Model_1')
modelPointValues = modelNode.GetMesh().GetCells().GetData()

cell = vtk.vtkCellLocator()
cell.SetDataSet(modelNode.GetMesh())
cell.BuildLocator

crosshairNode=slicer.util.getNode('Crosshair')
crosshairNodeObserverTag = crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, self.onMouseMoved)

def onMouseMoved(self, observer, eventid):  
        ras=[0,0,0]
        crosshairNode.GetCursorPositionRAS(ras)
        if markupsNode.GetNumberOfFiducials() == 0:
         markupsNode.AddFiducial(*ras)
        else:
         markupsNode.SetNthFiducialPosition(0,*ras)
        closestCell = cell.FindCell(ras) /**//Problem starts here
        print("inside mouse event")
        #closestPointValue = modelPointValues.GetTuple(closestCell)
        print("RAS = " + repr(ras) )#+ "    value = " + repr(closestPointValue))

image

The code crashed because you did not build the locator. cell.BuildLocator just prints the address of the BuildLocator method. You need to add () to call the method: cell.BuildLocator().

Another issue is that you mix two approaches: getting point coordinates from markups and crosshair. If you use markups then you don’t need to use crosshair, as you can get 3D positions from the markup points.

See a complete working example here (requires recent Preview Release of Slicer): https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Select_cells_of_a_using_markups_fiducial_points

1 Like

Hi Andras,
Is there a way to select cells on the surface of mesh using onMouseClicked event.

Please suggest.

Regards,
Saima Safdar

It should be possible, but the example script that I linked above can already add markups and thus select cells on mouse click.

Andras I need to use only the mouse clicks to select the cells of a mesh without using the fiducials.
I understand adding three fiducial points to locate the cell will be not feasible.

I would want to select may cells from the surface of the brain where I can apply force. the craniotomy induced part I need to select and it will be different for each MRI. So I need to select the area by mouse. Any suggestions how can I do it?

Thank you so much for replies.

Looking forward to your answer.

Regards,
Saima Safdar

Can you write a bit more about what exactly you would like to achieve?

What is your input data? 3D volumes? Segmentations? Surface scans?

What would you like to do with the data? What would you like to get as end results?

Data = 3D volumetric brain Mesh
What would you like to do with the data? Need to select the surface cells from the brain portion where craniotomy was induced. I will be using the preoperative mri images.
What would you like to get as end results? after selecting cells I will save those cells in a file and will pass those cells along with the complete brain mesh to external Meshless algorithm to compute the craniotomy induced brain shift.

We have very good tool to mark regions in volumetric images: Segment Editor module. You can get cell IDs that overlap the craniotomy region by following these steps:

  • segment the craniotomy region on the image using Segment Editor
  • export segmentation to a labelmap volume
  • use “Probe volume with model” to label all mesh points with 1/0 (corresponding to overlap / does not overlap with the segmented region)
  • find cell IDs corresponding to points that are labelled with “1” - you can use VTK filters (similarly to this) or just by iterating through all the cells and see if any of its points are labelled with “1”

Hi Andras,
Can above be done through scripting. Please help

thank you

Regards,
Saima Safdar

Hi ANdras, I used the steps you told me in 3d slicer its producing the following results instead of only highlighting the segmented volume portion.

image

What am I doing wrong.

I loaded the skull stripped volume.
created a segmentation using scissors and mask volume effect.
image
new volume generated
image
exported segmentation as labelmap volume.
image

used the new volume for input in probe volume model.
image
one time I click on the model it looks like below:
image
other time I click on the same model eye open eye close it looks like below:
image

Could you please guide me what am I doing wrong I need only the segmented volume region to be selected on the model.

Please help.

Also I need to do all this through scripting.

Regards,
Saima Safdar

Hi andras,
I applied the probe volume with model filter. Got the cell ids using the script below:

for cellIndex in range(ncells):
        cellpoints = mesh.GetCellPoints(cellIndex,idList)
        scalarArray = mesh.GetPointData().GetArray(0)
        #print(scalarArray)
        numPoints = idList.GetNumberOfIds()
        #print(numPoints)
        for pointIndex in range(numPoints):
            value = scalarArray.GetValue(idList.GetId(pointIndex))
            if(value == 1):
               print(cellIndex)

could you please tell me how could I get those cells coloured differently on the model.

Looking forward to your reply.

Thank you

Regards,
Saima Safdar

P.S. Also please tell me how can i use the probe volume with model using script. thankyou

While the VTK code above that gives you point IDs that have a certain scalar value is correct, you may find it easier to get the point data as numpy array and use numpy for processing:

import numpy as np
voxelValues = slicer.util.arrayFromModelPointData(getNode('Output Model'), 'NRRDImage')
pointIDs = np.where(voxelValues == 1)

You can use Models module / Display / Scalars section to color a model by a selected scalar.

“Probe volume with model” module is a CLI module, so you can run it from Python as described here.

1 Like

n = getNode(“Output Model_1”)

n
(MRMLCorePython.vtkMRMLModelNode)0000023BCBDE8E28
voxelValues = slicer.util.arrayFromModelPointData(n, ‘NRRDImage’)
Traceback (most recent call last):
File “”, line 1, in
File “C:\Users\22374464\AppData\Local\NA-MIC\Slicer 4.11.0-2019-07-06\bin\Python\slicer\util.py”, line 1009, in arrayFromModelPointData
arrayVtk = modelNode.GetPolyData().GetPointData().GetArray(arrayName)
AttributeError: ‘NoneType’ object has no attribute ‘GetPointData’

getting the above error. Why dont understand?

I need to color the selected cells. For example I want to color the cell in the model. I am getting the location of that cell then using that location to set the activescalar. is it right. I dont know how to color. Any help?

nn = slicer.util.getNode(outputVolume.GetID())
d = nn.GetModelDisplayNode()
l = nn.GetMesh().GetCellLocationsArray()
v = l.GetValue(4740)
d.SetActiveScalar(‘R’,v)
d.SetAndObserveColorNodeID(‘FullRainbow’)
d.ScalarVisibilityOn()
d.AutoScalarRangeOn()

Hi Andras,
Is there a way to change the color for different cells in a 3d volumetric mesh by scripting. i know cell ids I need to change the color for those cells. How can I do it. please guide

Thank you

Regards,
Saima Safdar