Interactive masking#

In this example, we will use a custom drawing tool to draw rectangles on a 2D figure. The data inside the rectangles will be masked.

[1]:
%matplotlib widget
import plopp as pp
import scipp as sc

We first generate some data that contains three bands of peaks that all have different spreads.

[2]:
from plopp.data.examples import three_bands

da = three_bands()

We then construct our custom tool, using Mpltoolbox’s Rectangles tool, and inheriting from Plopp’s DrawingTool.

[3]:
from plopp.widgets.drawing import DrawingTool
from functools import partial
from mpltoolbox import Rectangles


def define_mask(da, rect_info):
    """
    Function that creates a mask inside the area
    covered by the rectangle.
    """
    x = rect_info['x']
    y = rect_info['y']
    b = min(y['bottom'], y['top'])
    t = max(y['bottom'], y['top'])
    l = min(x['left'], x['right'])
    r = max(x['left'], x['right'])

    xcoord = sc.midpoints(da.coords[x['dim']])
    ycoord = sc.midpoints(da.coords[y['dim']])
    return (xcoord >= l) & (xcoord <= r) & (ycoord >= b) & (ycoord <= t)


def _get_rect_info(artist, figure):
    """
    Convert the raw rectangle info to a dict containing the dimensions of
    each axis, and values with units.
    """
    return lambda: {
        'x': {
            'dim': figure.canvas.dims['x'],
            'left': sc.scalar(artist.xy[0], unit=figure.canvas.units['x']),
            'right': sc.scalar(
                artist.xy[0] + artist.width, unit=figure.canvas.units['x']
            ),
        },
        'y': {
            'dim': figure.canvas.dims['y'],
            'bottom': sc.scalar(artist.xy[1], unit=figure.canvas.units['y']),
            'top': sc.scalar(
                artist.xy[1] + artist.height, unit=figure.canvas.units['y']
            ),
        },
    }


RectangleTool = partial(
    DrawingTool, tool=Rectangles, get_artist_info=_get_rect_info, icon='vector-square'
)

Finally, we create our visualization interface with the figure, adding our new tool to the toolbar.

[4]:
data_node = pp.Node(da)


def apply_masks(da, *masks):
    out = da.copy(deep=False)
    for i, mask in enumerate(masks):
        out.masks[str(i)] = mask
    return out


masking_node = pp.Node(apply_masks, data_node)

fig = pp.imagefigure(masking_node, logc=True)

r = RectangleTool(
    figure=fig, input_node=data_node, func=define_mask, destination=masking_node
)
fig.toolbar['roi'] = r
[6]:
fig
[6]:
[7]:
pp.show_graph(fig)
[7]:
../_images/gallery_interactive-masking_10_0.svg

To retrieve the masked data array, simply call the node that is applying the masks:

