Skip to content

Instantly share code, notes, and snippets.

@pieper
Last active December 26, 2022 00:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pieper/f9da3e0a73c70981b48d0747132526d5 to your computer and use it in GitHub Desktop.
Save pieper/f9da3e0a73c70981b48d0747132526d5 to your computer and use it in GitHub Desktop.
Slicer CPPYY example
# Copyright Steve Pieper
# https://github.com/Slicer/Slicer/blob/master/License.txt
# Demo video: https://youtu.be/xcQKj4yp2nw
"""
exec(open('/Users/pieper/slicer/latest/SlicerTMSGuide/guide.py', 'r').read())
"""
import cppyy
import numpy
import os
import time
def arrayFromModelPointDataModified(modelNode, arrayName):
"""Indicate that modification of a numpy array returned by :py:meth:`arrayFromModelPoints` has been completed."""
arrayVtk = modelNode.GetPolyData().GetPointData().GetArray(arrayName)
arrayVtk.Modified()
slicer.util.arrayFromModelPointDataModified = arrayFromModelPointDataModified
slicer.mrmlScene.Clear(0)
path = '/Users/pieper/slicer/latest/SlicerTMSGuide'
pialPath = os.path.join(path, 'data/lh.pial')
thicknessPath = os.path.join(path, 'data/lh.thickness')
pial = slicer.util.loadModel(pialPath)
slicer.util.loadScalarOverlay(thicknessPath, pial.GetID())
pial.GetDisplayNode().SetScalarRangeFlag(0)
pial.GetDisplayNode().SetScalarRange(0,50)
pial.GetDisplayNode().SetAndObserveColorNodeID('vtkMRMLColorTableNodeFileCividis.txt')
ras = [-65, 10, 26]
markupsLogic = slicer.vtkSlicerMarkupsLogic()
markupsLogic.SetMRMLScene(slicer.mrmlScene)
markupsLogic.AddFiducial(*ras)
markupsLogic.JumpSlicesToLocation(*ras, False)
markupFiducials = slicer.util.getNode('F')
markupFiducials.GetDisplayNode().SetTextScale(0)
markupFiducials.GetDisplayNode().SetGlyphScale(10)
markupFiducials.GetDisplayNode().SetSelectedColor([1,1,0])
markupFiducials.GetDisplayNode().SetSnapMode(slicer.vtkMRMLMarkupsDisplayNode.SnapModeUnconstrained)
def updateOverlay(caller, event):
pointsArray = slicer.util.arrayFromModelPoints(pial)
scalarArray = slicer.util.arrayFromModelPointData(pial, 'lh.thickness')
pointArray = slicer.util.arrayFromMarkupsControlPoints(markupFiducials)
func1d = lambda p: numpy.linalg.norm(pointArray - p)
scalarArray[:] = numpy.apply_along_axis(func1d, 1, pointsArray)
slicer.util.arrayFromModelPointDataModified(pial, 'lh.thickness')
def compileAndImportCPP(cppSource):
namespaceTag = "cppyy_"+str(time.time()).replace(".", "_")
cppSource = "namespace " + namespaceTag + " {" + cppSource + " }"
cppyy.cppdef(cppSource)
exec("from cppyy.gbl import " + namespaceTag)
namespace = eval("cppyy.gbl." + namespaceTag)
return namespace
cppyy.include("math.h")
fillWithDistancesSource = """
void fillWithDistances(void *pointsArrayData, void *pointData, void *scalarArrayData, unsigned int size) {
float *pointsArray = (float *)pointsArrayData;
double *point = (double *)pointData;
float *scalarArray = (float *)scalarArrayData;
unsigned int offset;
for (offset = 0; offset < size; offset++) {
scalarArray[offset] = sqrt (
(pointsArray[offset*3 + 0] - point[0]) * (pointsArray[offset*3 + 0] - point[0]) +
(pointsArray[offset*3 + 1] - point[1]) * (pointsArray[offset*3 + 1] - point[1]) +
(pointsArray[offset*3 + 2] - point[2]) * (pointsArray[offset*3 + 2] - point[2]) );
}
}
"""
fillWithDistances = compileAndImportCPP(fillWithDistancesSource).fillWithDistances
def updateOverlayCpp(caller, event):
pointsArray = slicer.util.arrayFromModelPoints(pial)
scalarArray = slicer.util.arrayFromModelPointData(pial, 'lh.thickness')
pointArray = slicer.util.arrayFromMarkupsControlPoints(markupFiducials)
fillWithDistances(pointsArray.data, pointArray.data, scalarArray.data, scalarArray.size)
slicer.util.arrayFromModelPointDataModified(pial, 'lh.thickness')
pointsArray = slicer.util.arrayFromModelPoints(pial)
scalarArray = slicer.util.arrayFromModelPointData(pial, 'lh.thickness')
pointArray = slicer.util.arrayFromMarkupsControlPoints(markupFiducials)
updateOverlayCpp(markupFiducials, slicer.vtkMRMLMarkupsNode.PointModifiedEvent)
ras = [50, 0, -70]
labelFiducial = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode")
markupsLogic.SetActiveListID(labelFiducial)
markupsLogic.AddFiducial(*ras)
markupsLogic.JumpSlicesToLocation(*ras, False)
labelFiducial.GetDisplayNode().SetTextScale(10)
labelFiducial.GetDisplayNode().SetGlyphScale(0)
labelFiducial.GetDisplayNode().SetSelectedColor([1,1,0])
labelFiducial.GetDisplayNode().SetSnapMode(slicer.vtkMRMLMarkupsDisplayNode.SnapModeUnconstrained)
#mode = "python"
mode = "cppyy"
if mode == "python":
labelFiducial.SetNthControlPointLabel(0, "Python")
markupFiducials.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateOverlay)
else:
labelFiducial.SetNthControlPointLabel(0, "Python + CPPYY")
markupFiducials.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, updateOverlayCpp)
@pieper
Copy link
Author

pieper commented Dec 26, 2022

Installing on a mac build currently requires setting this variable so that the pip install succeeds in building the prereqs: SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk ./Slicer-build/Slicer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment