예제 #1
0
class QwtColorBar(QwtPlot):
    menu_table = {
        'unzoom intensity range': 200,
        'lock colorbar scale': 201,
        'unlock colorbar scale': 202,
    }

    set_image_range = pyqtSignal(int, int, int, int)

    def __init__(self, colorbar_number=0, parent=None):
        QwtPlot.__init__(self, parent)
        self._mainwin = parent and parent.topLevelWidget()
        self.colorbar_number = colorbar_number
        # create copy of standard application font..
        font = QFont()
        fi = QFontInfo(font)
        # and scale it down to 70%
        font.setPointSize(fi.pointSize() * 0.7)
        # apply font to QwtPlot
        #       self.setTitleFont(font);
        for axis in range(0, 4):
            self.setAxisFont(axis, font)
#         self.setAxisTitleFont(axis,font);

# make a QwtPlot widget
        self.plotLayout().setCanvasMargin(0)
        self.plotLayout().setAlignCanvasToScales(1)
        # set axis parameters
        self.enableAxis(QwtPlot.yLeft)
        self.enableAxis(QwtPlot.xBottom, False)
        self.setAxisLabelRotation(QwtPlot.yLeft, 270)
        self.setAxisLabelAlignment(QwtPlot.yLeft, Qt.AlignTop)
        # default color bar
        self.plotImage = QwtPlotImage(self)
        self.plotImage.attach(self)
        self.updateDisplay()
        self.min = 0.0
        self.max = 256.0
        self.is_active = False
        self.log_scale = False
        self.ampl_phase = False
        self.bar_array = numpy.reshape(numpy.arange(self.max), (1, 256))
        self.y_scale = (self.min, self.max)
        self.plotImage.setData(self.bar_array, None, self.y_scale)

        # Over-ride default QWT Plot size policy of MinimumExpanding
        # Otherwise minimum size of plots is too large when embedded in a
        # QGridlayout
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # width limits - the following seem reasonable
        # we don't want the bar to resize itself freely - it becomes too big!
        #       self.setMaximumWidth(self.sizeHint().width() * 2.5)
        self.setMaximumWidth(self.sizeHint().width() * 1.5)

        self.spy = Spy(self.canvas())
        self.spy.MouseMove.connect(self.MouseMoveEvent)
        self.spy.MousePress.connect(self.MousePressEvent)
        self.spy.MouseRelease.connect(self.MouseReleaseEvent)

        self.zoomStack = []
        self.xzoom_loc = None
        self.yzoom_loc = None
        self.prev_xpos = None
        self.prev_ypos = None
        self.raw_image_min = None
        self.raw_image_max = None
        # create zoom curve
        self.zoom_outline = QwtPlotCurve()

        self.setMouseTracking(True)
        self.installEventFilter(self)

        # add intructions on how to use
        self.setWhatsThis(colorbar_instructions)

        # create pull_down menu and add menu components
        if self._mainwin:
            self._menu = QMenu(self._mainwin)
        else:
            self._menu = QMenu(None)

        self._unzoom_action = QAction('unzoom intensity range', self)
        self._menu.addAction(self._unzoom_action)
        self._unzoom_action.setVisible(False)
        self._unzoom_action.triggered.connect(self.unzoom)

        self._lock_colorbar = QAction('lock colorbar scale', self)
        self._menu.addAction(self._lock_colorbar)
        self._lock_colorbar.triggered.connect(self.lock_colorbar)

        self._unlock_colorbar = QAction('unlock colorbar scale', self)
        self._menu.addAction(self._unlock_colorbar)
        self._unlock_colorbar.setVisible(False)
        self._unlock_colorbar.triggered.connect(self.unlock_colorbar)
        self._lock_bar = False

        # for drag & drop stuff ...
        self.setAcceptDrops(True)
        self.yhb = 0
        self.ylb = 0
        self.xhb = 0
        self.xlb = 0

    # __init__()

    def lock_colorbar(self):
        self._lock_colorbar.setVisible(False)
        self._unlock_colorbar.setVisible(True)
        if len(self.zoomStack):
            self._unzoom_action.setVisible(False)
        self._lock_bar = True
        self.emit_range()

    def unlock_colorbar(self):
        self._lock_colorbar.setVisible(True)
        self._unlock_colorbar.setVisible(False)
        if len(self.zoomStack):
            self._unzoom_action.setVisible(True)
        self._lock_bar = False
        self.emit_range()

    def get_data_range(self):
        """ returns range of this widget when called by 'foreign'
          widget on which we have done a drop event
      """
        rng = (self.min, self.max, self.colorbar_number, self.ampl_phase)
        return rng

    def dragEnterEvent(self, event):
        """ drag & drop event callback entered when we move out of or
          in to a widget 
      """
        try:
            if event.mimeData().hasText():
                event.acceptProposedAction()
        except:
            pass

    def dropEvent(self, event):
        """ callback that handles a drop event from drag & drop """
        if event.source() == self:
            return
        if event.mimeData().hasText():
            command_str = str(event.mimeData().text())
            if command_str.find('copyColorRange') > -1:
                components = event.source().get_data_range()
                min = components[0]
                max = components[1]
                colorbar = components[2]
                amp_phas = components[3]
                if self.colorbar_number == colorbar and not self._lock_bar:
                    self.zoomStack == []
                    try:
                        self.zoomState = (
                            self.axisScaleDiv(QwtPlot.yLeft).lBound(),
                            self.axisScaleDiv(QwtPlot.yLeft).hBound(),
                        )
                    except:
                        self.zoomState = (
                            self.axisScaleDiv(QwtPlot.yLeft).lowerBound(),
                            self.axisScaleDiv(QwtPlot.yLeft).upperBound(),
                        )
                    self.zoomStack.append(self.zoomState)
                    self._unzoom_action.setVisible(True)
                    self.setRange(min, max, colorbar, amp_phas)
        else:
            message = 'QwtColorBar dropEvent decode failure'
            mb_reporter = QMessageBox.information(self, "QwtColorBar", message)
        event.acceptProposedAction()

    def startDrag(self, event):
        """ operations done when we start a drag event """
        drag = Qt.QDrag(self)
        mimedata = Qt.QMimeData()
        passed_string = 'copyColorRange'
        mimedata.setText(passed_string)
        drag.setMimeData(mimedata)
        drag.exec_()
        event.accept()

    def setRange(self, min, max, colorbar_number=0, ampl_phase=False):
        """ sets display range for this colorbar and emits signal
          to associated display to set corresponding range 
      """
        if ampl_phase != self.ampl_phase:
            return

        if colorbar_number == self.colorbar_number:
            if min > max:
                temp = max
                max = min
                min = temp
            if abs(max - min) < 2.0e-8:
                if max == 0.0 or min == 0.0:
                    min = -0.1
                    max = 0.1
                else:
                    min = 0.9 * min
                    max = 1.1 * max
            self.min = min * 1.0
            self.max = max * 1.0

            # send event to display_image.py that range has changed
            self.emit_range()

            if self.log_scale:
                max = log(self.max)
                min = log(self.min)
                delta = (max - min) / 255.0
                for i in range(256):
                    self.bar_array[0, i] = exp(min + i * delta)
            else:
                delta = (self.max - self.min) / 255.0
                for i in range(256):
                    self.bar_array[0, i] = self.min + i * delta
            self.y_scale = (self.min, self.max)
            self.plotImage.setData(self.bar_array, None, self.y_scale)
            self.show()
            self.replot()

    # set Range()

    def getTransformOffset(self):
        """ get the offset value for a plot with a log scale """
        return self.plotImage.getTransformOffset()

    def setScales(self):
        self.plotImage.setLogScale(self.log_scale)
        self.plotImage.setLogYScale(self.log_scale)
        self.setAxisAutoScale(QwtPlot.yLeft)
        if self.log_scale:
            self.setAxisScaleEngine(QwtPlot.yLeft, QwtLogScaleEngine())
        else:
            self.setAxisScaleEngine(QwtPlot.yLeft, QwtLinearScaleEngine())

    def handleRangeParms(self, limits, colorbar_number, log_scale, ampl_phase):
        if ampl_phase is None:
            ampl_phase = False
        self.setMaxRange(limits, colorbar_number, log_scale, ampl_phase)

    def setMaxRange(self,
                    limits,
                    colorbar_number=0,
                    log_scale=False,
                    ampl_phase=False):
        """ sets maximum range parameters for this colorbar """
        #     print('in colorbar setMaxRange : colorbar numbers ',colorbar_number,self.colorbar_number)
        if colorbar_number == self.colorbar_number:
            self.ampl_phase = ampl_phase

            if self.ampl_phase is None:
                self.ampl_phase = False
            self.log_scale = log_scale
            self.setScales()
            min = limits[0]
            max = limits[1]
            try:
                self.raw_image_min = limits[2]
                self.raw_image_max = limits[3]
            except:
                pass
            if min > max:
                temp = max
                max = min
                min = temp
#       if abs(max - min) < 0.00005:
            if abs(max - min) < 2.0e-8:
                if max == 0.0 or min == 0.0:
                    min = -0.1
                    max = 0.1
                else:
                    min = 0.9 * min
                    max = 1.1 * max
            if not self._lock_bar:
                self.image_min = min * 1.0
                self.image_max = max * 1.0
                self.min = self.image_min
                self.max = self.image_max
            if self.log_scale:
                if self.min <= 0.0:
                    offset = -1.0 * self.min + 0.001
                    self.min = self.min + offset
                    self.max = self.max + offset
                    self.image_min = self.min
                    self.image_max = self.max
                max = log(self.max)
                min = log(self.min)
                delta = (max - min) / 255.0
                for i in range(256):
                    self.bar_array[0, i] = exp(min + i * delta)
                if HAS_TIMBA: _dprint(3, 'log bar array is ', self.bar_array)
            else:
                delta = (self.max - self.min) / 255.0
                for i in range(256):
                    self.bar_array[0, i] = self.min + i * delta
            if not self._lock_bar:
                self.y_scale = (self.min, self.max)
                self.plotImage.setData(self.bar_array, None, self.y_scale)
                self.show()
                self.replot()

    # setMaxRange()

    def showDisplay(self, show_self, colorbar_number=0):
        """ callback to show or hide this colorbar """
        #     print('in colorbar show display with self.colorbar_number', self.colorbar_number)
        if colorbar_number == self.colorbar_number:
            self.is_active = True
            if show_self > 0:
                self.show()
#         print('should show')
            else:
                self.hide()
#         print('should hide')
            self.replot()

    # showDisplay

    def unHide(self):
        """ callback to show this colorbar """
        if self.is_active:
            self.show()

    def emit_range(self):
        #     print('emitting range')
        self.set_image_range.emit(self.min, self.max, self.colorbar_number,
                                  self._lock_bar)

    def setBarLock(self, set_lock=False):
        self._lock_bar = set_lock
        if self._lock_bar:
            toggle_id = self.menu_table['lock colorbar scale']
            self._menu.setItemVisible(toggle_id, False)
            toggle_id = self.menu_table['unlock colorbar scale']
            self._menu.setItemVisible(toggle_id, True)
        else:
            toggle_id == self.menu_table['unlock colorbar scale']
            self._menu.setItemVisible(toggle_id, False)
            toggle_id = self.menu_table['lock colorbar scale']
            self._menu.setItemVisible(toggle_id, True)
        self.emit_range()

    def unzoom(self):
        """ callback to set range of this colorbar back to default """
        if len(self.zoomStack):
            while len(self.zoomStack):
                ymin, ymax = self.zoomStack.pop()

            self._unzoom_action.setVisible(False)

        if not self.raw_image_min is None:
            self.image_min = self.raw_image_min
            self.image_max = self.raw_image_max
        self.setAxisScale(QwtPlot.yLeft, self.image_min, self.image_max)
        if self.image_min > self.image_max:
            temp = self.image_max
            self.image_max = self.image_min
            self.image_min = temp
        self.setRange(self.image_min, self.image_max, self.colorbar_number,
                      self.ampl_phase)

    # set the type of colorbar display, can be one of "hippo", "grayscale"
    # or "brentjens"
    def setDisplayType(self, display_type):
        self.plotImage.setDisplayType(display_type)
        self.plotImage.setData(self.bar_array, None, self.y_scale)
        self.replot()

    # setDisplayType()

    def drawCanvasItems(self, painter, rectangle, maps, filter):
        self.plotImage.drawImage(painter, maps[QwtPlot.xBottom],
                                 maps[QwtPlot.yLeft])
        QwtPlot.drawCanvasItems(self, painter, rectangle, maps, filter)

    # drawCanvasItems()

    def MouseMoveEvent(self, e):
        """ callback to handle mouse moved event """
        #     print('in mouse move event')
        position = e.pos()
        xPos = position.x()
        yPos = position.y()
        self.xpos = self.invTransform(QwtPlot.xBottom, xPos)
        self.ypos = self.invTransform(QwtPlot.yLeft, yPos)
        if not self.xzoom_loc is None:
            self.xzoom_loc = [
                self.press_xpos, self.press_xpos, self.xpos, self.xpos,
                self.press_xpos
            ]
            self.yzoom_loc = [
                self.press_ypos, self.ypos, self.ypos, self.press_ypos,
                self.press_ypos
            ]
            if self.zoom_outline is None:
                self.zoom_outline = QwtPlotCurve()
            self.zoom_outline.setSamples(self.xzoom_loc, self.yzoom_loc)
            self.replot()

            # Test if mouse has moved outside the plot. If yes, we're
            # starting a drag.
            if xPos < self.xlb - 10 or xPos > self.xhb + 10 or yPos > self.ylb + 10 or yPos < self.yhb - 10:
                if not self.xzoom_loc is None:
                    self.zoom_outline.detach()
                    self.xzoom_loc = None
                    self.yzoom_loc = None
                    self.replot()
                self.startDrag(e)

    # onMouseMoved()

    def MousePressEvent(self, e):
        """ callback to handle mouse pressed event """
        if Qt.LeftButton == e.button():
            # get bounds of plot. Keep them around for later test if
            # we're initiating a drag operation
            try:
                self.yhb = self.transform(
                    QwtPlot.yLeft,
                    self.axisScaleDiv(QwtPlot.yLeft).hBound())
                self.ylb = self.transform(
                    QwtPlot.yLeft,
                    self.axisScaleDiv(QwtPlot.yLeft).lBound())
                self.xhb = self.transform(
                    QwtPlot.xBottom,
                    self.axisScaleDiv(QwtPlot.xBottom).hBound())
                self.xlb = self.transform(
                    QwtPlot.xBottom,
                    self.axisScaleDiv(QwtPlot.xBottom).lBound())
            except:
                self.yhb = self.transform(
                    QwtPlot.yLeft,
                    self.axisScaleDiv(QwtPlot.yLeft).upperBound())
                self.ylb = self.transform(
                    QwtPlot.yLeft,
                    self.axisScaleDiv(QwtPlot.yLeft).lowerBound())
                self.xhb = self.transform(
                    QwtPlot.xBottom,
                    self.axisScaleDiv(QwtPlot.xBottom).upperBound())
                self.xlb = self.transform(
                    QwtPlot.xBottom,
                    self.axisScaleDiv(QwtPlot.xBottom).lowerBound())
            # Python semantics: self.pos = e.pos() does not work; force a copy
            if HAS_TIMBA: _dprint(3, 'e.pos() ', e.pos())
            self.press_xpos = self.xpos
            self.press_ypos = self.ypos
            if HAS_TIMBA:
                _dprint(3, 'self.xpos self.ypos ', self.xpos, ' ', self.ypos)
            if not self._lock_bar:
                self.xzoom_loc = [self.press_xpos]
                self.yzoom_loc = [self.press_ypos]
                self.zoom_outline.attach(self)
                if self.zoomStack == []:
                    try:
                        self.zoomState = (
                            self.axisScaleDiv(QwtPlot.yLeft).lBound(),
                            self.axisScaleDiv(QwtPlot.yLeft).hBound(),
                        )
                    except:
                        self.zoomState = (
                            self.axisScaleDiv(QwtPlot.yLeft).lowerBound(),
                            self.axisScaleDiv(QwtPlot.yLeft).upperBound(),
                        )
                # fake a mouse move to show the cursor position
