Recording non-responses

Hello! I have a question regarding the recording of non-responses. In my experiment, people are instructed to press a key within a specific timeframe, which is then recorded as a ‘hit’ in my output. However, I would like to also record when they fail to press the key in the specified time window.
My current code snippet looks like this:

PM = “space” in keys
y=realClock.getTime()


elif PM:
y=realClock.getTime()
SpaceResponseTime.append(y)

    if 54 <= y <=60 or 0 <= y <= 4:    
        z='Hit'
        SpaceResponseType.append(z)
    
 ...      

if 54 <= y <=60 and PM != :
m=‘missed’
SpaceResponseType.append(m)

But what happens now is that even if a ‘hit’ occurred during the timeframe, ‘missed’ is entered for every other possible time point of the frame. Instead, I would like to have just one missed entered, if at the end of the time frame no response had occurred.

The second question I have in regards to this is that I would like to have only one ‘hit’ recorded in the time frame. Right now, multiple space bar presses in the time window lead to multiple ‘hits’ being saved, but ideally I would like the other ‘hits’ to be discarded. Is there a way to achieve that? I have tried with len(PM) <= 1, but apparently that was completely wrong syntax.

I hope all of this makes sense… Thanks in advance!!

Best Wishes,
Jasmine

Since your code contains an elif statement and no if statement, I have to assume that some key information is missing.

When does the routine end?

One approach would be to wait until the end of the routine and then cycle through all of the keyboard responses checking to see if each one is in the window and setting a flag to True if it is. Then save data based on whether the flag is True or False.

Does the routine only contain one window? I’m wondering whether your 0-4 is for overshoots because you think that y with go back to zero. Shouldn’t it be 54 to 64 seconds (or possibly 56 to 64 seconds if you want 4 seconds either way).

You might find my PM Time demo task useful to look at if you are also wanting participants to be able to check the time.

Thank you very much for your response! So the PM task is embedded in a lexical decision task, meaning that each routine is defined by the LDT and the routines are very short (~1.5s).
There is a clock component that runs across the trial, independent of the LDT routines, up to 60s and then resets itself to 0. We want to accept PM responses (space bar press) between seconds 55 and 0-4 (exactly, as an overshoot).
As you suggested, I tried to ‘flag’ the responses with the variable PMstate. I set it to PMstate = false at the beginning of the trial and then it should change to true when a correct PM response is given. Additionally, I have created an independent clock (myClock) that is initialised at the start of the first routine and then is supposed to reset the PMstate variable to ‘false’ at seconds 5, 65, 125,… of the trial.
The current issue here is that when a correct PM response is given, the PMstate changes to true, however, responses are still recorded as a hit. Also, the PMstate then remains ‘true’ and doesn’t return to ‘false’, meaning that after the first PM time window all responses are recorded as incorrect.
I will attach the entire code of this component below. Probably this is a simple syntax issue, but I lack knowledge to identify this.
I have also had a look into the example of a time-based PM experiment that you were referring to, but not sure I found the correct code. Do you mean the clock_flag?

Thank you again and again for taking your time to go through these issues!

Best wishes,
Jasmine

Begin Routine Tab:

### clock initialisation that ends experiment after xx seconds
if real.thisN == 0: # only on the first trial
    startTime = globalClock.getTime()
    PMstate = False
    PMc = 0
    myClock = core.Clock() 

x=-10
UResponseTime= []
SpaceResponseTime= []
SpaceResponseType=[]
msg= ''
TimeStamp = []
PMResponse = ['f', 'h']
PMidx= []
pmstate = []
TrialZeit = []

Each Frame Tab:

### end trial after 200 seconds

if globalClock.getTime() - startTime >= 200:
    real.finished = True
    continueRoutine = False

#GC = globalClock.getTime() 
#if y >= 7 and GC >= 65 and GC >= 125 and GC >= 185:
#    PMidx==False
    
#initialiesiere Tastatur 
kb= keyboard.Keyboard()
keys= kb.getKeys(['t',"space"], waitRelease = True, clear=True)
PM = "space" in keys
seconds = "Sekunden vergangen"
y=realClock.getTime()


#timer

    
if realClock.getTime() > 60: # LB 31.01: von 61 zu 60 geändert damit die Zeitangabe nachher nicht bis 61 geht (?)
    realClock.reset()
    PMc += 1
    PMidx.append(PMc)
    


if 't' in keys:
    x = realClock.getTime()
    UResponseTime.append(x)
    g = myClock.getTime()
    TrialZeit.append(g)


    
#Leertste

elif PM:
        y=realClock.getTime()
        SpaceResponseTime.append(y)

   
        if 54 <= y <=60 or 0 <= y <= 4 and PMstate == False:    
            z='Hit'
            SpaceResponseType.append(z)
            PMstate = True
            pmstate.append(PMstate)
            msg='Leertaste gedrückt'
            msgDuration = 1
        
        else:
            z='False Alarm'
            SpaceResponseType.append('f')
            msg='Leertaste gedrückt'
            msgDuration = 1
            pmstate.append(PMstate)
            
if  myClock.getTime() >= 5 or myClock.getTime() >= 60 or myClock.getTime() >= 180 or myClock.getTime() >= 240:
    PMstate = False
    
    
if realClock.getTime()-x < 5.0:
    Time = int(realClock.getTime()) + 1 # LB 31.01: + 1, damit es nicht bei 0 beginnt
    UNachricht= f"{Time} Sekunden vergangen" # LB 31.01: zuerst Zeit als Variable speichern und diese dann mit Text kombinieren mittels F-string
else:
    UNachricht= " "