Hi there, I am running an fMRI task in Psychopy 2025.X.X on Windows 11 in which a target appears and the participant is instructed to press the button during this target. The task is supposed to record the reaction time for this button press. For the most part, the code does this, however, in a variable number of trials, the reaction time is not recorded. The log files all look like this when this occurs:
| 319.4994 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.4994 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.5161 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.5328 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.5495 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.5661 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.5825 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.5993 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.6161 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.6329 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.6495 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.6662 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.6828 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.6995 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.7161 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.7328 |
EXP |
unnamed Polygon: autoDraw = True |
| 319.7343 |
DATA |
Keypress: 1 |
| 319.7495 |
EXP |
unnamed Polygon: autoDraw = False |
I tried switching between Psychopy default dependencies and iohub to accept button presses and the issue persists. I am wondering if anyone has experienced similar issues and if there are any easy workarounds? We are using a Fiber Optic Response Devices 8 Button fMRI Response Pad.
Thank you!
Akash
Dear Akash,
Each row of that output is a specific frame. So to me, it looks like your participant pressed “Key 1” at 319.7343 seconds (global clock).
Could you provide more information about your experiment? Are you using builder or coder? If you are using builder, what type of response are you using (keyboard, buttonbox, custom code, serial/parallel)?
Make sure you have the “save onset/offset times” box check as well.
Issac
Hi Isaac,
Thanks for the quick response!
We use the coder for the experiment and are running it separately with both a button box and keyboard inputs. I have found I encounter the same issue in a portion of the trials using both the keyboard and button box.
Does this seem like an issue with the logic of the code? I have tried a number of code changes to account for instances when the input comes in this specific frame with little success.
Thanks!
Akash
Dear Akash,
Could you share some of that code? How much does it differ from psychopy’s basic key press evaluation logic?
# if key_resp is starting this frame...
if key_resp.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
key_resp.frameNStart = frameN # exact frame index
key_resp.tStart = t # local t and not account for scr refresh
key_resp.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(key_resp, 'tStartRefresh') # time at next scr refresh
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'key_resp.started')
# update status
key_resp.status = STARTED
# keyboard checking is just starting
waitOnFlip = True
win.callOnFlip(key_resp.clock.reset) # t=0 on next screen flip
win.callOnFlip(key_resp.clearEvents, eventType='keyboard') # clear events on next screen flip
if key_resp.status == STARTED and not waitOnFlip:
theseKeys = key_resp.getKeys(keyList=['y','n','left','right','space'], ignoreKeys=["escape"], waitRelease=False)
_key_resp_allKeys.extend(theseKeys)
if len(_key_resp_allKeys):
key_resp.keys = _key_resp_allKeys[-1].name # just the last key pressed
key_resp.rt = _key_resp_allKeys[-1].rt
key_resp.duration = _key_resp_allKeys[-1].duration
# a response ends the routine
continueRoutine = False
Also, have you tried between all 3 of the keyboard backends (iohub, pyglet, PsychToolbox)? You only mentioned two in your original post. I know I had issues with that when using a CRS Eyetracker, a Cedrus button box, and a keyboard. I decided to just remove the button box (as gaming keyboards are as good, or better than button boxes these days).
However, looking at your input device, could explain what you are using to convert the optical to parallel/serial/USB? It looks like it uses optical signal and then you have an interim box thing that converst that to USB output (almost similar to a optical→TTL converter). First thing I would do is see what happens when you remove the keyboard input component, and only use the button box. This is to narrow down the problem being specific to the interaction between the button box and keyboard, or is it something specific to how psychopy is reading the input from your “905” interface/ “Current Designs” box
Issac
Hi Isaac,
Below is code for each trial:
`# -------Start Routine “Target”-------
# Log target onset time
exp.addData(‘Tgt.OnsetTime’, runClock.getTime())
while continueRoutine and routineTimer.getTime() > 0:
# Get current time
t = TargetClock.getTime()
# Selection screen updates
if t >= 0.0 and Target.status == NOT_STARTED:
# Keep track of start time/frame for later
Target.tStart = t
# Display target
Target.setAutoDraw(True)
# Open response options
target_response.tStart = t
target_response.status = STARTED
# Keyboard checking is just starting
win.callOnFlip(target_response.clock.reset) # t=0 on next screen flip
event.clearEvents(eventType='keyboard')
theseKeys = []
if Target.status == STARTED and t <= target_durs.loc[0,trial_type]:
Target.setAutoDraw(True)
theseKeys = event.getKeys(keyList=forwardKeys)
if len(theseKeys) > 0:
rt = target_response.clock.getTime()
target_response.rt = rt
if trial_response == 0:
trial_response = 1
# Check if all components have finished
if not continueRoutine:
break
continueRoutine = False
for thisComponent in TargetComponents:
if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
continueRoutine = True
break # At least one component has not yet finished
# Draw fixation if we're done, so we don't leave a blank screen for any frames
if not continueRoutine:
fix.draw()
win.flip()`
I tried adapting the task to use iohub, however, it was not compatible with our stimulus presentation computer at the scanner as button presses failed to record. Given this is an fMRI task, it unfortunately won’t be possible to switch over to exclusively using a keyboard.
My feeling is the issue lies in how psychopy is reading keyboard presses because the issue is present in both in-scanner runs and out-of-scanner runs on the laptop.
Below is the code specific to where the issue occurs:
`# Set the fixation after target by accounting for the variable target
# time window
if rt:
fix_after_target = isi_target_isi_time - fix_after_cue - rt
else:
fix_after_target = isi_target_isi_time - fix_after_cue - target_durs.loc[0,trial_type]
too_slow_rt = show_fixation(fix_after_target)
if too_slow_rt:
print('too slow rt: ', too_slow_rt)
trial_response = 3
exp.addData('trial.too_slow_rt', too_slow_rt)`
Thanks!
Akash