Ejemplo n.º 1
0
 def onReload(self):
     EditUtil.EditUtil().setCurrentEffect("DefaultTool")
     import Isobrush
     # TODO: this causes a flash of the new widget, but not a big deal since it's only devel mode
     w = Isobrush.IsobrushWidget()
     w.onReload()
     del (w.parent)
     EditUtil.EditUtil().setCurrentEffect("Isobrush")
Ejemplo n.º 2
0
 def updateParam(self, p, v):
     r = self.structuresView.currentIndex().row()
     if (r > -1):
         ei = slicer.modules.SlicerPathologyWidget.editorWidget.helper.structures.item(
             r, 3).text()
     else:
         ei = EditUtil.EditUtil().getParameterNode().GetParameter(
             'SlicerPathology,tilename') + '-label'
     if ei not in params:
         params[ei] = cparams.copy()
         if (r < 0):
             params[ei][
                 'label'] = slicer.modules.SlicerPathologyWidget.editorWidget.helper.editUtil.getLabelName(
                 )
         else:
             params[ei][
                 'label'] = slicer.modules.SlicerPathologyWidget.editorWidget.helper.structures.item(
                     r, 2).text()
     params[ei][p] = v
     cparams[p] = v
     jstr = json.dumps(params,
                       sort_keys=True,
                       indent=4,
                       separators=(',', ': '))
     self.parameterNode.SetParameter("QuickTCGAEffect,erich", jstr)
Ejemplo n.º 3
0
 def updateParameterNode(self, caller, event):
   node = EditUtil.EditUtil().getParameterNode()
   if node != self.parameterNode:
     if self.parameterNode:
       node.RemoveObserver(self.parameterNodeTag)
     self.parameterNode = node
     self.parameterNodeTag = node.AddObserver("ModifiedEvent", self.updateGUIFromMRML)
Ejemplo n.º 4
0
 def updateSliders(self):
     r = self.structuresView.currentIndex().row()
     if (r > -1):
         ei = slicer.modules.SlicerPathologyWidget.editorWidget.helper.structures.item(
             r, 3).text()
     else:
         ei = EditUtil.EditUtil().getParameterNode().GetParameter(
             'SlicerPathology,tilename') + '-label'
     if ei not in params:
         params[ei] = cparams.copy()
         if (r < 0):
             params[ei][
                 'label'] = slicer.modules.SlicerPathologyWidget.editorWidget.helper.editUtil.getLabelName(
                 )
         else:
             params[ei][
                 'label'] = slicer.modules.SlicerPathologyWidget.editorWidget.helper.structures.item(
                     r, 2).text()
         jstr = json.dumps(params,
                           sort_keys=True,
                           indent=4,
                           separators=(',', ': '))
         self.parameterNode.SetParameter("QuickTCGAEffect,erich", jstr)
     self.frameOtsuSlider.value = params[ei]["otsuRatio"]
     self.frameCurvatureWeightSlider.value = params[ei]["curvatureWeight"]
     self.frameSizeThldSlider.value = params[ei]["sizeThld"]
     self.frameSizeUpperThldSlider.value = params[ei]["sizeUpperThld"]
     self.frameMPPSlider.value = params[ei]["mpp"]
Ejemplo n.º 5
0
    def setDefaultParams(self):
        """Configure here all the required params for any LabelEffect (Paint, Draw, ect.)"""
        self.editUtil = EditUtil.EditUtil()
        self.parameterNode = self.editUtil.getParameterNode()

        self.parameterNode.SetParameter("LabelEffect,paintOver", "1") # Enable paintOver
        self.parameterNode.SetParameter("LabelEffect,paintThreshold", "0")   # Enable Threshold checkbox
Ejemplo n.º 6
0
  def step(self, iterations=1):

    if self.pendingEvent:
      if self.pendingEvent.command_execution_status == 0:
        # TODO: is there an attribute for CL_COMPLETE?
        # TODO: also catch error codes here
        #
        # put data back in node
        #
        self.steeredArray[:] = self.labelNext_dev.get()
        self.steeredNode.GetImageData().Modified()
        self.steeredNode.Modified()
      else:
        return

    #
    # get the parameters from MRML
    #
    # TODO: handl any real growcut parameters
    node = EditUtil.EditUtil().getParameterNode()

    #
    # initialize candidates if needed
    #
    if not self.candidatesInitialized:
      self.clProgram.clearShort(
          self.clQueue, self.shape, None, self.candidatesNext_dev.data).wait()
      print("self.candidatesNext_dev mean ", self.candidatesNext_dev.get().mean())
      self.clProgram.initialCandidates(
          self.clQueue, self.shape, None, self.labelArray_dev.data,
          self.candidates_dev.data).wait()
      print("self.labelArray_dev mean ", self.labelArray_dev.get().mean())
      print("self.candidates_dev mean ", self.candidates_dev.get().mean())
      self.candidatesInitialized = True

    #
    # run iterations
    # - save the pending event from the last call so that we can
    #   know when the execution is finished (so the main event loop
    #   is not blocked on this execution)
    #
    for iteration in xrange(iterations):
      self.clProgram.growCut(self.clQueue, self.work_size, None,
          self.backgroundArray_dev.data, self.labelArray_dev.data,
          self.theta_dev.data,
          self.thetaNext_dev.data, self.labelNext_dev.data,
          self.candidates_dev.data, self.candidatesNext_dev.data,
          self.backgroundArrayMax, global_offset=self.work_offset)
      self.clProgram.copyShort(self.clQueue, self.work_size, None,
          self.labelNext_dev.data, self.labelArray_dev.data, global_offset=self.work_offset)
      self.clProgram.copyShort(self.clQueue, self.work_size, None,
          self.candidatesNext_dev.data, self.candidates_dev.data, global_offset=self.work_offset)
      self.clProgram.clearShort(self.clQueue, self.work_size, None,
          self.candidatesNext_dev.data, global_offset=self.work_offset)
      self.pendingEvent = self.clProgram.copyFloat(self.clQueue, self.work_size, None,
          self.thetaNext_dev.data, self.theta_dev.data, global_offset=self.work_offset)
