Getting lasso to work properly on subplots in matplotlib

I want to create a scatter plot matrix that will consist of some subplots. I extracted my data from the TXT file and created an array of the form (x,y,z,p1,p2,p3,p4). The first three columns of the array represent the x, y, z coordinates from the original image from which this data comes from, and the last four columns (p1, p2, p3, p4) are some other parameters. Therefore, in each row of the array, the parameters p1, p2, p3, p4 have the same coordinates (x, y, z). In the scatter plot, I want to visualize each parameter p_i (e.g. p1) with respect to another p_i (e.g. p2, p3, p4).

I want to draw an area of ​​interest (ROI) in each subtitle, highlight the points that are included in the ROI in each subtitle. In each subheading, various parameters are visualized (for example, p1 vs p2), but for one point in each subheading there is another point with the same coordinates x, y, z in the remaining subsets. I implemented a ROI drawing using the Lassomatplotlib example . An example of how this code is implemented is shown in the following figure.Figure 1

There is a malfunction in my implementation. I can draw a lasso in each subtitle, but the dots are highlighted only when lasso is drawn in a specific subtitle, which corresponds to the first function call LassoManagerin my code (in my code selector1). As you can see in the following figure, the initial value is assigned to lassos, which can be drawn in different subheadings, but only the identifier that matches in selector 1 is used, which causes a code malfunction, regardless of which subheading I drew the ROI.

Figure 2

Here is my code:

"""
Show how to use a lasso to select a set of points and get the indices
of the selected points.  A callback is used to change the color of the
selected points

This is currently a proof-of-concept implementation (though it is
usable as is).  There will be some refinement of the API.
"""


from matplotlib.widgets import Lasso
from matplotlib.colors import colorConverter
from matplotlib.collections import RegularPolyCollection
from matplotlib import path


import matplotlib.pyplot as plt
import numpy as np

class Datum(object):
      colorin = colorConverter.to_rgba('red')
      colorout = colorConverter.to_rgba('blue')
      def __init__(self, x, y, include=False):
          self.x = x
          self.y = y
          if include: self.color = self.colorin
          else: self.color = self.colorout

class LassoManager(object):
    #class for highlighting region of points within a Lasso
      def __init__(self, ax, data):


          self.axes = ax
          self.canvas = ax.figure.canvas
          self.data = data
          self.Nxy = len(data)

          facecolors = [d.color for d in data]
          self.xys = [(d.x, d.y) for d in data]
          fig = ax.figure
          self.collection = RegularPolyCollection(
             fig.dpi, 6, sizes=(1,),
             facecolors=facecolors,
             offsets = self.xys,
             transOffset = ax.transData)

          ax.add_collection(self.collection)

          self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)

      def callback(self, verts):
          facecolors = self.collection.get_facecolors()
          print "The id of this lasso is", id(self)


          p = path.Path(verts)
          ind = p.contains_points(self.xys)
          #ind prints boolean array of points in subplot where true means that the point is included

          for i in range(len(self.xys)):


              if ind[i]:

                # facecolors[i] = Datum.colorin
                axes[0][0].plot(x[i], y[i], 'ro',  ls='',  picker=3)
                axes[2][0].plot(x[i], y1[i], 'ro',  ls='',  picker=3)
                axes[1][0].plot(x[i], x1[i], 'ro',  ls='',  picker=3)
                axes[1][4].plot(y[i], x1[i], 'ro',  ls='',  picker=3)
                axes[2][5].plot(x1[i], y1[i], 'ro',  ls='',  picker=3)
                axes[2][6].plot(y[i], y1[i], 'ro',  ls='',  picker=3)
                # print ind[i], x[i], y[i], x1[i], y1[i]

              else:

                # facecolors[i] = Datum.colorout
                axes[0][0].plot(x[i], y[i], 'bo',  ls='',  picker=3)
                axes[2][0].plot(x[i], y1[i], 'bo',  ls='',  picker=3)
                axes[1][0].plot(x[i], x1[i], 'bo',  ls='',  picker=3)
                axes[1][7].plot(y[i], x1[i], 'bo',  ls='',  picker=3)
                axes[2][8].plot(x1[i], y1[i], 'bo',  ls='',  picker=3)
                axes[2][9].plot(y[i], y1[i], 'bo',  ls='',  picker=3)

          plt.draw()


          self.canvas.draw_idle()
          self.canvas.widgetlock.release(self.lasso)
          del self.lasso
          # noinspection PyArgumentList


      def onpress(self, event):
          if self.canvas.widgetlock.locked(): return
          if event.inaxes is None: return

          self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback)

          # acquire a lock on the widget drawing
          self.canvas.widgetlock(self.lasso)




