From 0ee2cd5c32299c18bf95de2ec33cf102f05d7e83 Mon Sep 17 00:00:00 2001
From: Pierre Raybaut
Date: Tue, 25 Jun 2024 11:35:03 +0200
Subject: [PATCH] Removed unnecessary `IStatsImageItemType` interface and
`BaseImage.get_stats` method
---
plotpy/interfaces/__init__.py | 1 -
plotpy/interfaces/items.py | 25 ----------
plotpy/items/image/base.py | 84 ---------------------------------
plotpy/tools/image.py | 88 +++++++++++++++++++++++++++++++++--
4 files changed, 84 insertions(+), 114 deletions(-)
diff --git a/plotpy/interfaces/__init__.py b/plotpy/interfaces/__init__.py
index ee73e762..3111b702 100644
--- a/plotpy/interfaces/__init__.py
+++ b/plotpy/interfaces/__init__.py
@@ -16,7 +16,6 @@
IItemType,
ISerializableType,
IShapeItemType,
- IStatsImageItemType,
ITrackableItemType,
IVoiImageItemType,
)
diff --git a/plotpy/interfaces/items.py b/plotpy/interfaces/items.py
index 56f00b6c..20f57d9f 100644
--- a/plotpy/interfaces/items.py
+++ b/plotpy/interfaces/items.py
@@ -148,31 +148,6 @@ def export_roi(
pass
-class IStatsImageItemType(IItemType):
- """An image supporting stats computations"""
-
- def get_stats(
- self,
- x0: float,
- y0: float,
- x1: float,
- y1: float,
- show_surface: bool = False,
- show_integral: bool = False,
- ) -> str:
- """Return formatted string with stats on image rectangular area
- (output should be compatible with AnnotatedShape.get_infos)
-
- Args:
- x0: X0
- y0: Y0
- x1: X1
- y1: Y1
- show_surface: Show surface (Default value = False)
- show_integral: Show integral (Default value = False)
- """
-
-
class ICSImageItemType(IItemType):
"""An image supporting X/Y cross sections"""
diff --git a/plotpy/items/image/base.py b/plotpy/items/image/base.py
index 732d4ff0..9a27a3d9 100644
--- a/plotpy/items/image/base.py
+++ b/plotpy/items/image/base.py
@@ -37,7 +37,6 @@
IHistDataSource,
IImageItemType,
ISerializableType,
- IStatsImageItemType,
ITrackableItemType,
IVoiImageItemType,
)
@@ -75,7 +74,6 @@ class BaseImageItem(QwtPlotItem):
IHistDataSource,
IVoiImageItemType,
ICSImageItemType,
- IStatsImageItemType,
IExportROIImageItemType,
)
_can_select = True
@@ -720,8 +718,6 @@ def types(self) -> tuple[type[IItemType], ...]:
ITrackableItemType,
ICSImageItemType,
IExportROIImageItemType,
- IStatsImageItemType,
- IStatsImageItemType,
)
def set_readonly(self, state: bool) -> None:
@@ -998,85 +994,6 @@ def __process_cross_section(self, ydata, apply_lut):
else:
return ydata
- def get_stats(
- self,
- x0: float,
- y0: float,
- x1: float,
- y1: float,
- show_surface: bool = False,
- show_integral: bool = False,
- ) -> str:
- """Return formatted string with stats on image rectangular area
- (output should be compatible with AnnotatedShape.get_infos)
-
- Args:
- x0: X0
- y0: Y0
- x1: X1
- y1: Y1
- show_surface: Show surface (Default value = False)
- show_integral: Show integral (Default value = False)
- """
- ix0, iy0, ix1, iy1 = self.get_closest_index_rect(x0, y0, x1, y1)
- data = self.data[iy0:iy1, ix0:ix1]
- xfmt = self.param.xformat
- yfmt = self.param.yformat
- zfmt = self.param.zformat
- try:
- xunit = xfmt.split()[1]
- except IndexError:
- xunit = ""
- try:
- yunit = yfmt.split()[1]
- except IndexError:
- yunit = ""
- try:
- zunit = zfmt.split()[1]
- except IndexError:
- zunit = ""
- if show_integral:
- integral = data.sum()
- infos = "
".join(
- [
- "%s" % self.param.label,
- "%sx%s %s"
- % (self.data.shape[1], self.data.shape[0], str(self.data.dtype)),
- "",
- "%s ≤ x ≤ %s" % (xfmt % x0, xfmt % x1),
- "%s ≤ y ≤ %s" % (yfmt % y0, yfmt % y1),
- "%s ≤ z ≤ %s" % (zfmt % data.min(), zfmt % data.max()),
- "‹z› = " + zfmt % data.mean(),
- "σ(z) = " + zfmt % data.std(),
- ]
- )
- if show_surface and xunit == yunit:
- surfacefmt = xfmt.split()[0] + " " + xunit
- if xunit != "":
- surfacefmt = surfacefmt + "²"
- surface = abs((x1 - x0) * (y1 - y0))
- infos = infos + "
" + _("surface = %s") % (surfacefmt % surface)
- if show_integral:
- integral = data.sum()
- integral_fmt = r"%.3e " + zunit
- infos = infos + "
" + _("sum = %s") % (integral_fmt % integral)
- if (
- show_surface
- and xunit == yunit
- and xunit is not None
- and show_integral
- and zunit is not None
- ):
- if surface != 0:
- density = integral / surface
- densityfmt = r"%.3e " + zunit + "/" + xunit
- if xunit != "":
- densityfmt = densityfmt + "²"
- infos = infos + "
" + _("density = %s") % (densityfmt % density)
- else:
- infos = infos + "
" + _("density not computed : surface is null !")
- return infos
-
def get_xsection(self, y0: float | int, apply_lut: bool = False) -> np.ndarray:
"""Return cross section along x-axis at y=y0
@@ -1287,7 +1204,6 @@ def types(self) -> tuple[type[IItemType], ...]:
ICSImageItemType,
ISerializableType,
IExportROIImageItemType,
- IStatsImageItemType,
)
def update_item_parameters(self) -> None:
diff --git a/plotpy/tools/image.py b/plotpy/tools/image.py
index 617e7bba..3f6fbc09 100644
--- a/plotpy/tools/image.py
+++ b/plotpy/tools/image.py
@@ -20,7 +20,7 @@
from plotpy.events import QtDragHandler, setup_standard_tool_filter
from plotpy.interfaces import (
IColormapImageItemType,
- IStatsImageItemType,
+ IImageItemType,
IVoiImageItemType,
)
from plotpy.items import (
@@ -63,6 +63,86 @@
from plotpy.styles.shape import AnnotationParam
+def get_stats(
+ item: BaseImageItem,
+ x0: float,
+ y0: float,
+ x1: float,
+ y1: float,
+ show_surface: bool = False,
+ show_integral: bool = False,
+) -> str:
+ """Return formatted string with stats on image rectangular area
+ (output should be compatible with AnnotatedShape.get_infos)
+
+ Args:
+ x0: X0
+ y0: Y0
+ x1: X1
+ y1: Y1
+ show_surface: Show surface (Default value = False)
+ show_integral: Show integral (Default value = False)
+ """
+ ix0, iy0, ix1, iy1 = item.get_closest_index_rect(x0, y0, x1, y1)
+ data = item.data[iy0:iy1, ix0:ix1]
+ param: BaseImageParam = item.param
+ xfmt = param.xformat
+ yfmt = param.yformat
+ zfmt = param.zformat
+ try:
+ xunit = xfmt.split()[1]
+ except IndexError:
+ xunit = ""
+ try:
+ yunit = yfmt.split()[1]
+ except IndexError:
+ yunit = ""
+ try:
+ zunit = zfmt.split()[1]
+ except IndexError:
+ zunit = ""
+ if show_integral:
+ integral = data.sum()
+ infos = "
".join(
+ [
+ "%s" % param.label,
+ "%sx%s %s" % (item.data.shape[1], item.data.shape[0], str(item.data.dtype)),
+ "",
+ "%s ≤ x ≤ %s" % (xfmt % x0, xfmt % x1),
+ "%s ≤ y ≤ %s" % (yfmt % y0, yfmt % y1),
+ "%s ≤ z ≤ %s" % (zfmt % data.min(), zfmt % data.max()),
+ "‹z› = " + zfmt % data.mean(),
+ "σ(z) = " + zfmt % data.std(),
+ ]
+ )
+ if show_surface and xunit == yunit:
+ surfacefmt = xfmt.split()[0] + " " + xunit
+ if xunit != "":
+ surfacefmt = surfacefmt + "²"
+ surface = abs((x1 - x0) * (y1 - y0))
+ infos = infos + "
" + _("surface = %s") % (surfacefmt % surface)
+ if show_integral:
+ integral = data.sum()
+ integral_fmt = r"%.3e " + zunit
+ infos = infos + "
" + _("sum = %s") % (integral_fmt % integral)
+ if (
+ show_surface
+ and xunit == yunit
+ and xunit is not None
+ and show_integral
+ and zunit is not None
+ ):
+ if surface != 0:
+ density = integral / surface
+ densityfmt = r"%.3e " + zunit + "/" + xunit
+ if xunit != "":
+ densityfmt = densityfmt + "²"
+ infos = infos + "
" + _("density = %s") % (densityfmt % density)
+ else:
+ infos = infos + "
" + _("density not computed : surface is null !")
+ return infos
+
+
class ImageStatsRectangle(AnnotatedRectangle):
"""Rectangle used to display image statistics
@@ -129,8 +209,8 @@ def get_infos(self) -> str | None:
return _("No available data")
else:
return _("No available data")
- return self.image_item.get_stats(
- *self.get_rect(), self.show_surface, self.show_integral
+ return get_stats(
+ self.image_item, *self.get_rect(), self.show_surface, self.show_integral
)
@@ -258,7 +338,7 @@ def get_associated_item(self, plot: BasePlot) -> BaseImageItem | None:
Returns:
Reference to the last image item associated with the tool
"""
- items = plot.get_selected_items(item_type=IStatsImageItemType)
+ items = plot.get_selected_items(item_type=IImageItemType)
if len(items) == 1:
self._last_item = weakref.ref(items[0])
return self.get_last_item()