Difference between revisions of "PsychoPy-Matplotlib"

From TSG Doc
Jump to: navigation, search
(example using PsychoPy to display matplotlib images without writing to file)
(No difference)

Revision as of 11:48, 17 March 2016

Matplotlib does not have a (documented) way of exporting an image other than writing to file or screen. PsychoPy does not have a documented way of importing images other than reading from file. The following example shows how to use the undocumented features in both libraries.

A matplotlib graph is made, written to file and shown in a PsychoPy ImageStim. Then the graph is updated and send directly to the ImageStim object to replace the old image. On the labcomputer this runs smoothly at 60Hz.

 1 #!/usr/bin/python
 2 from __future__ import print_function
 3 from psychopy import visual, event
 4 import pyglet.gl as GL
 5 import numpy as np
 6 import matplotlib.pyplot as plt  # default backend TkAgg is ok
 7 import math
 8 import sys, time
 9 #for optimalization: http://bastibe.de/2013-05-30-speeding-up-matplotlib.html
10 
11 # make initial image
12 t = np.linspace(0, 4*np.pi, 1000) # horizontal axis
13 fig, ax = plt.subplots()         # create new figure
14 fig.set_size_inches([8,6])       # yuck
15 line, = ax.plot(t, np.sin(t))    # initial plot
16 fig.savefig('img.png', dpi=80)   # must be set to 80, this is what tostring_rgb does also
17 ncols, nrows = fig.canvas.get_width_height()
18 
19 # put it in an ImageStim
20 win = visual.Window(monitor='testMonitor')
21 img = visual.ImageStim(win, 'img.png', units='pix', interpolate=False, flipVert=True)
22 
23 # change it
24 x = t0 = t1 = 0
25 while not event.getKeys():
26 	ax.draw_artist(ax.patch)        # faster than redrawing the canvas
27 	ax.draw_artist(line)            # faster than redrawing the canvas
28 	buf = fig.canvas.tostring_rgb() # make a bitmap
29 	# convert bitmap to correct format for GL texture
30 	tex = np.fromstring(buf, dtype=np.uint8).reshape(nrows, ncols, 3).astype(np.float32)/255
31 	img._createTexture(tex, img._texID, GL.GL_RGB, img, forcePOW2=False) # set texture in video mem
32 	img.draw()                      
33 	t1 = win.flip()                 # mark time on screen
34 	print("{:.3f} s/frame".format(t1-t0), end='\r') # show frame time
35 	sys.stdout.flush()              # write text immediately
36 	t0 = t1                         # prepare for next iteration
37 	x += 0.01                       # change graph
38 	line.set_ydata(np.sin(2*t+x))   # change graph, faster than ax.clear, ax.plot