[PYTHON] GUI box area selection on Matplotlib plots

Introduction

I wrote the code to select the box area with the mouse on the plot of matplotlib and obtain the result (coordinates). To achieve this, we use a module called matplotlib.widgets. Of course, [sample code] [sample code] listed in matplotlib.org is fine, but since coordinates cannot be stored as it is, it is necessary to implement it as in the following class. I think there is. Also, I arranged it so that the colored box remains after the area is confirmed (in [Sample code] [sample code], the box disappears after confirmation).

rectselect.py Import and use the following rectselect.py as a module. Since the release function is involved in arranging colored boxes, if you want to delete the box after confirmation, you can comment out the line related to release.

rectselect.py


import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.widgets import RectangleSelector

class RectSelect(object):
    def __init__(self, ax=None):
        self.ax = ax or plt.gca()
        self.rect = Rectangle((0,0), 0, 0, color='orange', alpha=0.5)
        self.ax.add_patch(self.rect)
        self.blc = np.zeros(2)
        self.trc = np.zeros(2)

        def selector(event):
            if event.key in ['Q', 'q'] and selector.RS.active:
                print ('RectSelect deactivated.')
                selector.RS.set_active(False)
            if event.key in ['A', 'a'] and not selector.RS.active:
                print ('RectSelect activated.')
                selector.RS.set_active(True)

        selector.RS = RectangleSelector(self.ax, self.callback)
        self.ax.figure.canvas.mpl_connect('key_press_event', selector)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.release)

    def callback(self, eclick, erelease):
        x0, x1 = eclick.xdata, erelease.xdata
        y0, y1 = eclick.ydata, erelease.ydata
        self.blc = min(x0, x1), min(y0, y1)
        self.trc = max(x0, x1), max(y0, y1)
        blc_print = '({:0.4},{:0.4})'.format(*self.blc)
        trc_print = '({:0.4},{:0.4})'.format(*self.trc)
        print('blc={}, trc={}'.format(blc_print, trc_print))

    def release(self, event):
        self.rect.set_width(self.trc[0] - self.blc[0])
        self.rect.set_height(self.trc[1] - self.blc[1])
        self.rect.set_xy(self.blc)
        self.ax.figure.canvas.draw()

Sample code

In actual use, it works if you put a RectSelect instance just beforeplt.show (). You can also explicitly specify the target ʻaxes`. Below is the actual operation.

python


import numpy as np
import matplotlib.pyplot as plt
from rectselect import RectSelect
#Something plot
x = np.random.random(20) * 10
y = np.random.random(20) * 10
plt.plot(x,y,'.')
#Box selection
region = RectSelect()
plt.show()
#Bottom left of the box(blc)And upper right(trc)Show coordinates of
print(region.blc) # --> (2.338709677419355, 3.7239583333333335)
print(region.trc) # --> (8.4879032258064502, 8.671875)

Box selected

The selected area is displayed surrounded by a line. select.png

After confirming the box selection

The selected area is filled and displayed. release.png

Recommended Posts

GUI box area selection on Matplotlib plots
View matplotlib plots on Tensorboard
Multiple file processing with Kivy + Matplotlib + Draw Graph on GUI