Using Slicer plot view signal

Hello,

I am not used to coding python scripts for Slicer and I am wondering how I can use the dataSelected signal provided by PlotViews.

I am creating some plots to visualize PCA data and I would like to detect when a point is selected on my projection plot.

I tried the following code to generate all the nodes I need and tried to create a qMRMLPlotView object to connect the dataSelected signal but it doesn’t seem to be working.

Do you know a proper way to use this signal?

code:

def generate2DVisualisationNodes(self):
    #clean previously created nodes
    self.delete2DVisualisationNodes()

    #generate PlotChartNodes to visualize the variance plot and the Projection plot
    variancePlotChartNode = self.generateVariancePlot()
    projectionPlotChartNode = self.generateProjectionPlot()

    # Switch to a layout that contains a plot view to create a plot widget
    layoutManager = slicer.app.layoutManager()
    layoutWithPlot = slicer.modules.plots.logic().GetLayoutWithPlot(layoutManager.layout)
    layoutManager.setLayout(layoutWithPlot)

    # Select chart in plot view
    plotWidget = layoutManager.plotWidget(0)
    plotViewNode = plotWidget.mrmlPlotViewNode()

    plotViewNode.SetPlotChartNodeID(projectionPlotChartNode.GetID())
    plotViewNode.SetPlotChartNodeID(variancePlotChartNode.GetID())

    plotView = slicer.qMRMLPlotView()
    plotView.setMRMLPlotViewNode(plotViewNode)
    plotView.connect("dataSelected(vtkStringArray, vtkCollection)", self.onDataSelected)

def generateProjectionPlot(self):
    projectionTableNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLTableNode","PCA projection table")
    table = projectionTableNode.GetTable()

    pc1=vtk.vtkFloatArray()
    pc2=vtk.vtkFloatArray()

    pc1.SetName("pc1")
    pc2.SetName("pc2")

    table.AddColumn(pc1)
    table.AddColumn(pc2)

    #Projection plot serie
    projectionPlotSeries = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLPlotSeriesNode", "PCA projection")
    projectionPlotSeries.SetAndObserveTableNodeID(projectionTableNode.GetID())
    projectionPlotSeries.SetXColumnName("pc1")
    projectionPlotSeries.SetYColumnName("pc2")
    projectionPlotSeries.SetPlotType(slicer.vtkMRMLPlotSeriesNode.PlotTypeScatter)
    projectionPlotSeries.SetLineStyle(slicer.vtkMRMLPlotSeriesNode.LineStyleNone)
    projectionPlotSeries.SetUniqueColor()

    # Create projection plot chart node
    projectionPlotChartNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLPlotChartNode","PCA projection plot chart")
       projectionPlotChartNode.AddAndObservePlotSeriesNodeID(projectionPlotSeries.GetID())
    projectionPlotChartNode.SetTitle('Population projection')
    projectionPlotChartNode.SetXAxisTitle('pc1')
    projectionPlotChartNode.SetYAxisTitle('pc2')

    return projectionPlotChartNode

Thank you!

Mateo

The correct syntax of creating the connection is:

plotView.connect("dataSelected(vtkStringArray*, vtkCollection*)", self.onDataSelected)

If you try to connect a non-existing signal then you can see an error message in the application log.

1 Like

Thank you for this quick answer, I have no more error in the application log but it’s still not working. Am I connecting the signal of the right object?
I wonder if there is a way to directly get the qMRMLPlotView object of Slicer instead of creating one.

Now it’s working, I was not creating the qMRMLPlotView object the right way. using the plotWidget object to create it solved my problem.

Thank you for your help!

here is the code that worked for me

    plotWidget = layoutManager.plotWidget(0)
    plotViewNode = plotWidget.mrmlPlotViewNode()

    plotViewNode.SetPlotChartNodeID(projectionPlotChartNode.GetID())
    plotViewNode.SetPlotChartNodeID(variancePlotChartNode.GetID())

    plotView = plotWidget.plotView()
    plotView.connect("dataSelected(vtkStringArray*, vtkCollection*)", self.onDataSelected)
1 Like

Hi Mateo,

It will be great if you can add the example as documentation here:
https://www.slicer.org/wiki/Documentation/Nightly/Developers/Plots

in the Signal section

or/and

https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository

Thanks in advance,

Cheers,
Davide.

Hi Davide,

Unfortunately, I don’t have the rights to modify the Slicer wiki, I will try to send a request to do so

Cheers,
Mateo

1 Like

Ok thanks! In the case you don’t manage to get the rights, I can copy and paste the example script (if for you it is ok).

1 Like

Sure, I have no problem with that, I let you do it, I think it will be easier like this.

Also, I find out that it could be useful to disconnect the signal before connecting it, I had Slicer crashes while reloading the module and using the signal.