Пример #1
0
    def initFigure(self):

        # Configure Layout
        self.layout_model = QGridLayout()
        self.setLayout( self.layout_model )

        # Figure title is 1x3 (row x col) excel cell
        self.TITLE = QLabel(text=self.title)
        self.TITLE.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.TITLE.setAlignment(QtCoreQtClass.AlignCenter)
        self.layout_model.addWidget(self.TITLE, 0, 0, 1, 3)
        self.layout_model.setRowStretch(0, 1)

        #Figure size is 4x3 (row x col) excel cell
        self.Figure = PlotWidget()
        self.Figure.setYRange(self.y_min, self.y_max)
        self.graph = PlotCurveItem(pen = self.color )

        #plot initial data
        self.graph.setData(self.x_data, self.y_data)
        self.Figure.addItem(self.graph)

        # add to main figure widget & resize the grid layout
        self.layout_model.addWidget(self.Figure, 1, 0, 4, 3)
        for n in range(4):
            self.layout_model.setRowStretch(n+1, 7)
Пример #2
0
    def _setupUi(self):
        self.image_view = PyDMImageView(
            parent=self,
            image_channel=self._dev+':Image-RB',
            width_channel=self._dev+':Width-RB')
        self.image_view.setObjectName('image')
        self.image_view.setStyleSheet(
            '#image{min-width:20em; min-height:20em;}')
        self.image_view.maxRedrawRate = 5
        self.image_view.colorMap = self.image_view.Jet
        self.image_view.readingOrder = self.image_view.Clike
        self._roixproj = SiriusConnectionSignal(self._dev+':ROIProjX-Mon')
        self._roiyproj = SiriusConnectionSignal(self._dev+':ROIProjY-Mon')
        self._roixfit = SiriusConnectionSignal(self._dev+':ROIGaussFitX-Mon')
        self._roiyfit = SiriusConnectionSignal(self._dev+':ROIGaussFitY-Mon')
        self._roixaxis = SiriusConnectionSignal(self._dev+':ROIAxisX-Mon')
        self._roiyaxis = SiriusConnectionSignal(self._dev+':ROIAxisY-Mon')
        self._roistartx = SiriusConnectionSignal(self._dev+':ROIStartX-Mon')
        self._roistarty = SiriusConnectionSignal(self._dev+':ROIStartY-Mon')
        self._roiendx = SiriusConnectionSignal(self._dev+':ROIEndX-Mon')
        self._roiendy = SiriusConnectionSignal(self._dev+':ROIEndY-Mon')
        self._roixproj.new_value_signal[np.ndarray].connect(self._update_roi)
        self.plt_roi = PlotCurveItem([0, 0, 500, 500, 0], [0, 500, 500, 0, 0])
        pen = mkPen()
        pen.setColor(QColor('red'))
        pen.setWidth(1)
        self.plt_roi.setPen(pen)
        self.image_view.addItem(self.plt_roi)
        self.plt_fit_x = PlotCurveItem([0, 0], [0, 400])
        self.plt_fit_y = PlotCurveItem([0, 0], [0, 400])
        self.plt_his_x = PlotCurveItem([0, 0], [0, 400])
        self.plt_his_y = PlotCurveItem([0, 0], [0, 400])
        pen = mkPen()
        pen.setColor(QColor('yellow'))
        self.plt_his_x.setPen(pen)
        self.plt_his_y.setPen(pen)
        self.image_view.addItem(self.plt_fit_x)
        self.image_view.addItem(self.plt_fit_y)
        self.image_view.addItem(self.plt_his_x)
        self.image_view.addItem(self.plt_his_y)

        gb_conf = self._get_config_widget(self)
        gb_posi = self._get_position_widget(self)
        gb_size = self._get_size_widget(self)

        gl = QGridLayout(self)
        gl.setContentsMargins(0, 0, 0, 0)
        if self._ori == 'V':
            gl.addWidget(self.image_view, 0, 0, 1, 2)
            gl.addWidget(gb_posi, 1, 0)
            gl.addWidget(gb_size, 1, 1)
            gl.addWidget(gb_conf, 2, 0, 1, 2)
        else:
            gl.addWidget(self.image_view, 0, 0, 1, 2)
            gl.addWidget(gb_conf, 0, 2, 2, 1)
            gl.addWidget(gb_posi, 1, 0)
            gl.addWidget(gb_size, 1, 1)
            gl.setColumnStretch(0, 5)
            gl.setColumnStretch(1, 5)
            gl.setColumnStretch(2, 1)
Пример #3
0
 def create_curve(self):
     """Creates a new plot item."""
     with self.lock:
         self.curve = PlotCurveItem(x=self.array_time,
                                    y=self.array_val,
                                    pen=self.pen)
     return self.curve
Пример #4
0
class lamb_pol:
    def __init__(self, dlamb):

        self.dlamb = dlamb
        self.p1main = glo_var.MyPW(x='x',
                                   y1='\u03bb',
                                   set_range=self.set_range)
        self.p1 = self.p1main.plotItem
        self.p1main.setLabel('bottom', "x", **glo_var.labelstyle)
        self.p1main.setLabel('left', "\u03bb", **glo_var.labelstyle)
        self.p1main.set_range = self.set_range

        # I didnt use it. Think about it.
        self.font = QtGui.QFont()
        self.font.setBold(True)
        self.viewbox = self.p1main.getViewBox()
        self.viewbox.setBackgroundColor('w')
        self.viewbox.setLimits(xMin=-0.03, yMin=-0.03, xMax=1.03)
        self.lambdas_xs, self.lambdas_ys = zip(*sorted(glo_var.lambdas))
        self.lambda_min = min(self.lambdas_ys)
        self.lambda_max = max(self.lambdas_ys)
        self.set_range()
        self.sp = myscat(size=7,
                         pen=mkPen(None),
                         brush=mkBrush(100, 200, 200),
                         symbolPen='w')
        self.lastClicked = []
        self.p1main.coordinate_label = QtGui.QLabel()
        self.frame = glo_var.setframe(
            self.p1main,
            width=1,
            coordinate_label=self.p1main.coordinate_label)
        self.dlamb.addWidget(self.frame)
        self.update()

    def set_range(self):
        self.viewbox.setRange(xRange=[0, 1.2 * self.lambda_max],
                              yRange=[0, 1.2 * self.lambda_max],
                              padding=0.1)

    def update(self):
        self.p1main.clear()
        self.x, self.y = zip(*sorted(glo_var.lambdas))
        self.curve = PlotCurveItem(np.array(self.x), np.array(self.y))
        self.curve.setPen(mkPen('k', width=glo_var.line_width))
        self.p1main.addItem(self.curve)
        self.sp.setData(self.x, self.y)
        self.sp.sigClicked.connect(self.clicked)
        self.p1main.addItem(self.sp)

    def clicked(self, item, points):
        self.points = points
        for p in self.lastClicked:
            p.resetPen()
        for p in points:
            p.setPen('b', width=2)
        self.lastClicked = points

    def receive(self, slid):
        self.sp.receive(slid, self)
Пример #5
0
 def make_right_axis(self):
     # self.p4.plot(self.domain,self.rho_avg,pen=self.rho_dash)
     self.p4_2.addItem(
         PlotCurveItem(self.betas_pre, self.rho_avg_pre, pen=self.rho_dash))
     self.p4_2.addItem(
         PlotCurveItem(self.betas_post,
                       self.rho_avg_post,
                       pen=self.rho_dash))
Пример #6
0
 def update(self):
     self.p1main.clear()
     self.x, self.y = zip(*sorted(glo_var.lambdas))
     self.curve = PlotCurveItem(np.array(self.x), np.array(self.y))
     self.curve.setPen(mkPen('k', width=glo_var.line_width))
     self.p1main.addItem(self.curve)
     self.sp.setData(self.x, self.y)
     self.sp.sigClicked.connect(self.clicked)
     self.p1main.addItem(self.sp)
Пример #7
0
 def plotTotalDistance(self, mode='new'):
     """ Plot monthly total distance. """
     colour = self.style['odometer']['colour']
     style = self._makeFillStyle(colour)
     dts, odo = self.data.getMonthlyOdometer()
     dts = [dt.timestamp() for dt in dts]
     if mode == 'new':
         self.backgroundItem = PlotCurveItem(dts, odo, **style)
         self.vb2.addItem(self.backgroundItem)
     elif mode == 'set':
         self.backgroundItem.setData(dts, odo, **style)
     self.plotItem.getAxis('right').setLabel('Total monthly distance',
                                             color=colour)
Пример #8
0
class FigureWidget(QWidget):

    def __init__(   self, title=f"Figure", yRange=[-2, 6], \
                    xdata=[], ydata=[], \
                    color=20 \
                ):
        super().__init__()
        self.title = f'<h3> {title} </h3>'
        
        self.color = color
        self.x_data = np.array(xdata)
        self.y_data = np.array(ydata)
        self.y_min, self.y_max = yRange[0] , yRange[1]
        self.initFigure()

    
    def initFigure(self):

        # Configure Layout
        self.layout_model = QGridLayout()
        self.setLayout( self.layout_model )

        # Figure title is 1x3 (row x col) excel cell
        self.TITLE = QLabel(text=self.title)
        self.TITLE.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.TITLE.setAlignment(QtCoreQtClass.AlignCenter)
        self.layout_model.addWidget(self.TITLE, 0, 0, 1, 3)
        self.layout_model.setRowStretch(0, 1)

        #Figure size is 4x3 (row x col) excel cell
        self.Figure = PlotWidget()
        self.Figure.setYRange(self.y_min, self.y_max)
        self.graph = PlotCurveItem(pen = self.color )

        #plot initial data
        self.graph.setData(self.x_data, self.y_data)
        self.Figure.addItem(self.graph)

        # add to main figure widget & resize the grid layout
        self.layout_model.addWidget(self.Figure, 1, 0, 4, 3)
        for n in range(4):
            self.layout_model.setRowStretch(n+1, 7)
    
    def PlotData(self, x_data, y_data):
        self.x_data = x_data
        self.y_data = y_data

        self.graph.setData(self.x_data, self.y_data)
Пример #9
0
    def start(self, xmlSubPanel, boardConfiguration):
        '''This method starts a timer used for any long running loops in a subpanel'''
        self.xmlSubPanel = xmlSubPanel
        self.boardConfiguration = boardConfiguration

        self.plotIndex = int(self.xml.find(self.xmlSubPanel + '/Index').text)
        plotSize = int(self.xml.find(self.xmlSubPanel + '/PlotSize').text)
        plotNames = self.xml.findall(self.xmlSubPanel + '/PlotName')
        self.plotCount = len(plotNames)

        self.ui.graphicsView.setRange(xRange=(0, plotSize), padding=0.0)
        self.ui.graphicsView.clear()
        self.ui.treeWidget.clear()

        self.data, self.curves, colors = [], [], [
            QtGui.QColor('blue'),
            QtGui.QColor('red'),
            QtGui.QColor('lime'),
            QtGui.QColor('cornflowerblue'),
            QtGui.QColor('greenyellow'),
            QtGui.QColor('violet'),
            QtGui.QColor('orange'),
            QtGui.QColor('deepskyblue'),
            QtGui.QColor('firebrick'),
            QtGui.QColor('aqua')
        ]

        for i in xrange(self.plotCount):
            self.data.append([0.0] * plotSize)
            self.curves.append(
                PlotCurveItem(self.data[i],
                              pen={
                                  'color': colors[i],
                                  'width': 2
                              }))
            self.ui.graphicsView.addItem(self.curves[i])

            plotName = plotNames[i].text
            newLine = QtGui.QTreeWidgetItem(self.ui.treeWidget)
            newLine.setCheckState(0, 2)
            newLine.setBackgroundColor(0, colors[i])
            newLine.setText(1, plotName + '   ')
            newLine.setText(2, '0.000')

        self.ui.treeWidget.resizeColumnToContents(0)
        self.ui.treeWidget.resizeColumnToContents(1)
        self.legend = self.ui.treeWidget.invisibleRootItem()

        if self.comm.isConnected() == True:
            telemetry = self.xml.find(self.xmlSubPanel + '/Telemetry').text
            if telemetry != '':
                self.comm.write(telemetry)
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.readContinuousData)
            self.timer.start(50)
            self.startCommThread()

        self.plot_timer = QtCore.QTimer()
        self.plot_timer.timeout.connect(self.update_plot)
        self.plot_timer.start(100)
Пример #10
0
 def createGraph(self, data, graph):
     plot = PlotItem()
     line = PlotCurveItem(x=asarray(
         [x for x in range(0, self.element.sections + 1)]),
                          y=data,
                          pxMode=True,
                          symbolSize=5)
     plot.addItem(line)
     graph.addItem(plot, row=0, col=0)
Пример #11
0
 def __init__(self, parent=None, background='default', axisItems=None):
     super(BasePlot, self).__init__(parent=parent,
                                    background=background,
                                    axisItems=axisItems)
     self.plotItem = self.getPlotItem()
     self.plotItem.hideButtons()
     self._auto_range_x = None
     self.setAutoRangeX(True)
     self._auto_range_y = None
     self.setAutoRangeY(True)
     self._show_x_grid = None
     self.setShowXGrid(False)
     self._show_y_grid = None
     self.setShowYGrid(False)
     self._curveColor = QColor(255, 255, 255)
     self.curve = PlotCurveItem(pen=self._curveColor)
     self.addItem(self.curve)
     self._title = None
