def hausdorffDistance(self,fiber1,fiber2):
    """
    calculate the distance between two fiber bundles
    Based on code from Laurent Chauvin
    """
    polyA = fiber1.GetPolyData()
    polyB = fiber2.GetPolyData()

    locA = vtk.vtkMergePoints()
    locB = vtk.vtkMergePoints()

    locA.SetDataSet(polyA)
    locB.SetDataSet(polyB)

    locs = (locA,locB)
    for loc in locs:
        loc.AutomaticOn()
        loc.BuildLocator()

    ptsA = polyA.GetPoints()
    ptsB = polyB.GetPoints()

    rangeA = ptsA.GetNumberOfPoints()
    rangeB = ptsB.GetNumberOfPoints()

    maxd = 0.0
    maxd1 = 0.0
    avgd = 0.0
    avgd1 = 0.0

    distanceA = vtk.vtkFloatArray()
    distanceA.SetName("Distance")
    for i in range(rangeA):
        pt = ptsA.GetPoint(i)
        bid = locB.FindClosestPoint(pt)
        ptb = ptsB.GetPoint(bid)
        d = self.pointDistance(pt,ptb)
        distanceA.InsertNextValue(d)
        avgd += d
        if d > maxd:
            maxd = d
    avgd = avgd / rangeA

    distanceB = vtk.vtkFloatArray()
    distanceB.SetName("Distance")
    for i in range(rangeB):
        pt = ptsB.GetPoint(i)
        bid = locA.FindClosestPoint(pt)
        ptb = ptsA.GetPoint(bid)
        d = self.pointDistance(pt,ptb)
        distanceB.InsertNextValue(d)
        avgd1 += d
        if d > maxd1:
            maxd1 = d
    avgd1 = avgd1 / rangeB

    polyA.GetPointData().SetScalars(distanceA)
    polyB.GetPointData().SetScalars(distanceB)

    return max(maxd,maxd1)
Example #2
0
  def __init__(self):
    self.__chartView = ctk.ctkVTKChartView()

    self.__bgxArray = vtk.vtkFloatArray()
    self.__bgyArray = vtk.vtkFloatArray()
    self.__bgxArray.SetName('')
    self.__bgyArray.SetName('1st multivolume')
    self.__chartTable = self.createNewVTKTable(self.__bgxArray, self.__bgyArray)

    self.__bgMultiVolumeNode = None
    self.__fgMultiVolumeNode = None

    self.__mvLabels = []

    self.__xLogScaleEnabled = False
    self.__yLogScaleEnabled = False

    self.__mvRange = [0,0]
    self.__nFramesForBaselineCalculation = 1

    self.__chartMode = None
    self.activateSignalIntensityMode()

    self.baselineAverageSignal = 0

    self.__showLegend = False
    def __init__(self):
        self.__chartView = ctk.ctkVTKChartView()

        self.__bgxArray = vtk.vtkFloatArray()
        self.__bgyArray = vtk.vtkFloatArray()
        self.__bgxArray.SetName('')
        self.__bgyArray.SetName('1st multivolume')
        self.__chartTable = self.createNewVTKTable(self.__bgxArray,
                                                   self.__bgyArray)

        self.__bgMultiVolumeNode = None
        self.__fgMultiVolumeNode = None

        self.__mvLabels = []

        self.__xLogScaleEnabled = False
        self.__yLogScaleEnabled = False

        self.__mvRange = [0, 0]
        self.__nFramesForBaselineCalculation = 1

        self.__chartMode = None
        self.activateSignalIntensityMode()

        self.baselineAverageSignal = 0

        self.__showLegend = False
  def onThresholdValuesChanged(self,lower,upper):
    # Check if this is the first update of the threshold range
    if self.thresholdFlag == 1:
      newScalars = vtk.vtkFloatArray()
      newScalars.SetNumberOfComponents( self.scalars.GetNumberOfComponents() )
      newScalars.SetNumberOfValues ( self.numberOfPoints )
      newScalars.SetName( "NewScalars" )
      # Set values of new scalars according to threshold
      for i in xrange( self.numberOfPoints ):
        value = self.scalars.GetValue( i )
        if value < lower:
          newScalars.SetValue( i, 0 )

        elif value > upper:
          newScalars.SetValue( i, self.range[1] )
        else:
  
          newScalars.SetValue( i, value )
      # Update the polydata with the new scalars
      self.polyData.GetPointData().AddArray( newScalars )
      self.polyData.GetPointData().RemoveArray( "NRRDImage" )
      self.polyData.Modified()
      self.outputModel.SetAndObservePolyData( self.polyData )
      self.outputModel.GetDisplayNode().SetScalarVisibility( 1 )
      self.outputModel.GetDisplayNode().SetActiveScalarName( "NewScalars" )
Example #5
0
    def onThresholdValuesChanged(self, lower, upper):
        # Check if this is the first update of the threshold range
        if self.thresholdFlag == 1:
            newScalars = vtk.vtkFloatArray()
            newScalars.SetNumberOfComponents(
                self.scalars.GetNumberOfComponents())
            newScalars.SetNumberOfValues(self.numberOfPoints)
            newScalars.SetName("NewScalars")
            # Set values of new scalars according to threshold
            for i in xrange(self.numberOfPoints):
                value = self.scalars.GetValue(i)
                if value < lower:
                    newScalars.SetValue(i, 0)

                elif value > upper:
                    newScalars.SetValue(i, self.range[1])
                else:

                    newScalars.SetValue(i, value)
            # Update the polydata with the new scalars
            self.polyData.GetPointData().AddArray(newScalars)
            self.polyData.GetPointData().RemoveArray("NRRDImage")
            self.polyData.Modified()
            self.outputModel.SetAndObservePolyData(self.polyData)
            self.outputModel.GetDisplayNode().SetScalarVisibility(1)
            self.outputModel.GetDisplayNode().SetActiveScalarName("NewScalars")
    def generateVTKFloatArrayFromNumpy(self, np_array):
        size = np_array.size

        vtk_float = vtk.vtkFloatArray()
        vtk_float.SetNumberOfComponents(1)
        for i in range(size):

            vtk_float.InsertNextTuple([np_array[i]])
        return vtk_float
    def __init__(self):
        self.__chartView = slicer.qMRMLPlotView()
        self.__chartView.setMRMLScene(slicer.mrmlScene)
        self.__chartViewNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLPlotViewNode")
        self.__chartView.setMRMLPlotViewNode(self.__chartViewNode)
        self.__chart = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLPlotChartNode")
        self.__chart.LegendVisibilityOff()
        self.__chart.SetAxisTitleFontSize(15)
        self.__chartViewNode.SetPlotChartNodeID(self.__chart.GetID())
        self.__chartView.show()

        self.__bgxArray = vtk.vtkFloatArray()
        self.__bgyArray = vtk.vtkFloatArray()
        self.__bgxArray.SetName('x')
        self.__bgyArray.SetName('1st multivolume')
        self.__chartTableNode = self.createNewVTKTableNode(
            self.__bgxArray, self.__bgyArray)
        self.__chartTable = self.__chartTableNode.GetTable()
        self.__fgChartTableNode = None

        self.__bgPlot = None
        self.__fgPlot = None

        self.__bgMultiVolumeNode = None
        self.__fgMultiVolumeNode = None

        self.__mvLabels = []

        self.__xLogScaleEnabled = False
        self.__yLogScaleEnabled = False

        self.__mvRange = [0, 0]
        self.__nFramesForBaselineCalculation = 1

        self.__chartMode = None
        self.activateSignalIntensityMode()

        self.baselineAverageSignal = 0

        self.__showLegend = False
Example #8
0
    def onProbeVolumeButtonClicked(self):
        # Set flag to prevent model from being thresholded without user input
        self.thresholdFlag = 0
        wallModel = self.inputModelSelector.currentNode()
        inputVol = self.inputVolumeSelector.currentNode()

        self.polyData = vtk.vtkPolyData()
        if not (wallModel):
            qt.QMessageBox.critical(slicer.util.mainWindow(),
                                    'Scar Visualization',
                                    'Wall model is required to proceed.')
        elif not (inputVol):
            qt.QMessageBox.critical(slicer.util.mainWindow(),
                                    'Scar Visualization',
                                    'Input volume is required to proceed.')
        else:
            self.outputModel = slicer.vtkMRMLModelNode()
            self.outputModel.SetName("Output Model")
            slicer.mrmlScene.AddNode(self.outputModel)
            paramProbe = {}
            paramProbe['InputVolume'] = inputVol
            paramProbe['InputModel'] = wallModel
            paramProbe['OutputModel'] = self.outputModel
            # Pass parameters to Probe Volume Model
            slicer.cli.run(slicer.modules.probevolumewithmodel,
                           None,
                           paramProbe,
                           wait_for_completion=True)
            # Set color of output model
            labelsColorNode = slicer.modules.colors.logic(
            ).GetColorTableNodeID(35)  # Color Warm Tint 3
            self.outputModel.GetDisplayNode().SetAndObserveColorNodeID(
                labelsColorNode)
            # Delete input model which is not required anymore
            slicer.mrmlScene.RemoveNode(wallModel)
            # Update threshold widget with scalar values from model
            self.polyData = self.outputModel.GetPolyData()
            self.numberOfPoints = self.polyData.GetNumberOfPoints()
            self.scalars = vtk.vtkFloatArray()
            self.scalars = self.polyData.GetPointData().GetScalars("NRRDImage")
            self.range = [0] * 2
            numberOfComponents = self.scalars.GetNumberOfComponents()
            for i in xrange(numberOfComponents):
                self.scalars.GetRange(self.range, i)
            lowerThreshold = self.range[0]
            upperThreshold = self.range[1]
            # Set threshold range according to current model
            self.threshold.minimum = lowerThreshold
            self.threshold.maximum = upperThreshold
            self.thresholdFlag = 1
 def onProbeVolumeButtonClicked(self): 
   # Set flag to prevent model from being thresholded without user input
   self.thresholdFlag = 0
   wallModel = self.inputModelSelector.currentNode() 
   inputVol = self.inputVolumeSelector.currentNode()
   
   self.polyData = vtk.vtkPolyData()
   if not (wallModel):
     qt.QMessageBox.critical(slicer.util.mainWindow(),
                            'Scar Visualization', 'Wall model is required to proceed.')
   elif not (inputVol):
     qt.QMessageBox.critical(slicer.util.mainWindow(),
                            'Scar Visualization', 'Input volume is required to proceed.')
   else:
     self.outputModel = slicer.vtkMRMLModelNode()
     self.outputModel.SetName( "Output Model" )
     slicer.mrmlScene.AddNode(self.outputModel)
     paramProbe = {}
     paramProbe['InputVolume'] = inputVol
     paramProbe['InputModel'] = wallModel
     paramProbe['OutputModel'] = self.outputModel
     # Pass parameters to Probe Volume Model
     slicer.cli.run( slicer.modules.probevolumewithmodel, None, paramProbe, wait_for_completion=True )
     # Set color of output model
     labelsColorNode = slicer.modules.colors.logic().GetColorTableNodeID(35)  # Color Warm Tint 3
     self.outputModel.GetDisplayNode().SetAndObserveColorNodeID(labelsColorNode)
     # Delete input model which is not required anymore
     slicer.mrmlScene.RemoveNode( wallModel )
     # Update threshold widget with scalar values from model
     self.polyData = self.outputModel.GetPolyData()
     self.numberOfPoints = self.polyData.GetNumberOfPoints()
     self.scalars = vtk.vtkFloatArray()
     self.scalars = self.polyData.GetPointData().GetScalars( "NRRDImage" )  
     self.range = [0] * 2
     numberOfComponents = self.scalars.GetNumberOfComponents()
     for i in xrange ( numberOfComponents ):
       self.scalars.GetRange(self.range, i)
     lowerThreshold = self.range[0]
     upperThreshold = self.range[1]
     # Set threshold range according to current model
     self.threshold.minimum = lowerThreshold
     self.threshold.maximum = upperThreshold
     self.thresholdFlag = 1
    def onApplyThreshold(self):
        min, max = self.getDistanceBound()

        newPoints = vtk.vtkPoints()
        newLines = vtk.vtkCellArray()
        newTensors = vtk.vtkFloatArray()
        newTensors.SetNumberOfComponents(9)
        newScalars = vtk.vtkFloatArray()

        points = self.inputPolyData.GetPoints()
        lines = self.inputPolyData.GetLines()
        tensors = self.inputPolyData.GetPointData().GetTensors()
        lines.InitTraversal()

        newId = 0
        for length in self.distanceTable:
            if length <= self.thresholdMax.value and length >= self.thresholdMin.value:
                ids = vtk.vtkIdList()
                lines.GetNextCell(ids)
                newLine = vtk.vtkPolyLine()
                #print(ids.GetNumberOfIds())
                newLine.GetPointIds().SetNumberOfIds(ids.GetNumberOfIds())
                #print(((length-min)/(max-min))*100)
                for i in range(ids.GetNumberOfIds()):
                    newPoints.InsertNextPoint(points.GetPoint(ids.GetId(i)))
                    newLine.GetPointIds().SetId(i, newId)
                    newScalars.InsertNextValue(((length - min) / (max - min)))
                    newId += 1
                    tensorValue = [0] * 9
                    if (tensors != None):
                        for j in range(9):
                            tensorValue[j] = tensors.GetComponent(
                                ids.GetId(i), j)
                    newTensors.InsertNextTuple(tensorValue)
                newLines.InsertNextCell(newLine)

        self.outputPolyData = vtk.vtkPolyData()
        self.outputPolyData.SetPoints(newPoints)
        self.outputPolyData.SetLines(newLines)
        self.outputPolyData.GetPointData().SetTensors(newTensors)
        newScalars.SetName("Length")
        self.outputPolyData.GetPointData().AddArray(newScalars)
        self.outputNode.SetAndObservePolyData(self.outputPolyData)

        chartViewNodes = slicer.mrmlScene.GetNodesByClass(
            'vtkMRMLChartViewNode')
        chartViewNodes.InitTraversal()
        chartViewNode = chartViewNodes.GetNextItemAsObject()

        arrayNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLDoubleArrayNode())
        array = arrayNode.GetArray()
        array.SetNumberOfTuples(10)
        step = (max - min) / 10
        interMin = min
        interMax = min + step
        for i in range(10):
            numberOfFibers = 0
            for length in self.distanceTable:
                if length <= interMax and length >= interMin and length <= self.thresholdMax.value and length >= self.thresholdMin.value:
                    numberOfFibers += 1
            array.SetComponent(i, 0, (interMin + interMax) / 2)
            array.SetComponent(i, 1, numberOfFibers)
            array.SetComponent(i, 2, 0)
            interMin += step
            interMax += step
        chartNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLChartNode())
        chartNode.AddArray("Fiber Length", arrayNode.GetID())
        chartViewNode.SetChartNodeID(chartNode.GetID())

        chartNode.SetProperty('default', 'title', 'Length Distribution')
        chartNode.SetProperty('default', 'xAxisLabel', 'Length')
        chartNode.SetProperty('default', 'yAxisLabel', 'Distribution')
        chartNode.SetProperty('default', 'type', 'Bar')
  def setup( self ):

    self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVCMRMLSceneChanged)

    w = qt.QWidget()
    layout = qt.QGridLayout()
    w.setLayout(layout)
    self.layout.addWidget(w)
    w.show()
    self.layout = layout

    # create frames
    self.inputFrame = ctk.ctkCollapsibleButton()
    self.inputFrame.text = "Input"
    self.inputFrame.collapsed = 0
    inputFrameLayout = qt.QFormLayout(self.inputFrame)
    self.layout.addWidget(self.inputFrame)


    self.ctrlFrame = ctk.ctkCollapsibleButton()
    self.ctrlFrame.text = "Frame control"
    self.ctrlFrame.collapsed = 0
    ctrlFrameLayout = qt.QGridLayout(self.ctrlFrame)
    self.layout.addWidget(self.ctrlFrame)

    self.plotFrame = ctk.ctkCollapsibleButton()
    self.plotFrame.text = "Plotting"
    self.plotFrame.collapsed = 0
    plotFrameLayout = qt.QGridLayout(self.plotFrame)
    self.layout.addWidget(self.plotFrame)

    self.plotSettingsFrame = ctk.ctkCollapsibleButton()
    self.plotSettingsFrame.text = "Settings"
    self.plotSettingsFrame.collapsed = 1
    plotSettingsFrameLayout = qt.QGridLayout(self.plotSettingsFrame)
    plotFrameLayout.addWidget(self.plotSettingsFrame,0,1)

    label = qt.QLabel('Input multivolume')
    self.__mvSelector = slicer.qMRMLNodeComboBox()
    self.__mvSelector.nodeTypes = ['vtkMRMLMultiVolumeNode']
    self.__mvSelector.setMRMLScene(slicer.mrmlScene)
    self.__mvSelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVCMRMLSceneChanged)
    self.__mvSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onInputChanged)
    self.__mvSelector.addEnabled = 0

    inputFrameLayout.addRow(label, self.__mvSelector)

    label = qt.QLabel('Input secondary multivolume')
    self.fgSelector = slicer.qMRMLNodeComboBox()
    self.fgSelector.nodeTypes = ['vtkMRMLMultiVolumeNode']
    self.fgSelector.setMRMLScene(slicer.mrmlScene)
    self.fgSelector.addEnabled = 0
    self.fgSelector.noneEnabled = 1
    self.fgSelector.toolTip = "Secondary multivolume will be used for the secondary \
      plot in interactive charting. As an example, this can be used to overlay the \
      curve obtained by fitting a model to the data"

    inputFrameLayout.addRow(label, self.fgSelector)

    # TODO: initialize the slider based on the contents of the labels array
    # slider to scroll over metadata stored in the vector container being explored
    self.__mdSlider = ctk.ctkSliderWidget()

    label = qt.QLabel('Current frame number')

    # "play" control
    self.playButton = qt.QPushButton('Play')
    self.playButton.toolTip = 'Iterate over multivolume frames'
    self.playButton.checkable = True

    ctrlFrameLayout.addWidget(label, 0, 0)
    ctrlFrameLayout.addWidget(self.__mdSlider, 0, 1)
    ctrlFrameLayout.addWidget(self.playButton, 0, 2)

    self.playButton.connect('toggled(bool)', self.onPlayButtonToggled)

    self.__mdSlider.connect('valueChanged(double)', self.onSliderChanged)

    label = qt.QLabel('Current frame copy')

    self.__vfSelector = slicer.qMRMLNodeComboBox()
    self.__vfSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
    self.__vfSelector.setMRMLScene(slicer.mrmlScene)
    self.__vfSelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVFMRMLSceneChanged)
    self.__vfSelector.addEnabled = 1
    self.__vfSelector.enabled = 0
    # do not show "children" of vtkMRMLScalarVolumeNode
    self.__vfSelector.hideChildNodeTypes = ["vtkMRMLDiffusionWeightedVolumeNode", \
        "vtkMRMLDiffusionTensorVolumeNode", "vtkMRMLVectorVolumeNode"]

    self.extractFrame = False
    self.extractButton = qt.QPushButton('Enable current frame copying')
    self.extractButton.checkable = True
    self.extractButton.connect('toggled(bool)', self.onExtractFrameToggled)

    ctrlFrameLayout.addWidget(label, 1, 0)
    ctrlFrameLayout.addWidget(self.__vfSelector,1,1,1,2)
    ctrlFrameLayout.addWidget(self.extractButton,2,0,1,3)

    # initialize slice observers (from DataProbe.py)
    # keep list of pairs: [observee,tag] so they can be removed easily
    self.styleObserverTags = []
    # keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic
    self.sliceWidgetsPerStyle = {}
    self.refreshObservers()

    # label map for probing
    label = qt.QLabel('Probed label volume')
    self.__fSelector = slicer.qMRMLNodeComboBox()
    self.__fSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
    self.__fSelector.addAttribute('vtkMRMLScalarVolumeNode','LabelMap','1')
    self.__fSelector.toolTip = 'Label map to be probed'
    self.__fSelector.setMRMLScene(slicer.mrmlScene)
    self.__fSelector.addEnabled = 0
    self.chartButton = qt.QPushButton('Chart')
    self.chartButton.checkable = False
    self.chartButton.connect('clicked()', self.onChartRequested)
    plotSettingsFrameLayout.addWidget(label,0,0)
    plotSettingsFrameLayout.addWidget(self.__fSelector,0,1)
    plotSettingsFrameLayout.addWidget(self.chartButton,0,2)

    self.iCharting = qt.QPushButton()
    self.iCharting.text = 'Enable interactive charting'
    self.iCharting.checkable = True

    plotSettingsFrameLayout.addWidget(self.iCharting,1,0,1,3)
    self.iCharting.setChecked(True)
    self.iCharting.connect('toggled(bool)', self.onInteractiveChartingChanged)

    groupLabel = qt.QLabel('Interactive plotting mode:')
    self.iChartingMode = qt.QButtonGroup()
    self.iChartingIntensity = qt.QRadioButton('Signal intensity')
    #self.iChartingIntensity.tooltip = 'Plot range adjusted dynamically to the range over the time course for the selected pixel'
    self.iChartingIntensityFixedAxes = qt.QRadioButton('Fixed range intensity')
    #self.iChartingIntensityFixedAxes.tooltip = "If checked, the extent of the vertical axis of the plot will be fixed to the range of the intensities in the input MultiVolume"
    self.iChartingPercent = qt.QRadioButton('Percent change')
    #self.iChartingPercent.tooltip = 'Percent change relative to the average of the first N frames (parameter set below)'
    self.iChartingIntensity.setChecked(1)

    self.groupWidget = qt.QWidget()
    self.groupLayout = qt.QFormLayout(self.groupWidget)
    self.groupLayout.addRow(groupLabel)
    self.groupLayout.addRow(self.iChartingIntensity)
    self.groupLayout.addRow(self.iChartingIntensityFixedAxes)
    self.groupLayout.addRow(self.iChartingPercent)

    self.baselineFrames = qt.QSpinBox()
    self.baselineFrames.minimum = 1
    label = qt.QLabel('Number of frames for baseline calculation')
    self.groupLayout.addRow(label,self.baselineFrames)

    self.xLogScaleCheckBox = qt.QCheckBox()
    self.xLogScaleCheckBox.setChecked(0)
    label = qt.QLabel('Use log scale for X axis')
    self.groupLayout.addRow(self.xLogScaleCheckBox,label)
    self.xLogScaleCheckBox.connect('stateChanged(int)', self.onXLogScaleRequested)

    self.yLogScaleCheckBox = qt.QCheckBox()
    self.yLogScaleCheckBox.setChecked(0)
    label = qt.QLabel('Use log scale for Y axis')
    self.groupLayout.addRow(self.yLogScaleCheckBox,label)
    self.yLogScaleCheckBox.connect('stateChanged(int)', self.onYLogScaleRequested)

    plotSettingsFrameLayout.addWidget(self.groupWidget,2,0)

    # add chart container widget
    self.__chartView = ctk.ctkVTKChartView(w)
    plotFrameLayout.addWidget(self.__chartView,3,0,1,3)

    self.__chart = self.__chartView.chart()
    self.__chartTable = vtk.vtkTable()
    self.__xArray = vtk.vtkFloatArray()
    self.__yArray = vtk.vtkFloatArray()
    # will crash if there is no name
    self.__xArray.SetName('')
    self.__yArray.SetName('signal intensity')
    self.__chartTable.AddColumn(self.__xArray)
    self.__chartTable.AddColumn(self.__yArray)
  def processEvent(self,observee,event):
    if not self.iCharting.checked:
      return

    if self.__mvNode == None:
      return

    mvImage = self.__mvNode.GetImageData()
    nComponents = self.__mvNode.GetNumberOfFrames()

    # TODO: use a timer to delay calculation and compress events
    if event == 'LeaveEvent':
      # reset all the readouts
      # TODO: reset the label text
      return

    if not self.sliceWidgetsPerStyle.has_key(observee):
      return

    sliceWidget = self.sliceWidgetsPerStyle[observee]
    sliceLogic = sliceWidget.sliceLogic()
    interactor = observee.GetInteractor()
    xy = interactor.GetEventPosition()
    xyz = sliceWidget.sliceView().convertDeviceToXYZ(xy);

    ras = sliceWidget.sliceView().convertXYZToRAS(xyz)
    bgLayer = sliceLogic.GetBackgroundLayer()
    fgLayer = sliceLogic.GetForegroundLayer()

    volumeNode = bgLayer.GetVolumeNode()
    fgVolumeNode = self.fgSelector.currentNode()
    if not volumeNode or volumeNode.GetID() != self.__mvNode.GetID():
      return
    if volumeNode != self.__mvNode:
      return

    nameLabel = volumeNode.GetName()
    xyToIJK = bgLayer.GetXYToIJKTransform()
    ijkFloat = xyToIJK.TransformDoublePoint(xyz)
    ijk = []
    for element in ijkFloat:
      try:
        index = int(round(element))
      except ValueError:
        index = 0
      ijk.append(index)

    extent = mvImage.GetExtent()
    if not (ijk[0]>=extent[0] and ijk[0]<=extent[1] and \
       ijk[1]>=extent[2] and ijk[1]<=extent[3] and \
       ijk[2]>=extent[4] and ijk[2]<=extent[5]):
      # pixel outside the valid extent
      return

    useFg = False
    if fgVolumeNode:
      fgxyToIJK = fgLayer.GetXYToIJKTransform()
      fgijkFloat = xyToIJK.TransformDoublePoint(xyz)
      fgijk = []
      for element in fgijkFloat:
        try:
          index = int(round(element))
        except ValueError:
          index = 0
        fgijk.append(index)
        fgImage = fgVolumeNode.GetImageData()

      fgChartTable = vtk.vtkTable()
      if fgijk[0] == ijk[0] and fgijk[1] == ijk[1] and fgijk[2] == ijk[2] and \
          fgImage.GetNumberOfScalarComponents() == mvImage.GetNumberOfScalarComponents():
        useFg = True

        fgxArray = vtk.vtkFloatArray()
        fgxArray.SetNumberOfTuples(nComponents)
        fgxArray.SetNumberOfComponents(1)
        fgxArray.Allocate(nComponents)
        fgxArray.SetName('frame')

        fgyArray = vtk.vtkFloatArray()
        fgyArray.SetNumberOfTuples(nComponents)
        fgyArray.SetNumberOfComponents(1)
        fgyArray.Allocate(nComponents)
        fgyArray.SetName('signal intensity')
 
        # will crash if there is no name
        fgChartTable.AddColumn(fgxArray)
        fgChartTable.AddColumn(fgyArray)
        fgChartTable.SetNumberOfRows(nComponents)

    # get the vector of values at IJK

    for c in range(nComponents):
      val = mvImage.GetScalarComponentAsDouble(ijk[0],ijk[1],ijk[2],c)
      self.__chartTable.SetValue(c, 0, self.__mvLabels[c])
      self.__chartTable.SetValue(c, 1, val)
      if useFg:
        fgValue = fgImage.GetScalarComponentAsDouble(ijk[0],ijk[1],ijk[2],c)
        fgChartTable.SetValue(c,0,self.__mvLabels[c])
        fgChartTable.SetValue(c,1,fgValue)

    baselineAverageSignal = 0
    if self.iChartingPercent.checked:
      # check if percent plotting was requested and recalculate
      nBaselines = min(self.baselineFrames.value,nComponents)
      for c in range(nBaselines):
        baselineAverageSignal += mvImage.GetScalarComponentAsDouble(ijk[0],ijk[1],ijk[2],c)
      baselineAverageSignal /= nBaselines
      if baselineAverageSignal != 0:
        for c in range(nComponents):
          intensity = mvImage.GetScalarComponentAsDouble(ijk[0],ijk[1],ijk[2],c)
          self.__chartTable.SetValue(c,1,(intensity/baselineAverageSignal-1)*100.)

    self.__chart.RemovePlot(0)
    self.__chart.RemovePlot(0)

    if self.iChartingPercent.checked and baselineAverageSignal != 0:
      self.__chart.GetAxis(0).SetTitle('change relative to baseline, %')
    else:
      self.__chart.GetAxis(0).SetTitle('signal intensity')

    tag = str(self.__mvNode.GetAttribute('MultiVolume.FrameIdentifyingDICOMTagName'))
    units = str(self.__mvNode.GetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits'))
    xTitle = tag+', '+units
    self.__chart.GetAxis(1).SetTitle(xTitle)
    if self.iChartingIntensityFixedAxes.checked == True:
      self.__chart.GetAxis(0).SetBehavior(vtk.vtkAxis.FIXED)
      self.__chart.GetAxis(0).SetRange(self.__mvRange[0],self.__mvRange[1])
    else:
      self.__chart.GetAxis(0).SetBehavior(vtk.vtkAxis.AUTO)
    if useFg:
      plot = self.__chart.AddPlot(vtk.vtkChart.POINTS)
      plot.SetInput(self.__chartTable, 0, 1)
      fgplot = self.__chart.AddPlot(vtk.vtkChart.LINE)
      fgplot.SetInput(fgChartTable, 0, 1)
    else:
      plot = self.__chart.AddPlot(vtk.vtkChart.LINE)
      plot.SetInput(self.__chartTable, 0, 1)
      
    if self.xLogScaleCheckBox.checkState() == 2:
      title = self.__chart.GetAxis(1).GetTitle()
      self.__chart.GetAxis(1).SetTitle('log of '+title)

    if self.yLogScaleCheckBox.checkState() == 2:
      title = self.__chart.GetAxis(0).GetTitle()
      self.__chart.GetAxis(0).SetTitle('log of '+title)
Example #13
0
    def setup(self):

        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.onVCMRMLSceneChanged)

        w = qt.QWidget()
        layout = qt.QGridLayout()
        w.setLayout(layout)
        self.layout.addWidget(w)
        w.show()
        self.layout = layout

        # create frames
        self.inputFrame = ctk.ctkCollapsibleButton()
        self.inputFrame.text = "Input"
        self.inputFrame.collapsed = 0
        inputFrameLayout = qt.QFormLayout(self.inputFrame)
        self.layout.addWidget(self.inputFrame)

        self.ctrlFrame = ctk.ctkCollapsibleButton()
        self.ctrlFrame.text = "Frame control"
        self.ctrlFrame.collapsed = 0
        ctrlFrameLayout = qt.QGridLayout(self.ctrlFrame)
        self.layout.addWidget(self.ctrlFrame)

        self.plotFrame = ctk.ctkCollapsibleButton()
        self.plotFrame.text = "Plotting"
        self.plotFrame.collapsed = 0
        plotFrameLayout = qt.QGridLayout(self.plotFrame)
        self.layout.addWidget(self.plotFrame)

        label = qt.QLabel('Input multivolume')
        self.__mvSelector = slicer.qMRMLNodeComboBox()
        self.__mvSelector.nodeTypes = ['vtkMRMLMultiVolumeNode']
        self.__mvSelector.setMRMLScene(slicer.mrmlScene)
        self.__mvSelector.connect('mrmlSceneChanged(vtkMRMLScene*)',
                                  self.onVCMRMLSceneChanged)
        self.__mvSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                  self.onInputChanged)
        self.__mvSelector.addEnabled = 0

        inputFrameLayout.addRow(label, self.__mvSelector)
        ##self.layout.addWidget(label)
        ##self.layout.addWidget(self.__mvSelector)

        # TODO: initialize the slider based on the contents of the labels array
        # slider to scroll over metadata stored in the vector container being explored
        self.__mdSlider = ctk.ctkSliderWidget()
        #self.__mdSlider.setRange(0,10)
        #self.__mdSlider.setValue(5)

        label = qt.QLabel('Current frame number')
        ##self.layout.addWidget(label)
        ##self.layout.addWidget(self.__mdSlider)

        # "play" control
        self.playButton = qt.QPushButton('Play')
        self.playButton.toolTip = 'Iterate over multivolume frames'
        self.playButton.checkable = True

        ctrlFrameLayout.addWidget(label, 0, 0)
        ctrlFrameLayout.addWidget(self.__mdSlider, 0, 1)
        ctrlFrameLayout.addWidget(self.playButton, 0, 2)

        self.playButton.connect('toggled(bool)', self.onPlayButtonToggled)

        self.__mdSlider.connect('valueChanged(double)', self.onSliderChanged)

        label = qt.QLabel('Current frame copy')

        self.__vfSelector = slicer.qMRMLNodeComboBox()
        self.__vfSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
        self.__vfSelector.setMRMLScene(slicer.mrmlScene)
        self.__vfSelector.connect('mrmlSceneChanged(vtkMRMLScene*)',
                                  self.onVFMRMLSceneChanged)
        self.__vfSelector.addEnabled = 1
        self.__vfSelector.enabled = 0
        # do not show "children" of vtkMRMLScalarVolumeNode
        self.__vfSelector.hideChildNodeTypes = ["vtkMRMLDiffusionWeightedVolumeNode", \
            "vtkMRMLDiffusionTensorVolumeNode", "vtkMRMLVectorVolumeNode"]

        self.extractFrame = False
        self.extractButton = qt.QPushButton('Enable current frame copying')
        self.extractButton.checkable = True
        self.extractButton.connect('toggled(bool)', self.onExtractFrameToggled)

        ctrlFrameLayout.addWidget(label, 1, 0)
        ctrlFrameLayout.addWidget(self.__vfSelector, 1, 1, 1, 2)
        ctrlFrameLayout.addWidget(self.extractButton, 2, 0, 1, 3)

        # initialize slice observers (from DataProbe.py)
        # keep list of pairs: [observee,tag] so they can be removed easily
        self.styleObserverTags = []
        # keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic
        self.sliceWidgetsPerStyle = {}
        self.refreshObservers()

        # label map for probing
        label = qt.QLabel('Probed label volume')
        self.__fSelector = slicer.qMRMLNodeComboBox()
        self.__fSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
        self.__fSelector.addAttribute('vtkMRMLScalarVolumeNode', 'LabelMap',
                                      '1')
        self.__fSelector.toolTip = 'Label map to be probed'
        self.__fSelector.setMRMLScene(slicer.mrmlScene)
        self.__fSelector.addEnabled = 0
        self.__fSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                 self.onLabelVolumeChanged)
        self.__fSelector.connect('mrmlSceneChanged(vtkMRMLScene*)',
                                 self.onLVMRMLSceneChanged)
        plotFrameLayout.addWidget(label, 0, 0, 1, 1)
        plotFrameLayout.addWidget(self.__fSelector, 0, 1, 1, 2)

        self.iCharting = qt.QPushButton()
        self.iCharting.text = 'Enable interactive charting'
        self.iCharting.checkable = True

        plotFrameLayout.addWidget(self.iCharting, 1, 0, 1, 3)
        self.iCharting.setChecked(True)
        self.iCharting.connect('toggled(bool)',
                               self.onInteractiveChartingChanged)

        label = qt.QLabel("Use intensity range to fix axis extent")
        label.toolTip = "If checked, the extent of the vertical axis of the plot will be fixed to the range of the intensities in the input MultiVolume"
        self.__fixedAxesCheckbox = qt.QCheckBox()
        self.__fixedAxesCheckbox.toolTip = "If checked, the extent of the vertical axis of the plot will be fixed to the range of the intensities in the input MultiVolume"
        self.__fixedAxesCheckbox.checked = False
        plotFrameLayout.addWidget(label, 2, 0)
        plotFrameLayout.addWidget(self.__fixedAxesCheckbox, 2, 1, 1, 2)

        # add chart container widget
        self.__chartView = ctk.ctkVTKChartView(w)
        plotFrameLayout.addWidget(self.__chartView, 3, 0, 1, 3)

        self.__chart = self.__chartView.chart()
        self.__chartTable = vtk.vtkTable()
        self.__xArray = vtk.vtkFloatArray()
        self.__yArray = vtk.vtkFloatArray()
        # will crash if there is no name
        self.__xArray.SetName('')
        self.__yArray.SetName('signal intensity')
        self.__chartTable.AddColumn(self.__xArray)
        self.__chartTable.AddColumn(self.__yArray)
