Reputation: 71
I am trying to code a small video game in Python with matplotlib exclusively. The idea is to have a character on a small axes object which is moving on a larger map. I managed to update the location of the axes but the method seems to redraw the full figure instead of the small axes object (by calling plt.draw() in the source code), therefore the heavy map behind the character as well, making the process extremely slow.
Is there any way to redraw a specific axes object in matplotlib ?
I am working in an IPython shell of a terminal.
Here is a test code simulating my problem where I obtain something 10 times slower than the ideal case :
import matplotlib.pylab as plt
import time
import numpy as np
dtframe = 0.02 #time between plot updating in seconds
frames = 30
plt.subplots(5,5) #to simulate an heavy background matplotlib figure
ax = plt.axes([0.1,0.5,0.03,0.03])
plt.show(block=False)
begin = time.time()
for j in np.linspace(0.1,0.9,frames):
plt.pause(dtframe)
ax.set_position([j,0.5,0.03,0.03])
#ax.set_position([j,0.5,0.03,0.03], redraw_only_axes=True) ???
print('Current time [s] :',time.time() - begin)
print('Expected time [s] :',dtframe*frames)
#Current time [s] : 5.70146918296814
#Expected time [s] : 0.6
Upvotes: 1
Views: 585
Reputation: 71
Based on the tutorial provided by @ianhi, here is the solution with blitting :
import matplotlib.pylab as plt
import time
import numpy as np
dtframe = 0.02 #time between plot updating in seconds
frames = 30
fig,axes = plt.subplots(5,5) #to simulate an heavy background matplotlib figure
ax = plt.axes([0.1,0.5,0.03,0.03],animated=True)
plt.show(block=False)
plt.pause(0.1)
bg = fig.canvas.copy_from_bbox(fig.bbox)
fig.canvas.blit(fig.bbox)
begin = time.time()
for j in np.linspace(0.1,0.9,frames):
fig.canvas.restore_region(bg)
ax.set_position([j,0.5,0.03,0.03])
plt.pause(dtframe)
fig.draw_artist(ax)
fig.canvas.blit(fig.bbox)
fig.canvas.flush_events()
print('Current time [s] :',time.time() - begin)
print('Expected time [s] :',dtframe*frames)
#Current time [s] : 1.2531671524047852
#Expected time [s] : 0.6
Upvotes: 0
Reputation: 3162
The technique you are looking for is called blitting.
There is a tutorial on doing this in matplotlib here: https://matplotlib.org/stable/tutorials/advanced/blitting.html
Upvotes: 1