Matplotlib动画:子图中的垂直光标线

2024-10-01 07:39:27 发布

您现在位置:Python中文网/ 问答频道 /正文

[解决方案已添加到本文的编辑部分]

两个动画子图垂直堆叠。在

我想显示一个黑色垂直线通过他们根据鼠标的位置。在

到目前为止,我只能在移动鼠标的时候完全弄乱人物。。。在

如何清除更新之间的旧垂直线?在

(只是出于好奇:由于鼠标的移动控制,我的电脑迷在不移动鼠标的情况下执行代码时会发疯。鼠标这么“计算贵”?!?)在

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from time import sleep

val1 = np.zeros(100)         
val2 = np.zeros(100)      

level1 = 0.2
level2 = 0.5

fig, ax = plt.subplots()

ax1 = plt.subplot2grid((2,1),(0,0))
lineVal1, = ax1.plot(np.zeros(100))
ax1.set_ylim(-0.5, 1.5)    

ax2 = plt.subplot2grid((2,1),(1,0))
lineVal2, = ax2.plot(np.zeros(100), color = "r")
ax2.set_ylim(-0.5, 1.5)    


def onMouseMove(event):
  ax1.axvline(x=event.xdata, color="k")
  ax2.axvline(x=event.xdata, color="k")



def updateData():
  global level1, val1
  global level2, val2

  clamp = lambda n, minn, maxn: max(min(maxn, n), minn)

  level1 = clamp(level1 + (np.random.random()-.5)/20.0, 0.0, 1.0)
  level2 = clamp(level2 + (np.random.random()-.5)/10.0, 0.0, 1.0)

  # values are appended to the respective arrays which keep the last 100 readings
  val1 = np.append(val1, level1)[-100:]
  val2 = np.append(val2, level2)[-100:]

  yield 1     # FuncAnimation expects an iterator

def visualize(i):

  lineVal1.set_ydata(val1)
  lineVal2.set_ydata(val2)

  return lineVal1,lineVal2

fig.canvas.mpl_connect('motion_notify_event', onMouseMove)
ani = animation.FuncAnimation(fig, visualize, updateData, interval=50)
plt.show()

编辑1

由Ophir解决:

^{pr2}$

编辑2

如果同一绘图中有更多数据集,如:

ax1 = plt.subplot2grid((2,1),(0,0))
lineVal1, = ax1.plot(np.zeros(100))
lineVal2, = ax2.plot(np.zeros(100), color = "r")
ax1.set_ylim(-0.5, 1.5)    

每个数据集的行存储在ax1.lines[]

  • ax1.lines[0]lineVal1
  • ax1.lines[1]是{}
  • ax1.lines[2]是垂直线,如果您已经绘制了它。在

这意味着onMouseMove必须更改为:

def onMouseMove(event):
  ax1.lines = ax1.lines[:2] # keep the first two lines
  ax1.axvline(x=event.xdata, color="k") # then draw the vertical line

Tags: eventnpzerosplt鼠标colorlinesset
2条回答

将您的onMouseMove替换为以下内容:

(我用了How to remove lines in a Matplotlib plot

def onMouseMove(event):
  ax1.lines = [ax1.lines[0]]
  ax2.lines = [ax2.lines[0]]
  ax1.axvline(x=event.xdata, color="k")
  ax2.axvline(x=event.xdata, color="k")

不需要在绘图中添加新的axvline,只需更改现有绘图的数据即可。您只需要存储axvline调用的返回值,就可以保留它的句柄。数据格式是([x, x], [0, 1]),可以使用set_data更改它。 (顺便说一下,对于axhlines,格式是([0, 1], [y, y])。)

添加以下全局变量:

axvline1 = ax1.axvline(x=0., color="k")
axvline2 = ax2.axvline(x=0., color="k")

并将conMouseMove处理程序更改为:

^{pr2}$

一个小缺点是从一开始就从x=0的vline开始。在

完整代码:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from time import sleep

val1 = np.zeros(100)         
val2 = np.zeros(100)      

level1 = 0.2
level2 = 0.5

fig, ax = plt.subplots()

ax1 = plt.subplot2grid((2,1),(0,0))
lineVal1, = ax1.plot(np.zeros(100))
ax1.set_ylim(-0.5, 1.5)    

ax2 = plt.subplot2grid((2,1),(1,0))
lineVal2, = ax2.plot(np.zeros(100), color = "r")
ax2.set_ylim(-0.5, 1.5)    

axvline1 = ax1.axvline(x=0., color="k")
axvline2 = ax2.axvline(x=0., color="k")


def onMouseMove(event):
  axvline1.set_data([event.xdata, event.xdata], [0, 1])
  axvline2.set_data([event.xdata, event.xdata], [0, 1])


def updateData():
  global level1, val1
  global level2, val2

  clamp = lambda n, minn, maxn: max(min(maxn, n), minn)

  level1 = clamp(level1 + (np.random.random()-.5)/20.0, 0.0, 1.0)
  level2 = clamp(level2 + (np.random.random()-.5)/10.0, 0.0, 1.0)

  # values are appended to the respective arrays which keep the last 100 readings
  val1 = np.append(val1, level1)[-100:]
  val2 = np.append(val2, level2)[-100:]

  yield 1     # FuncAnimation expects an iterator

def visualize(i):

  lineVal1.set_ydata(val1)
  lineVal2.set_ydata(val2)

  return lineVal1,lineVal2

fig.canvas.mpl_connect('motion_notify_event', onMouseMove)
ani = animation.FuncAnimation(fig, visualize, updateData, interval=50)
plt.show()

相关问题 更多 >