Creating a clock for time based prospective memory task

Hi everyone, I am new to psychopy and trying to build a time-based prospective memory task. Specifically, the task should include a clock counting up from that appears for 3 seconds when participants press a certain button, in congruence with a n-back task. I’ve looked at a ton of past posts talking about implementing this clock feature, and right now my coding skills aren’t up to par therefore, I am having trouble integrating the code to fit my study and I would like to try to do this without having to create complex custom code.

Right now I have a trial with n-back words text (set to every repeat), a text clock (set to every frame) which just includes “$t” in the text field, response keys (set to every repeat), and a loop containing my n-back excel document. I also have a rectangle that partially covers up the text clock (right now the clock has too many decimals to be fully covered). I want the study to work so that a rectangle is always covering the clock unless someone presses the spacebar, then it becomes uncovered for 3 seconds.

Here are my current issues

  • the clock has way too many digits I want it to just include seconds w/o decimals- how would I do this?
  • right now, the experiment is only running if the text clock is set to every frame, although I would like it to be set to every repeat. This is the error message I am getting when I set it to every repeat:

text_clock.setText(t)
NameError: name 't' is not defined

  • the response keys are only changing the n-back words, I don’t have anything to remove the rectangle from the clock (the rectangle is timed to be on there for infinity), how could I configure psychopy so I have 2 groups of response keys (y/n) and spacebar that correlate to two different stimuli (n-back task and the rectangle)?

Please let me know if you have any advice! Again, I’m very new to psychopy so I apologize if these questions are confusing.

the clock has way too many digits I want it to just include seconds w/o decimals- how would I do this?

round(t)

the experiment is only running if the text clock is set to every frame

t is the time since the start of the routine, which is why it only works if you set to every frame. If you want a clock that spans across routines, you could create one using myClock = core.Clock() and then use round(myClock.getTime())

You might find some more answers if you look at my PM Time online demo. I also have a PM N-Back.

Thank you! I added a code component with myClock = core.Clock() during the begin experiment section of the code. The clock was working for every repeat, although but it was only counting up by 2 seconds (which is the duration of the text_clock stimuli).

Then I tried to utilize the clock code you provided in your code snippets page. I put code type to both and put myClock = core.Clock() in the python side of begin experiment and myClock = new util.Clock(); in the JS side. I also put myClock.reset() oldTime=0 in the python side of begin routine, newTime=myClock.getTime() mins = floor(newTime/60) secs = newTime%60 if newTime != oldTime: text_clock.text=str(int(mins)).zfill(2) + ':' + str(int(secs)).zfill(2) oldTime = newTime
in the python side of each frame and if ((newTime !== oldTime)) { clock_time.text = ((Number.parseInt(mins).toString().padStart(2,"0") + ":") + Number.parseInt(secs).toString().padStart(2,"0")); oldTime = newTime; } in the JS side of each frame. Finally I put **text_clock.setAutoDraw(False)** in the end routine python section. right now I am getting the following error:

mins = floor(newTime/60) NameError: name 'floor' is not defined

Do you know where I went wrong?

Hello,

floor is a function from the Python math-library. See here

how to deal with this problem.

Your need a code-component at the begin of the experiment which is set to both.

Best wishes Jens

Thank you for the demos! I have borrowed from your PM time code and am still not fully there yet: I have gotten the experiment to the point where it counts up on a screen with the n-back words, but haven’t been able to excute the step where pressing the space bar removes a rectangle covering up the clock for 3 seconds. Do you mind taking a look at my code? I thought it would allow me to make the rectangle transparent if the space bar is pressed but currently the rectangle is transparent all of the time even without pressing the space bar. Also, I have two reponse key elements, one for nback response keys that force the end of the routine, and one titled “spaceresponse” that is meant for the clock. Here is my code:

begin experiment:
countStarted = False

begin routine:
if not countStarted:
myClock = core.Clock()
countStarted = True

each frame
timeelapsed = myClock.getTime()
if spaceresponse.keys:
if 'space' in spaceresponse.keys:
polygon.setOpacity(0)
else:
polygon.setOpacity(100)

if timeelapsed >= 300:
continueRoutine = False
trials.finished = True
countStarted = False
else:
minutes = int(timeelapsed/60.0)
seconds = int(timeelapsed - (minutes * 60.0))
timeText = str(minutes) + ':' + str(seconds)

