1

I am using matplotlib.pyplot to animate some array data. The data is in the form of an intensity map, so I have a mesh of x and y locations, and a value associated with those locations.

The difficulty is that I cannot simply update the intensity data because the x and y locations change as well.

For example, I can get something like this work, but it requires having an over-determined x and y grid first that will cover the entire range:

cax = ax.pcolormesh(x, y, G[:-1, :-1, 0],
                    vmin=-1, vmax=1, cmap='Blues')
fig.colorbar(cax)

def animate(i):
     cax.set_array(G[:-1, :-1, i].flatten())

This works, but I end up with a fairly large intensity array filled mostly with zeros.

I have found an example here that allows the x and y values to be changed. Here is a modified MWE:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig2 = plt.figure()

x = np.arange(-9, 10)
y = np.arange(-9, 10).reshape(-1, 1)
base = np.hypot(x, y)
ims = []
for add in np.arange(15):
    x = np.arange(-9+add, 10+add)
    y = np.arange(-9+add, 10+add)
    x, y = np.meshgrid(x, y)
    ims.append((plt.pcolormesh(x, y, base + add, norm=plt.Normalize(0, 30)),))

im_ani = animation.ArtistAnimation(fig2, ims, interval=50, repeat_delay=3000,
                                   blit=True)
plt.show()

The issue here is two-fold. First, I have about 3000 frames, so the list ims becomes unmanageable. Secondly, how can I get the data to clear between frames and not show every frame all at once? Perhaps there's a better way altogether?

Bonus: using a slider could be an alternative to an animation. I've used Slider on these types of data before, but only by initializing a huge x and y grid.

Thanks for the help! Apologies if I'm not using the proper tags.

Erika H
  • 33
  • 5
  • What about the standard img animation and adding animated ticks and tick labels by setting the displayed values manually and according to the shift of your real data? Would that help? – mikuszefski Mar 02 '18 at 08:35
  • @mikuszefski Not exactly. For what I'm trying to accomplish, I don't want the displayed x and y limits to change every time. I wanted to avoid to over-determined grid method to save on computational time and resources. Changing the plot ticks every frame would be taking a step backwards. For now, it seems like the over-determined grid is the best choice, even though it isn't elegant. – Erika H Mar 02 '18 at 17:07
  • Well, I had the impression that performance is an issue and looking at the comments [here](https://stackoverflow.com/a/21169703/803359), it seems that my idea for the previous comment, namely using `imshow()`, is supported. That would require manual setting of ticklabels, though, while I think that this should be OK performance wise. – mikuszefski Mar 05 '18 at 11:54
  • ...unless your `x` and `y` are non-equidistant. – mikuszefski Mar 05 '18 at 11:56

1 Answers1

0

I may misunderstand the problem here, but using a FuncAnimation seems more appropriate here.

With blitting

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()

x = np.arange(-9, 10)
y = np.arange(-9, 10).reshape(-1, 1)
base = np.hypot(x, y)

def animate(i):
    x = np.arange(-9+i, 10+i)
    y = np.arange(-9+i, 10+i)
    x, y = np.meshgrid(x, y)
    pc = ax.pcolormesh(x, y, base + i, norm=plt.Normalize(0, 30))
    return pc,

ax.axis([-9,30,-9,30])
im_ani = animation.FuncAnimation(fig, animate, frames=30, interval=50, 
                                 repeat_delay=3000, blit=True)
plt.show()

Without blitting

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()

x = np.arange(-9, 10)
y = np.arange(-9, 10).reshape(-1, 1)
base = np.hypot(x, y)


store=[]
def animate(i):
    x = np.arange(-9+i, 10+i)
    y = np.arange(-9+i, 10+i)
    x, y = np.meshgrid(x, y)
    if store:
        store[0].remove()
        del store[0]
    pc = ax.pcolormesh(x, y, base + i, norm=plt.Normalize(0, 30))
    store.append(pc)


ax.axis([-9,30,-9,30])
im_ani = animation.FuncAnimation(fig, animate, frames=30, interval=50, 
                                 repeat_delay=3000)
plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • It's almost there. With "blit=True," nothing shows, but without it, everything does. Adding "ax.clear()" works, but it's ridiculous to have to call this (and reset all the other axis options) every time. I might just have to settle for the over-determined grid solution. Thanks for the input – Erika H Mar 02 '18 at 17:04
  • I don't know why `blit=True` does not work for you; in any case I added another solution without blitting. – ImportanceOfBeingErnest Mar 02 '18 at 17:10