Drawing a region of interest in a scatter plot and printing the points contained in matplotlib

StackOverflow https://stackoverflow.com/questions/22567533

Domanda

In a scatterplot matrix, I want to draw a region of interest(ROI) and print the points that are contained in that region. For the time being, I can draw regions in the subplots but I do not know how to get and print the points that are contained in the region. A region is drawn, when the shift key and the left mouse button are hold pressed. The region is closed by clicking on the right mouse button, while the shift is hold pressed. Any suggestions about how the printing of the points inside the ROI( a functionality similar to LassoSelector demo) will be appreciated. Thanks in advance!!

Here is the code:

 from pylab import *


 class ROI:

    def __init__(self, axes, fig):
        self.previous_point = []
        self.start_point = []
        self.end_point = []
        self.line = None    

        self.fig =  fig
        self.fig.canvas.draw()

    def motion_notify_callback(self, event):
        if event.inaxes: 
            axes = event.inaxes
            x, y = event.xdata, event.ydata
            if event.button == None and self.line != None and event.key == 'shift': # #Move line around
                self.line.set_data([self.previous_point[0], x],
                                   [self.previous_point[1], y])
                self.fig.canvas.draw()
         elif event.button == 1 and event.key == 'shift': # Free Hand Drawing
                    line = Line2D([self.previous_point[0], x],
                                  [self.previous_point[1], y])
                    axes.add_line(line)
                    self.previous_point = [x, y]
                    self.fig.canvas.draw()


    def button_press_callback(self, event):
        if event.inaxes: 
            x, y = event.xdata, event.ydata
            axes = event.inaxes
            if (event.key == 'shift') and (event.button == 1):  # If you press the right button
                    if self.line == None: # if there is no line, create a line
                        self.line = Line2D([x,  x],
                                           [y, y],
                                           marker = 's')
                        self.start_point = [x,y]
                        self.previous_point =  self.start_point
                        axes.add_line(self.line)
                        self.fig.canvas.draw()
                    # add a segment
                    else: # if there is a line, create a segment
                        self.line = Line2D([self.previous_point[0], x],
                                           [self.previous_point[1], y],
                                           marker = 'o')
                        self.previous_point = [x,y]
                        event.inaxes.add_line(self.line)
                        self.fig.canvas.draw()

            if (event.button == 3) and (event.key == 'shift') and (self.line != None): # close the loop
                        self.line.set_data([self.previous_point[0], self.start_point[0]],
                                           [self.previous_point[1], self.start_point[1]])                       
                        axes.add_line(self.line)
                        self.fig.canvas.draw()
                        self.line = None




def main():
    data = np.random.rand(100,4)
    plt.close("all")
    x, y = data[:, 0], data[:, 1]
    x1, y1 = data[:,2], data[:, 3]
    fig, axes = plt.subplots(ncols=2, nrows=1)
    for ax, marker in zip(axes.flat, ['o', 'o']):



        axes.flat[0].plot(x, y, 'r',  ls='', marker=marker, picker=3)

        axes.flat[1].plot(x, x1,'r', ls='', marker=marker, picker=3)

        cursor = ROI(ax, fig)

    #axes.set_title(" shift+left click: line segment       shift+left pressed: doodle        shift+right click: close region")

    fig.canvas.mpl_connect('motion_notify_event', cursor.motion_notify_callback)
    fig.canvas.mpl_connect('button_press_event', cursor.button_press_callback)
    show()

if __name__ == "__main__":
    main()   
È stato utile?

Soluzione

I think matplotlib has a nice function called matplotlib.nxutils for checking if points are inside polygon or not.

http://matplotlib.org/faq/howto_faq.html#test-whether-a-point-is-inside-a-polygon

You can convert your ROI into polygon and apply nx.points_inside_poly.

(Edit) matplotlib.nxutils has been depreciated and repclaed with matplotlib.path.Path.contains_points. I did not know that. Thanks for head up. Here's a small snippet that uses Path.contains_points.

from pylab import *
from matplotlib.path import Path
import matplotlib.patches as patches

data = np.random.rand(100,4)

verts = [(0.3, 0.7), (0.3, 0.3), (0.7, 0.3), (0.7, 0.7)]

path1 = Path(verts)
index = path1.contains_points(data[:,:2])

print data[index, :2]

plot(data[:,0],data[:,1], 'b.')
patch = patches.PathPatch(path1, facecolor='orange', lw=2)
gca().add_patch(patch)
plot(data[index,0], data[index,1], 'r.')
show()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top