psychopy.org | Reference | Downloads | Github

Show group of eight elements, mark down some of them and get information about marked in coding mode

Hi.

Currently I developing following test of working memory:

  1. I show a series of symbols (one at a time about 0.4-1 seconds each) to subjects and they have to remember them.
  2. Then I show a group of eight items and asked to remember which of those eight they just already saw in the sequence.
  3. The subject must mark down (preferable via using mouse) items that were in the series and then I will calculate all that I need.

Question: What kind of PsychoPy objects you can recommend me to use for showing group of eight elements and getting information about pressed items?

OS : Linux
PsychoPy version : 3.1.3

The mouse component allows you to enter a list of stimulus names that are clickable. So let’s say you have eight image stimulus components, called image_1, image_2, etc. Put that list of names, separated by commas, into the “clickable stimuli” list, and in the “Store params for clicked” field, type name. Then PsychoPy will record for you the list of valid stimuli that were clicked.

Try starting with just accepting one mouse click response, as that is simple. Then once you have implemented that, come back to us for specific advice on how to allow multiple responses before ending the trial.

You might also want to think about providing visual feedback (e.g. highlighting already-clicked items). Again, once you have the task mostly implemented, it will be easier for us to give specific suggestions to provide that.

1 Like

I can not figure out issue with mouse buffer.
I use components TextStim for show some random symbol (from font Symbola)
I want to change contrast of stimuli (instance of TextStim) when mouse was pressed.
I put to code component in tab “Begin Routine” this code:

if sum(mouseResp.getPressed()) and stim.contains(mouseResp):
    stim.setContrast(-stim.contrast)
    print('{} was pressed'.format(stim.name))
stim.draw()
win.flip()

But as I can see, this instruction stim.setContrast(-stim.contrast) executed 2-5 times. I need only 1 :slight_smile:

May be better place here all code related to it.
For showing symbols I have 8 text stimuluses saved in dictionary SymbStimuluses
In path[‘trialList’] I store randomly generated symbol.
InstrAfterTrial contain text with instruction to choose symbol
And I use Builder mode because I wanna later run experiment @ pavlovia

for thisStim in SymbStimuluses:
     globals()[thisStim['name']].setText(chr(path['trialList'][SymbStimuluses.index(thisStim)]))
     globals()[thisStim['name']].setPos(thisStim['pos'])
     globals()[thisStim['name']].setContrast(symbols['contrast'])
event.clearEvents()
while True:
    keys = event.getKeys()
    if 'space' in keys:
        break
    for thisStim in SymbStimuluses:
        if sum(mouseResp.getPressed()) and globals()[thisStim['name']].contains(mouseResp):
            globals()[thisStim['name']].setContrast(-globals()[thisStim['name']].contrast)
            print('{} was pressed'.format(globals()[thisStim['name']].name))
        globals()[thisStim['name']].draw()
    InstrAfterTrial.draw()
    win.flip()

At a glance I think it’s just executing on every frame, and even a single click takes place over a few frames at 60Hz. What you want is some kind of check that the mouse had not been pressed on the previous frame. Two easy solutions.

  1. Create a boolean to track whether the mouse has been clicked on the previous frame, and make it part of the if statement. So:
for thisStim in SymbStimuluses: 
    if not clickHappened and sum(mouseResp.getPressed()) and globals()[thisStim['name']].contains(mouseResp): 
        clickHappened = True
        globals()[thisStim['name']].setContrast(-globals()[thisStim['name']].contrast) 
        print('{} was pressed'.format(globals()[thisStim['name']].name)) globals()[thisStim['name']].draw()

and just make sure you initialize clickHappened as False, and then add one extra statement:

if not sum(mouseResp.getPressed()) and clickHappened:
    clickHappened = False

to reset it.

  1. You can put in a while loop in the middle of this that waits for the mouse to be released before doing anything else. That will just mean things happen on mouse-up rather than mouse-down, which you can decide whether or not you want.
for thisStim in SymbStimuluses: 
    if sum(mouseResp.getPressed()) and globals()[thisStim['name']].contains(mouseResp): 
        while sum(mouseResp.getPressed()):
            pass
        globals()[thisStim['name']].setContrast(-globals()[thisStim['name']].contrast) 
        print('{} was pressed'.format(globals()[thisStim['name']].name)) globals()[thisStim['name']].draw()

etc.

1 Like

Jonathan is on to it in terms of needing to keep track of whether the mouse has been released after it was initially pressed.

But you shouldn’t insert while loops like this in Builder-generated code. Builder code runs on a cycle of keeping up with the screen refresh. A while loop could easily make your code take more than one screen refresh cycle to complete (if tracking mouse-down duration, this will almost certainly happen, as Jonathan notes). This will then break all of Builder’s careful timing control.

So don’t enter into a loop waiting for the mouse to be released. Just maintain boolean variables that track when the mouse is pressed and when it has been released. i.e. deal with that status in program logic rather than entering into an indefinite loop.

Also, for the same reason, never call win.flip() in Builder experiments. Builder calls win.flip() once per drawing cycle. If you call it yourself, again, you will break Builder’s careful drawing-cycle centred code by pausing until the next screen refresh, well before Builder has finished everything else that needs to happen on the current cycle.

2 Likes