繁体   English   中英

可拖动的Matplotlib散点图使用blitting进行动画绘制

[英]Draggable Matplotlib scatter with an animated plot using blitting

我最近问了一个有关创建可拖动散点图的问题,在我能够提出一个可行示例的帮助下。 请参阅“ PathCollection”不可迭代-创建可拖动的散点图

我现在正尝试使用通过blitting动画情节创建的DraggableScatter类。

我尝试在多个位置附加DraggableScatter类,例如,在初始化分散之后,在init函数和update函数中。 在第一种情况下,DraggableScatter的散点为空,这是有道理的,但显然不起作用。 在其他两个中,似乎没有捕获到点击。

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

class DraggableScatter():

    epsilon = 5

    def __init__(self, scatter):
        self.scatter = scatter
        self._ind = None
        self.ax = scatter.axes
        self.canvas = self.ax.figure.canvas
        self.canvas.mpl_connect('button_press_event', self.button_press_callback)
        self.canvas.mpl_connect('button_release_event', self.button_release_callback)
        self.canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)


    def get_ind_under_point(self, event):   
        xy = np.asarray(self.scatter.get_offsets())
        xyt = self.ax.transData.transform(xy)
        xt, yt = xyt[:, 0], xyt[:, 1]

        d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
        ind = d.argmin()

        if d[ind] >= self.epsilon:
            ind = None

        return ind

    def button_press_callback(self, event):
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        self._ind = self.get_ind_under_point(event)

    def button_release_callback(self, event):
        if event.button != 1:
            return
        self._ind = None

    def motion_notify_callback(self, event):
        if self._ind is None:
            return
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        x, y = event.xdata, event.ydata
        xy = np.asarray(self.scatter.get_offsets())
        xy[self._ind] = np.array([x, y])        
        self.scatter.set_offsets(xy)
        self.canvas.draw_idle()


fig, ax = plt.subplots(1, 1)
scatter = ax.scatter([],[])


def init():
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 1)

    return scatter,

def update(frame):
    scatter = ax.scatter(np.random.rand(10), np.random.rand(10), marker ='o')
    ds = DraggableScatter(scatter)
    return scatter,

ani = FuncAnimation(fig=fig, func=update, init_func=init, blit=True, interval=5000)
plt.show()

什么是正确的方法?

与GTK3Cairo后端一起使用。 (使用TkAgg,Qt4Agg,Qt5Agg,GTK3Agg无效。)

创建一次DraggableScatter ,然后使用ds.scatter.set_offsetsupdate函数中更改散点数据:

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

class DraggableScatter():

    epsilon = 5

    def __init__(self, scatter):
        self.scatter = scatter
        self._ind = None
        self.ax = scatter.axes
        self.canvas = self.ax.figure.canvas
        self.canvas.mpl_connect('button_press_event', self.button_press_callback)
        self.canvas.mpl_connect('button_release_event', self.button_release_callback)
        self.canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)


    def get_ind_under_point(self, event):   
        xy = np.asarray(self.scatter.get_offsets())
        xyt = self.ax.transData.transform(xy)
        xt, yt = xyt[:, 0], xyt[:, 1]

        d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
        ind = d.argmin()

        if d[ind] >= self.epsilon:
            ind = None

        return ind

    def button_press_callback(self, event):
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        self._ind = self.get_ind_under_point(event)

    def button_release_callback(self, event):
        if event.button != 1:
            return
        self._ind = None

    def motion_notify_callback(self, event):
        if self._ind is None:
            return
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        x, y = event.xdata, event.ydata
        xy = np.asarray(self.scatter.get_offsets())
        xy[self._ind] = np.array([x, y])        
        self.scatter.set_offsets(xy)
        self.canvas.draw_idle()


fig, ax = plt.subplots(1, 1)
scatter = ax.scatter(np.random.rand(10), np.random.rand(10), marker ='o')
ds = DraggableScatter(scatter)

def init():
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 1)
    return ds.scatter,

def update(frame, ds):
    x, y = np.random.rand(10), np.random.rand(10)
    ds.scatter.set_offsets(np.column_stack([x, y]))
    return ds.scatter,

ani = FuncAnimation(fig=fig, func=update, init_func=init, fargs=[ds], blit=True, 
                    interval=5000)
plt.show()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM