6

As a result of a full day of trial and error, I'm posting my findings as a help to anyone else who may come across this problem.

For the last couple days, I've been trying to simulate a real-time plot of some radar data from a netCDF file to work with a GUI I'm building for a school project. The first thing I tried was a simple redrawing of the data using the 'interactive mode' of matplotlib, as follows:

import matplotlib.pylab as plt

fig = plt.figure()
plt.ion() #Interactive mode on
for i in range(2,155): #Set to the number of rows in your quadmesh, start at 2 for overlap
    plt.hold(True)
    print i
    #Please note: To use this example you must compute X, Y, and C previously.
    #Here I take a slice of the data I'm plotting - if this were a real-time
    #plot, you would insert the new data to be plotted here.
    temp = plt.pcolormesh(X[i-2:i], Y[i-2:i], C[i-2:i])
    plt.draw()
    plt.pause(.001) #You must use plt.pause or the figure will freeze

 plt.hold(False)      
 plt.ioff() #Interactive mode off

While this technically works, it also disables the zoom functions, as well as pan, and well, everything!

For a radar display plot, this was unacceptable. See my solution to this below.

Melangeaddict
  • 123
  • 1
  • 8
  • Congrats on getting things working! It's perfectly fine (and encouraged) to ask a question and post your own answer on stackoverflow. However, it's best to separate the question and the answer. Right now, you have them together. If you have a chance, post the second half of your question as the answer. After a day or so, you can mark it as the accepted answer, as well. Incidentally, excellent question and excellent answer! – Joe Kington Feb 01 '14 at 19:52
  • Also, just so you know, `imshow` (with `interp='none'` to match `pcolormesh`) would be a better choice for the animation. It renders considerably faster, especially for large datasets. Also, if you change the animation to update an existing object instead of adding a new one on top of the old, you'll have much better performance (your current approach may become slower with each frame). At any rate, just suggestions if it turns out that you need better performance once you have access to the "live" data stream. – Joe Kington Feb 01 '14 at 19:58

1 Answers1

3

So I started looking into the matplotlib animation API, hoping to find a solution. The animation did turn out to be exactly what I was looking for, although its use with a QuadMesh object in slices was not exactly documented. This is what I eventually came up with:

import matplotlib.pylab as plt
from matplotlib import animation

fig = plt.figure()

plt.hold(True)
#We need to prime the pump, so to speak and create a quadmesh for plt to work with
plt.pcolormesh(X[0:1], Y[0:1], C[0:1])

anim = animation.FuncAnimation(fig, animate, frames = range(2,155), blit = False)

plt.show()
plt.hold(False)

def animate( self, i):
    plt.title('Ray: %.2f'%i)
    #This is where new data is inserted into the plot.
    plt.pcolormesh(X[i-2:i], Y[i-2:i], C[i-2:i])

Note that blit must be False! Otherwise it will yell at you about a QuadMesh object not being 'iterable'.

I don't have access to the radar yet, so I haven't been able to test this against live data streams, but for a static file, it has worked great thus far. While the data is being plotted, I can zoom and pan with the animation.

Good luck with your own animation/plotting ambitions!

Melangeaddict
  • 123
  • 1
  • 8
  • 1
    `blit=True` is looking for a list of objects to update. If you assign a handle to your pcolormesh object, e.g. `pcm = plt.pcolormesh(X[0:1], Y[0:1], C[0:1])` then you can update the `pcm`'s data with `pcm.set_array(new_cdata)` The animate function needs to return an iterable of objects to be updated, so you need to add `return pcm,` to the end of the `animate` function. Note the comma, that tells the function to return `pcm` as an element of a 1-element tuple. – KDN Aug 03 '16 at 20:41