psychopy.org | Reference | Downloads | Github

Randomising stimulus positions and trials

Hello all,

Here is the background to my study. Participants will be asked to choose 4 different types of information, from four different lists of stimuli. One list will be comprised of a number of cities, one a list of code words, one a list of months and one list of faces.

The design of the experiment is four blocks, with 6 trials in each, so 4 X 6.

In 3 of the 6 trials per block, the information will be critical info-this means info which the participant has chosen, and therefore has knowledge about. This is possible, because four stimuli will be presented to participants in the form of the lists, and they will be allowed to choose one from each. In the blocks, two of these four will feature in every trial, alongside irrelevant stimuli (see below).

Trial Structure
T1 Berlin
T2 Madrid
T3 London
T4 Venice

IR 1 Florence
IR 2 Prague
IR 3 Vienna
IR 4 Salzburg
IR 5 Lisbon
IR 6 Brussels
IR 7 Helsinki
IR 8 Zurich

Cites Block Example
Trial 1 T1 T2 IR1, IR2, IR3 and IR4
Trial 2 T1-T3 IR5, IR6, IR7 and IR8
Trial 3 T1-T4
Trial 4 T2-T3
Trial 5 T2-T4
Trial 6 T3-T4
Thus, if you chose 1, it would appear 3 times. If you chose, 2 it would appear 3 times, if chose 3 ditto
So if I chose Berlin (T1), I would see it three times, thus 3/6 trials would be critical.

So for each block, there will be six trials in each.
In each trial, six stimuli (words) will be presented around a fixation cross. These will be left there until a button press is initiated. The screen will then flip to the next set of six stimuli, until the block ends.

Here is my code.

from psychopy import visual, core, event #import some libraries from PsychoPy
import psychopy.event
import os
from psychopy import data
from random import shuffle
import random, copy

#
expName = 'CIT_Experiment'
thisPath = os.path.split(__file__)[0]
os.chdir(thisPath)


expInfo = {}

expInfo['seqLength'] = 6
expInfo['date'] = data.getDateStr()  # add a simple timestamp

#IMPORTANT NEED TO CHANGE INFO FOR EACH PARTICIPANT
expInfo['participant'] = 'p18 f 22 '


filename = 'data/%s_%s_%s' %(expInfo['participant'], expName, expInfo['date'])
##create psychopy experiment handler
thisExp = data.ExperimentHandler(version='',
    extraInfo=expInfo, 
    savePickle=True, saveWideText=True,
    dataFileName=filename)
    

print('Created EXPinfo')

mywin = visual.Window([1920,1080], monitor="testMonitor", units="deg")

#lists of stimuli
#Practice Round
Target = visual.TextStim(mywin, text = "text default")
text_stim_list = [] # a list to hold them cities not used in the main exp!
Practice_Stim_text = ["Montreal", "Melbourne", "Boston", "Havana", "Toronto", "Tripoli"] # their content


#This section creates the trials

Matrix = [[0 for x in xrange(6)] for x in xrange(6)]

Matrix[0][0] = 1
Matrix[0][1] = 2
Matrix[0][2] = 3
Matrix[0][3] = 4
Matrix[0][4] = 5
Matrix[0][5] = 6

Matrix[1][0] = 1
Matrix[1][1] = 3
Matrix[1][2] = 8
Matrix[1][3] = 9
Matrix[1][4] = 5
Matrix[1][5] = 10

Matrix[2][0] = 1
Matrix[2][1] = 4
Matrix[2][2] = 8
Matrix[2][3] = 10
Matrix[2][4] = 4
Matrix[2][5] = 9

Matrix[3][0] = 1
Matrix[3][1] = 11
Matrix[3][2] = 8
Matrix[3][3] = 10
Matrix[3][4] = 4
Matrix[3][5] = 9

Matrix[4][0] = 1
Matrix[4][1] = 7
Matrix[4][2] = 8
Matrix[4][3] = 9
Matrix[4][4] = 5
Matrix[4][5] = 10

Matrix[5][0] = 1
Matrix[5][1] = 4
Matrix[5][2] = 3
Matrix[5][3] = 9
Matrix[5][4] = 5
Matrix[5][5] = 10

#Thise section Loads into trial handler
print('Created trials')
trialsList = []

#create a window
mywin = visual.Window([1920,1080], monitor="testMonitor", units="deg")
mywin.update()

Target = visual.TextStim(mywin, text = "text default")

fixation = visual.GratingStim(mywin, tex=None, mask='raisedCos', size=20, units='pix')

responseClock = core.Clock()

#Add in any pre-instructions here
#Initial message to participants about the study 
message1 = visual.TextStim(mywin, text = "You have been captured by the plotters. As a test to see if you have information regarding the event, an on screen test will be adminstered. Press Spacebar when ready")
message1.draw()
mywin.update()


#this will wait for a button press confirmation from p's to continue
response = event.waitKeys(keyList = ['space',], timeStamped = True)



for trial in range(6):
    thisTrial = {}
    for i in range(6):
        
        id = Matrix[trial][i]
        
        if(id ==1):
            text = 'Berlin'
        elif(id == 2):
            text = 'Paris'
        elif(id == 3):
            text = 'London'
        elif(id == 4):
            text = 'Budapest'
        elif(id == 5):
            text = 'Vienna'
        elif(id == 6):
            text = 'Athens'
        elif(id == 7):
            text = 'Brussels'
        elif(id == 8):
            text = 'Stockholm'
        elif(id == 9):
            text = 'Istanbul'
        elif(id == 10):
            text = 'Warsaw'
        elif(id == 11):
            text = 'Madrid'
        elif(id == 12):
            text = 'Helsinki'
        else:
            text = id
        
        thisTrial[i] = text
    trialsList.append(thisTrial)
    
    print('SavedTrials')


    positions = [
     (-10, 10),
     (10, 10),
     (-10, -10),
     (10, -10),
     (-1, -10),
     (1, 10),
     ]


    #This section displays and runs experiment

    trials = data.TrialHandler(trialList=trialsList, nReps=1,
        method='random', 
        extraInfo=expInfo, name='trials')
    thisExp.addLoop(trials)






    #Do the trials
    print('DoingTrials')

    for i in range(6):
        # Prepare stimulus
        fixation.draw()
        # Show it 
        random.shuffle (positions)
        print (positions)
        Target.pos = positions[i]
        Target.text = thisTrial[i]
        print (Target.text)


        Target.draw()
        
    mywin.flip()
    responseClock.reset()
    resp = event.waitKeys('q''p')
    if resp == ["escape"]:
        core.quit()
    trials.addData('respDetect.keys', resp)
    trials.addData('respDetect.rt', responseClock.getTime())
    mywin.flip()
        
    thisExp.nextEntry()

#Initial message to participants about the study 
message1 = visual.TextStim(mywin, text = "Our intelligence tells us a certain month has been chosen....")
message1.draw()
mywin.update()

#this will wait for a button press confirmation from p's to continue
response = event.waitKeys(keyList = ['space',], timeStamped = True)

So… my problem. I wish to randomise the trials, in order to prevent learning and order effects (i.e. participants getting an idea of what is to come next, and responding accordingly). So, I want to be able to randomise the trials of each block, so that that trials containing berlin, for example, appear randomly rather than consecutivly. In addition, I wish to randomise the position of the stimuli on the screen, in order to prevent almost the exact same problem as described previously (i.e. participants learning where the stimuli will physically appear).

One issue I am having is that the stimuli’s positions are being randomised, but more than one stimuli (word) is appearing in each position, and in in some positions, no stimuli are appearing. This is occuring, as you will notice, when I use the random.shuffle (positions) function. Any help with this would be hugely appreciated.

Nathan

This is presumably because the random.shuffle (positions) statement is within your for i in range(6): loop. If you put your random.shuffle (positions) statement outside of the loop (say after the print('DoingTrials') statement), that should fix it.

Problem solved :slight_smile: Thank you so much Damien

Nathan

Another problem I am having with the code is that, although I have the correct stimuli appearing on screen, the output file from the experiment handler is not displaying the correct information. It is stating results for cities which were not shown on screen. Here is a screenshot of the output.

So, for example, in trial 1, the following cities are displayed:
Berlin Paris Brussels Madrid Vienna Athens
However, clearly the results are showing a different story.

i think the solution may lie in how the Exp.handler is being updated. However, any help is appreciated.

Code is:

from psychopy import visual, core, event #import some libraries from PsychoPy
import psychopy.event
import os
from psychopy import data
from random import shuffle
import random, copy

#
expName = 'CIT_Experiment'
thisPath = os.path.split(__file__)[0]
os.chdir(thisPath)


expInfo = {}

expInfo['seqLength'] = 6
expInfo['date'] = data.getDateStr()  # add a simple timestamp

#IMPORTANT NEED TO CHANGE INFO FOR EACH PARTICIPANT
expInfo['participant'] = 'p18 f 22 '


filename = 'data/%s_%s_%s' %(expInfo['participant'], expName, expInfo['date'])
##create psychopy experiment handler
thisExp = data.ExperimentHandler(version='',
    extraInfo=expInfo, 
    savePickle=True, saveWideText=True,
    dataFileName=filename)
    

print('Created EXPinfo')

mywin = visual.Window([1920,1080], monitor="testMonitor", units="deg")

#lists of stimuli
#Practice Round
Target = visual.TextStim(mywin, text = "text default")
text_stim_list = [] # a list to hold them cities not used in the main exp!
Practice_Stim_text = ["Montreal", "Melbourne", "Boston", "Havana", "Toronto", "Tripoli"] # their content


#This section creates the trials

Matrix = [[0 for x in xrange(6)] for x in xrange(6)]

Matrix[0][0] = 1
Matrix[0][1] = 2
Matrix[0][2] = 5
Matrix[0][3] = 6
Matrix[0][4] = 7
Matrix[0][5] = 8

Matrix[1][0] = 1
Matrix[1][1] = 3
Matrix[1][2] = 9
Matrix[1][3] = 11
Matrix[1][4] = 7
Matrix[1][5] = 12

Matrix[2][0] = 1
Matrix[2][1] = 4
Matrix[2][2] = 9
Matrix[2][3] = 12
Matrix[2][4] = 6
Matrix[2][5] = 10

Matrix[3][0] = 2
Matrix[3][1] = 3
Matrix[3][2] = 8
Matrix[3][3] = 10
Matrix[3][4] = 5
Matrix[3][5] = 9

Matrix[4][0] = 2
Matrix[4][1] = 4
Matrix[4][2] = 8
Matrix[4][3] = 11
Matrix[4][4] = 7
Matrix[4][5] = 12

Matrix[5][0] = 3
Matrix[5][1] = 4
Matrix[5][2] = 5
Matrix[5][3] = 6
Matrix[5][4] = 11
Matrix[5][5] = 10

#Thise section Loads into trial handler
print('Created trials')
trialsList = []

#create a window
mywin = visual.Window([1920,1080], monitor="testMonitor", units="deg")
mywin.update()

Target = visual.TextStim(mywin, text = "text default")

fixation = visual.GratingStim(mywin, tex=None, mask='raisedCos', size=20, units='pix')

responseClock = core.Clock()

#Add in any pre-instructions here
#Initial message to participants about the study 
message1 = visual.TextStim(mywin, text = "You have been captured by the plotters. As a test to see if you have information regarding the event, an on screen test will be adminstered. Press Spacebar when ready")
message1.draw()
mywin.update()


#this will wait for a button press confirmation from p's to continue
response = event.waitKeys(keyList = ['space',], timeStamped = True)



for trial in range(6):
    thisTrial = {}
    for i in range(6):
        
        id = Matrix[trial][i]
        
        if(id ==1):
            text = 'Berlin'
        elif(id == 2):
            text = 'Paris'
        elif(id == 3):
            text = 'London'
        elif(id == 4):
            text = 'Budapest'
        elif(id == 5):
            text = 'Brussels'
        elif(id == 6):
            text = 'Madrid'
        elif(id == 7):
            text = 'Vienna'
        elif(id == 8):
            text = 'Athens'
        elif(id == 9):
            text = 'Stockholm'
        elif(id == 10):
            text = 'Istanbul'
        elif(id == 11):
            text = 'Helsinki'
        elif(id == 12):
            text = 'Warsaw'
        else:
            text = id
        
        thisTrial[i] = text
    trialsList.append(thisTrial)
    
    print('SavedTrials')


    positions = [
     (-10, 10),
     (10, 10),
     (-10, -10),
     (10, -10),
     (-1, -10),
     (1, 10),
     ]


    #This section displays and runs experiment

    trials = data.TrialHandler(trialList=trialsList, nReps=1,
        method='random', 
        extraInfo=expInfo, name='trials')
    thisExp.addLoop(trials)






    #Do the trials
    print('DoingTrials')
    print(positions)
    random.shuffle(positions)

    for i in range(6):
        # Prepare stimulus
        fixation.draw()
        # Show it 
        print (positions)
        Target.pos = positions[i]
        Target.text = thisTrial[i]
        #print (Target.text)


        Target.draw()
        
    mywin.flip()
    responseClock.reset()
    resp = event.waitKeys('q''p')
    if resp == ["escape"]:
        core.quit()
    trials.addData('respDetect.keys', resp)
    trials.addData('respDetect.rt', responseClock.getTime())
    mywin.flip()
        
    thisExp.nextEntry()

#Initial message to participants about the study 
message1 = visual.TextStim(mywin, text = "Our intelligence tells us a certain month has been chosen....")
message1.draw()
mywin.update()

#this will wait for a button press confirmation from p's to continue
response = event.waitKeys(keyList = ['space',], timeStamped = True)




















##################Month block#######################
#In some dimension, this block is allowing the data to be saved, not sure how probs trial handler


#This section creates the trials

Matrix = [[0 for x in xrange(6)] for x in xrange(6)]

Matrix[0][0] = 1
Matrix[0][1] = 2
Matrix[0][2] = 3
Matrix[0][3] = 4
Matrix[0][4] = 5
Matrix[0][5] = 6

Matrix[1][0] = 1
Matrix[1][1] = 3
Matrix[1][2] = 8
Matrix[1][3] = 9
Matrix[1][4] = 5
Matrix[1][5] = 10

Matrix[2][0] = 1
Matrix[2][1] = 4
Matrix[2][2] = 8
Matrix[2][3] = 10
Matrix[2][4] = 4
Matrix[2][5] = 9

Matrix[3][0] = 1
Matrix[3][1] = 11
Matrix[3][2] = 8
Matrix[3][3] = 10
Matrix[3][4] = 4
Matrix[3][5] = 9

Matrix[4][0] = 1
Matrix[4][1] = 7
Matrix[4][2] = 8
Matrix[4][3] = 9
Matrix[4][4] = 5
Matrix[4][5] = 10

Matrix[5][0] = 1
Matrix[5][1] = 7
Matrix[5][2] = 8
Matrix[5][3] = 9
Matrix[5][4] = 5
Matrix[5][5] = 10


#Thise section Loads into trial handler
#print('Created trials')
trialsList = []


for trial in range(6):
    thisTrial = {}
    for i in range(6):
        
        id = Matrix[trial][i]
        
        if(id ==1):
            text = 'January'
        elif(id == 2):
            text = 'Febuary'
        elif(id == 3):
            text = 'March'
        elif(id == 4):
            text = 'April'
        elif(id == 5):
            text = 'May'
        elif(id == 6):
            text = 'June'
        elif(id == 7):
            text = 'July'
        elif(id == 8):
            text = 'August'
        elif(id == 9):
            text = 'September'
        elif(id == 10):
            text = 'October'
        elif(id == 11):
            text = 'November'
        elif(id == 12):
            text = 'December'
        else:
            text = id
        
        thisTrial[i] = text
    trialsList.append(thisTrial)
    
print('SavedTrials')


#Do the trials
print('DoingTrials')

for trial in trials:
    for i in range(6):
        # Prepare stimulus
        fixation.draw()
        # Show it 
        Target.pos = positions[i]
        Target.text = text

        Target.draw()
        
    mywin.flip()
    responseClock.reset()
    resp = event.waitKeys('q''p')
    if resp == ["escape"]:
        core.quit()
    trials.addData('respDetect.keys', resp)
    trials.addData('respDetect.rt', responseClock.getTime())
    mywin.flip()
        
    thisExp.nextEntry()

Note the month block is not strictly of interest; however, I have included it as it may be the cause of the problem somehow

Nathan