| Reference | Downloads | Github

Psychojs - Inner Loop pattern

In psychopy, some attributes of a loop (I’m looking primarily at selected rows right now) are checked just-in-time (conceptually every repeat, though builder treats it differently from most “set every repeat” attributes), before the loop is begun and not during initial instantiation. In psychojs, the selection indices behave similar to “set constant” as everything is added to the scheduler before running (I think? please correct me if I’m wrong!).

One common pattern for outer-loop/inner-loop is to specify a set of trial indices to use for the inner loop in each pass of the outer loop (e.g. show a bunch of condition A trials together, maybe randomizing between condition A blocks and condition B blocks). A common way I do that is to set the row indices to a variable, e.g:

Since the selection indices of TrialHandler.importConditions is only occurring in trialsLoopBegin, and running code via a component in a routine in the outer loop happens after scheduling, I’m not sure how to pass selection indices the best way. It looks like there may soon be a workaround to make trial attributes accessible with a snapshot but this also doesn’t seem quite like it fixes the problem.

Is there a recommended pattern for this in psychojs? I prefer to stay within the builder’s semantic description but would be find using a manual stopgap until we can add it.

Thanks for any suggestions @apitiot and @dvbridges ,

1 Like

Ping @apitot @dvbridges any thoughts, suggestions, questions? Thanks!

PS - @dvbridges ; Can you confirm that the solution you listed with cond.xlsx and A.xlsx in your earlier answer works in psychojs? I’m able to use a variable as a conditions file name in python, but not online, getting a <condition_filename> is not defined error (I think because of the way the loop is scheduled).

If it doesn’t work, can you think of a way to make it? Thank you!

Hi @erik.kastman, yes you can create nested loops for online studies, where the conditions files are held in a variable of the outerloop. E.g., the outer loop has a list of conditions files in a column called conditionList, and the conditionList variable can be used in the inner loop to define the list of trials for each loop iteration. Here is an example:

Thanks @dvbridges - it looks like an older version of my outer loop was getting cached somehow (possibly not clicking through it to make builder aware of a new column) so I was confusing missing variables with javascript errors; I can also confirm that specifying specific csv’s for inner loops is working.

It’s still not quite a solution to my original question of generating indices, so I’m going to leave this discussion open right now pending work on the quickly evolving psychojs, but I appreciate the example. Thank you!

Hi David,

I THINK I have the same problem as @erik.kastman.

I have an experiment that works offline. I have actually almost converted everything to JS, but I can’t get the final loop to run. My final loop (loop #4) is based on whether or not the particpant got an answer right or wrong in the very first loop. They are only presented with their wrong answers in the final loop. This is done by adding 0 (for wrong answer) to the trial number and creating a vector of incorrect trial numbers (e.g. [1, 3, 4]). That vector is called myIndices. Then under selected rows in the trials box I have $myIndices. It works perfectly in python. Online, I’m getting roughly the same thing as erik - SelectedRows is undefined - I think because it is looking for a column named myIndices in the .csv file instead of recognizing myIndices as a variable created during the experiment.

I can’t tell if your example is solving this problem. If it is, can I please have the code as I don’t understand how to fix it from your description.

If it’s not doing the same thing, is there a fix for this?

My experiment:

Thank you!

I got it to work. It dawned on me last night that the problem may not be that the online version can’t find variables that are not in the .csv, but that my variable may be recording incorrectly. Because the experiment never completed, I was never seeing how it was recorded. That was exactly the problem. I fixed the JS code for the variable and it is now working great.

@erik.kastman maybe check the code for variable you’ve put in the trials menu. I hope that helps.

1 Like

Hi @dvbridges! I am using a nested loop in an online study and am running into an issue despite implementing this solution. In my outer loop, the “conditions” dialog box is directly calling a file path to my conditions file (“html/resources/debug_levels.csv”). In this file, I have a column labelled “pancakeinstances,” and this column lists several more conditions files I want to call in my inner loop (e.g. “debug_level_1.csv,” “debug_level_2.csv”). In my inner loop, I’m calling “$pancakesinstances” in the “conditions” dialog box. However, when I run my experiment, I get the following error.

Do you have any idea what could be causing this? I tried to look at your nestloops example, but the link is broken. Interestingly, if I load a condition file directly into my inner loop, the experiment works fine, but the variable itself seems to be the issue.

Thank you so much!!

Hi, I currently seem to have the same issue as you describe (see my topic Error when importing conditions in nested loops). As your post is a few months old, did you manage to find a solution to your issue (that you would be willing to share with me)?

Hi @bianhaan! My “solution” was to get rid of the nested loops entirely - I removed the outer loop and now have my four exposure levels, four break screens, and four “ready for the next level?” screens as separate PsychoPy components. I can then directly load my condition file for each exposure level into each component.

It’s not the most elegant solution - but it works totally fine and there’s absolutely no difference on the user’s end; that is, it looks the same as if you were to program nested loops and run it in the Builder.

I took a look at your experiment and see that you have several more loops than I do, so I’m not sure if this “solution” will be applicable (or worth your time!). But on a smaller scale, it worked fine for me.

Let me know if you have any additional questions!