timing issues with large window resolutions

115 views
Skip to first unread message

Tommy Sprague

unread,
Jul 10, 2009, 12:00:01 PM7/10/09
to psychopy-users, eagl...@bcm.edu, eagle...@gmail.com
I am a new user of PsychoPy and have encountered an issue that I have
not found a way to resolve.

I have created a simple script to display a stimulus in which a square
and circle both flash on the screen for 60 ms, followed by a blank
screen for 1 s, followed by the circle presented for 60 ms at some
point during a 910 ms presentation of the square. This stimulus
involves only 3 frames (sq+circ, sq alone, blank screen), and so I
only need to make 6 frame changes over ~2 sec. I’ve done my best to
follow any and all coding practices used in the demos, and this works
great if I use a small window size (such as the 600x600 used in the
demos). However, when using a window size equivalent to my full
screen resolution (1680x1050), the stimulus slows significantly.
Recording the times of frame onsets/offsets in order to determine the
actual duration of each frame presented, I find that PsychoPy takes
about 40 ms to draw 1 frame (60 Hz) – again, this problem does not
occur when using sufficiently small window sizes.

Are there any potential causes of this problem, and if so, does anyone
know of any possible solutions?

I’ve attached the code I’m working with now, and below are some system
details that may be relevant:

IDE: I use EasyEclipse with the Endthought distribution of Python/
SciPy/NumPy/etc, along with Pygame and PsychoPy installed, however the
same issue occurs when using the PsychoPy IDE
Graphics: NVIDIA Quadro NVS 285 with driver version 6.14.10.9371 (64MB
onboard memory/64MB of system memory) – this works great with
Psychtoolbox 2.5/3.0
Processor: Intel Core 2 6400 @ 2.13 GHz
RAM: 2.00 GB
OS: Win XP SP3

The same problem occurs on my Late-2008 Macbook Pro running Win 7 RC1
(2.8 GHz dual-core, 4GB RAM, GeForce 9500M graphics w/ 256MB dedicated
memory, same IDE setup)

Also, I am completely new to Python, but have experience programming
in MATLAB and Java – if there is anything I’m doing inefficiently in
my code that could be the cause of this problem, I’d appreciate any
advice you might have to improve this.

code:

from psychopy import visual, core, event
import numpy as np


global_clock = core.Clock()

frame_outsize = 0.5
frame_width = 0.1
circle_size = .15

stim_color = [1.0,1.0,1.0]
bg_color = [-1.0,-1.0,-1.0]

context_dur = 0.91 # in seconds
test_dur = 0.06 # in seconds

#bgWin = visual.Window( size = (1680,1050),
# allowGUI = False,
# rgb = (-1.0,-1.0,-1.0))


myWin = visual.Window( size = (1680,1050),
rgb = bg_color,
allowGUI = False,
monitor = 'testMonitor',
units = 'norm') # [-1 to 1] on either
side

FPS = 60#round(myWin.fps())

context_fr = round(context_dur*FPS)
test_fr = round(test_dur*FPS)

frame_out = visual.ShapeStim( myWin,
units = 'norm',
lineRGB = stim_color,
lineWidth = 1.0,
fillRGB = stim_color,
vertices = [[-frame_outsize, -
frame_outsize],[ frame_outsize,-frame_outsize],
[ frame_outsize,
frame_outsize],[-frame_outsize, frame_outsize]])
frame_in= visual.ShapeStim( myWin,
units = 'norm',
lineRGB = bg_color,
lineWidth = 1.0,
fillRGB = bg_color,
vertices = [[-frame_outsize
+frame_width, -frame_outsize+frame_width],
[ frame_outsize-
frame_width, -frame_outsize+frame_width],
[ frame_outsize-
frame_width, frame_outsize-frame_width],
[-frame_outsize
+frame_width, frame_outsize-frame_width]])

circ = visual.PatchStim(myWin,
tex = 'none',
mask = 'circle',
units = 'norm',
pos = [0.0,0.0],
size = .15,
rgb = [1.0, 1.0, 1.0])


#frame_out.draw()
#frame_in.draw()
#circ.draw()
#myWin.flip()

frames = [3,2,1,3,1]
durs = [test_fr,1*FPS,0,test_fr,context_fr-test_fr]
actual_durs = []
mean_fr_dur = [[],[],[],[],[]]
blank = 2

def draw_TCE(fr_type):
"draws appropraite frame (given by fr_type) to the global window
and flips"
global_clock.reset()
if fr_type==1: # context only
frame_out.draw()
frame_in.draw()
myWin.flip()
elif fr_type==2: # blank screen
myWin.flip()
elif fr_type==3:
frame_out.draw()
frame_in.draw()
circ.draw()
myWin.flip()
elif fr_type==4:
circ.draw()
myWin.flip()
return global_clock.getTime()

stim_clock = core.Clock()

