I'm using matplotlib plotting in python GUI using animation. And below is the code
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_())
I'm updating the plot using set_offsets inside the plot function which is called by animation. When plot values is kept increasing and plotting is done, the plot goes out of figure. So i used autoscale(). But its not working. Still axes remains fixed and plots goes out of view.
The problem is that the scatter offsets are not taken into account when the axes are autoscaled. This may be a bug, or a desired feature; in any case two workarounds would be:
plot
One workaround which may in many cases be acceptable is to use a line plot plt.plot
instead of plt.scatter
. In this case the axes can be autoscaled using ax.relim
followed by ax.autoscale_view()
.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
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 = FuncAnimation(fig, plot, fargs=(data,), frames=4, interval=100, repeat=True)
plt.show()
scatter
and set limits programmaticallyIf the above cannot be used (e.g. because the scatter points should have different size or color), one would need to update the limits depending on the data.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
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 = FuncAnimation(fig, plot, fargs=(data,), frames=4, interval=100, repeat=True)
plt.show()