예제 #1
0
  def setupMeasurementsArea(self):
    self.measurementsGroupBox = qt.QGroupBox("Measurements")
    self.measurementsGroupBox.setLayout(qt.QGridLayout())
    self.tableView = slicer.qMRMLTableView()
    self.tableView.setMinimumHeight(150)
    self.tableView.setMaximumHeight(150)
    self.tableView.setSelectionBehavior(qt.QTableView.SelectRows)

    if ModuleWidgetMixin.isQtVersionOlder():
      self.tableView.horizontalHeader().setResizeMode(qt.QHeaderView.Stretch)
    else:
      self.tableView.horizontalHeader().setSectionResizeMode(qt.QHeaderView.Stretch)

    self.fourUpTableView = None
    self.segmentStatisticsConfigButton = self.createButton("Segment Statistics Parameters")

    self.calculateMeasurementsButton = self.createButton("Calculate Measurements", enabled=False)
    self.calculateAutomaticallyCheckbox = qt.QCheckBox("Auto Update")
    self.calculateAutomaticallyCheckbox.checked = True

    self.measurementsGroupBox.layout().addWidget(self.tableView, 0, 0, 1, 2)
    self.measurementsGroupBox.layout().addWidget(self.segmentStatisticsConfigButton, 1, 0, 1, 2)
    self.measurementsGroupBox.layout().addWidget(self.calculateMeasurementsButton, 2, 0)
    self.measurementsGroupBox.layout().addWidget(self.calculateAutomaticallyCheckbox, 2, 1)

    self.mainModuleWidgetLayout.addWidget(self.measurementsGroupBox)
예제 #2
0
  def setupMeasurementsArea(self):
    self.measurementsGroupBox = qt.QGroupBox("Measurements")
    self.measurementsGroupBox.setLayout(qt.QGridLayout())
    self.tableView = slicer.qMRMLTableView()
    self.tableView.setMinimumHeight(150)
    self.tableView.setMaximumHeight(150)
    self.tableView.setSelectionBehavior(qt.QTableView.SelectRows)

    if ModuleWidgetMixin.isQtVersionOlder():
      self.tableView.horizontalHeader().setResizeMode(qt.QHeaderView.Stretch)
    else:
      self.tableView.horizontalHeader().setSectionResizeMode(qt.QHeaderView.Stretch)

    self.fourUpTableView = None
    self.segmentStatisticsConfigButton = self.createButton("Segment Statistics Parameters")

    self.calculateMeasurementsButton = self.createButton("Calculate Measurements", enabled=False)
    self.calculateAutomaticallyCheckbox = qt.QCheckBox("Auto Update")
    self.calculateAutomaticallyCheckbox.checked = True

    self.measurementsGroupBox.layout().addWidget(self.tableView, 0, 0, 1, 2)
    self.measurementsGroupBox.layout().addWidget(self.segmentStatisticsConfigButton, 1, 0, 1, 2)
    self.measurementsGroupBox.layout().addWidget(self.calculateMeasurementsButton, 2, 0)
    self.measurementsGroupBox.layout().addWidget(self.calculateAutomaticallyCheckbox, 2, 1)

    self.mainModuleWidgetLayout.addWidget(self.measurementsGroupBox)
예제 #3
0
 def setFOV2Largest2DRegion(self, widget, largestLabel=None, factor=1.5):
   if not largestLabel:
     largestLabel = self.findLargest2DRegion(self.segmentationNode)
   slicer.mrmlScene.AddNode(largestLabel)
   sliceLogic = widget.sliceLogic()
   sliceNode = sliceLogic.GetSliceNode()
   compositeNode = widget.mrmlSliceCompositeNode()
   savedVolumeID = compositeNode.GetBackgroundVolumeID()
   savedFOV = sliceNode.GetFieldOfView()
   compositeNode.SetBackgroundVolumeID(largestLabel.GetID())
   sliceLogic.FitSliceToAll()
   compositeNode.SetBackgroundVolumeID(savedVolumeID)
   FOV = sliceNode.GetFieldOfView()
   ModuleWidgetMixin.setFOV(sliceLogic, [FOV[0] * factor, FOV[1] * factor, FOV[2]])
   slicer.mrmlScene.RemoveNode(largestLabel)
   return largestLabel
    def getData(self):
        data = ""

        prostateMap = ProstateSectorMapDialog()
        prostateMap.displayCheckboxBorder(visible=False)

        for finding in self._assessmentCategory.getFindings():
            prostateMap.resetButtons()
            prostateMap.setSelectedSectors(finding.getSectors())
            prostateMap.setButtonsVisible(checkedOnly=True)

            data += '''
        <div class="print-friendly">
          <h2>{0}</h2>
          <table border=1 width='100%' cellPadding=3 cellSpacing=0>
            {1}
          </table>
          <br>
        </div>
        '''.format(
                finding.getName(), "".join([
                    self.sectorMapScreenShot.format(
                        ModuleWidgetMixin.pixelmapAsRaw(pixmap))
                    for pixmap in prostateMap.getScreenShots()
                ]))

        return data
예제 #5
0
 def setFOV2Largest2DRegion(self, widget, largestLabel=None, factor=1.5):
   if not largestLabel:
     largestLabel = self.findLargest2DRegion(self.segmentationNode)
   slicer.mrmlScene.AddNode(largestLabel)
   sliceLogic = widget.sliceLogic()
   sliceNode = sliceLogic.GetSliceNode()
   compositeNode = widget.mrmlSliceCompositeNode()
   savedVolumeID = compositeNode.GetBackgroundVolumeID()
   savedFOV = sliceNode.GetFieldOfView()
   compositeNode.SetBackgroundVolumeID(largestLabel.GetID())
   sliceLogic.FitSliceToAll()
   compositeNode.SetBackgroundVolumeID(savedVolumeID)
   FOV = sliceNode.GetFieldOfView()
   ModuleWidgetMixin.setFOV(sliceLogic, [FOV[0] * factor, FOV[1] * factor, FOV[2]])
   slicer.mrmlScene.RemoveNode(largestLabel)
   return largestLabel
예제 #6
0
  def viewerPerVolume(cls, volumeNodes, layout, background, opacity=1.0):
    """ Load each volume in the scene into its own slice viewer and link them all together.
    If background is specified, put it in the background of all viewers and make the other volumes be the foreground.
    If label is specified, make it active as the label layer of all viewers. Return a map of slice nodes indexed by
    the view name (given or generated). Opacity applies only when background is selected.
    """

    if not volumeNodes:
      raise ValueError("VolumeNodes are supposed to be non empty")

    layoutManager = slicer.app.layoutManager()
    layoutManager.setLayout(layout)

    sliceWidgets = list(ModuleWidgetMixin.getAllVisibleWidgets())

    slicer.app.processEvents()

    for index, volume in enumerate(volumeNodes):
      sliceWidget = sliceWidgets[index]
      volumeNodeID = volume.GetID()

      compositeNode = sliceWidget.mrmlSliceCompositeNode()
      compositeNode.SetBackgroundVolumeID(background.GetID())
      compositeNode.SetForegroundVolumeID(volumeNodeID)
      compositeNode.SetForegroundOpacity(opacity)

      sliceNode = sliceWidget.mrmlSliceNode()
      orientation = cls.getOrientation(volume)
      if orientation:
        sliceNode.SetOrientation(orientation)
      sliceNode.RotateToVolumePlane(volume)
      sliceWidget.fitSliceToBackground()
예제 #7
0
 def addSideBySideSliceAnnotations(self):
   self.removeSliceAnnotations()
   kwargs = {"yPos":55 if ModuleWidgetMixin.isQtVersionOlder() else 80, "size":30}
   self.sliceAnnotations.append(SliceAnnotation(self.redWidget, constants.LEFT_VIEWER_SLICE_ANNOTATION_TEXT, **kwargs))
   self.sliceAnnotations.append(SliceAnnotation(self.yellowWidget, constants.RIGHT_VIEWER_SLICE_ANNOTATION_TEXT, **kwargs))
   self.addNewImageAnnotation(self.yellowWidget, constants.RIGHT_VIEWER_SLICE_NEEDLE_IMAGE_ANNOTATION_TEXT)
   self.addOldImageAnnotation(self.yellowWidget, constants.RIGHT_VIEWER_SLICE_TRANSFORMED_ANNOTATION_TEXT)
   self.addRegistrationResultStatusAnnotation(self.yellowWidget)
예제 #8
0
 def setTargetTableSizeConstraints(self):
   method = getattr(self.targetTable.horizontalHeader(),
                    "setResizeMode" if ModuleWidgetMixin.isQtVersionOlder() else
                    "setSectionResizeMode")
   method(qt.QHeaderView.Stretch)
   method(0, qt.QHeaderView.Stretch)
   method(1, qt.QHeaderView.ResizeToContents)
   method(2, qt.QHeaderView.ResizeToContents)
예제 #9
0
 def addFourUpSliceAnnotations(self):
   self.removeSliceAnnotations()
   if not (self.currentResult.skipped or (self.session.seriesTypeManager.isCoverProstate(self.currentResult.name) and
                                            not self.session.data.usePreopData)):
     self.sliceAnnotations.append(SliceAnnotation(self.redWidget, constants.RIGHT_VIEWER_SLICE_ANNOTATION_TEXT,
                                                  yPos=50 if ModuleWidgetMixin.isQtVersionOlder() else 75, size=20))
     self.addNewImageAnnotation(self.redWidget, constants.RIGHT_VIEWER_SLICE_NEEDLE_IMAGE_ANNOTATION_TEXT, size=15)
     self.addOldImageAnnotation(self.redWidget, constants.RIGHT_VIEWER_SLICE_TRANSFORMED_ANNOTATION_TEXT, size=15)
   self.addRegistrationResultStatusAnnotation(self.redWidget)
예제 #10
0
 def _fitIntoViewport(self, size):
     tempSize = self.textProperty.GetFontSize()
     self.textProperty.SetFontSize(size)
     self.textActor.SetTextProperty(self.textProperty)
     if self._getFontWidth() > (self.sliceView.width if ModuleWidgetMixin.isQtVersionOlder() else \
             self.sliceView.width * self.sliceView.devicePixelRatio()):
         self.textProperty.SetFontSize(tempSize)
         self.textActor.SetTextProperty(self.textProperty)
         return False
     return True
예제 #11
0
 def onInvokeRegistration(self, initial=True, retryMode=False, segmentationData=None):
   self.progress = ModuleWidgetMixin.createProgressDialog(maximum=4, value=1, windowFlags=qt.Qt.CustomizeWindowHint |
                                                                                          qt.Qt.WindowTitleHint)
   self.progress.setCancelButton(None)
   if initial:
     self.applyInitialRegistration(retryMode, segmentationData, progressCallback=self.updateProgressBar)
   else:
     self.applyRegistration(progressCallback=self.updateProgressBar)
   self.progress.close()
   self.progress = None
   logging.debug('Re-Registration is done')
    def setupViewSettingsArea(self):
        self.fourUpSliceLayoutButton = FourUpLayoutButton()
        self.fourUpSliceTableViewLayoutButton = FourUpTableViewLayoutButton()
        self.crosshairButton = CrosshairButton()
        self.crosshairButton.setSliceIntersectionEnabled(True)

        hbox = ModuleWidgetMixin.createHLayout([
            self.fourUpSliceLayoutButton,
            self.fourUpSliceTableViewLayoutButton, self.crosshairButton
        ])
        self.layout.addWidget(hbox)
예제 #13
0
 def targetList(self, targetList):
   self._targetList = targetList
   if self.currentGuidanceComputation and self.observer:
     self.self.currentGuidanceComputation.RemoveObserver(self.observer)
   self.currentGuidanceComputation = self.getOrCreateNewGuidanceComputation(targetList)
   if self.currentGuidanceComputation:
     self.observer = self.currentGuidanceComputation.addEventObserver(vtk.vtkCommand.ModifiedEvent,
                                                                      self.updateHoleAndDepth)
   if ModuleWidgetMixin.isQtVersionOlder():
     self.reset()
   else:
     self.beginResetModel()
     self.endResetModel()
예제 #14
0
 def _applyVerticalAlign(self):
     sliceViewHeight = self.sliceView.height if ModuleWidgetMixin.isQtVersionOlder() else \
       self.sliceView.height * self.sliceView.devicePixelRatio()
     centerY = int((sliceViewHeight - self._getFontHeight()) / 2)
     if self.yPos:
         yPos = self.yPos if 0 < self.yPos < centerY else centerY
     else:
         if self.verticalAlign == self.ALIGN_TOP:
             yPos = sliceViewHeight - self._getFontHeight()
         elif self.verticalAlign == self.ALIGN_CENTER:
             yPos = centerY
         elif self.verticalAlign == self.ALIGN_BOTTOM:
             yPos = 0
     return int(yPos)
예제 #15
0
 def _applyHorizontalAlign(self):
     sliceViewWidth = self.sliceView.width if ModuleWidgetMixin.isQtVersionOlder() else \
       self.sliceView.width * self.sliceView.devicePixelRatio()
     centerX = int((sliceViewWidth - self._getFontWidth()) / 2)
     if self.xPos:
         xPos = self.xPos if 0 < self.xPos < centerX else centerX
     else:
         if self.horizontalAlign == self.ALIGN_LEFT:
             xPos = 0
         elif self.horizontalAlign == self.ALIGN_CENTER:
             xPos = centerX
         elif self.horizontalAlign == self.ALIGN_RIGHT:
             xPos = sliceViewWidth - self._getFontWidth()
     return int(xPos)
예제 #16
0
 def _onAnnotationButtonClicked(self, button, checked):
     currentItem = self._annotationListWidget.currentItem()
     if not currentItem:
         return
     itemWidget = self._annotationListWidget.itemWidget(currentItem)
     seriesType = itemWidget.getSeriesType()
     if checked:
         for b in self._annotationButtonGroup.buttons():
             if b.checked and b is not button:
                 b.checked = False
         for w in ModuleWidgetMixin.getAllVisibleWidgets():
             enabled = w.mrmlSliceCompositeNode().GetForegroundVolumeID() is not None and seriesType.getVolume() is \
                       slicer.mrmlScene.GetNodeByID(w.mrmlSliceCompositeNode().GetForegroundVolumeID())
             w.enabled = enabled
             w.setStyleSheet("#frame{{border: 5px ridge {};}}".format(
                 "green" if enabled else "black"))
         self._onAnnotationToolSelected(seriesType,
                                        button.property("MRML_NODE_CLASS"))
     else:
         for w in ModuleWidgetMixin.getAllVisibleWidgets():
             w.enabled = True
             w.setStyleSheet("")
         self._onAnnotationToolDeselected(
             seriesType, button.property("MRML_NODE_CLASS"))
예제 #17
0
  def _onLoadButtonClicked(self):
    self._dataSelectionDialog = DataSelectionDialog()
    self._loadedVolumeNodes = OrderedDict()

    nodeAddedObserver = slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, self._onVolumeNodeAdded)
    nodeRemovedObserver = slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeRemovedEvent, self._onVolumeNodeRemoved)
    try:
      if self._dataSelectionDialog.exec_():
        self._hangingProtocol = HangingProtocolFactory.getHangingProtocol(self.loadedVolumeNodes.values())
        if not self._hangingProtocol:
          raise RuntimeError("No eligible hanging protocol found.")
        background = list(self._loadedVolumeNodes.values())[0]
        self.logic.viewerPerVolume(volumeNodes=self._loadedVolumeNodes.values(), layout=self._hangingProtocol.LAYOUT,
                                   background=background)
        ModuleWidgetMixin.linkAllSliceWidgets(1)
        for sliceWidget in ModuleWidgetMixin.getAllVisibleWidgets():
          sliceWidget.mrmlSliceNode().RotateToVolumePlane(background)
        self._checkForMultiVolumes()
    except Exception as exc:
      logging.error(exc)
    finally:
      slicer.mrmlScene.RemoveObserver(nodeAddedObserver)
      slicer.mrmlScene.RemoveObserver(nodeRemovedObserver)
      self.updateGUIFromData()
예제 #18
0
 def addNewImageAnnotation(self, widget, text, size=20):
   self.newImageAnnotation = SliceAnnotation(widget, text, yPos=35 if ModuleWidgetMixin.isQtVersionOlder() else 45,
                                             opacity=0.0, color=(0, 0.5, 0), size=size)
   self.sliceAnnotations.append(self.newImageAnnotation)
예제 #19
0
 def updateProgressBar(self, **kwargs):
     ModuleWidgetMixin.updateProgressBar(self,
                                         progress=self.progress,
                                         **kwargs)
예제 #20
0
class SliceTrackerConstants(object):

  MODULE_NAME = "SliceTracker"

  PREOP_SAMPLE_DATA_URL = 'https://github.com/SlicerProstate/SliceTracker/releases/download/test-data/Preop-deid.zip'
  INTRAOP_SAMPLE_DATA_URL = 'https://github.com/SlicerProstate/SliceTracker/releases/download/test-data/Intraop-deid.zip'

  JSON_FILENAME = "results.json"

  MISSING_PREOP_ANNOTATION_TEXT = "No preop data available"
  LEFT_VIEWER_SLICE_ANNOTATION_TEXT = 'BIOPSY PLAN'
  RIGHT_VIEWER_SLICE_ANNOTATION_TEXT = 'TRACKED TARGETS'
  RIGHT_VIEWER_SLICE_TRANSFORMED_ANNOTATION_TEXT = 'OLD'
  RIGHT_VIEWER_SLICE_NEEDLE_IMAGE_ANNOTATION_TEXT = 'NEW'
  APPROVED_RESULT_TEXT_ANNOTATION = "approved"
  REJECTED_RESULT_TEXT_ANNOTATION = "rejected"
  SKIPPED_RESULT_TEXT_ANNOTATION = "skipped"

  LAYOUT_RED_SLICE_ONLY = slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView
  LAYOUT_FOUR_UP = slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView
  LAYOUT_FOUR_UP_QUANTITATIVE = slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpPlotView
  LAYOUT_SIDE_BY_SIDE = slicer.vtkMRMLLayoutNode.SlicerLayoutSideBySideView
  ALLOWED_LAYOUTS = [LAYOUT_SIDE_BY_SIDE, LAYOUT_FOUR_UP, LAYOUT_RED_SLICE_ONLY, LAYOUT_FOUR_UP_QUANTITATIVE]

  PLANNING_IMAGE = "PLANNING IMAGE"
  COVER_PROSTATE = "COVER PROSTATE"
  COVER_TEMPLATE = "COVER TEMPLATE"
  GUIDANCE_IMAGE = "GUIDANCE"
  VIBE_IMAGE = "VIBE"
  OTHER_IMAGE = "OTHER"

  TRACKABLE_IMAGE_TYPES = [COVER_PROSTATE, COVER_TEMPLATE, GUIDANCE_IMAGE]

  ZFrame_INSTRUCTION_STEPS = {1: "Scroll and click into ZFrame center to set ROI center",
                              2: "Click outside of upper right ZFrame corner to set ROI border"}

  IntraopSeriesSelectorToolTip = """
  <html>
    <head>
      <style type="text/css"> </style>
    </head>
    <body style="font-family:'Lucida Grande',sans-serif; font-size: 12pt; font-weight: 400; font-style: normal;border: 1px solid black;margin-top:0px;">
      <table cellspacing=5>
        <tbody>
          <tr>
            <td>
              <img src="%s">
            </td>
            <td style="vertical-align: middle">
              <strong>tracked</strong>(registration result available)
            </td>
          </tr>
          <tr>
            <td>
              <img src="%s">
            </td>
            <td style="vertical-align: middle">
              <strong>untracked</strong>(no registration result available)
            </td>
          </tr>
          <tr>
            <td>
              <img src="%s">
            </td>
            <td style="vertical-align: middle">
              <strong>skipped</strong>(no registration result available)
            </td>
          </tr>
          <tr>
            <td style="vertical-align: middle">
              <img src="%s">
            </td>
            <td>
              <strong>rejected</strong>(non satisfactory/approved registration result available)
            </td>
          </tr>
        </tbody>
      </table>
    </body>
  </html>
  """ % (helper.createAndGetRawColoredPixelMap("green"), helper.createAndGetRawColoredPixelMap("yellow"),
         helper.createAndGetRawColoredPixelMap("red"), helper.createAndGetRawColoredPixelMap("grey"))
예제 #21
0
 def setupPreopLoadedTargets(self):
     targets = self.data.initialTargets
     ModuleWidgetMixin.setFiducialNodeVisibility(targets, show=True)
     self.applyDefaultTargetDisplayNode(targets)
     self.markupsLogic.JumpSlicesToNthPointInMarkup(targets.GetID(), 0)
예제 #22
0
 def addOldImageAnnotation(self, widget, text, size=20):
   self.oldImageAnnotation = SliceAnnotation(widget, text, yPos=35 if ModuleWidgetMixin.isQtVersionOlder() else 45,
                                             size=size)
   self.sliceAnnotations.append(self.oldImageAnnotation)
 def updateProgressBar(self, **kwargs):
   ModuleWidgetMixin.updateProgressBar(self, progress=self.progress, **kwargs)