Random Without Replacement (over multiple blocks)

URL of experiment: Pavlovia

Description of the problem:
Picture1

I have a conditions file consisting of 40 words (for the WNW routines), and another consisting consisting of 8 words (for the PM routines). I want the program to randomly sample from the WNW list and then terminate the loop after 5 trials (WNW routine), then randomly sample 1 trial from the PM list and then terminate (PM routine), and so forth. There are a total of 8 WNW routines and 8 PM routines, so by the end it will have gone through 40 WNW trials and 8 PM trials. The key is to randomly sample without replacement across all the lists (i.e., none of the 40 WNW trials are repeated).

I’ve gotten this to work on the Builder with the following codes:

############Python#########################
Routine_1 - Begin Experiment
all_rows = list(range(40))
shuffle(all_rows)

all_PM_rows = list(range(8))
shuffle(all_PM_rows)

WNW - Begin Experiment
Python
wnwCount = wnwCount + 1
if wnwCount >= 5:
trials.finished = 1
#####################################

And then then in the wnwTrial Loop:
Picture2

However, it won’t initialize in Pavlovia.

###########JS##########################
Routine_1 - Begin Experiment
all_rows = […Array(40).keys()];
util.shuffle(all_rows);

all_PM_rows = […Array(8).keys()];
util.shuffle(all_PM_rows);

WNW - Begin Experiment
wnwCount = (wnwCount + 1);
if ((wnwCount >= 5)) {
trials.finished = 1;
}
#####################################

And then then in the wnwTrial Loop:
Picture2

I suspect the issue is coming from the “Select Rows” column in the loop, but not sure how else to insert the specific row information. I realize there are probably more elegant ways to do this, but it generally works for our purposes. Was hoping maybe someone had a relatively quick/simple solution.

Here are some relevant discourses where I pulled the codes/procedures from:

  1. Randomization across blocks without repetition of stimuli?

  2. Exit a loop on pavlovia - #30 by Kath_K

Figured out a much more elegant solution, so thought I’d update in case anyone had the same problem. (got it from this discourse: Exit a loop on pavlovia - #30 by Kath_K)

There are two different conditions files for the wnw and PM routines. It samples 5 trials from the WNW trial, breaks out, and samples once from the PM trial, then loops back to the beginning (code2). This repeats 8 times. It samples randomly and without replacement.

################################################
Code1 JS - Begin Experiment:
// Make array for PM cues
// There are 8 stories in each file
pmArr = […Array(8).keys()];
util.shuffle(pmArr)

// make array for stimLoop
// There are 40 stimuli
stimArray = […Array(40).keys()];
util.shuffle(stimArray)

Code1 JS - Begin Routine:
// Get the next PM cue
pmRow = ;
if (blockType == 1) {
val = pmArr.pop()
}

pmRow.push(val);
pmRow.push(val);

Code2 JS - Begin Routine:
// Get 5 stim
currentArray =
for (let i=0; i<5; i++) {
if (blockType == 1) {
currentArray.push(stimArray.pop())
}
}
################################################

You may also be interested in my solution for a prospective memory experiment with multiple blocks. The experiment is set to public.

Best wishes,

Wakefield

2 Likes

Hello
To randomise the order of two blocks, I used the following code component in the begin experiment tab:
orders = [[1, 0], [0, 1]]
shuffle(orders)

Then set the reps of the block loops to: orders[0][outer_loop_name.thisN] and orders[1][outer_loop_name.thisN]

It works perfectly offline, but I get this error when running on Pavlovia TypeError: Cannot read property ‘0’ of undefined
Any idea why?
I have inserted the JS code component at the beginning of the experiment, as outlined in the crib sheet.
Thanks,
Ellen

As per my crib sheet this doesn’t work online

Thanks, do you know what equivalent I can use that will work online? To randomise the presentation of two blocks for each participant. I already have a loop called trials, so I can’t change the outer loop name to trials

Thanks,
Ellen

You don’t necessarily need to change the name of the loop, just refer to it as trials in the JavaScript. Alternatively you can use your own variable and add one to it at the end of each loop.

Thanks for helping me with this.
Using Builder, does that mean I can put trials.thisN in the reps on the inner loops? In which case I get this error: hand_block = data.TrialHandler(nReps=orders[0][trials.thisN], method=‘sequential’,
NameError: name ‘trials’ is not defined

Or do I need to keep outer_loop_name on Builder and manually adjust to trials in the JavaScript?

could you please set this to public view? Not able to see the experiment. Thanks.

Sorry, I decided to make it private once they had live data in them.

I’ll attach a couple of psyexp files here that might be helpful.

pm_ldt_v.psyexp (75.5 KB) – different valence of words in each block but non-words randomised across all blocks

pm_ldt.psyexp (86.9 KB)

Thanks @wakecarter