Randomizing and picking a specific number of trials in a larger trial pool

Hello everyone,
I have a question concerning my dot probe experiment. In this experiment, I´m using words instead of pictures as you can see in this excel sheet

Because my research focusses on the attentional bias of people with misophonia, I am using these trial-types:
neutral-neutral (Baseline)
misophonic-neutral
negative-neutral

My problem is that I`m replicating another experiment, which was programmed with Inquisit.

Because of the replication, I have to combine every word pair (12 misophonic, 12 negative and 24 neutral words). All in all I have to have 288 trials (96 misophonic-neutral, 96 negative-neutral and 96 neutral-neutral combinations).

If I pair all of my available words the number of trials doesn`t match the 288 trials (96-96-96).

Is there a way to restrict PsychoPy on a specific number of randomzied trials that need to be picked from a larger pool of trials?

And if that is possible, the randomized trials for each group (misophonic-neutral, negative-neutral and neutral-neutral) have to be represented equally in the experiment.

Thank you very much!

It’s easy to pick a random subset by ending a loop early.

However, I think what you want is independent randomisation so you don’t need to combine everything with everything in your spreadsheet. Have a look at my online demo.

1 Like

Thank you!

I looked into the independent randomization and I´m afraid the experiment Im trying to replicate is different, because Im not using the trial-type negative-misophonic.

