Пример #1
0
class MapViewWidget(DynImageView):
    sigShowSpectra = Signal(int)

    def __init__(self, *args, **kwargs):
        super(MapViewWidget, self).__init__(*args, **kwargs)
        # self.scene.sigMouseMoved.connect(self.showSpectra)
        self.scene.sigMouseClicked.connect(self.showSpectra)
        self.view.invertY(True)

        # add arrow
        # self.arrow = ArrowItem(angle=60, headLen=15, tipAngle=45, baseAngle=30, brush = (200, 80, 20))
        # self.arrow.setPos(0, 0)
        self.cross = PlotDataItem([0], [0],
                                  symbolBrush=(200, 0, 0),
                                  symbolPen=(200, 0, 0),
                                  symbol='+',
                                  symbolSize=16)

        self.view.addItem(self.cross)
        self.cross.hide()
        #add txt
        self.txt = TextItem('', anchor=(0, 0))
        self.addItem(self.txt)

    def setEnergy(self, lineobject):
        E = lineobject.value()
        # map E to index
        i = val2ind(E, self.wavenumbers)
        # print('E:', E, 'wav:', self.wavenumbers[i])
        self.setCurrentIndex(i)

    def showSpectra(self, event):

        pos = event.pos()
        if self.view.sceneBoundingRect().contains(
                pos
        ):  # Note, when axes are added, you must get the view with self.view.getViewBox()
            mousePoint = self.view.mapSceneToView(pos)
            x, y = int(mousePoint.x()), int(mousePoint.y())
            y = self.row - y - 1
            try:
                ind = self.rc2ind[(y, x)]
                self.sigShowSpectra.emit(ind)
                # print(x, y, ind, x + y * self.n_col)

                #update arrow
                self.cross.setData([x + 0.5], [self.row - y - 0.5])
                self.cross.show()
                # update text
                self.txt.setHtml(
                    f'<div style="text-align: center"><span style="color: #FFF; font-size: 8pt">X: {x}</div>\
            <div style="text-align: center"><span style="color: #FFF; font-size: 8pt">Y: {y}</div>\
            <div style="text-align: center"><span style="color: #FFF; font-size: 8pt">Point: #{ind}</div>'
                )
            except Exception:
                self.cross.hide()

    def setHeader(self, header: NonDBHeader, field: str, *args, **kwargs):
        self.header = header
        self.field = field

        imageEvent = next(header.events(fields=['image']))
        self.rc2ind = imageEvent['rc_index']
        self.wavenumbers = imageEvent['wavenumbers']
        # make lazy array from document
        data = None
        try:
            data = header.meta_array(field)
            self.row = data.shape[1]
            self.col = data.shape[2]
            self.txt.setPos(self.col, 0)
        except IndexError:
            msg.logMessage(
                'Header object contained no frames with field '
                '{field}'
                '.', msg.ERROR)

        if data is not None:
            # kwargs['transform'] = QTransform(1, 0, 0, -1, 0, data.shape[-2])
            self.setImage(img=data, *args, **kwargs)
            self._data = data

    def updateImage(self, autoHistogramRange=True):
        super(MapViewWidget, self).updateImage(autoHistogramRange)
        self.ui.roiPlot.setVisible(False)

    def setImage(self, img, **kwargs):
        super(MapViewWidget, self).setImage(img, **kwargs)
        self.ui.roiPlot.setVisible(False)

    def makeMask(self, thresholds):
        peak1550 = val2ind(1550, self.wavenumbers)
        thr1550 = thresholds[0]
        mask = self._data[peak1550] > thr1550
        mask = mask.astype(np.int)
        return mask
Пример #2
0
class OrbitView(GraphicsLayoutWidget):
    def __init__(self,
                 orbit=None,
                 axis="X",
                 use_sector_ticks=True,
                 parent=None,
                 ymin=-1.0,
                 ymax=1.0,
                 name=None,
                 label=None,
                 units=None,
                 draw_timer=None,
                 magnet_list=None):
        super(OrbitView, self).__init__(parent=parent)
        axis = axis.lower()
        if axis not in ["x", "y", "tmit"]:
            raise Exception("Axis must be 'x', 'y', or 'tmit'")
        self.axis = axis
        self.use_sector_ticks = use_sector_ticks
        self.sector_ticks = [[], []]
        self.ci.layout.setSpacing(0.0)
        self.plotLabel = self.addLabel(text=name,
                                       row=0,
                                       col=0,
                                       rowspan=3,
                                       angle=-90)
        self.up_magnet_view = MagnetView(magnet_list=orbit, direction="up")
        self.up_magnet_view.hideAxis('left')
        self.up_magnet_view.hideAxis('bottom')
        self.ci.layout.setRowStretchFactor(0, 3)
        self.plotItem = self.addPlot(name=name, row=0, col=1)
        self.ci.layout.setRowStretchFactor(1, 0)
        self.down_magnet_view = MagnetView(magnet_list=orbit, direction="down")
        self.down_magnet_view.hideAxis('left')
        self.up_magnet_view.setXLink(self.plotItem)
        self.down_magnet_view.setXLink(self.plotItem)
        self.ci.layout.setRowStretchFactor(2, 0)
        self.show_magnet_buttons = False
        if axis != "tmit" and magnet_list is not None:
            self.show_magnet_views(True)
        self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate
                                   )  # Greatly improves drawing performance.
        self.plotItem.setMouseEnabled(y=False)
        #Customize the right-click menu.
        self.plotItem.setMenuEnabled(enableMenu=False, enableViewBoxMenu=None)
        reset_view_range = QAction("Reset View Range", self.plotItem.vb.menu)
        reset_view_range.triggered.connect(self.reset_range)
        self.plotItem.vb.scene().contextMenu = []
        existing_menu_actions = self.plotItem.vb.menu.actions()
        self.plotItem.vb.menu.insertAction(existing_menu_actions[0],
                                           reset_view_range)
        for action in existing_menu_actions:
            if str(action.text()) == "View All":
                self.plotItem.vb.menu.removeAction(action)
        self.plotItem.showGrid(y=True)
        #self.plotItem.getAxis('left').setStyle(tickTextWidth=60)
        #self.plotItem.getAxis('left').setStyle(autoExpandTextSpace=False)
        #if label is not None:
        #   self.plotItem.getAxis('left').enableAutoSIPrefix(enable=False)
        #   self.plotItem.getAxis('left').setLabel(text=label, units=units)
        self.bpm_brush = QBrush(QColor(0, 255, 0))
        self.energy_bpm_brush = QBrush(QColor(100, 200, 255))
        self.ymin = ymin  #Y axis goes from self.ymin to self.ymax by default.
        self.ymax = ymax
        self.yminlimit = 10.0 * ymin  #This is the limit on the Y axis range.
        self.ymaxlimit = 10.0 * ymax  #This is the upper limit on the Y axis range.
        self.plotItem.setLimits(minYRange=0.04,
                                maxYRange=abs(self.ymaxlimit - self.yminlimit))
        self.axis_pen = QPen(QBrush(QColor(255, 255, 255)), 0)
        self.axis_pen.setCapStyle(Qt.FlatCap)
        self.bpm_pen = QPen(self.bpm_brush, 2)
        self.bpm_pen.setCosmetic(True)
        self.bpm_pen.setCapStyle(Qt.FlatCap)
        self.no_beam_brush = QBrush(QColor(0, 255, 0, 45))
        self.no_beam_pen = QPen(self.no_beam_brush, 2)
        self.no_beam_pen.setCosmetic(True)
        self.no_beam_pen.setCapStyle(Qt.FlatCap)
        self.energy_bpm_pen = QPen(self.energy_bpm_brush, 2)
        self.energy_bpm_pen.setCosmetic(True)
        self.energy_bpm_pen.setCapStyle(Qt.FlatCap)
        self.fit_brush = QBrush(QColor(255, 255, 255, 255))
        self.fit_pen = QPen(self.fit_brush, 0)
        self.fit_pen.setCosmetic(True)
        self.fit_pen.setCapStyle(Qt.FlatCap)
        self.axis_line = QGraphicsLineItem(0.0, 0.0, 1.0, 0.0)
        self.axis_line.setPen(self.axis_pen)
        self.plotItem.addItem(self.axis_line, ignoreBounds=True)
        self.lines = {}
        self.orbit = None
        self.needs_initial_range = True
        self.set_draw_timer(draw_timer)
        self._display_fit = False
        self.fit_data_item = None
        self.fit_options = {}
        if orbit is not None:
            self.set_orbit(orbit)

    def make_right_click_menu(self):
        menu = QMenu(self)
        return menu

    def display_fit(self, enabled=True):
        if enabled and self.fit_data_item is None:
            self.fit_data_item = PlotDataItem(pen=self.fit_pen)
            self.plotItem.addItem(self.fit_data_item)
        elif not enabled:
            self.plotItem.removeItem(self.fit_data_item)
            self.fit_data_item = None
        self._display_fit = enabled

    def set_draw_timer(self, new_timer, start=False):
        try:
            self.draw_timer.timeout.disconnect(self.redraw_bpms)
        except:
            pass
        if new_timer is None:
            new_timer = QTimer(self)
            new_timer.setInterval(int(1000 / 60))
        self.draw_timer = new_timer
        self.draw_timer.timeout.connect(self.redraw_bpms)
        if start:
            self.draw_timer.start()

    def set_orbit(self, orbit, reset_range=True):
        if self.orbit == orbit:
            return
        old_range = None
        old_zmax = None
        old_zmin = None
        if self.orbit is not None:
            old_range = self.plotItem.viewRect()
            old_zmax = self.orbit.zmax()
            old_zmin = self.orbit.zmin()
        self.clear_orbit()
        self.orbit = orbit
        extent = self.orbit.zmax() - self.orbit.zmin()
        self.plotItem.setLimits(xMin=self.orbit.zmin() - (0.02 * extent),
                                xMax=self.orbit.zmax() + (0.02 * extent))
        self.plotItem.enableAutoRange(enable=False)
        self.axis_line.setLine(self.orbit.zmin(), 0.0, self.orbit.zmax(), 0.0)
        for bpm in self.orbit:
            line = BPMLineItem(bpm)
            self.lines[bpm.name] = line
            self.set_pen_for_bpm(bpm)
            self.plotItem.addItem(self.lines[bpm.name])
        if self.use_sector_ticks and (old_zmax != orbit.zmax()
                                      or old_zmin != orbit.zmin()):
            self.sector_ticks = [[], []]
            self.sector_ticks[0] = self.orbit.sector_locations()
            unit_nums = [name.split(":")[-1] for name in self.orbit.names()]
            self.sector_ticks[1] = zip(self.orbit.z_vals(), unit_nums)
            self.plotItem.getAxis('bottom').setTicks(self.sector_ticks)
            self.plotItem.getAxis('bottom').setStyle(textFillLimits=[(0,
                                                                      0.72)])
            self.plotItem.showGrid(x=True)
        if reset_range or self.needs_initial_range:
            self.reset_range()
            self.needs_initial_range = False
        else:
            self.plotItem.setRange(old_range, padding=0.0, update=False)
        self.draw_timer.start()

    def show_magnet_views(self, enabled):
        if enabled == self.show_magnet_buttons:
            return
        self.show_magnet_buttons = enabled
        if enabled:
            self.addItem(self.up_magnet_view, row=1, col=1)
            self.addItem(self.down_magnet_view, row=2, col=1)
            self.up_magnet_view.setXLink(self.plotItem)
            self.down_magnet_view.setXLink(self.plotItem)
        else:
            self.removeItem(self.up_magnet_view)
            self.removeItem(self.down_magnet_view)

    def set_magnet_list(self, magnet_list):
        self.up_magnet_view.set_magnets(magnet_list, reset_range=False)
        self.down_magnet_view.set_magnets(magnet_list, reset_range=False)

    @pyqtSlot(bool)
    def reset_range(self, checked=False):
        self.plotItem.enableAutoRange(axis=ViewBox.XAxis)
        self.plotItem.setYRange(self.ymin, self.ymax)

    def wheelEvent(self, event):
        if event.modifiers() == Qt.ShiftModifier:
            numPixels = event.pixelDelta()
            numDegrees = event.angleDelta()
            if not numPixels.isNull():
                s = (1.005)**(numPixels.y())
            else:
                s = (1.005)**(numDegrees.y() * (-1.0 / 8.0))
            self.plotItem.vb.scaleBy(y=s)
        else:
            super(OrbitView, self).wheelEvent(event)

    def clear_orbit(self):
        self.draw_timer.stop()
        auto_range_x_enabled = self.plotItem.vb.state['autoRange'][0]
        auto_range_y_enabled = self.plotItem.vb.state['autoRange'][1]
        self.plotItem.enableAutoRange(enable=False)
        if self.orbit is None:
            return
        for bpm in self.orbit:
            self.plotItem.removeItem(self.lines[bpm.name])
        self.plotItem.enableAutoRange(x=auto_range_x_enabled,
                                      y=auto_range_y_enabled)
        self.lines = {}

    @pyqtSlot()
    def redraw_bpms(self):
        for bpm in self.orbit:
            self.set_pen_for_bpm(bpm)
            self.lines[bpm.name].setLine(bpm.z, 0.0, bpm.z, bpm[self.axis])
        self.update_fit()

    def set_pen_for_bpm(self, bpm):
        if bpm.severity(self.axis) != 0:
            self.lines[bpm.name].setPen(self.no_beam_pen)
        else:
            if bpm.is_energy_bpm:
                self.lines[bpm.name].setPen(self.energy_bpm_pen)
            else:
                self.lines[bpm.name].setPen(self.bpm_pen)

    def update_fit(self):
        if not self._display_fit:
            return
        if self.orbit.fit_data is None:
            if self.fit_data_item is not None:
                self.fit_data_item.hide()
            return
        fit_data = None
        if self.axis == 'x':
            fit_data = self.orbit.fit_data['xpos']
        elif self.axis == 'y':
            fit_data = self.orbit.fit_data['ypos']
        self.fit_data_item.show()
        self.fit_data_item.setData(x=self.orbit.fit_data['zs'], y=fit_data)

    @pyqtSlot()
    def stop(self):
        self.draw_timer.stop()

    @pyqtSlot()
    def start(self):
        if self.orbit is not None:
            self.draw_timer.start()

    def setXLink(self, view):
        return self.plotItem.setXLink(view.plotItem)

    def setYLink(self, view):
        return self.plotItem.setYLink(view.plotItem)