Ejemplo n.º 7
0
 def __init__(self,options,preferredDeviceType='GPU'):
   self.preferredDeviceType = preferredDeviceType
   self.editUtil = EditUtil.EditUtil()
   self.sliceWidget = options.tools[0].sliceWidget
   if hasattr(slicer.modules, 'editorBot'):
     slicer.modules.editorBot.active = False
     del(slicer.modules.editorBot)
   slicer.modules.editorBot = self
   self.interval = 100
   self.active = False
   self.start()
Ejemplo n.º 8
0
    def apply(self, xy, mode=0, forced_path=None, forced_point=None):
        #
        # get the parameters from MRML
        #

        # For sanity purposes, tool can always "paint" over existing labels. If we find some foreseeable reason why we might
        # not want this in all cases, we can re-add to the GUI.

        #
        # get the label and background volume nodes
        #
        labelLogic = self.sliceLogic.GetLabelLayer()
        labelNode = labelLogic.GetVolumeNode()
        backgroundLogic = self.sliceLogic.GetBackgroundLayer()
        backgroundNode = backgroundLogic.GetVolumeNode()

        ##### self.errorMessageFrame.textCursor().insertHtml('Error Detected!')
        ##### self.errorMessageFrame.setStyleSheet("QTextEdit {color:red}")

        #
        # get the ijk location of the clicked point
        # by projecting through patient space back into index
        # space of the volume.  Result is sub-pixel, so round it
        # (note: bg and lb will be the same for volumes created
        # by the editor, but can be different if the use selected
        # different bg nodes, but that is not handled here).
        #
        xyToIJK = labelLogic.GetXYToIJKTransform()
        ijkFloat = xyToIJK.TransformDoublePoint(xy + (0, ))
        ijk = []
        for element in ijkFloat:
            try:
                intElement = int(round(element))
            except ValueError:
                intElement = 0
            ijk.append(intElement)
        ijk.reverse()
        ijk = tuple(ijk)

        ### IJK ACTIVE HERE
        #
        # Get the numpy array for the bg and label
        #
        node = EditUtil.EditUtil().getParameterNode()
        offset = float(node.GetParameter("TraceAndSelect,offsetvalue"))
        if offset != 0 and mode == 0:
            self.progress = qt.QProgressDialog()
            self.progress.setLabelText("Processing Slices...")
            self.progress.setCancelButtonText("Abort Fill")
            self.progress.setMinimum(0)
            self.progress.setMaximum(abs(offset))
            self.progress.setAutoClose(1)
            self.progress.open()
        return self.fill(ijk, [], mode, forced_path, forced_point)
Ejemplo n.º 9
0
    def __init__(self, options):
        self.editUtil = EditUtil.EditUtil()
        #self.sliceWidget = options.tools[0].sliceWidget
        self.sliceWidget = slicer.app.layoutManager().sliceWidget('Red')
        if hasattr(slicer.modules, 'TCGAEditorBot'):
            slicer.modules.TCGAEditorBot.active = False
            del (slicer.modules.TCGAEditorBot)
        slicer.modules.TCGAEditorBot = self

        self.redSliceWidget = options.redSliceWidget
        self.greenSliceWidget = options.greenSliceWidget
        self.yellowSliceWidget = options.yellowSliceWidget
        self.start()
    def onloadCTButtonClicked(self):
        # widge to load file
        w = qt.QWidget()
        w.resize(320, 240)
        w.setWindowTitle("Select CT Image")
        image_path = qt.QFileDialog.getOpenFileName(w, 'Open File', '/')
        path = str('/'.join(image_path.split('/')[0:-1])) + '/'
        print(path)
        print(image_path)

        if image_path is not None:
            self.image_loaded = True
            print(image_path)

        filetype = ".nrrd"
        self.filetype = filetype
        lm = slicer.app.layoutManager()
        lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView)
        view = lm.threeDWidget(0).threeDView()
        viewNode = view.mrmlViewNode()

        viewNode.SetBackgroundColor((0, 0, 0))
        viewNode.SetBackgroundColor2((0, 0, 0))
        viewNode.SetAxisLabelsVisible(0)
        viewNode.SetBoxVisible(0)

        # load image (master volume)
        load, image = slicer.util.loadVolume(image_path, returnNode=True)
        volumesLogic = slicer.modules.volumes.logic()
        label_name = image.GetName() + "-rough-label"
        label = volumesLogic.CreateLabelVolume(slicer.mrmlScene, image,
                                               label_name)
        label_path = str(path + label_name + filetype)
        print(label_path)

        self.view = view
        self.path = path
        self.image_path = image_path
        self.label_path = label_path
        self.image_name = image.GetName()
        self.label_name = label_name
        self.labelpostfix1 = '_tumor_label'
        self.labelpostfix2 = '_lung_label'

        selectionNode = slicer.app.applicationLogic().GetSelectionNode()
        selectionNode.SetReferenceActiveLabelVolumeID(label.GetID())
        EditUtil.EditUtil().propagateVolumeSelection()

        # switch to Edit module
        slicer.util.selectModule('Editor')
        slicer.modules.EditorWidget.toolsBox.selectEffect('PaintEffect')
Ejemplo n.º 11
0
    def __init__(self, sliceLogic):
        print("Preparing Growcut interaction")
        self.attributes = ('MouseTool')
        self.displayName = 'FastGrowCut Effect'

        #disconnect all shortcuts that may exist, to allow Fast GrowCut's to work, reconnect once bot is turned off
        slicer.modules.EditorWidget.removeShortcutKeys()
        self.sliceLogic = sliceLogic
        self.editUtil = EditUtil.EditUtil()

        #initialize Fast GrowCut
        self.init_fGrowCut()

        self.fastCrowCutCreated = False
Ejemplo n.º 12
0
    def __init__(self, sliceLogic):
        print("Preparing CleverSeg interaction")
        self.attributes = ('MouseTool')
        self.displayName = 'CleverSeg Effect'

        # disconnect all shortcuts that may exist, to allow CleverSeg's to work, reconnect once bot is turned off
        slicer.modules.EditorWidget.removeShortcutKeys()
        self.sliceLogic = sliceLogic
        self.editUtil = EditUtil.EditUtil()

        # initialize CleverSeg
        self.init_fCleverSeg()

        self.CleverSegCreated = False
Ejemplo n.º 13
0
    def onloadMRIFLAIRButtonClicked(self):
        # widge to load file
        w = qt.QWidget()
        w.resize(320, 240)
        w.setWindowTitle("Select MRI FLAIR Image")
        self.FLAIR_image_path = qt.QFileDialog.getOpenFileName(
            w, 'Open File', '/')
        self.FLAIR_path = str('/'.join(
            self.FLAIR_image_path.split('/')[0:-1])) + '/'

        lm = slicer.app.layoutManager()
        lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView)
        view = lm.threeDWidget(0).threeDView()
        viewNode = view.mrmlViewNode()

        viewNode.SetBackgroundColor((0, 0, 0))
        viewNode.SetBackgroundColor2((0, 0, 0))
        viewNode.SetAxisLabelsVisible(0)
        viewNode.SetBoxVisible(0)
        self.view = view

        load, image = slicer.util.loadVolume(self.FLAIR_image_path,
                                             returnNode=True)

        # adding a automated seed point
        volumesLogic = slicer.modules.volumes.logic()
        label_name = image.GetName() + "-rough-label"
        label = volumesLogic.CreateLabelVolume(slicer.mrmlScene, image,
                                               label_name)
        #        label_path  = str(path+label_name+filetype)
        #        print(label_path)
        #
        #        self.view = view
        #        self.path = path
        #        self.image_path = image_path
        #        self.label_path = label_path
        #        self.image_name = image.GetName()
        self.label_name = label_name
        #        self.labelpostfix1 = '_tumor_confidenceconnected'
        #        self.labelpostfix2 = '_lung_confidenceconnected'

        selectionNode = slicer.app.applicationLogic().GetSelectionNode()
        selectionNode.SetReferenceActiveLabelVolumeID(label.GetID())
        EditUtil.EditUtil().propagateVolumeSelection()

        # switch to Edit module
        slicer.util.selectModule('Editor')
        slicer.modules.EditorWidget.toolsBox.selectEffect('PaintEffect')
Ejemplo n.º 14
0
    def run_qtcga_segmentation_1(self):
        """
        Original recipe
        :return: 
        """
        if self.bEditTCGA:

            self.currentMessage = "Quick TCGA: running nucleus segmentation ..."
            slicer.util.showStatusMessage(self.currentMessage)
            seedArray = slicer.util.array(self.labelNode.GetName())
            self.qTCGASeedArray[:] = seedArray[:]

            node = EditUtil.EditUtil().getParameterNode()  # get the parameters from MRML
            otsuRatio = float(node.GetParameter("ShortCut,otsuRatio"))
            print(otsuRatio)
            curvatureWeight = float(node.GetParameter("ShortCut,curvatureWeight")) / 10
            print(curvatureWeight)
            sizeThld = float(node.GetParameter("ShortCut,sizeThld"))
            print(sizeThld)
            sizeUpperThld = float(node.GetParameter("ShortCut,sizeUpperThld"))
            print(sizeUpperThld)
            mpp = float(node.GetParameter("ShortCut,mpp")) / 100
            print(mpp)

            self.qTCGAMod.SetotsuRatio(otsuRatio)
            self.qTCGAMod.SetcurvatureWeight(curvatureWeight)
            self.qTCGAMod.SetsizeThld(sizeThld)
            self.qTCGAMod.SetsizeUpperThld(sizeUpperThld)
            self.qTCGAMod.Setmpp(mpp)

            self.qTCGAMod.SetSourceVol(self.foregroundNode.GetImageData())
            self.qTCGAMod.SetSeedVol(self.labelNode.GetImageData())
            self.qTCGASegArray[:] = seedArray[:]

            self.labelNode.GetImageData().Modified()
            self.labelNode.Modified()

            self.bEditTCGA = False

            self.currentMessage = "Quick TCGA done: nuclei segmentation is done; press 'F' to enable ROI selection for refinement"
            slicer.util.showStatusMessage(self.currentMessage)

        else:
            self.currentMessage = "Quick TCGA: go to seed labels first by pressing 'E'"
            slicer.util.showStatusMessage(self.currentMessage)
Ejemplo n.º 15
0
    def setErrorMessage(self, errorText, errorColor=0):
        """Call this to seet the message in the error box.
        Parameters: 
          errorText: string to be displayed in the box 
          errorColor: int 1 or 0 (DEFAULT IS 0) that sets the color of the text as either green (1) or red (0)
        Returns: none"""

        if (errorColor == 1):
            errorColor = "QTextEdit {color:Green}"
        elif (errorColor == 0):
            errorColor = "QTextEdit {color:red}"
        else:
            # Why did you do this? Read the function? I'm going to make the text white to punish you
            errorColor = "QTextEdit {color:white}"

        node = EditUtil.EditUtil().getParameterNode()
        node.SetParameter("TraceAndSelect,errorMessage", str(errorText))
        node.SetParameter("TraceAndSelect,errorMessageColor", str(errorColor))
        return
