How to randomize blocks in OpenSesame (a solution not a question)
Hello everyone,
I've had this problem where I wanted to randomize blocks of trials (i.e., randomize the presentation of the blocks, not the trials within a block). After some researching, I found Sebastian's youtube video on how to counterbalance blocks, and I found that extremely useful. However, if you would like to purely randomize blocks for each participant, I came up with a solution that I think anyone can do fairly simply. I am not a programmer, so if anyone sees something wrong or how to do this more simply, let me know!
1) The first step is to create an inline code at the beginning of the experiment (see the picture in step 2 to figure out where to place it. Mine is called "new_inline_script_3"):
from random import shuffle
#create a list of the number of blocks that you need. Always start at 0. Here I have eight blocks.
block_list = [0, 1, 2, 3, 4, 5, 6, 7]
#randomize the list that you just made
shuffle(block_list)
#create variables that will be used to help randomize later in your MainSequence. The number of variables depends on the number of blocks you have in your experiment (and should correspond to how many are in the block_list). So if you have only 3 blocks, you would use b0, b1 and b2.
b0 = block_list[0]
b1 = block_list[1]
b2 = block_list[2]
b3 = block_list[3]
b4 = block_list[4]
b5 = block_list[5]
b6 = block_list[6]
b7 = block_list[7]
#Make these variables part of the experiment
exp.set('b0',b0)
exp.set('b1',b1)
exp.set('b2',b2)
exp.set('b3',b3)
exp.set('b4',b4)
exp.set('b5',b5)
exp.set('b6',b6)
exp.set('b7',b7)
2) Next set up your experiment hierarchically to include a Main Loop and Main Sequence. Call them MainLoop and MainSequence (if you call them something else, you will have to change the 'count_MainSequence' variable in step 4 to whatever you call your "MainSequence" sequence). Add the blocks within the Main Sequence.
3) For the main loop, you need to have as many cycles as you have blocks. v3.1 is a bit different than previous versions in that you can't specify how many cycles you want through a drop down menu. But all you have to do is double click on cells in the first column to specify this.
4) Click on the your Main Sequence and then add the following to the "run if" arguments next to each block:
block1 --> =self.get('b0) == self.get('count_MainSequence')
block2 --> self.get('b1') == self.get('count_MainSequence')"
etc...
Notice that the "b" variables start with 0. So Block 1 should be associated with b0
You can do this by going into the code itself:
set flush_keyboard yes
set description "Runs a number of items in sequence"
run Block1 "=self.get('b0') == self.get('count_MainSequence')"
run Block2 "=self.get('b1') == self.get('count_MainSequence')"
run Block3 "=self.get('b2') == self.get('count_MainSequence')"
run Block4 "=self.get('b3') == self.get('count_MainSequence')"
run Block5 "=self.get('b4') == self.get('count_MainSequence')"
run Block6 "=self.get('b5') == self.get('count_MainSequence')"
run Block7 "=self.get('b6') == self.get('count_MainSequence')"
run Block8 "=self.get('b7') == self.get('count_MainSequence')"
Or you can just click on the "run if" boxes and adding the code.
That's it! Each time you run a participant, they should get a random order of each block. I hope this helps someone, and there is an easier way of doing this, let me know!
Comments
I tried this but it keeps showing me there are syntax errors in both the set flush and the set description lines.
Have you encountered this before?
How do you define the blocks as variables?
hi @dsurfingmark and everyone else reading this (maybe @Fab?:D),
I included the above (amazing) solution to randomize block presentation in my experiment. I've been looking for exactly this, so thanks a million!
Following these steps, I ran into two problems I couldn't solve so I'm looking for a hint or a way out..:
1) My 10 blocks keep being presented, which means it works (yeah!), but in a never-ending loop. How do I make it stop after the tenth and proceed to the end of the experiment? I can present an End-of-Experiment-Screen, sure, but that doesn't quite solve it.
2) Before creating the shuffled blocks list, all trials of a block were presented. Now, only one of ten blocks (a different one each time) really starts with the trials, as if the run-if statement applies only to one block? All the other blocks are simply not presented, although the spreadsheet lists for each block contains items. It's specific to the shuffled blocks as practice trials run smoothly.
I've attached my experiment in case you want to have a look and appreciate any help and idea you might have!
Best,
Christin
Hi @schuetzin ,
I couldn't run your task 'cause I don't have a parallel port and I'm using Open Sesame 4 (your program contains a style of coding frmo an earlier version that has been simplified in OS4). You can check the release notes and documentation for OS4 for more information.
Still, just looking at the structure of your task, I think that the problem lies with the fact that your main loop contains 10 rows and that your sequence contains 10 blocks. Hence, the task is going to execute the a first row from the loop, which will go through the whole sequence and so the 10 blocks, then it's gonna do it again when executing a second row from the loop etc. That explains why your block 1 gets repeated (in fact it gets repeated 10 times). You need to keep a single row in your main loop and set the number of cycles to 10.
The next problem is that your "Run if" refers to
count_main_sequence
. The problem here is that every time a row of the main loop is executed, the count for main_sequence is going to be 0 (I'm pretty sure of this but you can easily check). For that reason, only the condition to present a first block is going to be met and so no other block can possibly be presented. My recommendation is to create your own counter, set it to 0 before the main loop, then increment it at the end of the main sequence, and to rewrite your "Run if" conditions with reference to that new variable. Doing so, your variable should aquire the values 0, 1, 2, 3 etc..Combining the two solutions above should solve your problem, but againm I can't check it on my computer, so you'll have to implement these solutions yourself.
Hope this helps,
Fabrice.
hey @Fab ,
Thanks for the quick response! I'm sorry you couldn't run it, I don't have a parallel port either, only in the lab, and thus have a test mode version activated in the uploaded experiment that doesn't try to access it when running on my computer. Right, I used OS3 because in the beginning, I followed a wonderful tutorial that I could not get to work in OS4..
Adding a block_sequence loop with 10 cycles and keeping a single row in the main loop (looping through all 10 blocks once) solved it, thanks a lot! I then changed the run-if statement to refer to count_block_sequence instead et voila. Awesome. The "block_counter" I created and placed at the end of the main_sequence now proceeds through the sequences incrementally by adding 1 at the end of each sequence that had been selected from the lists index (done in step 1 in the first post):
var.count_block_sequence = var.count_block_sequence + 1
On a side note: Since I display the block number that the participant is in ("This was the 2. block" and so on) by indexing the variable in the sketchpad (This was the [show_block_sequence]. block), I have the count_block_sequence variable defined in an inline script at the start of the experiment
var.count_block_sequence = 0
and the presented number defined below that in a new variable based on the block_sequence count:
var.show_block_sequence = var.count_block_sequence + 1
The same statement goes before the inline script above ("block_counter") so that the next block number fits the block presented next.
Just posting this extra in case someone else wants to implement (visible) block randomisation starting at 1 :)
Again, thanks for your help!
Christin