Animation based only on updating colors in the plot

I have a plot consisting of a large number of lines. At each step, the colors of the lines should be updated in the animation, but doing a for loop on the lines seems very expensive. Is there a better way to do this?

Here is my code:

import numpy as np lines=[] from matplotlib import pyplot as plt import matplotlib.animation as animation #initial plot fig=plt.figure() ax=plt.subplot(1,1,1) for i in range(10): lines.append([]) for j in range(10): lines[i].append(ax.plot([i,j],color='0.8')) lines=np.asarray(lines) ##Updating the colors 10 times im=[] for steps in range(10): colors=np.random.random(size=(10,10)) for i in range(10): for j in range(10): lines[i,j][0].set_color(str(colors[i,j])) plt.draw() # im.append(ax) plt.pause(.1) #ani = animation.ArtistAnimation(fig, im, interval=1000, blit=True,repeat_delay=1000) plt.show() 

Plus, I could not get him to work with an animated artist! I used a draw. What is wrong with animation lines

Now increasing these 10 s to 100 makes the program terribly slow:

 import numpy as np lines=[] from matplotlib import pyplot as plt import matplotlib.animation as animation #initial plot fig=plt.figure() ax=plt.subplot(1,1,1) for i in range(100): lines.append([]) for j in range(100): lines[i].append(ax.plot([i,j],color='0.8')) lines=np.asarray(lines) ##Updating the colors 10 times im=[] for steps in range(10): colors=np.random.random(size=(100,100)) for i in range(100): for j in range(100): lines[i,j][0].set_color(str(colors[i,j])) plt.draw() # im.append(ax) plt.pause(.1) #ani = animation.ArtistAnimation(fig, im, interval=1000, blit=True,repeat_delay=1000) plt.show() 

As I said, I want to run it side by side with animation. Therefore, I prefer to make animation. I think this would solve the problem with the delay, at least after the start of the animation, but right now, as I defined it, it does not work.

+6
source share
2 answers

The easiest way to use LineCollection for this. This way you can set all the colors as a single array and, as a rule, get much better drawing performance.

The best performance basically is that collections are an optimized way to draw many similar objects in matplotlib. In this case, the exclusion of nested loops for setting colors is actually secondary.

With that in mind, try something else along these lines:

 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(i): colors = np.random.random(len(lines)) col.set_array(colors) return col, # Setting this to a very short update interval to show rapid drawing. # 25ms would be more reasonable than 1ms. ani = animation.FuncAnimation(fig, update, interval=1, blit=True, init_func=lambda: [col]) # Some matplotlib versions explictly need an `init_func` to display properly... # Ideally we'd fully initialize the plot inside it. For simplicitly, we'll just # return the artist so that `FuncAnimation` knows what to draw. plt.show() 

enter image description here

+5
source

If you want to speed up the for loop, there are some good ways to do this. The best for what you are trying to do, generator expressions, might be something like this:

 iterator = (<variable>.upper() for <samevariable> in <list or other iterable object>) 

(for more specific information about them, there is documentation at http://www.python.org/dev/peps/pep-0289/ and https://wiki.python.org/moin/Generators )

There are other non-cycle-related ways to update color, but they are unlikely to be faster than a generator. You could create some form of group for strings and call something like:

 lines.update() 

for all of them.

+2
source

Source: https://habr.com/ru/post/958326/


All Articles