3 nested loops for counterbalancing task order

I am building an numerical stroop expirement. In this task the subject see’s 2 digits that differ in font size and needs to decide which is larger. In the numercial task the subject chooses the numerically larger digit(ignoring physical size), in the physicall size the subject chooses the physically larger digit (ignoring numerical size).
For each I created 2 loops, since I split the task to 3 blocks. (I hope you can see the image pasted here)

Now, I want to counterbalance the order of the tasks, so that half the participants start with the physical task, and the other half start with the numerical task.
How do I do this? Another loop over the 2 task loops? What would the condition file for this loop look like?

Thank you!

Hi Naama,

There are some posts about counterbalancing on the forum. I guess the first result I get (by @jon) is particularly useful, since he’s the inventor of PsychoPy :slight_smile:

Best, Thomas

Thank you Thomas.
I read quite a few of these posts, however I couldn’t find one that would answer my problem.
If I understand correctly, none of these enable me to randomize the order of 2 separate loops in my experiment.

Yes, the answer ultimately would be to use the block design concept. You don’t want Trial_Phys and Trial_Num you just want Trial and then let the conditions files determine whether the number or physical size is varying. See the documentation on block designs here:

Thank you! Hopefully it will work

Hi John,
I tried to this but I still have one more problem:
The numerical and size tasks have different instructions? How can I embed it here?

HI @NaamaK Did you solve this problem? I’m in the same situation/…

The instructions are just another variable in your block-level conditions file.

1 Like

I did not solve this…

Hi everyone!

I am sure this is much discussed within the PsychoPy team, and the importance / urgency of this functionality well appreciated, but I would just like to add my voice (as a newcomer to this world) to this particular issue: Block sequence control.

Despite all the other wonders of this platform, all the current approaches suggested for counterbalancing and randomisation are, erm… well, let’s just say a little ‘inelegant’. They kind of work for a limited subset of cases, but for larger and more complicated experiments - quickly become either really nasty, overly complicated or simply not do-able.

I would like to humbly suggest this should probably be the number 1 development priority for the platform.

Ie, for the case below – a way by which we can either programmatically define the sequence of appearance of Block A and block B for counterbalanced designs, or randomly alter the sequence for randomised block design.

Thanks folks for an (otherwise) amazing platform.

@jon , @Becca .


1 Like

I suspect that:

  • ISI_A is pretty much the same as ISI_B? (or possibly identical?) You should use a single routine called ISI
  • trial_A is pretty much the same as trial_B? (with different stimuli?) A single trial
  • Instructions_A is the same as _B except different text? A single block_instructs

That being the case, what you want is this design:

Then the outer loop determines the conditions file for the inner loop and also the text content for the block_instructs

We may at some point add a system to do this for you “automatically” but any pre-canned solution actually suffers when someone wants something complicated (scientists will always come up with something that doesn’t fit the design). The above solution gives you complete control

Hi @Jon!

Thanks for your response! So lovely this community (and founders) are so active and helpful.

I’m afraid this approach won’t work for me though. While the ISI’s are the same, the two blocks of the experiment (trialA and trialB here…) are utterly different.

In fact for the current experiment I am working on now I have three blocks that i would like to present in random sequence, and each block is utterly different to the others.

I have been playing around with achieving this programatically. It occurred to me while doing the 3 day intensive course (which was excellent - Becca absolutely smashed it!), that it seems odd that we ask users to use a drop down menu to define a sequence when we have the tools to programmatically do this using RNGs and tables, etc… under the hood.

So… this is my first attempt at doing so. It seems to work and is doing most of what it should BUT… I am currently stuck because I can’t seem to get (from the code of a trial routine) the iterations ($Loup.thisN) of the outer loop - which I need to set a pointer for which value I should dig out of a table that determines which block should be presented on which iteration (of the outer loop).

Hmmm… Not sure if I’m being obtuse or I there is a reason I can’t do this (scope?). I have to do some more digging, reading, fiddling around.

I’ve uploaded the experiment here: Pavlovia

(Please forgive my ugly, hacky code)




What version are you using? .thisN works in the the latest version.

You can have routines which skip using continueRoutine=False in Begin Routine to switch between two routines. You could then reuse ISI and instructions.


Yes it works for the inner loop, but I can’t get the same value from the outerloop.


Ok - thanks. Lemme play around a little more.


Interesting. It is possible that .thisN has only been fixed for inner loops, which would be a shame.

Please could you confirm whether it SHOULD work @Becca ?

Thanks so much @wakecarter. :slight_smile:

Super interested to hear the answer to this.


Ah. Wait. No.

@wakecarter , @Becca


I did not have the component set to ‘set every repeat’.

This now works fine. I can get both the iteration of the local and outer loop just fine.

Huge - apologies. I’m an idiot.


Ok. It’s done. I’ve gotten this to work.

Uploaded as Pilot to Pavlovia here: Pavlovia

This experiment selects, at random, from the complete set of possible sequences of 3 blocks.

I had to include an additional routine within the main loop, but before the Trial loops because I couldn’t seem to read the thisN value from the local loop and use it within the nReps field. Perhaps this is because the thisN value doesn’t exist yet when instantiating this object?


I am super pleased I can now do this. But… it’s complicated. It has taken me DAYS to figure out - and this is with a highly abstracted, clean little experiment that doesn’t actually do anything or have any other code present.

I now need to recreate this logic in my big experiment which has lots of code, each block has multiple routines and is waaaaay more complicated generally. This is going to be tricky.

I would really like to say, I think the ability to randomise the sequence of blocks is a super important feature of any experiment presentation platform, and would LOVE to see a neater and ideally really simple GUI-driven way of doing this.


Thanks for all your help everyone.

Yay! :slight_smile:




Sorry to reopen this discussion but it seems that I have the same problem. I would like to counterbalancing order of 4 subtasks. I had already posted a message (Concatenate in nReps) but I think I am in a wrong direction. Your solution looks like easier but I don’t understand what TheSquence refers to in your coding. Could you enlighten me? or give me some supplementary advice?
I am a beginner with coding, I think I miss some basic rules to understand what you did.

Thank you if you can help.