Example #1
0
 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)
Example #2
0
    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()
Example #3
0
 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
Example #4
0
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)
Example #5
0
    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)