Simplicity
Simplicity

Reputation: 48936

AttributeError: Class instance has no attribute 'xyz'

For the class below, I'm getting this exception:

AttributeError: LineIntensityProfileLogic instance has no attribute 'probeVolume' 

How can I solve this issue? Thanks

class LineIntensityProfileLogic(ScriptedLoadableModuleLogic):
  """This class should implement all the actual
  computation done by your module.  The interface
  should be such that other python code can import
  this class and make use of the functionality without
  requiring an instance of the Widget.
  Uses ScriptedLoadableModuleLogic base class, available at:
  https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
  """

  def hasImageData(self,volumeNode):
    """This is a dummy logic method that
    returns true if the passed in volume
    node has valid image data
    """
    if not volumeNode:
      print('no volume node')
      return False
    if volumeNode.GetImageData() == None:
      print('no image data')
      return False
    return True

  def takeScreenshot(self,name,description,type=-1):
    # show the message even if not taking a screen shot
    self.delayDisplay(description)

    if self.enableScreenshots == 0:
      return

    lm = slicer.app.layoutManager()
    # switch on the type to get the requested window
    widget = 0
    if type == slicer.qMRMLScreenShotDialog.FullLayout:
      # full layout
      widget = lm.viewport()
    elif type == slicer.qMRMLScreenShotDialog.ThreeD:
      # just the 3D window
      widget = lm.threeDWidget(0).threeDView()
    elif type == slicer.qMRMLScreenShotDialog.Red:
      # red slice window
      widget = lm.sliceWidget("Red")
    elif type == slicer.qMRMLScreenShotDialog.Yellow:
      # yellow slice window
      widget = lm.sliceWidget("Yellow")
    elif type == slicer.qMRMLScreenShotDialog.Green:
      # green slice window
      widget = lm.sliceWidget("Green")
    else:
      # default to using the full window
      widget = slicer.util.mainWindow()
      # reset the type so that the node is set correctly
      type = slicer.qMRMLScreenShotDialog.FullLayout

    # grab and convert to vtk image data
    qpixMap = qt.QPixmap().grabWidget(widget)
    qimage = qpixMap.toImage()
    imageData = vtk.vtkImageData()
    slicer.qMRMLUtils().qImageToVtkImageData(qimage,imageData)

    annotationLogic = slicer.modules.annotations.logic()
    annotationLogic.CreateSnapShot(name, description, type, self.screenshotScaleFactor, imageData)

  def run(self,volumeNode1,volumeNode2,rulerNode,enableScreenshots=0,screenshotScaleFactor=1):
    """
    Run the actual algorithm
    """
    print('LineIntensityProfileLogic run() called')

    """
    1. get the list(s) of intensity samples along the ruler
    2. set up quantitative layout
    3. use the chart view to plot the intensity sampless
    """

    """
    1. get the list of samples
    """
    if not rulerNode or (not volumeNode1 and not volumeNode2):
      print('Inputs are not initialized')
      return

    volumeSamples1 = None
    volumeSamples2 = None

    if volumeNode1:
      volumeSamples1 = self.probeVolume(volumeNode1, rulerNode)
    if volumeNode2:
      volumeSamples2 = self.probeVolume(volumeNode2, rulerNode)

    print('volumeSamples1 = '+str(volumeSamples1))
    print('volumeSamples2 = '+str(volumeSamples2))

    imageSamples = [volumeSamples1, volumeSamples2]
    legendNames = [volumeNode1.GetName()+' - '+rulerNode.GetName(), volumeNode2.GetName+' - '+rulerNode.GetName()]
    self.showChart(imageSamples, legendNames)

    self.delayDisplay('Running the aglorithm')

    self.enableScreenshots = enableScreenshots
    self.screenshotScaleFactor = screenshotScaleFactor

    self.takeScreenshot('LineIntensityProfile-Start','Start',-1)

    return True

    def probeVolume(self,volumeNode,rulerNode):
    # get ruler endpoints coordinates in RAS 
        p0ras = rulerNode.GetPolyData().GetPoint(0)+(1,)
        p1ras = rulerNode.GetPolyData().GetPoint(1)+(1,)

    # Convert RAS to IJK coordinates of the vtkImageData
    ras2ijk = vtk.vtkMatrix4x4()
    volumeNode.GetRASToIJKMatrix(ras2ijk)
    p0ijk = [int(round(c)) for c in ras2ijk.MultiplyPoint(p0ras)[:3]]
    p1ijk = [int(round(c)) for c in ras2ijk.MultiplyPoint(p1ras)[:3]]

    # Create VTK line that will be used for sampling
    line = vtk.vtkLineSource()
    line.SetResolution(100)
    line.SetPoint1(p0ijk[0],p0ijk[1],p0ijk[2])
    line.SetPoint2(p1ijk[0],p1ijk[1],p1ijk[2])

    # Create VTK probe filter and sample the image
    probe = vtk.vtkProbeFilter()
    probe.SetInputConnection(line.GetOutputPort())
    probe.SetSourceData(volumeNode.GetImageData())
    probe.Update()

    # return VTK array 
    return probe.GetOutput().GetPointData().GetArray('ImageScalars')

    def showChart(self, samples, names):
      print("Logic showing chart")

    # Switch to a layout containing a chart viewer
    lm = slicer.app.layoutManager()
    lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpQuantitativeView)


    # Initialize double array MRML node for each sample list since this is ,
    # what chart view MRML node needs
    doubleArrays = []
    for sample in samples:
      arrayNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLDoubleArrayNode())
      array = arrayNode.GetArray()
      nDataPoints = sample.GetNumberOfTuples()
      array.SetNumberOfTuples(nDataPoints)
      array.SetNumberOfComponents(3)
      for i in range(nDataPoints):
        array.SetComponent(i, 0, i)
        array.SetComponent(i, 1, sample.GetTuple(i))
        array.SetComponent(i, 2, 0)

        doubleArrays.append(arrayNode)

    # Get the chart view MRML node
    cvNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLChartViewNode')
    cvNodes.SetReferenceCount(cvNodes.GetReferenceCount()-1)
    cvNodes.InitTraversal()
    cvNode = cvNodes.GetNextItemAsObject()

    # Create a new chart node
    chartNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLChartNode())
    for pairs in zip(names, doubleArrays):
      chartNode.AddArray(pairs[0], pairs[1], GetID())
    cvNode.SetChartNodeID(chartNode.GetID())

    return

Upvotes: 0

Views: 801

Answers (1)

Anand S Kumar
Anand S Kumar

Reputation: 90979

You seem to be using 2 spaces for indentation.

But for the function - probeVolume , it is indented 4 spaces , which caused it to be inside function run , are you sure that indentation is correct?

Not just probeVolume , function - showChart is also indented 4 spaces,

Upvotes: 1

Related Questions