使用滑块matplotlib更新x值

时间:2017-06-09 06:00:14

标签: python matplotlib

我尝试绘制一个图表,显示化学反应的进展。进度本身(时间或反应步骤)应该可以使用滑块进行更改。 我到目前为止的代码:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
fig.canvas.set_window_title('Reaktionsfortschritt')

t0 = 0
t = np.arange(0, t0, .5)
k0 = 0.17
a = np.exp(- k0 * t)

l, = plt.plot(t, a, lw=3, color='crimson')
plt.axis([0, 20, 0, 1])

axrs = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor='lightblue')
srs = Slider(axrs, 'Reaktionsschritte', 0, 20, valinit=0)

def xval(*args):
    x = srs.val
    t = np.arange(0, x, 0.5)
    #l.set_ydata(np.exp(- 0.6 * t))
    #plt.plot(t, a)
    fig.canvas.draw_idle()

srs.on_changed(xval)

plt.show()

据我所知,使用xval函数更新了plot-range(t)。但是,没有图表的绘图。 我尝试使用plt.plot(t, a)l.set_ydata(...)进行重新绘制。

编辑

好的,现在我添加了描述产品形成的第二个功能(b)。我也以与更新功能相同的方式添加了该功能。结果我得到一个非常奇怪的行为:使用滑块,我只能在正x方向绘图,例如在那里我不会回去。绘制图表后,它就会赢得' undraw'减小滑块值时。有什么建议吗?

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
fig.canvas.set_window_title('Reaktionsfortschritt')

t = np.arange(0, 0, .5)
k0 = 0.17
a = np.exp(- k0 * t)
b = 1 - np.exp(- k0 * t)
# plot
l, = plt.plot(t, a, lw=3, color='crimson')
m, = plt.plot(t, b, lw=3, color='dodgerblue')
plt.axis([0, 20, 0, 1])
plt.grid(True)

axrs = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor='lightblue')
srs = Slider(axrs, 'Zeit', 0, 20, valinit=0)

def update(x):
    t = np.arange(0, x, 2)
    ax.lines.pop(0)  # remove previous line plot
    ax.plot(t, np.exp(- k0 * t), lw=3, color='crimson')
    ax.plot(t, 1 - np.exp(- k0 * t), lw=3, color='dodgerblue')
    fig.canvas.draw()

srs.on_changed(update)

plt.show()

1 个答案:

答案 0 :(得分:2)

假设你在x轴上有时间并且想要每次更改由同一个函数创建的绘图的最长时间,我想出了这个:

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

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
fig.canvas.set_window_title('Reaktionsfortschritt')

t0 = 0
t = np.arange(0, t0, .5)
k0 = 0.17
a = np.exp(- k0 * t)

l, = ax.plot(t, a, lw=3, color='crimson')
plt.axis([0, 20, 0, 1])

axrs = plt.axes([0.25, 0.1, 0.65, 0.03])
srs = Slider(axrs, 'Reaktionsschritte', 0, 20, valinit=0)

def update(x):
    t0 = x
    t = np.arange(0, t0, .5)
    ax.lines.pop(0)  # remove previous line plot
    ax.plot(t, np.exp(- k0 * t), lw=3, color='crimson')  # plot new one
    fig.canvas.draw()

srs.on_changed(update)

plt.show()

查看更改Slider值时的作用,并告诉我这是否是您想要它做的。

要编辑:
添加第二个绘图时,您有两个lines个对象。在运行代码之后(在触摸Slider之前)尝试直接打印ax.lines并看到它确实是两个lines的列表。然后调用ax.lines.pop(0)并查看列表中是否弹出了一个元素。这就是上面的代码所做的事情,每次触摸Slider时都会从axes对象ax中删除行(因为之后调用了update),在调用{{ 1}}导致以前的情节消失。如果您现在触摸Slider一次,则会向fig.canvas.draw()添加两个新的lines,并且只会移除一个ax。这就是为什么你认为没有回头的原因 因此,如果您现在添加了第二个图,则只需使用ax.lines从列表ax.lines.pop(0)中弹出两次,代码就可以正常运行; - )