Reputation: 11637
The following code supposed to do the same thing here where lines colours are updated during an animation. However, the colour is not being updated. Which part of this code is wrong?
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
import matplotlib.animation as animation
lines = []
for i in range(10):
for j in range(10):
lines.append([(0, i), (1, j)])
fig, ax = plt.subplots()
colors = np.random.random(len(lines))
col = LineCollection(lines, array=colors, cmap=plt.cm.gray)
ax.add_collection(col)
ax.autoscale()
ims = []
for i in range(100):
colors = np.random.random(len(lines))
col.set_array(colors)
ims.append([ax.add_collection(col)])
ani = animation.ArtistAnimation(fig, ims, interval=200, blit=True,repeat_delay=10000)
plt.show()
The output I get from the above code is below
Upvotes: 3
Views: 3223
Reputation: 11
According to the documentation of "LineCollection" we can set the individual color of each segment by using the method "set_color" and providing a sequence of rgba tupels:
c : color or list of colors
Single color (all patches have same color), or a sequence of rgba tuples; if it is a sequence the patches will cycle through the sequence.
The following code should work properly. It is using FuncAnimation though.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
import matplotlib.animation as animation
lines = []
for i in range(10):
for j in range(10):
lines.append([(0, i), (1, j)])
fig, ax = plt.subplots()
colors = np.random.random(len(lines))
col = LineCollection(lines, array=colors, cmap=plt.cm.gray)
ax.add_collection(col)
ax.autoscale()
def update(num, collection):
colors = [(c, c, c) for c in np.random.random(len(lines))]
collection.set_color(colors)
return collection,
ani = animation.FuncAnimation(fig, update, 100, fargs=[col], interval=25, blit=True)
plt.show()
Upvotes: 0
Reputation: 22681
You need to draw the changed artist (your LineCollection
) just after the line
col.set_array(colors)
You need to do this because the LineCollection was first added to the axes with the line
ax.add_collection(col)
and then it is changed in the loop. You must then update the figure. The simplest way to do this is by calling plt.draw()
just before the line
im=ax.add_collection(col)
This however replots everything, and slows done a lot the animation. The solution is to draw first all the rest with a call to plt.draw()
before the loop, and then updating only the changed artist with a call to ax.draw_artist(col)
. The resulting code looks like this
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
import matplotlib.animation as animation
lines=[]
for i in range(10):
for j in range(10):
lines.append([(0, i), (1, j)])
fig, ax = plt.subplots()
colors = np.random.random(len(lines))
col = LineCollection(lines, array=colors, cmap=plt.cm.gray)
ax.add_collection(col)
ax.autoscale()
ims=[]
plt.draw()
for i in range(100):
col = LineCollection(lines,cmap=plt.cm.gray)
colors = np.random.random(len(lines))
col.set_array(colors)
ax.draw_artist(col)
im=ax.add_collection(col)
ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval=25, blit=True,repeat_delay=10000)
plt.show()
It is less tricky to do the same thing using FuncAnimation()
, see an example here, but you said you don't want to use it for some reasons.
Upvotes: 2
Reputation: 11637
I found a solution but its so dumb. I have to create the same package of lines again:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
import matplotlib.animation as animation
lines=[]
for i in range(10):
for j in range(10):
lines.append([(0, i), (1, j)])
fig, ax = plt.subplots()
colors = np.random.random(len(lines))
col = LineCollection(lines, array=colors, cmap=plt.cm.gray)
ax.add_collection(col)
ax.autoscale()
ims=[]
for i in range(100):
col = LineCollection(lines,cmap=plt.cm.gray)
colors = np.random.random(len(lines))
col.set_array(colors)
im=ax.add_collection(col)
ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval=25, blit=True,repeat_delay=10000)
plt.show()
I would be happy if somebody gives a me a solution without renewing the lines but only updating the colours.
Upvotes: 1