Difference between revisions of "PsychoPy-Matplotlib"

From TSG Doc
Jump to: navigation, search
m
(link to video)
Line 5: Line 5:
 
A matplotlib graph is made, written to file and shown in a PsychoPy ImageStim. Then the graph is updated  
 
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 (without writing to file) to replace the old image. On the  
 
and send directly to the ImageStim object (without writing to file) to replace the old image. On the  
labcomputer this runs smoothly at 60Hz.
+
labcomputer this runs smoothly at 60Hz. This is what it looks [https://www.socsci.ru.nl/wilberth/python/image/psychopy-matplotlib.ogv like].
  
 
<syntaxhighlight lang="python" line="1" >
 
<syntaxhighlight lang="python" line="1" >

Revision as of 11:57, 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 (without writing to file) to replace the old image. On the labcomputer this runs smoothly at 60Hz. This is what it looks like.

 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