I've got a simulation model running in Python using NumPy and SciPy and it produces a 2D NumPy array as the output each iteration. I've been displaying this output as an image using matplotlib and the imshow function. However, I've found out about Glumpy, and on its documentation page it says:
Thanks to the IPython shell, glumpy can be ran in interactive mode where you can experience live update in displayed arrays when their contents is changed.
However, I can't seem to work out how to do this with the examples they've given. Basically my model runs as a single function which has a big for loop in it to loop for the number of iterations I'm running. At the end of each iteration of the for loop I want to display the array. At the moment I'm using matplotlib to save the image out to a png file, as displaying it on the screen through matplotlib seems to freeze the python process.
I'm sure there's a way to do this with Glumpy, I'm just not sure how, and I can't find any useful tutorials.
all() in Python. The numpy. all() function tests whether all array elements along the mentioned axis evaluate to True.
The Glumpy documentation is fairly nonexistent! Here's an example of a simple simulation, comparing array visualisation with glumpy
against matplotlib
:
import numpy as np
import glumpy
from OpenGL import GLUT as glut
from time import time
from matplotlib.pyplot import subplots,close
from matplotlib import cm
def randomwalk(dims=(256,256),n=3,sigma=10,alpha=0.95,seed=1):
""" A simple random walk with memory """
M = np.zeros(dims,dtype=np.float32)
r,c = dims
gen = np.random.RandomState(seed)
pos = gen.rand(2,n)*((r,),(c,))
old_delta = gen.randn(2,n)*sigma
while 1:
delta = (1.-alpha)*gen.randn(2,n)*sigma + alpha*old_delta
pos += delta
for ri,ci in pos.T:
if not (0. <= ri < r) : ri = abs(ri % r)
if not (0. <= ci < c) : ci = abs(ci % c)
M[ri,ci] += 1
old_delta = delta
yield M
def mplrun(niter=1000):
""" Visualise the simulation using matplotlib, using blit for
improved speed"""
fig,ax = subplots(1,1)
rw = randomwalk()
im = ax.imshow(rw.next(),interpolation='nearest',cmap=cm.hot,animated=True)
fig.canvas.draw()
background = fig.canvas.copy_from_bbox(ax.bbox) # cache the background
tic = time()
for ii in xrange(niter):
im.set_data(rw.next()) # update the image data
fig.canvas.restore_region(background) # restore background
ax.draw_artist(im) # redraw the image
fig.canvas.blit(ax.bbox) # redraw the axes rectangle
close(fig)
print "Matplotlib average FPS: %.2f" %(niter/(time()-tic))
def gprun(niter=1000):
""" Visualise the same simulation using Glumpy """
rw = randomwalk()
M = rw.next()
# create a glumpy figure
fig = glumpy.figure((512,512))
# the Image.data attribute is a referenced copy of M - when M
# changes, the image data also gets updated
im = glumpy.image.Image(M,colormap=glumpy.colormap.Hot)
@fig.event
def on_draw():
""" called in the simulation loop, and also when the
figure is resized """
fig.clear()
im.update()
im.draw( x=0, y=0, z=0, width=fig.width, height=fig.height )
tic = time()
for ii in xrange(niter):
M = rw.next() # update the array
glut.glutMainLoopEvent() # dispatch queued window events
on_draw() # update the image in the back buffer
glut.glutSwapBuffers() # swap the buffers so image is displayed
fig.window.hide()
print "Glumpy average FPS: %.2f" %(niter/(time()-tic))
if __name__ == "__main__":
mplrun()
gprun()
Using matplotlib
with GTKAgg
as my backend and using blit
to avoid drawing the background each time, I can hit about 95 FPS. With Glumpy
I get about 250-300 FPS, even though I currently a fairly crappy graphics setup on my laptop. Having said that, Glumpy
is a bit more fiddly to get working, and unless you are dealing with huge matrices, or you need a very high framerate for whatever reason, I would stick with using matplotlib
with blit
.
Using pyformulas 0.2.8 you can use pf.screen to create a non-blocking screen:
import pyformulas as pf
import numpy as np
canvas = np.floor(np.random.normal(scale=50, size=(480,640,3)) % 256).astype(np.uint8)
screen = pf.screen(canvas)
while screen.exists():
canvas = np.floor(np.random.normal(scale=50, size=(480,640,3)) % 256).astype(np.uint8)
screen.update(canvas)
#screen.close()
Disclaimer: I am the maintainer for pyformulas
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With