Пример #12
0
 def _plot_horizontal_lines(self):
     """
     Function plots the vertical dashed lines that points to the selected
     sequence values at the y axis.
     """
     for _ in range(len(self.sequences)):
         self.plot_horline.append(
             PlotCurveItem(pen=mkPen(QColor(Qt.blue), style=Qt.DashLine)))
         self.plot_horlabel.append(
             TextItem(color=QColor(Qt.black), anchor=(0, 1)))
     for item in self.plot_horlabel + self.plot_horline:
         self.addItem(item)
    def __show_data(self, field1, field2, field3):
        if self.__shared_data.parameter is not None:
            # Generate the timecodes if needed
            if len(self.__shared_data.parameter['TIMECODE']) == 0:
                if self.__shared_data.sampling_rate is None:
                    result = False
                    while not result and result == 0:
                        result = self.__show_sampling_rate_picker()

                self.__shared_data.add_timecode()

            self.__x_axis_viewbox.clear()
            self.__y_axis_viewbox.clear()
            self.__z_axis_viewbox.clear()

            # Show the 3 selected fields
            self.__x_axis_viewbox.addItem(PlotCurveItem(list(map(int, self.__shared_data.parameter.get(field1))),
                                                        pen='#34495e'))
            self.__y_axis_viewbox.addItem(PlotCurveItem(list(map(int, self.__shared_data.parameter.get(field2))),
                                                        pen='#9b59b6'))
            self.__z_axis_viewbox.addItem(PlotCurveItem(list(map(int, self.__shared_data.parameter.get(field3))),
                                                        pen='#3498db'))

            self.__x_axis_item.setLabel(field1, color="#34495e")
            self.__y_axis_item.setLabel(field2, color="#9b59b6")
            self.__z_axis_item.setLabel(field3, color="#3498db")

            # Add the middle line and the bottom timecodes
            timecodes = self.__shared_data.parameter['TIMECODE']
            middle = [0] * len(timecodes)
            self.__plot_item_viewbox.addItem(PlotCurveItem(middle, pen='#000000'))
            self.__plot_item.getAxis('bottom').setTicks(
                self.__generate_time_ticks(timecodes, self.__shared_data.sampling_rate))

            # Enable the controls
            self.__sync_time_edit.setEnabled(True)
            self.__sync_time_button.setEnabled(True)
            self.__dir_picker_button.setEnabled(False)
        self.__update_views()
Пример #14
0
    def __init__(self, image=None, fillHistogram=True, bounds: tuple = None):
        GraphicsWidget.__init__(self)
        self.imageItem = lambda: None  # fake a dead weakref

        self.layout = QGraphicsGridLayout()
        self.setLayout(self.layout)
        self.layout.setContentsMargins(1, 1, 1, 1)
        self.layout.setSpacing(0)
        self.vb = ViewBox(parent=self)
        # self.vb.setMaximumHeight(152)
        # self.vb.setMinimumWidth(45)
        self.vb.setMouseEnabled(x=True, y=False)

        self.region = LinearRegionItem([0, 1], 'vertical', swapMode='block', bounds=bounds)
        self.region.setZValue(1000)
        self.vb.addItem(self.region)
        self.region.lines[0].addMarker('<|', 0.5)
        self.region.lines[1].addMarker('|>', 0.5)
        self.region.sigRegionChanged.connect(self.regionChanging)
        self.region.sigRegionChangeFinished.connect(self.regionChanged)

        self.axis = AxisItem('bottom', linkView=self.vb, maxTickLength=-10, parent=self)
        self.layout.addItem(self.axis, 1, 0)
        self.layout.addItem(self.vb, 0, 0)
        self.range = None
        self.vb.sigRangeChanged.connect(self.viewRangeChanged)

        self.plot = PlotCurveItem(pen=(200, 200, 200, 100))
        # self.plot.rotate(90)
        self.vb.addItem(self.plot)

        self.fillHistogram(fillHistogram)
        self._showRegions()

        self.autoHistogramRange()

        if image is not None:
            self.setImageItem(image)
Пример #15
0
    def genTimePlotA(self):
        newData = self.initializeData()

        if not newData.size:
            self.printStatus('Invalid PV? Unable to get data. Aborting.')
            self.ui.startButton.setEnabled(True)
            return

        data = newData[:self.numPoints]

        self.plotAttributes["curve"] = PlotCurveItem(data, pen=1)
        self.plot.addItem(self.plotAttributes["curve"])

        self.plotFit(arange(self.numPoints), data, self.devices["A"])
Пример #16
0
 def _plot_horizontal_lines(self):
     """
     Function plots the vertical dashed lines that points to the selected
     sequence values at the y axis.
     """
     highlight = self.palette().highlight()
     text = self.palette().text()
     for _ in range(len(self.sequences)):
         self.plot_horline.append(
             PlotCurveItem(pen=mkPen(highlight.color(), style=Qt.DashLine)))
         self.plot_horlabel.append(
             TextItem(color=text.color(), anchor=(0, 1)))
     for item in self.plot_horlabel + self.plot_horline:
         self.addItem(item)
Пример #17
0
    def getLinearFit(self, xData, yData, updateExistingPlot):
        # noinspection PyTupleAssignmentBalance
        m, b = polyfit(xData, yData, 1)
        fitData = polyval([m, b], xData)

        self.text["slope"].setText('Slope: ' + str("{:.3e}".format(m)))

        if updateExistingPlot:
            self.plotAttributes["fit"].setData(xData, fitData)
        else:
            # noinspection PyTypeChecker
            self.plotAttributes["fit"] = PlotCurveItem(xData,
                                                       fitData,
                                                       'g-',
                                                       linewidth=1)
Пример #18
0
def curve_item_factory(pen='red'):
    """
    Create a PlotCurveItem with the given pen
    Parameters
    ----------
    pen: any type of arguments accepted by pyqtgraph.function.mkColor or one of the COLORS_DICT key

    Returns
    -------
    PlotCurveItem
    """
    if isinstance(pen, str):
        if pen in COLORS_DICT:
            pen = COLORS_DICT[pen]

    return PlotCurveItem(pen=pen)
Пример #19
0
    def genPlotFFT(self, newdata, updateExistingPlot):

        if not newdata.size:
            return None

        newdata = newdata[:self.numPoints]

        nans, x = isnan(newdata), lambda z: z.nonzero()[0]
        # interpolate nans
        newdata[nans] = interp(x(nans), x(~nans), newdata[~nans])
        # remove DC component
        newdata = newdata - mean(newdata)

        newdata = concatenate([newdata, zeros(self.numPoints * 2)])

        ps = abs(fft.fft(newdata)) / newdata.size

        self.waitForRate()
        frequencies = fft.fftfreq(newdata.size, 1.0 / self.getRate())
        keep = (frequencies >= 0)
        ps = ps[keep]
        frequencies = frequencies[keep]
        idx = argsort(frequencies)

        if updateExistingPlot:
            self.plotAttributes["curve"].setData(x=frequencies[idx], y=ps[idx])
        else:
            # noinspection PyTypeChecker
            self.plotAttributes["curve"] = PlotCurveItem(x=frequencies[idx],
                                                         y=ps[idx],
                                                         pen=1)

        self.plot.addItem(self.plotAttributes["curve"])
        self.plot.setTitle(self.devices["A"])
        self.plotAttributes["frequencies"] = frequencies

        return ps
Пример #20
0
    def getPolynomialFit(self, xData, yData, updateExistingPlot):
        co = polyfit(xData, yData, self.fitOrder)
        pol = poly1d(co)
        xDataSorted = sorted(xData)
        fit = pol(xDataSorted)

        if updateExistingPlot:
            self.plotAttributes["parab"].setData(xDataSorted, fit)
        else:
            # noinspection PyTypeChecker
            self.plotAttributes["parab"] = PlotCurveItem(xDataSorted,
                                                         fit,
                                                         pen=3,
                                                         size=2)

        if self.fitOrder == 2:
            self.text["slope"].setText('Peak: ' + str(-co[1] / (2 * co[0])))

        elif self.fitOrder == 3:
            self.text["slope"].setText(
                str("{:.2e}".format(co[0])) + 'x^3' +
                str("+{:.2e}".format(co[1])) + 'x^2' +
                str("+{:.2e}".format(co[2])) + 'x' +
                str("+{:.2e}".format(co[3])))
Пример #21
0
    def _setupUi(self):
        vl = QVBoxLayout(self)
        self.image_view = ImageView(
            self.process_image,
            parent=self,
            image_channel=self.image_channel,
            width_channel=self.width_channel)
        self.image_view.maxRedrawRate = 5
        self.image_view.readingOrder = self.image_view.Clike
        self.plt_roi = PlotCurveItem([0, 0, 400, 400, 0], [0, 400, 400, 0, 0])
        pen = mkPen()
        pen.setColor(QColor('red'))
        pen.setWidth(1)
        self.plt_roi.setPen(pen)
        self.image_view.addItem(self.plt_roi)
        self.plt_fit_x = PlotCurveItem([0, 0], [0, 400])
        self.plt_fit_y = PlotCurveItem([0, 0], [0, 400])
        self.plt_his_x = PlotCurveItem([0, 0], [0, 400])
        self.plt_his_y = PlotCurveItem([0, 0], [0, 400])
        pen = mkPen()
        pen.setColor(QColor('yellow'))
        self.plt_his_x.setPen(pen)
        self.plt_his_y.setPen(pen)
        self.image_view.addItem(self.plt_fit_x)
        self.image_view.addItem(self.plt_fit_y)
        self.image_view.addItem(self.plt_his_x)
        self.image_view.addItem(self.plt_his_y)
        vl.addWidget(self.image_view)

        gb_trig = QGroupBox('Trigger', self)
        vl.addWidget(gb_trig)
        gb_trig.setLayout(QVBoxLayout())
        gb_trig.layout().addWidget(HLTriggerSimple(
            gb_trig, device=self.trig_name, prefix=self._prefix))

        gb_pos = QGroupBox('Position [mm]', self)
        vl.addWidget(gb_pos)
        hl = QHBoxLayout(gb_pos)
        fl = QFormLayout()
        hl.addLayout(fl)
        self.cbox_method = QComboBox(gb_pos)
        self.cbox_method.addItem('Gauss Fit')
        self.cbox_method.addItem('Moments')
        fl.addRow(QLabel('Method', gb_pos), self.cbox_method)
        self.spbox_roi_size_x = QSpinBoxPlus(gb_pos)
        self.spbox_roi_size_y = QSpinBoxPlus(gb_pos)
        self.spbox_roi_center_x = QSpinBoxPlus(gb_pos)
        self.spbox_roi_center_y = QSpinBoxPlus(gb_pos)
        self.spbox_roi_size_x.setKeyboardTracking(False)
        self.spbox_roi_size_y.setKeyboardTracking(False)
        self.spbox_roi_center_x.setKeyboardTracking(False)
        self.spbox_roi_center_y.setKeyboardTracking(False)
        self.spbox_roi_size_x.setMaximum(2448)
        self.spbox_roi_size_y.setMaximum(2050)
        self.spbox_roi_center_x.setMaximum(2448)
        self.spbox_roi_center_y.setMaximum(2050)
        self.spbox_roi_size_x.setValue(300)
        self.spbox_roi_size_y.setValue(400)
        self.spbox_roi_center_x.setValue(500)
        self.spbox_roi_center_y.setValue(500)
        fl.addRow(QLabel('ROI Size X', gb_pos), self.spbox_roi_size_x)
        fl.addRow(QLabel('ROI Size Y', gb_pos), self.spbox_roi_size_y)
        self.cbbox_auto_center = QCheckBox('Automatic Centering', gb_pos)
        self.cbbox_auto_center.clicked.connect(self.cbbox_auto_center_clicked)
        self.cbbox_auto_center.setChecked(True)
        fl.addRow(self.cbbox_auto_center)
        fl.addRow(QLabel('ROI Center X', gb_pos), self.spbox_roi_center_x)
        fl.addRow(QLabel('ROI Center Y', gb_pos), self.spbox_roi_center_y)
        self.spbox_img_max = QSpinBoxPlus(gb_pos)
        self.spbox_img_max.setKeyboardTracking(False)
        self.spbox_img_max.setMinimum(0)
        self.spbox_img_max.setMaximum(2448)
        self.spbox_img_max.setValue(0)
        fl.addRow(QLabel('Max. Pixel Val.', gb_pos), self.spbox_img_max)
        self.cbbox_acq_bg = QCheckBox('Acquire Background', gb_pos)
        self.cbbox_acq_bg.clicked.connect(self.cbbox_acq_bg_checked)
        fl.addRow(self.cbbox_acq_bg)
        self.pb_reset_bg = QPushButton('Reset BG', gb_pos)
        self.pb_reset_bg.clicked.connect(self.pb_reset_bg_clicked)
        fl.addRow(self.pb_reset_bg)
        fl = QFormLayout()
        hl.addLayout(fl)
        self.lb_xave = QLabel('0', gb_pos)
        self.lb_yave = QLabel('0', gb_pos)
        self.lb_xstd = QLabel('0', gb_pos)
        self.lb_ystd = QLabel('0', gb_pos)
        fl.addRow(QLabel('Average Position', gb_pos))
        fl.addRow(QLabel('x = ', gb_pos), self.lb_xave)
        fl.addRow(QLabel('y = ', gb_pos), self.lb_yave)
        fl.addRow(QLabel('Beam Size', gb_pos))
        fl.addRow(QLabel('x = ', gb_pos), self.lb_xstd)
        fl.addRow(QLabel('y = ', gb_pos), self.lb_ystd)

        hl.setSpacing(12)
        hl.setStretch(0, 1)
        hl.setStretch(1, 1)
