Do not repeat the stimuli in two loops

Hello,
I create a task where I have 10 stimuli per category, and I have 8 categories. In my first block, I want the participant to see 5 of the 10 words in each category (Ok I managed to do it, with 8 csv list file). But I don’t want him to see the same stimulus again in the second block ("CategoryValenceNeg).
How do I do this? I tried adding a global loop that refers to the same list but it doesn’t work…
Any ideas? I’m a beginner, I succeeded with several tutorials and questions/answers to create the code for the randomization but I have no base in python… well now a little bit.


Thanks!

Hi @Cju, you could do this by using the “selected rows” field for the loops. Put a code component in front of the first loop and define two variables which contain two random non-overlapping subsets of the row indices of the conditions file. Then use those two to select the rows to be used for the first and second loop respectively.

Thanks! But… I’m really sorry I don’t understand how to do that :S

In some routine before the first of the two sub-loops, insert a code component. Then input this code:

import random

RowsLoop1 = random.sample(range(10), 5)
RowsLoop2 = list(set(range(10)) - set(RowsLoop1))

Then, use these two variables in the “selected rows” field of the respective loops. Let me know, if that works for you!

1 Like

Hi ! It partially work…
But with this code, we can see only 5 words instead of 40 like before…
Here, I have 8 categories, separated in 8 csv files.
Here is the code :

import csv
newConditions = # define an initially empty list
for fileName in [‘FrenchPosCong.csv’, ‘EnglishPosCong.csv’,‘FrenchNegCong.csv’, ‘EnglishNegCong.csv’,‘FrenchPosIncong.csv’, ‘EnglishPosIncong.csv’,‘FrenchNegIncong.csv’, ‘EnglishNegIncong.csv’]:
conditions = data.importConditions(fileName) # create a list of dictionaries
shuffle(conditions) # randomise their order
conditions = conditions[0:5] # select just ten of them
newConditions.extend(conditions)
# will end up as 20 randomly selected but balanced-for-consistency trials

header = newConditions[0].keys() # get the header labels as a list
with open(‘newConditionList1.csv’,‘w’) as file: # create a new CSV file
output = csv.DictWriter(file, fieldnames=header) # arrange to write our dictionaries to it
output.writeheader()
output.writerows(newConditions)`

I tried to change L "range(80), 40) and range(80)
but it gives me this error message :

File “/Users/Catherine/Desktop/SC-AAT_build/test_lastrun.py”, line 380, in
trialList=data.importConditions(‘newConditionList1.csv’, selection=RowsLoop1),
File “/Applications/PsychoPy 2.app/Contents/Resources/lib/python3.8/psychopy/data/utils.py”, line 463, in importConditions
trialList.append(allConds[int(ii)])
IndexError: list index out of range
################ Experiment ended with exit code 1 [pid:35667] #################

Ah sorry, I thought the categories would be presented one after the other because you were talking about 8 different csv files and you have one outer loop.

So, do I understand you correctly that participants only go through the first and the second loop once with both having 40 trials? So you basically want to take your 8 csv files, sample 5 rows out of each one for the first loop, and then sample the 5 others for the second loop?

Please try this. Not sure if it works, since I don’t have the files to test it.

import csv
import random

CSVfiles = ['FrenchPosCong.csv', 'EnglishPosCong.csv','FrenchNegCong.csv', 'EnglishNegCong.csv','FrenchPosIncong.csv', 'EnglishPosIncong.csv','FrenchNegIncong.csv', 'EnglishNegIncong.csv']

randomIndices = []

# generate indices for all csv files
for i in range(len(CSVfiles)):
    RowsLoop1 = random.sample(range(10), 5)
    RowsLoop2 = list(set(range(10)) - set(RowsLoop1))
    randomIndices.append([RowsLoop1, RowsLoop2])

# generate two files with non-overlapping subsets, 40 trials each
for j in [1, 2]:

    newConditions = [] # define an initially empty list

    for i in range(len(CSVfiles)):
        fileName = CSVfiles[i]
        conditions = data.importConditions(fileName) # create a list of dictionaries
        shuffle(conditions) # randomise their order
        conditions = conditions[randomIndices[i][j - 1]] # select just 5 of them
        newConditions.extend(conditions)
    
    header = newConditions[0].keys() # get the header labels as a list
    with open('newConditionList' + j + '.csv',‘w’) as file: # create a new CSV file
    output = csv.DictWriter(file, fieldnames=header) # arrange to write our dictionaries to it
    output.writeheader()
    output.writerows(newConditions)

This (hopefully) generates two new csv files (newConditionsList1.csv and newConditionsList2.csv), which you can then use for your two loops.

Thanks, Yes ! They only see two loops, each with 5items x 8 categories (40) from a total of 80 words.
I try to debug it…
This is the error message :
File “/Users/Catherine/Desktop/SC-AAT_build/test_lastrun.py”, line 122, in
conditions = conditions[randomIndices[i][j - 1]] # select just 5 of them
TypeError: list indices must be integers or slices, not list

Maybe this works:

conditions = [conditions[k] for k in randomIndices[i][j - 1]] 

Now I have that… I try to resolve b myself with tuto but it getting worse lol! I need a real Python training…

File “/Users/Catherine/Desktop/SC-AAT_build/test_lastrun.py”, line 126, in
with open(‘newConditionList’ + j + ‘.csv’,‘w’) as file: # create a new CSV file
TypeError: can only concatenate str (not “int”) to str

I’ve try this : with open(‘newConditionList’ + str(j) + ‘.csv’,‘w’) as file: but not working.
Thanks for your help

Looks like a proper solution! What error do you get now?

This, even if the file exists.

File “/Applications/PsychoPy 2.app/Contents/Resources/lib/python3.8/psychopy/data/utils.py”, line 291, in importConditions
raise ValueError(msg % os.path.abspath(fileName))
ValueError: Conditions file not found: /Users/Catherine/Desktop/SC-AAT_build/newConditionsList1.csv

Can you take a look inside the .py file and see if the file is created before it is needed / referenced?

The newConditionsList1 isn’t created ! I don’t know why. But the newConditionsList2 yes.
In the code I correct the missing “s” and change de ‘w’ for ‘w’.
This is my code now

import csv
import random

CSVfiles = ['FrenchPosCong.csv', 'EnglishPosCong.csv','FrenchNegCong.csv', 'EnglishNegCong.csv','FrenchPosIncong.csv', 'EnglishPosIncong.csv','FrenchNegIncong.csv', 'EnglishNegIncong.csv']

randomIndices = []


# generate indices for all csv files
for i in range(len(CSVfiles)):
    RowsLoop1 = random.sample(range(10), 5)
    RowsLoop2 = list(set(range(10)) - set(RowsLoop1))
    randomIndices.append([RowsLoop1, RowsLoop2])

# generate two files with non-overlapping subsets, 40 trials each
for j in [1,2]:

    newConditions = [] # define an initially empty list

for i in range(len(CSVfiles)):
    fileName = CSVfiles[i]
    conditions = data.importConditions(fileName) # create a list of dictionaries
    shuffle(conditions) # randomise their order
    conditions = [conditions[k] for k in randomIndices[i][j-1]]  # select just 5 of them
    newConditions.extend(conditions)
    
header = newConditions[0].keys() # get the header labels as a list
with open('newConditionsList' + str(j) + '.csv','w') as file: # create a new CSV file
    output = csv.DictWriter(file, fieldnames=header) # arrange to write our dictionaries to it
    output.writeheader()
    output.writerows(newConditions)

I think you reformatted the code slightly which causes the error: All lines starting at the second for-loop need to be indented so they are part of the first for-loop. See my original code.

Ok but this is the message error I have when I do the same code as yours, that was I try to change it but indeed maybe my solution wasn’t good either
:
File “/Users/Catherine/Desktop/SC-AAT_build/test_lastrun.py”, line 128
output = csv.DictWriter(file, fieldnames=header) # arrange to write our dictionaries to it
^
IndentationError: expected an indented block

Try it like this:

import csv
import random

CSVfiles = ['FrenchPosCong.csv', 'EnglishPosCong.csv','FrenchNegCong.csv', 'EnglishNegCong.csv','FrenchPosIncong.csv', 'EnglishPosIncong.csv','FrenchNegIncong.csv', 'EnglishNegIncong.csv']

randomIndices = []


# generate indices for all csv files
for i in range(len(CSVfiles)):
    RowsLoop1 = random.sample(range(10), 5)
    RowsLoop2 = list(set(range(10)) - set(RowsLoop1))
    randomIndices.append([RowsLoop1, RowsLoop2])

# generate two files with non-overlapping subsets, 40 trials each
for j in [1,2]:

    newConditions = [] # define an initially empty list

    for i in range(len(CSVfiles)):
        fileName = CSVfiles[i]
        conditions = data.importConditions(fileName) # create a list of dictionaries
        shuffle(conditions) # randomise their order
        conditions = [conditions[k] for k in randomIndices[i][j-1]]  # select just 5 of them
        newConditions.extend(conditions)
        
    header = newConditions[0].keys() # get the header labels as a list
    with open('newConditionsList' + str(j) + '.csv','w') as file: # create a new CSV file
        output = csv.DictWriter(file, fieldnames=header) # arrange to write our dictionaries to it
        output.writeheader()
        output.writerows(newConditions)