from collections import namedtuple import numpy as np from skimage import data from skimage.viewer import ImageViewer, has_qt from skimage.viewer.canvastools import ( LineTool, ThickLineTool, RectangleTool, PaintTool) from skimage.viewer.canvastools.base import CanvasToolBase from skimage._shared import testing from skimage._shared.testing import assert_equal, parametrize try: from matplotlib.testing.decorators import cleanup except ImportError: def cleanup(func): return func def get_end_points(image): h, w = image.shape[0:2] x = [w / 3, 2 * w / 3] y = [h / 2] * 2 return np.transpose([x, y]) def do_event(viewer, etype, button=1, xdata=0, ydata=0, key=None): """ *name* the event name *canvas* the FigureCanvas instance generating the event *guiEvent* the GUI event that triggered the matplotlib event *x* x position - pixels from left of canvas *y* y position - pixels from bottom of canvas *inaxes* the :class:`~matplotlib.axes.Axes` instance if mouse is over axes *xdata* x coord of mouse in data coords *ydata* y coord of mouse in data coords *button* button pressed None, 1, 2, 3, 'up', 'down' (up and down are used for scroll events) *key* the key depressed when the mouse event triggered (see :class:`KeyEvent`) *step* number of scroll steps (positive for 'up', negative for 'down') """ ax = viewer.ax event = namedtuple('Event', ('name canvas guiEvent x y inaxes xdata ydata ' 'button key step')) event.button = button event.x, event.y = ax.transData.transform((xdata, ydata)) event.xdata, event.ydata = xdata, ydata event.inaxes = ax event.canvas = ax.figure.canvas event.key = key event.step = 1 event.guiEvent = None event.name = 'Custom' func = getattr(viewer._event_manager, 'on_%s' % etype) func(event) @cleanup @testing.skipif(not has_qt, reason="Qt not installed") def test_line_tool(): img = data.camera() viewer = ImageViewer(img) tool = LineTool(viewer, maxdist=10, line_props=dict(linewidth=3), handle_props=dict(markersize=5)) tool.end_points = get_end_points(img) assert_equal(tool.end_points, np.array([[170, 256], [341, 256]])) # grab a handle and move it do_event(viewer, 'mouse_press', xdata=170, ydata=256) do_event(viewer, 'move', xdata=180, ydata=260) do_event(viewer, 'mouse_release') assert_equal(tool.geometry, np.array([[180, 260], [341, 256]])) # create a new line do_event(viewer, 'mouse_press', xdata=10, ydata=10) do_event(viewer, 'move', xdata=100, ydata=100) do_event(viewer, 'mouse_release') assert_equal(tool.geometry, np.array([[100, 100], [10, 10]])) @cleanup @testing.skipif(not has_qt, reason="Qt not installed") def test_thick_line_tool(): img = data.camera() viewer = ImageViewer(img) tool = ThickLineTool(viewer, maxdist=10, line_props=dict(color='red'), handle_props=dict(markersize=5)) tool.end_points = get_end_points(img) do_event(viewer, 'scroll', button='up') assert_equal(tool.linewidth, 2) do_event(viewer, 'scroll', button='down') assert_equal(tool.linewidth, 1) do_event(viewer, 'key_press', key='+') assert_equal(tool.linewidth, 2) do_event(viewer, 'key_press', key='-') assert_equal(tool.linewidth, 1) @cleanup @testing.skipif(not has_qt, reason="Qt not installed") def test_rect_tool(): img = data.camera() viewer = ImageViewer(img) tool = RectangleTool(viewer, maxdist=10) tool.extents = (100, 150, 100, 150) assert_equal(tool.corners, ((100, 150, 150, 100), (100, 100, 150, 150))) assert_equal(tool.extents, (100, 150, 100, 150)) assert_equal(tool.edge_centers, ((100, 125.0, 150, 125.0), (125.0, 100, 125.0, 150))) assert_equal(tool.geometry, (100, 150, 100, 150)) # grab a corner and move it do_event(viewer, 'mouse_press', xdata=100, ydata=100) do_event(viewer, 'move', xdata=120, ydata=120) do_event(viewer, 'mouse_release') # assert_equal(tool.geometry, [120, 150, 120, 150]) # create a new line do_event(viewer, 'mouse_press', xdata=10, ydata=10) do_event(viewer, 'move', xdata=100, ydata=100) do_event(viewer, 'mouse_release') assert_equal(tool.geometry, [10, 100, 10, 100]) @cleanup @testing.skipif(not has_qt, reason="Qt not installed") @parametrize('img', [data.moon(), data.astronaut()]) def test_paint_tool(img): viewer = ImageViewer(img) tool = PaintTool(viewer, img.shape) tool.radius = 10 assert_equal(tool.radius, 10) tool.label = 2 assert_equal(tool.label, 2) assert_equal(tool.shape, img.shape[:2]) do_event(viewer, 'mouse_press', xdata=100, ydata=100) do_event(viewer, 'move', xdata=110, ydata=110) do_event(viewer, 'mouse_release') assert_equal(tool.overlay[tool.overlay == 2].size, 761) tool.label = 5 do_event(viewer, 'mouse_press', xdata=20, ydata=20) do_event(viewer, 'move', xdata=40, ydata=40) do_event(viewer, 'mouse_release') assert_equal(tool.overlay[tool.overlay == 5].size, 881) assert_equal(tool.overlay[tool.overlay == 2].size, 761) do_event(viewer, 'key_press', key='enter') tool.overlay = tool.overlay * 0 assert_equal(tool.overlay.sum(), 0) assert_equal(tool.cmap.N, tool._overlay_plot.norm.vmax) @cleanup @testing.skipif(not has_qt, reason="Qt not installed") def test_base_tool(): img = data.moon() viewer = ImageViewer(img) tool = CanvasToolBase(viewer) tool.set_visible(False) tool.set_visible(True) do_event(viewer, 'key_press', key='enter') tool.redraw() tool.remove() tool = CanvasToolBase(viewer, useblit=False) tool.redraw()