if __name__ == '__main__':

   dat = np.loadtxt(r"parameters.txt")
   x, y = dat[:, 3], dat[:, 4]  #p1,p2
   x1, y1 = dat[:, 5], dat[:, 6]  #p3,p4

   a = np.array([x,y])  #p1,p2
   a = a.transpose()

   b = np.array([x,y1])  #p1,p4
   b = b.transpose()

   c = np.array([x,x1])  #p1,p3
   c = c.transpose()

   d = np.array([y,x1])  #p3,p2
   d = d.transpose()

   e = np.array([x1,y1])  #p3,p4
   e = e.transpose()

   f = np.array([y,y1])  ##p2, p4
   f = f.transpose()


   data = []

   data0 = [Datum(*xy) for xy in a]   #p1,p2
   data.append(data0)
   data1 = [Datum(*xy) for xy in b]   #p1,p4
   data.append(data1)
   data2 = [Datum(*xy) for xy in c]   #p1,p3
   data.append(data2)
   data3 = [Datum(*xy) for xy in d]   #p3,p2
   data.append(data3)
   data4 = [Datum(*xy) for xy in e]   #p3,p4
   data.append(data4)
   data5 = [Datum(*xy) for xy in f]   #p2, p4
   data.append(data5)

   #print data
   #print len(data)

   fig, axes = plt.subplots(ncols=3, nrows=3)

   axes[0][0].plot(x, y, 'bo',  ls='',  picker=3)
   axes[0][0].set_xlabel('p1')
   axes[0][0].set_ylabel('p2')
   axes[0][0].set_xlim((min(x)-50, max(x)+50))
   axes[0][0].set_ylim((min(y)-50, max(y)+50))
   selector1 = LassoManager(axes[0][0], data[0])
   print "selector1 is", id(selector1)      #lman.append(l1)

   #p1 vs p4
   axes[2][0].plot(x, y1, 'bo',  ls='',  picker=3)
   axes[2][0].set_xlabel('p1')
   axes[2][0].set_ylabel('p4')
   axes[2][0].set_xlim((min(x)-50, max(x)+50))
   axes[2][0].set_ylim((min(y1)-40, max(y1)+50))
   selector2 = LassoManager(axes[2][0], data[1])
   print "selector2 is", id(selector2)


   #p1 vs p3
   axes[1][0].plot(x, x1, 'bo',  ls='',  picker=3)
   axes[1][0].set_xlabel('p1')
   axes[1][0].set_ylabel('p3')
   axes[1][0].set_xlim((min(x)-50, max(x)+50))
   axes[1][0].set_ylim((min(x1)-40, max(x1)+50))
   selector3 = LassoManager(axes[1][0], data[2])
   print "selector3 is", id(selector3)

   #p2 vs p3
   axes[1][10].plot(y, x1, 'bo',  ls='',  picker=3)
   axes[1][11].set_xlabel('p2')
   axes[1][12].set_ylabel('p3')
   axes[1][13].set_xlim((min(y)-50, max(y)+50))
   axes[1][14].set_ylim((min(x1)-40, max(x1)+50))
   selector4 =  LassoManager(axes[1][15], data[3])
   print "selector4 is", id(selector4)




   #p2 vs p4
   axes[2][16].plot(y, y1, 'bo',  ls='',  picker=3)
   axes[2][17].set_xlabel('p2')
   axes[2][18].set_ylabel('p4')
   axes[2][19].set_xlim((min(y)-50, max(y)+50))
   axes[2][20].set_ylim((min(y1)-40, max(y1)+50))
   selector5 = LassoManager(axes[2][21], data[5])
   print "selector5 is", id(selector5)


   #p3 vs p4
   axes[2][22].plot(x1, y1, 'bo',  ls='',  picker=3)
   axes[2][23].set_xlabel('p3')
   axes[2][24].set_ylabel('p4')
   axes[2][25].set_xlim((min(x1)-50, max(x1)+50))
   axes[2][26].set_ylim((min(y1)-40, max(y1)+50))
   selector6 = LassoManager(axes[2][27], data[4])
   print "selector6 is", id(selector6)


   #non-visible subplots
   axes[0][28].plot(x,x)
   axes[0][29].set_visible(False)
   axes[0][30].plot(y,y)
   axes[0][31].set_visible(False)
   axes[1][32].plot(x1,x1)
   axes[1][33].set_visible(False)

   plt.subplots_adjust(left=0.1, right=0.95, wspace=0.6, hspace=0.7)

   plt.show()

