psychopy.org | Reference | Downloads | Github

Click sequences


#1

Hello everyone,

I am creating a task in which three similar shapes (e.g. squares; S1, S2, S3) with different sizes are presented on the screen in each trial and participants have to order them from the smallest to the largest one.

I want to use a mouse component to collect the responses - every time that the participant clicks on a shape, I want to record the name of the shape on which the mouse has been pressed. At the end of the trial I want a response column with (S*, S*, S*) and I want to check if it matches my “corrAns” column.

I managed to write the code component to some extent, but for each trial it saves only the last shape I click on instead of all of them. The mouse is set to collect mouse state “on click”. I am not very familiar with coding… Does anyone know what is wrong in my code and how I can collect information for all the three clicks?

Begin Experiment:

mouse.clickSequence = []

squares = [S1, S2, S3]

Each Frame:

for square in [S1, S2, S3]:

    if mouse.isPressedIn(square):
            mouse.clickSequence.append(square.name)
            thisExp.addData('clickSequence', square.name)

End Experiment

if mouse.clickSequence == eval(corrAns):
    thisExp.addData('correct_trials', 1)
else:
    thisExp.addData('correct_trials', 0)


#2

You are currently only getting the last value as this is how you store the data:

thisExp.addData('clickSequence', square.name)

i.e. you are explicitly storing only one value. You could instead do this:

thisExp.addData('clickSequence', mouse.clickSequence)

But this will embed the entire list into a cell in your output data file, and this can make analysis quite tricky. Instead, I would recommend storing each stimulus name in its own column in the data. This would most easily be done at the end of the routine. There is no guarantee the list actually contains 3 entries, so you need to protect against that (also note that your current code allows for more than 3 entries: you might want to consider that).

for i in range(3):
    try:
        # store variables response_0, response_1, etc
        thisExp.addData('response_' + str(i), mouse.clickSequence[i])
    except IndexError:
        thisExp.addData('response_' + str(i), '') # no response

#3

Hi Michael,

Thank you very much for your answer and for spotting that mistake.

I made the first change that you suggested. It is true that my output looks tricky and difficult to analyse. This is not only because there are multiple elements in each list in a cell, but also because the lists are “added together”. For example if the output list of the first loop (which is a trial) has 9 elements, the same 9 elements are reported also at the beginning of the output list of the second loop and followed by the list of the second loop, and so on… To solve this, I have tried to change “thisExp.addData” to “currentLoop.addData” or “trials.addData” but it does not change.

I think the above problem also affects the bit of code you suggested to collect the responses - which is actually much easier to analyse, thanks! Currently, it seems that only the very first shape selected is taken for all the three answers not only in the first trials, but also in all the subsequent trials. I think that the fact that I have the same responses across trials is linked to the problem above, but I am not sure to understand why it is also the same response within the same trial.

Any further suggestion would be highly appreciated.

Many thanks,
s


#4

Righto. You need to shift this line:

mouse.clickSequence = []

from the Begin Experiment tab to the Begin routine tab, so that it gets reset at the start of every trial.

Although I’m not entirely sure what your trial structure is. You seem to say that a loop equals a trial, rather than a single iteration of the loop equalling a trial? If you need something to happen just once per loop, you can do something like this:

if your_loop_name.thisN == 0: # only on the first iteration of the loop
    mouse.clickSequence = []

#5

Hi Michael,

Sorry for the confusion - a single iteration of the loop is a trial, so I don’t need the last part of coding.

The suggestion of having different column for each response is really helpful, but unfortunately it still takes into account the number of frames. For example, if the first answer in S1 lasts two frames, and the second one in S2 lasts three frames, my “response_” columns will be S1 - S1 - S2. Is it possible to save only the first frame of a click?

The only way I can think of to get around this problem is by setting a loop to be a trial and store the mouse click at the end of each routine… It would not be an elegant solution, but it should work (?)…

Thanks in advance,
S


#6

I’m a bit lost here, but I think you are saying that you can record multiple responses to a single stimulus: this is likely because .isPressedIn() will keep reporting True until the mouse button is released. If you don’t want to record such multiple instances, you need to explicitly filter them out. e.g:

for square in [S1, S2, S3]:
    if mouse.isPressedIn(square):
        # store the first response:
        if len(mouse.clickSequence) == 0:
            mouse.clickSequence.append(square.name)
        # for subsequent responses, only store if they aren't a repetition
        # of the immediately prior one (entry [-1]):
        elif mouse.clickSequence[-1] != square.name
            mouse.clickSequence.append(square.name)