Cedrus button box timing testing




Дата канвертавання15.04.2016
Памер89.94 Kb.
CEDRUS BUTTON BOX TIMING TESTING
28/3/08

ALW
We attempted to quantify the reliability of our Cedrus Response pad RB-730, which we used for several experiments. We wanted to know at what time the button was pressed relative to something being drawn on the screen.


The stimulus presentation is controlled in time by our python program loops, and we know the time of some stimulus being drawn relative to (a) the frame counter, updated manually with frame+=1 after each call of win.update(), and (b) the computer’s clock. The button-box has an internal clock all of it’s own, which is reset at the start of each trial by the python command s.write(‘e5’), where ‘s’ is the name of the connection to the button-box.
To find out the errors between the time the computer thinks a stimulus was drawn and the time the button box thinks a press was made, when the press is simultaneous with the stimulus, we did the following:
We asked John Holden to construct for us an apparatus that would press the button on the box when a flash appears on the screen. On a given frame, the computer screen flashed all white, and a light diode was held up to the upper left hand corner of the screen. The diode sent a signal to the oscilloscope, which sent a signal to a solenoid. The solenoid was held with a clamp so that it was touching, but not pushing down on the button. The flash would trigger the solenoid to press the button. John Holden said that he tested this apparatus and found the delays between the flash and the solenoid response to be nearly instantaneous, for our purposes at least.
The program I made (below) records the frame and computer-clock time of the flash, and it extracts the time the button-box thinks that the button was pressed. Then I can take the frame count, divide it by the screen refresh rate, to get the time the computer thinks the flash happened, and subtract from that the time the button-box says the press occurred.
I did this on both the mac tower (in the testing room to the left when you walk in the lab) and the Powerbook G4 laptop on which most of these experiments were run.
I also did tests in which the button-box timer was set only once at the start of the session, rather than at the start of every trial. Here are the results:

Mac Tower




DIFF BTWN FRAMECOUNT/HZ AND BB TIME







Average

Std Dev

Min

Max

50 trls, 50 resets

 

-31.75485714

2.354074482

-35.612

-26.612

50 trls, 1 reset

 

85.41285714

64.37537776

-22.657

190.242







 







 

Laptop




DIFF BTWN FRAMECOUNT/HZ AND BB TIME







Average

Std Dev

Min

Max

50 trls, 50 resets

 

-27.572

2.019900988

-30.612

-20.612

50 trls, 1 reset

 

166.76764

110.3286262

-16.657

353.152

HZ = 119.65, according to the tachometer.

In the table above, the errors were calculated as follows:

(frameOfFlash/refreshRate) – buttonBoxTimeOfPress. So, the fact that these errors are negative means that the button press time recorded by the box is greater than the time the computer thought it made the flash. This is not what we would expect if there were some delays in starting up the bb clock, but it is what we expect if it takes some time for the solenoid to press the button.


I also calculated the differences between the button box clock’s time and the time the computer clock said the flash occurred:


Mac Tower




DIFF BTWN COMP CLOCK AND BB TIME

 







Average

Std dev

Min

Max

50 trls, 50 resets

 

12.69016327

5.476571374

1.927

23.559

50 trls, 1 reset

 

135.1716122

69.93688168

18.636

251.753







 







 

Laptop




DIFF BTWN COMP CLOCK AND BB TIME

 







Average

Std dev

Min

Max

50 trls, 50 resets

 

10.72028

3.500040927

0.741

18.975

50 trls, 1 reset

 

134.13298

69.84315732

14.542

247.592

In my programs I used frames, not the computer clock, to know where to draw the stimulus.


Here is the code used:
#BUTTON BOX TIMING PRECISION TESTING

#1.0


#March 26, 2008

#This version resets box clock on every trial


from psychopy import *

from random import random

import numpy

from numpy import sin, cos, pi

from psychopy import serial

from struct import unpack


HZ=119.65
fileName = 'buttonBoxTest'

dataFile = open(fileName+'.txt', 'w')

dataFile.write('Button-Box Test with reset on every trial\n\n')

dataFile.write('Trial\t frameOfFlash\t timeOfFlash\t framePressRecorded\t timePressRecorded\t pressTimeByFrame\t boxPressTime\t frame-BoxDiscrep\t clock-BoxDiscrep\n')

trialClock = core.Clock()

win = visual.Window(monitor='g810', fullscr=1,units ='deg', rgb=-1.0)

win.setMouseVisible(False)
flash=visual.PatchStim(win, rgb=1, tex=None, size=[50,50])
s = serial.Serial('/dev/tty.usbserial-FT3ERKOD', 115200)

s.flushInput()

trialClock = core.Clock()
numTrials=5

currTrial = 1


while currTrial<=numTrials:

PRESSED = False

RELEASED = False

time_of_keypress_ms = -9999

timePressRecorded = -99

framePressRecorded = -999

s.write('e5') #start the button box's clock

frame=1


t0=trialClock.getTime()

t=0


s.flushInput()

while frame<300:

if frame==180:

flash.draw()

timeOfFlash=t

frameOfFlash=frame

if s.inWaiting() > 0:

if PRESSED == False:

response = s.read(6)

formatted_response = unpack('

time_of_keypress_ms = formatted_response[2]

timePressRecorded = t

framePressRecorded = frame

PRESSED = True

s.flushInput()
elif RELEASED == False:

ReleaseResponse=s.read(6)

formatted_ReleaseResponse=unpack('

time_of_release_ms = formatted_ReleaseResponse[2]

timeReleaseRecorded = t

frameReleaseRecorded = frame

RELEASED = True

s.flushInput()

else:

print 'a third response pad signal!!!!!!!'



extraResponse=1

s.flushInput()

frame +=1

t=trialClock.getTime()-t0

win.update()

#RECORD DATA

time_of_keypress = time_of_keypress_ms/1000.0

tPress_byFrame = frameOfFlash/HZ

frame_box_discrep = tPress_byFrame - time_of_keypress

frame_clock_discrep = tPress_byFrame - timePressRecorded

box_clock_discrep = timePressRecorded - time_of_keypress

dataFile.write('%i\t %i\t %f\t %i\t %f\t %f\t %f\t %f\t %f\n' %(currTrial,

frameOfFlash,

timeOfFlash,

framePressRecorded,

timePressRecorded,

tPress_byFrame,

time_of_keypress,

frame_box_discrep,

box_clock_discrep))

currTrial+=1
#BUTTON BOX TIMING PRECISION TESTING

#1.0


#March 26, 2008

#This version resets box clock at start of session only


from psychopy import *

from random import random

import numpy

from numpy import sin, cos, pi

from psychopy import serial

from struct import unpack


HZ=119.65
fileName = 'buttonBox1ResetTest'

dataFile = open(fileName+'.txt', 'w')

dataFile.write('Button-Box Test with reset on every trial\n\n')

dataFile.write('Trial\t frameOfFlash\t innerFrameOfFlash\t timeOfFlash\t framePressRecorded\t timePressRecorded\t pressTimeByFrame\t boxPressTime\t frame-BoxDiscrep\t clock-BoxDiscrep\n')


trialClock = core.Clock()

win = visual.Window(monitor='g810', fullscr=1,units ='deg', rgb=-1.0)

win.setMouseVisible(False)
flash=visual.PatchStim(win, rgb=1, tex=None, size=[50,50])
s = serial.Serial('/dev/tty.usbserial-FT3ERKOD', 115200)

s.flushInput()

trialClock = core.Clock()
numTrials=5

currTrial = 1


STOP = False

s.write('e5')

frame=1

overallT0=trialClock.getTime()



overallT = 0
while currTrial<=numTrials:

PRESSED = False

RELEASED = False

time_of_keypress_ms = -9999

timePressRecorded = -99

framePressRecorded = -999

innerFrame = 1

s.flushInput()

while innerFrame<300:

if innerFrame==180:

flash.draw()

timeOfFlash=t

innerFrameOfFlash=innerFrame

frameOfFlash = frame

if s.inWaiting() > 0:

if PRESSED == False:

response = s.read(6)

formatted_response = unpack('

time_of_keypress_ms = formatted_response[2]

timePressRecorded = t

framePressRecorded = frame

innerFramePressRecorded = innerFrame

PRESSED = True

s.flushInput()


elif RELEASED == False:

ReleaseResponse=s.read(6)

formatted_ReleaseResponse=unpack('

time_of_release_ms = formatted_ReleaseResponse[2]

timeReleaseRecorded = t

frameReleaseRecorded = frame

RELEASED = True

s.flushInput()

else:

print 'a third response pad signal!!!!!!!'



extraResponse=1

s.flushInput()

frame +=1

innerFrame+=1

t=trialClock.getTime()-overallT0

win.update()


#RECORD DATA

time_of_keypress = time_of_keypress_ms/1000.0

tPress_byFrame = frameOfFlash/HZ

frame_box_discrep = tPress_byFrame - time_of_keypress

frame_clock_discrep = tPress_byFrame - timePressRecorded

box_clock_discrep = timePressRecorded - time_of_keypress

dataFile.write('%i\t %i\t %i\t %f\t %i\t %f\t %f\t %f\t %f\t %f\n' %(currTrial,

frameOfFlash,

innerFrameOfFlash,

timeOfFlash,

framePressRecorded,

timePressRecorded,

tPress_byFrame,

time_of_keypress,

frame_box_discrep,

box_clock_discrep))

currTrial+=1

We also tried to figure out why there are differences in the time according to our frame counter and the time according to the computer clock.


The version above produces errors about 16 ms between the time the computer clock thinks the flash happened and the time the flash happened according to the frame counter and HZ.
But after messing around with it some, we got those errors to down below 1 ms with this code:
#BUTTON BOX TIMING PRECISION TESTING

#1.0


#March 26, 2008

#This version resets box clock on every trial


from psychopy import *

from random import random

import numpy

from numpy import sin, cos, pi

from psychopy import serial

from struct import unpack


HZ=119.65
fileName = 'buttonBoxTest'

dataFile = open(fileName+'.txt', 'w')

dataFile.write('Button-Box Test with reset on every trial\n\n')

dataFile.write('Trial\t frameOfFlash\t timeOfFlash\t framePressRecorded\t timePressRecorded\t pressTimeByFrame\t boxPressTime\t frame-clockFlash\t frame-BoxDiscrep\t clock-BoxDiscrep\n')

trialClock = core.Clock()

win = visual.Window(monitor='g810', fullscr=1,units ='deg', rgb=-1.0)

win.setMouseVisible(False)
flash=visual.PatchStim(win, rgb=1, tex=None, size=[50,50])
s = serial.Serial('/dev/tty.usbserial-FT3ERKOD', 115200)

s.flushInput()

trialClock = core.Clock()
numTrials=10

currTrial = 1


while currTrial<=numTrials:

PRESSED = False

RELEASED = False

time_of_keypress_ms = -9999

timePressRecorded = -99

framePressRecorded = -999

win.update()

s.write('e5') #start the button box's clock

frame=0

t0=trialClock.getTime()



t=0

#s.flushInput()

while frame<300:

if frame==180: #180

flash.draw()

timeOfFlash=t#trialClock.getTime()-t0

frameOfFlash=frame

if s.inWaiting() > 0:

if PRESSED == False:

response = s.read(6)

formatted_response = unpack('

time_of_keypress_ms = formatted_response[2]

timePressRecorded = t

framePressRecorded = frame

PRESSED = True

s.flushInput()


elif RELEASED == False:

ReleaseResponse=s.read(6)

formatted_ReleaseResponse=unpack('

time_of_release_ms = formatted_ReleaseResponse[2]

timeReleaseRecorded = t

frameReleaseRecorded = frame

RELEASED = True

s.flushInput()

else:

print 'a third response pad signal!!!!!!!'



extraResponse=1

s.flushInput()

win.update()

frame +=1

t=trialClock.getTime()-t0

#RECORD DATA

time_of_keypress = time_of_keypress_ms/1000.0

tPress_byFrame = frameOfFlash/HZ

frame_box_discrep = tPress_byFrame - time_of_keypress

frame_clock_discrep = tPress_byFrame - timePressRecorded

box_clock_discrep = timePressRecorded - time_of_keypress

frame_clock_FlashDiscrep = tPress_byFrame-timeOfFlash

dataFile.write('%i\t %i\t %f\t %i\t %f\t %f\t %f\t %f\t %f\t %f\n' %(currTrial,

frameOfFlash,

timeOfFlash,

framePressRecorded,

timePressRecorded,

tPress_byFrame,

time_of_keypress,

frame_clock_FlashDiscrep,

frame_box_discrep,

box_clock_discrep))



currTrial+=1


База данных защищена авторским правом ©shkola.of.by 2016
звярнуцца да адміністрацыі

    Галоўная старонка