for i in range(len(frames)):
print "drawing frame " + str(frames[i]) + " for " + str(durs[i]) +
" frames"
for d in range(int(durs[i])):
mean_fr_dur[i].append(draw_TCE(frames[i]))
actual_durs.append(stim_clock.getTime())
stim_clock.reset(0)
draw_TCE(blank)

print actual_durs
print mean_fr_dur
m = np.mean(mean_fr_dur[1])
print m
print "FPS = " + str(myWin.fps())
event.waitKeys()
myWin.close()
core.quit()

Jon Peirce

unread,
Jul 12, 2009, 9:43:00 AM7/12/09
to psychop...@googlegroups.com
Hi Tommy,

For me (on a macbook air) the only dropped frames I see are at the
beginning of the run, which is common because of the overhead of setting
up the window etc. Adding 10 or 20 blank frames (just win.flip() a few
times) before the main script is enough to leave no dropped frames in
the critical period. Obviously in a real experiment this would occur
naturally during instructions/fixation screens at the beginning of the exp.

Also you tend to get slightly better performance in full screen mode
(set fullscr=True during window init).

Lastly, you're calling win.fps() at the end of the script, but now in
psychopy you have to manually set the recording of frame times to occur
(so that in periods of non-drawing the stats don't get messed up). So
typically a script might have something like;

# set up window and stimuli

#present some dead frames to allow setup to occur
for i in range(20):
win.flip()
win.setRecordFrameInterval(True) #this has to be turned on manually
win.frameClock.reset() #this should be handled by
setRecordFrameInterval, will be as of 1.00.04!

#run the rest of your study...

#then check for dropped frames
win.fps()
#print individual intervals
print 'frame intervals:', win.frameIntervals
#or save them to a log file
win.saveFrameIntervals('lastFrames.log')

Hope this helps!
Jon

Alex Holcombe

unread,
Jul 13, 2009, 10:23:27 PM7/13/09
to psychopy-users
Perhaps a bunch of win.flip() calls should be added to
visual.Window
by default, with a boolean flag available to turn it off for those who
don't want it. That would prevent other newbies from getting bad
timing with psychopy. But I'm sure Jon is extremely busy with
programming other things!

Jon Peirce

unread,
Jul 14, 2009, 6:42:23 AM7/14/09
to psychop...@googlegroups.com
I could do this very easily but my guess is that it's better to have it after initialising stimuli too, rather than just after initialising the window, and that needs to be done by the user. By the way, I don't think we need flips as such, just a pause to allow everything to settle should be fine. I'll add this to the new script-generating GUI (which will partly serve to generate best-practice scripts) but for now I think the use of a period of fixation, or a ready message etc will take care of it for nearly all experiments.

Incidentally, on OS X and linux you can alter the priority of a running script with
os.system("sudo renice -n %s %s" % (new_nice, os.getpid()))
With new_nice set to -20 you'll get maximum priority (negatice niceness means not very nice for other proceses). Unfortunately, you need be sudo for this so you need to type in the password each time. For most cases I doubt that's worth the hassle.

Jon

This message has been checked for viruses but the contents of an attachment may still contain software viruses, which could damage your computer system: you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation.

da...@davebritton.com

unread,
Jul 14, 2009, 2:48:35 PM7/14/09
to psychop...@googlegroups.com
It appears that the latest source download and installation
documentation of PsychoPy doesn't note that if you want to use the
parallel port IO you need to install the winioport.py package as a
dependency. It says so in the reference documentation in the source
code, but it would be good for this to be mentioned in the Windows
dependency installation section also, with a link to the winioport
download at http://www.geocities.com/dinceraydin/python/indexeng.html
. Also, some reference to Python2.5 vs. 2.4 might be important, so the
user doesn't install ctypes for 2.4 as the winioport readme says to do
(unless they really are using 2.4) because 2.5 already comes with
ctypes. And, yikes, is there some way to make this potentially
important functionality less dependent on a geocities home page? On
that page Aydin writes "Thanks to DriverLINX Port I/O Driver for Win95
and WinNT..." which driver is probably embedded in Aydin's exe file,
although it's proprietary to SST, so the open sourceness of winioport
is troubled. Is there an alternative to SST's DriverLINX available in
open source?
-Dave

Jon Peirce

unread,
Jul 15, 2009, 5:13:39 AM7/15/09
to psychop...@googlegroups.com
For now I've added winioport to the dependencies on the installation page.

winioport.py itself could simply be included with PsychoPy (in the same way that serial.py is already). This is essentially trivial because these are single-file packages and include their licenses are compatible and included in the file. That would solve the issue of incorrect instructions for installing ctypes. PsychoPy already depends on ctypes, but i imagine most new users have python2.5 so don't need it.

So the bigger issue is with dlportio. I don't know about SST's policy for distributing that, but I'll email them and find out if they mind us distributing it ourselves, either wrapped into psychopy or as a separate download from our site.

chrs,
Jon
Reply all
Reply to author
Forward
0 new messages