Example #14
0
    def createChart(self, sliceWidget, xy, ignoreCurrentBackground=False):
        if not sliceWidget and not xy:
            return

        sliceLogic = sliceWidget.sliceLogic()

        bgLayer = sliceLogic.GetBackgroundLayer()

        doIJKToRASTransformation = False
        bgVolumeNode = bgLayer.GetVolumeNode()
        if not bgVolumeNode or bgVolumeNode.GetID() != self.__bgMultiVolumeNode.GetID() or \
          bgVolumeNode != self.__bgMultiVolumeNode:
            if not ignoreCurrentBackground:
                return
            else:
                doIJKToRASTransformation = True

        xyz = sliceWidget.sliceView().convertDeviceToXYZ(xy)
        xyToIJK = bgLayer.GetXYToIJKTransform()
        ijkFloat = xyToIJK.TransformDoublePoint(xyz)
        if doIJKToRASTransformation:
            RAStoIJK = vtk.vtkMatrix4x4()
            self.__bgMultiVolumeNode.GetRASToIJKMatrix(RAStoIJK)
            ras = self.xyToRAS(sliceLogic, xy)
            ijkFloat = RAStoIJK.MultiplyPoint([ras[0], ras[1], ras[2], 1])[:3]

        bgijk = self.getIJKIntFromIJKFloat(ijkFloat)
        bgImage = self.__bgMultiVolumeNode.GetImageData()

        if not self.arePixelsWithinImageExtent(bgImage, bgijk):
            self.clearPlots()
            return

        nComponents = self.__bgMultiVolumeNode.GetNumberOfFrames()

        useFg = False
        fgImage = None
        fgijk = None
        if self.__fgMultiVolumeNode:
            fgijkFloat = xyToIJK.TransformDoublePoint(xyz)
            fgijk = self.getIJKIntFromIJKFloat(fgijkFloat)

            fgImage = self.__fgMultiVolumeNode.GetImageData()
            if self.__fgChartTableNode:
                slicer.mrmlScene.RemoveNode(self.__fgChartTableNode)
            self.__fgChartTableNode = slicer.mrmlScene.AddNewNodeByClass(
                "vtkMRMLTableNode", "fgChartTable")
            fgChartTable = self.__fgChartTableNode.GetTable()
            if fgijk[0] == bgijk[0] and fgijk[1] == bgijk[1] and fgijk[2] == bgijk[2] and \
               fgImage.GetNumberOfScalarComponents() == bgImage.GetNumberOfScalarComponents():
                useFg = True

                fgxArray = vtk.vtkFloatArray()
                self.refreshArray(fgxArray, nComponents, 'fg')

                fgyArray = vtk.vtkFloatArray()
                self.refreshArray(fgyArray, nComponents, '2nd multivolume')

                # will crash if there is no name
                fgChartTable.AddColumn(fgxArray)
                fgChartTable.AddColumn(fgyArray)
                fgChartTable.SetNumberOfRows(nComponents)

        # get the vector of values at IJK
        for c in range(nComponents):
            val = bgImage.GetScalarComponentAsDouble(bgijk[0], bgijk[1],
                                                     bgijk[2], c)
            if math.isnan(val):
                val = 0
            self.__chartTable.SetValue(c, 0, self.__mvLabels[c])
            self.__chartTable.SetValue(c, 1, val)
            if useFg:
                fgValue = fgImage.GetScalarComponentAsDouble(
                    bgijk[0], bgijk[1], bgijk[2], c)
                if math.isnan(fgValue):
                    fgValue = 0
                fgChartTable.SetValue(c, 0, self.__mvLabels[c])
                fgChartTable.SetValue(c, 1, fgValue)

        self.baselineAverageSignal = 0
        if self.__chartMode == self.PERCENTAGE_CHANGE_MODE:
            self.computePercentageChangeWithRespectToBaseline(
                self.__bgMultiVolumeNode, self.__chartTable, bgijk)
            if useFg:
                self.computePercentageChangeWithRespectToBaseline(
                    self.__fgMultiVolumeNode, fgChartTable, fgijk)

        self.clearPlots()
        self.setAxesTitle()

        self.__bgPlot = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLPlotSeriesNode", "1st multivolume")
        self.__bgPlot.SetAndObserveTableNodeID(self.__chartTableNode.GetID())
        self.__bgPlot.SetXColumnName('x')
        self.__bgPlot.SetYColumnName('1st multivolume')
        self.__bgPlot.SetPlotType(slicer.vtkMRMLPlotSeriesNode.PlotTypeScatter)
        if useFg:
            self.__bgPlot.SetLineStyle(
                slicer.vtkMRMLPlotSeriesNode.LineStyleNone)
        else:
            self.__bgPlot.SetMarkerStyle(
                slicer.vtkMRMLPlotSeriesNode.MarkerStyleNone)
        self.__chart.AddAndObservePlotSeriesNodeID(self.__bgPlot.GetID())
        # bgPlot.SetLabel("Primary multivolume ")

        if useFg:
            self.__fgPlot = slicer.mrmlScene.AddNewNodeByClass(
                "vtkMRMLPlotSeriesNode", "2nd multivolume")
            self.__fgPlot.SetAndObserveTableNodeID(
                self.__fgChartTableNode.GetID())
            self.__fgPlot.SetXColumnName('fg')
            self.__fgPlot.SetYColumnName('2nd multivolume')
            self.__fgPlot.SetPlotType(
                slicer.vtkMRMLPlotSeriesNode.PlotTypeScatter)
            self.__fgPlot.SetColor(1, 0, 0)
            self.__fgPlot.SetMarkerStyle(
                slicer.vtkMRMLPlotSeriesNode.MarkerStyleNone)
            self.__chart.AddAndObservePlotSeriesNodeID(self.__fgPlot.GetID())
Example #15
0
    def processEvent(self, observee, event):
        if not self.iCharting.checked:
            return

        if self.__mvNode == None:
            return

        mvImage = self.__mvNode.GetImageData()
        nComponents = self.__mvNode.GetNumberOfFrames()

        # TODO: use a timer to delay calculation and compress events
        if event == 'LeaveEvent':
            # reset all the readouts
            # TODO: reset the label text
            return

        if not self.sliceWidgetsPerStyle.has_key(observee):
            return

        sliceWidget = self.sliceWidgetsPerStyle[observee]
        sliceLogic = sliceWidget.sliceLogic()
        interactor = observee.GetInteractor()
        xy = interactor.GetEventPosition()
        xyz = sliceWidget.sliceView().convertDeviceToXYZ(xy)

        ras = sliceWidget.sliceView().convertXYZToRAS(xyz)
        bgLayer = sliceLogic.GetBackgroundLayer()
        fgLayer = sliceLogic.GetForegroundLayer()

        volumeNode = bgLayer.GetVolumeNode()
        fgVolumeNode = self.fgSelector.currentNode()
        if not volumeNode or volumeNode.GetID() != self.__mvNode.GetID():
            return
        if volumeNode != self.__mvNode:
            return

        nameLabel = volumeNode.GetName()
        xyToIJK = bgLayer.GetXYToIJKTransform()
        ijkFloat = xyToIJK.TransformDoublePoint(xyz)
        ijk = []
        for element in ijkFloat:
            try:
                index = int(round(element))
            except ValueError:
                index = 0
            ijk.append(index)

        extent = mvImage.GetExtent()
        if not (ijk[0]>=extent[0] and ijk[0]<=extent[1] and \
           ijk[1]>=extent[2] and ijk[1]<=extent[3] and \
           ijk[2]>=extent[4] and ijk[2]<=extent[5]):
            # pixel outside the valid extent
            return

        useFg = False
        if fgVolumeNode:
            fgxyToIJK = fgLayer.GetXYToIJKTransform()
            fgijkFloat = xyToIJK.TransformDoublePoint(xyz)
            fgijk = []
            for element in fgijkFloat:
                try:
                    index = int(round(element))
                except ValueError:
                    index = 0
                fgijk.append(index)
                fgImage = fgVolumeNode.GetImageData()

            fgChartTable = vtk.vtkTable()
            if fgijk[0] == ijk[0] and fgijk[1] == ijk[1] and fgijk[2] == ijk[2] and \
                fgImage.GetNumberOfScalarComponents() == mvImage.GetNumberOfScalarComponents():
                useFg = True

                fgxArray = vtk.vtkFloatArray()
                fgxArray.SetNumberOfTuples(nComponents)
                fgxArray.SetNumberOfComponents(1)
                fgxArray.Allocate(nComponents)
                fgxArray.SetName('frame')

                fgyArray = vtk.vtkFloatArray()
                fgyArray.SetNumberOfTuples(nComponents)
                fgyArray.SetNumberOfComponents(1)
                fgyArray.Allocate(nComponents)
                fgyArray.SetName('signal intensity')

                # will crash if there is no name
                fgChartTable.AddColumn(fgxArray)
                fgChartTable.AddColumn(fgyArray)
                fgChartTable.SetNumberOfRows(nComponents)

        # get the vector of values at IJK

        for c in range(nComponents):
            val = mvImage.GetScalarComponentAsDouble(ijk[0], ijk[1], ijk[2], c)
            self.__chartTable.SetValue(c, 0, self.__mvLabels[c])
            self.__chartTable.SetValue(c, 1, val)
            if useFg:
                fgValue = fgImage.GetScalarComponentAsDouble(
                    ijk[0], ijk[1], ijk[2], c)
                fgChartTable.SetValue(c, 0, self.__mvLabels[c])
                fgChartTable.SetValue(c, 1, fgValue)

        baselineAverageSignal = 0
        if self.iChartingPercent.checked:
            # check if percent plotting was requested and recalculate
            nBaselines = min(self.baselineFrames.value, nComponents)
            for c in range(nBaselines):
                baselineAverageSignal += mvImage.GetScalarComponentAsDouble(
                    ijk[0], ijk[1], ijk[2], c)
            baselineAverageSignal /= nBaselines
            if baselineAverageSignal != 0:
                for c in range(nComponents):
                    intensity = mvImage.GetScalarComponentAsDouble(
                        ijk[0], ijk[1], ijk[2], c)
                    self.__chartTable.SetValue(
                        c, 1, (intensity / baselineAverageSignal - 1) * 100.)

        self.__chart.RemovePlot(0)
        self.__chart.RemovePlot(0)

        if self.iChartingPercent.checked and baselineAverageSignal != 0:
            self.__chart.GetAxis(0).SetTitle('change relative to baseline, %')
        else:
            self.__chart.GetAxis(0).SetTitle('signal intensity')

        tag = str(
            self.__mvNode.GetAttribute(
                'MultiVolume.FrameIdentifyingDICOMTagName'))
        units = str(
            self.__mvNode.GetAttribute(
                'MultiVolume.FrameIdentifyingDICOMTagUnits'))
        xTitle = tag + ', ' + units
        self.__chart.GetAxis(1).SetTitle(xTitle)
        if self.iChartingIntensityFixedAxes.checked == True:
            self.__chart.GetAxis(0).SetBehavior(vtk.vtkAxis.FIXED)
            self.__chart.GetAxis(0).SetRange(self.__mvRange[0],
                                             self.__mvRange[1])
        else:
            self.__chart.GetAxis(0).SetBehavior(vtk.vtkAxis.AUTO)
        if useFg:
            plot = self.__chart.AddPlot(vtk.vtkChart.POINTS)
            plot.SetInput(self.__chartTable, 0, 1)
            fgplot = self.__chart.AddPlot(vtk.vtkChart.LINE)
            fgplot.SetInput(fgChartTable, 0, 1)
        else:
            plot = self.__chart.AddPlot(vtk.vtkChart.LINE)
            plot.SetInput(self.__chartTable, 0, 1)

        if self.xLogScaleCheckBox.checkState() == 2:
            title = self.__chart.GetAxis(1).GetTitle()
            self.__chart.GetAxis(1).SetTitle('log of ' + title)

        if self.yLogScaleCheckBox.checkState() == 2:
            title = self.__chart.GetAxis(0).GetTitle()
            self.__chart.GetAxis(0).SetTitle('log of ' + title)
Example #16
0
    def setup(self, wName, parent):
        if self.ctrlWidget:
            return

        self.LinkViewers()
        self.numFrames = len(self.nodeImgList[0][0])

        if parent:
            self.ctrlWidget = parent
        else:
            # Create seperate window
            self.ctrlWidget = slicer.qMRMLWidget()
            self.ctrlWidget.setMRMLScene(slicer.mrmlScene)
            self.ctrlWidget.setLayout(qt.QFormLayout())

        self.ctrlWidget.setWindowTitle(wName)
        ctrlLayout = self.ctrlWidget.layout()

        # Create Slider Panel
        self.sliderPanel = qt.QWidget()
        self.sliderPanel.setLayout(qt.QGridLayout())
        ctrlLayout.addWidget(self.sliderPanel)
        sliderLayout = self.sliderPanel.layout()

        if self.numFrames > 1:
            self.ctrlFrameLabel = qt.QLabel('Frame')
            self.ctrlFrameSlider = ctk.ctkSliderWidget()
            self.ctrlFrameSlider.connect('valueChanged(double)',
                                         self.onSliderFrameChanged)
            sliderLayout.addWidget(self.ctrlFrameLabel, 0, 0)
            sliderLayout.addWidget(self.ctrlFrameSlider, 0, 1)

        self.ctrlLevelLabel = qt.QLabel('Level')
        self.ctrlLevelSlider = ctk.ctkSliderWidget()
        self.ctrlLevelSlider.connect('valueChanged(double)',
                                     self.onSliderLevelChanged)
        sliderLayout.addWidget(self.ctrlLevelLabel, 1, 0)
        sliderLayout.addWidget(self.ctrlLevelSlider, 1, 1)

        self.ctrlWindowLabel = qt.QLabel('Window')
        self.ctrlWindowSlider = ctk.ctkSliderWidget()
        self.ctrlWindowSlider.connect('valueChanged(double)',
                                      self.onSliderWindowChanged)
        sliderLayout.addWidget(self.ctrlWindowLabel, 2, 0)
        sliderLayout.addWidget(self.ctrlWindowSlider, 2, 1)

        self.setSliderRangesAndValues()

        if self.sliceNodeList:
            self.orientPanel = qt.QWidget()
            self.orientPanel.setLayout(qt.QGridLayout())
            ctrlLayout.addWidget(self.orientPanel)

            self.orientationButtons = {}
            index = 0
            for orientation in self.orientations:
                self.orientationButtons[orientation] = qt.QRadioButton()
                self.orientationButtons[orientation].text = orientation
                # self.orientationBox.layout().addWidget(self.orientationButtons[orientation])
                self.orientPanel.layout().addWidget(
                    self.orientationButtons[orientation], 0, index)
                self.orientationButtons[orientation].connect(
                    "clicked()", lambda o=orientation: self.setOrientation(o))
                index += 1

        self.setOrientation(self.selectedOrientation)

        if False:
            #self.plotFrame = ctk.ctkCollapsibleButton()
            #self.plotFrame.text = "Plotting"
            #self.plotFrame.collapsed = 0
            self.plotFrame = qt.QWidget()
            plotFrameLayout = qt.QGridLayout(self.plotFrame)
            ctrlLayout.addWidget(self.plotFrame)

            self.plotSettingsFrame = ctk.ctkCollapsibleButton()
            self.plotSettingsFrame.text = "Settings"
            self.plotSettingsFrame.collapsed = 1
            plotSettingsFrameLayout = qt.QGridLayout(self.plotSettingsFrame)
            #plotFrameLayout.addWidget(self.plotSettingsFrame,0,1)

            self.xLogScaleCheckBox = qt.QCheckBox()
            self.xLogScaleCheckBox.setChecked(0)

            self.yLogScaleCheckBox = qt.QCheckBox()
            self.yLogScaleCheckBox.setChecked(0)

            # taken from  https://github.com/fedorov/MultiVolumeExplorer
            self.__chartView = ctk.ctkVTKChartView(self.ctrlWidget)
            # self.plotFrame)
            #  self.ctrlWidget
            plotFrameLayout.addWidget(self.__chartView, 0, 0)

            self.__chart = self.__chartView.chart()
            self.__chartTable = vtk.vtkTable()
            self.__xArray = vtk.vtkFloatArray()
            self.__yArray = vtk.vtkFloatArray()
            # will crash if there is no name
            self.__xArray.SetName('')
            self.__yArray.SetName('signal intensity')
            self.__chartTable.AddColumn(self.__xArray)
            self.__chartTable.AddColumn(self.__yArray)

            self.onInputChanged()
            self.refreshObservers()

        self.buttonPanel = qt.QWidget()
        self.buttonPanel.setLayout(qt.QGridLayout())
        ctrlLayout.addWidget(self.buttonPanel)

        self.exitButton = qt.QPushButton("Exit")
        self.exitButton.toolTip = "Close down slicer."
        self.exitButton.name = "sviewer exit"
        self.buttonPanel.layout().addWidget(self.exitButton, 0, 0)
        self.exitButton.connect('clicked()', exit)

        # do not do ctrlWin.show() here - for some reason window does not pop up then
        return self.ctrlWidget
Example #17
0
  def createChart(self, sliceWidget, xy, ignoreCurrentBackground=False):
    if not sliceWidget and not xy:
      return

    sliceLogic = sliceWidget.sliceLogic()

    bgLayer = sliceLogic.GetBackgroundLayer()

    doIJKToRASTransformation = False
    bgVolumeNode = bgLayer.GetVolumeNode()
    if not bgVolumeNode or bgVolumeNode.GetID() != self.__bgMultiVolumeNode.GetID() or \
      bgVolumeNode != self.__bgMultiVolumeNode:
      if not ignoreCurrentBackground:
        return
      else:
        doIJKToRASTransformation = True

    xyz = sliceWidget.sliceView().convertDeviceToXYZ(xy)
    xyToIJK = bgLayer.GetXYToIJKTransform()
    ijkFloat = xyToIJK.TransformDoublePoint(xyz)
    if doIJKToRASTransformation:
      RAStoIJK = vtk.vtkMatrix4x4()
      self.__bgMultiVolumeNode.GetRASToIJKMatrix(RAStoIJK)
      ras = self.xyToRAS(sliceLogic, xy)
      ijkFloat = RAStoIJK.MultiplyPoint([ras[0], ras[1], ras[2], 1])[:3]

    bgijk = self.getIJKIntFromIJKFloat(ijkFloat)
    bgImage = self.__bgMultiVolumeNode.GetImageData()

    if not self.arePixelsWithinImageExtent(bgImage, bgijk):
      self.clearPlots()
      return

    nComponents = self.__bgMultiVolumeNode.GetNumberOfFrames()

    useFg = False
    fgImage = None
    fgijk = None
    if self.__fgMultiVolumeNode:
      fgijkFloat = xyToIJK.TransformDoublePoint(xyz)
      fgijk = self.getIJKIntFromIJKFloat(fgijkFloat)

      fgImage = self.__fgMultiVolumeNode.GetImageData()
      fgChartTable = vtk.vtkTable()
      if fgijk[0] == bgijk[0] and fgijk[1] == bgijk[1] and fgijk[2] == bgijk[2] and \
         fgImage.GetNumberOfScalarComponents() == bgImage.GetNumberOfScalarComponents():
        useFg = True

        fgxArray = vtk.vtkFloatArray()
        self.refreshArray(fgxArray, nComponents, '')

        fgyArray = vtk.vtkFloatArray()
        self.refreshArray(fgyArray, nComponents, '2nd multivolume')

        # will crash if there is no name
        fgChartTable.AddColumn(fgxArray)
        fgChartTable.AddColumn(fgyArray)
        fgChartTable.SetNumberOfRows(nComponents)

    # get the vector of values at IJK
    for c in range(nComponents):
      val = bgImage.GetScalarComponentAsDouble(bgijk[0],bgijk[1],bgijk[2],c)
      if math.isnan(val):
        val = 0
      self.__chartTable.SetValue(c, 0, self.__mvLabels[c])
      self.__chartTable.SetValue(c, 1, val)
      if useFg:
        fgValue = fgImage.GetScalarComponentAsDouble(bgijk[0],bgijk[1],bgijk[2],c)
        if math.isnan(fgValue):
          fgValue = 0
        fgChartTable.SetValue(c,0,self.__mvLabels[c])
        fgChartTable.SetValue(c,1,fgValue)

    self.baselineAverageSignal = 0
    if self.__chartMode == self.PERCENTAGE_CHANGE_MODE:
      self.computePercentageChangeWithRespectToBaseline(self.__bgMultiVolumeNode, self.__chartTable, bgijk)
      if useFg:
        self.computePercentageChangeWithRespectToBaseline(self.__fgMultiVolumeNode, fgChartTable, fgijk)

    self.clearPlots()
    self.setAxesTitle()

    bgPlot = self.chart.AddPlot(vtk.vtkChart.POINTS if useFg else vtk.vtkChart.LINE)
    # bgPlot.SetLabel("Primary multivolume ")
    self.setPlotInputTable(bgPlot, self.__chartTable)

    if useFg:
      fgPlot = self.chart.AddPlot(vtk.vtkChart.LINE)
      # bgPlot.SetLabel("Primary multivolume ")
      self.setPlotInputTable(fgPlot, fgChartTable)
