8

I have been struggling with this for a while and can't get it to work. I am reading a file in chunks and scatter plotting data from it, and I would like to "animate" it by updating the scatter plot for each chunk in a for loop (and also adapt it to a live stream of data).

So something like this ugly example works for a single plot:

x = [1, 2, 3, 4]
y = [4, 3, 2, 1]
alpha = [0.2, 0.3, 0.8, 1.0]
c = np.asarray([(0, 0, 1, a) for a in alpha])
s = scatter(x, y, marker='o', color=c, edgecolors=c)

plot of above

But how do I update the plot without calling s.remove() and scatter() repeatedly? The completely unintuitively-named s.set_array and s.set_offsets are supposed to update the colors and the x and y positions, but I can't figure out how to use them with the type of x, y, alpha data I have above.

(Also, is there a better way to do the alpha in the above plot?)

endolith
  • 25,479
  • 34
  • 128
  • 192
  • @endolith: There is a question here about updating a graph in realtime: http://stackoverflow.com/questions/13181118/using-matplotlib-or-pyqtgraph-to-graph-real-time-data maybe that will help? – Dair May 31 '14 at 03:47
  • 1
    `set_array` works when you are using a colormap to determine the color of the markers, not when you have set the colors by hand. The other assumption that those functions make is that the number of makers does not change (iirc). – tacaswell Jun 01 '14 at 13:56
  • @tcaswell: Well the colors are generated from the data, not manually, so a colormap with varying alpha could work. Can you write an example of how to use a custom colormap and update the scatter colors? The number of markers will not change. – endolith Jun 02 '14 at 17:15
  • http://matplotlib.org/examples/pylab_examples/custom_cmap.html – tacaswell Jun 03 '14 at 17:05
  • @tcaswell: I sort of got that to work, but the edgecolors are different. What am I doing wrong? https://gist.github.com/endolith/f96d3939ffa5d79c81cc – endolith Jun 04 '14 at 03:15
  • Sorry, been busy recently, `scatter(x, y, c=alpha, cmap=cdict4, linewidth=0)` just get rid of the edge. (edited because I remembered kwargs wrong) – tacaswell Jun 04 '14 at 18:27
  • Sorry to necropost but I followed you here from this question: http://stackoverflow.com/questions/15452405/updating-marker-style-in-scatter-plot-with-matplotlib and I'm still unclear exactly how you set the colours with set_array. Any tips? – Magic_Matt_Man Oct 24 '14 at 13:19
  • @Magic_Matt_Man Uhhh... I thought this question was answered, did it get deleted? I have a working solution somewhere I'll try to post it later – endolith Oct 24 '14 at 13:57
  • @endolith Ah thanks very much. I appreciate the effort, but I also found my own solution in the end, without using set_array. I am updating the colours in a loop (animation with fig.canvas.draw) and found that doing this on each iteration works: `n = mpl.colors.Normalize(vmin = min(speedsList), vmax = max(speedsList)); m = mpl.cm.ScalarMappable(norm=n, cmap=mpl.cm.afmhot); scat.set_facecolor(m.to_rgba(speedsList)); scat.set_clim(vmin=min(speedsList), vmax=max(speedsList));` where scat is the scatter plot and speedsList is the data from which to draw the colour info. – Magic_Matt_Man Oct 24 '14 at 14:11
  • @Magic_Matt_Man That's good. Can you post it as an answer? – endolith Oct 24 '14 at 14:16

1 Answers1

5

The solution I found for this involves using Normalize to make a normalised colour list based on the relevant data, mapping it to a ScalarMappable, and using that to set the face colour and c limits on each frame of the animation. With scat the handle of the scatter plot and speedsList provides the colour data:

n = mpl.colors.Normalize(vmin = min(speedsList), vmax = max(speedsList))
m = mpl.cm.ScalarMappable(norm=n, cmap=mpl.cm.afmhot)
scat.set_facecolor(m.to_rgba(speedsList))
scat.set_clim(vmin=min(speedsList), vmax=max(speedsList))

This does exactly what I expect it to.

Magic_Matt_Man
  • 2,020
  • 3
  • 16
  • 16