Recording time of cursor in stimulus + restarting a trial if afk

What are you trying to achieve?:
I have four annuli (hollow circles) on the screen, each in their respective quadrants (no actual sectioning). I want to record the amount of time the participant spends in the correct annuli, then at the end of my experiment have a screen showing the participant’s average time spent in the annuli (might do it as a percent/ratio; doesn’t matter). I’m having troubles figuring out how to get the time.

What did you try to make it work?:

Begin routine:

from psychopy import core
core.clock.reset()

Each frame:

if mouse in [CorrectQuad]:
    RT = core.clock.getTime()
    thisExp.addData('RT in ms', RT*1000)

What specifically went wrong when you tried that?:

AttributeError: module ‘psychopy.core’ has no attribute ‘clock’

Python is case sensitive. The core module has a psychopy.core.Clock class with a capital C.

To use this class, you would first create an object of that class in the Begin Experiment tab:

myCustomTimer = core.Clock()
listToStoreTimeSpentInQuad = []

In Begin Routine, you create a boolean variable to track whether the mouse is in your stimulus:

endTimeInQuad = None
startTimeInQuad = None
mouseIsInQuad = False
myCustomTimer.reset()

Then you can use the code you used with your custom timer:

if CorrectQuad.contains(mouse) and not mouseIsInQuad: # the mouse was just moved inside the quad
    startTimeInQuad = myCustomTimer.getTime()
    mouseIsInQuad = True
elif not CorrectQuad.contains(mouse) and mouseIsInQuad: # the mouse was just moved outside the quad
    endTimeInQuad = myCustomTimer.getTime()
    mouseIsInQuad = False

In the end Routine tab, you can then store the values. I don’t know how you end your routine.
To handle cases, in which the mouse stays in the Quad stimulus and the routine is ended without the mouse moving outside of it, I added the if (startTimeInQuad is not None) and (endTimeInQuad is None) condition.

if (startTimeInQuad is not None) and (endTimeInQuad is None):
    endTimeInQuad = myCustomTimer.getTime()
thisExp.addData('startTimeInQuad', startTimeInQuad)
thisExp.addData('endTimeInQuad', endTimeInQuad)
if (startTimeInQuad is not None) and (endTimeInQuad is not None):
    thisTimeSpendInQuad = endTimeInQuad - startTimeInQuad
else:
    thisTimeSpendInQuad = 0
listToStoreTimeSpentInQuad.append(thisTimeSpendInQuad)

If at some point in your experiment, you want to retrieve the mean time spent in the Quad stimulus, you can use meanTimeSpentInQuad = mean(listToStoreTimeSpentInQuad).

P.S. You don’t need to import the psychopy.core module. The PsychoPy builder does that for you. You can check this if you compile the Python script and check the first few lines with import statements.

I haven’t checked this code, so it still may not be the optimal solution and it may raise errors, which you’ll have to debug. :wink:

1 Like

I think you want

Begin Routine
timer = core.Clock()

Each Frame

if mouse in [CorrectQuad]:
    RT = round(timer*1000)
    thisExp.addData('RT in ms', RT)

However, do you want the routine to end? I feel that this is going to keep overwriting the RT which doesn’t seem likely to be the intention.

You definitely shouldn’t be importing every routine, and I suspect you don’t need to at all.

I think @obeescee is not interested in the RT (despite what the code suggests) but in

Then you would have to record the time at which the mouse enters the stimulus area and the time at which the mouse leaves it, as I suggest above. But you make a good point about the need for some condition, which ends the routine.

Thank you so much. The code is working quite well and allows me to report the mean time spent in the correct annuli to my participant. Awesome. Now I’ll be figuring out how to pause/restart timer should the participant go in and out of the annuli (this should be doable with the foundation you’ve built for me. I see the path for such a thing).

I have one question: lets say I have 12 trials per loop, each ending automatically after 2.5 s. I want to restart a trial, not the loop in the case that the participant doesn’t move their mouse at all. Is there anyway to do that? I was thinking it’s possible with your variables. Something like this:

if not CorrectQuad.contains(mouse) and not inQuad:
  wait(1)
  #some statement to restart trial and not loop

Is there a difference between restarting a trial and not ending it?

Restarting a trial would mean we get 12 real (as in, no afk) trials. Not ending it, since trials automatically end after a few seconds, would mean null trials are still counted as trials (and a resulting <12 trials for data).

I was proposing that if you want the trials to end after 2.5 seconds but repeat if the mouse doesn’t move then they could end 2.5 seconds (or less) after the first mouse movement.

I’ve edited the title to aid those looking for solutions. This is what I did to restart a trial if my participant isn’t moving 1 second after stimulus presentation. More importantly, I also present them with some text reminding them of the task at hand (kind of).

if not inQuad and t >= 2:
    continueRoutine = False
    afk.finished = False
    afkMessage = True
else:
    afk.finished = True
    afkMessage = False

The screenshot of my flow may help interpret this. My afk routine is nested inside the trials routine (the ‘true’ loop; gives me amt of trials and randomness). Afk routine set to 99 reps.