def __init__(self, *args, **kwargs): super(PyQtGraphImagePlot, self).__init__(*args, **kwargs) self.ui.histogram.hide() self.ui.roiBtn.hide() self.ui.normBtn.hide() self.line1 = InfiniteLine(pos=0, angle=0, movable=False) self.line2 = InfiniteLine(pos=0, angle=90, movable=False) self.addItem(self.line1) self.addItem(self.line2)
def __init__(self): super(MyImageView, self).__init__() self.ui.histogram.gradient.restoreState( {"ticks": [(0.0, (255, 0, 0)), (0.5, (255, 255, 255)), (1.0, (0, 0, 255))], "mode": "rgb"} ) self.h_line = InfiniteLine(pos=0, angle=0) self.v_line = InfiniteLine(pos=0, angle=90) self.view.addItem(self.h_line) self.view.addItem(self.v_line) win.time_slider.valueChanged.connect(self.set_time)
class PyQtGraphImagePlot(ImageView): def __init__(self, *args, **kwargs): super(PyQtGraphImagePlot, self).__init__(*args, **kwargs) self.ui.histogram.hide() self.ui.roiBtn.hide() self.ui.normBtn.hide() self.line1 = InfiniteLine(pos=0, angle=0, movable=False) self.line2 = InfiniteLine(pos=0, angle=90, movable=False) self.addItem(self.line1) self.addItem(self.line2) def plot(self, arr): self.setImage(np.array(arr)) self.line1.setPos(arr.shape[0]/2.) self.line2.setPos(arr.shape[1]/2.)
def update_data(self, x_attr, y_attr, i, j): """ Update graph :param x_attr: x attributes :param y_attr: y attributes :return: None """ OWScatterPlotGraph.update_data(self, x_attr, y_attr) x_index, y_index = i, j X = self.original_data[x_index] Y = self.original_data[y_index] valid = self.get_valid_list([x_index, y_index]) X = X[valid] Y = Y[valid] x_min, x_max = self.attr_values[x_attr] X = numpy.array([numpy.ones_like(X), X]).T try: beta, _, _, _ = numpy.linalg.lstsq(X, Y) except numpy.linalg.LinAlgError: beta = [0, 0] angle = atan2(beta[1], 1) * 180 / pi ti = InfiniteLine((-999, beta[0] + -999 * beta[1]), angle=angle, pen='r') # TODO FIX self.plot_widget.addItem(ti) if self.last_line is not None: self.plot_widget.removeItem(self.last_line) self.last_line = ti self.plot_widget.replot()
def draw_regression_line(self, x_data, y_data, min_x, max_x): if self.show_reg_line and self.can_draw_regresssion_line(): slope, intercept, rvalue, _, _ = linregress(x_data, y_data) start_y = min_x * slope + intercept end_y = max_x * slope + intercept angle = np.degrees(np.arctan((end_y - start_y) / (max_x - min_x))) rotate = ((angle + 45) % 180) - 45 > 90 color = QColor("#505050") l_opts = dict( color=color, position=abs(int(rotate) - 0.85), rotateAxis=(1, 0), movable=True, ) self.reg_line_item = InfiniteLine( pos=QPointF(min_x, start_y), pen=pg.mkPen(color=color, width=1), angle=angle, label="r = {:.2f}".format(rvalue), labelOpts=l_opts, ) if rotate: self.reg_line_item.label.angle = 180 self.reg_line_item.label.updateTransform() self.plot_widget.addItem(self.reg_line_item)
class TimePlot(PlotWidget): def __init__(self, *args, **kwargs): super(TimePlot, self).__init__(*args, **kwargs) self.add_line() win.time_slider.valueChanged.connect(self.set_time) def add_line(self): self.time_vline = InfiniteLine(angle=90) self.addItem(self.time_vline) def plot(self, x, *args, **kwargs): self.time_pts = x win.time_slider.setMaximum(len(self.time_pts)-1) self.plotItem.plot(x, *args, **kwargs) def set_time(self, time_idx): pos = self.time_pts[time_idx] self.time_vline.setPos(pos)
class MyImageView(ImageView): def __init__(self): super(MyImageView, self).__init__() self.ui.histogram.gradient.restoreState( {"ticks": [(0.0, (255, 0, 0)), (0.5, (255, 255, 255)), (1.0, (0, 0, 255))], "mode": "rgb"} ) self.h_line = InfiniteLine(pos=0, angle=0) self.v_line = InfiniteLine(pos=0, angle=90) self.view.addItem(self.h_line) self.view.addItem(self.v_line) win.time_slider.valueChanged.connect(self.set_time) def setImage(self, img, **kwargs): super(MyImageView, self).setImage(img, **kwargs) self.v_line.setPos(img.shape[1]/2.) self.h_line.setPos(img.shape[2]/2.) max_value = abs(img).max() self.setLevels(-max_value, max_value) win.time_slider.setMaximum(len(kwargs['xvals'])-1) def set_time(self, time_idx): self.setCurrentIndex(time_idx)
def test_update_line(self, init_prog): prog = init_prog IL = InfiniteLine() prog.update_line(IL)
def add_line(self): self.time_vline = InfiniteLine(angle=90) self.addItem(self.time_vline)
def __init__(self, parent=None, name="ImageView", view=None, imageItem=None, *args): QtGui.QWidget.__init__(self, parent, *args) self.levelMax = 4096 self.levelMin = 0 self.name = name self.image = None self.axes = {} self.imageDisp = None self.ui = Ui_Form() self.ui.setupUi(self) self.scene = self.ui.graphicsView.scene() self.ignoreTimeLine = False self.wcsAxes = WCSAxes() if view is None: self.view = self.wcsAxes.plotItem else: self.view = view self.ui.graphicsView.setCentralItem(self.view) self.view.setAspectLocked(True) self.view.invertY() if imageItem is None: self.imageItem = ImageItem() else: self.imageItem = imageItem self.view.addItem(self.imageItem) self.currentIndex = 0 self.ui.histogram.setImageItem(self.imageItem) self.menu = None self._hideSlider() self.roiEnabled = False self.roi = MultiROI() self.roi.setZValue(20) self.view.addItem(self.roi) self.roi.hide() self.normRoi = MultiROI() self.normRoi.setPen('y') self.normRoi.setZValue(20) self.view.addItem(self.normRoi) self.normRoi.hide() self.roiCurve = self.ui.roiPlot.plot() self.timeLine = InfiniteLine(0, movable=True) self.timeLine.setPen((255, 255, 0, 200)) self.timeLine.setZValue(1) self.ui.roiPlot.addItem(self.timeLine) self.ui.splitter.setSizes([self.height() - 35, 35]) self.ui.roiPlot.hideAxis('left') self.keysPressed = {} self.playTimer = QtCore.QTimer() self.playRate = 0 self.lastPlayTime = 0 self.normRgn = LinearRegionItem() self.normRgn.setZValue(0) self.ui.roiPlot.addItem(self.normRgn) self.normRgn.hide() # wrap functions from view box for fn in ['addItem', 'removeItem']: setattr(self, fn, getattr(self.view, fn)) # wrap functions from histogram for fn in [ 'setHistogramRange', 'autoHistogramRange', 'getLookupTable', 'getLevels' ]: setattr(self, fn, getattr(self.ui.histogram, fn)) self.ui.horizontalSlider.valueChanged.connect(self._sliderValueChanged) self.ui.sliderValueSpinBox.valueChanged.connect(self._spinBoxChanged) self.timeLine.sigPositionChanged.connect(self.timeLineChanged) self.roi.sigRegionChanged.connect(self.roiChanged) self.playTimer.timeout.connect(self.timeout) self.normProxy = pg.SignalProxy(self.normRgn.sigRegionChanged, slot=self.updateNorm) self.normRoi.sigRegionChangeFinished.connect(self.updateNorm) self.ui.roiPlot.registerPlot(self.name + '_ROI') self.view.register(self.name) self.noRepeatKeys = [ QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Up, QtCore.Qt.Key_Down, QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown ] # initialize roi plot to correct shape / visibility self.setROIType(None)
class AstroImageView(pg.ImageView): """ Extends ImageView class. - Replace default HistogramLUTWidget with our AstroHistogramLUTWidget. - Replace PlotWidget for roiPlot (defined inside UI class) by AstroWaveFormPlotWidget - Delete roiBtn """ def __init__(self, parent=None, name="ImageView", view=None, imageItem=None, *args): QtGui.QWidget.__init__(self, parent, *args) self.levelMax = 4096 self.levelMin = 0 self.name = name self.image = None self.axes = {} self.imageDisp = None self.ui = Ui_Form() self.ui.setupUi(self) self.scene = self.ui.graphicsView.scene() self.ignoreTimeLine = False self.wcsAxes = WCSAxes() if view is None: self.view = self.wcsAxes.plotItem else: self.view = view self.ui.graphicsView.setCentralItem(self.view) self.view.setAspectLocked(True) self.view.invertY() if imageItem is None: self.imageItem = ImageItem() else: self.imageItem = imageItem self.view.addItem(self.imageItem) self.currentIndex = 0 self.ui.histogram.setImageItem(self.imageItem) self.menu = None self._hideSlider() self.roiEnabled = False self.roi = MultiROI() self.roi.setZValue(20) self.view.addItem(self.roi) self.roi.hide() self.normRoi = MultiROI() self.normRoi.setPen('y') self.normRoi.setZValue(20) self.view.addItem(self.normRoi) self.normRoi.hide() self.roiCurve = self.ui.roiPlot.plot() self.timeLine = InfiniteLine(0, movable=True) self.timeLine.setPen((255, 255, 0, 200)) self.timeLine.setZValue(1) self.ui.roiPlot.addItem(self.timeLine) self.ui.splitter.setSizes([self.height() - 35, 35]) self.ui.roiPlot.hideAxis('left') self.keysPressed = {} self.playTimer = QtCore.QTimer() self.playRate = 0 self.lastPlayTime = 0 self.normRgn = LinearRegionItem() self.normRgn.setZValue(0) self.ui.roiPlot.addItem(self.normRgn) self.normRgn.hide() # wrap functions from view box for fn in ['addItem', 'removeItem']: setattr(self, fn, getattr(self.view, fn)) # wrap functions from histogram for fn in [ 'setHistogramRange', 'autoHistogramRange', 'getLookupTable', 'getLevels' ]: setattr(self, fn, getattr(self.ui.histogram, fn)) self.ui.horizontalSlider.valueChanged.connect(self._sliderValueChanged) self.ui.sliderValueSpinBox.valueChanged.connect(self._spinBoxChanged) self.timeLine.sigPositionChanged.connect(self.timeLineChanged) self.roi.sigRegionChanged.connect(self.roiChanged) self.playTimer.timeout.connect(self.timeout) self.normProxy = pg.SignalProxy(self.normRgn.sigRegionChanged, slot=self.updateNorm) self.normRoi.sigRegionChangeFinished.connect(self.updateNorm) self.ui.roiPlot.registerPlot(self.name + '_ROI') self.view.register(self.name) self.noRepeatKeys = [ QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Up, QtCore.Qt.Key_Down, QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown ] # initialize roi plot to correct shape / visibility self.setROIType(None) def set_fits_file(self, fitsFile): self.wcsAxes.setFitsFile(fitsFile) flux = fitsFile.flux() wave = fitsFile.wave() self.setImage(flux, xvals=wave) self.ui.roiPlot.setFitsFile(fitsFile) # TODO: Autorange the image after it is drawn. # This is a work around for what seems to be a bug in the # *pg.ArrowItem*: When arrows are shown in the canvas, the default # range of the axis becomes larger. Arrows are included from *WCSAxis*. timer = threading.Timer(0.1, lambda: self.view.vb.menu.autoRange()) timer.start() def setImage(self, img, autoRange=True, autoLevels=True, levels=None, axes=None, xvals=None, pos=None, scale=None, transform=None, autoHistogramRange=True): """ Reimplement setImage without using roiBtn """ if hasattr(img, 'implements') and img.implements('MetaArray'): img = img.asarray() if not isinstance(img, np.ndarray): required = ['dtype', 'max', 'min', 'ndim', 'shape', 'size'] if not all([hasattr(img, attr) for attr in required]): raise TypeError("Image must be NumPy array or any object " "that provides compatible attributes/methods:" "\n %s" % str(required)) self.image = img self.imageDisp = None if axes is None: if self.imageItem.axisOrder == 'col-major': x, y = (0, 1) else: x, y = (1, 0) if img.ndim == 2: self.axes = {'t': None, 'x': x, 'y': y, 'c': None} elif img.ndim == 3: # Ambiguous case; make a guess if img.shape[2] <= 4: self.axes = {'t': None, 'x': x, 'y': y, 'c': 2} else: self.axes = {'t': 0, 'x': x + 1, 'y': y + 1, 'c': None} elif img.ndim == 4: # Even more ambiguous; just assume the default self.axes = {'t': 0, 'x': x + 1, 'y': y + 1, 'c': 3} else: raise Exception("Can not interpret image with dimensions %s" % str(img.shape)) elif isinstance(axes, dict): self.axes = axes.copy() elif isinstance(axes, list) or isinstance(axes, tuple): self.axes = {} for i in range(len(axes)): self.axes[axes[i]] = i else: raise Exception("Can not interpret axis specification %s. " "Must be like {'t': 2, 'x': 0, 'y': 1} or " "('t', 'x', 'y', 'c')" % str(axes)) for x in ['t', 'x', 'y', 'c']: self.axes[x] = self.axes.get(x, None) axes = self.axes if xvals is not None: self.tVals = xvals elif axes['t'] is not None: if hasattr(img, 'xvals'): try: self.tVals = img.xvals(axes['t']) except Exception: self.tVals = np.arange(img.shape[axes['t']]) else: self.tVals = np.arange(img.shape[axes['t']]) self.currentIndex = 0 self.updateImage(autoHistogramRange=autoHistogramRange) if levels is None and autoLevels: self.autoLevels() # this does nothing since getProcessedImage sets these values again. if levels is not None: self.setLevels(*levels) if self.roiEnabled: self.roiChanged() if self.axes['t'] is not None: self.ui.roiPlot.setXRange(self.tVals.min(), self.tVals.max()) self.timeLine.setValue(0) if len(self.tVals) > 1: start = self.tVals.min() stop = (self.tVals.max() + abs(self.tVals[-1] - self.tVals[0]) * 0.02) elif len(self.tVals) == 1: start = self.tVals[0] - 0.5 stop = self.tVals[0] + 0.5 else: start = 0 stop = 1 for s in [self.timeLine, self.normRgn]: s.setBounds([start, stop]) self.imageItem.resetTransform() if scale is not None: self.imageItem.scale(*scale) if pos is not None: self.imageItem.setPos(*pos) if transform is not None: self.imageItem.setTransform(transform) if autoRange: self.autoRange() self._updateRoiPlot() # Override normalization functions to just return the image as is # We do not use ImageView's normalization features (yet) def normalize(self, image): return image.view(np.ndarray).copy() # Override as well def updateNorm(self): pass def setROIType(self, roiType): if roiType is None: self.roiEnabled = False else: self.roiEnabled = True if roiType == ROIType.SEMIAUTOMATIC: self._showSlider() else: self._hideSlider() self.roi.setROIType(roiType) self._updateRoiPlot() def _updateRoiPlot(self): showRoiPlot = False if self.roiEnabled: showRoiPlot = True self.roi.show() self.ui.roiPlot.setMouseEnabled(True, True) self.ui.splitter.setSizes( [self.height() * 0.6, self.height() * 0.4]) self.roiCurve.show() self.roiChanged() self.ui.roiPlot.showAxis('left') else: self.roi.hide() self.ui.roiPlot.setMouseEnabled(False, False) self.roiCurve.hide() self.ui.roiPlot.hideAxis('left') if self.hasTimeAxis(): showRoiPlot = True mn = self.tVals.min() mx = self.tVals.max() self.ui.roiPlot.setXRange(mn, mx, padding=0.01) self.timeLine.show() self.timeLine.setBounds([mn, mx]) self.ui.roiPlot.show() if not self.roiEnabled: self.ui.splitter.setSizes([self.height() - 35, 35]) else: self.timeLine.hide() self.ui.roiPlot.setVisible(showRoiPlot) def _hideSlider(self): self.ui.horizontalSliderLabel.hide() self.ui.horizontalSlider.hide() self.ui.sliderValueSpinBox.hide() def _showSlider(self): self.ui.horizontalSliderLabel.show() self.ui.horizontalSlider.show() self.ui.sliderValueSpinBox.show() def _sliderValueChanged(self, value): spinBoxVal = value / 100.0 self.ui.sliderValueSpinBox.setValue(spinBoxVal) self.roi.setSliderValue(spinBoxVal) def _spinBoxChanged(self, value): self.ui.horizontalSlider.setValue(int(value * 100)) self.roi.setSliderValue(value)