psychopy.org | Reference | Downloads | Github

Creating a four alternative forced choice task

Dear users,
I have a working two alternative forced choice (2AFC) task in which participants are first shown a word, and then have to select the matching picture from two side-by-side choices. In builder, this is accomplished by having two picture objects in my loop. The loop reads from an excel file containing two columns: ‘Match’ and ‘Mismatch’. One picture object reads file names from the ‘Match’ column (Image field = $Match), while the other reads from ‘Mismatch’. It’s essential that the position of these objects is randomised on each trial, and this is accomplished using the following code component. Note that the position field for the Match object and Mismatch object is $matchPos and $misPos respectively.

In Begin Routine

if random()>0.5:
…matchPos = [-0.5,0.0]
…misPos = [+0.5,0.0]
…corrAns='left’
else:
…matchPos = [-0.5,0.0]
…misPos = [+0.5,0.0]
…corrAns=‘right’

I would like to adapt this paradigm to include two extra positions and two extra mismatch pictures (hence, a four-alternative forced choice task,). I imagine something like this:

master_positions = [[-0.5,0.0],[+0.5,0.0],[0.0,-0.5],[0.0,+0.5]
position = random.shuffle(master_positions)
if random()>0.25:
…matchPos=position[1]
…mis1Pos=position[2]
…mis2Pos=position[3]
…mis3Pos=position[4]
…corrAns = ‘left’

et cetera…

Can anyone suggest a way to get this working (or an alternative approach)? I’d be very grateful for any advice.

The approach of shuffling a list is a great way to randomise positions. You don’t need the if random()>0.25: bit though. Just assign positions to your stimuli once using elements 1 through 4 as you have done above.

The only remaining question is to determine what the correct response is. To do that, we need to know how you expect the subject to give their 4AFC response.

Thanks Michael! Responses are made with directional arrows on the keyboard - so ‘up’, ‘down’, ‘left’ and ‘right’.

Below, we modify your arrangement a bit so we don’t shuffle the positions directly. Instead we shuffle a list of indices that we then use to refer to the static lists of positions and responses in a random order. This allows us to always be able to match up the position of the match stimulus with its corresponding response.

Begin Experiment tab:

# specify lists of stimulus positions and their corresponding responses:
positions = [[-0.5, 0.0], [0.5, 0.0], [0.0, -0.5], [0.0, 0.5]]
responses = ['left', 'right', 'down', 'up'] 

# create a list of indices to those lists, which will
# get shuffled on each trial:
indices = [0, 1, 2, 3]

Every routine tab:

# randomise locations for this trial:
shuffle(indices)

matchPos = positions[indices[0]]
mis1Pos = positions[indices[1]]
mis2Pos = positions[indices[2]]
mis3Pos = positions[indices[3]]

# get the corresponding correct response:
corrAns = responses[indices[0]]

Note that this method uses true random allocation so the rep # of each configuration is a random variable. For balanced design it is better to do something as follows:

from itertools import permutations 
from itertools import repeat 
from random import shuffle

loc_list = list(permutations([(1,1),(2,2), (3,3), (4,4)]))
shuffle(loc_list)
while loc_list:
    loc_element = loc_list.pop()
    e1, e2, e3, e4 = loc_element
    print e1, e2, e3, e4

Dear Michael,

Apologies for the late reply. Thank you for your advice! I implemented the code you suggested. It seems to partially work as expected…but the experiment intermittently crashes and throws the following error:

corrAns = responses[indices[0]]
IndexError: list index out of range

Do you know what might be going wrong…?

Thanks again,
Lyam

You need to debug this to find the source of the problem.

e.g. sprinkle some (temporary) print statements near where that error is occurring:

print(indices[0])
print(len(responses))

etc

Dear Lyam

Similar to your experiment, My task uses a randomization methods, and like you, I got an error “IndexError: list index out of range”. Could you debug your codes?

I would appreciate any advice.

Thanks.

I’m afraid not - I ended up ditching the paradigm and taking a wholly different approach. If it helps at all, the example that I presented in my original question (see the top of this thread) definitely works for presenting only two possible options.

Sorry I couldn’t be more help. I suggest debugging the problem in your experiment, as Michael suggested to me, and posting the output in this thread.

1 Like

Dear Lyam

I debugged my own program. I think if you change the place of your final line, it can work.
I think you put this line at the routine tab:

corrAns = responses[indices[0]]

Go to the coder view and replace it at the end of the trial because there the keyboard has been defined.
Hope this comment helps.

Hi, fellows…

I’m trying to figure out how to present two comparison stimuli randomly, at the corners of the computer screen, as well. However, I’m using the mouse component to collect the participants’ responses. I used the excel grids to specify the correct responses(see req_response in the code below). In addition I used the following statements to register whether the participants’ response in a give trial was correct or incorrct:

if mouse_resp_fdn.clicked_name[0] == req_response:
…total_correct += 1
…som.setVolume(1)
else:
…som.setVolume(0)
thisExp.addData (‘total_correct’, total_correct)

This is working pretty well now that comparison stimuli are presented randomly at the bottom-left and bottom-right corners of the screen. Do I need to do any modifications here to achieve the same goal with comparisons presented randomly at the four corners?

Best,

It’s probably best if you delete this post and start a new topic that has sufficient detail to stand on its own. People are much more likely to answer if they down’t have to wade through a series of previous posts to understand yours.