Hi community,
now i want to generate landmarks uniformly from a grid plane to my volume mesh as the diagram shown below (since i want to generate a mean model of a series of data sets, i need to generate landmarks uniformly with a grid plane with fixed size points to do projection on volume mesh)
However, last I checked there was a bug in which it cropped the selected model when you enable the warp model option. You may want to check with @cpinter.
I don’t believe the SurfaceMarkup extension would help much in your case, other than with initializing the grid to be projected. The projection will need to be done within your module.
I don’t understand this. Do you have an issue in the surface markup with your use case?
Perhaps it was a misunderstanding on my part of what surface node option does . I thought if I choose a model, the Surface markups would be projected to the surface of the model following the topography of the surface. Instead currently it seems to be cropping the model (similar to the plane or curve functionality within Dynamic Modeler).
I would recommend using readily available VTK filters for point sampling, such as vtkPoissonDiskSampler and vtkPolyDataPointSampler. They produce approximately uniform grid even if the surface is uneven.
Full example:
modelNode = getNode('model')
# Sample points on the surface
sampler = vtk.vtkPoissonDiskSampler()
sampler.SetInputConnection(modelNode.GetPolyDataConnection())
sampler.SetRadius(10.0)
sampler.Update()
sampler.GetOutput().GetNumberOfPoints()
# Get point coordinates as numpy array
import vtk.util.numpy_support
pointData = sampler.GetOutput().GetPoints().GetData()
coordsArray = vtk.util.numpy_support.vtk_to_numpy(pointData)
# Create a markup point list
markupPointList = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLMarkupsFiducialNode')
markupPointList.CreateDefaultDisplayNodes()
displayNode = markupPointList.GetDisplayNode()
displayNode.SetPointLabelsVisibility(False)
markupPointList.SetLocked(True)
# Set sampled point coordinates into the markup point list
updateMarkupsControlPointsFromArray(markupPointList, coordsArray)
Note that in the very latest Slicer Preview Release (that you download on 2022-09-03 or later) I’ve made some performance improvements in updateMarkupsControlPointsFromArray completes immediately instead in tens of seconds (if you have many points).
If you want to place points only in a specific part of the surface then you can clip the model using Dynamic Modeler module (Curve cut, Boundary cut, or Select by points tool) before you project.
@lassoan
Sorry to interrupt, I also want to know if I can set the exact amount of point size? So that every model can generate same amount of uniform points.
Thank you for your time!
If you want to have exact same number of points then I would do that by registering the model where you placed the points to the other models. If you have the transformation then you can use that to transfer the landmark points.
There are lots of tools for these kinds of things in Slicer. If you describe your overall goal then we can give better advice.
@lassoan
Okay, so for example i have three data sets which are three models of different patients. And i want to place a fixed size of landmarks on them(for example 1000 points) so that i can calculate the mean model of the 3 models.
Model 1: X1,1/X1,2/X1,3/…X1,1000
Model 2: X2,1/X2,2/X2,3/…X2,1000
Model 3: X3,1/X3,2/X3,3/…X3,1000
Mean model:( (X1,1+X2,1+X3,1)/3 / (X1,2+X2,2+X3,2)/3 /…/ (X1,1000+X2,1000+X3,1000)/3
So now i want to generate points on each model. Which the points size must be fixed(for example 1000 points) and each point should be generated at a similar location.(X1,1 and X2,1 should be place at similar anatomy location)
Therefore for my previous problem i hope to solve it by projecting a set points of a grid plane so that i can achieve my goal.
However, do you have further advices? Thank you so much for your time.
Thanks, this is very useful information. This is a quite common shape analysis task and SlicerMorph and SlicerSalt extensions have very sophisticated tools for it. I would recommend to follow the tutorial created for these extensions.
@lassoan
Thank you so much!
However I’ve tried it but for the point generation part I could not set a fixed size of points.
Do you have any advice about it?
Thank you for your time.
@joanne40226 you are trying to achieve something that as far as I know nobody has achieved to do successfully (and in a repeatable way). Even if you can create identical number of points on them, there is no guarantee that these points will correspond correctly (anatomically speaking) and averaging them may not give an accurate representation.
Typically one uses deformable registration to project all these shapes into a common coordinate system, do the averaging there and then sample the grid on the average model and inverse the deformation to map the grid points created on the average model to the subjects.
You can sort of replicate this pipeline in ALPACA (SLicerMorph extension). You will start with one sample (as opposed to the mean), create your grid points. Then use ALPACA to transfer those points to the remaining samples. To create the mean model, you can take this set of points (that now exists for all your samples), feed them into the GPA and estimate a mean shape. You can then assign one of your samples as a reference sample and deform it to this mean shape, and export it as a model.
ANother alternative is a different extension called Auto3DGM that tries to create points and correspondence at the same time. It is typically used for evolutionary studies, where correspondences are hard to pin down. I think their repository also lists some papers that explain the method along with what groups that it has been applied to. After the AUto3DGM creates these points, you can repeat the GPA step I described above to create your mean model.
When you are working with GPA make sure to check “Skip Scaling” during GPA alignment, so that the final mean shape is in physical coordinates (as opposed to being in procrustes coordinates).