[8]:
masking_node()
[8]:
Show/Hide data repr Show/Hide attributes
scipp.DataArray (885.23 KB)
    • y: 300
    • x: 300
    • x
      (x [bin-edge])
      float64
      cm
      -50.0, -48.667, ..., 348.667, 350.0
      Values:
      array([-50. , -48.66666667, -47.33333333, -46. , -44.66666667, -43.33333333, -42. , -40.66666667, -39.33333333, -38. , -36.66666667, -35.33333333, -34. , -32.66666667, -31.33333333, -30. , -28.66666667, -27.33333333, -26. , -24.66666667, -23.33333333, -22. , -20.66666667, -19.33333333, -18. , -16.66666667, -15.33333333, -14. , -12.66666667, -11.33333333, -10. , -8.66666667, -7.33333333, -6. , -4.66666667, -3.33333333, -2. , -0.66666667, 0.66666667, 2. , 3.33333333, 4.66666667, 6. , 7.33333333, 8.66666667, 10. , 11.33333333, 12.66666667, 14. , 15.33333333, 16.66666667, 18. , 19.33333333, 20.66666667, 22. , 23.33333333, 24.66666667, 26. , 27.33333333, 28.66666667, 30. , 31.33333333, 32.66666667, 34. , 35.33333333, 36.66666667, 38. , 39.33333333, 40.66666667, 42. , 43.33333333, 44.66666667, 46. , 47.33333333, 48.66666667, 50. , 51.33333333, 52.66666667, 54. , 55.33333333, 56.66666667, 58. , 59.33333333, 60.66666667, 62. , 63.33333333, 64.66666667, 66. , 67.33333333, 68.66666667, 70. , 71.33333333, 72.66666667, 74. , 75.33333333, 76.66666667, 78. , 79.33333333, 80.66666667, 82. , 83.33333333, 84.66666667, 86. , 87.33333333, 88.66666667, 90. , 91.33333333, 92.66666667, 94. , 95.33333333, 96.66666667, 98. , 99.33333333, 100.66666667, 102. , 103.33333333, 104.66666667, 106. , 107.33333333, 108.66666667, 110. , 111.33333333, 112.66666667, 114. , 115.33333333, 116.66666667, 118. , 119.33333333, 120.66666667, 122. , 123.33333333, 124.66666667, 126. , 127.33333333, 128.66666667, 130. , 131.33333333, 132.66666667, 134. , 135.33333333, 136.66666667, 138. , 139.33333333, 140.66666667, 142. , 143.33333333, 144.66666667, 146. , 147.33333333, 148.66666667, 150. , 151.33333333, 152.66666667, 154. , 155.33333333, 156.66666667, 158. , 159.33333333, 160.66666667, 162. , 163.33333333, 164.66666667, 166. , 167.33333333, 168.66666667, 170. , 171.33333333, 172.66666667, 174. , 175.33333333, 176.66666667, 178. , 179.33333333, 180.66666667, 182. , 183.33333333, 184.66666667, 186. , 187.33333333, 188.66666667, 190. , 191.33333333, 192.66666667, 194. , 195.33333333, 196.66666667, 198. , 199.33333333, 200.66666667, 202. , 203.33333333, 204.66666667, 206. , 207.33333333, 208.66666667, 210. , 211.33333333, 212.66666667, 214. , 215.33333333, 216.66666667, 218. , 219.33333333, 220.66666667, 222. , 223.33333333, 224.66666667, 226. , 227.33333333, 228.66666667, 230. , 231.33333333, 232.66666667, 234. , 235.33333333, 236.66666667, 238. , 239.33333333, 240.66666667, 242. , 243.33333333, 244.66666667, 246. , 247.33333333, 248.66666667, 250. , 251.33333333, 252.66666667, 254. , 255.33333333, 256.66666667, 258. , 259.33333333, 260.66666667, 262. , 263.33333333, 264.66666667, 266. , 267.33333333, 268.66666667, 270. , 271.33333333, 272.66666667, 274. , 275.33333333, 276.66666667, 278. , 279.33333333, 280.66666667, 282. , 283.33333333, 284.66666667, 286. , 287.33333333, 288.66666667, 290. , 291.33333333, 292.66666667, 294. , 295.33333333, 296.66666667, 298. , 299.33333333, 300.66666667, 302. , 303.33333333, 304.66666667, 306. , 307.33333333, 308.66666667, 310. , 311.33333333, 312.66666667, 314. , 315.33333333, 316.66666667, 318. , 319.33333333, 320.66666667, 322. , 323.33333333, 324.66666667, 326. , 327.33333333, 328.66666667, 330. , 331.33333333, 332.66666667, 334. , 335.33333333, 336.66666667, 338. , 339.33333333, 340.66666667, 342. , 343.33333333, 344.66666667, 346. , 347.33333333, 348.66666667, 350. ])
    • y
      (y [bin-edge])
      float64
      cm
      -50.0, -48.667, ..., 348.667, 350.0
      Values:
      array([-50. , -48.66666667, -47.33333333, -46. , -44.66666667, -43.33333333, -42. , -40.66666667, -39.33333333, -38. , -36.66666667, -35.33333333, -34. , -32.66666667, -31.33333333, -30. , -28.66666667, -27.33333333, -26. , -24.66666667, -23.33333333, -22. , -20.66666667, -19.33333333, -18. , -16.66666667, -15.33333333, -14. , -12.66666667, -11.33333333, -10. , -8.66666667, -7.33333333, -6. , -4.66666667, -3.33333333, -2. , -0.66666667, 0.66666667, 2. , 3.33333333, 4.66666667, 6. , 7.33333333, 8.66666667, 10. , 11.33333333, 12.66666667, 14. , 15.33333333, 16.66666667, 18. , 19.33333333, 20.66666667, 22. , 23.33333333, 24.66666667, 26. , 27.33333333, 28.66666667, 30. , 31.33333333, 32.66666667, 34. , 35.33333333, 36.66666667, 38. , 39.33333333, 40.66666667, 42. , 43.33333333, 44.66666667, 46. , 47.33333333, 48.66666667, 50. , 51.33333333, 52.66666667, 54. , 55.33333333, 56.66666667, 58. , 59.33333333, 60.66666667, 62. , 63.33333333, 64.66666667, 66. , 67.33333333, 68.66666667, 70. , 71.33333333, 72.66666667, 74. , 75.33333333, 76.66666667, 78. , 79.33333333, 80.66666667, 82. , 83.33333333, 84.66666667, 86. , 87.33333333, 88.66666667, 90. , 91.33333333, 92.66666667, 94. , 95.33333333, 96.66666667, 98. , 99.33333333, 100.66666667, 102. , 103.33333333, 104.66666667, 106. , 107.33333333, 108.66666667, 110. , 111.33333333, 112.66666667, 114. , 115.33333333, 116.66666667, 118. , 119.33333333, 120.66666667, 122. , 123.33333333, 124.66666667, 126. , 127.33333333, 128.66666667, 130. , 131.33333333, 132.66666667, 134. , 135.33333333, 136.66666667, 138. , 139.33333333, 140.66666667, 142. , 143.33333333, 144.66666667, 146. , 147.33333333, 148.66666667, 150. , 151.33333333, 152.66666667, 154. , 155.33333333, 156.66666667, 158. , 159.33333333, 160.66666667, 162. , 163.33333333, 164.66666667, 166. , 167.33333333, 168.66666667, 170. , 171.33333333, 172.66666667, 174. , 175.33333333, 176.66666667, 178. , 179.33333333, 180.66666667, 182. , 183.33333333, 184.66666667, 186. , 187.33333333, 188.66666667, 190. , 191.33333333, 192.66666667, 194. , 195.33333333, 196.66666667, 198. , 199.33333333, 200.66666667, 202. , 203.33333333, 204.66666667, 206. , 207.33333333, 208.66666667, 210. , 211.33333333, 212.66666667, 214. , 215.33333333, 216.66666667, 218. , 219.33333333, 220.66666667, 222. , 223.33333333, 224.66666667, 226. , 227.33333333, 228.66666667, 230. , 231.33333333, 232.66666667, 234. , 235.33333333, 236.66666667, 238. , 239.33333333, 240.66666667, 242. , 243.33333333, 244.66666667, 246. , 247.33333333, 248.66666667, 250. , 251.33333333, 252.66666667, 254. , 255.33333333, 256.66666667, 258. , 259.33333333, 260.66666667, 262. , 263.33333333, 264.66666667, 266. , 267.33333333, 268.66666667, 270. , 271.33333333, 272.66666667, 274. , 275.33333333, 276.66666667, 278. , 279.33333333, 280.66666667, 282. , 283.33333333, 284.66666667, 286. , 287.33333333, 288.66666667, 290. , 291.33333333, 292.66666667, 294. , 295.33333333, 296.66666667, 298. , 299.33333333, 300.66666667, 302. , 303.33333333, 304.66666667, 306. , 307.33333333, 308.66666667, 310. , 311.33333333, 312.66666667, 314. , 315.33333333, 316.66666667, 318. , 319.33333333, 320.66666667, 322. , 323.33333333, 324.66666667, 326. , 327.33333333, 328.66666667, 330. , 331.33333333, 332.66666667, 334. , 335.33333333, 336.66666667, 338. , 339.33333333, 340.66666667, 342. , 343.33333333, 344.66666667, 346. , 347.33333333, 348.66666667, 350. ])
    • (y, x)
      float64
      counts
      1.0, 1.0, ..., 1.0, 1.0
      Values:
      array([[1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], ..., [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.]], shape=(300, 300))
    • 0
      (x, y)
      bool
      False, False, ..., False, False
      Values:
      array([[False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False], ..., [False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False]], shape=(300, 300))
    • 1
      (x, y)
      bool
      False, False, ..., False, False
      Values:
      array([[False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False], ..., [False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False]], shape=(300, 300))