PsychoPy-Matplotlib

From TSG Doc
Revision as of 12:48, 17 March 2016 by Wilbert.vanham (talk | contribs) (example using PsychoPy to display matplotlib images without writing to file)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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
 2from __future__ import print_function
 3from psychopy import visual, event
 4import pyglet.gl as GL
 5import numpy as np
 6import matplotlib.pyplot as plt  # default backend TkAgg is ok
 7import math
 8import sys, time
 9#for optimalization: http://bastibe.de/2013-05-30-speeding-up-matplotlib.html
10
11# make initial image
12t = np.linspace(0, 4*np.pi, 1000) # horizontal axis
13fig, ax = plt.subplots()         # create new figure
14fig.set_size_inches([8,6])       # yuck
15line, = ax.plot(t, np.sin(t))    # initial plot
16fig.savefig('img.png', dpi=80)   # must be set to 80, this is what tostring_rgb does also
17ncols, nrows = fig.canvas.get_width_height()
18
19# put it in an ImageStim
20win = visual.Window(monitor='testMonitor')
21img = visual.ImageStim(win, 'img.png', units='pix', interpolate=False, flipVert=True)
22
23# change it
24x = t0 = t1 = 0
25while 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