Calculate a scalp to scalp distance

Dear Slicer experts,

Quick mail to know if you know a way/a module to calculate a scalp to scalp distance (i.e. distance along the surface)?

More than “CurveMaker”, I would like an automatic way to realize that (1/mesh the brain,2/ calculate distance between nodes?).

Thanks in advance,
All the best,

Frederic

You can use Model to model distance extension to measure distance between surfaces.

What do you mean by “More than CurveMaker…”?

Hi Andras,
Thanks for your quick reply.

My question lacked of precision: I have several T1-weighted images, and I would like, always on the same scalp, calculate distance along the surface.

“Model to model distance” seems works for two different models, I would rather work just about one model (T1–>mesh of the scalp–>compute the distance between two points on the mesh).
Is-it possible?

Thanks a lot!
Frederic

I don’t know about any module that provides this but it’s very easy to create a new module for this, as this VTK class compute geodesic path on a surface: https://www.vtk.org/doc/nightly/html/classvtkDijkstraGraphGeodesicPath.html#details

2 Likes

Thanks Andrea,
Very easy for you, but not for me ;).

Before use the VTK class, how is-it possible to mesh the scalp of T1 image with 3dslicer?

Thanks once again,

Frederic

Use Segment Editor tool to create surface mesh from an image.

1 Like

Great, Thanks a lot Andras.

Dear Andras and Slicer users,
I have begun my script to calculate distance along the surface.
However, I butt into an obstacle. Indeed, How could I make correspond vertex (in bold below) of my vtkPolyDataMapper with coordinate obtain by the fiducal properties (in italic)?
Perhaps by a KD-Tree (tk.vtkKdTree)?

Thanks in advance.
Frederic

In python:

##Access to Fiducial Properties
fidList = slicer.util.getNode('F')
numFids = fidList.GetNumberOfFiducials()
for i in range(numFids):
  ras = [0,0,0]
  fidList.GetNthFiducialPosition(i,ras)
  print i,": RAS =",ras_

#vtkDijkstraGraphGeodesicPath
dijkstra = vtk.vtkDijkstraGraphGeodesicPath()
dijkstra.SetInputConnection(reader.GetOutputPort())
dijkstra.SetStartVertex(**20**)
dijkstra.SetEndVertex(**500000**)
dijkstra.Update()
1 Like

To get index of a point closest to a spatial position, you need use a locator:

somePolyData = someModelNode.GetPolyData()
pointLocator = vtk.vtkPointLocator()
pointLocator.SetDataSet(somePolyData)
pointLocator.BuildLocator()
closestPointId = curvePointsLocator.FindClosestPoint(point)

Not that these are all standard VTK operations, there is nothing specific to Slicer. So, you may find answers by searching in VTK source code, reading the VTK textbook (it is worth reading the book cover to cover, a few times), and browsing VTK examples.

1 Like

Hello,I have the same question with you? On the surface of the scalp,how to measure the distance between two pionts without Curve maker module?Dose the problem has been solved?
Thanks for your attention!

@Frederic it would be great if you could upload current version of your module to Github, even if it is not functional yet. It would allow me, @doc-xie, and others to see the progress and help out. The core of this feature can be implemented by adding 30-40 lines of python code to the module template generated by Extension wizard module, so it should be possible to complete it in a couple of days. If you get stuck anywhere then let us know.

Hi,
First of all, thanks @lassoan for your locator code.
Second, my in progress draft for the module was here, with two python scripts: One is a standalone version for python (without 3dslicer) and the second for 3dslicer.
I am moving slowly because I found this RvtkStatismo that made all that I want (HTH @doc-xie) .

Thanks for the update. Slicer is a frontend, from where you can use various libraries. So, if you find Statismo useful then you can add wrappers to make it avaiable directly from Slicer.

@doc-xie if you are interested to pick it up from where @Frederic left off then, I would recommend to create a skeleton extension and a Python scripted module inside (as explained in the Slicer programming tutorial) and add Frederic’s processing code to that.

1 Like

Yes, thanks for your believing, I am very intresting about 3D Slicer, but I am a new learner and have not any knowledge about Python. So I decide to study it with your help because the importance of Python. By the way, I am looking forward to the progress of this topic!

1 Like

I have made much advance in this script, I will return to you when I will have more time (I defend my PhD research in two weeks).
Best,
Frederic

1 Like

OK!
Waiting for your good news!

Hello Frederic!
Is there any progress in the calculation tools or methods of measurement excepting Curve maker Module in 3D Slicer?
Best wishes!

Hi doc-xie.
Yes, I have update the Github.
@lassoan could you help me to create an extension (I have begun on my Github)?
@doc-xie For the moment, you could use it from your python interactor (for 3 points):

1/ Load your model in 3dslicer
2/ Draw your 3 points with the “Create-and-Place-Fiducial” button
3/ Insert this code in your python interactor:

import sys, slicer, numpy, os, math, vtk

model = getNode('name_of_your_data') #Go to Data module and see the name of your model, "Name"
#Access to Fiducial Properties (to determinate the start and the end point of the geodesic path)
fidList = slicer.util.getNode('F')
numFids = fidList.GetNumberOfFiducials()
list=[]
for i in range(numFids):
  ras = [0,0,0]
  fidList.GetNthFiducialPosition(i,ras)
  print i,": RAS =",ras
  list.append(ras)
  
#create locator
pd = model.GetModelDisplayNode()
pd1=pd.GetOutputPolyData()
pd1.GetNumberOfPoints()
loc = vtk.vtkPointLocator()
loc.SetDataSet(pd1)
loc.BuildLocator()
closestPointId = loc.FindClosestPoint(list[0]) #point1 
closestPointId1 = loc.FindClosestPoint(list[1]) #point2
closestPointId2 = loc.FindClosestPoint(list[2]) #point3

#get the distance of the geodesic path 
appendFilter = vtk.vtkAppendFilter()
appendFilter.MergePointsOn()
points = vtk.vtkPoints()

vIds = [closestPointId,closestPointId1,closestPointId2]
p0 = [0,0,0]
p1 = [0,0,0]
dist = 0.0
for n in range(len(vIds)-1):
	v0 = vIds[n]
	v1 = vIds[n+1]
	
	#create geodesic path: vtkDijkstraGraphGeodesicPath
	dijkstra = vtk.vtkDijkstraGraphGeodesicPath()
	dijkstra.SetInputConnection(pd.GetOutputPolyDataConnection())
	dijkstra.SetStartVertex(v0)
	dijkstra.SetEndVertex(v1)
	dijkstra.Update()
				
	pts = dijkstra.GetOutput().GetPoints()
	end = n<len(vIds)-2 and 0 or -1
	for ptId in range(pts.GetNumberOfPoints()-1, end, -1):
		pts.GetPoint(ptId, p0)
		points.InsertNextPoint(p0)		
	
	for ptId in range(pts.GetNumberOfPoints()-1):
		pts.GetPoint(ptId, p0)
		pts.GetPoint(ptId+1, p1)
		dist += math.sqrt(vtk.vtkMath.Distance2BetweenPoints(p0, p1))
		
	appendFilter.AddInputConnection(dijkstra.GetOutputPort())

print 'length= ', dist/10 ,'cm'

Best

Hi,Frederic!
After I insert the code in my phthon interactor, what i get is following:

Traceback (most recent call last):
File “”, line 1, in
NameError: name ‘vIds’ is not defined

print 'length= ', dist/10 ,‘cm’
length= 0.0 cm

What is the reason?
Thanks a lot!
doc-xie

Don’t forget to change this line:
model = getNode('name_of_your_data') #Go to Data module and see the name of your model, "Name"