#         self.onMouseMoved(e)
        elif Qt.RightButton == e.button():
            e.accept()
            self._menu.popup(e.globalPos())

    # onMousePressed()

    def MouseReleaseEvent(self, e):
        """ handles mouse release event if we're not doing a drop """

        # if color bar is locked, do nothing
        if self._lock_bar:
            return

        if Qt.LeftButton == e.button():
            xmin = min(self.xpos, self.press_xpos)
            xmax = max(self.xpos, self.press_xpos)
            ymin = min(self.ypos, self.press_ypos)
            ymax = max(self.ypos, self.press_ypos)
            if not self.xzoom_loc is None:
                self.zoom_outline.detach()
                self.xzoom_loc = None
                self.yzoom_loc = None
            if xmin == xmax or ymin == ymax:
                return
            self.zoomStack.append(self.zoomState)
            #       print('self.zoomsSack', self.zoomStack)
            self.zoomState = (ymin, ymax)
            if len(self.zoomStack):
                self._unzoom_action.setVisible(True)
        elif Qt.RightButton == e.button():
            if len(self.zoomStack):
                ymin, ymax = self.zoomStack.pop()
            else:
                return

        self.setAxisScale(QwtPlot.yLeft, ymin, ymax)
        if ymin > ymax:
            temp = ymax
            ymax = ymin
            ymin = temp
        self.setRange(ymin, ymax, self.colorbar_number, self.ampl_phase)

        self.replot()

    # onMouseReleased()

    def updateDisplay(self):
        # calculate 3 NumPy arrays
        self.gain = 1.0
        # image
        self.plotImage.setData(
            square(512, -1.0 * self.gain * pi,
                   self.gain * pi), (-1.0 * self.gain * pi, self.gain * pi),
            (-1.0 * self.gain * pi, self.gain * pi))