Ejemplo n.º 16
0
    def runQTCGA_NucleiSegYi(self):
        self.currentMessage = "Quick TCGA: running nucleus segmentation ..."
        slicer.util.showStatusMessage(self.currentMessage)
        seedArray = slicer.util.array(self.labelNode.GetName())
        self.qTCGASeedArray[:] = seedArray[:]

        node = EditUtil.EditUtil().getParameterNode(
        )  # get the parameters from MRML
        otsuRatio = float(node.GetParameter("QuickTCGAEffect,otsuRatio"))
        curvatureWeight = float(
            node.GetParameter("QuickTCGAEffect,curvatureWeight")) / 10
        sizeThld = float(node.GetParameter("QuickTCGAEffect,sizeThld"))
        sizeUpperThld = float(
            node.GetParameter("QuickTCGAEffect,sizeUpperThld"))
        mpp = float(node.GetParameter("QuickTCGAEffect,mpp")) / 100

        self.qTCGAMod.SetotsuRatio(otsuRatio)
        self.qTCGAMod.SetcurvatureWeight(curvatureWeight)
        self.qTCGAMod.SetsizeThld(sizeThld)
        self.qTCGAMod.SetsizeUpperThld(sizeUpperThld)
        self.qTCGAMod.Setmpp(mpp)
        AA = self.foregroundNode.GetImageData()
        a1 = 0
        b1 = 0
        ddd = AA.GetDimensions()
        a2 = ddd[0] - 1
        b2 = ddd[1] - 1
        LL = self.labelNode.GetImageData()
        BB = self.GetTile(AA, a1, b1, a2, b2)
        LL = self.GetTile(LL, a1, b1, a2, b2)
        self.qTCGAMod.SetSourceVol(BB)
        self.qTCGAMod.SetSeedVol(LL)
        self.qTCGAMod.Run_NucleiSegYi()
        self.qTCGASegArray[:] = seedArray[:]
        self.MergeImages(LL, self.labelNode.GetImageData(), a1, b1)
        self.foregroundNode.GetImageData().Modified()
        self.foregroundNode.Modified()
        self.labelNode.GetImageData().Modified()
        self.labelNode.Modified()
        self.currentMessage = "Quick TCGA done: nuclei segmetnation is done; press 'F' to enable ROI selection for refinement"
        slicer.util.showStatusMessage(self.currentMessage)
Ejemplo n.º 17
0
    def __init__(self, sliceLogic):
        print("Preparing Quick TCGA Interaction")
        self.attributes = 'MouseTool'
        self.displayName = 'ShortCut Effect'

        # disconnect all shortcuts that may exist, to allow ShortCut's to work, reconnect once bot is turned off
        if hasattr(slicer.modules, 'EditorWidget'):
            slicer.modules.EditorWidget.removeShortcutKeys()
        self.sliceLogic = sliceLogic
        self.editUtil = EditUtil.EditUtil()
        self.swRed = slicer.app.layoutManager().sliceWidget('Red').sliceLogic()
        self.sw = slicer.app.layoutManager().sliceWidget('Red')
        self.interactor = self.sw.sliceView().interactor()  # initialize to red slice interactor
        # self.computeCurrSliceSmarter()  # initialize the current slice to something meaningful

        self.mouse_obs_growcut, self.swLUT_growcut = bind_view_observers(self.updateShortCutROI)

        # initialize Fast GrowCut
        self.init_ShortCut()

        self.ShortCutCreated = False
Ejemplo n.º 18
0
 def onSaveButtonClicked(self):
     bundle = EditUtil.EditUtil().getParameterNode().GetParameter(
         'QuickTCGAEffect,erich')
     tran = json.loads(bundle)
     layers = []
     for key in tran:
         nn = tran[key]
         nn["file"] = key + '.tif'
         layers.append(tran[key])
     j = {}
     j['layers'] = layers
     j['username'] = self.setupUserName.text
     j['sourcetile'] = self.tilename
     j['generator'] = "3DSlicer-4.5.0 with SlicerPathology v1.0a"
     j['timestamp'] = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
     labelNodes = slicer.util.getNodes('vtkMRMLLabelMapVolumeNode*')
     savedMessage = 'Segmentations for the following series were saved:\n\n'
     for label in labelNodes.values():
         labelName = label.GetName()
         labelFileName = os.path.join(self.dataDirButton.directory,
                                      labelName + '.tif')
         print "labelFileName : " + labelFileName
         sNode = slicer.vtkMRMLVolumeArchetypeStorageNode()
         sNode.SetFileName(labelFileName)
         sNode.SetWriteFileFormat('tif')
         sNode.SetURI(None)
         success = sNode.WriteData(label)
         if success:
             print "successful writing " + labelFileName
         else:
             print "failed writing " + labelFileName
     jstr = json.dumps(j, sort_keys=True, indent=4, separators=(',', ': '))
     f = open(
         os.path.join(self.dataDirButton.directory,
                      self.tilename + '.json'), 'w')
     f.write(jstr)
     f.close()