Example #18
0
    def setup(self):

        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.onVCMRMLSceneChanged)

        w = qt.QWidget()
        layout = qt.QGridLayout()
        w.setLayout(layout)
        self.layout.addWidget(w)
        w.show()
        self.layout = layout

        # create frames
        self.inputFrame = ctk.ctkCollapsibleButton()
        self.inputFrame.text = "Input"
        self.inputFrame.collapsed = 0
        inputFrameLayout = qt.QFormLayout(self.inputFrame)
        self.layout.addWidget(self.inputFrame)

        self.ctrlFrame = ctk.ctkCollapsibleButton()
        self.ctrlFrame.text = "Frame control"
        self.ctrlFrame.collapsed = 0
        ctrlFrameLayout = qt.QGridLayout(self.ctrlFrame)
        self.layout.addWidget(self.ctrlFrame)

        self.plotFrame = ctk.ctkCollapsibleButton()
        self.plotFrame.text = "Plotting"
        self.plotFrame.collapsed = 0
        plotFrameLayout = qt.QGridLayout(self.plotFrame)
        self.layout.addWidget(self.plotFrame)

        self.plotSettingsFrame = ctk.ctkCollapsibleButton()
        self.plotSettingsFrame.text = "Settings"
        self.plotSettingsFrame.collapsed = 1
        plotSettingsFrameLayout = qt.QGridLayout(self.plotSettingsFrame)
        plotFrameLayout.addWidget(self.plotSettingsFrame, 0, 1)

        label = qt.QLabel('Input multivolume')
        self.__mvSelector = slicer.qMRMLNodeComboBox()
        self.__mvSelector.nodeTypes = ['vtkMRMLMultiVolumeNode']
        self.__mvSelector.setMRMLScene(slicer.mrmlScene)
        self.__mvSelector.connect('mrmlSceneChanged(vtkMRMLScene*)',
                                  self.onVCMRMLSceneChanged)
        self.__mvSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                  self.onInputChanged)
        self.__mvSelector.addEnabled = 0

        inputFrameLayout.addRow(label, self.__mvSelector)

        label = qt.QLabel('Input secondary multivolume')
        self.fgSelector = slicer.qMRMLNodeComboBox()
        self.fgSelector.nodeTypes = ['vtkMRMLMultiVolumeNode']
        self.fgSelector.setMRMLScene(slicer.mrmlScene)
        self.fgSelector.addEnabled = 0
        self.fgSelector.noneEnabled = 1
        self.fgSelector.toolTip = "Secondary multivolume will be used for the secondary \
      plot in interactive charting. As an example, this can be used to overlay the \
      curve obtained by fitting a model to the data"

        inputFrameLayout.addRow(label, self.fgSelector)

        # TODO: initialize the slider based on the contents of the labels array
        # slider to scroll over metadata stored in the vector container being explored
        self.__mdSlider = ctk.ctkSliderWidget()

        label = qt.QLabel('Current frame number')

        # "play" control
        self.playButton = qt.QPushButton('Play')
        self.playButton.toolTip = 'Iterate over multivolume frames'
        self.playButton.checkable = True

        ctrlFrameLayout.addWidget(label, 0, 0)
        ctrlFrameLayout.addWidget(self.__mdSlider, 0, 1)
        ctrlFrameLayout.addWidget(self.playButton, 0, 2)

        self.playButton.connect('toggled(bool)', self.onPlayButtonToggled)

        self.__mdSlider.connect('valueChanged(double)', self.onSliderChanged)

        label = qt.QLabel('Current frame copy')

        self.__vfSelector = slicer.qMRMLNodeComboBox()
        self.__vfSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
        self.__vfSelector.setMRMLScene(slicer.mrmlScene)
        self.__vfSelector.connect('mrmlSceneChanged(vtkMRMLScene*)',
                                  self.onVFMRMLSceneChanged)
        self.__vfSelector.addEnabled = 1
        self.__vfSelector.enabled = 0
        # do not show "children" of vtkMRMLScalarVolumeNode
        self.__vfSelector.hideChildNodeTypes = ["vtkMRMLDiffusionWeightedVolumeNode", \
            "vtkMRMLDiffusionTensorVolumeNode", "vtkMRMLVectorVolumeNode"]

        self.extractFrame = False
        self.extractButton = qt.QPushButton('Enable current frame copying')
        self.extractButton.checkable = True
        self.extractButton.connect('toggled(bool)', self.onExtractFrameToggled)

        ctrlFrameLayout.addWidget(label, 1, 0)
        ctrlFrameLayout.addWidget(self.__vfSelector, 1, 1, 1, 2)
        ctrlFrameLayout.addWidget(self.extractButton, 2, 0, 1, 3)

        # initialize slice observers (from DataProbe.py)
        # keep list of pairs: [observee,tag] so they can be removed easily
        self.styleObserverTags = []
        # keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic
        self.sliceWidgetsPerStyle = {}
        self.refreshObservers()

        # label map for probing
        label = qt.QLabel('Probed label volume')
        self.__fSelector = slicer.qMRMLNodeComboBox()
        self.__fSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
        self.__fSelector.addAttribute('vtkMRMLScalarVolumeNode', 'LabelMap',
                                      '1')
        self.__fSelector.toolTip = 'Label map to be probed'
        self.__fSelector.setMRMLScene(slicer.mrmlScene)
        self.__fSelector.addEnabled = 0
        self.chartButton = qt.QPushButton('Chart')
        self.chartButton.checkable = False
        self.chartButton.connect('clicked()', self.onChartRequested)
        plotSettingsFrameLayout.addWidget(label, 0, 0)
        plotSettingsFrameLayout.addWidget(self.__fSelector, 0, 1)
        plotSettingsFrameLayout.addWidget(self.chartButton, 0, 2)

        self.iCharting = qt.QPushButton()
        self.iCharting.text = 'Enable interactive charting'
        self.iCharting.checkable = True

        plotSettingsFrameLayout.addWidget(self.iCharting, 1, 0, 1, 3)
        self.iCharting.setChecked(True)
        self.iCharting.connect('toggled(bool)',
                               self.onInteractiveChartingChanged)

        groupLabel = qt.QLabel('Interactive plotting mode:')
        self.iChartingMode = qt.QButtonGroup()
        self.iChartingIntensity = qt.QRadioButton('Signal intensity')
        #self.iChartingIntensity.tooltip = 'Plot range adjusted dynamically to the range over the time course for the selected pixel'
        self.iChartingIntensityFixedAxes = qt.QRadioButton(
            'Fixed range intensity')
        #self.iChartingIntensityFixedAxes.tooltip = "If checked, the extent of the vertical axis of the plot will be fixed to the range of the intensities in the input MultiVolume"
        self.iChartingPercent = qt.QRadioButton('Percent change')
        #self.iChartingPercent.tooltip = 'Percent change relative to the average of the first N frames (parameter set below)'
        self.iChartingIntensity.setChecked(1)

        self.groupWidget = qt.QWidget()
        self.groupLayout = qt.QFormLayout(self.groupWidget)
        self.groupLayout.addRow(groupLabel)
        self.groupLayout.addRow(self.iChartingIntensity)
        self.groupLayout.addRow(self.iChartingIntensityFixedAxes)
        self.groupLayout.addRow(self.iChartingPercent)

        self.baselineFrames = qt.QSpinBox()
        self.baselineFrames.minimum = 1
        label = qt.QLabel('Number of frames for baseline calculation')
        self.groupLayout.addRow(label, self.baselineFrames)

        self.xLogScaleCheckBox = qt.QCheckBox()
        self.xLogScaleCheckBox.setChecked(0)
        label = qt.QLabel('Use log scale for X axis')
        self.groupLayout.addRow(self.xLogScaleCheckBox, label)
        self.xLogScaleCheckBox.connect('stateChanged(int)',
                                       self.onXLogScaleRequested)

        self.yLogScaleCheckBox = qt.QCheckBox()
        self.yLogScaleCheckBox.setChecked(0)
        label = qt.QLabel('Use log scale for Y axis')
        self.groupLayout.addRow(self.yLogScaleCheckBox, label)
        self.yLogScaleCheckBox.connect('stateChanged(int)',
                                       self.onYLogScaleRequested)

        plotSettingsFrameLayout.addWidget(self.groupWidget, 2, 0)

        # add chart container widget
        self.__chartView = ctk.ctkVTKChartView(w)
        plotFrameLayout.addWidget(self.__chartView, 3, 0, 1, 3)

        self.__chart = self.__chartView.chart()
        self.__chartTable = vtk.vtkTable()
        self.__xArray = vtk.vtkFloatArray()
        self.__yArray = vtk.vtkFloatArray()
        # will crash if there is no name
        self.__xArray.SetName('')
        self.__yArray.SetName('signal intensity')
        self.__chartTable.AddColumn(self.__xArray)
        self.__chartTable.AddColumn(self.__yArray)
