使用matplotlib的动画交互式绘图 [英] Animated interactive plot using matplotlib

查看:179
本文介绍了使用matplotlib的动画交互式绘图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在寻找一种使用matplotlib制作动画交互式绘图的方法时,我在堆栈溢出文档中遇到了这段代码:

While looking for a way to make animated interactive plot using matplotlib, I encountered this piece of code on Stack overflow documentation:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.widgets import Slider

TWOPI = 2*np.pi

fig, ax = plt.subplots()

t = np.arange(0.0, TWOPI, 0.001)
initial_amp = .5
s = initial_amp*np.sin(t)
l, = plt.plot(t, s, lw=2)

ax = plt.axis([0,TWOPI,-1,1])

axamp = plt.axes([0.25, .03, 0.50, 0.02])
# Slider
samp = Slider(axamp, 'Amp', 0, 1, valinit=initial_amp)

def update(val):
    # amp is the current value of the slider
    amp = samp.val
    # update curve
    l.set_ydata(amp*np.sin(t))
    # redraw canvas while idle
    fig.canvas.draw_idle()

# call update function on slider value change
samp.on_changed(update)

plt.show()

这段代码几乎可以完全满足我的要求,但是我希望对绘图进行动画处理,即使滑块自动从左向右移动,例如每秒移动0.01.有没有简单的方法可以做到这一点?知道我还想将手动控件保留在滑块上(使用click事件).

This code does almost exactly what I'm looking for, but I would wish to animate the plot, i.e. make the slider moves automatically from left to right, for instance progressing of 0.01 every second. Is there any simple way of doing that? Knowing that I also want to keep the manual control on the slider (using click event).

推荐答案

下面是对代码的简单修改,以添加动画:

Here is a simple adaptation of your code to add animation:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.widgets import Slider

TWOPI = 2*np.pi

fig, ax = plt.subplots()

t = np.arange(0.0, TWOPI, 0.001)
initial_amp = .5
s = initial_amp*np.sin(t)
l, = plt.plot(t, s, lw=2)

ax = plt.axis([0,TWOPI,-1,1])

axamp = plt.axes([0.25, .03, 0.50, 0.02])
# Slider
samp = Slider(axamp, 'Amp', 0, 1, valinit=initial_amp)

# Animation controls
is_manual = False # True if user has taken control of the animation
interval = 100 # ms, time between animation frames
loop_len = 5.0 # seconds per loop
scale = interval / 1000 / loop_len

def update_slider(val):
    global is_manual
    is_manual=True
    update(val)

def update(val):
    # update curve
    l.set_ydata(val*np.sin(t))
    # redraw canvas while idle
    fig.canvas.draw_idle()

def update_plot(num):
    global is_manual
    if is_manual:
        return l, # don't change

    val = (samp.val + scale) % samp.valmax
    samp.set_val(val)
    is_manual = False # the above line called update_slider, so we need to reset this
    return l,

def on_click(event):
    # Check where the click happened
    (xm,ym),(xM,yM) = samp.label.clipbox.get_points()
    if xm < event.x < xM and ym < event.y < yM:
        # Event happened within the slider, ignore since it is handled in update_slider
        return
    else:
        # user clicked somewhere else on canvas = unpause
        global is_manual
        is_manual=False

# call update function on slider value change
samp.on_changed(update_slider)

fig.canvas.mpl_connect('button_press_event', on_click)

ani = animation.FuncAnimation(fig, update_plot, interval=interval)

plt.show()

主要变化是添加了update_plot函数,该函数用于在倒数第二行中创建FuncAnimation.动画从设置的最后一个滑块值开始递增.

The main change is the addition of the update_plot function, which is used to make a FuncAnimation in the second to last line. The animation increments from the last slider value that was set.

变量is_manual跟踪用户何时单击滑块.用户单击它后,变量将设置为True,动画将不再更新绘图.

The variable is_manual keeps track of when the user has clicked on the slider. After the user clicks on it, the variable is set to True and the animation will no longer update the plot.

要恢复动画,我添加了一个on_click函数,当用户单击画布上除滑块以外的其他位置时,该函数会设置is_manual = False.

To resume animation, I added an on_click function which sets is_manual = False when the user clicks somewhere on the canvas OTHER than the slider.

由于这是一个快速处理的脚本,因此我将变量保留为全局变量,但您可以轻松地将其编写在适当的类中.

Since this is a quick-and-dirty script I left variables as global, but you could easily write it up in a proper class.

请注意,调用samp.set_val会隐式调用update_slider函数,当用户直接单击滑块时也会调用该函数,因此我们必须在update_plot函数中重置is_manual.

Note that calling samp.set_val implicitly calls the update_slider function, which is also called when the user clicks directly on the slider, so we have to reset is_manual in the update_plot function.

这篇关于使用matplotlib的动画交互式绘图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