[英]Using matplotlib.animate to animate a contour plot in python
[英]matplotlib.animate in python using multiprocessing
我正在尝试使用 python 进程为 plot 设置动画,如下所示:
from multiprocessing import Process
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
process_enabled = 1;
print("Process enabled: ", process_enabled)
x = []
y = []
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
def start_animation():
# Set up plot to call animate() function periodically
ani = animation.FuncAnimation(fig, animate, fargs=(x, y), interval=1000)
print("Called animate function")
plt.show()
# This function is called periodically from FuncAnimation
def animate(i, xs, ys):
fx=[0.045,0.02,0.0,0.04,0.015,-0.01,0.015,0.045,0.035,0.01,
0.055,0.04,0.02,0.025,0.0,-0.005,-0.005,-0.02,-0.05,-0.03] # fx values
# Add x and y to lists
xs.append(dt.datetime.now().strftime('%H:%M:%S.%f'))
if(i<len(fx)):
ys.append(fx[i])
# Draw x and y lists
ax.clear()
if(i<len(fx)):
ys_stacked = np.stack((np.array(ys),0.1+np.array(ys)),axis=1)
ax.plot(xs, ys_stacked)
print("Animating")
# Format plot
if(i<len(fx)):
plt.xticks(rotation=45, ha='right')
plt.subplots_adjust(bottom=0.30)
plt.title('Force/Torque Sensor Data')
plt.ylabel('Fx (N)')
if(process_enabled):
p_graph = Process(name='Graph', target=start_animation)
print("Created graph process")
p_graph.start()
print("Started graph process")
else:
start_animation()
当我禁用该过程时, start_animation() function 工作正常,并显示 plot 并开始 animation。 但是,当启用该进程时,该进程将启动,然后代码在 print("Called animate function") 处中断。 没有 plot window 并且终端中没有错误消息)。
我对 python 和 matplotlib 中的多处理都是新手。 任何方向将不胜感激。
干杯,托尼
我正在尝试解决同样的问题,但还没有完全弄清楚。 但是,我想我可以就您的问题提供一些有用的评论。
首先,您有什么理由要在单独的进程中处理 animation 吗? 您的方法似乎在单个过程中运行良好。 为此,您需要解决许多问题。 如果您确实需要一个单独的过程,那么以下可能会有用。
首先,您将无法在'graph'
进程中使用全局变量,因为该进程不共享这些变量的相同实例(请参阅全局变量和 Python 多处理)。
您可以在进程之间共享 state,但这对于您想要共享的复杂对象(即plt.figure()
)来说是困难的。 有关更多信息,请参阅multiprocessing
参考 ( https://docs.python.org/3/library/multiprocessing.html#sharing-state-between-processes )
最后一个建议是pyplot
界面。 这对于简单的脚本和交互式数据分析很方便,但它混淆了很多重要的事情——比如在调用plt
方法时知道你正在处理的图形、轴等。
我使用自定义 class 提供了另一种面向对象的方法,它可以运行您的 animation(无需单独的进程):
import sys
from multiprocessing import Process, Queue
import datetime as dt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.backends.qt_compat import QtWidgets
import matplotlib.animation as animation
class StripChart(FigureCanvasQTAgg):
def __init__(self):
self.fig = Figure(figsize=(8,5), dpi=100)
self.ax = self.fig.add_subplot(111)
# hold a copy of our torque data
self.fx = [0.045,0.02,0.0,0.04,0.015,-0.01,0.015,0.045,0.035,0.01,
0.055,0.04,0.02,0.025,0.0,-0.005,-0.005,-0.02,-0.05,-0.03]
super().__init__(self.fig)
# instantiate the data arrays
self.xs = []
self.ys = []
def start_animation(self):
print("starting animation")
# set up the animation
self.ani = animation.FuncAnimation(self.fig, self.animate, init_func=self.clear_frame,
frames=100, interval=500, blit=False)
def clear_frame(self):
self.ax.clear()
self.ax.plot([], [])
def animate(self, i):
print("animate frame")
# get the current time
t_now = dt.datetime.now()
# update trace values
self.xs.append(t_now.strftime("%H:%M:%S.%f"))
self.ys.append(self.fx[i % len(self.fx)])
# keep max len(self.fx) points
if len(self.xs) > len(self.fx):
self.xs.pop(0)
self.ys.pop(0)
self.ax.clear()
self.ax.plot(self.xs, self.ys)
# need to reapply format after clearing axes
self.fig.autofmt_xdate(rotation=45)
self.fig.subplots_adjust(bottom=0.30)
self.ax.set_title('Force/Torque Sensor Data')
self.ax.set_ylabel('Fx (N)')
if __name__=='__main__':
# start a new qapplication
qapp = QtWidgets.QApplication(sys.argv)
# create our figure in the main process
strip_chart = StripChart()
strip_chart.show()
strip_chart.start_animation()
# start qt main loop
qapp.exec()
本例中的注意事项:
pip install pyqt5
)init_func
,您并不需要它,因为您可以在animate
方法中调用self.ax.clear()
。blit=True
但您需要修改clear_frame
和animate
方法以返回要更新的艺术家(请参阅https://jakevdp.ZBF21518181B514/B753243BIO4/blog/B75243 2012/08/18/matplotlib-animation-tutorial/了解更多信息)。 一个缺点是您将无法使用该方法更新轴标签。我假设您想在单独的进程中运行 animation 的原因是更新图形数据或绘制所有点涉及一些耗时/CPU 密集型任务。 也许您已将其嵌入到其他 UI 中?
我尝试在单独的进程中执行 animation,但您需要传递显示的图形实例。 正如我所提到的,这并不简单,尽管似乎有办法做到这一点( https://stackoverflow.com/a/57793267/13752965 )。 如果我找到可行的解决方案,我会更新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.