Пример #22
0
class ProcessImage(QWidget):
    def __init__(self, parent=None, place='LI-Energy', prefix=_VACA_PREFIX):
        super().__init__(parent)
        self._place = place or 'LI-Energy'
        self._prefix = prefix
        self._select_experimental_setup()
        self.cen_x = None
        self.cen_y = None
        self.sigma_x = None
        self.sigma_y = None
        self.bg_ready = False
        self.bg = None
        self.nbg = 0
        self._setupUi()

    def _select_experimental_setup(self):
        pref = self._prefix
        if self._place.lower().startswith('li-ene'):
            prof = pref + ('-' if pref else '') + 'LA-BI:PRF4'
            self.conv_coefx = PV(prof + ':X:Gauss:Coef')
            self.conv_coefy = PV(prof + ':Y:Gauss:Coef')
            self.image_channel = prof + ':RAW:ArrayData'
            self.width_channel = prof + ':ROI:MaxSizeX_RBV'
            self.trig_name = 'LI-Fam:TI-Scrn'
        elif self._place.lower().startswith('li-emit'):
            prof = pref + ('-' if pref else '') + 'LA-BI:PRF5'
            self.conv_coefx = PV(prof + ':X:Gauss:Coef')
            self.conv_coefy = PV(prof + ':Y:Gauss:Coef')
            self.image_channel = prof + ':RAW:ArrayData'
            self.width_channel = prof + ':ROI:MaxSizeX_RBV'
            self.trig_name = 'LI-Fam:TI-Scrn'
        elif self._place.lower().startswith('tb-emit'):
            prof = _PVName('TB-02:DI-ScrnCam-2').substitute(prefix=pref)
            self.conv_coefx = PV(prof.substitute(propty='ImgScaleFactorX-RB'))
            self.conv_coefy = PV(prof.substitute(propty='ImgScaleFactorY-RB'))
            prof = _PVName('TB-02:DI-Scrn-2').substitute(prefix=pref)
            self.image_channel = prof.substitute(propty='ImgData-Mon')
            self.width_channel = prof.substitute(propty='ImgROIWidth-RB')
            self.trig_name = 'TB-Fam:TI-Scrn'
        else:
            raise Exception('Wrong value for "place".')

    def _setupUi(self):
        vl = QVBoxLayout(self)
        self.image_view = ImageView(
            self.process_image,
            parent=self,
            image_channel=self.image_channel,
            width_channel=self.width_channel)
        self.image_view.maxRedrawRate = 5
        self.image_view.readingOrder = self.image_view.Clike
        self.plt_roi = PlotCurveItem([0, 0, 400, 400, 0], [0, 400, 400, 0, 0])
        pen = mkPen()
        pen.setColor(QColor('red'))
        pen.setWidth(1)
        self.plt_roi.setPen(pen)
        self.image_view.addItem(self.plt_roi)
        self.plt_fit_x = PlotCurveItem([0, 0], [0, 400])
        self.plt_fit_y = PlotCurveItem([0, 0], [0, 400])
        self.plt_his_x = PlotCurveItem([0, 0], [0, 400])
        self.plt_his_y = PlotCurveItem([0, 0], [0, 400])
        pen = mkPen()
        pen.setColor(QColor('yellow'))
        self.plt_his_x.setPen(pen)
        self.plt_his_y.setPen(pen)
        self.image_view.addItem(self.plt_fit_x)
        self.image_view.addItem(self.plt_fit_y)
        self.image_view.addItem(self.plt_his_x)
        self.image_view.addItem(self.plt_his_y)
        vl.addWidget(self.image_view)

        gb_trig = QGroupBox('Trigger', self)
        vl.addWidget(gb_trig)
        gb_trig.setLayout(QVBoxLayout())
        gb_trig.layout().addWidget(HLTriggerSimple(
            gb_trig, device=self.trig_name, prefix=self._prefix))

        gb_pos = QGroupBox('Position [mm]', self)
        vl.addWidget(gb_pos)
        hl = QHBoxLayout(gb_pos)
        fl = QFormLayout()
        hl.addLayout(fl)
        self.cbox_method = QComboBox(gb_pos)
        self.cbox_method.addItem('Gauss Fit')
        self.cbox_method.addItem('Moments')
        fl.addRow(QLabel('Method', gb_pos), self.cbox_method)
        self.spbox_roi_size_x = QSpinBoxPlus(gb_pos)
        self.spbox_roi_size_y = QSpinBoxPlus(gb_pos)
        self.spbox_roi_center_x = QSpinBoxPlus(gb_pos)
        self.spbox_roi_center_y = QSpinBoxPlus(gb_pos)
        self.spbox_roi_size_x.setKeyboardTracking(False)
        self.spbox_roi_size_y.setKeyboardTracking(False)
        self.spbox_roi_center_x.setKeyboardTracking(False)
        self.spbox_roi_center_y.setKeyboardTracking(False)
        self.spbox_roi_size_x.setMaximum(2448)
        self.spbox_roi_size_y.setMaximum(2050)
        self.spbox_roi_center_x.setMaximum(2448)
        self.spbox_roi_center_y.setMaximum(2050)
        self.spbox_roi_size_x.setValue(300)
        self.spbox_roi_size_y.setValue(400)
        self.spbox_roi_center_x.setValue(500)
        self.spbox_roi_center_y.setValue(500)
        fl.addRow(QLabel('ROI Size X', gb_pos), self.spbox_roi_size_x)
        fl.addRow(QLabel('ROI Size Y', gb_pos), self.spbox_roi_size_y)
        self.cbbox_auto_center = QCheckBox('Automatic Centering', gb_pos)
        self.cbbox_auto_center.clicked.connect(self.cbbox_auto_center_clicked)
        self.cbbox_auto_center.setChecked(True)
        fl.addRow(self.cbbox_auto_center)
        fl.addRow(QLabel('ROI Center X', gb_pos), self.spbox_roi_center_x)
        fl.addRow(QLabel('ROI Center Y', gb_pos), self.spbox_roi_center_y)
        self.spbox_img_max = QSpinBoxPlus(gb_pos)
        self.spbox_img_max.setKeyboardTracking(False)
        self.spbox_img_max.setMinimum(0)
        self.spbox_img_max.setMaximum(2448)
        self.spbox_img_max.setValue(0)
        fl.addRow(QLabel('Max. Pixel Val.', gb_pos), self.spbox_img_max)
        self.cbbox_acq_bg = QCheckBox('Acquire Background', gb_pos)
        self.cbbox_acq_bg.clicked.connect(self.cbbox_acq_bg_checked)
        fl.addRow(self.cbbox_acq_bg)
        self.pb_reset_bg = QPushButton('Reset BG', gb_pos)
        self.pb_reset_bg.clicked.connect(self.pb_reset_bg_clicked)
        fl.addRow(self.pb_reset_bg)
        fl = QFormLayout()
        hl.addLayout(fl)
        self.lb_xave = QLabel('0', gb_pos)
        self.lb_yave = QLabel('0', gb_pos)
        self.lb_xstd = QLabel('0', gb_pos)
        self.lb_ystd = QLabel('0', gb_pos)
        fl.addRow(QLabel('Average Position', gb_pos))
        fl.addRow(QLabel('x = ', gb_pos), self.lb_xave)
        fl.addRow(QLabel('y = ', gb_pos), self.lb_yave)
        fl.addRow(QLabel('Beam Size', gb_pos))
        fl.addRow(QLabel('x = ', gb_pos), self.lb_xstd)
        fl.addRow(QLabel('y = ', gb_pos), self.lb_ystd)

        hl.setSpacing(12)
        hl.setStretch(0, 1)
        hl.setStretch(1, 1)

    def cbbox_auto_center_clicked(self, clicked):
        self.spbox_roi_center_x.setEnabled(not clicked)
        self.spbox_roi_center_y.setEnabled(not clicked)

    def pb_reset_bg_clicked(self, clicked=False):
        self.bg_ready = False
        self.bg = None
        self.nbg = 0

    def cbbox_acq_bg_checked(self, check):
        if check:
            self.pb_reset_bg_clicked()
        else:
            if self.bg is not None:
                self.bg /= self.nbg
                self.bg_ready = True

    def calc_roi(self, image):
        proj_x = image.sum(axis=0)
        proj_y = image.sum(axis=1)
        axis_x = np.arange(image.shape[1])
        axis_y = np.arange(image.shape[0])

        if self.cbbox_auto_center.isChecked():
            cen_x, _ = _calc_moments(axis_x, proj_x)
            cen_y, _ = _calc_moments(axis_y, proj_y)
        else:
            cen_x = self.spbox_roi_center_x.value()
            cen_y = self.spbox_roi_center_y.value()

        roi_size_x = self.spbox_roi_size_x.value()
        roi_size_y = self.spbox_roi_size_y.value()
        strt_x, end_x = np.array([-1, 1])*roi_size_x + int(cen_x)
        strt_y, end_y = np.array([-1, 1])*roi_size_y + int(cen_y)
        strt_x = max(strt_x, 0)
        strt_y = max(strt_y, 0)
        end_x = min(end_x, image.shape[1])
        end_y = min(end_y, image.shape[0])
        self.plt_roi.setData(
            np.array([strt_x, strt_x, end_x, end_x, strt_x]),
            np.array([strt_y, end_y, end_y, strt_y, strt_y]))

        image = image[strt_y:end_y, strt_x:end_x]
        proj_x = image.sum(axis=0)
        proj_y = image.sum(axis=1)
        axis_x = axis_x[strt_x:end_x]
        axis_y = axis_y[strt_y:end_y]
        return proj_x, proj_y, axis_x, axis_y

    def process_image(self, image, wid):
        if wid <= 0:
            return image
        try:
            image = image.reshape((-1, wid))
        except (TypeError, ValueError, AttributeError):
            return image
        if self.cbbox_acq_bg.isChecked():
            if self.bg is None:
                self.bg = np.array(image, dtype=float)
            else:
                self.bg += np.array(image, dtype=float)
            self.nbg += 1
            return image
        if self.bg_ready:
            image -= np.array(self.bg, dtype=image.dtype)
            b = np.where(image < 0)
            image[b] = 0

        maxi = self.spbox_img_max.value()
        if maxi > 0:
            b = np.where(image > maxi)
            self.image_view.colorMapMax = maxi
            image[b] = maxi

        proj_x, proj_y, axis_x, axis_y = self.calc_roi(image)
        x_max = max(proj_x)
        y_max = max(proj_y)
        if self.cbox_method.currentIndex():
            cen_x, std_x = _calc_moments(axis_x, proj_x)
            cen_y, std_y = _calc_moments(axis_y, proj_y)
            amp_x = x_max
            amp_y = y_max
            off_x = 0
            off_y = 0
        else:
            amp_x, cen_x, std_x, off_x = _fit_gaussian(axis_x, proj_x)
            amp_y, cen_y, std_y, off_y = _fit_gaussian(axis_y, proj_y)
        std_x = abs(std_x)
        std_y = abs(std_y)
        yd = _gaussian(axis_x, amp_x, cen_x, std_x, off_x)/x_max*400
        self.plt_fit_x.setData(axis_x, yd + axis_y[0])
        self.plt_his_x.setData(axis_x, proj_x/x_max*400 + axis_y[0])

        yd = _gaussian(axis_y, amp_y, cen_y, std_y, off_y)/y_max*400
        self.plt_fit_y.setData(yd + axis_x[0], axis_y)
        self.plt_his_y.setData(proj_y/y_max*400 + axis_x[0], axis_y)

        offset_x = image.shape[1]/2
        offset_y = image.shape[0]/2
        self.lb_xave.setText('{0:4d}'.format(int(cen_x or 0)))
        self.lb_yave.setText('{0:4d}'.format(int(cen_y or 0)))
        self.lb_xstd.setText('{0:4d}'.format(int(std_x or 0)))
        self.lb_ystd.setText('{0:4d}'.format(int(std_y or 0)))

        coefx = self.conv_coefx.value
        coefy = self.conv_coefy.value
        if coefx is None or coefy is None:
            return

        cen_x -= offset_x
        cen_y -= offset_y
        self.cen_x = cen_x * coefx*1e-3  # transform to meter
        self.cen_y = cen_y * coefy*1e-3
        self.sigma_x = std_x * coefx*1e-3
        self.sigma_y = std_y * coefy*1e-3

        return image

    def get_params(self):
        return self.cen_x, self.sigma_x, self.cen_y, self.sigma_y