Ejemplo n.º 19
0
    def fill(self,
             ijk,
             optional_seeds=[],
             mode=0,
             forced_path=None,
             forced_point=None):
        print("Mode: %d" % mode)
        paintOver = 1
        mean = (0, 0)
        count = 0
        node = EditUtil.EditUtil().getParameterNode()

        # Max number of pixels to fill in (does not include path)
        print("@@@MaxPixels:%s" %
              node.GetParameter("TraceAndSelect,maxPixels"))
        maxPixels = float(node.GetParameter("TraceAndSelect,maxPixels"))

        # Minimum intensity value to be detected
        print("@@@Theshold Min:%s" %
              node.GetParameter("TraceAndSelect,paintThresholdMin"))
        thresholdMin = float(
            node.GetParameter("TraceAndSelect,paintThresholdMin"))

        # Maximum intensity value to be detected
        print("@@@Theshold Max:%s" %
              node.GetParameter("TraceAndSelect,paintThresholdMax"))
        thresholdMax = float(
            node.GetParameter("TraceAndSelect,paintThresholdMax"))

        labelLogic = self.sliceLogic.GetLabelLayer()
        labelNode = labelLogic.GetVolumeNode()
        backgroundLogic = self.sliceLogic.GetBackgroundLayer()
        backgroundNode = backgroundLogic.GetVolumeNode()

        import vtk.util.numpy_support, numpy
        backgroundImage = backgroundNode.GetImageData()
        labelImage = labelNode.GetImageData()
        shape = list(backgroundImage.GetDimensions())
        shape.reverse()
        backgroundArray = vtk.util.numpy_support.vtk_to_numpy(
            backgroundImage.GetPointData().GetScalars()).reshape(shape)
        labelArray = vtk.util.numpy_support.vtk_to_numpy(
            labelImage.GetPointData().GetScalars()).reshape(shape)

        ijk_reconstruction_indexes = []
        # THIS SHOULD ALWAYS BE TRUE
        # VOLUME MODE IS DISABLED BECAUSE I HAVE NO CLUE WHAT IT IS
        original_ijk = list(ijk)
        if self.fillMode == 'Plane':
            # select the plane corresponding to current slice orientation
            # for the input volume
            ijkPlane = self.sliceIJKPlane()
            i, j, k = ijk
            if ijkPlane == 'JK':
                backgroundDrawArray = backgroundArray[:, :, k]
                labelDrawArray = labelArray[:, :, k]
                ijk = (i, j)
                ijk_reconstruction_indexes = (0, 1)
            if ijkPlane == 'IK':
                backgroundDrawArray = backgroundArray[:, j, :]
                labelDrawArray = labelArray[:, j, :]
                ijk = (i, k)
                ijk_reconstruction_indexes = (0, 2)
            if ijkPlane == 'IJ':
                backgroundDrawArray = backgroundArray[i, :, :]
                labelDrawArray = labelArray[i, :, :]
                ijk = (j, k)
                ijk_reconstruction_indexes = (1, 2)
        else:
            print(
                "HOW DID YOU DO THAT??? WHAT DID YOU DO TO ACTIVATE VOLUME MODE???"
            )
            self.setErrorMessage("Error: volume mode not supported.")
            return

        # Log info about where the user clicked for debugging purposes
        value = backgroundDrawArray[ijk]
        print("@@@location=", ijk)
        print("@@@value=", value)

        # Get the current label that the user wishes to assign using the tool
        label = EditUtil.EditUtil().getLabel()

        # Use lo and hi for threshold checks
        # Easiest way to do things is check if a pixel is outside the threshold, ie.

        lo = thresholdMin
        hi = thresholdMax

        best_path = []
        fill_point = ijk

        if mode == 0 and forced_path is not None and forced_point is not None:
            best_path = forced_path
            fill_point = forced_point
        else:
            # Build path

            best_path, visited, dead_ends = gimme_a_path(
                ijk, 200, hi, lo, backgroundDrawArray, optional_seeds)
            print("@@@Dead ends:", dead_ends)

            attempts = 0
            max_attempts = 2
            while dead_ends > 150 or dead_ends < 0 and attempts < max_attempts:
                attempts += 1
                lo -= 25
                print("Lowering min tolerance to:", lo)
                node.SetParameter("LabelEffect,paintThresholdMin", str(lo))
                best_path, visited, dead_ends = gimme_a_path(
                    ijk, 200, hi, lo, backgroundDrawArray, optional_seeds)
                print("@@@Dead ends:", dead_ends)

            if dead_ends < 0:
                print("@@@No path found? Weird.")
                self.setErrorMessage(
                    "Error: could not find any suitable path.")
                return

            # Save state before doing anything
            self.undoRedo.saveState()
            for pixel in visited:
                labelDrawArray[pixel] = label

            EditUtil.EditUtil().markVolumeNodeAsModified(labelNode)

            if mode == 1:  # Outline only mode
                print("Outline made, returning.")
                self.setErrorMessage(
                    "Preview complete. No errrors detected.\nLeft click to confirm.\nRight click to try a new outline.\nUndo to remove.",
                    1)
                return (best_path, ijk)

        #
        # Fill path
        #

        # Fill the path using a recursive search
        toVisit = [
            fill_point,
        ]
        extrema = get_extrema(best_path)
        # Create a map that contains the location of the pixels
        # that have been already visited (added or considered to be added).
        # This is required if paintOver is enabled because then we reconsider
        # all pixels (not just the ones that have not labelled yet).
        if paintOver:
            labelDrawVisitedArray = numpy.zeros(labelDrawArray.shape,
                                                dtype='bool')

        pixelsSet = 0
        print("@@@FILLING PATH")
        while toVisit != []:
            location = toVisit.pop(0)

            try:
                l = fetch_val(labelDrawArray, location)
                b = fetch_val(backgroundDrawArray, location)
            except IndexError:
                continue
            if (not paintOver and l != 0):
                # label filled already and not painting over, leave it alone
                continue
            try:
                if (paintOver and l == label):
                    temp1 = mean[0] + location[0]
                    temp2 = mean[1] + location[1]
                    mean = (temp1, temp2)
                    count += 1
                    # label is the current one, but maybe it was filled with another high/low value,
                    # so we have to visit it once (and only once) in this session, too
                    if labelDrawVisitedArray[location]:
                        # visited already, so don't try to fill it again
                        continue
                    else:
                        # we'll visit this pixel now, so mark it as visited
                        labelDrawVisitedArray[location] = True
            except ValueError:
                print("@@@VALUE ERROR!", l)
                print("@@@Location: ", location)
                print("@@@fill_point:", fill_point)
                print("@@@toVisit:", toVisit)
                continue
            if location in best_path:
                continue
            if not (extrema[0] < location[0] < extrema[1]
                    and extrema[2] < location[1] < extrema[3]):
                # Went out of bounds for path
                print("@@@WENT OUT OF BOUNDS FOR PATH!")
                self.setErrorMessage("Error: Went out of bounds for path.")
                self.undoRedo.undo()
                return
            labelDrawArray[location] = label
            if l != label:
                # only count those pixels that were changed (to allow step-by-step growing by multiple mouse clicks)
                pixelsSet += 1
            if pixelsSet > maxPixels:
                toVisit = []
            else:
                # add the 4 neighbors to the stack
                toVisit.append((location[0] - 1, location[1]))
                toVisit.append((location[0] + 1, location[1]))
                toVisit.append((location[0], location[1] - 1))
                toVisit.append((location[0], location[1] + 1))

        # signal to slicer that the label needs to be updated
        ## CHANGE OFFSET
        print("@@@Offset:|%s|" %
              node.GetParameter("TraceAndSelect,offsetvalue"))

        self.offset = float(node.GetParameter("TraceAndSelect,offsetvalue"))
        print("OFFSET SIGN: %s" % math.copysign(1, self.offset))

        if self.offset != 0:
            slices_seen = self.progress.maximum - abs(self.offset)
            if self.progress.wasCanceled:
                self.offset = 0
                layoutManager = slicer.app.layoutManager()
                widget = layoutManager.sliceWidget('Red')
                rednode = widget.sliceLogic().GetSliceNode()
                rednode.SetSliceOffset(rednode.GetSliceOffset() +
                                       math.copysign(1, self.offset))
                node.SetParameter("TraceAndSelect,offsetvalue", str(0))
                self.setErrorMessage(
                    "Fill abandoned after {} slice(s)".format(
                        int(slices_seen)), 1)
                return
            self.progress.setValue(slices_seen)
            layoutManager = slicer.app.layoutManager()
            widget = layoutManager.sliceWidget('Red')
            rednode = widget.sliceLogic().GetSliceNode()
            rednode.SetSliceOffset(rednode.GetSliceOffset() +
                                   math.copysign(1, self.offset))
            node.SetParameter("TraceAndSelect,offsetvalue",
                              str(self.offset - math.copysign(1, self.offset)))
            print(self.offset)

            ### Calc centoid mean stuff here

            recs_mean = (mean[0] / count, mean[1] / count)
            rec_mean = get_optional_seeds(best_path, recs_mean)[0]
            print("MEAN:", rec_mean, recs_mean)
            rec_ijk = list(original_ijk)
            for i in range(0, 3):
                rec_ijk[i] = int(rec_ijk[i] +
                                 int(math.copysign(1, self.offset)))
            rec_ijk[ijk_reconstruction_indexes[0]] = rec_mean[0]
            rec_ijk[ijk_reconstruction_indexes[1]] = rec_mean[1]
            print("RECURSIVE IJK:", rec_ijk)
            print("#########RECURSE#########")
            return self.fill(rec_ijk,
                             optional_seeds=get_optional_seeds(
                                 best_path, recs_mean))

            ###

        print("@@@FILL DONE")
        EditUtil.EditUtil().markVolumeNodeAsModified(labelNode)
        self.setErrorMessage("Fill complete. No errors detected.", 1)

        return
Ejemplo n.º 20
0
  def apply(self,xy):
    #
    # get the parameters from MRML
    #
    node = EditUtil.EditUtil().getParameterNode()
    tolerance = float(node.GetParameter("WandEffect,tolerance"))
    maxPixels = float(node.GetParameter("WandEffect,maxPixels"))
    paintOver = int(node.GetParameter("LabelEffect,paintOver"))
    
    #
    # get the label and background volume nodes
    #
    labelLogic = self.sliceLogic.GetLabelLayer()
    labelNode = labelLogic.GetVolumeNode()
    backgroundLogic = self.sliceLogic.GetBackgroundLayer()
    backgroundNode = backgroundLogic.GetVolumeNode()

    #
    # get the ijk location of the clicked point
    # by projecting through patient space back into index
    # space of the volume.  Result is sub-pixel, so round it
    # (note: bg and lb will be the same for volumes created
    # by the editor, but can be different if the use selected
    # different bg nodes, but that is not handled here).
    # 
    xyToIJK = labelLogic.GetXYToIJKTransform().GetMatrix()
    ijkFloat = xyToIJK.MultiplyPoint(xy+(0,1))[:3]
    ijk = []
    for element in ijkFloat:
      try:
        intElement = int(round(element))
      except ValueError:
        intElement = 0
      ijk.append(intElement)
    ijk.reverse()
    ijk = tuple(ijk)

    #
    # Get the numpy array for the bg and label
    #
    import vtk.util.numpy_support
    backgroundImage = backgroundNode.GetImageData()
    labelImage = labelNode.GetImageData()
    shape = list(backgroundImage.GetDimensions())
    shape.reverse()
    backgroundArray = vtk.util.numpy_support.vtk_to_numpy(backgroundImage.GetPointData().GetScalars()).reshape(shape)
    labelArray = vtk.util.numpy_support.vtk_to_numpy(labelImage.GetPointData().GetScalars()).reshape(shape)

    if self.fillMode == 'Plane':
      # select the plane corresponding to current slice orientation
      # for the input volume
      ijkPlane = self.sliceIJKPlane()
      i,j,k = ijk
      if ijkPlane == 'JK':
        backgroundDrawArray = backgroundArray[:,:,k]
        labelDrawArray = labelArray[:,:,k]
        ijk = (i, j)
      if ijkPlane == 'IK':
        backgroundDrawArray = backgroundArray[:,j,:]
        labelDrawArray = labelArray[:,j,:]
        ijk = (i, k)
      if ijkPlane == 'IJ':
        backgroundDrawArray = backgroundArray[i,:,:]
        labelDrawArray = labelArray[i,:,:]
        ijk = (j, k)
    elif self.fillMode == 'Volume':
      backgroundDrawArray = backgroundArray
      labelDrawArray = labelArray

    #
    # do a recursive search for pixels to change
    #
    self.undoRedo.saveState()
    value = backgroundDrawArray[ijk]
    label = EditUtil.EditUtil().getLabel()
    lo = value - tolerance
    hi = value + tolerance
    pixelsSet = 0
    toVisit = [ijk,]
    visited = []    
    while toVisit != []:
      location = toVisit.pop(0)
      try:
        l = labelDrawArray[location]
        b = backgroundDrawArray[location]
      except IndexError:
        continue
      if (not paintOver and l != 0):
        # label filled already and not painting over, leave it alone
        continue
      if (paintOver and l == label):
        # label is the current one, but maybe it was filled with another high/low value,
        # so we have to visit it once (and only once) in this session, too
        visitedCurrentLocation = True
        try:
          visited.index(location)
        except ValueError:
          # not found, so not visited yet
          visitedCurrentLocation = False
        if visitedCurrentLocation:        
          continue
        else:
          visited.append(location)
      if b < lo or b > hi:
        continue
      labelDrawArray[location] = label        
      if l != label:
        # only count those pixels that were changed (to allow step-by-step growing by multiple mouse clicks)
        pixelsSet += 1      
      if pixelsSet > maxPixels:
        toVisit = []
      else:
        if self.fillMode == 'Plane':
          # add the 4 neighbors to the stack
          toVisit.append((location[0] - 1, location[1]     ))
          toVisit.append((location[0] + 1, location[1]     ))
          toVisit.append((location[0]    , location[1] - 1 ))
          toVisit.append((location[0]    , location[1] + 1 ))
        elif self.fillMode == 'Volume':
          # add the 6 neighbors to the stack
          toVisit.append((location[0] - 1, location[1]    , location[2]    ))
          toVisit.append((location[0] + 1, location[1]    , location[2]    ))
          toVisit.append((location[0]    , location[1] - 1, location[2]    ))
          toVisit.append((location[0]    , location[1] + 1, location[2]    ))
          toVisit.append((location[0]    , location[1]    , location[2] - 1))
          toVisit.append((location[0]    , location[1]    , location[2] + 1))

    # signal to slicer that the label needs to be updated
    labelImage.Modified()
    labelNode.Modified()
Ejemplo n.º 21
0
    def init_QuickTCGA(self):
        self.emergencyStopFunc = None
        self.dialogBox = qt.QMessageBox(
        )  #will display messages to draw users attention if he does anything wrong
        self.dialogBox.setWindowTitle("QuickTCGA Error")
        self.dialogBox.setWindowModality(
            qt.Qt.NonModal
        )  #will allow user to continue interacting with Slicer

        # TODO: check this claim- might be causing leaks
        # set the image, label nodes (this will not change although the user can
        # alter what is bgrnd/frgrnd in editor)
        # Confused about how info propagates UIarray to UIVol, not the other way, NEEDS AUTO TESTS

        self.labelNode = self.editUtil.getLabelVolume(
        )  #labelLogic.GetVolumeNode()
        self.backgroundNode = self.editUtil.getBackgroundVolume(
        )  #backgroundLogic.GetVolumeNode()
        self.foregroundNode = self.swRed.GetForegroundLayer().GetVolumeNode()

        #perform safety check on right images/labels being selected, #set up images
        #if red slice doesnt have a label or image, go no further
        if type(self.backgroundNode) == type(None) or type(
                self.labelNode) == type(None):
            self.dialogBox.setText(
                "Either Image (must be Background Image) or Label not set in slice views."
            )
            self.dialogBox.show()

        if self.emergencyStopFunc:
            self.emergencyStopFunc()
            return

        volumesLogic = slicer.modules.volumes.logic()

        self.labelName = self.labelNode.GetName(
        )  # record name of label so user, cant trick us
        self.imgBgrdName = self.backgroundNode.GetName()
        self.imgFgrdName = self.foregroundNode.GetName()

        if self.sliceViewMatchEditor(
                self.sliceLogic
        ) == False:  # do nothing, exit function if user has played with images
            if self.emergencyStopFunc:
                self.emergencyStopFunc()
                return

        # QuickTCGA shortcuts

    ##resetQTCGAKey = qt.QKeySequence(qt.Qt.Key_R) # reset initialization flag
    ##runQTCGAClusterKey = qt.QKeySequence(qt.Qt.Key_S) # run fast growcut
        runNucleiSegKey = qt.QKeySequence(qt.Qt.Key_Y)
        ##editTCGAKey = qt.QKeySequence(qt.Qt.Key_E) # edit seed labels
        ##runQTCGATemplateKey = qt.QKeySequence(qt.Qt.Key_T)
        ##runQTCGARefineCurvatureKey = qt.QKeySequence(qt.Qt.Key_U)
        ##runQTCGAShortCutKey = qt.QKeySequence(qt.Qt.Key_C)
        ##runQTCGAShortEditCutKey = qt.QKeySequence(qt.Qt.Key_F)

        print " key to run QuickTCGA segmentation is  Y"

        self.qtkeyconnections = []
        self.qtkeydefsQTCGA = [[runNucleiSegKey, self.runQTCGA_NucleiSegYi]]

        for keydef in self.qtkeydefsQTCGA:
            s = qt.QShortcut(keydef[0], slicer.util.mainWindow()
                             )  # connect this qt event to mainWindow focus
            s.connect('activated()', keydef[1])
            self.qtkeyconnections.append(s)

        self.qTCGALabMod_tag = self.sliceLogic.AddObserver(
            "ModifiedEvent", self.QTCGAChangeLabelInput
        )  # put test listener on the whole window

        # Quick TCGA parameters
        self.bEditTCGA = True
        self.bEditShortCut = False
        self.currentMessage = ""

        seedArray = slicer.util.array(self.labelName)
        self.qTCGASeedArray = seedArray.copy()
        self.qTCGASegArray = seedArray.copy()
        self.qTCGASeedArray[:] = 0
        self.qTCGASegArray[:] = 0

        self.SCutROIRad = 50
        self.volSize = self.labelNode.GetImageData().GetDimensions()
        self.qSCutROIArray = seedArray.copy(
        )  #np.zeros([self.volSize[0],self.volSize[1],1])
        self.qSCutROIArray[:] = 0

        roiVTK = vtk.vtkImageData()
        roiVTK.DeepCopy(self.labelNode.GetImageData())
        self.roiVTK = roiVTK

        import vtkSlicerQuickTCGAModuleLogicPython

        node = EditUtil.EditUtil().getParameterNode(
        )  # get the parameters from MRML
        otsuRatio = float(node.GetParameter("QuickTCGAEffect,otsuRatio"))
        curvatureWeight = float(
            node.GetParameter("QuickTCGAEffect,curvatureWeight")) / 10
        sizeThld = float(node.GetParameter("QuickTCGAEffect,sizeThld"))
        sizeUpperThld = float(
            node.GetParameter("QuickTCGAEffect,sizeUpperThld"))
        mpp = float(node.GetParameter("QuickTCGAEffect,mpp")) / 100
        cparams["otsuRatio"] = otsuRatio
        cparams["curvatureWeight"] = curvatureWeight
        cparams["sizeThld"] = sizeThld
        cparams["sizeUpperThld"] = sizeUpperThld
        cparams["mpp"] = mpp
        qTCGAMod = vtkSlicerQuickTCGAModuleLogicPython.vtkQuickTCGA()
        qTCGAMod.SetSourceVol(self.foregroundNode.GetImageData())
        qTCGAMod.SetotsuRatio(otsuRatio)
        qTCGAMod.SetcurvatureWeight(curvatureWeight)
        qTCGAMod.SetsizeThld(sizeThld)
        qTCGAMod.SetsizeUpperThld(sizeUpperThld)
        qTCGAMod.Setmpp(mpp)
        qTCGAMod.Initialization()
        self.qTCGAMod = qTCGAMod
        self.QuickTCGACreated = True  #tracks if completed the initializtion (so can do stop correctly) of KSlice
Ejemplo n.º 22
0
  def apply(self,xy):
    # TODO: save the undo state - not yet available for extensions
    # EditorStoreCheckPoint $_layers(label,node)
    
    #
    # get the parameters from MRML
    #
    node = EditUtil.EditUtil().getParameterNode()
    tolerance = float(node.GetParameter("GooCut,tolerance"))
    maxPixels = float(node.GetParameter("GooCut,maxPixels"))


    #
    # get the label and background volume nodes
    #
    labelLogic = self.sliceLogic.GetLabelLayer()
    labelNode = labelLogic.GetVolumeNode()
    labelNode.SetModifiedSinceRead(1)
    backgroundLogic = self.sliceLogic.GetBackgroundLayer()
    backgroundNode = backgroundLogic.GetVolumeNode()

    #
    # get the ijk location of the clicked point
    # by projecting through patient space back into index
    # space of the volume.  Result is sub-pixel, so round it
    # (note: bg and lb will be the same for volumes created
    # by the editor, but can be different if the use selected
    # different bg nodes, but that is not handled here).
    # 
    xyToIJK = labelLogic.GetXYToIJKTransform().GetMatrix()
    ijkFloat = xyToIJK.MultiplyPoint(xy+(0,1))[:3]
    ijk = []
    for element in ijkFloat:
      try:
        intElement = int(element)
      except ValueError:
        intElement = 0
      ijk.append(intElement)
    ijk.reverse()
    ijk = tuple(ijk)

    #
    # Get the numpy array for the bg and label
    #
    import vtk.util.numpy_support
    backgroundImage = backgroundNode.GetImageData()
    labelImage = labelNode.GetImageData()
    shape = list(backgroundImage.GetDimensions())
    shape.reverse()
    backgroundArray = vtk.util.numpy_support.vtk_to_numpy(backgroundImage.GetPointData().GetScalars()).reshape(shape)
    labelArray = vtk.util.numpy_support.vtk_to_numpy(labelImage.GetPointData().GetScalars()).reshape(shape)

    #
    # do a region growing
    #
    try:
      value = backgroundArray[ijk]
    except IndexError:
      # outside of volume
      return
    label = EditUtil.EditUtil().getLabel()
    lo = value - tolerance
    hi = value + tolerance
    pixelsSet = 0
    toVisit = [ijk,]
    while toVisit != []:
      location = toVisit.pop()
      try:
        l = labelArray[location]
        b = backgroundArray[location]
      except IndexError:
        continue
      if l != 0 or b < lo or b > hi:
        continue
      labelArray[location] = label
      pixelsSet += 1
      if pixelsSet > maxPixels:
        toVisit = []
      else:
        # add the 6 neighbors to the stack
        toVisit.append((location[0] - 1, location[1]    , location[2]    ))
        toVisit.append((location[0] + 1, location[1]    , location[2]    ))
        toVisit.append((location[0]    , location[1] - 1, location[2]    ))
        toVisit.append((location[0]    , location[1] + 1, location[2]    ))
        toVisit.append((location[0]    , location[1]    , location[2] - 1))
        toVisit.append((location[0]    , location[1]    , location[2] + 1))

    labelImage.Modified()
    labelNode.Modified()
Ejemplo n.º 23
0
    def processEvent(self, caller=None, event=None):
        """
    handle events from the render window interactor
    """

        node = EditUtil.EditUtil().getParameterNode()
        preview = int(node.GetParameter("TraceAndSelect,preview"))
        # Clear any saved outlines if preview has been just disabled
        if not preview:
            if self.prevPath != []:
                self.prevPath = []
                self.prevFillPoint = None
                self.undoRedo.undo()

        # let the superclass deal with the event if it wants to
        super(TraceAndSelectTool, self).processEvent(caller, event)

        # LEFT CLICK
        if event == "LeftButtonPressEvent":
            xy = self.interactor.GetEventPosition()
            sliceLogic = self.sliceWidget.sliceLogic()
            logic = TraceAndSelectLogic(sliceLogic)
            logic.undoRedo = self.undoRedo
            if self.prevPath != []:
                logic.apply(xy,
                            forced_path=self.prevPath,
                            forced_point=self.prevFillPoint)
                self.prevPath = []
                self.prevFillPoint = None
            else:
                logic.apply(xy)
            print("Got a %s at %s in %s" %
                  (event, str(xy),
                   self.sliceWidget.sliceLogic().GetSliceNode().GetName()))
            self.abortEvent(event)
        # RIGHT CLICK
        elif event == "RightButtonPressEvent" and preview:
            xy = self.interactor.GetEventPosition()
            sliceLogic = self.sliceWidget.sliceLogic()
            logic = TraceAndSelectLogic(sliceLogic)
            logic.undoRedo = self.undoRedo
            # Erase stored path and remove from view
            if self.prevPath != []:
                self.prevPath = []
                self.prevFillPoint = None
                logic.undoRedo.undo()
            # Store prevPath and prevFillPoint
            self.prevPath, self.prevFillPoint = logic.apply(xy, 1)
            print("Got a %s at %s in %s" %
                  (event, str(xy),
                   self.sliceWidget.sliceLogic().GetSliceNode().GetName()))
            self.abortEvent(event)
        # SLICE VIEW HAS CHANGED
        elif event == "ModifiedEvent":  # Offset was changed on one of the viewing panels
            # Erase stored path and remove from view
            if self.prevPath != []:
                self.prevPath = []
                self.prevFillPoint = None
                self.undoRedo.undo()
                sliceLogic = self.sliceWidget.sliceLogic()
                logic = TraceAndSelectLogic(sliceLogic)
                logic.setErrorMessage("Previewed path was discarded.", 1)

        else:
            pass

        # events from the slice node
        if caller and caller.IsA('vtkMRMLSliceNode'):
            # here you can respond to pan/zoom or other changes
            # to the view
            pass