running python 3.9:
import matplotlib.pyplot as plot
import numpy as np
import matplotlib.animation as animation
fig, plt = plot.subplots()
myArray = np.array([[0, 1, 2, 3, 4, 5, 6],
[7, 8, 9, 10, 11, 12, 13],
[14, 15, 16, 17, 18, 19, 20],
[21, 22, 23, 24, 25, 26, 27],
[28, 29, 30, 31, 32, 33, 34],
[35, 36, 37, 38, 39, 40, 41],
[42, 43, 44, 45, 46, 47, 48]])
def randint():
return np.random.randint(0, 7)
def randNewValue():
return np.random.randint(0, 48) #/10
def labelSquares():
for i in range(7):
for j in range(7):
plt.text(j, i, myArray[i, j], ha="center", va="center", color="white")
def modifyArrayElement(r, c, x):
row = r
col = c
new_value = x
myArray[row, col] = new_value
# labelSquares()
return myArray
ims = []
for i in range(100):
row = randint()
col = randint()
newValue = randNewValue()
# plt.text(col, row, myArray[row, col], ha="center", va="center", color="white")
# labelSquares()
im = plt.imshow(modifyArrayElement(row, col, newValue), animated = True)
if i == 0:
plt.imshow(modifyArrayElement(row, col, newValue))
ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval = 400, blit = True, repeat_delay = 5000)
labelSquares() # how to make it run "during" the animation, i.e: show progression of changing labels (plt.text) along with color changing, matching myArray values at each iteration?
f = r"c://Temp/animation.gif"
writergif = animation.PillowWriter(fps=2)
# ani.save(f, writer=writergif)
plot.show()
The result shows an animation of changing square colors as the contents of myArray changes, however, I would like the numbers inside them (text labels) to also change along, matching myArray values at each iteration of the for loop instead of staying static at final values all the time. Placing labelSquares() - or any similar labeling attempt inside the for loop - does not work. Is there a way to do it? (Sorry if this is a trivial problem showing my inexperience with pyplot, and I hope all the experts forgive me for asking such a stupid question)
From the ArtistAnimation
documentation on the artistlist parameter:
Each list entry is a collection of Artist objects that are made visible on the corresponding frame.
Note that every object you add to a Matplotlib figure is an artist, including the Text
objects that are returned by plt.text
. So, for each frame, we can get hold of these and put them in a list together with the AxesImage
artist from imshow
.
Since your ModifyArrayElement
function changes the global array in-place, the labelSquares
function has those updates automatically, and so does imshow
, so I simplified the imshow
calls. Also added animated=True
to the plt.text
to prevent unnecessary drawing.
import matplotlib.pyplot as plot
import numpy as np
import matplotlib.animation as animation
fig, plt = plot.subplots()
myArray = np.array([[0, 1, 2, 3, 4, 5, 6],
[7, 8, 9, 10, 11, 12, 13],
[14, 15, 16, 17, 18, 19, 20],
[21, 22, 23, 24, 25, 26, 27],
[28, 29, 30, 31, 32, 33, 34],
[35, 36, 37, 38, 39, 40, 41],
[42, 43, 44, 45, 46, 47, 48]])
def randint():
return np.random.randint(0, 7)
def randNewValue():
return np.random.randint(0, 48) #/10
def labelSquares():
all_texts = []
for i in range(7):
for j in range(7):
all_texts.append(plt.text(j, i, myArray[i, j], ha="center",
va="center", color="white",
animated=True))
return all_texts
def modifyArrayElement(r, c, x):
row = r
col = c
new_value = x
myArray[row, col] = new_value
return myArray
artists = []
for i in range(100):
row = randint()
col = randint()
newValue = randNewValue()
modifyArrayElement(row, col, newValue)
im = plt.imshow(myArray, animated=True)
frame_artists = labelSquares()
frame_artists.append(im)
artists.append(frame_artists)
ani = animation.ArtistAnimation(fig, artists, interval = 400, blit = True, repeat_delay = 5000)
writergif = animation.PillowWriter(fps=2)
ani.save("myanim.gif", writer=writergif)