I do have the Inquisit code, but sadly I can`t figure out a way to replicate this using PsychoPy.

/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
/ posttrialpause = 500
</defaults>

************************** stimuli *****************************

<text negativeright>
/ items = negative
/ select = noreplace
/ position = (70, 50)
/ txcolor = (0, 0, 0)
/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
</text>

<text negativeleft>
/ items = negative
/ select = noreplace
/ position = (30, 50)
/ txcolor = (0, 0, 0)
/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
</text>

<item negative>
/1="berauben"
/2="betrügen"
/3="drohen"
/4="fürchten"
/5="gefährden"
/6="klauen"
/7="schießen"
/8="schlagen"
/9="stehlen"
/10="verletzen"
/11="zerstören"
/12="zwingen"
</item>

<text neutralright>
/ items = neutral
/ select = noreplacenot (neutralleft)
/ position = (70, 50)
/ txcolor = (0, 0, 0)
/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
</text>

<text neutralleft>
/ items = neutral
/ select = noreplacenot (neutralright)
/ position = (30, 50)
/ txcolor = (0, 0, 0)
/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
</text>


<text neutralnegright>
/ items = neutralneg
/ select = noreplace 
/ position = (70, 50)
/ txcolor = (0, 0, 0)
/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
</text>

<text neutralnegleft>
/ items = neutralneg
/ select = noreplace
/ position = (30, 50)
/ txcolor = (0, 0, 0)
/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
</text>

<item neutral>
/1="ahnen" 
/2="anlegen"
/3="auftreten"
/4="bedienen"
/5="betragen"
/6="beweisen"
/7="binden"
/8="bitten"
/9="drücken"
/10="einsetzen"
/11="eintreten"
/12="erfassen"
</item>

<item neutralneg>
/1="erheben"
/2="erteilen"
/3="gehören"
/4="gelten"
/5="greifen"
/6="heben"
/7="neigen"
/8="nennen"
/9="stapeln"
/10="tragen"
/11="vermuten"
/12="weisen"
</item>

<text misophoniaright>
/ items = misophonia
/ select = noreplace
/ position = (70, 50)
/ txcolor = (0, 0, 0)
/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
</text>

<text misophonialeft>
/ items = misophonia
/ select = noreplace
/ position = (30, 50)
/ txcolor = (0, 0, 0)
/ fontstyle = ("Arial", 4%, false, false, false, false, 5, 0)
</text>

<item misophonia>
/1="abbeißen"
/2="essen"
/3="kauen"
/4="knabbern" 
/5="knirschen"
/6="knistern"
/7="schlucken"
/8="schlürfen"
/9="schmatzen"
/10="schnauben"
/11="schnaufen"
/12="trinken"
</item>

<shape probeleft>
/ shape = circle
/ size = (1%, 1%)
/ color = (200, 200, 200)
/ position = (30%, 50%)
</shape>

<shape proberight>
/ shape = circle
/ size = (1%, 1%)
/ color = (200, 200, 200)
/ position = (70%, 50%)
</shape>

<text fixation>
/ items = ("+")
</text>

<text erasefixation>
/ items = ("+")
/ txcolor = (255, 255, 255)
</text>

<shape erasewords>
/ color = (255, 255, 255)
/ size = (90%, 90%)
</shape>

*************************** Instructions *******************
<instruct>
/ nextlabel = "Drücken Sie bitte die Leertaste um weiterzukommen"
/ lastlabel = "Drücken Sie bitte die Leertaste um weiterzukommen"
/ nextkey = (" ")
/ fontstyle = ("Arial", 2%, false, false, false, false, 5, 0)
</instruct>

<page begin>
^^Im Folgenden werden wir Ihre Reaktionszeit testen. Bei jedem Durchgang wird ein Fixierkreuz (+) für 500 ms präsentiert. 
^^Bitte schauen Sie auf das Kreuz, wenn es präsentiert wird. Danach erscheinen links und rechts vom Kreuz zwei Wörter für jeweils 500 ms. 
^^Beide Wörter werden dann vom Bildschirm gelöscht und an Stelle eines der beiden Wörter erscheint ein grauer Punkt.
^^Ihre Aufgabe ist es, so schnell wie möglich auf diesen Punkt zu reagieren:
^^Wenn der Punkt auf der linken Seite erscheint, drücken Sie bitte den Buchstaben "E".
^^Wenn der Punkt auf der rechten Seite erscheint, drücken Sie bitte den Buchstaben "I".
^^Arbeiten Sie so schnell und genau wie möglich.
</page>

<page practice>
^^Sie haben jetzt Gelegenheit, das Vorgehen kurz zu üben. Bitte platzieren Sie den linken Zeigefinger auf dem Buchstaben E und den rechten Zeigefinger auf dem Buchstaben I.
^^Zur Erinnerung:
^^Wenn der Punkt auf der linken Seite erscheint, drücken Sie bitte den Buchstaben "E".
^^Wenn der Punkt auf der rechten Seite erscheint, drücken Sie bitte den Buchstaben "I".
</page>

<page test>
^^Es beginnt jetzt die eigentliche Untersuchung. Bitte platzieren Sie den linken Zeigefinger auf dem Buchstaben E und den rechten Zeigefinger auf dem Buchstaben I.
^^Zur Erinnerung:
^^Wenn der Punkt auf der linken Seite erscheint, drücken Sie bitte den Buchstaben "E".
^^Wenn der Punkt auf der rechten Seite erscheint, drücken Sie bitte den Buchstaben "I".
</page>

<page Pause>
^^Bevor die Untersuchung weitergeht, haben Sie nun die Möglichkeit, sich kurz auszuruhen.
^^Sobald Sie sich erholt haben, können Sie die Untersuchung fortführen.
</page>

<page test2>
^^Es beginnt jetzt der zweite Teil der Untersuchung. Bitte platzieren Sie den linken Zeigefinger auf dem Buchstaben E und den rechten Zeigefinger auf dem Buchstaben I.
^^Zur Erinnerung:
^^Wenn der Punkt auf der linken Seite erscheint, drücken Sie bitte den Buchstaben "E".
^^Wenn der Punkt auf der rechten Seite erscheint, drücken Sie bitte den Buchstaben "I".
</page>

<page end>
^^^Herzlichen Dank für Ihre Mitarbeit
</page>


*************************** trials **********************

<trial negneuleft>
/ correctresponse = ("e")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, negativeleft, neutralnegright; 1000=erasewords, probeleft]
</trial>

<trial negneuright>
/ correctresponse = ("i")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, negativeleft, neutralnegright; 1000=erasewords, proberight]
</trial>

<trial neunegleft>
/ correctresponse = ("e")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, neutralnegleft, negativeright; 1000=erasewords, probeleft]
</trial>

<trial neunegright>
/ correctresponse = ("i")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, neutralnegleft, negativeright; 1000=erasewords, proberight]
</trial>

<trial misoneuleft>
/ correctresponse = ("e")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, misophonialeft, neutralnegright; 1000=erasewords, probeleft]
</trial>

<trial misoneuright>
/ correctresponse = ("i")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, misophonialeft, neutralnegright; 1000=erasewords, proberight]
</trial>

<trial neumisoleft>
/ correctresponse = ("e")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, neutralnegleft, misophoniaright; 1000=erasewords, probeleft]
</trial>

<trial neumisoright>
/ correctresponse = ("i")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, neutralnegleft, misophoniaright; 1000=erasewords, proberight]
</trial>

<trial neuneuleft>
/ correctresponse = ("e")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, neutralleft, neutralright; 1000=erasewords, probeleft]
</trial>

<trial neuneuright>
/ correctresponse = ("i")
/ validresponse = ("e", "i")
/ stimulustimes = [0=fixation; 500=erasefixation, neutralleft, neutralright; 1000=erasewords, proberight]
</trial>

********************** blocks ***************************

<block practice>
/ preinstructions = (practice)
/ trials = [1-6=noreplace(neuneuleft, neuneuright)]
</block>

<block test>
/ preinstructions = (test)
/ trials = [1-144=noreplace(negneuleft, negneuright, neunegleft, neunegright, misoneuleft, misoneuright, neumisoleft, neumisoright, neuneuleft, neuneuright, neuneuleft, neuneuright)]
/ postinstructions = (Pause)
</block>

<block test2>
/ preinstructions = (test2)
/ trials = [1-144=noreplace(negneuleft, negneuright, neunegleft, neunegright, misoneuleft, misoneuright, neumisoleft, neumisoright, neuneuleft, neuneuright, neuneuleft, neuneuright)]
</block>
************************** experiment************************

<expt>
/ preinstructions = (begin)
/ blocks = [1=practice; 2=test; 3=test2]
/ postinstructions = (end)
</expt>


Is there maybe another way to replicate this experiment?
Or is it infact possible by using (a maybe altered) independent randomization?

I programmed my experiment by using the Builder and sadly I cannot translate this code into JavaScript or Python, for it to work in PsychoPy.

Thank you very much for your help! Sadly I`m very new to PsychoPy so I´m having difficulties solving problems like these by myself.