Hello,

does this help?

Best wishes Jens

1 Like

Hi Jens, working off of that forum post you sent, I set the polygon opacity to 1 and constant, and now I am able to press the space bar once for the polygon to become transparent, however it is staying like that. All of my keys including the backspace are set to every repeat- is this possibly causing the problem? I want at lest two of the keys set to every repeat and if I set the spacebar key to constant, the words stop showing up after the first repeat.

For the code, it would be good to have something like
if 'space' in spaceresponse.keys:
polygon.setOpacity(0) for 3 seconds

obviouly that isn’t the right structure- the post above had the opacity set to 1 every 10 seconds but I would like it to be set to 1 every 3 seconds after its transparency was activated.

edit: I set all aspects of the layout and appearance of the polygon to every repeat- It is kind of working now, however if i press the space bar like 2 seconds into the routine, it becomes opaque agian within one second.

I’m now in the process of moving the experiment online and although the code is working locally, I am getting the following error:

ReferenceError: timeelapsed is not defined

This is my code
Begin Experiment:
py
countStarted = False
js
countStarted = false;

Begin routine:
py
if not countStarted:
myClock = core.Clock()
countStarted = True
js
if ((! countStarted)) {
myClock = new util.Clock();
countStarted = true;
}
Each Frame:
py
timeelapsed = myClock.getTime()
minutes = int(timeelapsed/60.0) # the integer number of minutes
seconds = int(timeelapsed - (minutes * 60.0))

if PMtwobackAspacebar.keys:
if 'space' in PMtwobackAspacebar.keys:
PM2backApolygon.setOpacity(0)
else:
PM2backApolygon.setOpacity(1)

if timeelapsed >= 300:
continueRoutine = False
twobackAloop.finished = True
countStarted = False
else:
timeText = str(minutes) + ':' + str(seconds) # create a string of characters representing the time
js
if (PMtwobackAspacebar.keys) {
if (_pj.in_es6("space", PMtwobackAspacebar.keys)) {
PM2backApolygon.setOpacity(0);
} else {
PM2backApolygon.setOpacity(1);
}
}
if ((timeelapsed >= 300)) {
continueRoutine = false;
twobackAloop.finished = true;
countStarted = false;
} else {
timeText = ((Number.parseInt(minutes).toString() + ":") + Number.parseInt(seconds).toString());
}


Is there any way to adapt the js code on the “each frame” tab to work on pavlovia?

Put timeelapsed = 0 in Begin Experiment

Ok- that fixed that error but now it’s giving me a “minutes is not defined” error again. I tried to copy the format of your PM time code on the JS side for the “timeText =” portion - is there something else I’m missing?

In your screenshot it looks like you are using a Both component and have deleted the first three lines of Python code from the JS side.

I added “Number.parseInt” to minutes and seconds and deleted the corresponding JS for time elapsed, minutes, and seconds to see if that would help because I saw on your code notes that you didn’t have a corresponding JS for new time, mins, or secs (I’m really not an expert at javascript so I was just kind of moving things around to see if it could work). I tried adding the auto-generated JS code for timeelapssed, minutes, and seconds and I got the following error: " TypeError: Cannot read properties of undefined (reading ‘getTime’)"

I have also tried combining your code with a section that would allow me to show and hide a rectangle over the clock:

but even when I include import math for python and import * as math from 'math'; for JS in the begin experiment tab, I am still getting an error that floor isn’t defined when I run the experiment locally.
Do you have a suggestion for getting floor to work, or for getting my original adaptation of the code to work?

edit: sorry I just realized that the blank JS columns on your code page mean that the reader should use the automatic python to JS code. However, keeping that in mind I am still having trouble with floor not being defined locally, and the type error for ‘getTime’ online

After adding JS to accompany the python side of my code, I am still getting the error: TypeError: Cannot read properties of undefined (reading ‘getTime’) developer tools shows that it is occurring on the timeelapsed = myClock.getTime(); line. How/where would I define “get time” and would this solve this problem?

When you see that there’s a problem with undefined when reading getTime then that suggests that the issue is with myClock not getTime. Did you follow my crib sheet on how to define a clock in JS?