Example #19
0
  def __init__(self,param):
    super(LesionFormWidget,self).__init__()

    # parameters node keeps all that is needed to render
    # the form and to store the scores
    self.param = param

    self.widget = qt.QWidget()
    self.layout = qt.QHBoxLayout(self.widget)

    lesionNameWidget = qt.QWidget()
    scoreSheetWidget = qt.QWidget()
    plotWidget = qt.QWidget()

    lnLayout = qt.QVBoxLayout(lesionNameWidget)
    ssLayout = qt.QVBoxLayout(scoreSheetWidget)
    pLayout = qt.QVBoxLayout(plotWidget)

    lesionName = qt.QLabel(self.param.lesionName)
    lnLayout.addWidget(lesionName)

    w = qt.QWidget()
    wl = qt.QHBoxLayout(w)

    for i in range(0,6):
      if i:
        label = qt.QLabel(str(i))
      else:
        label = qt.QLabel('')

      wl.addWidget(label)

    ssLayout.addWidget(w)

    w = qt.QWidget()
    wl = qt.QHBoxLayout(w)

    t2label = qt.QLabel('T2W')
    wl.addWidget(t2label)
    t2radios = []
    self.t2group = qt.QButtonGroup()
    for i in range(1,6):
      t2radios.append(qt.QRadioButton())
      self.t2group.addButton(t2radios[-1],i)
      wl.addWidget(t2radios[-1])
    self.t2group.connect('buttonClicked(int)', self.onT2scoreUpdated)
  
    ssLayout.addWidget(w)
  
    w = qt.QWidget()
    wl = qt.QHBoxLayout(w)
  
    dwilabel = qt.QLabel('DWI')
    wl.addWidget(dwilabel)
    dwiradios = []
    self.dwigroup = qt.QButtonGroup()
    for i in range(1,6):
      dwiradios.append(qt.QRadioButton())
      self.dwigroup.addButton(dwiradios[-1],i)
      wl.addWidget(dwiradios[-1])
    self.dwigroup.connect('buttonClicked(int)', self.onDWIscoreUpdated)
  
    ssLayout.addWidget(w)
  
    w = qt.QWidget()
    wl = qt.QHBoxLayout(w)
  
    dcelabel = qt.QLabel('DCE')
    wl.addWidget(dcelabel)
    dceradios = []
    self.dcegroup = qt.QButtonGroup()
    for i in range(1,6):
      dceradios.append(qt.QRadioButton())
      self.dcegroup.addButton(dceradios[-1],i)
      wl.addWidget(dceradios[-1])
    self.dcegroup.connect('buttonClicked(int)', self.onDCEscoreUpdated)
  
    ssLayout.addWidget(w)
  
    chartView = ctk.ctkVTKChartView(plotWidget)
    chart = chartView.chart()
    table = vtk.vtkTable()
    x = vtk.vtkFloatArray()
    y = vtk.vtkFloatArray()
    x.SetName('time point')
    y.SetName('signal intensity')
    table.AddColumn(x)
    table.AddColumn(y)
  
    table.SetNumberOfRows(100)
    for c in range(len(self.param.x)):
      table.SetValue(c,0,self.param.x[c])
      table.SetValue(c,1,self.param.y[c])
    
    plot = chart.AddPlot(0)
    plot.SetInput(table,0,1)
    chart.AddPlot(0)
  
    cw = qt.QWidget()
    cwl = qt.QVBoxLayout(cw)
    cwl.addWidget(chartView)
    pLayout.addWidget(cw)

    self.layout.addWidget(lesionNameWidget)
    self.layout.addWidget(scoreSheetWidget)
    self.layout.addWidget(plotWidget)
    def chartContact(self, screwCount):

        # Show this chart in the plot view
        plotWidget = slicer.app.layoutManager().plotWidget(0)
        plotViewNode = plotWidget.mrmlPlotViewNode()

        # Retrieve/Create plot chart
        plotChartNode = plotViewNode.GetPlotChartNode()
        if not plotChartNode:
            plotChartNode = slicer.mrmlScene.AddNewNodeByClass(
                "vtkMRMLPlotChartNode", "Screw - Bone Contact chart")
            plotViewNode.SetPlotChartNodeID(plotChartNode.GetID())
        plotChartNode.SetTitle("Screw - Bone Contact")
        plotChartNode.SetXAxisTitle('Screw Percentile (Head - Tip)')
        plotChartNode.SetYAxisTitle('Average HU Contact')

        # Retrieve/Create plot table
        firstPlotSeries = plotChartNode.GetNthPlotSeriesNode(0)
        plotTableNode = firstPlotSeries.GetTableNode(
        ) if firstPlotSeries else None
        if not plotTableNode:
            plotTableNode = slicer.mrmlScene.AddNewNodeByClass(
                "vtkMRMLTableNode", "Screw - Bone Contact table")

        # Set x, cortical bone, and cancellous bone columns
        plotTableNode.RemoveAllColumns()
        arrX = vtk.vtkFloatArray()
        arrX.SetName("Screw Percentile")
        plotTableNode.AddColumn(arrX)
        arrCortical = vtk.vtkFloatArray()
        arrCortical.SetName("Cortical Bone")
        plotTableNode.AddColumn(arrCortical)
        arrCancellous = vtk.vtkFloatArray()
        arrCancellous.SetName("Cancellous Bone")
        plotTableNode.AddColumn(arrCancellous)
        numPoints = 10
        plotTable = plotTableNode.GetTable()
        plotTable.SetNumberOfRows(numPoints)
        for i in range(numPoints):
            plotTable.SetValue(i, 0, i * 10)
            plotTable.SetValue(i, 1, 250)
            plotTable.SetValue(i, 2, 130)

        arrays = [arrCortical, arrCancellous]

        for i in range(screwCount):
            # Create an Array Node and add some data
            arrScrew = vtk.vtkFloatArray()
            arrScrew.SetName('Screw %s' % i)
            arrScrew.SetNumberOfValues(numPoints)
            screwValues = self.screwContact[i]
            for j in range(numPoints):
                arrScrew.SetValue(j, screwValues[j])
            plotTableNode.AddColumn(arrScrew)
            arrays.append(arrScrew)

        # Update/Create plot series
        for arrIndex, arr in enumerate(arrays):
            plotSeriesNode = plotChartNode.GetNthPlotSeriesNode(arrIndex)
            if not plotSeriesNode:
                plotSeriesNode = slicer.mrmlScene.AddNewNodeByClass(
                    "vtkMRMLPlotSeriesNode")
                plotChartNode.AddAndObservePlotSeriesNodeID(
                    plotSeriesNode.GetID())
            plotSeriesNode.SetName("{0}".format(arr.GetName()))
            plotSeriesNode.SetAndObserveTableNodeID(plotTableNode.GetID())
            plotSeriesNode.SetXColumnName(arrX.GetName())
            plotSeriesNode.SetYColumnName(arr.GetName())
            plotSeriesNode.SetPlotType(
                slicer.vtkMRMLPlotSeriesNode.PlotTypeScatter)
            if arrIndex < 2:
                # two constant lines
                plotSeriesNode.SetLineStyle(
                    slicer.vtkMRMLPlotSeriesNode.LineStyleDash)
            else:
                plotSeriesNode.SetLineStyle(
                    slicer.vtkMRMLPlotSeriesNode.LineStyleSolid)
            plotSeriesNode.SetMarkerStyle(
                slicer.vtkMRMLPlotSeriesNode.MarkerStyleNone)
            plotSeriesNode.SetUniqueColor()

        # Remove extra series nodes
        for i in range(plotChartNode.GetNumberOfPlotSeriesNodes() -
                       len(arrays)):
            plotChartNode.RemoveNthPlotSeriesNodeID(
                plotChartNode.GetNumberOfPlotSeriesNodes() - 1)
