Анимация в matplotlib с разбросом и использованием set_offsets: автомасштабирование фигуры не работает

Я использую графику matplotlib в графическом интерфейсе python с использованием анимации. А ниже код

import sys
from PyQt4 import QtGui

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
class Window(QtGui.QDialog):
    def __init__(self, parent=None):
    super(Window, self).__init__(parent)
    self.figure = plt.figure()
    self.canvas = FigureCanvas(self.figure)
    self.toolbar = NavigationToolbar(self.canvas, self)
    layout = QtGui.QVBoxLayout()
    layout.addWidget(self.toolbar)
    layout.addWidget(self.canvas)
    self.setLayout(layout)
    self.ax=self.figure.add_subplot(111)

    plt.autoscale(enable=True, axis='both', tight=None #for auto scaling

    self.data = [500, -500, 501, -502,.... 623] #some list of data
    self.ax = plt.gca()
    self.ax.grid()
    self.sc = self.ax.scatter(self.data[::2], self.data[1::2]

def plot(self, a):
    for i in range(len(self.data)):
        self.data[i] = int(self.data[i])+5
    self.sc.set_offsets(np.c_[self.data[::2], self.data[1::2]])
    self.canvas.draw()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    main = Window()
    ani = matplotlib.animation.FuncAnimation(main.figure, main.plot, 
            frames=4, interval=100, repeat=True) 
    main.show()

    sys.exit(app.exec_())

Я обновляю сюжет, используя set_offsets внутри функции plot, которая вызывается анимацией. Когда значения графика продолжают увеличиваться и построение графика завершено, график выходит из строя. Поэтому я использовал автомасштабирование(). Но это не работает. Тем не менее оси остаются фиксированными, а графики исчезают из поля зрения. Пожалуйста, помогите мне сделать автомасштабирование на рисунке. Заранее спасибо.


person Anand    schedule 28.04.2017    source источник
comment
я думаю, теперь все выглядит хорошо .. @ImportanceOfBeingErnest   -  person Anand    schedule 28.04.2017


Ответы (1)


Проблема в том, что смещения разброса не учитываются при автомасштабировании осей. Это может быть ошибка или желаемая функция; в любом случае два обходных пути:

используя plot

Одним из обходных путей, который во многих случаях может быть приемлемым, является использование линейного графика plt.plot вместо plt.scatter. В этом случае оси можно автоматически масштабировать, используя ax.relim, а затем ax.autoscale_view().

import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np

fig, ax = plt.subplots()  
ax.grid()  

data = np.cumsum(np.random.normal(size=100)) #some list of data
sc, = ax.plot(data[::2], data[1::2], marker="o", ls="") # set linestyle to none

def plot(a, data):
    data += np.cumsum(np.random.normal(size=100)+3e-2)
    sc.set_data(data[::2], data[1::2])
    ax.relim()
    ax.autoscale_view(True,True,True)

ani = matplotlib.animation.FuncAnimation(fig, plot, fargs=(data,),
            frames=4, interval=100, repeat=True) 
plt.show()

используя scatter и программно устанавливая лимиты

Если вышеуказанное нельзя использовать (например, из-за того, что точки рассеяния должны иметь разный размер или цвет), необходимо будет обновить пределы в зависимости от данных.

import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np

fig, ax = plt.subplots()    

data = np.cumsum(np.random.normal(size=100)) #some list of data

ax.grid()
sc = ax.scatter(data[::2], data[1::2], c=data[1::2])

def plot(a, data):
    data += np.cumsum(np.random.normal(size=100)+3e-2)
    X = np.c_[data[::2], data[1::2]]
    sc.set_offsets(X)
    # manually relim:
    xmin=X[:,0].min(); xmax=X[:,0].max()
    ymin=X[:,1].min(); ymax=X[:,1].max()
    ax.set_xlim(xmin-0.1*(xmax-xmin),xmax+0.1*(xmax-xmin))
    ax.set_ylim(ymin-0.1*(ymax-ymin),ymax+0.1*(ymax-ymin))

ani = matplotlib.animation.FuncAnimation(fig, plot, fargs=(data,),
            frames=4, interval=100, repeat=True) 
plt.show()

введите описание изображения здесь

person ImportanceOfBeingErnest    schedule 28.04.2017
comment
Когда я попробовал этот подход, я получил трассировку «AttributeError: объект PathCollection не имеет атрибута set_xlim». Любые мысли, почему, пожалуйста? - person DavidA; 13.07.2017
comment
Нет. Во-первых, есть два подхода выше. Непонятно, какой вы взяли. Во-вторых, оба работают как есть. Если вы что-то изменили, как кто-то должен знать, что вы изменили. Поэтому никто не сможет вам помочь, если вы не предоставите минимально воспроизводимый пример проблемы. Лучше всего сделать это, задав новый вопрос об этом. - person ImportanceOfBeingErnest; 13.07.2017
comment
Спасибо за ваш ответ. Я использовал второй метод. Я неправильно назвал set_xlim в PathCollection вместо объекта осей. Теперь работает. - person DavidA; 14.07.2017
comment
Спасибо за публикацию. - person Cloud Cho; 08.03.2018
comment
Можно ли добавить обновляющуюся линию тренда, а также скаттер? - person Ohm; 23.04.2018
comment
@ Ом Да, это так! Если у вас возникли проблемы с этим, задайте вопрос с четким описанием проблемы (Как спросить) и < href="https://stackoverflow.com/help/minimal-reproducible-example">минимальный воспроизводимый пример проблемы. - person ImportanceOfBeingErnest; 23.04.2018