and I think it is important for me to add that I will have to run this experiment online on pavlovia

From what you’ve said, valence1 and valence2 aren’t independently randomised but there are only ten combinations (mis_neu, neu_mis, neg_neu, neu_neg and neu_neu) time two dot positions (though you might want to double the number of neu_neu trials).

You could have three shuffled word lists (one for each valence) and then .pop() words from those lists as needed for the trials.

Do your words always appear as pairs? If so, then the word lists would contain pairs instead of single words.

1 Like

Thank you very much for your answer!

I am always using word pairs so I would have to use 3 lists (excel sheets or seperate excel files) for each combination (e.g. neutral-negative in one sheet, neutral-misophonic in one sheet etc.)

Because I have to vary the side each valence appears in and the side the dot appears, a pair of two words (e.g. negative-neutral valences) would have 4 options, that have to be put in the word list:

I have 12 misophonic, 12 negative and 24 neutral words and the experiment must contain two blocks.
Each block has 144 trials (48x misophonic-neutral, 48x negative-neutral and 48x neutral-neutral).

The program therefore has to randomly pick 48 trials (rows) from each excel list with a noreplace condition.

What I basically have then are three lists, that each contain 100+ rows (because each word combination results in 4 options) and I have to randomly pick 48 of each list.

Also the randomly chosen rows (48 misophonic-neutral, negative-neutral, neutral-neutral) have to be presented in a random order (it is not possible to first present 48 of the first list, then 48 of the second list etc.)

These are the excel files I mentioned:
Neutralneg-misophonisch_Wordsheet.xlsx (26.9 KB)
Neutralneg-negativ_Wordsheet.xlsx (27.2 KB)
Neutral-Neutral_Wordsheet.xlsx (26.8 KB)

@wakecarter

Could you further explain, what you mean by that please?

The additional information, that has to be considered is this:

Sadly I think this is something I would need to enter code for. Though I have built my experiment completely by using the builder, because I do not have any knowledge when it comes to coding.

Thank you very much!

I have an idea which involves minimal coding.

