Я пытаюсь построить данные в реальном времени с FuncAnimation
из matplotlib
на двух участках.Конечная цель состоит в том, чтобы построить данные датчика в реальном времени от Arduino.
На 5-летнем компьютере без графической карты, на которой запущен Debian 9. Отображается случайная прогулка с частотой 200 кадров в секунду, на каждом из которых отображается 4 случайных прогулки.
Проблема в том, что ось y не обновляется соответственно.Показатели производительности на рисунке показывают, что ax1.y_lim
находится в [-108; 94]
, однако, ось Y в ax1
только колеблется в [-5;2]
более или менее.
Идея была взята изhttps://learn.sparkfun.com/tutorials/graph-sensor-data-with-python-and-matplotlib/update-a-graph-in-real-time) и программа:
#!/usr/bin/ipython3 -i
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import time
class RealTimePlot:
def __init__(self, fig, bufsize=100, data_rows=8):
self.fig = fig
self.bufsize = bufsize
self.data_rows = data_rows
self._init_plot()
self._init_data()
self._init_plot2()
self.fps_start = time.time()
self.fps_counter, self.fps_print = (0, 100)
def _init_plot(self):
plt.ion()
self.ax1 = self.fig.add_subplot(2, 1, 1)
self.ax1.set_xlim(0, self.bufsize)
self.ax2 = self.fig.add_subplot(2, 1, 2)
self.ax2.set_xlim(0, self.bufsize)
def _init_data(self):
self.y = np.zeros((self.data_rows, self.bufsize))
self.x = list(range(self.bufsize))
self.data_labels = list(map(chr, range(ord('A'), ord('A') + self.data_rows)))
def _init_plot2(self):
self.artists = []
self.ind_sub1 = range(self.data_rows // 2)
self.ind_sub2 = range(self.data_rows // 2, self.data_rows)
for i in self.ind_sub1:
line, = self.ax1.plot(self.x, self.y[i,:], label=self.data_labels[i])
self.artists.append(line)
for i in self.ind_sub2:
line, = self.ax2.plot(self.x, self.y[i,:], label=self.data_labels[i])
self.artists.append(line)
self.ax1.legend()
self.ax2.legend()
self.fig.tight_layout()
def read_data(self):
new_data = np.random.rand(self.data_rows) * 10 - 5
ret = self.y[:,-1] + new_data
return ret.reshape(-1,1)
def animate(self, i):
# add new data
new_data = self.read_data().reshape((self.y.shape[0], 1))
self.y = np.append(self.y, new_data, axis=1)[:, -self.y.shape[1]:]
# update plot data
self.ax1_min, self.ax1_max = (np.min(self.y[self.ind_sub1,:]), np.max(self.y[self.ind_sub1,:]))
self.ax1.set_ylim(self.ax1_min, self.ax1_max)
self.ax2_min, self.ax2_max = (np.min(self.y[self.ind_sub2,:]), np.max(self.y[self.ind_sub2,:]))
self.ax2.set_ylim(self.ax2_min, self.ax2_max)
for nr, line in enumerate(self.artists):
line.set_ydata(self.y[nr,:])
# performance stats
if self.fps_counter == self.fps_print:
fps = self.fps_counter // (time.time() - self.fps_start)
print('FPS:', fps, 'Ax1Min', int(self.ax1_min), 'Ax1Max', int(self.ax1_max),
'Ax2Min', int(self.ax2_min), 'Ax2Max', int(self.ax2_max))
self.fps_counter = 0
self.fps_start = time.time()
else:
self.fps_counter += 1
return self.artists
fig = plt.figure(figsize=(16,6))
a = RealTimePlot(fig, bufsize=100, data_rows=8)
ani = animation.FuncAnimation(fig, a.animate, interval=0, blit=True)
plt.show()
Как можно изменить функцию animate
без потери частоты кадров?
Кстати, частота кадров сильно падает, если при создании сюжета вы используете более крупные значения figsize.