Source code for mantidimaging.gui.widgets.mi_mini_image_view.view

# Copyright (C) 2022 ISIS Rutherford Appleton Laboratory UKRI
# SPDX - License - Identifier: GPL-3.0-or-later

from itertools import chain, tee
from typing import List, Optional, Tuple
from weakref import WeakSet

from pyqtgraph import ImageItem, ViewBox
from pyqtgraph.graphicsItems.GraphicsLayout import GraphicsLayout
from pyqtgraph.graphicsItems.HistogramLUTItem import HistogramLUTItem
from PyQt5.QtWidgets import QAction

from mantidimaging.core.utility.close_enough_point import CloseEnoughPoint
from mantidimaging.gui.utility.qt_helpers import BlockQtSignals
from mantidimaging.gui.widgets.bad_data_overlay.bad_data_overlay import BadDataOverlay

graveyard = []


# https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.pairwise
# COMPAT python < 3.10
[docs] def pairwise(iterable): # pairwise('ABCDEFG') --> AB BC CD DE EF FG a, b = tee(iterable) next(b, None) return zip(a, b)
[docs] 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() self.auto_action: Optional[QAction] = None @property def image_item(self) -> ImageItem: return self.im @property def viewbox(self) -> ViewBox: return self.vb
[docs] def clear(self): self.im.clear() self.set_auto_color_enabled(False)
[docs] def setImage(self, *args, **kwargs): self.im.setImage(*args, **kwargs) self.check_for_bad_data() self.set_auto_color_enabled(self.im.image is not None)
[docs] @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)
[docs] def add_axis_sibling(self, sibling: "MIMiniImageView"): self.axis_siblings.add(sibling)
[docs] def add_hist_sibling(self, sibling: "MIMiniImageView"): self.histogram_siblings.add(sibling)
[docs] def get_parts(self) -> Tuple[ImageItem, ViewBox, HistogramLUTItem]: return self.im, self.vb, self.hist
[docs] 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)
[docs] 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}")
[docs] 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)
[docs] def add_auto_color_action(self) -> QAction: self.auto_action = QAction("Auto", self) place = self.hist.gradient.menu.actions()[12] self.hist.gradient.menu.insertAction(place, self.auto_action) self.hist.gradient.menu.insertSeparator(self.auto_action) self.set_auto_color_enabled(False) return self.auto_action
[docs] def set_auto_color_enabled(self, enabled: bool = True): if self.auto_action is not None: self.auto_action.setEnabled(enabled)