Each of your spreadsheets contains 576 conditions (plus the header). If you put them all into one spreadsheet you could use the following code to select the rows. Create a code component in your first routine and add the following to Begin Experiment

rows = list(range(576))
useRows = []
shuffle(rows)
for Idx in range(48):
     useRows.append(rows[Idx])
shuffle(rows)
for Idx in range(48):
     useRows.append(rows[Idx]+576)
shuffle(rows)
for Idx in range(48):
     useRows.append(rows[Idx]+1152)

Then put $useRows in the selected rows.

N.B. I haven’t tested this.

2 Likes

@wakecarter Thank you sooo much!!! It worked!

Will this code also work when I run my experiment online? I set the code type to “both” so that it automatically translates to JS.

Also, I wanted to also use this code for the 6 test trials each participant has to do before the actual experiment starts.

The test trials only contain neutral words (Baseline).
So I used my excel-sheet with only neutral words and wanted to create a code component.

Baseline_Wordsheet.xlsx (28.4 KB)

I tried changing your code into:

rows = list(range(576))
useRows = []
shuffle(rows)
for Idx in range(6):
     useRows.append(rows[Idx])

but it did not work.

Do I have to change more of this code or does this code not apply to the method I am trying to achieve here?

Thank you!

Yes, that code should be fine online if you use Auto. Auto automatically translates, not both.

If you want to have 6 test trials in the first loop and they are in the final 6 rows of the spreadsheet then you could simply have your practice loop point to:

1728:1734

Your code selects 6 rows from the first 576 rows.

The problem is, that the 6 baseline trials have to be picked randomly from all the neutral-neutral combinations.

Therefore I have similar conditions as in the problem above, only that now I have to pick 6 trials randomly from an excel sheet with 576 neutral-neutral combinations.

In that case, in what way didn’t this work?

The experiment crashes and I get this notification in the Runner:

Generating PsychoPy script...

## Running: C:\Users\Aliki\Desktop\Master\Masterarbeit\Experiment\Dot_Probe_Miso\Dot_Probe_Task_Miso_neu_lastrun.py ##
13191.3291     EXP     Imported Baseline_Wordsheet.xlsx as conditions, 576 conditions, 9 params
13191.9691     EXP     Imported Wordsheet_Gesamt.xlsx as conditions, 1728 conditions, 8 params
13192.7115     EXP     Imported Wordsheet_Gesamt.xlsx as conditions, 1728 conditions, 8 params
13192.7116     WARNING     duplicate variable names: valence1, dp, dot_location, dotKorrekt, WortRechts, valence2, WortLinks, dotposition
13192.7144     INFO     Loaded monitor calibration from ['2021_09_05 16:08']
13193.0612     EXP     Imported Baseline_Wordsheet.xlsx as conditions, 576 conditions, 9 params
13194.3045     EXP     Imported Wordsheet_Gesamt.xlsx as conditions, 1728 conditions, 8 params
13194.8843     EXP     Imported Wordsheet_Gesamt.xlsx as conditions, 1728 conditions, 8 params
13194.8845     WARNING     duplicate variable names: valence1, dp, dot_location, dotKorrekt, WortRechts, valence2, WortLinks, dotposition
pygame 2.1.0 (SDL 2.0.16, Python 3.8.10)
Hello from the pygame community. https://www.pygame.org/contribute.html
[177, 113, 186, 25, 406, 237, 21, 389, 525, 163, 168, 26, 364, 84, 336, 448, 259, 381, 120, 515, 559, 342, 146, 415, 49, 366, 224, 338, 261, 414, 376, 60, 80, 444, 184, 279, 422, 130, 529, 263, 23, 362, 390, 307, 202, 253, 247, 57, 589, 731, 1107, 746, 1135, 1065, 682, 978, 1109, 1067, 816, 962, 1022, 1078, 799, 716, 889, 832, 762, 818, 1108, 872, 602, 843, 998, 1139, 724, 1024, 949, 812, 909, 865, 827, 624, 685, 1061, 902, 725, 898, 582, 721, 1076, 947, 1090, 742, 688, 854, 656, 1481, 1236, 1469, 1647, 1667, 1711, 1299, 1216, 1154, 1374, 1322, 1703, 1458, 1579, 1612, 1524, 1186, 1394, 1314, 1271, 1656, 1659, 1699, 1273, 1407, 1310, 1179, 1472, 1550, 1484, 1230, 1468, 1289, 1562, 1214, 1498, 1674, 1161, 1418, 1710, 1638, 1252, 1228, 1657, 1580, 1269, 1646, 1369]
Traceback (most recent call last):
576
1.5516     WARNING     We strongly recommend you activate the PTB sound engine in PsychoPy prefs as the preferred audio engine. Its timing is vastly superior. Your prefs are currently set to use ['sounddevice', 'PTB', 'pyo', 'pygame'] (in that order).
1.0359     WARNING     Monitor specification not found. Creating a temporary one...
  File "C:\Users\Aliki\Desktop\Master\Masterarbeit\Experiment\Dot_Probe_Miso\Dot_Probe_Task_Miso_neu_lastrun.py", line 487, in <module>
    trialList=data.importConditions('Baseline_Wordsheet.xlsx', selection=useRows),
  File "C:\Users\Aliki\AppData\Local\Programs\PsychoPy\lib\site-packages\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:2420] #################