예제 #2
0
class QwtImagePlot(QwtPlot):
    def __init__(self, *args):
        QwtPlot.__init__(self, *args)
	# make a QwtPlot widget
        self.plotLayout().setCanvasMargin(0)
        self.plotLayout().setAlignCanvasToScales(1)
        self.setTitle('QwtImagePlot: (un)zoom & (un)hide')
	# set axis titles
        self.setAxisTitle(QwtPlot.xBottom, 'time (s)')
        self.setAxisTitle(QwtPlot.yLeft, 'frequency (Hz)')
	# insert a few curves
        self.cSin = QwtPlotCurve('y = pi*sin(x)')
        self.cCos = QwtPlotCurve('y = 4*pi*sin(x)*cos(x)**2')
        self.cSin.attach(self)
        self.cCos.attach(self)
	# set curve styles
        self.cSin.setPen(QPen(Qt.green, 2))
        self.cCos.setPen(QPen(Qt.black, 2))
        self.xzoom_loc = None
        self.yzoom_loc = None
        self.xpos = None
        self.ypos = None

	# attach a grid
        grid = QwtPlotGrid()
        grid.attach(self)
        grid.setPen(Qt.black, 0, Qt.DotLine)

        # create zoom curve
        self.zoom_outline = QwtPlotCurve()
        self.zoom_outline.setStyle(QwtPlotCurve.Lines) 

        # create and initialize an image display
        self.plotImage = QwtPlotImage(self)
        self.plotImage.attach(self)
        self.gain = 2.0
        self.updateDisplay()

        self.zoomStack = []

        self.spy = Spy(self.canvas())
        self.prev_xpos = None
        self.prev_ypos = None

#       self.connect(self, Qt.SIGNAL("legendClicked(QwtPlotItem*)"),
#                    self.toggleVisibility)

        self.spy.MouseMove.connect(self.onmouseMoveEvent)
        self.spy.MousePress.connect(self.onmousePressEvent)
        self.spy.MouseRelease.connect(self.onmouseReleaseEvent)


    # __init__()

    def toggleVisibility(self, plotItem):
        """Toggle the visibility of a plot item
        """
        plotItem.setVisible(not plotItem.isVisible())
        self.replot()



    # showCoordinates()


    def updateDisplay(self):
      offset = 3
      # calculate 3 NumPy arrays
      x = numpy.arange(-1.0 * self.gain*math.pi, self.gain*math.pi, 0.01)
      y = math.pi*numpy.sin(x) + offset
      z = self.gain * self.gain*math.pi*numpy.cos(x)*numpy.cos(x)*numpy.sin(x) + offset
      # copy the data
      self.cSin.setSamples(x, y)
      self.cCos.setSamples(x, z)
      # image
      test_image = sinx_image(8,16,offset)
      self.plotImage.setData(test_image)

#     self.plotImage.setData(
#           square(512,-1.0 * self.gain*math.pi, self.gain*math.pi), (-1.0*self.gain*math.pi, self.gain*math.pi), (-1.0*self.gain*math.pi, self.gain*math.pi))

    def updateBarDisplay(self):
      self.min = 0.0
      self.max = 256.0
      self.bar_array = numpy.reshape(numpy.arange(self.max), (1,256))
      self.y_scale = (self.min, self.max)
      self.plotImage.setData(self.bar_array, None, self.y_scale)

    def start_timer(self, time):
      """ start a timer going to update the image every 1/10 sec """
      self.timer = QTimer(self)
      self.timer.timeout.connect(self.testEvent)
      self.timer.start(time)

    def testEvent(self):
      """ change the gain factor and recalculate the image """
      self.gain = self.gain + 1.0
      self.updateDisplay()
      self.updateBarDisplay()
      self.replot()


    def mouseCatch(self,x,y,z):
      print('in mouseCatch')
      print('caught', x,y, z)

    def onmouseMoveEvent(self,event):
      position = event.pos()
      x = position.x()
      y = position.y()
      button = event.button()
      if not self.xpos is None:
        self.xpos = self.invTransform(QwtPlot.xBottom, x)
        self.ypos = self.invTransform(QwtPlot.yLeft, y)
        if not self.xzoom_loc is None:
          self.xzoom_loc = [self.press_xpos, self.press_xpos,  self.xpos, self.xpos,self.press_xpos]
          self.yzoom_loc = [self.press_ypos, self.ypos,  self.ypos, self.press_ypos,self.press_ypos]
          self.zoom_outline.setSamples(self.xzoom_loc,self.yzoom_loc)
          self.replot()

    def onmousePressEvent(self,event):
        position = event.pos()
        x = position.x()
        y = position.y()
        button = event.button()
        if Qt.LeftButton == button:
            if self.xpos is None:
              self.xpos = self.invTransform(QwtPlot.xBottom, x)
              self.ypos = self.invTransform(QwtPlot.yLeft, y)
            # Python semantics: self.pos = e.pos() does not work; force a copy
            self.press_xpos = self.xpos
            self.press_ypos = self.ypos
            self.xzoom_loc = [self.press_xpos]
            self.yzoom_loc = [self.press_ypos]
            self.zoom_outline.attach(self)
            self.zooming = 1
            if self.zoomStack == []:
                try:
                  self.zoomState = (
                    self.axisScaleDiv(QwtPlot.xBottom).lBound(),
                    self.axisScaleDiv(QwtPlot.xBottom).hBound(),
                    self.axisScaleDiv(QwtPlot.yLeft).lBound(),
                    self.axisScaleDiv(QwtPlot.yLeft).hBound(),
                    )
                except:
                  self.zoomState = (
                    self.axisScaleDiv(QwtPlot.xBottom).lowerBound(),
                    self.axisScaleDiv(QwtPlot.xBottom).upperBound(),
                    self.axisScaleDiv(QwtPlot.yLeft).lowerBound(),
                    self.axisScaleDiv(QwtPlot.yLeft).upperBound(),
                    )
        elif Qt.RightButton == button:
            self.zooming = 0
    # mousePressEvent()

    def onmouseReleaseEvent(self,event):
        position = event.pos()
        x = position.x()
        y = position.y()
        button = event.button()
        if Qt.LeftButton == button:
            xmin = min(self.xpos, self.press_xpos)
            xmax = max(self.xpos, self.press_xpos)
            ymin = min(self.ypos, self.press_ypos)
            ymax = max(self.ypos, self.press_ypos)
            if not self.xzoom_loc is None:
              self.zoom_outline.detach()
              self.xzoom_loc = None
              self.yzoom_loc = None
            if xmin == xmax or ymin == ymax:
                return
            self.zoomStack.append(self.zoomState)
            self.zoomState = (xmin, xmax, ymin, ymax)
        elif Qt.RightButton == button:
            # we back up the zoom stack
            if len(self.zoomStack):
                xmin, xmax, ymin, ymax = self.zoomStack.pop()
            else:
                return

        if button != Qt.MidButton:
          self.setAxisScale(QwtPlot.xBottom, xmin, xmax)
          self.setAxisScale(QwtPlot.yLeft, ymin, ymax)
          self.plotImage.update_xMap_draw(xmin,xmax)
          self.plotImage.update_yMap_draw(ymin,ymax)
          self.replot()

    # mouseReleaseEvent()


    def toggleCurve(self, key):
        curve = self.curve(key)
        if curve:
            curve.setEnabled(not curve.enabled())
            self.replot()
예제 #3
0
class ZoomPopup(QWidget):

    winclosed = pyqtSignal(int)
    winpaused = pyqtSignal(int)
    save_zoom_display = pyqtSignal(str, int)
    image_auto_scale = pyqtSignal(int)
    image_scale_values = pyqtSignal(float, float)

    def __init__(self,
                 CurveNumber,
                 x_values,
                 y_values,
                 flags,
                 pen,
                 parent=None,
                 name=None):
        """ Initialises all the variables.  
        creates the main zoom plot
        connects the qt signals
    """

        QWidget.__init__(self, parent)
        self.setWindowTitle('Channel ' + str(CurveNumber))
        self._parent = parent
        self._d_zoomActive = self._d_zoom = False
        self._curve_number = CurveNumber
        self.curves = {}

        self._do_close = True  # enable closing by window manager
        self._do_pause = False  # pause mode is False at startup
        self._compare_max = False
        self._do_linear_scale = True  # linear Y axis scale by default
        self._do_fixed_scale = False  # auto scaling by default
        self._array_label = "Channel "

        #Create the plot for selected curve to zoom
        self._plotter = QwtImageDisplay(self)
        self._plotter.setZoomDisplay()

        self._zoom_plot_label = self._array_label + str(
            self._curve_number) + " Sequence (oldest to most recent)"

        self._max_crv = -1  # negative value used to indicate that this display
        self._min_crv = -1  # is not being used

        #####end of parameters set for the plot#######/

        # we seem to need a layout for PyQt
        box1 = QHBoxLayout(self)
        box1.addWidget(self._plotter)
        #   self.plotPrinter = plot_printer_qt5.plot_printer(self._plotter)

        self._plotter.winpaused.connect(self.Pausing)
        self._plotter.compare.connect(self.do_compare)
        #   self._plotter.do_print.connnect(self.plotPrinter.do_print)
        self._plotter.save_display.connect(self.handle_save_display)

        # insert flags ?
        self._plotter.initVellsContextMenu()
        self.update_plot(y_values, flags)
        self.show()

    def handle_save_display(self, title):
        self.save_zoom_display.emit(self._zoom_plot_label, self._curve_number)

    def do_compare_max(self, x_values):
        ### instantiate the envelop that will show min/max deviations
        self._max_envelop = self._y_values
        self._min_envelop = self._y_values
        self._max_crv = QwtPlotCurve('Zoomed max curve')
        self._max_crv.attach(self._plotter)
        self._min_crv = QwtPlotCurve('Zoomed min curve')
        self._min_crv.attach(self._plotter)
        self._max_crv.setData(x_values, self._max_envelop)
        self._min_crv.setData(x_values, self._min_envelop)
        self._compare_max = True

    def do_compare(self):
        print('in zoomwin do_compare')
        if self._compare_max:
            self.stop_compare_max()
            self._compare_max = False
        else:
            self._max_envelop = self._y_values
            self._min_envelop = self._y_values
            self._max_crv = QwtPlotCurve('Zoomed max curve')
            self._max_crv.attach(self._plotter)
            self._min_crv = QwtPlotCurve('Zoomed min curve')
            self._min_crv.attach(self._plotter)
            self._max_crv.setData(x_values, self._max_envelop)
            self._min_crv.setData(x_values, self._min_envelop)
            self._compare_max = True
        self.reset_max()

    def stop_compare_max(self):
        if self._compare_max:
            self._max_envelop = 0.0
            self._min_envelop = 0.0
            self._max_crv.detach()
            self._min_crv.detach()
            self._compare_max = False
            self._max_crv = -1
            self._min_crv = -1

    def get_max(self):
        if self._compare_max:
            self._max_envelop = self.max(self._max_envelop, self._y_values)
            self._min_envelop = self.min(self._min_envelop, self._y_values)

    def max(self, array1, array2):
        shape = array1.shape
        max_envelop = array1
        for i in range(shape[0]):
            if array2[i] > array1[i]:
                max_envelop[i] = array2[i]
        return max_envelop

    def min(self, array1, array2):
        shape = array1.shape
        min_envelop = array1
        for i in range(shape[0]):
            if array2[i] < array1[i]:
                min_envelop[i] = array2[i]
        return min_envelop

    def reset_max(self):
        if self._compare_max:
            self._max_envelop = self._y_values
            self._min_envelop = self._y_values

    def test_max(self):
        if self._compare_max:
            return True
        else:
            return False

    def pause_mode(self):
        if self._do_pause:
            return True
        else:
            return False

    def exec_close(self):
        self.close()

    def Pausing(self):
        self.winpaused.emit(self._curve_number)

    def change_scale_type(self):
        # click means change to fixed scale
        toggle_id = self.menu_table['Fixed Scale ']
        if self._do_fixed_scale:
            self._do_fixed_scale = False
            self._menu.changeItem(toggle_id, 'Fixed Scale')
            self._plotter.setAxisAutoScale(QwtPlot.yLeft)
            self.image_auto_scale.emit(0)
        else:
            self._do_fixed_scale = True
            self._menu.changeItem(toggle_id, 'Auto Scale')
            # find current data min and max
            scale_max = self._y_values.max()
            scale_min = self._y_values.min()

    def set_scale_values(self, max_value, min_value):
        if self._do_fixed_scale:
            self.image_scale_values.emit(max_value, min_value)
            self._plotter.setAxisScale(QwtPlot.yLeft, min_value, max_value)
            self._plotter.replot()

    def cancel_scale_request(self):
        if self._do_fixed_scale:
            toggle_id = self.menu_table['Fixed Scale ']
            self._menu.changeItem(toggle_id, 'Fixed Scale')
            self._plotter.setAxisAutoScale(QwtPlot.yLeft)
            self._do_fixed_scale = False

    def update_plot(self, y_values, flags):
        if not self._do_pause:
            self._plotter.unsetFlagsData()
            self._y_values = y_values
            abs_flags = numpy.absolute(flags)
            if abs_flags.max() > 0:
                if len(flags) == len(self._y_values):
                    self._plotter.setFlagsData(flags, flip_axes=True)
                    self._plotter.set_flag_toggles_active(True, False)
            else:
                self._plotter.set_flag_toggles_active(False, False)
            self._plotter.array_plot(incoming_plot_array=self._y_values,
                                     flip_axes=True)

            #     self.get_max()
            self._plotter.replot()

    def setDataLabel(self, data_label, array_label, is_array=False):
        self._data_label = data_label
        if array_label is None:
            self._array_label = 'Ch ' + str(self._curve_number)
        else:
            self._array_label = array_label
        if is_array:
            self._zoom_plot_label = self._data_label + ": " + self._array_label
        else:
            self._zoom_plot_label = self._data_label + ": " + self._array_label + " Sequence (oldest to most recent)"
        self._plotter.setAxisTitle(QwtPlot.xBottom, self._zoom_plot_label)
        self._plotter._x_title = self._zoom_plot_label
        self.setWindowTitle(self._zoom_plot_label)

    def plotMouseMoved(self, e):
        """	Gets x and y position of the mouse on the plot according to axis' value
        set right text on the button and underneath the plot
    """
        # (I) e (QMouseEvent) Mouse event
        lbl = QString("Event=")
        lbl2 = QString("")
        lbl2.setNum(self._plotter.invTransform(QwtPlot.xBottom,
                                               e.pos().x()), 'g', 3)
        lbl += lbl2 + ",  Signal="
        lbl2.setNum(self._plotter.invTransform(QwtPlot.yLeft,
                                               e.pos().y()), 'g', 3)
        lbl += lbl2


#   self._ControlFrame._lblInfo.setText(lbl)

    def closeEvent(self, ce):
        if self._do_close:
            self.winclosed.emit(self._curve_number)
            ce.accept()
        else:
            ce.ignore()