Installation

Install in local Python environment (where jupyter notebook is started):

python -m pip install ipywidgets pandas

Install in Slicer Python environment (by running the cell below):

In [ ]:
# There are no official pyzmq wheels for Python-3.6 for Windows, so we have to install manually
import os
if os.name=='nt':
    pip_install("https://files.pythonhosted.org/packages/94/e1/13059383d21444caa16306b48c8bf7a62331ca361d553d2119696ea67119/pyzmq-19.0.0-cp36-cp36m-win_amd64.whl")

pip_install("ipywidgets pandas")

Interactive volume rendering

The entire view layout or selected widgets can be displayed in a notebook cell. Views can be shown using interactive widgets (slice scrolling, view rotation). Rendering happens server-side, in Slicer, which can run on the cloud, on a container. Source data does not have to be sent to the user's computer.

In [3]:
# Get a volume
slicer.mrmlScene.Clear()
volume = slicer.nb.downloadFromURL(
  'https://github.com/Slicer/SlicerTestingData/releases/download/SHA256/4507b664690840abb6cb9af2d919377ffc4ef75b167cb6fd0f747befdb12e38e',
  'CTChest.nrrd', "CT")[0]

# Enable 3D volume rendering
slicer.nb.showVolumeRendering(volume)

slicer.nb.displayViews("FourUp")
#slicer.nb.displayViews("Conventional")
# slicer.nb.displaySliceView('Red')
# slicer.nb.display3DView()
Out[3]:
In [4]:
# Interactive 3D view
from ipywidgets import interact

@interact(roll=(-90.0,90.0,5), pitch=(-90.0,90.0,5), yaw=(-180.0,180.0,5))
def update(roll=0, pitch=0, yaw=0):
    return slicer.nb.display3DView(0, orientation=[roll, pitch, yaw])

Interactive segmentation visualization

In [5]:
# Create segmentation using thresholding
slicer.util.selectModule("SegmentEditor")
segmentEditorWidget = slicer.modules.segmenteditor.widgetRepresentation().self().editor
segmentEditorNode = segmentEditorWidget.mrmlSegmentEditorNode()

segmentationNode=slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLSegmentationNode")
if not segmentationNode:
    segmentationNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentationNode")
segmentEditorWidget.setSegmentationNode(segmentationNode)
segmentEditorWidget.setMasterVolumeNode(volume)
segmentationNode.GetSegmentation().RemoveAllSegments()

# Add bone segment
segmentID = segmentationNode.GetSegmentation().AddEmptySegment("bone")
segmentationNode.GetSegmentation().GetSegment(segmentID).SetColor(0.9, 0.8, 0.6)
segmentEditorNode.SetSelectedSegmentID(segmentID)
segmentEditorWidget.setActiveEffectByName("Threshold")
effect = segmentEditorWidget.activeEffect()
effect.setParameter("MinimumThreshold", 220)
effect.setParameter("MaximumThreshold", 2000)
effect.self().onApply()

# Add body segment
segmentID = segmentationNode.GetSegmentation().AddEmptySegment("body")
segmentEditorNode.SetSelectedSegmentID(segmentID)
segmentationNode.GetSegmentation().GetSegment(segmentID).SetColor(0.7, 0.2, 0.3)
segmentEditorWidget.setActiveEffectByName("Threshold")
effect = segmentEditorWidget.activeEffect()
effect.setParameter("MinimumThreshold", -500)
effect.setParameter("MaximumThreshold", 220)
effect.self().onApply()

# Add a sphere-shaped segment
sphereSource = vtk.vtkSphereSource()
sphereSource.SetCenter(-100, -30, -170)
sphereSource.SetRadius(45)
sphereSource.SetThetaResolution(20)
sphereSource.Update()
segmentationNode.AddSegmentFromClosedSurfaceRepresentation(sphereSource.GetOutput(), "sphere", [0.2,0.8,0.1])

# Show results
slicer.modules.volumerendering.logic().GetFirstVolumeRenderingDisplayNode(volume).VisibilityOff() # hide volume rendering
segmentationNode.GetSegmentation().SetConversionParameter('Smoothing factor','0.0') # disable 3D smoothing
segmentationNode.CreateClosedSurfaceRepresentation() # show segmentation in 3D
segmentationNode.GetDisplayNode().SetOpacity3D(0.5)
volume.GetDisplayNode().AutoWindowLevelOff()
volume.GetDisplayNode().SetWindowLevel(420,30)
slicer.nb.displayViews()
Out[5]: