PsychoPy-Matplotlib
Revision as of 11:48, 17 March 2016 by Wilbert.vanham (talk | contribs) (example using PsychoPy to display matplotlib images without writing to file)
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