Пример #23
0
class SiriusSpectrogramView(GraphicsLayoutWidget, PyDMWidget, PyDMColorMap,
                            ReadingOrder):
    """
    A SpectrogramView with support for Channels and more from PyDM.

    If there is no :attr:`channelWidth` it is possible to define the width of
    the image with the :attr:`width` property.

    The :attr:`normalizeData` property defines if the colors of the images are
    relative to the :attr:`colorMapMin` and :attr:`colorMapMax` property or to
    the minimum and maximum values of the image.

    Use the :attr:`newImageSignal` to hook up to a signal that is emitted when
    a new image is rendered in the widget.

    Parameters
    ----------
    parent : QWidget
        The parent widget for the Label
    image_channel : str, optional
        The channel to be used by the widget for the image data.
    xaxis_channel : str, optional
        The channel to be used by the widget to receive the image width
        (if ReadingOrder == Clike), and to set the xaxis values
    yaxis_channel : str, optional
        The channel to be used by the widget to receive the image width
        (if ReadingOrder == Fortranlike), and to set the yaxis values
    background : QColor, optional
        QColor to set the background color of the GraphicsView
    """

    Q_ENUMS(PyDMColorMap)
    Q_ENUMS(ReadingOrder)

    color_maps = cmaps

    def __init__(self,
                 parent=None,
                 image_channel=None,
                 xaxis_channel=None,
                 yaxis_channel=None,
                 roioffsetx_channel=None,
                 roioffsety_channel=None,
                 roiwidth_channel=None,
                 roiheight_channel=None,
                 title='',
                 background='w',
                 image_width=0,
                 image_height=0):
        """Initialize widget."""
        GraphicsLayoutWidget.__init__(self, parent)
        PyDMWidget.__init__(self)
        self.thread = None
        self._imagechannel = None
        self._xaxischannel = None
        self._yaxischannel = None
        self._roioffsetxchannel = None
        self._roioffsetychannel = None
        self._roiwidthchannel = None
        self._roiheightchannel = None
        self._channels = 7 * [
            None,
        ]
        self.image_waveform = np.zeros(0)
        self._image_width = image_width if not xaxis_channel else 0
        self._image_height = image_height if not yaxis_channel else 0
        self._roi_offsetx = 0
        self._roi_offsety = 0
        self._roi_width = 0
        self._roi_height = 0
        self._normalize_data = False
        self._auto_downsample = True
        self._last_yaxis_data = None
        self._last_xaxis_data = None
        self._auto_colorbar_lims = True
        self.format_tooltip = '{0:.4g}, {1:.4g}'

        # ViewBox and imageItem.
        self._view = ViewBox()
        self._image_item = ImageItem()
        self._view.addItem(self._image_item)

        # ROI
        self.ROICurve = PlotCurveItem([0, 0, 0, 0, 0], [0, 0, 0, 0, 0])
        self.ROIColor = QColor('red')
        pen = mkPen()
        pen.setColor(QColor('transparent'))
        pen.setWidth(1)
        self.ROICurve.setPen(pen)
        self._view.addItem(self.ROICurve)

        # Axis.
        self.xaxis = AxisItem('bottom')
        self.xaxis.setPen(QColor(0, 0, 0))
        if not xaxis_channel:
            self.xaxis.setVisible(False)
        self.yaxis = AxisItem('left')
        self.yaxis.setPen(QColor(0, 0, 0))
        if not yaxis_channel:
            self.yaxis.setVisible(False)

        # Colorbar legend.
        self.colorbar = _GradientLegend()

        # Title.
        start_row = 0
        if title:
            self.title = LabelItem(text=title, color='#000000')
            self.addItem(self.title, 0, 0, 1, 3)
            start_row = 1

        # Set layout.
        self.addItem(self._view, start_row, 1)
        self.addItem(self.yaxis, start_row, 0)
        self.addItem(self.colorbar, start_row, 2)
        self.addItem(self.xaxis, start_row + 1, 1)
        self.setBackground(background)
        self.ci.layout.setColumnSpacing(0, 0)
        self.ci.layout.setRowSpacing(start_row, 0)

        # Set color map limits.
        self.cm_min = 0.0
        self.cm_max = 255.0

        # Set default reading order of numpy array data to Clike.
        self._reading_order = ReadingOrder.Clike

        # Make a right-click menu for changing the color map.
        self.cm_group = QActionGroup(self)
        self.cmap_for_action = {}
        for cm in self.color_maps:
            action = self.cm_group.addAction(cmap_names[cm])
            action.setCheckable(True)
            self.cmap_for_action[action] = cm

        # Set the default colormap.
        self._cm_colors = None
        self.colorMap = PyDMColorMap.Inferno

        # Setup the redraw timer.
        self.needs_redraw = False
        self.redraw_timer = QTimer(self)
        self.redraw_timer.timeout.connect(self.redrawImage)
        self._redraw_rate = 30
        self.maxRedrawRate = self._redraw_rate
        self.newImageSignal = self._image_item.sigImageChanged

        # Set Channels.
        self.imageChannel = image_channel
        self.xAxisChannel = xaxis_channel
        self.yAxisChannel = yaxis_channel
        self.ROIOffsetXChannel = roioffsetx_channel
        self.ROIOffsetYChannel = roioffsety_channel
        self.ROIWidthChannel = roiwidth_channel
        self.ROIHeightChannel = roiheight_channel

    # --- Context menu ---
    def widget_ctx_menu(self):
        """
        Fetch the Widget specific context menu.

        It will be populated with additional tools by `assemble_tools_menu`.

        Returns
        -------
        QMenu or None
            If the return of this method is None a new QMenu will be created by
            `assemble_tools_menu`.
        """
        self.menu = ViewBoxMenu(self._view)
        cm_menu = self.menu.addMenu("Color Map")
        for act in self.cmap_for_action.keys():
            cm_menu.addAction(act)
        cm_menu.triggered.connect(self._changeColorMap)
        return self.menu

    # --- Colormap methods ---
    def _changeColorMap(self, action):
        """
        Method invoked by the colormap Action Menu.

        Changes the current colormap used to render the image.

        Parameters
        ----------
        action : QAction
        """
        self.colorMap = self.cmap_for_action[action]

    @Property(float)
    def colorMapMin(self):
        """
        Minimum value for the colormap.

        Returns
        -------
        float
        """
        return self.cm_min

    @colorMapMin.setter
    @Slot(float)
    def colorMapMin(self, new_min):
        """
        Set the minimum value for the colormap.

        Parameters
        ----------
        new_min : float
        """
        if self.cm_min != new_min:
            self.cm_min = new_min
            if self.cm_min > self.cm_max:
                self.cm_max = self.cm_min

    @Property(float)
    def colorMapMax(self):
        """
        Maximum value for the colormap.

        Returns
        -------
        float
        """
        return self.cm_max

    @colorMapMax.setter
    @Slot(float)
    def colorMapMax(self, new_max):
        """
        Set the maximum value for the colormap.

        Parameters
        ----------
        new_max : float
        """
        if self.cm_max != new_max:
            self.cm_max = new_max
            if self.cm_max < self.cm_min:
                self.cm_min = self.cm_max

    def setColorMapLimits(self, mn, mx):
        """
        Set the limit values for the colormap.

        Parameters
        ----------
        mn : int
            The lower limit
        mx : int
            The upper limit
        """
        if mn >= mx:
            return
        self.cm_max = mx
        self.cm_min = mn

    @Property(PyDMColorMap)
    def colorMap(self):
        """
        Return the color map used by the SpectrogramView.

        Returns
        -------
        PyDMColorMap
        """
        return self._colormap

    @colorMap.setter
    def colorMap(self, new_cmap):
        """
        Set the color map used by the SpectrogramView.

        Parameters
        -------
        new_cmap : PyDMColorMap
        """
        self._colormap = new_cmap
        self._cm_colors = self.color_maps[new_cmap]
        self.setColorMap()
        for action in self.cm_group.actions():
            if self.cmap_for_action[action] == self._colormap:
                action.setChecked(True)
            else:
                action.setChecked(False)

    def setColorMap(self, cmap=None):
        """
        Update the image colormap.

        Parameters
        ----------
        cmap : ColorMap
        """
        if not cmap:
            if not self._cm_colors.any():
                return
            # Take default values
            pos = np.linspace(0.0, 1.0, num=len(self._cm_colors))
            cmap = ColorMap(pos, self._cm_colors)
        self._view.setBackgroundColor(cmap.map(0))
        lut = cmap.getLookupTable(0.0, 1.0, alpha=False)
        self.colorbar.setIntColorScale(colors=lut)
        self._image_item.setLookupTable(lut)

    # --- Connection Slots ---
    @Slot(bool)
    def image_connection_state_changed(self, conn):
        """
        Callback invoked when the Image Channel connection state is changed.

        Parameters
        ----------
        conn : bool
            The new connection state.
        """
        if conn:
            self.redraw_timer.start()
        else:
            self.redraw_timer.stop()

    @Slot(bool)
    def yaxis_connection_state_changed(self, connected):
        """
        Callback invoked when the TimeAxis Channel connection state is changed.

        Parameters
        ----------
        conn : bool
            The new connection state.
        """
        self._timeaxis_connected = connected

    @Slot(bool)
    def roioffsetx_connection_state_changed(self, conn):
        """
        Run when the ROIOffsetX Channel connection state changes.

        Parameters
        ----------
        conn : bool
            The new connection state.

        """
        if not conn:
            self._roi_offsetx = 0

    @Slot(bool)
    def roioffsety_connection_state_changed(self, conn):
        """
        Run when the ROIOffsetY Channel connection state changes.

        Parameters
        ----------
        conn : bool
            The new connection state.

        """
        if not conn:
            self._roi_offsety = 0

    @Slot(bool)
    def roiwidth_connection_state_changed(self, conn):
        """
        Run when the ROIWidth Channel connection state changes.

        Parameters
        ----------
        conn : bool
            The new connection state.

        """
        if not conn:
            self._roi_width = 0

    @Slot(bool)
    def roiheight_connection_state_changed(self, conn):
        """
        Run when the ROIHeight Channel connection state changes.

        Parameters
        ----------
        conn : bool
            The new connection state.

        """
        if not conn:
            self._roi_height = 0

    # --- Value Slots ---
    @Slot(np.ndarray)
    def image_value_changed(self, new_image):
        """
        Callback invoked when the Image Channel value is changed.

        We try to do as little as possible in this method, because it
        gets called every time the image channel updates, which might
        be extremely often.  Basically just store the data, and set
        a flag requesting that the image be redrawn.

        Parameters
        ----------
        new_image : np.ndarray
            The new image data.  This can be a flat 1D array, or a 2D array.
        """
        if new_image is None or new_image.size == 0:
            return
        logging.debug("SpectrogramView Received New Image: Needs Redraw->True")
        self.image_waveform = new_image
        self.needs_redraw = True
        if not self._image_height and self._image_width:
            self._image_height = new_image.size / self._image_width
        elif not self._image_width and self._image_height:
            self._image_width = new_image.size / self._image_height

    @Slot(np.ndarray)
    @Slot(float)
    def xaxis_value_changed(self, new_array):
        """
        Callback invoked when the Image Width Channel value is changed.

        Parameters
        ----------
        new_array : np.ndarray
            The new x axis array
        """
        if new_array is None:
            return
        if isinstance(new_array, float):
            new_array = np.array([
                new_array,
            ])
        self._last_xaxis_data = new_array
        if self._reading_order == self.Clike:
            self._image_width = new_array.size
        else:
            self._image_height = new_array.size
        self.needs_redraw = True

    @Slot(np.ndarray)
    @Slot(float)
    def yaxis_value_changed(self, new_array):
        """
        Callback invoked when the TimeAxis Channel value is changed.

        Parameters
        ----------
        new_array : np.array
            The new y axis array
        """
        if new_array is None:
            return
        if isinstance(new_array, float):
            new_array = np.array([
                new_array,
            ])
        self._last_yaxis_data = new_array
        if self._reading_order == self.Fortranlike:
            self._image_width = new_array.size
        else:
            self._image_height = new_array.size
        self.needs_redraw = True

    @Slot(int)
    def roioffsetx_value_changed(self, new_offset):
        """
        Run when the ROIOffsetX Channel value changes.

        Parameters
        ----------
        new_offsetx : int
            The new image ROI horizontal offset

        """
        if new_offset is None:
            return
        self._roi_offsetx = new_offset
        self.redrawROI()

    @Slot(int)
    def roioffsety_value_changed(self, new_offset):
        """
        Run when the ROIOffsetY Channel value changes.

        Parameters
        ----------
        new_offsety : int
            The new image ROI vertical offset

        """
        if new_offset is None:
            return
        self._roi_offsety = new_offset
        self.redrawROI()

    @Slot(int)
    def roiwidth_value_changed(self, new_width):
        """
        Run when the ROIWidth Channel value changes.

        Parameters
        ----------
        new_width : int
            The new image ROI width

        """
        if new_width is None:
            return
        self._roi_width = int(new_width)
        self.redrawROI()

    @Slot(int)
    def roiheight_value_changed(self, new_height):
        """
        Run when the ROIHeight Channel value changes.

        Parameters
        ----------
        new_height : int
            The new image ROI height

        """
        if new_height is None:
            return
        self._roi_height = int(new_height)
        self.redrawROI()

    # --- Image update methods ---
    def process_image(self, image):
        """
        Boilerplate method.

        To be used by applications in order to add calculations and also modify
        the image before it is displayed at the widget.

        .. warning::
           This code runs in a separated QThread so it **MUST** not try to
           write to QWidgets.

        Parameters
        ----------
        image : np.ndarray
            The Image Data as a 2D numpy array

        Returns
        -------
        np.ndarray
            The Image Data as a 2D numpy array after processing.
        """
        return image

    def redrawImage(self):
        """
        Set the image data into the ImageItem, if needed.

        If necessary, reshape the image to 2D first.
        """
        if self.thread is not None and not self.thread.isFinished():
            logger.warning(
                "Image processing has taken longer than the refresh rate.")
            return
        self.thread = SpectrogramUpdateThread(self)
        self.thread.updateSignal.connect(self._updateDisplay)
        logging.debug("SpectrogramView RedrawImage Thread Launched")
        self.thread.start()

    @Slot(list)
    def _updateDisplay(self, data):
        logging.debug("SpectrogramView Update Display with new image")

        # Update axis
        if self._last_xaxis_data is not None:
            szx = self._last_xaxis_data.size
            xMin = self._last_xaxis_data.min()
            xMax = self._last_xaxis_data.max()
        else:
            szx = self.imageWidth if self.readingOrder == self.Clike \
                else self.imageHeight
            xMin = 0
            xMax = szx

        if self._last_yaxis_data is not None:
            szy = self._last_yaxis_data.size
            yMin = self._last_yaxis_data.min()
            yMax = self._last_yaxis_data.max()
        else:
            szy = self.imageHeight if self.readingOrder == self.Clike \
                else self.imageWidth
            yMin = 0
            yMax = szy

        self.xaxis.setRange(xMin, xMax)
        self.yaxis.setRange(yMin, yMax)
        self._view.setLimits(xMin=0,
                             xMax=szx,
                             yMin=0,
                             yMax=szy,
                             minXRange=szx,
                             maxXRange=szx,
                             minYRange=szy,
                             maxYRange=szy)

        # Update image
        if self.autoSetColorbarLims:
            self.colorbar.setLimits(data)
        mini, maxi = data[0], data[1]
        img = data[2]
        self._image_item.setLevels([mini, maxi])
        self._image_item.setImage(img,
                                  autoLevels=False,
                                  autoDownsample=self.autoDownsample)

    # ROI update methods
    def redrawROI(self):
        startx = self._roi_offsetx
        endx = self._roi_offsetx + self._roi_width
        starty = self._roi_offsety
        endy = self._roi_offsety + self._roi_height
        self.ROICurve.setData([startx, startx, endx, endx, startx],
                              [starty, endy, endy, starty, starty])

    def showROI(self, show):
        """Set ROI visibility."""
        pen = mkPen()
        if show:
            pen.setColor(self.ROIColor)
        else:
            pen.setColor(QColor('transparent'))
        self.ROICurve.setPen(pen)

    # --- Properties ---
    @Property(bool)
    def autoDownsample(self):
        """
        Return if we should or not apply the autoDownsample option.

        Return
        ------
        bool
        """
        return self._auto_downsample

    @autoDownsample.setter
    def autoDownsample(self, new_value):
        """
        Whether we should or not apply the autoDownsample option.

        Parameters
        ----------
        new_value: bool
        """
        if new_value != self._auto_downsample:
            self._auto_downsample = new_value

    @Property(bool)
    def autoSetColorbarLims(self):
        """
        Return if we should or not auto set colorbar limits.

        Return
        ------
        bool
        """
        return self._auto_colorbar_lims

    @autoSetColorbarLims.setter
    def autoSetColorbarLims(self, new_value):
        """
        Whether we should or not auto set colorbar limits.

        Parameters
        ----------
        new_value: bool
        """
        if new_value != self._auto_colorbar_lims:
            self._auto_colorbar_lims = new_value

    @Property(int)
    def imageWidth(self):
        """
        Return the width of the image.

        Return
        ------
        int
        """
        return self._image_width

    @imageWidth.setter
    def imageWidth(self, new_width):
        """
        Set the width of the image.

        Can be overridden by :attr:`xAxisChannel` and :attr:`yAxisChannel`.

        Parameters
        ----------
        new_width: int
        """
        boo = self._image_width != int(new_width)
        boo &= not self._xaxischannel
        boo &= not self._yaxischannel
        if boo:
            self._image_width = int(new_width)

    @Property(int)
    def imageHeight(self):
        """
        Return the height of the image.

        Return
        ------
        int
        """
        return self._image_height

    @Property(int)
    def ROIOffsetX(self):
        """
        Return the ROI offset in X axis in pixels.

        Return
        ------
        int
        """
        return self._roi_offsetx

    @ROIOffsetX.setter
    def ROIOffsetX(self, new_offset):
        """
        Set the ROI offset in X axis in pixels.

        Can be overridden by :attr:`ROIOffsetXChannel`.

        Parameters
        ----------
        new_offset: int
        """
        if new_offset is None:
            return
        boo = self._roi_offsetx != int(new_offset)
        boo &= not self._roioffsetxchannel
        if boo:
            self._roi_offsetx = int(new_offset)
            self.redrawROI()

    @Property(int)
    def ROIOffsetY(self):
        """
        Return the ROI offset in Y axis in pixels.

        Return
        ------
        int
        """
        return self._roi_offsety

    @ROIOffsetY.setter
    def ROIOffsetY(self, new_offset):
        """
        Set the ROI offset in Y axis in pixels.

        Can be overridden by :attr:`ROIOffsetYChannel`.

        Parameters
        ----------
        new_offset: int
        """
        if new_offset is None:
            return
        boo = self._roi_offsety != int(new_offset)
        boo &= not self._roioffsetychannel
        if boo:
            self._roi_offsety = int(new_offset)
            self.redrawROI()

    @Property(int)
    def ROIWidth(self):
        """
        Return the ROI width in pixels.

        Return
        ------
        int
        """
        return self._roi_width

    @ROIWidth.setter
    def ROIWidth(self, new_width):
        """
        Set the ROI width in pixels.

        Can be overridden by :attr:`ROIWidthChannel`.

        Parameters
        ----------
        new_width: int
        """
        if new_width is None:
            return
        boo = self._roi_width != int(new_width)
        boo &= not self._roiwidthchannel
        if boo:
            self._roi_width = int(new_width)
            self.redrawROI()

    @Property(int)
    def ROIHeight(self):
        """
        Return the ROI height in pixels.

        Return
        ------
        int
        """
        return self._roi_height

    @ROIHeight.setter
    def ROIHeight(self, new_height):
        """
        Set the ROI height in pixels.

        Can be overridden by :attr:`ROIHeightChannel`.

        Parameters
        ----------
        new_height: int
        """
        if new_height is None:
            return
        boo = self._roi_height != int(new_height)
        boo &= not self._roiheightchannel
        if boo:
            self._roi_height = int(new_height)
            self.redrawROI()

    @Property(bool)
    def normalizeData(self):
        """
        Return True if the colors are relative to data maximum and minimum.

        Returns
        -------
        bool
        """
        return self._normalize_data

    @normalizeData.setter
    @Slot(bool)
    def normalizeData(self, new_norm):
        """
        Define if the colors are relative to minimum and maximum of the data.

        Parameters
        ----------
        new_norm: bool
        """
        if self._normalize_data != new_norm:
            self._normalize_data = new_norm

    @Property(ReadingOrder)
    def readingOrder(self):
        """
        Return the reading order of the :attr:`imageChannel` array.

        Returns
        -------
        ReadingOrder
        """
        return self._reading_order

    @readingOrder.setter
    def readingOrder(self, order):
        """
        Set reading order of the :attr:`imageChannel` array.

        Parameters
        ----------
        order: ReadingOrder
        """
        if self._reading_order != order:
            self._reading_order = order

        if order == self.Clike:
            if self._last_xaxis_data is not None:
                self._image_width = self._last_xaxis_data.size
            if self._last_yaxis_data is not None:
                self._image_height = self._last_yaxis_data.size
        elif order == self.Fortranlike:
            if self._last_yaxis_data is not None:
                self._image_width = self._last_yaxis_data.size
            if self._last_xaxis_data is not None:
                self._image_height = self._last_xaxis_data.size

    @Property(int)
    def maxRedrawRate(self):
        """
        The maximum rate (in Hz) at which the plot will be redrawn.

        The plot will not be redrawn if there is not new data to draw.

        Returns
        -------
        int
        """
        return self._redraw_rate

    @maxRedrawRate.setter
    def maxRedrawRate(self, redraw_rate):
        """
        The maximum rate (in Hz) at which the plot will be redrawn.

        The plot will not be redrawn if there is not new data to draw.

        Parameters
        -------
        redraw_rate : int
        """
        self._redraw_rate = redraw_rate
        self.redraw_timer.setInterval(int((1.0 / self._redraw_rate) * 1000))

    # --- Events rederivations ---
    def keyPressEvent(self, ev):
        """Handle keypress events."""
        return

    def mouseMoveEvent(self, ev):
        if not self._image_item.width() or not self._image_item.height():
            super().mouseMoveEvent(ev)
            return
        pos = ev.pos()
        posaux = self._image_item.mapFromDevice(ev.pos())
        if posaux.x() < 0 or posaux.x() >= self._image_item.width() or \
                posaux.y() < 0 or posaux.y() >= self._image_item.height():
            super().mouseMoveEvent(ev)
            return

        pos_scene = self._view.mapSceneToView(pos)
        x = round(pos_scene.x())
        y = round(pos_scene.y())

        if self.xAxisChannel and self._last_xaxis_data is not None:
            maxx = len(self._last_xaxis_data) - 1
            x = x if x < maxx else maxx
            valx = self._last_xaxis_data[x]
        else:
            valx = x

        if self.yAxisChannel and self._last_yaxis_data is not None:
            maxy = len(self._last_yaxis_data) - 1
            y = y if y < maxy else maxy
            valy = self._last_yaxis_data[y]
        else:
            valy = y

        txt = self.format_tooltip.format(valx, valy)
        QToolTip.showText(self.mapToGlobal(pos), txt, self, self.geometry(),
                          5000)
        super().mouseMoveEvent(ev)

    # --- Channels ---
    @Property(str)
    def imageChannel(self):
        """
        The channel address in use for the image data .

        Returns
        -------
        str
            Channel address
        """
        if self._imagechannel:
            return str(self._imagechannel.address)
        else:
            return ''

    @imageChannel.setter
    def imageChannel(self, value):
        """
        The channel address in use for the image data .

        Parameters
        ----------
        value : str
            Channel address
        """
        if self._imagechannel != value:
            # Disconnect old channel
            if self._imagechannel:
                self._imagechannel.disconnect()
            # Create and connect new channel
            self._imagechannel = PyDMChannel(
                address=value,
                connection_slot=self.image_connection_state_changed,
                value_slot=self.image_value_changed,
                severity_slot=self.alarmSeverityChanged)
            self._channels[0] = self._imagechannel
            self._imagechannel.connect()

    @Property(str)
    def xAxisChannel(self):
        """
        The channel address in use for the x-axis of image.

        Returns
        -------
        str
            Channel address
        """
        if self._xaxischannel:
            return str(self._xaxischannel.address)
        else:
            return ''

    @xAxisChannel.setter
    def xAxisChannel(self, value):
        """
        The channel address in use for the x-axis of image.

        Parameters
        ----------
        value : str
            Channel address
        """
        if self._xaxischannel != value:
            # Disconnect old channel
            if self._xaxischannel:
                self._xaxischannel.disconnect()
            # Create and connect new channel
            self._xaxischannel = PyDMChannel(
                address=value,
                connection_slot=self.connectionStateChanged,
                value_slot=self.xaxis_value_changed,
                severity_slot=self.alarmSeverityChanged)
            self._channels[1] = self._xaxischannel
            self._xaxischannel.connect()

    @Property(str)
    def yAxisChannel(self):
        """
        The channel address in use for the time axis.

        Returns
        -------
        str
            Channel address
        """
        if self._yaxischannel:
            return str(self._yaxischannel.address)
        else:
            return ''

    @yAxisChannel.setter
    def yAxisChannel(self, value):
        """
        The channel address in use for the time axis.

        Parameters
        ----------
        value : str
            Channel address
        """
        if self._yaxischannel != value:
            # Disconnect old channel
            if self._yaxischannel:
                self._yaxischannel.disconnect()
            # Create and connect new channel
            self._yaxischannel = PyDMChannel(
                address=value,
                connection_slot=self.yaxis_connection_state_changed,
                value_slot=self.yaxis_value_changed,
                severity_slot=self.alarmSeverityChanged)
            self._channels[2] = self._yaxischannel
            self._yaxischannel.connect()

    @Property(str)
    def ROIOffsetXChannel(self):
        """
        Return the channel address in use for the image ROI horizontal offset.

        Returns
        -------
        str
            Channel address

        """
        if self._roioffsetxchannel:
            return str(self._roioffsetxchannel.address)
        else:
            return ''

    @ROIOffsetXChannel.setter
    def ROIOffsetXChannel(self, value):
        """
        Return the channel address in use for the image ROI horizontal offset.

        Parameters
        ----------
        value : str
            Channel address

        """
        if self._roioffsetxchannel != value:
            # Disconnect old channel
            if self._roioffsetxchannel:
                self._roioffsetxchannel.disconnect()
            # Create and connect new channel
            self._roioffsetxchannel = PyDMChannel(
                address=value,
                connection_slot=self.roioffsetx_connection_state_changed,
                value_slot=self.roioffsetx_value_changed,
                severity_slot=self.alarmSeverityChanged)
            self._channels[3] = self._roioffsetxchannel
            self._roioffsetxchannel.connect()

    @Property(str)
    def ROIOffsetYChannel(self):
        """
        Return the channel address in use for the image ROI vertical offset.

        Returns
        -------
        str
            Channel address

        """
        if self._roioffsetychannel:
            return str(self._roioffsetychannel.address)
        else:
            return ''

    @ROIOffsetYChannel.setter
    def ROIOffsetYChannel(self, value):
        """
        Return the channel address in use for the image ROI vertical offset.

        Parameters
        ----------
        value : str
            Channel address

        """
        if self._roioffsetychannel != value:
            # Disconnect old channel
            if self._roioffsetychannel:
                self._roioffsetychannel.disconnect()
            # Create and connect new channel
            self._roioffsetychannel = PyDMChannel(
                address=value,
                connection_slot=self.roioffsety_connection_state_changed,
                value_slot=self.roioffsety_value_changed,
                severity_slot=self.alarmSeverityChanged)
            self._channels[4] = self._roioffsetychannel
            self._roioffsetychannel.connect()

    @Property(str)
    def ROIWidthChannel(self):
        """
        Return the channel address in use for the image ROI width.

        Returns
        -------
        str
            Channel address

        """
        if self._roiwidthchannel:
            return str(self._roiwidthchannel.address)
        else:
            return ''

    @ROIWidthChannel.setter
    def ROIWidthChannel(self, value):
        """
        Return the channel address in use for the image ROI width.

        Parameters
        ----------
        value : str
            Channel address

        """
        if self._roiwidthchannel != value:
            # Disconnect old channel
            if self._roiwidthchannel:
                self._roiwidthchannel.disconnect()
            # Create and connect new channel
            self._roiwidthchannel = PyDMChannel(
                address=value,
                connection_slot=self.roiwidth_connection_state_changed,
                value_slot=self.roiwidth_value_changed,
                severity_slot=self.alarmSeverityChanged)
            self._channels[5] = self._roiwidthchannel
            self._roiwidthchannel.connect()

    @Property(str)
    def ROIHeightChannel(self):
        """
        Return the channel address in use for the image ROI height.

        Returns
        -------
        str
            Channel address

        """
        if self._roiheightchannel:
            return str(self._roiheightchannel.address)
        else:
            return ''

    @ROIHeightChannel.setter
    def ROIHeightChannel(self, value):
        """
        Return the channel address in use for the image ROI height.

        Parameters
        ----------
        value : str
            Channel address

        """
        if self._roiheightchannel != value:
            # Disconnect old channel
            if self._roiheightchannel:
                self._roiheightchannel.disconnect()
            # Create and connect new channel
            self._roiheightchannel = PyDMChannel(
                address=value,
                connection_slot=self.roiheight_connection_state_changed,
                value_slot=self.roiheight_value_changed,
                severity_slot=self.alarmSeverityChanged)
            self._channels[6] = self._roiheightchannel
            self._roiheightchannel.connect()

    def channels(self):
        """
        Return the channels being used for this Widget.

        Returns
        -------
        channels : list
            List of PyDMChannel objects
        """
        return self._channels

    def channels_for_tools(self):
        """Return channels for tools."""
        return [self._imagechannel]
Пример #24
0
    def plotData(self, plotItem, selectedItems):
        '''selectedItems: items selected in tree view
           dfData: data frame of the selected data
        '''

        #plotItem = self.dataPlot.plotItem

        # viewbox = pg.ViewBox()
        # plotItem.scene().addItem(viewbox)

        #plotItem = self.currSelctPlotWgt
        plotItem.addLegend()

        #plotItem.getAxis('bottom').setPen(pg.mkPen(color='#000000', width=1))
        i = 0
        for iItem in selectedItems:
            if iItem.parent():     # not the root item
                filename = iItem.parent().text(1)    # get the parent item name - filename

                for iData in self.lTestDATA:          # find out the data from the data frame list by the filename
                    if filename == iData.fileName:
                        dfData = iData.data
                        break                       # break out of the loop for data


                data_head = iItem.text(1)           # get the column name of data for plotting
                curve_name = data_head + '>>' + iItem.text(2) + '>>' + iItem.text(3)    # parameter/parameter desc/unit

                # y axis
                data_2_plot = list(dfData[data_head])

                # get the list of time column, for x axis
                sTime = list(dfData['TIME'])

                # convert the time in string to date time object
                iTime = [self.sTimeToDateTime(j) for j in sTime]

                i += 1  # for color index use

                # example
                # pw.plot(x=[x.timestamp() for x in iTime ], y= list(df['BCVIIN']), pen = 'r')
                try:
                    plotcurve = PlotCurveItem(x=[x.timestamp() for x in iTime], y= data_2_plot, name = curve_name, pen=self.colorDex[i%5])
                    plotItem.addItem(plotcurve)
                except Exception as e:
                    QMessageBox.critical(self, "Error", "Error with data to plot.\n" + e.__str__())

                if not self.bPlotted:
                    self.bPlotted = True
                plotWgtName = self.currSelctPlotWgt.getViewBox().name
                if not plotWgtName: print("check the plotwidget definition in the mainUI.py, comment it!!!!")
                self.lPlottedItems.append({'Plot': plotWgtName, 'Curvename': curve_name, 'Filename': filename })
                self.listWidget.addItem(plotWgtName + '||' + curve_name + '||' + filename )

                # labl = QLabel(curve_name)
                # plotItem.addItem(labl)

                for lgditem in plotItem.scene().items():  # remove the legend
                    if isinstance(lgditem, graphicsItems.LegendItem.ItemSample):  #
                        lgditem.hide()   # hide the sample of legend  # plotItem.scene().items()[5].item is the curve itself
                        break

                self.autoRangeAllWins()
Пример #25
0
class CurveItem:
    """Represents a curve to be plotted in a diagram."""

    SignalAppearance = namedtuple('SignalAppearance',
                                  ['pen_color', 'pen_width', 'pen_style'])

    colors = [
        SignalAppearance(QtGui.QColor(255, 255, 0), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(255, 0, 0), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(0, 255, 0), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(255, 255, 255), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(51, 153, 255), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(0, 255, 255), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(255, 0, 255), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(204, 153, 102), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(0, 0, 255), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(0, 255, 0), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(255, 204, 0), 1,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(153, 255, 153), 2,
                         QtCore.Qt.DotLine),
        SignalAppearance(QtGui.QColor(255, 170, 0), 2,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 0, 0), 2,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(0, 255, 255), 1,
                         QtCore.Qt.DotLine),
        SignalAppearance(QtGui.QColor(255, 170, 255), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(127, 255, 127), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 255, 127), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 0, 0), 2,
                         QtCore.Qt.DotLine),
        SignalAppearance(QtGui.QColor(255, 0, 0), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(0, 255, 0), 2,
                         QtCore.Qt.DotLine),
        SignalAppearance(QtGui.QColor(255, 255, 255), 2,
                         QtCore.Qt.SolidLine),
        SignalAppearance(QtGui.QColor(51, 153, 255), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 0, 255), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 153, 204), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(204, 153, 102), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 204, 0), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 0, 255), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 153, 204), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(204, 153, 102), 1,
                         QtCore.Qt.DashLine),
        SignalAppearance(QtGui.QColor(255, 204, 0), 1,
                         QtCore.Qt.DashLine)
    ]

    def __init__(self, subscription_id, driver_addr, sig_name, y_axis,
                 color_idx):
        """
        Initializes an instance of class CurveItem.

        driver_addr - IcePAP driver address.
        sig_name    - Signal name.
        y_axis      - Y axis to plot against.
        """
        self.subscription_id = subscription_id
        self.driver_addr = driver_addr
        self.signal_name = sig_name
        self.y_axis = y_axis
        self.array_time = []
        self.array_val = []
        self.val_min = 0
        self.val_max = 0
        col_item = self.colors[color_idx]
        self.color = col_item.pen_color
        self.pen = {'color': col_item.pen_color,
                    'width': col_item.pen_width,
                    'style': col_item.pen_style}
        self.curve = None
        self.lock = RLock()
        self.signature = ''
        self.update_signature()

    def update_signature(self):
        """Sets the new value of the signature string."""
        self.signature = '{}:{}:{}'.format(self.driver_addr,
                                           self.signal_name,
                                           self.y_axis)

    def create_curve(self):
        """Creates a new plot item."""
        with self.lock:
            self.curve = PlotCurveItem(x=self.array_time,
                                       y=self.array_val,
                                       pen=self.pen)
        return self.curve

    def update_curve(self, time_min, time_max):
        """Updates the curve with recent collected data."""
        with self.lock:
            idx_min = self.get_time_index(time_min)
            idx_max = self.get_time_index(time_max)
            self.curve.setData(x=self.array_time[idx_min:idx_max],
                               y=self.array_val[idx_min:idx_max])

    def in_range(self, t):
        """
        Check to see if time is within range of collected data.

        t - Time value.
        Return: True if time is within range of collected data.
                Otherwise False.
        """
        with self.lock:
            if self.array_time and \
                    self.array_time[0] < t < self.array_time[-1]:
                return True
        return False

    def start_time(self):
        """
        Get time for first data sample.

        Return: Time of the first collected data sample. -1 if none.
        """
        with self.lock:
            if self.array_time:
                return self.array_time[0]
        return -1

    def collect(self, new_data):
        """Store new collected data."""
        with self.lock:
            if not self.array_val:
                self.val_min = self.val_max = new_data[0][1]
            for t, v in new_data:
                self.array_time.append(t)
                self.array_val.append(v)
                if v > self.val_max:
                    self.val_max = v
                elif v < self.val_min:
                    self.val_min = v

    def get_y(self, time_val):
        """
        Retrieve the signal value corresponding to the provided time value.

        t_val - Time value.
        Return: Signal value corresponding to an adjacent sample in time.
        """
        with self.lock:
            idx = self.get_time_index(time_val)
            return self.array_val[idx]

    def clear(self):
        self.array_time[:] = []
        self.array_val[:] = []

    def get_time_index(self, time_val):
        """
        Retrieve the sample index corresponding to the provided time value.

        t_val - Time value.
        Return: Index of a sample adjacent to the provided time value.
        """
        with self.lock:
            if not self.array_time:
                return -1
            if len(self.array_time) == 1:
                return 0
            time_min = self.array_time[0]
            time_max = self.array_time[-1]
            if time_val < time_min:
                return 0
            elif time_val > time_max:
                return len(self.array_time)
            delta_t = time_max - time_min
            t = time_val - time_min
            idx = int((t / delta_t) * len(self.array_time))
            while self.array_time[idx] > time_val:
                idx -= 1
            while self.array_time[idx] < time_val:
                idx += 1
            return idx
Пример #26
0
class HistogramItem(GraphicsWidget):
    """
    This is a graphicsWidget which provides controls for adjusting the display of an image.

    Includes:

    - Image histogram 
    - Movable region over histogram to select black/white levels

    Parameters
    ----------
    image : ImageItem or None
        If *image* is provided, then the control will be automatically linked to
        the image and changes to the control will be immediately reflected in
        the image's appearance.
    fillHistogram : bool
        By default, the histogram is rendered with a fill.
        For performance, set *fillHistogram* = False.
    """

    sigLevelsChanged = pyqtSignal(object)
    sigLevelChangeFinished = pyqtSignal(object)

    def __init__(self, image=None, fillHistogram=True, bounds: tuple = None):
        GraphicsWidget.__init__(self)
        self.imageItem = lambda: None  # fake a dead weakref

        self.layout = QGraphicsGridLayout()
        self.setLayout(self.layout)
        self.layout.setContentsMargins(1, 1, 1, 1)
        self.layout.setSpacing(0)
        self.vb = ViewBox(parent=self)
        # self.vb.setMaximumHeight(152)
        # self.vb.setMinimumWidth(45)
        self.vb.setMouseEnabled(x=True, y=False)

        self.region = LinearRegionItem([0, 1], 'vertical', swapMode='block', bounds=bounds)
        self.region.setZValue(1000)
        self.vb.addItem(self.region)
        self.region.lines[0].addMarker('<|', 0.5)
        self.region.lines[1].addMarker('|>', 0.5)
        self.region.sigRegionChanged.connect(self.regionChanging)
        self.region.sigRegionChangeFinished.connect(self.regionChanged)

        self.axis = AxisItem('bottom', linkView=self.vb, maxTickLength=-10, parent=self)
        self.layout.addItem(self.axis, 1, 0)
        self.layout.addItem(self.vb, 0, 0)
        self.range = None
        self.vb.sigRangeChanged.connect(self.viewRangeChanged)

        self.plot = PlotCurveItem(pen=(200, 200, 200, 100))
        # self.plot.rotate(90)
        self.vb.addItem(self.plot)

        self.fillHistogram(fillHistogram)
        self._showRegions()

        self.autoHistogramRange()

        if image is not None:
            self.setImageItem(image)

    def fillHistogram(self, fill=True, level=0.0, color=(100, 100, 200)):
        if fill:
            self.plot.setFillLevel(level)
            self.plot.setBrush(color)
        else:
            self.plot.setFillLevel(None)


    def paint(self, p, *args):
        rgn = self.getLevels()
        self.vb.mapFromViewToItem(self, Point(self.vb.viewRect().center().x(), rgn[0]))
        self.vb.mapFromViewToItem(self, Point(self.vb.viewRect().center().x(), rgn[1]))


    def setHistogramRange(self, mn, mx, padding=0.1):
        """Set the Y range on the histogram plot. This disables auto-scaling."""
        self.vb.enableAutoRange(self.vb.XAxis, False)
        self.vb.setYRange(mn, mx, padding)

    def autoHistogramRange(self):
        """Enable auto-scaling on the histogram plot."""
        self.vb.enableAutoRange(self.vb.XYAxes)

    def setImageItem(self, img):
        """Set an ImageItem to have its levels and LUT automatically controlled
        by this HistogramLUTItem.
        """
        self.imageItem = weakref.ref(img)
        img.sigImageChanged.connect(self.imageChanged)
        self.regionChanged()
        self.imageChanged(autoLevel=True)

    def viewRangeChanged(self):
        self.update()

    def regionChanged(self):
        if self.imageItem() is not None:
            self.imageItem().setLevels(self.getLevels())
        self.sigLevelChangeFinished.emit(self)

    def regionChanging(self):
        if self.imageItem() is not None:
            self.imageItem().setLevels(self.getLevels())
        self.sigLevelsChanged.emit(self)
        self.update()

    def imageChanged(self, autoLevel=False):
        if self.imageItem() is None:
            return

        self.plot.setVisible(True)
        # plot one histogram for all image data
        h = self.imageItem().getHistogram()
        if h[0] is None:
            return
        self.plot.setData(*h)
        if autoLevel:
            mn = h[0][0]
            mx = h[0][-1]
            self.region.setRegion([mn, mx])
        else:
            mn, mx = self.imageItem().levels
            self.region.setRegion([mn, mx])

    def getLevels(self):
        """
        Return the min and max levels.
        """
        return self.region.getRegion()

    def setLevels(self, min=None, max=None):
        """
        Set the min/max (bright and dark) levels.
        """
        assert None not in (min, max)
        self.region.setRegion((min, max))

    def _showRegions(self):
        self.region.setVisible(True)

    def saveState(self):
        return {
            'levels': self.getLevels(),
        }

    def restoreState(self, state):
        self.setLevels(*state['levels'])
Пример #27
0
class SiriusProcessImage(QWidget):
    def __init__(self, parent=None, device='', convertion_set=True,
                 orientation='V'):
        super().__init__(parent)
        self._dev = SiriusPVName(device)
        self._conv_set = convertion_set
        self._ori = orientation
        self._setupUi()

    def _setupUi(self):
        self.image_view = PyDMImageView(
            parent=self,
            image_channel=self._dev+':Image-RB',
            width_channel=self._dev+':Width-RB')
        self.image_view.setObjectName('image')
        self.image_view.setStyleSheet(
            '#image{min-width:20em; min-height:20em;}')
        self.image_view.maxRedrawRate = 5
        self.image_view.colorMap = self.image_view.Jet
        self.image_view.readingOrder = self.image_view.Clike
        self._roixproj = SiriusConnectionSignal(self._dev+':ROIProjX-Mon')
        self._roiyproj = SiriusConnectionSignal(self._dev+':ROIProjY-Mon')
        self._roixfit = SiriusConnectionSignal(self._dev+':ROIGaussFitX-Mon')
        self._roiyfit = SiriusConnectionSignal(self._dev+':ROIGaussFitY-Mon')
        self._roixaxis = SiriusConnectionSignal(self._dev+':ROIAxisX-Mon')
        self._roiyaxis = SiriusConnectionSignal(self._dev+':ROIAxisY-Mon')
        self._roistartx = SiriusConnectionSignal(self._dev+':ROIStartX-Mon')
        self._roistarty = SiriusConnectionSignal(self._dev+':ROIStartY-Mon')
        self._roiendx = SiriusConnectionSignal(self._dev+':ROIEndX-Mon')
        self._roiendy = SiriusConnectionSignal(self._dev+':ROIEndY-Mon')
        self._roixproj.new_value_signal[np.ndarray].connect(self._update_roi)
        self.plt_roi = PlotCurveItem([0, 0, 500, 500, 0], [0, 500, 500, 0, 0])
        pen = mkPen()
        pen.setColor(QColor('red'))
        pen.setWidth(1)
        self.plt_roi.setPen(pen)
        self.image_view.addItem(self.plt_roi)
        self.plt_fit_x = PlotCurveItem([0, 0], [0, 400])
        self.plt_fit_y = PlotCurveItem([0, 0], [0, 400])
        self.plt_his_x = PlotCurveItem([0, 0], [0, 400])
        self.plt_his_y = PlotCurveItem([0, 0], [0, 400])
        pen = mkPen()
        pen.setColor(QColor('yellow'))
        self.plt_his_x.setPen(pen)
        self.plt_his_y.setPen(pen)
        self.image_view.addItem(self.plt_fit_x)
        self.image_view.addItem(self.plt_fit_y)
        self.image_view.addItem(self.plt_his_x)
        self.image_view.addItem(self.plt_his_y)

        gb_conf = self._get_config_widget(self)
        gb_posi = self._get_position_widget(self)
        gb_size = self._get_size_widget(self)

        gl = QGridLayout(self)
        gl.setContentsMargins(0, 0, 0, 0)
        if self._ori == 'V':
            gl.addWidget(self.image_view, 0, 0, 1, 2)
            gl.addWidget(gb_posi, 1, 0)
            gl.addWidget(gb_size, 1, 1)
            gl.addWidget(gb_conf, 2, 0, 1, 2)
        else:
            gl.addWidget(self.image_view, 0, 0, 1, 2)
            gl.addWidget(gb_conf, 0, 2, 2, 1)
            gl.addWidget(gb_posi, 1, 0)
            gl.addWidget(gb_size, 1, 1)
            gl.setColumnStretch(0, 5)
            gl.setColumnStretch(1, 5)
            gl.setColumnStretch(2, 1)

    def _get_config_widget(self, parent):
        gb_pos = QGroupBox('Image Processing ', parent)

        meth_sp = PyDMEnumComboBox(
            gb_pos, init_channel=self._dev+':CalcMethod-Sel')
        meth_lb = SiriusLabel(gb_pos, init_channel=self._dev+':CalcMethod-Sts')
        meth_ld = QLabel('Method', gb_pos)

        nrpt_ld = QLabel('Num. Pts.', gb_pos)
        nrpt_sp = SiriusSpinbox(
            gb_pos, init_channel=self._dev+':NrAverages-SP')
        nrpt_sp.showStepExponent = False
        rdb = PyDMLabel(gb_pos, init_channel=self._dev+':NrAverages-RB')
        rdb.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        slsh = QLabel('/', gb_pos, alignment=Qt.AlignCenter)
        slsh.setStyleSheet('min-width:0.7em; max-width:0.7em;')
        cnt = PyDMLabel(gb_pos, init_channel=self._dev+':BufferSize-Mon')
        cnt.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        cnt.setToolTip('Current Buffer Size')
        pbt = PyDMPushButton(
            gb_pos, init_channel=self._dev+':ResetBuffer-Cmd', pressValue=1)
        pbt.setToolTip('Reset Buffer')
        pbt.setIcon(qta.icon('mdi.delete-empty'))
        pbt.setObjectName('rst')
        pbt.setStyleSheet(
            '#rst{min-width:25px; max-width:25px; icon-size:20px;}')
        nrpt_wd = QWidget(gb_pos)
        hbl = QHBoxLayout(nrpt_wd)
        hbl.addWidget(pbt)
        hbl.addStretch()
        hbl.addWidget(cnt)
        hbl.addWidget(slsh)
        hbl.addWidget(rdb)

        rsx_sp = SiriusSpinbox(gb_pos, init_channel=self._dev+':ROISizeX-SP')
        rsx_sp.showStepExponent = False
        rsx_lb = SiriusLabel(gb_pos, init_channel=self._dev+':ROISizeX-RB')
        rsx_ld = QLabel('ROI Size X', gb_pos)

        rsy_sp = SiriusSpinbox(gb_pos, init_channel=self._dev+':ROISizeY-SP')
        rsy_sp.showStepExponent = False
        rsy_lb = SiriusLabel(gb_pos, init_channel=self._dev+':ROISizeY-RB')
        rsy_ld = QLabel('ROI Size Y', gb_pos)

        ra_bt = PyDMStateButton(
            gb_pos, init_channel=self._dev+':ROIAutoCenter-Sel')
        ra_lb = SiriusLabel(
            gb_pos, init_channel=self._dev+':ROIAutoCenter-Sts')
        ra_ld = QLabel('Auto Center:', gb_pos)

        rcx_sp = SiriusSpinbox(gb_pos, init_channel=self._dev+':ROICenterX-SP')
        rcx_sp.showStepExponent = False
        rcx_lb = SiriusLabel(gb_pos, init_channel=self._dev+':ROICenterX-RB')
        rcx_ld = QLabel('ROI Center X', gb_pos)

        rcy_sp = SiriusSpinbox(gb_pos, init_channel=self._dev+':ROICenterY-SP')
        rcy_sp.showStepExponent = False
        rcy_lb = SiriusLabel(gb_pos, init_channel=self._dev+':ROICenterY-RB')
        rcy_ld = QLabel('ROI Center Y', gb_pos)

        sts_bt = QPushButton(qta.icon('fa5s.ellipsis-h'), '', gb_pos)
        sts_bt.setToolTip('Open Detailed Configs')
        sts_bt.setObjectName('sts')
        sts_bt.setStyleSheet(
            '#sts{min-width:25px; max-width:25px; icon-size:20px;}')
        Window = create_window_from_widget(
            _DetailedWidget, title='Image Processing Detailed Configs')
        connect_window(
            sts_bt, Window, gb_pos, device=self._dev,
            convertion_set=self._conv_set)
        hlay = QHBoxLayout()
        hlay.addWidget(sts_bt, alignment=Qt.AlignRight)

        lay = QGridLayout(gb_pos)
        if self._ori == 'V':
            lay.addWidget(meth_ld, 0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(meth_sp, 0, 1)
            lay.addWidget(meth_lb, 1, 1)
            lay.addWidget(nrpt_ld, 2, 0, alignment=Qt.AlignLeft)
            lay.addWidget(nrpt_sp, 2, 1)
            lay.addWidget(nrpt_wd, 3, 0, 1, 2)
            lay.addWidget(rsx_ld, 4+0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rsx_sp, 4+0, 1)
            lay.addWidget(rsx_lb, 4+1, 1)
            lay.addWidget(rsy_ld, 6+0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rsy_sp, 6+0, 1)
            lay.addWidget(rsy_lb, 6+1, 1)
            lay.addWidget(sts_bt, 0, 0+4, alignment=Qt.AlignRight)
            lay.addWidget(ra_ld, 2+0, 0+3, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(ra_bt, 2+0, 1+3)
            lay.addWidget(ra_lb, 2+1, 1+3, alignment=Qt.AlignLeft)
            lay.addWidget(rcx_ld, 4+0, 0+3, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rcx_sp, 4+0, 1+3)
            lay.addWidget(rcx_lb, 4+1, 1+3)
            lay.addWidget(rcy_ld, 6+0, 0+3, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rcy_sp, 6+0, 1+3)
            lay.addWidget(rcy_lb, 6+1, 1+3)
        else:
            lay.addWidget(meth_ld, 0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(meth_sp, 0, 1)
            lay.addWidget(meth_lb, 1, 1)
            lay.addWidget(nrpt_ld, 2, 0, alignment=Qt.AlignLeft)
            lay.addWidget(nrpt_sp, 2, 1)
            lay.addWidget(nrpt_wd, 3, 0, 1, 2)
            lay.addWidget(rsx_ld, 4+0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rsx_sp, 4+0, 1)
            lay.addWidget(rsx_lb, 4+1, 1)
            lay.addWidget(rsy_ld, 6+0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rsy_sp, 6+0, 1)
            lay.addWidget(rsy_lb, 6+1, 1)
            lay.addWidget(ra_ld, 8+0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(ra_bt, 8+0, 1)
            lay.addWidget(ra_lb, 8+1, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rcx_ld, 10+0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rcx_sp, 10+0, 1)
            lay.addWidget(rcx_lb, 10+1, 1)
            lay.addWidget(rcy_ld, 12+0, 0, 2, 1, alignment=Qt.AlignLeft)
            lay.addWidget(rcy_sp, 12+0, 1)
            lay.addWidget(rcy_lb, 12+1, 1)
            lay.addWidget(sts_bt, 14, 0, alignment=Qt.AlignLeft)
            lay.setRowStretch(15, 5)

        return gb_pos

    def _get_position_widget(self, parent):
        gb_posi = QGroupBox('Position [px / mm]', parent)
        fl_posi = QFormLayout(gb_posi)

        wid = QWidget(gb_posi)
        wid.setLayout(QHBoxLayout())
        xave = SiriusLabel(wid, init_channel=self._dev+':BeamCenterX-Mon')
        xavemm = SiriusLabel(wid, init_channel=self._dev+':BeamCentermmX-Mon')
        xave.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        xavemm.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
        sep = QLabel('/', wid)
        sep.setStyleSheet('max-width:0.7em;')
        wid.layout().addWidget(xave)
        wid.layout().addWidget(sep)
        wid.layout().addWidget(xavemm)
        fl_posi.addRow(QLabel(
            'X =', gb_posi, alignment=Qt.AlignBottom), wid)

        wid = QWidget(gb_posi)
        wid.setLayout(QHBoxLayout())
        yave = SiriusLabel(wid, init_channel=self._dev+':BeamCenterY-Mon')
        yavemm = SiriusLabel(wid, init_channel=self._dev+':BeamCentermmY-Mon')
        yave.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        yavemm.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
        sep = QLabel('/', wid)
        sep.setStyleSheet('max-width:0.7em;')
        wid.layout().addWidget(yave)
        wid.layout().addWidget(sep)
        wid.layout().addWidget(yavemm)
        fl_posi.addRow(QLabel(
            'Y =', gb_posi, alignment=Qt.AlignBottom), wid)

        return gb_posi

    def _get_size_widget(self, parent):
        gb_size = QGroupBox('Size [px / mm]', parent)
        fl_size = QFormLayout(gb_size)

        wid = QWidget(gb_size)
        wid.setLayout(QHBoxLayout())
        xave = SiriusLabel(wid, init_channel=self._dev+':BeamSizeX-Mon')
        xavemm = SiriusLabel(wid, init_channel=self._dev+':BeamSizemmX-Mon')
        xave.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        xavemm.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
        sep = QLabel('/', wid)
        sep.setStyleSheet('max-width:0.7em;')
        wid.layout().addWidget(xave)
        wid.layout().addWidget(sep)
        wid.layout().addWidget(xavemm)
        fl_size.addRow(QLabel(
            'X =', gb_size, alignment=Qt.AlignBottom), wid)

        wid = QWidget(gb_size)
        wid.setLayout(QHBoxLayout())
        yave = SiriusLabel(wid, init_channel=self._dev+':BeamSizeY-Mon')
        yavemm = SiriusLabel(wid, init_channel=self._dev+':BeamSizemmY-Mon')
        yave.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        yavemm.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
        sep = QLabel('/', wid)
        sep.setStyleSheet('max-width:0.7em;')
        wid.layout().addWidget(yave)
        wid.layout().addWidget(sep)
        wid.layout().addWidget(yavemm)
        fl_size.addRow(QLabel(
            'Y =', gb_size, alignment=Qt.AlignBottom), wid)

        return gb_size

    def _update_roi(self):
        xaxis = self._roixaxis.getvalue()
        yaxis = self._roiyaxis.getvalue()
        xproj = self._roixproj.getvalue()
        yproj = self._roiyproj.getvalue()
        xfit = self._roixfit.getvalue()
        yfit = self._roiyfit.getvalue()
        notnone = xaxis is not None
        notnone &= yaxis is not None
        notnone &= xproj is not None
        notnone &= yproj is not None
        notnone &= xfit is not None
        notnone &= yfit is not None
        if notnone:
            samesize = xaxis.size == xproj.size
            samesize &= xaxis.size == xfit.size
            samesize &= yaxis.size == yproj.size
            samesize &= yaxis.size == yfit.size
            if samesize:
                xproj = xproj/np.max(xproj) * 400 + yaxis[0]
                yproj = yproj/np.max(yproj) * 400 + xaxis[0]
                xfit = xfit/np.max(xfit) * 400 + yaxis[0]
                yfit = yfit/np.max(yfit) * 400 + xaxis[0]
                self.plt_his_x.setData(xaxis, xproj)
                self.plt_his_y.setData(yproj, yaxis)
                self.plt_fit_x.setData(xaxis, xfit)
                self.plt_fit_y.setData(yfit, yaxis)

        srtx = self._roistartx.getvalue()
        srty = self._roistarty.getvalue()
        endx = self._roiendx.getvalue()
        endy = self._roiendy.getvalue()
        if set([None, ]) - set([srtx, srty, endx, endy]):
            self.plt_roi.setData(
                [srtx, srtx, endx, endx, srtx],
                [srty, endy, endy, srty, srty])
Пример #28
0
	def make_right_axis(self):
		self.p3_2.addItem(PlotCurveItem(self.alphas_pre,self.rho_avg_pre,pen=self.rho_dash))
		self.p3_2.addItem(PlotCurveItem(self.alphas_post,self.rho_avg_post,pen=self.rho_dash))
Пример #29
0
    def __init__(self,
                 parent=None,
                 image_channel=None,
                 xaxis_channel=None,
                 yaxis_channel=None,
                 roioffsetx_channel=None,
                 roioffsety_channel=None,
                 roiwidth_channel=None,
                 roiheight_channel=None,
                 title='',
                 background='w',
                 image_width=0,
                 image_height=0):
        """Initialize widget."""
        GraphicsLayoutWidget.__init__(self, parent)
        PyDMWidget.__init__(self)
        self.thread = None
        self._imagechannel = None
        self._xaxischannel = None
        self._yaxischannel = None
        self._roioffsetxchannel = None
        self._roioffsetychannel = None
        self._roiwidthchannel = None
        self._roiheightchannel = None
        self._channels = 7 * [
            None,
        ]
        self.image_waveform = np.zeros(0)
        self._image_width = image_width if not xaxis_channel else 0
        self._image_height = image_height if not yaxis_channel else 0
        self._roi_offsetx = 0
        self._roi_offsety = 0
        self._roi_width = 0
        self._roi_height = 0
        self._normalize_data = False
        self._auto_downsample = True
        self._last_yaxis_data = None
        self._last_xaxis_data = None
        self._auto_colorbar_lims = True
        self.format_tooltip = '{0:.4g}, {1:.4g}'

        # ViewBox and imageItem.
        self._view = ViewBox()
        self._image_item = ImageItem()
        self._view.addItem(self._image_item)

        # ROI
        self.ROICurve = PlotCurveItem([0, 0, 0, 0, 0], [0, 0, 0, 0, 0])
        self.ROIColor = QColor('red')
        pen = mkPen()
        pen.setColor(QColor('transparent'))
        pen.setWidth(1)
        self.ROICurve.setPen(pen)
        self._view.addItem(self.ROICurve)

        # Axis.
        self.xaxis = AxisItem('bottom')
        self.xaxis.setPen(QColor(0, 0, 0))
        if not xaxis_channel:
            self.xaxis.setVisible(False)
        self.yaxis = AxisItem('left')
        self.yaxis.setPen(QColor(0, 0, 0))
        if not yaxis_channel:
            self.yaxis.setVisible(False)

        # Colorbar legend.
        self.colorbar = _GradientLegend()

        # Title.
        start_row = 0
        if title:
            self.title = LabelItem(text=title, color='#000000')
            self.addItem(self.title, 0, 0, 1, 3)
            start_row = 1

        # Set layout.
        self.addItem(self._view, start_row, 1)
        self.addItem(self.yaxis, start_row, 0)
        self.addItem(self.colorbar, start_row, 2)
        self.addItem(self.xaxis, start_row + 1, 1)
        self.setBackground(background)
        self.ci.layout.setColumnSpacing(0, 0)
        self.ci.layout.setRowSpacing(start_row, 0)

        # Set color map limits.
        self.cm_min = 0.0
        self.cm_max = 255.0

        # Set default reading order of numpy array data to Clike.
        self._reading_order = ReadingOrder.Clike

        # Make a right-click menu for changing the color map.
        self.cm_group = QActionGroup(self)
        self.cmap_for_action = {}
        for cm in self.color_maps:
            action = self.cm_group.addAction(cmap_names[cm])
            action.setCheckable(True)
            self.cmap_for_action[action] = cm

        # Set the default colormap.
        self._cm_colors = None
        self.colorMap = PyDMColorMap.Inferno

        # Setup the redraw timer.
        self.needs_redraw = False
        self.redraw_timer = QTimer(self)
        self.redraw_timer.timeout.connect(self.redrawImage)
        self._redraw_rate = 30
        self.maxRedrawRate = self._redraw_rate
        self.newImageSignal = self._image_item.sigImageChanged

        # Set Channels.
        self.imageChannel = image_channel
        self.xAxisChannel = xaxis_channel
        self.yAxisChannel = yaxis_channel
        self.ROIOffsetXChannel = roioffsetx_channel
        self.ROIOffsetYChannel = roioffsety_channel
        self.ROIWidthChannel = roiwidth_channel
        self.ROIHeightChannel = roiheight_channel
Пример #30
0
class BasePlot(PlotWidget):
    def __init__(self, parent=None, background='default', axisItems=None):
        super(BasePlot, self).__init__(parent=parent,
                                       background=background,
                                       axisItems=axisItems)
        self.plotItem = self.getPlotItem()
        self.plotItem.hideButtons()
        self._auto_range_x = None
        self.setAutoRangeX(True)
        self._auto_range_y = None
        self.setAutoRangeY(True)
        self._show_x_grid = None
        self.setShowXGrid(False)
        self._show_y_grid = None
        self.setShowYGrid(False)
        self._curveColor = QColor(255, 255, 255)
        self.curve = PlotCurveItem(pen=self._curveColor)
        self.addItem(self.curve)
        self._title = None

    def getAutoRangeX(self):
        return self._auto_range_x

    def setAutoRangeX(self, value):
        self._auto_range_x = value
        self.plotItem.enableAutoRange(ViewBox.XAxis, enable=self._auto_range_x)

    def resetAutoRangeX(self):
        self.setAutoRangeX(True)

    autoRangeX = pyqtProperty("bool", getAutoRangeX, setAutoRangeX,
                              resetAutoRangeX)

    def getAutoRangeY(self):
        return self._auto_range_y

    def setAutoRangeY(self, value):
        self._auto_range_y = value
        self.plotItem.enableAutoRange(ViewBox.YAxis, enable=self._auto_range_y)

    def resetAutoRangeY(self):
        self.setAutoRangeY(True)

    autoRangeY = pyqtProperty("bool", getAutoRangeY, setAutoRangeY,
                              resetAutoRangeY)

    def getShowXGrid(self):
        return self._show_x_grid

    def setShowXGrid(self, value):
        self._show_x_grid = value
        self.showGrid(x=self._show_x_grid)

    def resetShowXGrid(self):
        self.setShowXGrid(False)

    showXGrid = pyqtProperty("bool", getShowXGrid, setShowXGrid,
                             resetShowXGrid)

    def getShowYGrid(self):
        return self._show_y_grid

    def setShowYGrid(self, value):
        self._show_y_grid = value
        self.showGrid(y=self._show_y_grid)

    def resetShowYGrid(self):
        self.setShowYGrid(False)

    showYGrid = pyqtProperty("bool", getShowYGrid, setShowYGrid,
                             resetShowYGrid)

    def getCurveColor(self):
        return self._curveColor

    def setCurveColor(self, color):
        if self._curveColor != color:
            self._curveColor = color
            self.curve.setPen(self._curveColor)

    curveColor = pyqtProperty(QColor, getCurveColor, setCurveColor)

    def getBackgroundColor(self):
        return self.backgroundBrush().color()

    def setBackgroundColor(self, color):
        if self.backgroundBrush().color() != color:
            self.setBackgroundBrush(QBrush(color))

    backgroundColor = pyqtProperty(QColor, getBackgroundColor,
                                   setBackgroundColor)

    def getAxisColor(self):
        return self.getAxis('bottom')._pen.color()

    def setAxisColor(self, color):
        if self.getAxis('bottom')._pen.color() != color:
            self.getAxis('bottom').setPen(color)
            self.getAxis('left').setPen(color)
            self.getAxis('top').setPen(color)
            self.getAxis('right').setPen(color)

    axisColor = pyqtProperty(QColor, getAxisColor, setAxisColor)

    def getPlotTitle(self):
        return str(self._title)

    def setPlotTitle(self, value):
        self._title = str(value)
        self.setTitle(self._title)

    def resetPlotTitle(self):
        self._title = None
        self.setTitle(self._title)

    title = pyqtProperty(str, getPlotTitle, setPlotTitle, resetPlotTitle)