Matplotlib EllipseSelector - 如何获取路径?
Matplotlib EllipseSelector - how to get the path?
下面是 matplotlib 小部件的基本示例 EllipseSelector。顾名思义,此小部件用于通过在轴上绘制椭圆来 select 数据。
确切地说,用户可以通过在轴上单击并拖动来绘制和修改椭圆。每次释放鼠标按钮时都会调用回调函数(例如:onselect)。
这是示例:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import EllipseSelector
class EllipseExample:
def __init__(self):
# creating data points
self.X, self.Y = (0, 1, 2), (0, -1, -2)
self.XY = np.asarray((self.X, self.Y)).T
# plotting
self.fig, self.ax = plt.subplots()
self.ax.scatter(self.X, self.Y) # just for visualization
# creating the EllipseSelector
self.es = EllipseSelector(self.ax, self.onselect,
drawtype='box', interactive=True)
# bool array about selection status of XY rows.
self.selection_bool = None # e.g. (False, True, False)
plt.show()
# selector callback method
def onselect(self, eclick, erelease):
print('click: (%f, %f)' % (eclick.xdata, eclick.ydata))
print('release : (%f, %f)' % (erelease.xdata, erelease.ydata))
# how to get the path of the selector's ellipse?
# path = self.es.??? <--- no clue how to get there
# self.selection_bool = path.contains_points(self.XY)
# print('selection:\n', self.selection_bool)
example = EllipseExample()
我使用过其他 matplotlib selection 小部件(PolygonSelector、RectangleSelector、LassoSelector)。这些都是return selection顶点对应selection形状,可以用来直接过滤数据(例如RectangleSelector给出x0,x1,y0,y1坐标矩形范围)或创建路径并通过 path.contains_points 检查数据是否在 selection.
内
基本上我在问:
我怎样才能将 EllipseSelector 用于绘图和椭圆以及 selector 部分?如何获取绘制椭圆的路径,以便我可以通过 path.contains_points 检查我的数据,如上例中的注释中所建议的那样。
似乎没有直接的方法可以通过 .contains_points()
检查点是否包含在选择器中。我能找到的最简单的方法是根据 EllipseSelector 的属性创建一个椭圆面片。这些属性继承自 RectangleSelector btw。
通过将选区的中心、宽度和高度传递给 matplotlib.patches.Ellipse
,我们得到一个椭圆面片,我们可以在其上调用方法 contains_points()
。此方法returns一个bool ndarray,每个元素对应一个数据点(True:选择包含点,False:选择不包含点)。
所述 bool 数组可用于例如过滤 pandas 数据框。
注意:在任何情况下都不要将此补丁添加到轴上(即不要绘制此补丁),因为它的坐标将被转换,如果没有转换步骤,您将无法再检查原始数据。
这是一个循序渐进的初学者友好示例,带有详细的代码注释:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import EllipseSelector
from matplotlib.patches import Ellipse
class EllipseSelectorExample:
def __init__(self):
# creating data points as numpy arrays
self.X = np.asarray((0, 1, 2, 3, 4, 5, 6))
self.Y = np.asarray((0, 0, 0, 0, 0, 0, 0))
# plotting
self.fig, self.ax = plt.subplots()
self.ax.set_xlim(-1, 7), self.ax.set_ylim(-3, 3)
self.ax.grid(True)
self.ax.scatter(self.X, self.Y)
# creating the EllipseSelector and connecting it to onselect
self.es = EllipseSelector(self.ax, self.onselect,
drawtype='box', interactive=True)
plt.show()
# selector callback method
def onselect(self, eclick, erelease):
# 1. Collect ellipse parameters (center, width, height)
# getting the center property of the drawn ellipse
cx, cy = self.es.center # tuple of floats: (x, y)
# calculating the width and height
# self.es.extents returns tuple of floats: (xmin, xmax, ymin, ymax)
xmin, xmax, ymin, ymax = self.es.extents
width = xmax - xmin
height = ymax - ymin
print(f'center=({cx:.2f},{cy:.2f}), '
f'width={width:.2f}, height={height:.2f}')
# 2. Create an ellipse patch
# CAUTION: DO NOT PLOT (==add this patch to ax), as the coordinates will
# be transformed and you will not be able to directly check your data
# points.
ellipse = Ellipse((cx,cy), width, height)
# 3. Check which points are contained in the ellipse by directly calling
# contains_points on the ellipse.
# contains_points wants input like ( (x0,y0), (x1,y1), ... )
# X=x0,x1,... Y=y0,y1,... -> [ [x0,y0], [x1,y1], [x2,y2], ... ]
XY = np.asarray((self.X, self.Y)).T
# calling contains_plot and returning our filter ndarray
filter_array = ellipse.contains_points(XY)
# 4. Apply filter to your data (optional)
X_filtered = self.X[filter_array]
Y_filtered = self.Y[filter_array]
# results:
print(f'\n'
f'original data:\nX={self.X}\nY={self.Y}\n'
f'filter_array={filter_array}\n'
f'resulting data:\nX={X_filtered}\nY={Y_filtered}')
example = EllipseSelectorExample()
这是上面例子的一个简短版本,检查要点只有 3 行代码:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import EllipseSelector
from matplotlib.patches import Ellipse
class EllipseSelectorExample:
def __init__(self):
self.MYDATA = np.array([[0, 1, 2, 3, 4, 5, 6],
[0, 0, 0, 0, 0, 0, 0]])
self.fig, self.ax = plt.subplots()
self.ax.set_xlim(-1, 7), self.ax.set_ylim(-3, 3), self.ax.grid(True)
self.ax.scatter(self.MYDATA[0], self.MYDATA[1])
self.es = EllipseSelector(self.ax, self.onselect,
drawtype='box', interactive=True)
plt.show()
# selector callback method
def onselect(self, eclick, erelease):
ext = self.es.extents
ellipse = Ellipse(self.es.center, ext[1]-ext[0], ext[3]-ext[2])
# result:
print(ellipse.contains_points(self.MYDATA.T))
example = EllipseSelectorExample()
下面是 matplotlib 小部件的基本示例 EllipseSelector。顾名思义,此小部件用于通过在轴上绘制椭圆来 select 数据。
确切地说,用户可以通过在轴上单击并拖动来绘制和修改椭圆。每次释放鼠标按钮时都会调用回调函数(例如:onselect)。
这是示例:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import EllipseSelector
class EllipseExample:
def __init__(self):
# creating data points
self.X, self.Y = (0, 1, 2), (0, -1, -2)
self.XY = np.asarray((self.X, self.Y)).T
# plotting
self.fig, self.ax = plt.subplots()
self.ax.scatter(self.X, self.Y) # just for visualization
# creating the EllipseSelector
self.es = EllipseSelector(self.ax, self.onselect,
drawtype='box', interactive=True)
# bool array about selection status of XY rows.
self.selection_bool = None # e.g. (False, True, False)
plt.show()
# selector callback method
def onselect(self, eclick, erelease):
print('click: (%f, %f)' % (eclick.xdata, eclick.ydata))
print('release : (%f, %f)' % (erelease.xdata, erelease.ydata))
# how to get the path of the selector's ellipse?
# path = self.es.??? <--- no clue how to get there
# self.selection_bool = path.contains_points(self.XY)
# print('selection:\n', self.selection_bool)
example = EllipseExample()
我使用过其他 matplotlib selection 小部件(PolygonSelector、RectangleSelector、LassoSelector)。这些都是return selection顶点对应selection形状,可以用来直接过滤数据(例如RectangleSelector给出x0,x1,y0,y1坐标矩形范围)或创建路径并通过 path.contains_points 检查数据是否在 selection.
内
基本上我在问:
我怎样才能将 EllipseSelector 用于绘图和椭圆以及 selector 部分?如何获取绘制椭圆的路径,以便我可以通过 path.contains_points 检查我的数据,如上例中的注释中所建议的那样。
似乎没有直接的方法可以通过 .contains_points()
检查点是否包含在选择器中。我能找到的最简单的方法是根据 EllipseSelector 的属性创建一个椭圆面片。这些属性继承自 RectangleSelector btw。
通过将选区的中心、宽度和高度传递给 matplotlib.patches.Ellipse
,我们得到一个椭圆面片,我们可以在其上调用方法 contains_points()
。此方法returns一个bool ndarray,每个元素对应一个数据点(True:选择包含点,False:选择不包含点)。
所述 bool 数组可用于例如过滤 pandas 数据框。
注意:在任何情况下都不要将此补丁添加到轴上(即不要绘制此补丁),因为它的坐标将被转换,如果没有转换步骤,您将无法再检查原始数据。
这是一个循序渐进的初学者友好示例,带有详细的代码注释:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import EllipseSelector
from matplotlib.patches import Ellipse
class EllipseSelectorExample:
def __init__(self):
# creating data points as numpy arrays
self.X = np.asarray((0, 1, 2, 3, 4, 5, 6))
self.Y = np.asarray((0, 0, 0, 0, 0, 0, 0))
# plotting
self.fig, self.ax = plt.subplots()
self.ax.set_xlim(-1, 7), self.ax.set_ylim(-3, 3)
self.ax.grid(True)
self.ax.scatter(self.X, self.Y)
# creating the EllipseSelector and connecting it to onselect
self.es = EllipseSelector(self.ax, self.onselect,
drawtype='box', interactive=True)
plt.show()
# selector callback method
def onselect(self, eclick, erelease):
# 1. Collect ellipse parameters (center, width, height)
# getting the center property of the drawn ellipse
cx, cy = self.es.center # tuple of floats: (x, y)
# calculating the width and height
# self.es.extents returns tuple of floats: (xmin, xmax, ymin, ymax)
xmin, xmax, ymin, ymax = self.es.extents
width = xmax - xmin
height = ymax - ymin
print(f'center=({cx:.2f},{cy:.2f}), '
f'width={width:.2f}, height={height:.2f}')
# 2. Create an ellipse patch
# CAUTION: DO NOT PLOT (==add this patch to ax), as the coordinates will
# be transformed and you will not be able to directly check your data
# points.
ellipse = Ellipse((cx,cy), width, height)
# 3. Check which points are contained in the ellipse by directly calling
# contains_points on the ellipse.
# contains_points wants input like ( (x0,y0), (x1,y1), ... )
# X=x0,x1,... Y=y0,y1,... -> [ [x0,y0], [x1,y1], [x2,y2], ... ]
XY = np.asarray((self.X, self.Y)).T
# calling contains_plot and returning our filter ndarray
filter_array = ellipse.contains_points(XY)
# 4. Apply filter to your data (optional)
X_filtered = self.X[filter_array]
Y_filtered = self.Y[filter_array]
# results:
print(f'\n'
f'original data:\nX={self.X}\nY={self.Y}\n'
f'filter_array={filter_array}\n'
f'resulting data:\nX={X_filtered}\nY={Y_filtered}')
example = EllipseSelectorExample()
这是上面例子的一个简短版本,检查要点只有 3 行代码:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import EllipseSelector
from matplotlib.patches import Ellipse
class EllipseSelectorExample:
def __init__(self):
self.MYDATA = np.array([[0, 1, 2, 3, 4, 5, 6],
[0, 0, 0, 0, 0, 0, 0]])
self.fig, self.ax = plt.subplots()
self.ax.set_xlim(-1, 7), self.ax.set_ylim(-3, 3), self.ax.grid(True)
self.ax.scatter(self.MYDATA[0], self.MYDATA[1])
self.es = EllipseSelector(self.ax, self.onselect,
drawtype='box', interactive=True)
plt.show()
# selector callback method
def onselect(self, eclick, erelease):
ext = self.es.extents
ellipse = Ellipse(self.es.center, ext[1]-ext[0], ext[3]-ext[2])
# result:
print(ellipse.contains_points(self.MYDATA.T))
example = EllipseSelectorExample()