Plotting the signals

I could not reproduce any crash with the scripts above, so maybe the issue is how you fill the tables with real data. I’ve made a couple of fixes and improvement (fix order of views, fit plot to the view, adjust labeling, etc.) and this is the result:

The updated code:

def SetLayout(nChannels):
    customLayout=(
    "<layout type=\"horizontal\" split=\"true\">" 
        "<item>"
            "<layout type=\"vertical\" split=\"true\">"
                "<item>"
                    "<view class=\"vtkMRMLSliceNode\" singletontag=\"Red\">"
                        "<property name=\"orientation\" action=\"default\">Axis</property>"
                        "<property name=\"viewlabel\" action=\"default\">R</property>"
                        "<property name=\"viewcolor\" action=\"default\">#F34A33</property>"
                    "</view>"
                "</item>"
                "<item>"
                    "<view class=\"vtkMRMLSliceNode\" singletontag=\"Yellow\">"
                        "<property name=\"orientation\" action=\"default\">Sagittal</property>"
                        "<property name=\"viewlabel\" action=\"default\">Y</property>"
                        "<property name=\"viewcolor\" action=\"default\">#EDD54C</property>"
                    "</view>"
                "</item>"
                "<item>"
                    "<view class=\"vtkMRMLSliceNode\" singletontag=\"Green\">"
                        "<property name=\"orientation\" action=\"default\">Coronal</property>"
                        "<property name=\"viewlabel\" action=\"default\">G</property>"
                        "<property name=\"viewcolor\" action=\"default\">#6EB04B</property>"
                    "</view>"
                "</item>"
            "</layout>"
        "</item>"
        "<item>"
            "<view class=\"vtkMRMLViewNode\" singletontag=\"1\">"
                "<property name=\"viewlabel\" action=\"default\">1</property>"
            "</view>"
        "</item>"
        "<item>"
            "<layout type=\"vertical\">")
    for i in range(nChannels):
        customLayout+='<item><view class="vtkMRMLPlotViewNode" singletontag="SignalView'+'-{}"'.format(i)+'>'
        customLayout+='<property name="viewlabel" action="default">'+'P{}'.format(i+1)+'</property>'
        customLayout+='</view></item>'
    customLayout+='</layout></item></layout>'
    slicer.customLayout = customLayout
    customLayoutId=501
    layoutManager=slicer.app.layoutManager()
    if not layoutManager.layoutLogic().GetLayoutNode().SetLayoutDescription(customLayoutId,customLayout):
        layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId,customLayout)
    layoutManager.setLayout(customLayoutId)
    for i in range(nChannels):
        layoutManager.plotWidget(i).plotController().setVisible(False)

def PlotSignal():
    import math
    num=10
    SetLayout(num)
    maxNumOfPoints=100
    layoutManager=slicer.app.layoutManager()
    if layoutManager.plotViewCount!=num:
        print("Plot view number({}) is not equal to signal channel number({})".format(layoutManager.plotViewCount,num))
        return
    for channel in range(num):
        tableNode=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLTableNode","Table{}".format(channel))
        table=tableNode.GetTable()
        table.Initialize()
        arrX=vtk.vtkFloatArray()
        arrX.SetName("Time(ms)")
        table.AddColumn(arrX)
        arrY=vtk.vtkFloatArray()
        name="{0} mm".format(channel)
        arrY.SetName(name)
        table.AddColumn(arrY)
        table.SetNumberOfRows(maxNumOfPoints)
        for j in range(maxNumOfPoints):
            table.SetValue(j,0,j)
            table.SetValue(j,1,math.sin(j))
        table.Modified()
        #Create two plot series nodes
        name="{0} mm".format(channel)
        plotSeriesNode=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLPlotSeriesNode","Signal@{0}".format(name))
        plotSeriesNode.SetAndObserveTableNodeID(tableNode.GetID())
        plotSeriesNode.SetXColumnName("Time(ms)")
        plotSeriesNode.SetYColumnName(name)
        plotSeriesNode.SetPlotType(slicer.vtkMRMLPlotSeriesNode.PlotTypeLine)
        plotSeriesNode.SetUniqueColor()
        plotChartNode=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLPlotChartNode","Chart@{0}".format(name))
        plotChartNode.AddAndObservePlotSeriesNodeID(plotSeriesNode.GetID())
        plotChartNode.SetXAxisTitle('') # 'Time(ms)'
        plotChartNode.SetYAxisTitle(f'uV @{name}')
        plotChartNode.SetAxisTitleFontSize(9)
        plotChartNode.SetAxisLabelFontSize(9)
        plotChartNode.SetYAxisRangeAuto(True)
        plotChartNode.SetXAxisRangeAuto(True)
        plotChartNode.SetLegendVisibility(False)
        plotViewNode=slicer.mrmlScene.GetSingletonNode(f'SignalView-{channel}','vtkMRMLPlotViewNode')
        plotViewNode.SetPlotChartNodeID(plotChartNode.GetID())
    for i in range(layoutManager.plotViewCount):
        layoutManager.plotWidget(i).plotView().fitToContent()

PlotSignal()
1 Like