matplotlib FuncAnimation не обновляет ось при построении графика в реальном времени - PullRequest
0 голосов
/ 23 декабря 2018

Я пытаюсь построить данные в реальном времени с FuncAnimation из matplotlib на двух участках.Конечная цель состоит в том, чтобы построить данные датчика в реальном времени от Arduino.

На 5-летнем компьютере без графической карты, на которой запущен Debian 9. Отображается случайная прогулка с частотой 200 кадров в секунду, на каждом из которых отображается 4 случайных прогулки.enter image description here

Проблема в том, что ось 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...