def mousePressEvent(self, ev): if ev.button() == QtCore.Qt.RightButton: ev.accept() self.dragStarted = True self.sigPressed.emit(ev.pos()) else: ImageItem.mousePressEvent(self, ev)
def __init__(self, *args, **kwargs): QtGui.QWidget.__init__(self) # variable that handles the manipulation of the spectrogram # create, recompute etc self.specgramHandler = Spectrogram() # create the histogram widget self.imageItem = ImageItem() self.__histogram = HorizontalHistogramWidget() self.__histogram.item.setImageItem(self.imageItem) # internal vieBox for image graph self.viewBox = ViewBox() self.viewBox.addItem(self.imageItem) self.viewBox.setMouseEnabled(x=False, y=False) self.viewBox.setMenuEnabled(False) self.viewBox.setAspectLocked(False) # set the X and Y axis for the graph self.xAxis = OscXAxis(self, orientation='bottom') self.yAxis = SpecYAxis(self, orientation='left') self.xAxis.linkToView(self.viewBox) self.yAxis.linkToView(self.viewBox) self.xAxis.setGrid(self.AXIS_LINES_OPACITY) self.yAxis.setGrid(self.AXIS_LINES_OPACITY) # adjust the graph zone in the control horizontal_histogram = kwargs[ "horizontal_histogram"] if "horizontal_histogram" in kwargs else True visible_histogram = kwargs[ "visible_histogram"] if "visible_histogram" in kwargs else False self.__updateLayout(histogramHorizontal=( horizontal_histogram if visible_histogram else None))
def mouseReleaseEvent(self, ev): if ev.button() == QtCore.Qt.RightButton: ev.accept() self.dragStarted = False self.sigReleased.emit(ev.pos()) else: ImageItem.mouseMoveEvent(self, ev)
def set_image(self, image, emit=True, *args, **kwargs) : """ Expects either np.arrays or pg.ImageItems as input and sets them correctly to this PlotWidget's Image with `addItem`. Also makes sure there is only one Image by deleting the previous image. Emits :signal:`sig_image_changed` **Parameters** ======== ============================================================== image np.ndarray or pyqtgraph.ImageItem instance; the image to be displayed. emit bool; whether or not to emit :signal:`sig_image_changed` (kw)args positional and keyword arguments that are passed on to :class:`pyqtgraph.ImageItem` ======== ============================================================== """ # Convert array to ImageItem if isinstance(image, ndarray) : if 0 not in image.shape : image_item = ImageItem(image, *args, **kwargs) else : logger.debug(('<{}>.set_image(): image.shape is {}. Not ' 'setting image.').format(self.name, image.shape)) return else : image_item = image # Throw an exception if image is not an ImageItem if not isinstance(image_item, ImageItem) : message = '''`image` should be a np.array or pg.ImageItem instance, not {}'''.format(type(image)) raise TypeError(message) # Transpose if necessary if self.transposed.get_value() : image_item = ImageItem(image_item.image.T, *args, **kwargs) # Replace the image self.remove_image() self.image_item = image_item self.image_data = image_item.image logger.debug('<{}>Setting image.'.format(self.name)) self.addItem(image_item) # Reset limits if necessary if self.xscale is not None and self.yscale is not None : axes_shape = (len(self.xscale), len(self.yscale)) if axes_shape != self.image_data.shape : self.xlim = None self.ylim = None self._set_axes_scales(emit=emit) if emit : logger.info('<{}>Emitting sig_image_changed.'.format(self.name)) self.sig_image_changed.emit()
def __init__(self, parent=None, res=(640, 480)): super(FrameBufferView, self).__init__(parent) #self.enableMouse() #self.setAspectLocked(True) self.scene = QtGui.QGraphicsScene() self.setScene(self.scene) self.imgArray = np.zeros(res) self.imgBuffer = ImageItem(border='w') self.scene.addItem(self.imgBuffer) self.fitInView( QtCore.QRectF(0, 0, self.imgArray.shape[1], self.imgArray.shape[1]))
def class_density_image(min_x, max_x, min_y, max_y, resolution, x_data, y_data, rgb_data): x_sz = (max_x-min_x)/(resolution-1) y_sz = (max_y-min_y)/(resolution-1) x_grid = [min_x+i*x_sz for i in range(resolution)] y_grid = [min_y+i*y_sz for i in range(resolution)] n_points = len(x_data) sample = range(n_points) if n_points > 1000: sample = grid_sample(x_data, y_data, 1000) x_data_norm = (np.array(x_data)-min_x)/(max_x-min_x) y_data_norm = (np.array(y_data)-min_y)/(max_y-min_y) x_grid_norm = (np.array(x_grid)-min_x)/(max_x-min_x) y_grid_norm = (np.array(y_grid)-min_y)/(max_y-min_y) img = compute_density(x_grid_norm, y_grid_norm, x_data_norm[sample], y_data_norm[sample], np.array(rgb_data)[sample]) density_img = ImageItem(img.astype(np.uint8), autoLevels=False) density_img.setRect(QRectF(min_x-x_sz/2, min_y-y_sz/2, max_x-min_x+x_sz, max_y-min_y+y_sz)) density_img.setZValue(-1) return density_img
class FrameBufferView(QtGui.QGraphicsView): ''' Object to display and update the image. ''' def __init__(self, parent=None, res=(640, 480)): super(FrameBufferView, self).__init__(parent) #self.enableMouse() #self.setAspectLocked(True) self.scene = QtGui.QGraphicsScene() self.setScene(self.scene) self.imgArray = np.zeros(res) self.imgBuffer = ImageItem(border='w') self.scene.addItem(self.imgBuffer) self.fitInView( QtCore.QRectF(0, 0, self.imgArray.shape[1], self.imgArray.shape[1])) #TODO - line update Q #Fills up when it changes, passes to the dispatcher def setResolution(res=(640, 480)): ''' ''' self.imgArray.resize(res) def viewedRect(self): ''' Return the pixel coordinates of the image visible in the viewport. ''' pass def updateImage(self, data): ''' Update the image with data. ''' self.imgBuffer.setImage(data)
def class_density_image(min_x, max_x, min_y, max_y, resolution, x_data, y_data, rgb_data): x_sz = (max_x - min_x) / (resolution - 1) y_sz = (max_y - min_y) / (resolution - 1) x_grid = [min_x + i * x_sz for i in range(resolution)] y_grid = [min_y + i * y_sz for i in range(resolution)] n_points = len(x_data) sample = range(n_points) if n_points > 1000: sample = grid_sample(x_data, y_data, 1000) x_data_norm = (np.array(x_data) - min_x) / (max_x - min_x) y_data_norm = (np.array(y_data) - min_y) / (max_y - min_y) x_grid_norm = (np.array(x_grid) - min_x) / (max_x - min_x) y_grid_norm = (np.array(y_grid) - min_y) / (max_y - min_y) img = compute_density( x_grid_norm, y_grid_norm, x_data_norm[sample], y_data_norm[sample], np.array(rgb_data)[sample], ) density_img = ImageItem(img.astype(np.uint8), autoLevels=False) density_img.setRect( QRectF( min_x - x_sz / 2, min_y - y_sz / 2, max_x - min_x + x_sz, max_y - min_y + y_sz, )) density_img.setZValue(-1) return density_img
class FrameBufferView(QtGui.QGraphicsView): ''' Object to display and update the image. ''' def __init__(self, parent=None, res=(640, 480)): super(FrameBufferView, self).__init__(parent) #self.enableMouse() #self.setAspectLocked(True) self.scene = QtGui.QGraphicsScene() self.setScene(self.scene) self.imgArray = np.zeros(res) self.imgBuffer = ImageItem(border='w') self.scene.addItem(self.imgBuffer) self.fitInView(QtCore.QRectF(0, 0, self.imgArray.shape[1], self.imgArray.shape[1])) #TODO - line update Q #Fills up when it changes, passes to the dispatcher def setResolution(res=(640, 480)): ''' ''' self.imgArray.resize(res) def viewedRect(self): ''' Return the pixel coordinates of the image visible in the viewport. ''' pass def updateImage(self, data): ''' Update the image with data. ''' self.imgBuffer.setImage(data)
def __init__(self, parent=None, res=(640, 480)): super(FrameBufferView, self).__init__(parent) #self.enableMouse() #self.setAspectLocked(True) self.scene = QtGui.QGraphicsScene() self.setScene(self.scene) self.imgArray = np.zeros(res) self.imgBuffer = ImageItem(border='w') self.scene.addItem(self.imgBuffer) self.fitInView(QtCore.QRectF(0, 0, self.imgArray.shape[1], self.imgArray.shape[1]))
def setup_pixel_mask(self, image, mask): image_item = ImageItem() lookup_table = pg.ColorMap([0, 1], np.array([[0, 0, 0, 0], [0, 0, 255, 255] ])).getLookupTable(alpha=True) image_item.setLookupTable(lookup_table) image.addItem(image_item) image_item.setImage(mask) return image_item
def set_image(self, image, emit=True, *args, **kwargs): """ Expects both, np.arrays and pg.ImageItems as input and sets them correctly to this PlotWidget's Image with `addItem`. Also makes sure there is only one Image by deleting the previous image. Emits :signal: `sig_image_changed` ====== ================================================================ image np.ndarray or pyqtgraph.ImageItem instance; the image to be displayed. emit bool; whether or not to emit :signal: `sig_image_changed` args positional and keyword arguments that are passed on to :class: kwargs `ImageItem <pyqtgraph.graphicsItems.ImageItem.ImageItem>` ====== ================================================================ """ self.image_data = image # Convert array to ImageItem if isinstance(image, ndarray): if 0 not in image.shape: image = ImageItem(image, *args, **kwargs) else: logger.debug(('<{}>.set_image(): image.shape is {}. Not ' 'setting image.').format(self.name, image.shape)) return # Throw an exception if image is not an ImageItem if not isinstance(image, ImageItem): message = '''`image` should be a np.array or pg.ImageItem instance, not {}'''.format(type(image)) raise TypeError(message) # Replace the image self.remove_image() self.image_item = image logger.debug('<{}>Setting image.'.format(self.name)) self.addItem(image) self._set_axes_scales(emit=emit) if emit: logger.info('<{}>Emitting sig_image_changed.'.format(self.name)) self.sig_image_changed.emit()
def set_image(self, image, *args, **kwargs) : """ Expects both, np.arrays and pg.ImageItems as input and sets them correctly to this PlotWidget's Image with `addItem`. Also makes sure there is only one Image by deleting the previous image. Emits :signal: `sig_image_changed` ====== ================================================================ image np.ndarray or pyqtgraph.ImageItem instance; the image to be displayed. args positional and keyword arguments that are passed on to :class: kwargs `ImageItem <pyqtgraph.graphicsItems.ImageItem.ImageItem>` ====== ================================================================ """ # Convert array to ImageItem if isinstance(image, ndarray) : image = ImageItem(image, *args, **kwargs) # Throw an exception if image is not an ImageItem if not isinstance(image, ImageItem) : message = '''`image` should be a np.array or pg.ImageItem instance, not {}'''.format(type(image)) raise TypeError(message) # Replace the image self.remove_image() self.image_item = image logger.debug('<{}>Setting image.'.format(self.name)) self.addItem(image) self._set_axes_scales(emit=False) # We suppressed emittance of sig_axes_changed to avoid external # listeners thinking the axes are different now. Thus, have to call # self.fix_viewrange manually. self.fix_viewrange() logger.info('<{}>Emitting sig_image_changed.'.format(self.name)) self.sig_image_changed.emit()
class SpectrogramWidget(QtGui.QWidget): """ Widget that visualize and interacts with a spectrogram graph of an audio signal. """ # SIGNALS # CONSTANTS # Value of the axis lines opacity AXIS_LINES_OPACITY = 255 # Max amount of columns to show on the visual widget. MAX_SPECGRAM_COLUMNS = 800 def __init__(self, *args, **kwargs): QtGui.QWidget.__init__(self) # variable that handles the manipulation of the spectrogram # create, recompute etc self.specgramHandler = Spectrogram() # create the histogram widget self.imageItem = ImageItem() self.__histogram = HorizontalHistogramWidget() self.__histogram.item.setImageItem(self.imageItem) # internal vieBox for image graph self.viewBox = ViewBox() self.viewBox.addItem(self.imageItem) self.viewBox.setMouseEnabled(x=False, y=False) self.viewBox.setMenuEnabled(False) self.viewBox.setAspectLocked(False) # set the X and Y axis for the graph self.xAxis = OscXAxis(self, orientation='bottom') self.yAxis = SpecYAxis(self, orientation='left') self.xAxis.linkToView(self.viewBox) self.yAxis.linkToView(self.viewBox) self.xAxis.setGrid(self.AXIS_LINES_OPACITY) self.yAxis.setGrid(self.AXIS_LINES_OPACITY) # adjust the graph zone in the control horizontal_histogram = kwargs[ "horizontal_histogram"] if "horizontal_histogram" in kwargs else True visible_histogram = kwargs[ "visible_histogram"] if "visible_histogram" in kwargs else False self.__updateLayout(histogramHorizontal=( horizontal_histogram if visible_histogram else None)) def __updateLayout(self, histogramHorizontal=None): """ Updates the layout of the widget to change the histogram position (horizontal-vertical) and visibility :param histogramHorizontal: None if invisible, true if horizontal false if vertical :return: """ # graph_control_layout self.graphics_view = pg.GraphicsView() # set the layout of the graphics view internal # that contains the axis and the view box to graph the spectrogram graphics_view_grid_layout = QtGui.QGraphicsGridLayout() graphics_view_grid_layout.setContentsMargins(0, 0, 0, 0) graphics_view_grid_layout.setHorizontalSpacing(0) graphics_view_grid_layout.setVerticalSpacing(0) graphics_view_grid_layout.addItem(self.xAxis, 1, 1) graphics_view_grid_layout.addItem(self.yAxis, 0, 0) graphics_view_grid_layout.addItem(self.viewBox, 0, 1) self.graphics_view.centralWidget.setLayout(graphics_view_grid_layout) layout = QtGui.QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.graphics_view, 0, 0) # add the elements in row,col if histogramHorizontal is not None: row = 1 if histogramHorizontal else 0 col = 1 - row self.__histogram = HorizontalHistogramWidget() if histogramHorizontal else\ HistogramLUTWidget() self.__histogram.item.gradient.loadPreset('thermal') self.__histogram.item.setImageItem(self.imageItem) layout.addWidget(self.histogram, row, col) self.setLayout(layout) # region Signal Property @property def signal(self): return self.specgramHandler.signal @signal.setter def signal(self, signal): if signal is None or not isinstance(signal, AudioSignal): raise ValueError( "Invalid assignation. Must be of type AudioSignal") self.specgramHandler.signal = signal max_columns = max(self.viewBox.width(), self.MAX_SPECGRAM_COLUMNS) self.specgramHandler.recomputeSpectrogram(maxCol=max_columns) # updating the axis scales self.xAxis.scale = self.specgramHandler.signal.samplingRate # updating the frequencies present in the signal # samplingRate/2 by Nyquist theorem. After update the spectrogram handler # there is an array in the specgramHandler with the freqs returned by the specgram # freqs is an array with the values of the frequency of each row of the specgram matriz self.yAxis.frequencies = self.specgramHandler.freqs # endregion # region Histogram Prop @property def histogram(self): """ Histogram widget with the values of the image. interacts with the image graph to change its color, threshold etc. Allow to visualize it outside the spectrogram widget :return: """ return self.__histogram # endregion def getInfo(self, x, y): """ Gets the values at x, y in the spectrogram :param x: the time position in rows of the spectrogram matriz :param y: the freq position in columns of the spectrogram matriz :return: a tuple with (time, freq, intensity) """ return self.specgramHandler.getInfo(x, y) def graph(self, indexFrom=0, indexTo=-1, padding=0): indexTo = indexTo if (indexTo >= 0 and indexTo > indexFrom) else self.signal.length # avoid to set the max columns too high that the spectrogram cant be computed # and do not consume more resources that necessary # show at most as many columns as pixels in the widget's width max_columns = max(self.viewBox.width(), self.MAX_SPECGRAM_COLUMNS) self.specgramHandler.recomputeSpectrogram(indexFrom, indexTo, max_columns) self.yAxis.frequencies = self.specgramHandler.freqs # set the new spectrogram image computed self.imageItem.setImage(self.specgramHandler.matriz) self.viewBox.setRange( xRange=(self.specgramHandler.from_osc_to_spec(indexFrom), self.specgramHandler.from_osc_to_spec(indexTo - 1)), padding=padding) # update the histogram colors of the spectrogram self.histogram.item.region.lineMoved() self.histogram.item.region.lineMoveFinished() self.xAxis.setRange(indexFrom, indexTo) self.update()
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 __init__(self, *args, **kwargs): ImageItem.__init__(self, *args, **kwargs) self.dragStarted = False
def mouseMoveEvent(self, ev): if self.dragStarted: self.sigDragged.emit(ev.pos()) ev.accept() else: ImageItem.mouseMoveEvent(self, ev)
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)