Select dialog

The selectdialog module provides a dialog box to select an area of the plot using a tool:

select an area with a shape tool and return the rectangle

items unselectable except for the given item

Example: get segment

# -*- coding: utf-8 -*-
#
# Licensed under the terms of the BSD 3-Clause
# (see plotpy/LICENSE for details)

"""
Test ``get_segment`` feature: select a segment on an image.

This plotpy tool provide a MATLAB-like "ginput" feature.
"""

# guitest: show

import numpy as np
import qtpy.QtCore as QC
from guidata.env import execenv
from guidata.qthelpers import qt_app_context

from plotpy.builder import make
from plotpy.coords import axes_to_canvas
from plotpy.tools import AnnotatedSegmentTool
from plotpy.widgets.selectdialog import SelectDialog, select_with_shape_tool

SEG_AXES_COORDS = [20, 20, 70, 70]


class PatchedSelectDialog(SelectDialog):
    """Patched SelectDialog"""

    def set_image_and_tool(self, item, toolclass, **kwargs):
        """Reimplement SelectDialog method"""
        super().set_image_and_tool(item, toolclass, **kwargs)
        if execenv.unattended:
            self.show()
            self.sel_tool.add_shape_to_plot(
                self.manager.get_plot(),
                QC.QPointF(*axes_to_canvas(item, *SEG_AXES_COORDS[:2])),
                QC.QPointF(*axes_to_canvas(item, *SEG_AXES_COORDS[2:])),
            )


def test_get_segment():
    """Test get_segment"""
    with qt_app_context():
        image = make.image(data=np.random.rand(200, 200), colormap="gray")
        shape = select_with_shape_tool(
            None,
            AnnotatedSegmentTool,
            image,
            "Test",
            tooldialogclass=PatchedSelectDialog,
        )
        if shape is not None:
            rect = shape.get_rect()
            if execenv.unattended:
                assert [round(i) for i in list(rect)] == SEG_AXES_COORDS
            elif rect is not None:
                distance = np.sqrt((rect[2] - rect[0]) ** 2 + (rect[3] - rect[1]) ** 2)
                print("Distance:", distance)


if __name__ == "__main__":
    test_get_segment()

Example: get rectangle

# -*- coding: utf-8 -*-
#
# For licensing and distribution details, please read carefully xgrid/__init__.py

"""
Get rectangular selection from image
"""

# guitest: show

import numpy as np
from guidata.env import execenv
from guidata.qthelpers import qt_app_context

from plotpy.builder import make
from plotpy.tests.tools.test_get_segment import SEG_AXES_COORDS, PatchedSelectDialog
from plotpy.tools import RectangleTool
from plotpy.widgets.selectdialog import select_with_shape_tool


def test_get_rectangle():
    """Test get_rectangle"""
    with qt_app_context():
        image = make.image(data=np.random.rand(200, 200), colormap="gray")
        shape = select_with_shape_tool(
            None, RectangleTool, image, "Test", tooldialogclass=PatchedSelectDialog
        )
        if shape is not None:
            rect = shape.get_rect()
            if execenv.unattended:
                assert [round(i) for i in list(rect)] == SEG_AXES_COORDS
            elif rect is not None:
                print("Area:", rect)


if __name__ == "__main__":
    test_get_rectangle()

Example: get rectangle with SVG

# -*- coding: utf-8 -*-
#
# For licensing and distribution details, please read carefully xgrid/__init__.py

"""
Get rectangular selection from image with SVG shape
"""

# guitest: show

from guidata.env import execenv
from guidata.qthelpers import qt_app_context

from plotpy.builder import make
from plotpy.tests import get_path
from plotpy.tests.data import gen_image4
from plotpy.tests.tools.test_get_segment import SEG_AXES_COORDS, PatchedSelectDialog
from plotpy.tools import RectangularShapeTool
from plotpy.widgets.selectdialog import select_with_shape_tool


class SVGToolExample(RectangularShapeTool):
    """Tool to select a rectangular area and create a pattern from it"""

    TITLE = "Pattern selection tool"
    ICON = "your_icon.svg"
    AVOID_NULL_SHAPE = True
    SVG_FNAME = get_path("svg_tool.svg")

    def create_shape(self):
        """Create shape to be drawn"""
        with open(self.SVG_FNAME, "rb") as svg_file:
            svg_data = svg_file.read()
        shape = make.svg("rectangle", svg_data, 0, 0, 1, 1, "SVG")
        self.set_shape_style(shape)
        return shape, 0, 2


def test_get_rectangle_with_svg():
    """Test get_rectangle_with_svg"""
    with qt_app_context():
        image = make.image(data=gen_image4(200, 200), colormap="gray")
        shape = select_with_shape_tool(
            None, SVGToolExample, image, "Test", tooldialogclass=PatchedSelectDialog
        )
        if shape is not None:
            rect = shape.get_rect()
            if execenv.unattended:
                assert [round(i) for i in list(rect)] == SEG_AXES_COORDS
            elif rect is not None:
                print("Area:", rect)


if __name__ == "__main__":
    test_get_rectangle_with_svg()

Reference

class plotpy.widgets.selectdialog.SelectDialog(parent: QWidget | None = None, toolbar: bool = False, options: PlotOptions | dict[str, Any] | None = None, panels: list[PanelWidget] | None = None, auto_tools: bool = True, title: str = 'PlotPy', icon: str = 'plotpy.svg', edit: bool = False)[source]

Plot dialog box to select an area of the plot using a tool

Parameters:
  • parent – parent widget

  • toolbar – show/hide toolbar

  • options – plot options

  • panels – additionnal panels

  • auto_tools – If True, the plot tools are automatically registered. If False, the user must register the tools manually.

  • title – The window title

  • icon – The window icon

  • edit – If True, the plot is editable

set_image_and_tool(item: ImageItem, toolclass: RectangularShapeTool, **kwargs) None[source]

Set the image item to be displayed and the tool to be used

Parameters:
  • item – Image item

  • toolclass – Tool class

  • kwargs – Keyword arguments for the tool class

get_new_shape() AbstractShape[source]

Get newly created shape

Returns:

Newly created shape

plotpy.widgets.selectdialog.select_with_shape_tool(parent: ~PyQt5.QtWidgets.QWidget, toolclass: ~plotpy.tools.shape.RectangularShapeTool, item: ~plotpy.items.image.image_items.ImageItem, title: str = None, size: tuple[int, int] = None, other_items: list[~qwt.plot.QwtPlotItem] = [], tooldialogclass: ~plotpy.widgets.selectdialog.SelectDialog = <class 'plotpy.widgets.selectdialog.SelectDialog'>, toolbar: bool = False, options: ~plotpy.plot.plotwidget.PlotOptions | dict[str, ~typing.Any] | None = None, icon=None, **kwargs) AbstractShape[source]

Select an area with a shape tool and return the rectangle

Parameters:
  • parent – Parent widget

  • toolclass – Tool class

  • item – Image item

  • title – Dialog title

  • size – Dialog size

  • other_items – Other items to be displayed

  • tooldialogclass – Tool dialog class

  • toolbar – show/hide toolbar

  • options – plot options

  • icon – Icon

  • kwargs – Keyword arguments for the tool class

Returns:

Selected shape

plotpy.widgets.selectdialog.set_items_unselectable(plot: BasePlot, except_item: QwtPlotItem = None) None[source]

Set items unselectable except for the given item