OS (e.g. Win10): Win10 PsychoPy version (e.g. 2024.2.4 Py 3.8): 2024.1.4 Standard Standalone Installation? (y) If not then what?: Do you want it to also run online? (n) What are you trying to achieve?:
I am currently piloting an fMRI study (using Current Design Buttonboxes as response button) and ran into the problem that, from some point in the experiment on, the buttonpresses seem not to be logged correctly anymore. Even though i can see the subject’s buttonpress using the LED display of the buttonbox, they do not seem to be registered within the experiment (not displayed on a second screen of the presentation PC) and appear as “None”-response without a reaction time within the csv-logs. However, they have been registered within the .log-logfile that i intended to use primarily to check the timing of triggers etc.
“None” is registered as allowed key, perhaps that could be a problem, but then again it isn’t for the first part of the experiment. I cannot seem to find a pattern, except that the issue worsens as the experiment progresses, i.e. within the final block 40-90% of the responses are “missed” by the software. Since i am computing performance-based rewards on a block level and present this feedback to the subject, I cannot rely on the .log-logfile to “correct” the logfile afterwards.
I used the builder to create the experiment and added some custom code blocks to define the target response, log information and display information about the current trial and response on a second screen.
What did you try to make it work?:
I edited the keyboard components, added an else-statement to check whether there might be an issue with the definition of the target key-press and printed it to the second screen that i also use to monitor the responses. I also checked the keyboard-component.started and .stopped columns to find out whether the component is “active” during the window of 2.1 s for the response. I also spot-checked whether the keypresses registered within the logfile would fall into that window.
I will add the pyhton script as well as some screenshots of the keyboard component and the data tab from the settings-cog. I have two subsequent conditions, each with a nested trial/block loop and both are started by triggers from the scanner (emulated as ‘t’ keypress). The keyboard components within both trial routines have identical settings and different variable names but the problem appears primarily within the second loop (or perhaps worsens more dramatically because the loop is longer and starts later within the study).
Please let me know if you need additional information, I’d be happy to add files or screenshots if it helps.
Yes, i removed “None” as an allowed key following my post here. I originally used it, thinking that it might be easier to discriminate no responses from wron buttons but i recognized that it’s not needed for that. Similarly, i included 8 and 9 in the each frame code, just in case a subject presses one of the other buttons on the buttonbox, but in practice that rarely happens, so i removed them from the “allowed keys” tab and forgot to adapt the code snippet.
We originally planned with a 2s response time-out and i had the trial routine set up in a way that it would last 2s (with the keyboard component also ending after 2s) followed by a 500 ms blank screen. Following those problems with registering of the responses i moved the blank phase inside the trial component and wanted to check whether a longer keyboard component duration and a short pause at the end of the trial might help saving all data. I thought that maybe, some operations might benefit from that, as I suspected that perhaps there might be problems when several components start and end at the same time. But I suspect that should not be a problem.
I will pilot the experiment again with a button- and a triggerbox on my laptop, to check whether removing “none” from the allowed keys section and extending the duration of the keyboard component to the end of the routine already does the trick!
I adjusted and tested several things but the bug/problem persists. I
removed “None” as an allowed key
split the code component used to present the keypresses and correct responses on the second screen and to log the trial performance measures into two parts. Before that, sometimes the .corr system variable and another logged variable that copied the status of that variable would differ but now the values are identical again.
added “key_resp_base.clearEvents()” in the beginning of the routine tab of the keyboard component to clear the keyboard buffer at the beginning of each trial
downloaded the most recent stable PsychoPy version that is also installed on the presentation computer of the scanner facility (v2024.2.4)
tried out a different buttonbox to check whether the problem stems from the hardware side
The problem still persists and the experiment runs fine for the first half of the experiment (i.e. the baseline block loops of the experiment) but gets progressively worse and does not log responses correctly (they appear as missed keypress without a reaction time).
However, the bug only appears at the scanner set-up and i cannot replicate it on my work laptop which complicates the debugging process.One more thing I noticed, is that the keyboard-component “.stopped” variable is not being logged consistently.
I will try out the approach from this post to change the logging of the response from “keypress” to “keyrelease” but it really is the last straw because I have no idea what else I could try out to make this work. Unfortunately, i cannot switch the key-release type as the interface does not include a button or display (e.g. I cannot switch between HID KEY vs. HID NAR and i don’t know which of these is currently active).
EDIT:
Might it perhaps be more sensible to use code component instead of using the preconfigured keyboard component? And would there be any examples for this approach? Perhaps it is a problem that the keyboard component is used 68 times per block and the performance of the component gets flakier or more errorprone with so many repeats?
I haven’t looked at all your routines. However, I noticed that you have added a win.flip() command to some code components, for example SaveTrialInfo_Base in the ‘Each Frame’ tab. This is not advised, as the builder will execute this command anyway.
Try saving information during non-critical phases of your experiment, for example at the end of the routine rather than after each frame.
You can also tell PsychoPy to save the onset and offset of routines and components. It is rarely necessary to do this by code. The code component end_fixation in the fixation routine does nothing. You already end the routine with a keypress, as you selected ‘Force end of routine’ for the keyboard component.
baseline_trial and cond_trial appear to perform the same function. Reuse a routine instead of rewriting it. This simplifies debugging and maintenance (see Wakefield's Daily Tips - #7 by wakecarter).
Also delete routines that you are using, e.g. ready_base.
I get the impression that you have mixed Builder routines and components with your own code. Only use code components if the Builder components do not offer the same option.
Thank you for your suggestions! I am currently implementing them. In the meantime, I did try out the suggestion of aforren1 from this post to switch to measure key-release instead of key-press. I just tested it once and it seems to run with less loss of responses at the scanner.
However, my supervisors are hesitant to move forward with that change, as usually we would measure the key-press as reaction time and not the release. At the moment, I am trying to find out, how the button box was configured and whether it does in fact send the automatic release signal with some fixed offset. I will check that, the next time I have access to the scanner but there’s not really any kind of display or manual regarding the button box, so I mostly rely on asking around.
So, now i am wondering: what does “.duration” of the keyboard component measure (esp. when it is set to measure RT in response to the key-release)? Is this the duration between start and end of the component within the routine (but this should be fixed to the pre-defined duration of the component?) or the duration of the key-press or something different? I couldn’t really find detailed information on that.
Maybe it is possible to infer the RT related to the key-press from the key-release timing?
Sorry again, for the long post and thank you so much for the support so far!
Look here to see what ‘duration’ means in this context: Measuring key lift time relative to stimulus onset. However, I am not sure that this will solve your problems. You want to register all RTs, not just most of them.
Have you tried addressing any of the issues I mentioned above?
Saving information to the disk at a time-critical moment;
using win.flip even though you shouldn’t,
storing information about the time yourself when PsychoPy can do this for you?
Thank you for the link, @JensBoelte! So, if I understand correctly, I should be able to determine the RT related to the keypress by subtracting the duration from the RT measured on the key-release.
The circumstance, that on first sight, i cannot tell from the csv whether a subject just did not react within the timeframe for the response or whether it was not correctly logged complicates the issue. So, i subsequently checked all trials without a response against the .txt logs. Specifically, checking whether any buttonpress was logged in the .txt log within the timeframe of keyboard-component.started and .stopped (or .started + 2.4s, in cases where the .stopped was not logged).
I tested two subjects with the key-release condition and in one of them only 4 responses are logged within the .txt that appear as no response in the csv. I would suspect that these are cases, where the subject pressed the button late within the component and did not release it in time. From the other subject no responses are missing.
Within the key-press condition, the number of “lost” reactions was 69 or 91 trials in the latest tests and 169 “lost” reactions in an earlier testrun.
I tried out a number of different things in the last few days (using the intended key-press setting) at the scanner facility:
cleaning up the code: reusing the trial routine for the baseline and the condition loop, deleting some of the routines that are not needed, removing code from the “each frame” tab and introducing a bool to ensure that the second screen is only flipped once after a response has been registered (moving this to the end of the routine defeats the purpose of monitoring which button was pressed as this information would only be present for one frame). However, the issue still persists
i tested a version without the second monitor, removing all the code bits related to that, but that still resulted in data loss
did a test-run without the scanning sequence running (no emulated key-press triggers sent) so that i could use the buttonbox and keep an eye on the monitors and an open task manager. Here, everything seemed fine and no responses were lost (but i also didn’t react really fast or pressed the button as lightly as perhaps someone would when lying in the scanner using their index fingers)
I additionally wanted to check whether the Button box sends an automatic release signal and started the experiment with the buttonpresses set to register key-release. I noticed that the trial timing is affected when I keep pressing one button for a longer time than intended, i.e. pressing the button down across multiple trials. Of course this would not be the “normal” usage of the buttonbox but this resulted in the screen freezing for the duration of the key-press and then skipping the blanks and mutliple trials as soon as the button is released again.
This also happens, when I test the experiment on my usual set-up, not immediately but after some trials of extended presses.
Since I couldn’t solve the issue with the accumulation of not registered reactions in the key-press setting, I am considering to change it to key-release. But the screen freezing issue might risk the non-slip timing. Is this a common side-effect of the key-release setting and is there a way to prevent this from happening?
I’ll try to create a minimal example where the screen freezing occurs but this might take a day or two.