Example #21
0
    def processEvent(self, observee, event):
        #if not self.iCharting.checked:
        #  return
        fgImages = self.nodeImgList[0]
        mvImage = fgImages[0]
        fgNodes = self.nodeList[0]

        nComponents = self.numFrames

        # TODO: use a timer to delay calculation and compress events
        if event == 'LeaveEvent':
            # reset all the readouts
            # TODO: reset the label text
            return

        if not self.sliceWidgetsPerStyle.has_key(observee):
            return

        sliceWidget = self.sliceWidgetsPerStyle[observee]
        sliceLogic = sliceWidget.sliceLogic()
        interactor = observee.GetInteractor()
        xy = interactor.GetEventPosition()

        coordinates = []
        # we need a 4 element point to be able to multiply further down
        coordinates.append(xy[0])
        coordinates.append(xy[1])
        coordinates.append(0)
        coordinates.append(1)

        xyToRas = sliceLogic.GetSliceNode().GetXYToRAS()
        rasPos = xyToRas.MultiplyPoint(coordinates)
        # VTK_CREATE(vtkMatrix4x4, rasToijk);
        rasToijk = vtk.vtkMatrix4x4()
        fgNodes[0].GetRASToIJKMatrix(rasToijk)
        ijkFloat = rasToijk.MultiplyPoint(rasPos)

        ijk = []
        for element in ijkFloat:
            try:
                index = int(round(element))
            except ValueError:
                index = 0
            ijk.append(index)

        extent = mvImage[0].GetExtent()
        if not (ijk[0]>=extent[0] and ijk[0]<=extent[1] and \
           ijk[1]>=extent[2] and ijk[1]<=extent[3] and \
           ijk[2]>=extent[4] and ijk[2]<=extent[5]):

            return

        nComponents = self.numFrames
        # for testing
        # nComponents=1
        if True:
            fgxArray = vtk.vtkFloatArray()
            fgxArray.SetNumberOfTuples(nComponents)
            fgxArray.SetNumberOfComponents(1)
            fgxArray.Allocate(nComponents)
            fgxArray.SetName('frame')

            fgyArray = vtk.vtkFloatArray()
            fgyArray.SetNumberOfTuples(nComponents)
            fgyArray.SetNumberOfComponents(1)
            fgyArray.Allocate(nComponents)
            fgyArray.SetName('signal intensity')

            # will crash if there is no name
            fgChartTable = vtk.vtkTable()
            fgChartTable.AddColumn(fgxArray)
            fgChartTable.AddColumn(fgyArray)
            fgChartTable.SetNumberOfRows(nComponents)

        # get the vector of values at IJK
        if (self.ctrlLevelSlider.maximum - self.ctrlLevelSlider.minimum) > 20:
            intFlag = True
        else:
            intFlag = False

        disVal = []
        if self.ctrlFrameSlider:
            cInd = int(self.ctrlFrameSlider.value)
        else:
            cInd = 0

        for c in range(nComponents):

            for img in fgImages:
                # for c in range(1):
                iLen = len(img)
                if c < iLen:
                    val = img[c].GetScalarComponentAsDouble(
                        ijk[0], ijk[1], ijk[2], 0)
                else:
                    val = img[iLen - 1].GetScalarComponentAsDouble(
                        ijk[0], ijk[1], ijk[2], 0)

                if intFlag:
                    val = int(val)
                else:
                    val = round(val * 100) / 100.0

                # Kilian:  will only show last image - change later
                self.__chartTable.SetValue(c, 0, self.__mvLabels[c])
                self.__chartTable.SetValue(c, 1, val)

                if cInd == c:
                    disVal.append(val)

            #if useFg:
            #  fgValue = fgImage.GetScalarComponentAsDouble(ijk[0],ijk[1],ijk[2],0)
            #  fgChartTable.SetValue(c,0,self.__mvLabels[c])
            #  fgChartTable.SetValue(c,1,fgValue)

        self.valueFrameValues.setText(disVal)

        # To disable plot uncomment
        # return

        baselineAverageSignal = 0
        # if self.iChartingPercent.checked:
        #   # check if percent plotting was requested and recalculate
        #   nBaselines = min(self.baselineFrames.value,nComponents)
        #   for c in range(nBaselines):
        #     baselineAverageSignal += mvImage[0].GetScalarComponentAsDouble(ijk[0],ijk[1],ijk[2],c)
        #   baselineAverageSignal /= nBaselines
        #   if baselineAverageSignal != 0:
        #     for c in range(nComponents):
        #       intensity = mvImage[0].GetScalarComponentAsDouble(ijk[0],ijk[1],ijk[2],c)
        #       self.__chartTable.SetValue(c,1,(intensity/baselineAverageSignal-1)*100.)

        self.__chart.RemovePlot(0)
        self.__chart.RemovePlot(0)

        #if self.iChartingPercent.checked and baselineAverageSignal != 0:
        #  self.__chart.GetAxis(0).SetTitle('change relative to baseline, %')
        #else:
        self.__chart.GetAxis(0).SetTitle('signal intensity')

        #tag = str(self.__mvNode.GetAttribute('MultiVolume.FrameIdentifyingDICOMTagName'))
        #units = str(self.__mvNode.GetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits'))
        #xTitle = tag+', '+units
        self.__chart.GetAxis(1).SetTitle("Time")
        #if self.iChartingIntensityFixedAxes.checked == True:

        # self.__chart.GetAxis(0).SetBehavior(vtk.vtkAxis.FIXED)
        # self.__chart.GetAxis(0).SetRange(self.__mvRange[0],self.__mvRange[1])
        # self.__chart.GetAxis(0).SetRange(2000,6000)

        # self.__chart.GetAxis(1).SetBehavior(vtk.vtkAxis.FIXED)
        # self.__chart.GetAxis(1).SetRange(2000,6000)

        #else:
        #  self.__chart.GetAxis(0).SetBehavior(vtk.vtkAxis.AUTO)
        # if useFg:
        useFg = False
        if useFg:
            plot = self.__chart.AddPlot(vtk.vtkChart.POINTS)
            if vtk.VTK_MAJOR_VERSION <= 5:
                plot.SetInput(self.__chartTable, 0, 1)
            else:
                plot.SetInputData(self.__chartTable, 0, 1)
            fgplot = self.__chart.AddPlot(vtk.vtkChart.LINE)
            if vtk.VTK_MAJOR_VERSION <= 5:
                fgplot.SetInput(fgChartTable, 0, 1)
            else:
                fgplot.SetInputData(fgChartTable, 0, 1)
        else:
            plot = self.__chart.AddPlot(vtk.vtkChart.LINE)
            if vtk.VTK_MAJOR_VERSION <= 5:
                plot.SetInput(self.__chartTable, 0, 1)
            else:
                plot.SetInputData(self.__chartTable, 0, 1)

        if self.xLogScaleCheckBox.checkState() == 2:
            title = self.__chart.GetAxis(1).GetTitle()
            self.__chart.GetAxis(1).SetTitle('log of ' + title)

        if self.yLogScaleCheckBox.checkState() == 2:
            title = self.__chart.GetAxis(0).GetTitle()
            self.__chart.GetAxis(0).SetTitle('log of ' + title)
  def setup( self ):

    self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVCMRMLSceneChanged)

    w = qt.QWidget()
    layout = qt.QGridLayout()
    w.setLayout(layout)
    self.layout.addWidget(w)
    w.show()
    self.layout = layout

    # create frames
    self.inputFrame = ctk.ctkCollapsibleButton()
    self.inputFrame.text = "Input"
    self.inputFrame.collapsed = 0
    inputFrameLayout = qt.QFormLayout(self.inputFrame)
    self.layout.addWidget(self.inputFrame)


    self.ctrlFrame = ctk.ctkCollapsibleButton()
    self.ctrlFrame.text = "Frame control"
    self.ctrlFrame.collapsed = 0
    ctrlFrameLayout = qt.QGridLayout(self.ctrlFrame)
    self.layout.addWidget(self.ctrlFrame)

    self.plotFrame = ctk.ctkCollapsibleButton()
    self.plotFrame.text = "Plotting"
    self.plotFrame.collapsed = 0
    plotFrameLayout = qt.QGridLayout(self.plotFrame)
    self.layout.addWidget(self.plotFrame)

    label = qt.QLabel('Input multivolume')
    self.__mvSelector = slicer.qMRMLNodeComboBox()
    self.__mvSelector.nodeTypes = ['vtkMRMLMultiVolumeNode']
    self.__mvSelector.setMRMLScene(slicer.mrmlScene)
    self.__mvSelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVCMRMLSceneChanged)
    self.__mvSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onInputChanged)
    self.__mvSelector.addEnabled = 0

    inputFrameLayout.addRow(label, self.__mvSelector)
    ##self.layout.addWidget(label)
    ##self.layout.addWidget(self.__mvSelector)


    # TODO: initialize the slider based on the contents of the labels array
    # slider to scroll over metadata stored in the vector container being explored
    self.__mdSlider = ctk.ctkSliderWidget()
    #self.__mdSlider.setRange(0,10)
    #self.__mdSlider.setValue(5)

    label = qt.QLabel('Current frame number')
    ##self.layout.addWidget(label)
    ##self.layout.addWidget(self.__mdSlider)

    # "play" control
    self.playButton = qt.QPushButton('Play')
    self.playButton.toolTip = 'Iterate over multivolume frames'
    self.playButton.checkable = True
    
    ctrlFrameLayout.addWidget(label, 0, 0)
    ctrlFrameLayout.addWidget(self.__mdSlider, 0, 1)
    ctrlFrameLayout.addWidget(self.playButton, 0, 2)
    
    self.playButton.connect('toggled(bool)', self.onPlayButtonToggled)

    self.__mdSlider.connect('valueChanged(double)', self.onSliderChanged)

    label = qt.QLabel('Current frame copy')

    self.__vfSelector = slicer.qMRMLNodeComboBox()
    self.__vfSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
    self.__vfSelector.setMRMLScene(slicer.mrmlScene)
    self.__vfSelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVFMRMLSceneChanged)
    self.__vfSelector.addEnabled = 1
    self.__vfSelector.enabled = 0
    # do not show "children" of vtkMRMLScalarVolumeNode
    self.__vfSelector.hideChildNodeTypes = ["vtkMRMLDiffusionWeightedVolumeNode", \
        "vtkMRMLDiffusionTensorVolumeNode", "vtkMRMLVectorVolumeNode"]

    self.extractFrame = False
    self.extractButton = qt.QPushButton('Enable current frame copying')
    self.extractButton.checkable = True
    self.extractButton.connect('toggled(bool)', self.onExtractFrameToggled)

    ctrlFrameLayout.addWidget(label, 1, 0)
    ctrlFrameLayout.addWidget(self.__vfSelector,1,1,1,2)
    ctrlFrameLayout.addWidget(self.extractButton,2,0,1,3)

    # initialize slice observers (from DataProbe.py)
    # keep list of pairs: [observee,tag] so they can be removed easily
    self.styleObserverTags = []
    # keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic
    self.sliceWidgetsPerStyle = {}
    self.refreshObservers()

    # label map for probing
    label = qt.QLabel('Probed label volume')
    self.__fSelector = slicer.qMRMLNodeComboBox()
    self.__fSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
    self.__fSelector.addAttribute('vtkMRMLScalarVolumeNode','LabelMap','1')
    self.__fSelector.toolTip = 'Label map to be probed'
    self.__fSelector.setMRMLScene(slicer.mrmlScene)
    self.__fSelector.addEnabled = 0
    self.__fSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onLabelVolumeChanged)
    self.__fSelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onLVMRMLSceneChanged)
    plotFrameLayout.addWidget(label,0,0,1,1)
    plotFrameLayout.addWidget(self.__fSelector,0,1,1,2)

    self.iCharting = qt.QPushButton()
    self.iCharting.text = 'Enable interactive charting'
    self.iCharting.checkable = True

    plotFrameLayout.addWidget(self.iCharting,1,0,1,3)
    self.iCharting.setChecked(True)
    self.iCharting.connect('toggled(bool)', self.onInteractiveChartingChanged)

    label = qt.QLabel("Use intensity range to fix axis extent")
    label.toolTip = "If checked, the extent of the vertical axis of the plot will be fixed to the range of the intensities in the input MultiVolume"
    self.__fixedAxesCheckbox = qt.QCheckBox()
    self.__fixedAxesCheckbox.toolTip = "If checked, the extent of the vertical axis of the plot will be fixed to the range of the intensities in the input MultiVolume"
    self.__fixedAxesCheckbox.checked = False
    plotFrameLayout.addWidget(label, 2, 0)
    plotFrameLayout.addWidget(self.__fixedAxesCheckbox, 2,1,1,2)

    # add chart container widget
    self.__chartView = ctk.ctkVTKChartView(w)
    plotFrameLayout.addWidget(self.__chartView,3,0,1,3)


    self.__chart = self.__chartView.chart()
    self.__chartTable = vtk.vtkTable()
    self.__xArray = vtk.vtkFloatArray()
    self.__yArray = vtk.vtkFloatArray()
    # will crash if there is no name
    self.__xArray.SetName('')
    self.__yArray.SetName('signal intensity')
    self.__chartTable.AddColumn(self.__xArray)
    self.__chartTable.AddColumn(self.__yArray)
    def onApplyThreshold(self):
        min,max = self.getDistanceBound()
		
        newPoints = vtk.vtkPoints()
        newLines = vtk.vtkCellArray()
        newTensors = vtk.vtkFloatArray()
        newTensors.SetNumberOfComponents(9)
        newScalars = vtk.vtkFloatArray()

        points = self.inputPolyData.GetPoints()
        lines = self.inputPolyData.GetLines()
        tensors = self.inputPolyData.GetPointData().GetTensors()
        lines.InitTraversal()

        newId = 0
        for length in self.distanceTable:
            if length<=self.thresholdMax.value and length>=self.thresholdMin.value:
                ids = vtk.vtkIdList()
                lines.GetNextCell(ids)
                newLine = vtk.vtkPolyLine()
                #print(ids.GetNumberOfIds())
                newLine.GetPointIds().SetNumberOfIds(ids.GetNumberOfIds())
                #print(((length-min)/(max-min))*100)
                for i in range(ids.GetNumberOfIds()): 
                    newPoints.InsertNextPoint(points.GetPoint(ids.GetId(i)))
                    newLine.GetPointIds().SetId(i,newId)
                    newScalars.InsertNextValue(((length-min)/(max-min)))
                    newId += 1
                    tensorValue = [0]*9
                    if(tensors != None):
                        for j in range(9):
                            tensorValue[j] = tensors.GetComponent(ids.GetId(i),j)
                    newTensors.InsertNextTuple(tensorValue)
                newLines.InsertNextCell(newLine)

        self.outputPolyData = vtk.vtkPolyData()
        self.outputPolyData.SetPoints(newPoints)
        self.outputPolyData.SetLines(newLines)
        self.outputPolyData.GetPointData().SetTensors(newTensors)
        newScalars.SetName("Length")
        self.outputPolyData.GetPointData().AddArray(newScalars)
        self.outputNode.SetAndObservePolyData(self.outputPolyData)
		
        chartViewNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLChartViewNode')
        chartViewNodes.InitTraversal()
        chartViewNode = chartViewNodes.GetNextItemAsObject()
		
        arrayNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLDoubleArrayNode())
        array = arrayNode.GetArray()
        array.SetNumberOfTuples(10)
        step = (max-min)/10
        interMin = min
        interMax = min+step
        for i in range(10):
            numberOfFibers = 0
            for length in self.distanceTable:
                if length<=interMax and length>=interMin and length<=self.thresholdMax.value and length>=self.thresholdMin.value:
                    numberOfFibers += 1
            array.SetComponent(i,0,(interMin+interMax)/2)
            array.SetComponent(i,1,numberOfFibers)
            array.SetComponent(i,2,0)
            interMin += step
            interMax += step
        chartNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLChartNode())
        chartNode.AddArray("Fiber Length",arrayNode.GetID())
        chartViewNode.SetChartNodeID(chartNode.GetID())
		
        chartNode.SetProperty('default', 'title', 'Length Distribution')
        chartNode.SetProperty('default', 'xAxisLabel', 'Length')
        chartNode.SetProperty('default', 'yAxisLabel', 'Distribution')
        chartNode.SetProperty('default', 'type', 'Bar')