def __init__(self, parent=None, *args, **kargs): background = kargs.get('background', 'default') GraphicsView.__init__(self, parent, useOpenGL=False, background=background) self.item = HistogramLUTItem(*args, **kargs) self.setCentralItem(self.item) self.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) self.setMinimumWidth(95)
def __init__(self, name: str = "MIMiniImageView"): super().__init__() self.name = name.title() self.im = ImageItem() self.vb = ViewBox(invertY=True, lockAspect=True, name=name) self.vb.addItem(self.im) self.hist = HistogramLUTItem(self.im) graveyard.append(self.vb) # Sub-layout prevents resizing issues when details text changes image_layout = self.addLayout(colspan=2) image_layout.addItem(self.vb) image_layout.addItem(self.hist) self.hist.setFixedWidth(100) # HistogramLUTItem used pixel sizes self.nextRow() self.details = self.addLabel("", colspan=2) self.im.hoverEvent = lambda ev: self.mouse_over(ev) self.axis_siblings: "WeakSet[MIMiniImageView]" = WeakSet() self.histogram_siblings: "WeakSet[MIMiniImageView]" = WeakSet()
def image_in_vb(self, name=None): im = ImageItem() vb = ViewBox(invertY=True, lockAspect=True, name=name) vb.addItem(im) hist = HistogramLUTItem(im) return im, vb, hist
class MIMiniImageView(GraphicsLayout, BadDataOverlay): def __init__(self, name: str = "MIMiniImageView"): super().__init__() self.name = name.title() self.im = ImageItem() self.vb = ViewBox(invertY=True, lockAspect=True, name=name) self.vb.addItem(self.im) self.hist = HistogramLUTItem(self.im) graveyard.append(self.vb) # Sub-layout prevents resizing issues when details text changes image_layout = self.addLayout(colspan=2) image_layout.addItem(self.vb) image_layout.addItem(self.hist) self.hist.setFixedWidth(100) # HistogramLUTItem used pixel sizes self.nextRow() self.details = self.addLabel("", colspan=2) self.im.hoverEvent = lambda ev: self.mouse_over(ev) self.axis_siblings: "WeakSet[MIMiniImageView]" = WeakSet() self.histogram_siblings: "WeakSet[MIMiniImageView]" = WeakSet() @property def image_item(self) -> ImageItem: return self.im @property def viewbox(self) -> ViewBox: return self.vb def clear(self): self.im.clear() def setImage(self, *args, **kwargs): self.im.setImage(*args, **kwargs) self.check_for_bad_data() @staticmethod def set_siblings(sibling_views: List["MIMiniImageView"], axis=False, hist=False): for view1 in sibling_views: for view2 in sibling_views: if view2 is not view1: if axis: view1.add_axis_sibling(view2) if hist: view1.add_hist_sibling(view2) def add_axis_sibling(self, sibling: "MIMiniImageView"): self.axis_siblings.add(sibling) def add_hist_sibling(self, sibling: "MIMiniImageView"): self.histogram_siblings.add(sibling) def get_parts(self) -> Tuple[ImageItem, ViewBox, HistogramLUTItem]: return self.im, self.vb, self.hist def mouse_over(self, ev): # Ignore events triggered by leaving window or right clicking if ev.exit: return pos = CloseEnoughPoint(ev.pos()) self.show_value(pos) for img_view in self.axis_siblings: img_view.show_value(pos) def show_value(self, pos): image = self.im.image if image is not None and pos.y < image.shape[ 0] and pos.x < image.shape[1]: pixel_value = image[pos.y, pos.x] value_string = ("%.6f" % pixel_value)[:8] self.details.setText(f"{self.name}: {value_string}") def link_sibling_axis(self): # Linking multiple viewboxes with locked aspect ratios causes # odd resizing behaviour. Use workaround from # https://github.com/pyqtgraph/pyqtgraph/issues/1348 self.vb.setAspectLocked(True) for view1, view2 in pairwise(chain([self], self.axis_siblings)): view2.vb.linkView(ViewBox.XAxis, view1.vb) view2.vb.linkView(ViewBox.YAxis, view1.vb) view2.vb.setAspectLocked(False) def unlink_sibling_axis(self): for img_view in chain([self], self.axis_siblings): img_view.vb.linkView(ViewBox.XAxis, None) img_view.vb.linkView(ViewBox.YAxis, None) img_view.vb.setAspectLocked(True) def link_sibling_histogram(self): for view1, view2 in pairwise(chain([self], self.histogram_siblings)): view1.hist.vb.linkView(ViewBox.YAxis, view2.hist.vb) for img_view in chain([self], self.histogram_siblings): img_view.hist.sigLevelChangeFinished.connect( img_view.update_sibling_histograms) def unlink_sibling_histogram(self): for img_view in chain([self], self.histogram_siblings): img_view.hist.vb.linkView(ViewBox.YAxis, None) try: img_view.hist.sigLevelChangeFinished.disconnect() except TypeError: # This is expected if there are slots currently connected pass def update_sibling_histograms(self): hist_range = self.hist.getLevels() for img_view in self.histogram_siblings: with BlockQtSignals(img_view.hist): img_view.hist.setLevels(*hist_range)
def __init__(self, image=None, fillHistogram=True): """ If *image* (ImageItem) 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. By default, the histogram is rendered with a fill. For performance, set *fillHistogram* = False. """ HistogramLUTItem.__init__(self, image, fillHistogram) self.layout = QtGui.QGraphicsGridLayout() self.layout.setContentsMargins(1, 1, 1, 1) self.layout.setSpacing(0) # the viewbox in which would be displayed the histogram # get a new and descriptive name for the view box self.view_boxHistogram = self.vb self.view_boxHistogram = ViewBox() self.view_boxHistogram.setMaximumHeight(self.HISTOGRAM_MAX_HEIGHT) self.view_boxHistogram.setMinimumHeight(self.HISTOGRAM_MIN_HEIGHT) self.view_boxHistogram.setMouseEnabled(x=False, y=False) # set defaults gradient position and color bar self.gradient.setOrientation('bottom') self.gradient.loadPreset('thermal') # todo remove this parche the region of threshold selection self.region.setVisible(False) self._region = LinearRegionItem(values=[-40, 0], orientation=LinearRegionItem.Vertical) self.view_boxHistogram.addItem(self._region) self.axis = AxisItem('top', linkView=self.view_boxHistogram, maxTickLength=-10, showValues=False) self.layout.addItem(self.axis, 0, 0) self.layout.addItem(self.view_boxHistogram, 1, 0) self.layout.addItem(self.gradient, 2, 0) self.gradient.setFlag(self.gradient.ItemStacksBehindParent) self.view_boxHistogram.setFlag(self.gradient.ItemStacksBehindParent) self.plot = PlotDataItem() self.fillHistogram(fillHistogram) self.view_boxHistogram.addItem(self.plot) self.autoHistogramRange() # set the fixed range of visualization self.view_boxHistogram.setXRange(-120, 5) self._region.setBounds((-120, 5)) y_range = self.view_boxHistogram.viewRange()[1] # the minThresholdLabel and maxThresholdLabel labels self.minThresholdLabel = pg.TextItem(self.tr(u'Min'), color=(255, 255, 255), anchor=(1, 0.5)) self.view_boxHistogram.addItem(self.minThresholdLabel) self.maxThresholdLabel = pg.TextItem(self.tr(u'Max'), color=(255, 255, 255), anchor=(0, 0.5)) self.view_boxHistogram.addItem(self.maxThresholdLabel) self.gradient.sigGradientChanged.connect(self.gradientChanged) self._region.sigRegionChanged.connect(self.regionChanging) self._region.sigRegionChangeFinished.connect(self.regionChanged) labels_ypos = self.view_boxHistogram.viewRange()[1][1] * 0.7 self.maxThresholdLabel.setPos(self._region.getRegion()[1], labels_ypos) self.minThresholdLabel.setPos(self._region.getRegion()[0], labels_ypos) # update the tooltips and position of the limit labels self._region.sigRegionChangeFinished.connect( lambda: self.maxThresholdLabel.setToolTip(self.tr(u'Max Threshold') + u": " + unicode(round(self._region.getRegion()[1], self.DECIMAL_PLACES)))) self._region.sigRegionChangeFinished.connect( lambda: self.minThresholdLabel.setToolTip(self.tr(u'Min Threshold') + u": " + unicode(round(self._region.getRegion()[0], self.DECIMAL_PLACES)))) # set the y position of the labels to the 70% of the visible y range of the viewbox self._region.sigRegionChanged.connect( lambda: self.maxThresholdLabel.setPos(self._region.getRegion()[1], self.view_boxHistogram.viewRange()[1][1] * 0.7)) self._region.sigRegionChanged.connect( lambda: self.minThresholdLabel.setPos(self._region.getRegion()[0], self.view_boxHistogram.viewRange()[1][1] * 0.7)) if image is not None: self.setImageItem(image) self.setLayout(self.layout)