Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2326: Updated the code to display warnings for zero, negative, and NaN values using user-friendly colors in the operation and reconstruction windows.
8 changes: 8 additions & 0 deletions mantidimaging/eyes_tests/reconstruct_window_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ def test_negative_nan_overlay(self):

self.check_target(widget=self.imaging.recon)

QApplication.processEvents()

error_message = self.imaging.recon.statusMessageTextEdit.toPlainText()

assert "NaN(s) found in the stack" in error_message
assert "Zero(es) found in the stack" in error_message
assert "Negative value(s) found in the stack" in error_message

def test_reconstruction_window_colour_palette_dialog(self):
self._load_strict_data_set()

Expand Down
60 changes: 47 additions & 13 deletions mantidimaging/gui/widgets/bad_data_overlay/bad_data_overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,49 @@

from abc import abstractmethod, ABC
from collections.abc import Callable
from typing import Final

import numpy as np
from pyqtgraph import ColorMap, ImageItem, ViewBox
from dataclasses import dataclass

from mantidimaging.gui.utility.qt_helpers import _metaclass_sip_abc
from mantidimaging.gui.widgets.indicator_icon.view import IndicatorIconView
from mantidimaging.core.utility import finder

OVERLAY_COLOUR_NAN = [255, 0, 0, 255]
OVERLAY_COLOUR_NONPOSITVE = [255, 192, 0, 255]
OVERLAY_COLOUR_MESSAGE = [255, 0, 0, 255]
OVERLAY_COLOUR_NAN = [200, 0, 200, 255]
OVERLAY_COLOUR_ZERO = [255, 140, 0, 255]
OVERLAY_COLOUR_NEGATIVE = [0, 180, 0, 255]
OVERLAY_COLOUR_MESSAGE = [0, 120, 255, 255]


def _is_zero(data: np.ndarray) -> np.ndarray:
"""
Check for zero values
"""
return data == 0


def _is_negative(data: np.ndarray) -> np.ndarray:
"""
Check for negative values
"""
return data < 0


@dataclass(frozen=True)
class CheckConfig:
name: str
color: list[int]
position: int
check_function: Callable[[np.ndarray], np.ndarray]
message: str


VALUE_CHECKS: Final[tuple[CheckConfig, ...]] = (
CheckConfig("zero", OVERLAY_COLOUR_ZERO, 1, _is_zero, "Zero values"),
CheckConfig("negative", OVERLAY_COLOUR_NEGATIVE, 2, _is_negative, "Negative values"),
)


class BadDataCheck:
Expand Down Expand Up @@ -80,21 +112,23 @@ def image_item(self) -> ImageItem:
def viewbox(self) -> ViewBox:
...

def enable_nan_check(self, enable: bool = True, actions: list[tuple[str, Callable]] | None = None) -> None:
def enable_value_check(self, enable: bool = True, actions: list[tuple[str, Callable]] | None = None) -> None:
"""
Enable or disable all values checks (zero, negative, NaN)
"""
if enable:
self.enable_check("nan", OVERLAY_COLOUR_NAN, 0, np.isnan, "Invalid values: Not a number", actions)
for config in VALUE_CHECKS:
self.enable_check(config.name, config.color, config.position, config.check_function, config.message,
actions)
else:
self.disable_check("nan")
for config in VALUE_CHECKS:
self.disable_check(config.name)

def enable_nonpositive_check(self, enable: bool = True, actions: list[tuple[str, Callable]] | None = None) -> None:
def enable_nan_check(self, enable: bool = True, actions: list[tuple[str, Callable]] | None = None) -> None:
if enable:

def is_non_positive(data):
return data <= 0

self.enable_check("nonpos", OVERLAY_COLOUR_NONPOSITVE, 1, is_non_positive, "Non-positive values", actions)
self.enable_check("nan", OVERLAY_COLOUR_NAN, 0, np.isnan, "Invalid values: Not a number", actions)
else:
self.disable_check("nonpos")
self.disable_check("nan")

def enable_check(self, name: str, color: list[int], pos: int, func: Callable, message: str,
actions: list[tuple[str, Callable]] | None) -> None:
Expand Down
6 changes: 3 additions & 3 deletions mantidimaging/gui/windows/operations/filter_previews.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
diff_pen = (0, 0, 200)

OVERLAY_THRESHOLD = 1e-3
OVERLAY_COLOUR_DIFFERENCE = [0, 255, 0, 255]
OVERLAY_COLOUR_DIFFERENCE = [0, 255, 255, 255]


def _data_valid_for_histogram(data) -> bool:
Expand Down Expand Up @@ -151,13 +151,13 @@ def add_difference_overlay(self, diff, nan_change):
self.image_diff_overlay.setLookupTable(lut)

def add_negative_overlay(self):
self.imageview_after.enable_nonpositive_check()
self.imageview_after.enable_value_check()

def hide_difference_overlay(self):
self.image_diff_overlay.setVisible(False)

def hide_negative_overlay(self):
self.imageview_after.enable_nonpositive_check(False)
self.imageview_after.enable_value_check(False)

def auto_range(self):
# This will cause the previews to all show by just causing autorange on self.imageview_before.viewbox
Expand Down
2 changes: 1 addition & 1 deletion mantidimaging/gui/windows/operations/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def _wait_for_stack_choice(self, new_stack: ImageStack, stack_uuid: UUID):
stack_choice = StackChoicePresenter(self.original_images_stack[stack_uuid], new_stack, self)
del self.original_images_stack[stack_uuid]
if self.model.show_negative_overlay():
stack_choice.enable_nonpositive_check()
stack_choice.enable_value_check()
stack_choice.show()

while not stack_choice.done:
Expand Down
4 changes: 2 additions & 2 deletions mantidimaging/gui/windows/recon/image_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ def __init__(self, parent):
self.imageview_projection.enable_nan_check()
self.imageview_sinogram.enable_nan_check()
self.imageview_recon.enable_nan_check()
self.imageview_projection.enable_nonpositive_check()
self.imageview_sinogram.enable_nonpositive_check()
self.imageview_projection.enable_value_check()
self.imageview_sinogram.enable_value_check()

def cleanup(self) -> None:
self.imageview_projection.cleanup()
Expand Down
6 changes: 3 additions & 3 deletions mantidimaging/gui/windows/stack_choice/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ def close_view(self):
self.original_stack = None
self.done = True

def enable_nonpositive_check(self) -> None:
self.view.original_stack.enable_nonpositive_check()
self.view.new_stack.enable_nonpositive_check()
def enable_value_check(self) -> None:
self.view.original_stack.enable_value_check()
self.view.new_stack.enable_value_check()
Loading