13207.1074     EXP     Imported Baseline_Wordsheet.xlsx as conditions, 576 conditions, 9 params
13207.6967     EXP     Imported Wordsheet_Gesamt.xlsx as conditions, 1728 conditions, 8 params
13208.6366     EXP     Imported Wordsheet_Gesamt.xlsx as conditions, 1728 conditions, 8 params
13208.6367     WARNING     duplicate variable names: valence1, dp, dot_location, dotKorrekt, WortRechts, valence2, WortLinks, dotposition
13208.6406     INFO     Loaded monitor calibration from ['2021_09_05 16:08']

I`m not sure but I think this is the reason the experiment crashes:

IndexError: list index out of range
################# Experiment ended with exit code 1 [pid:2420] #################

Correct. How many rows does your spreadsheet have now? Have you put everything into one spreadsheet? What does your code now look like?

The code you have written me above works just fine with the actual experiment where I have 48-48-48 combinations (misophonic-neutral, negative-neutral, neutral-neutral).

Now I am talking about the practice trials, which come before the actual experiment.
In these practice trials I am using only the neutral-neutral combinations, which is why I have created a new spreadsheet with only the neutral-neutral combinations.

Baseline_Wordsheet.xlsx (28.4 KB)

The speadsheet has 576 rows (plus the header).

The code I`m using is this:

rows = list(range(576))
useRows = []
shuffle(rows)
for Idx in range(6):
     useRows.append(rows[Idx])

and I put it in “Begin Experiment”.

I also put $useRows in the selected rows.

[177, 113, 186, 25, 406, 237, 21, 389, 525, 163, 168, 26, 364, 84, 336, 448, 259, 381, 120, 515, 559, 342, 146, 415, 49, 366, 224, 338, 261, 414, 376, 60, 80, 444, 184, 279, 422, 130, 529, 263, 23, 362, 390, 307, 202, 253, 247, 57, 589, 731, 1107, 746, 1135, 1065, 682, 978, 1109, 1067, 816, 962, 1022, 1078, 799, 716, 889, 832, 762, 818, 1108, 872, 602, 843, 998, 1139, 724, 1024, 949, 812, 909, 865, 827, 624, 685, 1061, 902, 725, 898, 582, 721, 1076, 947, 1090, 742, 688, 854, 656, 1481, 1236, 1469, 1647, 1667, 1711, 1299, 1216, 1154, 1374, 1322, 1703, 1458, 1579, 1612, 1524, 1186, 1394, 1314, 1271, 1656, 1659, 1699, 1273, 1407, 1310, 1179, 1472, 1550, 1484, 1230, 1468, 1289, 1562, 1214, 1498, 1674, 1161, 1418, 1710, 1638, 1252, 1228, 1657, 1580, 1269, 1646, 1369]

This list contains numbers greater than 575.

Maybe you are setting useRows for the main trials before you start the practice trials. How about setting useRowsP for the practice and useRows for the main trials to avoid any conflicts.

1 Like

Yes! That worked! Thank you sooo much!! :blush: