Surface mesh with multiple scalar data

Slicer supports loading of surface meshes (polydata) and volumetric meshes (unstructured grid).

The data set that you get from from the EP mapping system is just a point cloud (earlier CartoEP versions were also able to export the reconstructed surface but more recent ones just provide the points).

The simplest way to store a point cloud is to use a POLYDATA. You can fix test1.vtk by replacing

DATASET STRUCTURED_GRID
DIMENSIONS 49328 1 1 

by

DATASET POLYDATA 

You can load this file into Slicer and visualize by applying a vtkGlyph3D filter - by copy-pasting this into the Python console:

pointsModelNode = getNode('test1')
glypher = vtk.vtkGlyph3D()
glypher.SetInputConnection(pointsModelNode.GetPolyDataConnection())
glyph = vtk.vtkSphereSource()
glypher.SetSourceConnection(glyph.GetOutputPort())
glypher.SetScaleModeToDataScalingOff()
glypher.Update()
glyphedModel = slicer.modules.models.logic().AddModel(glypher.GetOutputPort())

You can also reconstruct a surface:

pointsModelNode = getNode('test1')
numberOfSamples = 256.0
normalSamplingFactor = 5e-5

polyData = pointsModelNode.GetPolyData()

sampleSize = max(polyData.GetNumberOfPoints() * normalSamplingFactor, 10)
normals = vtk.vtkPCANormalEstimation()
normals.SetInputData(polyData)
normals.SetSampleSize(sampleSize)
normals.SetNormalOrientationToGraphTraversal()
normals.FlipNormalsOff()

distance = vtk.vtkSignedDistance()
distance.SetInputConnection(normals.GetOutputPort())

boundingBox = vtk.vtkBoundingBox()
boundingBox.SetBounds(polyData.GetBounds())

radius = boundingBox.GetMaxLength() / numberOfSamples * 4.0  # about 4 voxels
distance.SetRadius(radius)
boundingBox.Inflate(boundingBox.GetLength(0) * .1, boundingBox.GetLength(1) * .1, boundingBox.GetLength(2) * .1)
distance.SetDimensions(int(numberOfSamples), int(numberOfSamples), int(numberOfSamples))
bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
boundingBox.GetBounds(bounds)
distance.SetBounds(bounds)

surface = vtk.vtkExtractSurface()
surface.SetInputConnection(distance.GetOutputPort())
surface.SetRadius(radius * .99)
surfaceModel = slicer.modules.models.logic().AddModel(surface.GetOutputPort())

image

We also have a small Slicer extension that can import EP maps that you might find useful. They could be improved to reconstruct the surface, etc. as has been discussed here, so you might do without Matlab and just do all your analysis and visualization in Python.

What kind of visualization and analysis would you like to do?

1 Like