Reputation: 1825
I plot information from a 2D array with pcolor. however, the information in the array is changed over the iterations, and I want to update the color map dynamically, in order to visualize the changes in real time. How can I do it in the most simple way?
Edit - example:
from __future__ import division
from pylab import *
import random
n = 50 # number of iterations
x = arange(0, 10, 0.1)
y = arange(0, 10, 0.1)
T = zeros([100,100]) # 10/0.1 = 100
X,Y = meshgrid(x, y)
"""initial conditions"""
for x in range(100):
for y in range(100):
T[x][y] = random.random()
pcolor(X, Y, T, cmap=cm.hot, vmax=abs(T).max(), vmin=0)
colorbar()
axis([0,10,0,10])
show() # colormap of the initial array
"""main loop"""
for i in range(n):
for x in range(100):
for y in range(100):
T[x][y] += 0.1 # here i do some calculations, the details are not important
# here I want to update the color map with the new array (T)
Thanks
Upvotes: 3
Views: 9618
Reputation: 87356
I would suggest using imshow
(doc):
# figure set up
fig, ax_lst = plt.subplots(2, 1)
ax_lst = ax_lst.ravel()
#fake data
data = rand(512, 512)
x = np.linspace(0, 5, 512)
X, Y = meshgrid(x, x)
data2 = np.sin(X ** 2 + Y **2)
# plot the first time#fake data
im = ax_lst[0].imshow(data, interpolation='nearest',
origin='bottom',
aspect='auto', # get rid of this to have equal aspect
vmin=np.min(data),
vmax=np.max(data),
cmap='jet')
cb = plt.colorbar(im)
pc = ax_lst[1].pcolor(data)
cb2 = plt.colorbar(pc)
To updata the data with imshow, just set the data array, and it takes care of all of the normalization and color mapping for you:
# update_data (imshow)
im.set_data(data2)
plt.draw()
To do the same with thing with pcolor
you need to do the normalization and color mapping your self (and guess the row-major vs column major right):
my_cmap = plt.get_cmap('jet')
#my_nom = # you will need to scale your read data between [0, 1]
new_color = my_cmap(data2.T.ravel())
pc.update({'facecolors':new_color})
draw()
Upvotes: 2
Reputation: 503
I have here a simple example how to update ax.pcolor
(or rather its faster cousin ax.pcolormesh
) during a simulation.
def make_movie(fig, meshData, conc, fout='writer_test.mp4',
dpi=150, metadata={}):
'''
Make a movie (on disk) starting from a first image generated with matplotlib,
by updating only the values that were dispayed with ax.pcolormesh(...).
Parameters
----------
meshData: mesh as returned by ax.pcolormesh()
conc: obj returned by readUCN
computed concentrations
fout: str
name of output file, with or without '.mp4' extension.
dpi: int
dots per inch of output movie
metadata: dict
passed on to FFMpegWriter.savings(fout, ...)
'''
plt.rcParams['animation.ffmpeg_path'] = '/usr/local/bin/ffmpeg'
from matplotlib.animation import FFMpegWriter
writer = FFMpegWriter(fps=15, metadata=metadata)
totims = conc.totim # get times of computed concentrations
with writer.saving(fig, fout, dpi):
for totim in totims:
C = conc.at_t(totim)[:, 0, :] # 3D --> 2D Xsection concentrations
#newcolors = cmap(norm(C.ravel()))
#meshData.update({'facecolors': newcolors})
meshData.update({'array': C.ravel()}) # reset array to new conc.
fig.canvas.draw_idle()
writer.grab_frame()
The lines starting with #newcolors
and #meshData.update
are as suggested by @tacaswell above. The line starting with meshdata.udate({array ...
replaces them. It just updates the data without computing the new facecolors. The last method is simpler and works just as well. Transposing the data array is not necessary.
Upvotes: 3
Reputation: 2175
You can connect events to your figure and call a specific function on that event. In the following I took an example of the matplotlib
documentation and added a function ontype
. This is called when 1
is pressed on the keyboard. Then X * func3()
is called. Ontype
is bound to the figure with fig.canvas.mpl_connect('key_press_event',ontype)
. In a similar way you could fire regular events time dependent.
#!/usr/bin/env python
"""
See pcolor_demo2 for an alternative way of generating pcolor plots
using imshow that is likely faster for large grids
"""
from __future__ import division
from matplotlib.patches import Patch
from pylab import *
def ontype(event):
''' function that is called on key event (press '1')'''
if event.key == '1':
print 'It is working'
fig.gca().clear()
# plot new function X * func3(X, Y)
Z = X * func3(X, Y)
pcolor(X, Y, Z, cmap=cm.RdBu, vmax=abs(Z).max(), vmin=-abs(Z).max())
fig.canvas.draw()
def func3(x,y):
return (1- x/2 + x**5 + y**3)*exp(-x**2-y**2)
# make these smaller to increase the resolution
dx, dy = 0.05, 0.05
x = arange(-3.0, 3.0001, dx)
y = arange(-3.0, 3.0001, dy)
X,Y = meshgrid(x, y)
Z = func3(X, Y)
fig=figure(figsize=(16,8))
# connect ontype to canvas
fig.canvas.mpl_connect('key_press_event',ontype)
pcolor(X, Y, Z, cmap=cm.RdBu, vmax=abs(Z).max(), vmin=-abs(Z).max())
colorbar()
axis([-3,3,-3,3])
show()
Upvotes: 1