From de10609b3c714b80a14bf6940e86763d0779402b Mon Sep 17 00:00:00 2001 From: wyzula-jan Date: Tue, 11 Mar 2025 14:12:16 +0100 Subject: [PATCH] refactor(image_widget): old BECImageWidget removed --- bec_widgets/cli/client.py | 1487 +++++++---------- .../jupyter_console/jupyter_console_window.py | 8 - .../widgets/containers/dock/dock_area.py | 6 +- .../plots/image/bec_image_widget.pyproject | 1 - .../plots/image/bec_image_widget_plugin.py | 58 - .../widgets/plots/image/image_widget.py | 516 ------ .../plots/image/register_bec_image_widget.py | 15 - tests/unit_tests/test_bec_dock.py | 6 +- tests/unit_tests/test_bec_image_widget.py | 224 --- 9 files changed, 649 insertions(+), 1672 deletions(-) delete mode 100644 bec_widgets/widgets/plots/image/bec_image_widget.pyproject delete mode 100644 bec_widgets/widgets/plots/image/bec_image_widget_plugin.py delete mode 100644 bec_widgets/widgets/plots/image/image_widget.py delete mode 100644 bec_widgets/widgets/plots/image/register_bec_image_widget.py delete mode 100644 tests/unit_tests/test_bec_image_widget.py diff --git a/bec_widgets/cli/client.py b/bec_widgets/cli/client.py index bbb547dd..78ad0f7c 100644 --- a/bec_widgets/cli/client.py +++ b/bec_widgets/cli/client.py @@ -18,8 +18,6 @@ class Widgets(str, enum.Enum): AbortButton = "AbortButton" BECColorMapWidget = "BECColorMapWidget" BECDockArea = "BECDockArea" - BECImageView = "BECImageView" - BECImageWidget = "BECImageWidget" BECMotorMapWidget = "BECMotorMapWidget" BECMultiWaveformWidget = "BECMultiWaveformWidget" BECProgressBar = "BECProgressBar" @@ -30,6 +28,7 @@ class Widgets(str, enum.Enum): DeviceBrowser = "DeviceBrowser" DeviceComboBox = "DeviceComboBox" DeviceLineEdit = "DeviceLineEdit" + Image = "Image" LMFitDialog = "LMFitDialog" LogPanel = "LogPanel" Minesweeper = "Minesweeper" @@ -687,148 +686,6 @@ class BECFigure(RPCBase): """ -class BECImage(RPCBase): - @property - @rpc_call - def color_map(self) -> "str": - """ - Get the current color map. - """ - - @color_map.setter - @rpc_call - def color_map(self) -> "str": - """ - Get the current color map. - """ - - @property - @rpc_call - def v_range(self) -> "tuple[float, float]": - """ - Get the color intensity range of the image. - """ - - @v_range.setter - @rpc_call - def v_range(self) -> "tuple[float, float]": - """ - Get the color intensity range of the image. - """ - - @property - @rpc_call - def v_min(self) -> "float": - """ - None - """ - - @v_min.setter - @rpc_call - def v_min(self) -> "float": - """ - None - """ - - @property - @rpc_call - def v_max(self) -> "float": - """ - None - """ - - @v_max.setter - @rpc_call - def v_max(self) -> "float": - """ - None - """ - - @property - @rpc_call - def autorange(self) -> "bool": - """ - None - """ - - @autorange.setter - @rpc_call - def autorange(self) -> "bool": - """ - None - """ - - @property - @rpc_call - def autorange_mode(self) -> "Literal['max', 'mean']": - """ - None - """ - - @autorange_mode.setter - @rpc_call - def autorange_mode(self) -> "Literal['max', 'mean']": - """ - None - """ - - @property - @rpc_call - def fft(self) -> "bool": - """ - Get or set whether FFT postprocessing is enabled. - """ - - @fft.setter - @rpc_call - def fft(self) -> "bool": - """ - Get or set whether FFT postprocessing is enabled. - """ - - @property - @rpc_call - def log(self) -> "bool": - """ - Get or set whether logarithmic scaling is applied. - """ - - @log.setter - @rpc_call - def log(self) -> "bool": - """ - Get or set whether logarithmic scaling is applied. - """ - - @property - @rpc_call - def rotation(self) -> "Optional[int]": - """ - Get or set the number of 90° rotations to apply. - """ - - @rotation.setter - @rpc_call - def rotation(self) -> "Optional[int]": - """ - Get or set the number of 90° rotations to apply. - """ - - @property - @rpc_call - def transpose(self) -> "bool": - """ - Get or set whether the image is transposed. - """ - - @transpose.setter - @rpc_call - def transpose(self) -> "bool": - """ - Get or set whether the image is transposed. - """ - - class BECImageItem(RPCBase): @property @rpc_call @@ -1338,705 +1195,6 @@ class BECImageShow(RPCBase): """ -class BECImageView(RPCBase): - @property - @rpc_call - def enable_toolbar(self) -> "bool": - """ - Show Toolbar. - """ - - @enable_toolbar.setter - @rpc_call - def enable_toolbar(self) -> "bool": - """ - Show Toolbar. - """ - - @property - @rpc_call - def enable_side_panel(self) -> "bool": - """ - Show Side Panel - """ - - @enable_side_panel.setter - @rpc_call - def enable_side_panel(self) -> "bool": - """ - Show Side Panel - """ - - @property - @rpc_call - def enable_fps_monitor(self) -> "bool": - """ - Enable the FPS monitor. - """ - - @enable_fps_monitor.setter - @rpc_call - def enable_fps_monitor(self) -> "bool": - """ - Enable the FPS monitor. - """ - - @rpc_call - def set(self, **kwargs): - """ - Set the properties of the plot widget. - - Args: - **kwargs: Keyword arguments for the properties to be set. - - Possible properties: - """ - - @property - @rpc_call - def title(self) -> "str": - """ - Set title of the plot. - """ - - @title.setter - @rpc_call - def title(self) -> "str": - """ - Set title of the plot. - """ - - @property - @rpc_call - def x_label(self) -> "str": - """ - The set label for the x-axis. - """ - - @x_label.setter - @rpc_call - def x_label(self) -> "str": - """ - The set label for the x-axis. - """ - - @property - @rpc_call - def y_label(self) -> "str": - """ - The set label for the y-axis. - """ - - @y_label.setter - @rpc_call - def y_label(self) -> "str": - """ - The set label for the y-axis. - """ - - @property - @rpc_call - def x_limits(self) -> "QPointF": - """ - Get the x limits of the plot. - """ - - @x_limits.setter - @rpc_call - def x_limits(self) -> "QPointF": - """ - Get the x limits of the plot. - """ - - @property - @rpc_call - def y_limits(self) -> "QPointF": - """ - Get the y limits of the plot. - """ - - @y_limits.setter - @rpc_call - def y_limits(self) -> "QPointF": - """ - Get the y limits of the plot. - """ - - @property - @rpc_call - def x_grid(self) -> "bool": - """ - Show grid on the x-axis. - """ - - @x_grid.setter - @rpc_call - def x_grid(self) -> "bool": - """ - Show grid on the x-axis. - """ - - @property - @rpc_call - def y_grid(self) -> "bool": - """ - Show grid on the y-axis. - """ - - @y_grid.setter - @rpc_call - def y_grid(self) -> "bool": - """ - Show grid on the y-axis. - """ - - @property - @rpc_call - def inner_axes(self) -> "bool": - """ - Show inner axes of the plot widget. - """ - - @inner_axes.setter - @rpc_call - def inner_axes(self) -> "bool": - """ - Show inner axes of the plot widget. - """ - - @property - @rpc_call - def outer_axes(self) -> "bool": - """ - Show the outer axes of the plot widget. - """ - - @outer_axes.setter - @rpc_call - def outer_axes(self) -> "bool": - """ - Show the outer axes of the plot widget. - """ - - @property - @rpc_call - def lock_aspect_ratio(self) -> "bool": - """ - Whether the aspect ratio is locked. - """ - - @lock_aspect_ratio.setter - @rpc_call - def lock_aspect_ratio(self) -> "bool": - """ - Whether the aspect ratio is locked. - """ - - @property - @rpc_call - def auto_range_x(self) -> "bool": - """ - Set auto range for the x-axis. - """ - - @auto_range_x.setter - @rpc_call - def auto_range_x(self) -> "bool": - """ - Set auto range for the x-axis. - """ - - @property - @rpc_call - def auto_range_y(self) -> "bool": - """ - Set auto range for the y-axis. - """ - - @auto_range_y.setter - @rpc_call - def auto_range_y(self) -> "bool": - """ - Set auto range for the y-axis. - """ - - @property - @rpc_call - def x_log(self) -> "bool": - """ - Set X-axis to log scale if True, linear if False. - """ - - @x_log.setter - @rpc_call - def x_log(self) -> "bool": - """ - Set X-axis to log scale if True, linear if False. - """ - - @property - @rpc_call - def y_log(self) -> "bool": - """ - Set Y-axis to log scale if True, linear if False. - """ - - @y_log.setter - @rpc_call - def y_log(self) -> "bool": - """ - Set Y-axis to log scale if True, linear if False. - """ - - @property - @rpc_call - def legend_label_size(self) -> "int": - """ - The font size of the legend font. - """ - - @legend_label_size.setter - @rpc_call - def legend_label_size(self) -> "int": - """ - The font size of the legend font. - """ - - @property - @rpc_call - def color_map(self) -> "str": - """ - Set the color map of the image. - """ - - @color_map.setter - @rpc_call - def color_map(self) -> "str": - """ - Set the color map of the image. - """ - - @property - @rpc_call - def vrange(self) -> "tuple": - """ - Get the vrange of the image. - """ - - @vrange.setter - @rpc_call - def vrange(self) -> "tuple": - """ - Get the vrange of the image. - """ - - @property - @rpc_call - def v_min(self) -> "float": - """ - Get the minimum value of the v_range. - """ - - @v_min.setter - @rpc_call - def v_min(self) -> "float": - """ - Get the minimum value of the v_range. - """ - - @property - @rpc_call - def v_max(self) -> "float": - """ - Get the maximum value of the v_range. - """ - - @v_max.setter - @rpc_call - def v_max(self) -> "float": - """ - Get the maximum value of the v_range. - """ - - @property - @rpc_call - def lock_aspect_ratio(self) -> "bool": - """ - Whether the aspect ratio is locked. - """ - - @lock_aspect_ratio.setter - @rpc_call - def lock_aspect_ratio(self) -> "bool": - """ - Whether the aspect ratio is locked. - """ - - @property - @rpc_call - def autorange(self) -> "bool": - """ - Whether autorange is enabled. - """ - - @autorange.setter - @rpc_call - def autorange(self) -> "bool": - """ - Whether autorange is enabled. - """ - - @property - @rpc_call - def autorange_mode(self) -> "str": - """ - Autorange mode. - - Options: - - "max": Use the maximum value of the image for autoranging. - - "mean": Use the mean value of the image for autoranging. - """ - - @autorange_mode.setter - @rpc_call - def autorange_mode(self) -> "str": - """ - Autorange mode. - - Options: - - "max": Use the maximum value of the image for autoranging. - - "mean": Use the mean value of the image for autoranging. - """ - - @property - @rpc_call - def monitor(self) -> "str": - """ - The name of the monitor to use for the image. - """ - - @monitor.setter - @rpc_call - def monitor(self) -> "str": - """ - The name of the monitor to use for the image. - """ - - @rpc_call - def enable_colorbar( - self, - enabled: "bool", - style: "Literal['full', 'simple']" = "full", - vrange: "tuple[int, int] | None" = None, - ): - """ - Enable the colorbar and switch types of colorbars. - - Args: - enabled(bool): Whether to enable the colorbar. - style(Literal["full", "simple"]): The type of colorbar to enable. - vrange(tuple): The range of values to use for the colorbar. - """ - - @property - @rpc_call - def enable_simple_colorbar(self) -> "bool": - """ - Enable the simple colorbar. - """ - - @enable_simple_colorbar.setter - @rpc_call - def enable_simple_colorbar(self) -> "bool": - """ - Enable the simple colorbar. - """ - - @property - @rpc_call - def enable_full_colorbar(self) -> "bool": - """ - Enable the full colorbar. - """ - - @enable_full_colorbar.setter - @rpc_call - def enable_full_colorbar(self) -> "bool": - """ - Enable the full colorbar. - """ - - @property - @rpc_call - def fft(self) -> "bool": - """ - Whether FFT postprocessing is enabled. - """ - - @fft.setter - @rpc_call - def fft(self) -> "bool": - """ - Whether FFT postprocessing is enabled. - """ - - @property - @rpc_call - def log(self) -> "bool": - """ - Whether logarithmic scaling is applied. - """ - - @log.setter - @rpc_call - def log(self) -> "bool": - """ - Whether logarithmic scaling is applied. - """ - - @property - @rpc_call - def rotation(self) -> "int": - """ - The number of 90° rotations to apply. - """ - - @rotation.setter - @rpc_call - def rotation(self) -> "int": - """ - The number of 90° rotations to apply. - """ - - @property - @rpc_call - def transpose(self) -> "bool": - """ - Whether the image is transposed. - """ - - @transpose.setter - @rpc_call - def transpose(self) -> "bool": - """ - Whether the image is transposed. - """ - - @rpc_call - def image( - self, - monitor: "str | None" = None, - monitor_type: "Literal['auto', '1d', '2d']" = "auto", - color_map: "str | None" = None, - color_bar: "Literal['simple', 'full'] | None" = None, - vrange: "tuple[int, int] | None" = None, - ) -> "BECImage": - """ - Set the image source and update the image. - - Args: - monitor(str): The name of the monitor to use for the image. - monitor_type(str): The type of monitor to use. Options are "1d", "2d", or "auto". - color_map(str): The color map to use for the image. - color_bar(str): The type of color bar to use. Options are "simple" or "full". - vrange(tuple): The range of values to use for the color map. - - Returns: - BECImage: The image object. - """ - - @property - @rpc_call - def main_image(self) -> "BECImage": - """ - Access the main image item. - """ - - -class BECImageWidget(RPCBase): - @rpc_call - def image( - self, - monitor: "str", - monitor_type: "Optional[Literal['1d', '2d']]" = "2d", - color_map: "Optional[str]" = "magma", - color_bar: "Optional[Literal['simple', 'full']]" = "full", - downsample: "Optional[bool]" = True, - opacity: "Optional[float]" = 1.0, - vrange: "Optional[tuple[int, int]]" = None, - **kwargs, - ) -> "BECImageItem": - """ - None - """ - - @rpc_call - def set(self, **kwargs): - """ - Set the properties of the plot widget. - - Args: - **kwargs: Keyword arguments for the properties to be set. - - Possible properties: - - title: str - - x_label: str - - y_label: str - - x_scale: Literal["linear", "log"] - - y_scale: Literal["linear", "log"] - - x_lim: tuple - - y_lim: tuple - - legend_label_size: int - """ - - @rpc_call - def set_title(self, title: "str"): - """ - Set the title of the plot widget. - - Args: - title(str): Title of the plot. - """ - - @rpc_call - def set_x_label(self, x_label: "str"): - """ - Set the x-axis label of the plot widget. - - Args: - x_label(str): Label of the x-axis. - """ - - @rpc_call - def set_y_label(self, y_label: "str"): - """ - Set the y-axis label of the plot widget. - - Args: - y_label(str): Label of the y-axis. - """ - - @rpc_call - def set_x_scale(self, x_scale: "Literal['linear', 'log']"): - """ - Set the scale of the x-axis of the plot widget. - - Args: - x_scale(Literal["linear", "log"]): Scale of the x-axis. - """ - - @rpc_call - def set_y_scale(self, y_scale: "Literal['linear', 'log']"): - """ - Set the scale of the y-axis of the plot widget. - - Args: - y_scale(Literal["linear", "log"]): Scale of the y-axis. - """ - - @rpc_call - def set_x_lim(self, x_lim: "tuple"): - """ - Set the limits of the x-axis of the plot widget. - - Args: - x_lim(tuple): Limits of the x-axis. - """ - - @rpc_call - def set_y_lim(self, y_lim: "tuple"): - """ - Set the limits of the y-axis of the plot widget. - - Args: - y_lim(tuple): Limits of the y-axis. - """ - - @rpc_call - def set_vrange(self, vmin: "float", vmax: "float", name: "str" = None): - """ - Set the range of the color bar. - If name is not specified, then set vrange for all images. - - Args: - vmin(float): Minimum value of the color bar. - vmax(float): Maximum value of the color bar. - name(str): The name of the image. If None, apply to all images. - """ - - @rpc_call - def set_fft(self, enable: "bool" = False, name: "str" = None): - """ - Set the FFT of the image. - If name is not specified, then set FFT for all images. - - Args: - enable(bool): Whether to perform FFT on the monitor data. - name(str): The name of the image. If None, apply to all images. - """ - - @rpc_call - def set_transpose(self, enable: "bool" = False, name: "str" = None): - """ - Set the transpose of the image. - If name is not specified, then set transpose for all images. - - Args: - enable(bool): Whether to transpose the monitor data before displaying. - name(str): The name of the image. If None, apply to all images. - """ - - @rpc_call - def set_rotation(self, deg_90: "int" = 0, name: "str" = None): - """ - Set the rotation of the image. - If name is not specified, then set rotation for all images. - - Args: - deg_90(int): The rotation angle of the monitor data before displaying. - name(str): The name of the image. If None, apply to all images. - """ - - @rpc_call - def set_log(self, enable: "bool" = False, name: "str" = None): - """ - Set the log of the image. - If name is not specified, then set log for all images. - - Args: - enable(bool): Whether to perform log on the monitor data. - name(str): The name of the image. If None, apply to all images. - """ - - @rpc_call - def set_grid(self, x_grid: "bool", y_grid: "bool"): - """ - Set the grid visibility of the plot widget. - - Args: - x_grid(bool): Visibility of the x-axis grid. - y_grid(bool): Visibility of the y-axis grid. - """ - - @rpc_call - def enable_fps_monitor(self, enabled: "bool"): - """ - Enable the FPS monitor of the plot widget. - - Args: - enabled(bool): If True, enable the FPS monitor. - """ - - @rpc_call - def lock_aspect_ratio(self, lock: "bool"): - """ - Lock the aspect ratio of the plot widget. - - Args: - lock(bool): Lock the aspect ratio. - """ - - class BECMainWindow(RPCBase): @rpc_call def remove(self): @@ -3516,6 +2674,649 @@ class DeviceSignalInputBase(RPCBase): """ +class Image(RPCBase): + @property + @rpc_call + def enable_toolbar(self) -> "bool": + """ + Show Toolbar. + """ + + @enable_toolbar.setter + @rpc_call + def enable_toolbar(self) -> "bool": + """ + Show Toolbar. + """ + + @property + @rpc_call + def enable_side_panel(self) -> "bool": + """ + Show Side Panel + """ + + @enable_side_panel.setter + @rpc_call + def enable_side_panel(self) -> "bool": + """ + Show Side Panel + """ + + @property + @rpc_call + def enable_fps_monitor(self) -> "bool": + """ + Enable the FPS monitor. + """ + + @enable_fps_monitor.setter + @rpc_call + def enable_fps_monitor(self) -> "bool": + """ + Enable the FPS monitor. + """ + + @rpc_call + def set(self, **kwargs): + """ + Set the properties of the plot widget. + + Args: + **kwargs: Keyword arguments for the properties to be set. + + Possible properties: + """ + + @property + @rpc_call + def title(self) -> "str": + """ + Set title of the plot. + """ + + @title.setter + @rpc_call + def title(self) -> "str": + """ + Set title of the plot. + """ + + @property + @rpc_call + def x_label(self) -> "str": + """ + The set label for the x-axis. + """ + + @x_label.setter + @rpc_call + def x_label(self) -> "str": + """ + The set label for the x-axis. + """ + + @property + @rpc_call + def y_label(self) -> "str": + """ + The set label for the y-axis. + """ + + @y_label.setter + @rpc_call + def y_label(self) -> "str": + """ + The set label for the y-axis. + """ + + @property + @rpc_call + def x_limits(self) -> "QPointF": + """ + Get the x limits of the plot. + """ + + @x_limits.setter + @rpc_call + def x_limits(self) -> "QPointF": + """ + Get the x limits of the plot. + """ + + @property + @rpc_call + def y_limits(self) -> "QPointF": + """ + Get the y limits of the plot. + """ + + @y_limits.setter + @rpc_call + def y_limits(self) -> "QPointF": + """ + Get the y limits of the plot. + """ + + @property + @rpc_call + def x_grid(self) -> "bool": + """ + Show grid on the x-axis. + """ + + @x_grid.setter + @rpc_call + def x_grid(self) -> "bool": + """ + Show grid on the x-axis. + """ + + @property + @rpc_call + def y_grid(self) -> "bool": + """ + Show grid on the y-axis. + """ + + @y_grid.setter + @rpc_call + def y_grid(self) -> "bool": + """ + Show grid on the y-axis. + """ + + @property + @rpc_call + def inner_axes(self) -> "bool": + """ + Show inner axes of the plot widget. + """ + + @inner_axes.setter + @rpc_call + def inner_axes(self) -> "bool": + """ + Show inner axes of the plot widget. + """ + + @property + @rpc_call + def outer_axes(self) -> "bool": + """ + Show the outer axes of the plot widget. + """ + + @outer_axes.setter + @rpc_call + def outer_axes(self) -> "bool": + """ + Show the outer axes of the plot widget. + """ + + @property + @rpc_call + def auto_range_x(self) -> "bool": + """ + Set auto range for the x-axis. + """ + + @auto_range_x.setter + @rpc_call + def auto_range_x(self) -> "bool": + """ + Set auto range for the x-axis. + """ + + @property + @rpc_call + def auto_range_y(self) -> "bool": + """ + Set auto range for the y-axis. + """ + + @auto_range_y.setter + @rpc_call + def auto_range_y(self) -> "bool": + """ + Set auto range for the y-axis. + """ + + @property + @rpc_call + def x_log(self) -> "bool": + """ + Set X-axis to log scale if True, linear if False. + """ + + @x_log.setter + @rpc_call + def x_log(self) -> "bool": + """ + Set X-axis to log scale if True, linear if False. + """ + + @property + @rpc_call + def y_log(self) -> "bool": + """ + Set Y-axis to log scale if True, linear if False. + """ + + @y_log.setter + @rpc_call + def y_log(self) -> "bool": + """ + Set Y-axis to log scale if True, linear if False. + """ + + @property + @rpc_call + def legend_label_size(self) -> "int": + """ + The font size of the legend font. + """ + + @legend_label_size.setter + @rpc_call + def legend_label_size(self) -> "int": + """ + The font size of the legend font. + """ + + @property + @rpc_call + def color_map(self) -> "str": + """ + Set the color map of the image. + """ + + @color_map.setter + @rpc_call + def color_map(self) -> "str": + """ + Set the color map of the image. + """ + + @property + @rpc_call + def vrange(self) -> "tuple": + """ + Get the vrange of the image. + """ + + @vrange.setter + @rpc_call + def vrange(self) -> "tuple": + """ + Get the vrange of the image. + """ + + @property + @rpc_call + def v_min(self) -> "float": + """ + Get the minimum value of the v_range. + """ + + @v_min.setter + @rpc_call + def v_min(self) -> "float": + """ + Get the minimum value of the v_range. + """ + + @property + @rpc_call + def v_max(self) -> "float": + """ + Get the maximum value of the v_range. + """ + + @v_max.setter + @rpc_call + def v_max(self) -> "float": + """ + Get the maximum value of the v_range. + """ + + @property + @rpc_call + def lock_aspect_ratio(self) -> "bool": + """ + Whether the aspect ratio is locked. + """ + + @lock_aspect_ratio.setter + @rpc_call + def lock_aspect_ratio(self) -> "bool": + """ + Whether the aspect ratio is locked. + """ + + @property + @rpc_call + def autorange(self) -> "bool": + """ + Whether autorange is enabled. + """ + + @autorange.setter + @rpc_call + def autorange(self) -> "bool": + """ + Whether autorange is enabled. + """ + + @property + @rpc_call + def autorange_mode(self) -> "str": + """ + Autorange mode. + + Options: + - "max": Use the maximum value of the image for autoranging. + - "mean": Use the mean value of the image for autoranging. + """ + + @autorange_mode.setter + @rpc_call + def autorange_mode(self) -> "str": + """ + Autorange mode. + + Options: + - "max": Use the maximum value of the image for autoranging. + - "mean": Use the mean value of the image for autoranging. + """ + + @property + @rpc_call + def monitor(self) -> "str": + """ + The name of the monitor to use for the image. + """ + + @monitor.setter + @rpc_call + def monitor(self) -> "str": + """ + The name of the monitor to use for the image. + """ + + @rpc_call + def enable_colorbar( + self, + enabled: "bool", + style: "Literal['full', 'simple']" = "full", + vrange: "tuple[int, int] | None" = None, + ): + """ + Enable the colorbar and switch types of colorbars. + + Args: + enabled(bool): Whether to enable the colorbar. + style(Literal["full", "simple"]): The type of colorbar to enable. + vrange(tuple): The range of values to use for the colorbar. + """ + + @property + @rpc_call + def enable_simple_colorbar(self) -> "bool": + """ + Enable the simple colorbar. + """ + + @enable_simple_colorbar.setter + @rpc_call + def enable_simple_colorbar(self) -> "bool": + """ + Enable the simple colorbar. + """ + + @property + @rpc_call + def enable_full_colorbar(self) -> "bool": + """ + Enable the full colorbar. + """ + + @enable_full_colorbar.setter + @rpc_call + def enable_full_colorbar(self) -> "bool": + """ + Enable the full colorbar. + """ + + @property + @rpc_call + def fft(self) -> "bool": + """ + Whether FFT postprocessing is enabled. + """ + + @fft.setter + @rpc_call + def fft(self) -> "bool": + """ + Whether FFT postprocessing is enabled. + """ + + @property + @rpc_call + def log(self) -> "bool": + """ + Whether logarithmic scaling is applied. + """ + + @log.setter + @rpc_call + def log(self) -> "bool": + """ + Whether logarithmic scaling is applied. + """ + + @property + @rpc_call + def rotation(self) -> "int": + """ + The number of 90° rotations to apply. + """ + + @rotation.setter + @rpc_call + def rotation(self) -> "int": + """ + The number of 90° rotations to apply. + """ + + @property + @rpc_call + def transpose(self) -> "bool": + """ + Whether the image is transposed. + """ + + @transpose.setter + @rpc_call + def transpose(self) -> "bool": + """ + Whether the image is transposed. + """ + + @rpc_call + def image( + self, + monitor: "str | None" = None, + monitor_type: "Literal['auto', '1d', '2d']" = "auto", + color_map: "str | None" = None, + color_bar: "Literal['simple', 'full'] | None" = None, + vrange: "tuple[int, int] | None" = None, + ) -> "ImageItem": + """ + Set the image source and update the image. + + Args: + monitor(str): The name of the monitor to use for the image. + monitor_type(str): The type of monitor to use. Options are "1d", "2d", or "auto". + color_map(str): The color map to use for the image. + color_bar(str): The type of color bar to use. Options are "simple" or "full". + vrange(tuple): The range of values to use for the color map. + + Returns: + ImageItem: The image object. + """ + + @property + @rpc_call + def main_image(self) -> "ImageItem": + """ + Access the main image item. + """ + + +class ImageItem(RPCBase): + @property + @rpc_call + def color_map(self) -> "str": + """ + Get the current color map. + """ + + @color_map.setter + @rpc_call + def color_map(self) -> "str": + """ + Get the current color map. + """ + + @property + @rpc_call + def v_range(self) -> "tuple[float, float]": + """ + Get the color intensity range of the image. + """ + + @v_range.setter + @rpc_call + def v_range(self) -> "tuple[float, float]": + """ + Get the color intensity range of the image. + """ + + @property + @rpc_call + def v_min(self) -> "float": + """ + None + """ + + @v_min.setter + @rpc_call + def v_min(self) -> "float": + """ + None + """ + + @property + @rpc_call + def v_max(self) -> "float": + """ + None + """ + + @v_max.setter + @rpc_call + def v_max(self) -> "float": + """ + None + """ + + @property + @rpc_call + def autorange(self) -> "bool": + """ + None + """ + + @autorange.setter + @rpc_call + def autorange(self) -> "bool": + """ + None + """ + + @property + @rpc_call + def autorange_mode(self) -> "Literal['max', 'mean']": + """ + None + """ + + @autorange_mode.setter + @rpc_call + def autorange_mode(self) -> "Literal['max', 'mean']": + """ + None + """ + + @property + @rpc_call + def fft(self) -> "bool": + """ + Get or set whether FFT postprocessing is enabled. + """ + + @fft.setter + @rpc_call + def fft(self) -> "bool": + """ + Get or set whether FFT postprocessing is enabled. + """ + + @property + @rpc_call + def log(self) -> "bool": + """ + Get or set whether logarithmic scaling is applied. + """ + + @log.setter + @rpc_call + def log(self) -> "bool": + """ + Get or set whether logarithmic scaling is applied. + """ + + @property + @rpc_call + def rotation(self) -> "Optional[int]": + """ + Get or set the number of 90° rotations to apply. + """ + + @rotation.setter + @rpc_call + def rotation(self) -> "Optional[int]": + """ + Get or set the number of 90° rotations to apply. + """ + + @property + @rpc_call + def transpose(self) -> "bool": + """ + Get or set whether the image is transposed. + """ + + @transpose.setter + @rpc_call + def transpose(self) -> "bool": + """ + Get or set whether the image is transposed. + """ + + class LMFitDialog(RPCBase): """Dialog for displaying the fit summary and params for LMFit DAP processes""" diff --git a/bec_widgets/examples/jupyter_console/jupyter_console_window.py b/bec_widgets/examples/jupyter_console/jupyter_console_window.py index 65d9c0d2..b43b91b7 100644 --- a/bec_widgets/examples/jupyter_console/jupyter_console_window.py +++ b/bec_widgets/examples/jupyter_console/jupyter_console_window.py @@ -53,10 +53,7 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover: "w9": self.w9, "w10": self.w10, "d0": self.d0, - "d1": self.d1, "im": self.im, - "im_old": self.im_old, - "it_old": self.it_old, "mi": self.mi, "mm": self.mm, "mw": self.mw, @@ -216,11 +213,6 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover: self.mm = self.d0.new("BECMotorMapWidget") self.mm.change_motors("samx", "samy") - self.d1 = self.dock.new(name="dock_1", position="right") - self.im_old = self.d1.new("BECImageWidget") - self.im_old.image("waveform", "1d") - self.it_old = self.im_old._image._images["device_monitor_1d"]["waveform"] - self.mw = None # self.wf.multi_waveform(monitor="waveform") # , config=config) self.dock.save_state() diff --git a/bec_widgets/widgets/containers/dock/dock_area.py b/bec_widgets/widgets/containers/dock/dock_area.py index 1c1724b7..0639d7b4 100644 --- a/bec_widgets/widgets/containers/dock/dock_area.py +++ b/bec_widgets/widgets/containers/dock/dock_area.py @@ -25,9 +25,9 @@ from bec_widgets.widgets.containers.dock.dock import BECDock, DockConfig from bec_widgets.widgets.control.device_control.positioner_box import PositionerBox from bec_widgets.widgets.control.scan_control.scan_control import ScanControl from bec_widgets.widgets.editors.vscode.vscode import VSCodeEditor -from bec_widgets.widgets.plots.image.image_widget import BECImageWidget from bec_widgets.widgets.plots.motor_map.motor_map_widget import BECMotorMapWidget from bec_widgets.widgets.plots.multi_waveform.multi_waveform_widget import BECMultiWaveformWidget +from bec_widgets.widgets.plots_next_gen.image.image import Image from bec_widgets.widgets.plots_next_gen.waveform.waveform import Waveform from bec_widgets.widgets.progress.ring_progress_bar.ring_progress_bar import RingProgressBar from bec_widgets.widgets.services.bec_queue.bec_queue import BECQueue @@ -102,7 +102,7 @@ class BECDockArea(BECWidget, QWidget): filled=True, ), "image": MaterialIconAction( - icon_name=BECImageWidget.ICON_NAME, tooltip="Add Image", filled=True + icon_name=Image.ICON_NAME, tooltip="Add Image", filled=True ), "motor_map": MaterialIconAction( icon_name=BECMotorMapWidget.ICON_NAME, @@ -180,7 +180,7 @@ class BECDockArea(BECWidget, QWidget): lambda: self._create_widget_from_toolbar(widget_name="BECMultiWaveformWidget") ) self.toolbar.widgets["menu_plots"].widgets["image"].triggered.connect( - lambda: self._create_widget_from_toolbar(widget_name="BECImageWidget") + lambda: self._create_widget_from_toolbar(widget_name="Image") ) self.toolbar.widgets["menu_plots"].widgets["motor_map"].triggered.connect( lambda: self._create_widget_from_toolbar(widget_name="BECMotorMapWidget") diff --git a/bec_widgets/widgets/plots/image/bec_image_widget.pyproject b/bec_widgets/widgets/plots/image/bec_image_widget.pyproject deleted file mode 100644 index a65dc560..00000000 --- a/bec_widgets/widgets/plots/image/bec_image_widget.pyproject +++ /dev/null @@ -1 +0,0 @@ -{'files': ['image_widget.py']} \ No newline at end of file diff --git a/bec_widgets/widgets/plots/image/bec_image_widget_plugin.py b/bec_widgets/widgets/plots/image/bec_image_widget_plugin.py deleted file mode 100644 index 94d056a6..00000000 --- a/bec_widgets/widgets/plots/image/bec_image_widget_plugin.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import os - -from qtpy.QtDesigner import QDesignerCustomWidgetInterface - -import bec_widgets -from bec_widgets.utils.bec_designer import designer_material_icon -from bec_widgets.widgets.plots.image.image_widget import BECImageWidget - -DOM_XML = """ - - - - -""" - -MODULE_PATH = os.path.dirname(bec_widgets.__file__) - - -class BECImageWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cover - def __init__(self): - super().__init__() - self._form_editor = None - - def createWidget(self, parent): - t = BECImageWidget(parent) - return t - - def domXml(self): - return DOM_XML - - def group(self): - return "BEC Plots" - - def icon(self): - return designer_material_icon(BECImageWidget.ICON_NAME) - - def includeFile(self): - return "bec_image_widget" - - def initialize(self, form_editor): - self._form_editor = form_editor - - def isContainer(self): - return False - - def isInitialized(self): - return self._form_editor is not None - - def name(self): - return "BECImageWidget" - - def toolTip(self): - return "BECImageWidget" - - def whatsThis(self): - return self.toolTip() diff --git a/bec_widgets/widgets/plots/image/image_widget.py b/bec_widgets/widgets/plots/image/image_widget.py deleted file mode 100644 index 39f14d3a..00000000 --- a/bec_widgets/widgets/plots/image/image_widget.py +++ /dev/null @@ -1,516 +0,0 @@ -from __future__ import annotations - -import sys -from typing import Literal, Optional - -import pyqtgraph as pg -from bec_lib.device import ReadoutPriority -from qtpy.QtWidgets import QComboBox, QVBoxLayout, QWidget - -from bec_widgets.qt_utils.error_popups import SafeSlot, WarningPopupUtility -from bec_widgets.qt_utils.settings_dialog import SettingsDialog -from bec_widgets.qt_utils.toolbar import ( - DeviceSelectionAction, - MaterialIconAction, - ModularToolBar, - SeparatorAction, - WidgetAction, -) -from bec_widgets.utils.bec_widget import BECWidget -from bec_widgets.widgets.containers.figure import BECFigure -from bec_widgets.widgets.containers.figure.plots.axis_settings import AxisSettings -from bec_widgets.widgets.containers.figure.plots.image.image import ImageConfig -from bec_widgets.widgets.containers.figure.plots.image.image_item import BECImageItem -from bec_widgets.widgets.control.device_input.base_classes.device_input_base import BECDeviceFilter -from bec_widgets.widgets.control.device_input.device_combobox.device_combobox import DeviceComboBox - - -# TODO will be deprecated -class BECImageWidget(BECWidget, QWidget): - PLUGIN = True - ICON_NAME = "image" - USER_ACCESS = [ - "image", - "set", - "set_title", - "set_x_label", - "set_y_label", - "set_x_scale", - "set_y_scale", - "set_x_lim", - "set_y_lim", - "set_vrange", - "set_fft", - "set_transpose", - "set_rotation", - "set_log", - "set_grid", - "enable_fps_monitor", - "lock_aspect_ratio", - ] - - def __init__( - self, - parent: QWidget | None = None, - config: ImageConfig | dict = None, - client=None, - gui_id: str | None = None, - **kwargs, - ) -> None: - if config is None: - config = ImageConfig(widget_class=self.__class__.__name__) - else: - if isinstance(config, dict): - config = ImageConfig(**config) - super().__init__(client=client, gui_id=gui_id, **kwargs) - QWidget.__init__(self, parent) - self.layout = QVBoxLayout(self) - self.layout.setSpacing(0) - self.layout.setContentsMargins(0, 0, 0, 0) - - self.fig = BECFigure() - self.dim_combo_box = QComboBox() - self.dim_combo_box.addItems(["1d", "2d"]) - self.toolbar = ModularToolBar( - actions={ - "monitor": DeviceSelectionAction( - "Monitor:", - DeviceComboBox( - device_filter=BECDeviceFilter.DEVICE, - readout_priority_filter=[ReadoutPriority.ASYNC], - ), - ), - "monitor_type": WidgetAction(widget=self.dim_combo_box), - "connect": MaterialIconAction(icon_name="link", tooltip="Connect Device"), - "separator_0": SeparatorAction(), - "save": MaterialIconAction(icon_name="save", tooltip="Open Export Dialog"), - "separator_1": SeparatorAction(), - "drag_mode": MaterialIconAction( - icon_name="open_with", tooltip="Drag Mouse Mode", checkable=True - ), - "rectangle_mode": MaterialIconAction( - icon_name="frame_inspect", tooltip="Rectangle Zoom Mode", checkable=True - ), - "auto_range": MaterialIconAction( - icon_name="open_in_full", tooltip="Autorange Plot" - ), - "auto_range_image": MaterialIconAction( - icon_name="hdr_auto", tooltip="Autorange Image Intensity", checkable=True - ), - "aspect_ratio": MaterialIconAction( - icon_name="aspect_ratio", tooltip="Lock image aspect ratio", checkable=True - ), - "separator_2": SeparatorAction(), - "FFT": MaterialIconAction(icon_name="fft", tooltip="Toggle FFT", checkable=True), - "log": MaterialIconAction( - icon_name="log_scale", tooltip="Toggle log scale", checkable=True - ), - "transpose": MaterialIconAction( - icon_name="transform", tooltip="Transpose Image", checkable=True - ), - "rotate_right": MaterialIconAction( - icon_name="rotate_right", tooltip="Rotate image clockwise by 90 deg" - ), - "rotate_left": MaterialIconAction( - icon_name="rotate_left", tooltip="Rotate image counterclockwise by 90 deg" - ), - "reset": MaterialIconAction( - icon_name="reset_settings", tooltip="Reset Image Settings" - ), - "separator_3": SeparatorAction(), - "fps_monitor": MaterialIconAction( - icon_name="speed", tooltip="Show FPS Monitor", checkable=True - ), - "axis_settings": MaterialIconAction( - icon_name="settings", tooltip="Open Configuration Dialog" - ), - }, - target_widget=self, - ) - - self.layout.addWidget(self.toolbar) - self.layout.addWidget(self.fig) - - self.warning_util = WarningPopupUtility(self) - - self._image = self.fig.image() - self._image.apply_config(config) - self.rotation = 0 - - self.config = config - - self._hook_actions() - - self.toolbar.widgets["drag_mode"].action.setChecked(True) - self.toolbar.widgets["auto_range_image"].action.setChecked(True) - - def _hook_actions(self): - self.toolbar.widgets["connect"].action.triggered.connect(self._connect_action) - # sepatator - self.toolbar.widgets["save"].action.triggered.connect(self.export) - # sepatator - self.toolbar.widgets["drag_mode"].action.triggered.connect(self.enable_mouse_pan_mode) - self.toolbar.widgets["rectangle_mode"].action.triggered.connect( - self.enable_mouse_rectangle_mode - ) - self.toolbar.widgets["auto_range"].action.triggered.connect(self.toggle_auto_range) - self.toolbar.widgets["auto_range_image"].action.triggered.connect( - self.toggle_image_autorange - ) - self.toolbar.widgets["aspect_ratio"].action.triggered.connect(self.toggle_aspect_ratio) - # sepatator - self.toolbar.widgets["FFT"].action.triggered.connect(self.toggle_fft) - self.toolbar.widgets["log"].action.triggered.connect(self.toggle_log) - self.toolbar.widgets["transpose"].action.triggered.connect(self.toggle_transpose) - self.toolbar.widgets["rotate_left"].action.triggered.connect(self.rotate_left) - self.toolbar.widgets["rotate_right"].action.triggered.connect(self.rotate_right) - self.toolbar.widgets["reset"].action.triggered.connect(self.reset_settings) - # sepatator - self.toolbar.widgets["axis_settings"].action.triggered.connect(self.show_axis_settings) - self.toolbar.widgets["fps_monitor"].action.toggled.connect(self.enable_fps_monitor) - - ################################### - # Dialog Windows - ################################### - @SafeSlot(popup_error=True) - def _connect_action(self): - monitor_combo = self.toolbar.widgets["monitor"].device_combobox - monitor_name = monitor_combo.currentText() - monitor_type = self.toolbar.widgets["monitor_type"].widget.currentText() - self.image(monitor=monitor_name, monitor_type=monitor_type) - monitor_combo.setStyleSheet("QComboBox { background-color: " "; }") - - def show_axis_settings(self): - dialog = SettingsDialog( - self, - settings_widget=AxisSettings(), - window_title="Axis Settings", - config=self._config_dict["axis"], - ) - dialog.exec() - - ################################### - # User Access Methods from image - ################################### - @SafeSlot(popup_error=True) - def image( - self, - monitor: str, - monitor_type: Optional[Literal["1d", "2d"]] = "2d", - color_map: Optional[str] = "magma", - color_bar: Optional[Literal["simple", "full"]] = "full", - downsample: Optional[bool] = True, - opacity: Optional[float] = 1.0, - vrange: Optional[tuple[int, int]] = None, - # post_processing: Optional[PostProcessingConfig] = None, - **kwargs, - ) -> BECImageItem: - if self.toolbar.widgets["monitor"].device_combobox.currentText() != monitor: - self.toolbar.widgets["monitor"].device_combobox.setCurrentText(monitor) - self.toolbar.widgets["monitor"].device_combobox.setStyleSheet( - "QComboBox {{ background-color: " "; }}" - ) - if self.toolbar.widgets["monitor_type"].widget.currentText() != monitor_type: - self.toolbar.widgets["monitor_type"].widget.setCurrentText(monitor_type) - self.toolbar.widgets["monitor_type"].widget.setStyleSheet( - "QComboBox {{ background-color: " "; }}" - ) - return self._image.image( - monitor=monitor, - monitor_type=monitor_type, - color_map=color_map, - color_bar=color_bar, - downsample=downsample, - opacity=opacity, - vrange=vrange, - **kwargs, - ) - - def set_vrange(self, vmin: float, vmax: float, name: str = None): - """ - Set the range of the color bar. - If name is not specified, then set vrange for all images. - - Args: - vmin(float): Minimum value of the color bar. - vmax(float): Maximum value of the color bar. - name(str): The name of the image. If None, apply to all images. - """ - self._image.set_vrange(vmin, vmax, name) - - def set_color_map(self, color_map: str, name: str = None): - """ - Set the color map of the image. - If name is not specified, then set color map for all images. - - Args: - cmap(str): The color map of the image. - name(str): The name of the image. If None, apply to all images. - """ - self._image.set_color_map(color_map, name) - - def set_fft(self, enable: bool = False, name: str = None): - """ - Set the FFT of the image. - If name is not specified, then set FFT for all images. - - Args: - enable(bool): Whether to perform FFT on the monitor data. - name(str): The name of the image. If None, apply to all images. - """ - self._image.set_fft(enable, name) - self.toolbar.widgets["FFT"].action.setChecked(enable) - - def set_transpose(self, enable: bool = False, name: str = None): - """ - Set the transpose of the image. - If name is not specified, then set transpose for all images. - - Args: - enable(bool): Whether to transpose the monitor data before displaying. - name(str): The name of the image. If None, apply to all images. - """ - self._image.set_transpose(enable, name) - self.toolbar.widgets["transpose"].action.setChecked(enable) - - def set_rotation(self, deg_90: int = 0, name: str = None): - """ - Set the rotation of the image. - If name is not specified, then set rotation for all images. - - Args: - deg_90(int): The rotation angle of the monitor data before displaying. - name(str): The name of the image. If None, apply to all images. - """ - self._image.set_rotation(deg_90, name) - - def set_log(self, enable: bool = False, name: str = None): - """ - Set the log of the image. - If name is not specified, then set log for all images. - - Args: - enable(bool): Whether to perform log on the monitor data. - name(str): The name of the image. If None, apply to all images. - """ - self._image.set_log(enable, name) - self.toolbar.widgets["log"].action.setChecked(enable) - - ################################### - # User Access Methods from Plotbase - ################################### - - def set(self, **kwargs): - """ - Set the properties of the plot widget. - - Args: - **kwargs: Keyword arguments for the properties to be set. - - Possible properties: - - title: str - - x_label: str - - y_label: str - - x_scale: Literal["linear", "log"] - - y_scale: Literal["linear", "log"] - - x_lim: tuple - - y_lim: tuple - - legend_label_size: int - """ - self._image.set(**kwargs) - - def set_title(self, title: str): - """ - Set the title of the plot widget. - - Args: - title(str): Title of the plot. - """ - self._image.set_title(title) - - def set_x_label(self, x_label: str): - """ - Set the x-axis label of the plot widget. - - Args: - x_label(str): Label of the x-axis. - """ - self._image.set_x_label(x_label) - - def set_y_label(self, y_label: str): - """ - Set the y-axis label of the plot widget. - - Args: - y_label(str): Label of the y-axis. - """ - self._image.set_y_label(y_label) - - def set_x_scale(self, x_scale: Literal["linear", "log"]): - """ - Set the scale of the x-axis of the plot widget. - - Args: - x_scale(Literal["linear", "log"]): Scale of the x-axis. - """ - self._image.set_x_scale(x_scale) - - def set_y_scale(self, y_scale: Literal["linear", "log"]): - """ - Set the scale of the y-axis of the plot widget. - - Args: - y_scale(Literal["linear", "log"]): Scale of the y-axis. - """ - self._image.set_y_scale(y_scale) - - def set_x_lim(self, x_lim: tuple): - """ - Set the limits of the x-axis of the plot widget. - - Args: - x_lim(tuple): Limits of the x-axis. - """ - self._image.set_x_lim(x_lim) - - def set_y_lim(self, y_lim: tuple): - """ - Set the limits of the y-axis of the plot widget. - - Args: - y_lim(tuple): Limits of the y-axis. - """ - self._image.set_y_lim(y_lim) - - def set_grid(self, x_grid: bool, y_grid: bool): - """ - Set the grid visibility of the plot widget. - - Args: - x_grid(bool): Visibility of the x-axis grid. - y_grid(bool): Visibility of the y-axis grid. - """ - self._image.set_grid(x_grid, y_grid) - - def lock_aspect_ratio(self, lock: bool): - """ - Lock the aspect ratio of the plot widget. - - Args: - lock(bool): Lock the aspect ratio. - """ - self._image.lock_aspect_ratio(lock) - - ################################### - # Toolbar Actions - ################################### - @SafeSlot() - def toggle_auto_range(self): - """ - Set the auto range of the plot widget from the toolbar. - """ - self._image.set_auto_range(True, "xy") - - @SafeSlot() - def toggle_fft(self): - checked = self.toolbar.widgets["FFT"].action.isChecked() - self.set_fft(checked) - - @SafeSlot() - def toggle_log(self): - checked = self.toolbar.widgets["log"].action.isChecked() - self.set_log(checked) - - @SafeSlot() - def toggle_transpose(self): - checked = self.toolbar.widgets["transpose"].action.isChecked() - self.set_transpose(checked) - - @SafeSlot() - def rotate_left(self): - self.rotation = (self.rotation + 1) % 4 - self.set_rotation(self.rotation) - - @SafeSlot() - def rotate_right(self): - self.rotation = (self.rotation - 1) % 4 - self.set_rotation(self.rotation) - - @SafeSlot() - def reset_settings(self): - self.set_log(False) - self.set_fft(False) - self.set_transpose(False) - self.rotation = 0 - self.set_rotation(0) - - self.toolbar.widgets["FFT"].action.setChecked(False) - self.toolbar.widgets["log"].action.setChecked(False) - self.toolbar.widgets["transpose"].action.setChecked(False) - - @SafeSlot() - def toggle_image_autorange(self): - """ - Enable the auto range of the image intensity. - """ - checked = self.toolbar.widgets["auto_range_image"].action.isChecked() - self._image.set_autorange(checked) - - @SafeSlot() - def toggle_aspect_ratio(self): - """ - Enable the auto range of the image intensity. - """ - checked = self.toolbar.widgets["aspect_ratio"].action.isChecked() - self._image.lock_aspect_ratio(checked) - - @SafeSlot() - def enable_mouse_rectangle_mode(self): - self.toolbar.widgets["rectangle_mode"].action.setChecked(True) - self.toolbar.widgets["drag_mode"].action.setChecked(False) - self._image.plot_item.getViewBox().setMouseMode(pg.ViewBox.RectMode) - - @SafeSlot() - def enable_mouse_pan_mode(self): - self.toolbar.widgets["drag_mode"].action.setChecked(True) - self.toolbar.widgets["rectangle_mode"].action.setChecked(False) - self._image.plot_item.getViewBox().setMouseMode(pg.ViewBox.PanMode) - - @SafeSlot() - def enable_fps_monitor(self, enabled: bool): - """ - Enable the FPS monitor of the plot widget. - - Args: - enabled(bool): If True, enable the FPS monitor. - """ - self._image.enable_fps_monitor(enabled) - if self.toolbar.widgets["fps_monitor"].action.isChecked() != enabled: - self.toolbar.widgets["fps_monitor"].action.setChecked(enabled) - - def export(self): - """ - Show the export dialog for the plot widget. - """ - self._image.export() - - def cleanup(self): - self.fig.cleanup() - self.toolbar.close() - self.toolbar.deleteLater() - return super().cleanup() - - -def main(): # pragma: no cover - - from qtpy.QtWidgets import QApplication - - app = QApplication(sys.argv) - widget = BECImageWidget() - widget.image("waveform", "1d") - widget.show() - sys.exit(app.exec_()) - - -if __name__ == "__main__": # pragma: no cover - main() diff --git a/bec_widgets/widgets/plots/image/register_bec_image_widget.py b/bec_widgets/widgets/plots/image/register_bec_image_widget.py deleted file mode 100644 index 776c1ac6..00000000 --- a/bec_widgets/widgets/plots/image/register_bec_image_widget.py +++ /dev/null @@ -1,15 +0,0 @@ -def main(): # pragma: no cover - from qtpy import PYSIDE6 - - if not PYSIDE6: - print("PYSIDE6 is not available in the environment. Cannot patch designer.") - return - from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection - - from bec_widgets.widgets.plots.image.bec_image_widget_plugin import BECImageWidgetPlugin - - QPyDesignerCustomWidgetCollection.addCustomWidget(BECImageWidgetPlugin()) - - -if __name__ == "__main__": # pragma: no cover - main() diff --git a/tests/unit_tests/test_bec_dock.py b/tests/unit_tests/test_bec_dock.py index 8490e447..7aa3dd8e 100644 --- a/tests/unit_tests/test_bec_dock.py +++ b/tests/unit_tests/test_bec_dock.py @@ -120,10 +120,8 @@ def test_toolbar_add_plot_waveform(bec_dock_area): def test_toolbar_add_plot_image(bec_dock_area): bec_dock_area.toolbar.widgets["menu_plots"].widgets["image"].trigger() - assert "BECImageWidget_0" in bec_dock_area.panels - assert ( - bec_dock_area.panels["BECImageWidget_0"].widgets[0].config.widget_class == "BECImageWidget" - ) + assert "Image_0" in bec_dock_area.panels + assert bec_dock_area.panels["Image_0"].widgets[0].config.widget_class == "Image" def test_toolbar_add_plot_motor_map(bec_dock_area): diff --git a/tests/unit_tests/test_bec_image_widget.py b/tests/unit_tests/test_bec_image_widget.py deleted file mode 100644 index 4dbe0d1f..00000000 --- a/tests/unit_tests/test_bec_image_widget.py +++ /dev/null @@ -1,224 +0,0 @@ -from unittest.mock import MagicMock - -import pyqtgraph as pg -import pytest - -from bec_widgets.widgets.control.device_input.base_classes.device_input_base import BECDeviceFilter -from bec_widgets.widgets.plots.image.image_widget import BECImageWidget - -from .client_mocks import mocked_client - - -@pytest.fixture -def image_widget(qtbot, mocked_client): - widget = BECImageWidget(client=mocked_client()) - qtbot.addWidget(widget) - qtbot.waitExposed(widget) - yield widget - - -@pytest.fixture -def mock_image(image_widget): - image_mock = MagicMock() - image_widget._image = image_mock - return image_mock - - -def test_image_widget_init(image_widget): - assert image_widget is not None - assert image_widget.client is not None - assert isinstance(image_widget, BECImageWidget) - assert image_widget.config.widget_class == "BECImageWidget" - assert image_widget._image is not None - - assert ( - BECDeviceFilter.DEVICE - in image_widget.toolbar.widgets["monitor"].device_combobox.config.device_filter - ) - assert image_widget.toolbar.widgets["drag_mode"].action.isChecked() == True - assert image_widget.toolbar.widgets["rectangle_mode"].action.isChecked() == False - assert image_widget.toolbar.widgets["auto_range"].action.isChecked() == False - assert image_widget.toolbar.widgets["auto_range_image"].action.isChecked() == True - assert image_widget.toolbar.widgets["FFT"].action.isChecked() == False - assert image_widget.toolbar.widgets["transpose"].action.isChecked() == False - assert image_widget.toolbar.widgets["log"].action.isChecked() == False - - -################################### -# Toolbar Actions -################################### -def test_toolbar_connect_action(image_widget, mock_image, qtbot): - combo_device = image_widget.toolbar.widgets["monitor"].device_combobox - combo_device.setCurrentText("eiger") - qtbot.wait(200) - assert combo_device.currentText() == "eiger" - combo_dim = image_widget.toolbar.widgets["monitor_type"].widget - combo_dim.setCurrentText("2d") - qtbot.wait(200) - assert combo_dim.currentText() == "2d" - action = image_widget.toolbar.widgets["connect"].action - action.trigger() - image_widget._image.image.assert_called_once_with( - monitor="eiger", - monitor_type="2d", - color_map="magma", - color_bar="full", - downsample=True, - opacity=1.0, - vrange=None, - ) - - -def test_image_toolbar_drag_mode_action_triggered(image_widget, qtbot): - action_drag = image_widget.toolbar.widgets["drag_mode"].action - action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action - action_drag.trigger() - assert action_drag.isChecked() == True - assert action_rectangle.isChecked() == False - - -def test_image_toolbar_rectangle_mode_action_triggered(image_widget, qtbot): - action_drag = image_widget.toolbar.widgets["drag_mode"].action - action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action - action_rectangle.trigger() - assert action_drag.isChecked() == False - assert action_rectangle.isChecked() == True - - -def test_image_toolbar_auto_range(image_widget, mock_image): - action = image_widget.toolbar.widgets["auto_range"].action - action.trigger() - image_widget._image.set_auto_range.assert_called_once_with(True, "xy") - - -def test_image_toolbar_enable_mouse_pan_mode(qtbot, image_widget): - action_drag = image_widget.toolbar.widgets["drag_mode"].action - action_rectangle = image_widget.toolbar.widgets["rectangle_mode"].action - - mock_view_box = MagicMock() - image_widget._image.plot_item.getViewBox = MagicMock(return_value=mock_view_box) - - image_widget.enable_mouse_pan_mode() - - assert action_drag.isChecked() == True - assert action_rectangle.isChecked() == False - mock_view_box.setMouseMode.assert_called_once_with(pg.ViewBox.PanMode) - - -def test_image_toolbar_auto_range_image(image_widget, mock_image): - action = image_widget.toolbar.widgets["auto_range_image"].action - action.trigger() - assert action.isChecked() == False - image_widget._image.set_autorange.assert_called_once_with(False) - - -def test_image_toolbar_FFT(image_widget, mock_image): - action = image_widget.toolbar.widgets["FFT"].action - action.trigger() - assert action.isChecked() == True - image_widget._image.set_fft.assert_called_once_with(True, None) - - -def test_image_toolbar_log(image_widget, mock_image): - action = image_widget.toolbar.widgets["log"].action - action.trigger() - assert action.isChecked() == True - image_widget._image.set_log.assert_called_once_with(True, None) - - -def test_image_toggle_transpose(image_widget, mock_image): - action = image_widget.toolbar.widgets["transpose"].action - action.trigger() - assert action.isChecked() == True - image_widget._image.set_transpose.assert_called_once_with(True, None) - - -def test_image_toolbar_rotation(image_widget, mock_image): - action_left = image_widget.toolbar.widgets["rotate_left"].action - action_right = image_widget.toolbar.widgets["rotate_right"].action - - action_left.trigger() - image_widget._image.set_rotation(1, None) - action_right.trigger() - image_widget._image.set_rotation(2, None) - - action_right.trigger() - image_widget._image.set_rotation(1, None) - - -################################### -# Wrapper methods for ImageShow -################################### - - -def test_image_set_image(image_widget, mock_image): - image_widget.image(monitor="image", monitor_type="2d") - image_widget._image.image.assert_called_once_with( - monitor="image", - monitor_type="2d", - color_map="magma", - color_bar="full", - downsample=True, - opacity=1.0, - vrange=None, - ) - - -def test_image_vrange(image_widget, mock_image): - image_widget.set_vrange(0, 1) - image_widget._image.set_vrange.assert_called_once_with(0, 1, None) - - -def test_image_set_color_map(image_widget, mock_image): - image_widget.set_color_map("viridis") - image_widget._image.set_color_map.assert_called_once_with("viridis", None) - - -def test_image_widget_set_title(image_widget, mock_image): - image_widget.set_title("Title Label") - image_widget._image.set_title.assert_called_once_with("Title Label") - - -def test_image_widget_set_x_label(image_widget, mock_image): - image_widget.set_x_label("X Label") - image_widget._image.set_x_label.assert_called_once_with("X Label") - - -def test_image_widget_set_y_label(image_widget, mock_image): - image_widget.set_y_label("Y Label") - image_widget._image.set_y_label.assert_called_once_with("Y Label") - - -def test_image_widget_set_x_scale(image_widget, mock_image): - image_widget.set_x_scale("linear") - image_widget._image.set_x_scale.assert_called_once_with("linear") - - -def test_image_widget_set_y_scale(image_widget, mock_image): - image_widget.set_y_scale("log") - image_widget._image.set_y_scale.assert_called_once_with("log") - - -def test_image_widget_set_x_lim(image_widget, mock_image): - image_widget.set_x_lim((0, 10)) - image_widget._image.set_x_lim.assert_called_once_with((0, 10)) - - -def test_image_widget_set_y_lim(image_widget, mock_image): - image_widget.set_y_lim((0, 10)) - image_widget._image.set_y_lim.assert_called_once_with((0, 10)) - - -def test_image_widget_set_grid(image_widget, mock_image): - image_widget.set_grid(True, False) - image_widget._image.set_grid.assert_called_once_with(True, False) - - -def test_image_widget_lock_aspect_ratio(image_widget, mock_image): - image_widget.lock_aspect_ratio(True) - image_widget._image.lock_aspect_ratio.assert_called_once_with(True) - - -def test_image_widget_export(image_widget, mock_image): - image_widget.export() - image_widget._image.export.assert_called_once()