Cannot store MultiVolumeExplorer chart to .svg

Operating system: Windows 7 Enterprise 64-bit (6.1, Build 7601)
Slicer version: version 4.10.2 revision 28257 built 2019-05-22

Expected behavior:
I am using the MultiVolumeExporer to extract a time intensity curve of a DCE MRI scan. To do this, I made a segmentation of the tumor and created a chart of the signal intensity over time.

There are actually 2 features that I would like.

  1. to access the raw extracted data values (i.e. the mean signal intensity over time)
  2. to save the chart that was created as an SVG such that I can use it in full resolution.

Actual behavior:

  1. the raw values are stored in a node that I am not able to access.
  2. I am not able to save the chart other than saving it a snapshot.

I found the following topic on exporting plots from slicer Exporting plots from Slicer

Using the information there, combined with the information provided in this commit: ENH: add option to save plot contents as svg · Slicer/Slicer@54ba5e0 · GitHub

I tried to save the chart in the following manner:

e = vtk.vtkGL2PSExporter()
e.SetFileFormatToSVG()
lm = slicer.app.layoutManager()
e.SetRenderWindow(lm.plotWidget(1).plotView())
e.SetFilePrefix(‘D:/pre’)
e.Update()

When I do this I get the following error message:
“TypeError: SetRenderWindow argument 1: method requires a VTK object”

I understand from this that the plotView apparently isn’t a VTK object. However I have no clue about how to change this or why it did seem to work in the above mentioned topic on chart exporting.

Also I tried to use the saveAsSVG function that war implemented in the above mentioned commit, however it does not seem to be available in slicer 4.10.2. I tried to use the slicer nightly build instead, however the MultiVolumeExplorer in the nightly doesn’t work as expected and doesn’t provide a chart.

Can you help me out here?

Ah, okay I obviously don’t need the plotWidget but need to access the chartWidget and get it’s renderer.
However unlike the sliceWidget, the chartWidget doesn’t have a lm.chartWidget(1).chartView().renderWindow()…

How do I access the renderer to pass it onto the exporter??

Ok, I didn’t know this but apparently you need to access the mrmlScene nodes and not the layoutManager nodes. I got the data out in the following manner:

# My goal is to get the datapoints from 'Chart_6'
n = slicer.mrmlScene.GetNodesByName('Chart_6')
for nn in n:
  print(nn) # Apparently only one node available

# Get the names of the data series in this node
for i in range(nn.GetArrayNames().GetNumberOfValues()):
  print(nn.GetArrayNames().GetValue(i))

# I want to have the series that is named 'tissue'
a_node_name = nn.GetArray('tissue')

a_MRML_node = slicer.mrmlScene.GetNodeByID(a_node_name)

a_vtk_node = a_MRML_node.GetArray()
data = [a_vtk_node.GetValue(e) for e in range(a_vtk_node.GetNumberOfValues())]

So I got the chart data which allows me to plot the graph myself. But still I think it should be possible to get the actual render itself. Can someone help me do this?

1 Like

You can get numpy array from a volume node using a single command: slicer.util.arrayFromVolume.

VTK plotting is extremely fast and allows rich interactions. VTK should be able to produce SVG plots, too, but probably it is simpler to just use matplotlib.

A complete example that gets voxels of an MRI volume as numpy array, computes histogram, draws a plot, saves as svg, and display it in a web view:

# Get a volume from SampleData and compute its histogram
import SampleData
import numpy as np
volumeNode = SampleData.SampleDataLogic().downloadMRHead()
volumeVoxels = slicer.util.arrayFromVolume(volumeNode)
histogram = np.histogram(volumeVoxels, bins=50)

# Make sure matplotlib is installed
try:
  import matplotlib
except ModuleNotFoundError:
  pip_install('matplotlib')
  import matplotlib

matplotlib.use('Agg')

# Show a plot using matplotlib
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(histogram[1][1:], histogram[0].astype(float))
ax.grid(True)
ax.set_ylim((0, 4e5))
outputFilePath = slicer.app.temporaryPath+'/test.svg'
plt.savefig(outputFilePath)

# Show the saved svg file in a web view window
webView = slicer.qSlicerWebWidget()
webView.url = qt.QUrl().fromLocalFile(outputFilePath)
webView.show()