1

So i copied this code from Animation based on only updating colours in a plot and made some slight adjusments. I have a plot and would like to change the color of a single line each frame. 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=[]
points=[(1,2),(5,4),(1,3),(2,1),(3,5)]
for i in range(len(points)-1):
        lines.append([points[i],points[i+1]])
fig, ax = plt.subplots()

colors = np.array([0.1,0.1,0.1,0.9])
col = LineCollection(lines, array=colors, cmap=plt.cm.bwr)
ax.add_collection(col)
ax.autoscale()
print(colors)
def update(i):
    colors[i%4]=np.random.random()
    col.set_array(colors)
    return col,
ani = animation.FuncAnimation(fig, update, interval=2000, blit=True, 
                              init_func=lambda: [col])
plt.show()

While it does work if i leave it this way, i initially want all the lines to have the same color. When i change the initial colors to

colors = np.array([0.9,0.9,0.9,0.9]) 

instead of

colors = np.array([0.1,0.1,0.1,0.9])

the plot just stops from updating and stays one color the entire time. If i change just one number from the colors array, it works. Why would that be and what should i change for it to work?

Samer
  • 13
  • 3
  • Try making `colors` in update a global variable by putting `global colors` immediately before `colors[i%4] = np.random.random()` – William Miller Jan 12 '20 at 07:57
  • @WilliamMiller doesn't work, `update` still only works if the initial colors has at least one different value – Samer Jan 12 '20 at 08:13

1 Answers1

0

You would need to tell the LineCollection about which value range should be mapped to the colors of the colormap. If you use all the same numbers as the initial array, the collection cannot even guess about that range, while if you take different values at the beginning it would use the minimum and maximum of those.

In either case it's actually better to define that range explicitely. For example to have the range [0,1] be mapped, use norm=plt.Normalize(0,1).

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
import matplotlib.animation as animation

lines=[]
points=[(1,2),(5,4),(1,3),(2,1),(3,5)]
for i in range(len(points)-1):
        lines.append([points[i],points[i+1]])
fig, ax = plt.subplots()

colors = np.array([0.1,0.1,0.1,0.1])
col = LineCollection(lines, array=colors, cmap=plt.cm.bwr, norm=plt.Normalize(0,1))
ax.add_collection(col)
ax.autoscale()
print(colors)
def update(i):
    colors[i%4]=np.random.random()
    col.set_array(colors)
    return col,
ani = animation.FuncAnimation(fig, update, interval=20, blit=True, 
                              init_func=lambda: [col])
plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712