Why is this happening in my code? There is no error in the code, but it does not work correctly. Any help would be appreciated!

+4
1

, , , init button_press_event .

, button_press_event ( canvas).

FIX

, lasso .

, , , LassoManager ( ), , .. .

current_axis, , .

"""
Show how to use a lasso to select a set of points and get the indices
of the selected points.  A callback is used to change the color of the
selected points

This is currently a proof-of-concept implementation (though it is
usable as is).  There will be some refinement of the API.
"""
from matplotlib.widgets import Lasso
from matplotlib.colors import colorConverter
from matplotlib.collections import RegularPolyCollection
from matplotlib import path

import matplotlib.pyplot as plt
from numpy import nonzero
from numpy.random import rand

class Datum(object):
    colorin = colorConverter.to_rgba('red')
    colorout = colorConverter.to_rgba('blue')
    def __init__(self, x, y, include=False):
        self.x = x
        self.y = y
        if include: self.color = self.colorin
        else: self.color = self.colorout


class LassoManager(object):
    def __init__(self, ax, data):
        self.axes = [ax]
        self.canvas = ax.figure.canvas
        self.data = [data]

        self.Nxy = [ len(data) ]

        facecolors = [d.color for d in data]
        self.xys = [ [(d.x, d.y) for d in data] ]
        fig = ax.figure
        self.collection = [ RegularPolyCollection(
            fig.dpi, 6, sizes=(100,),
            facecolors=facecolors,
            offsets = self.xys[0],
            transOffset = ax.transData)]

        ax.add_collection(self.collection[0])

        self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)

    def callback(self, verts):

        axind = self.axes.index(self.current_axes)
        facecolors = self.collection[axind].get_facecolors()
        p = path.Path(verts)
        ind = p.contains_points(self.xys[axind])
        for i in range(len(self.xys[axind])):
            if ind[i]:
                facecolors[i] = Datum.colorin
            else:
                facecolors[i] = Datum.colorout

        self.canvas.draw_idle()
        self.canvas.widgetlock.release(self.lasso)
        del self.lasso

    def onpress(self, event):
        if self.canvas.widgetlock.locked(): return
        if event.inaxes is None: return
        self.current_axes = event.inaxes

        self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback)
        # acquire a lock on the widget drawing
        self.canvas.widgetlock(self.lasso)

    def add_axis(self, ax,  data):
        self.axes.append(ax)
        self.data.append(data)

        self.Nxy.append( len(data) )

        facecolors = [d.color for d in data]
        self.xys.append( [(d.x, d.y) for d in data] )
        fig = ax.figure
        self.collection.append( RegularPolyCollection(
            fig.dpi, 6, sizes=(100,),
            facecolors=facecolors,
            offsets = self.xys[-1],
            transOffset = ax.transData))

        ax.add_collection(self.collection[-1])



if __name__ == '__main__':

    data = [Datum(*xy) for xy in rand(100, 2)]
    data2 = [Datum(*xy) for xy in rand(100, 2)]

    ax = plt.subplot(1,2,1)
    lman = LassoManager(ax, data)
    ax2 = plt.subplot(1,2,2)
    lman.add_axis(ax2, data2)
    plt.show()
+2

Source: https://habr.com/ru/post/1538451/


All Articles