psychopy.org | Reference | Downloads | Github

Selecting different rows per iteration in a loop

randomization

#1

Dear users,

I have a .xlsx file with 48 links to files that I use to get stimuli within a inner loop.
Per inner loop 12 file are presented, in total the inner loop is repeated 4 times in an outer loop.

How can I (in builder) define that stimulis:

  • 1-12 are going to be presented in iteration 1,
  • 13-24 in iteration 2 etc.

I tried with selected row but I can only statically choose 1:12.

Thank you for your help

Best Vivian


Randomly selecting a subset of 5 excel rows from groups of 10 rows on each trial
#2

I can think of two ways to do this.

Split up the conditions file

Advantage: easy to understand. Disadvantage: many conditions files.

In this case, you need two loops around your routine(s). The outer loop loops over a file with four rows, each containing a conditions file (say, in a column called conditions_file. The inner loop loads these conditions files in turn (enter $conditions_file as file name). So you have five conditions files in total: (1) row 1-12, (2) row 13-24, (3) row 25-36, (4) row 37-48, (5) the names of these four conditions files.

Select rows dynamically

Advantage: only one conditions file. Disadvantage: quite complex.

  1. Create a new routine with a code component in the beginning of your loop.
  2. Under “Begin experiment” define a variable: this_loop_number = 0.
  3. Then under “Begin Routine” increment this value on each loop: this_loop_number +=1.
  4. In the loop, set “select rows” to $((this_loop_number-1)*12+1):(this_loop_number*12)
  5. Finally, add a loop around the whole thing which repeats four times to get 1:12, 13:24, 25:36, and 37:48.

Randomly selecting different parameters per iteration of a routine
#3

I wanted to check that @lindeloev’s “setting rows dynamically” solution worked (that’s how it was designed but I don’t think this is often tested). It did! :dancers:

So here’s an example experiment file showing it in action. Put these 3 files together in a folder and run the blockSubset experiment. A couple of notes:

  • the entries in the blocks file are '0:5, '5:10, '10:15 and note the ' just at the beginning of each one. That tells Excel to treat this as a string and not be clever and convert it into a date/time. For excel a string is indicated by just one ' at the beginning of the cell.
  • I set up this to run a single repeat of each trial. The trials within the blocks I made random and the blocks I made sequential (so you get 1-5 shuffled, then 5-10 shuffled etc)

blockSubset.psyexp (6.6 KB)
allConds.xlsx (28.5 KB)
blocks.xlsx (27.3 KB)


#4

Hi sorry I have a similiar issue, I just wanted to see if it would apply to my problem. I have also created a task looped from an excel file with 50 rows. I currently have it working from a place in which the participant provides a rating at each row. I was hoping to change my task (because it takes too long) to get ratings for the first 10 rows. Then to only trigger a rating for every second row for the next rows that comes through (with odd rows having the stimulus appear for two seconds then moving to the next row). Would I use a simliar method to yours here?


Sound files cannot finish playing in nested loops
#5

Probably not. In your case, you still want to run through every row in the conditions file, it’s just that on some of those trials you want to skip the rating scale. Probably the best way to do this is instead with a code snippet that decides if the rating scale will run on a given trial. The easiest way to arrange this would be to put the rating scale in its own routine. Insert a code component on that routine, and in its Begin routine tab, put some code something like this, which decides whether the routine will run, depending on the trial number (the default is that the routine will run, so you only need to determine trials where it won’t):

# am assuming your trial loop is called 'trials'. Replace with 
# your actual loop name if necessary.

# NB loops are 0-based, so trial index 9 refers to the tenth trial.
if trials.thisN > 9 and trials.thisN % 2 == 0:
    continueRoutine = False

The % operator returns the remainder after division. As 10 is even, 10 % 2 returns 0 and 11 % 2 returns 1, and so on, allowing you to flip behaviour between odd and even number trials. NB this is all zero based, so trial # 10 is actually the 11th trial, and so on.


Selecting rows per iteration in a loop, to cary out a rating
#6

Hi Michael thanks so much for your reply! I appreciate it! I tried inserting a code component and putting in

if bead_loop.thisN > 9 and bead_loop.thisN % 2 == 0:
     continueRoutine = False

I copied this into the ‘begin routine’ tab and my task continued with no syntax errors but nothing changed it ran through ratings at all 50 iterations. I also tried taking this same code and cutting it into the ‘end routine’ tab and nothing changed here either. Do I potentially need to change something in the rating component to make it recognise the code. When I open up the rating component ‘start’ is set on time(s) ‘1’, would this override the code?


#7

This will only work in latest version(s) of PsychoPy, so check that you are up-to-date. You can also put in some debugging code like this:

    if bead_loop.thisN > 9 and bead_loop.thisN % 2 == 0:
        continueRoutine = False
        print(bead_loop.thisN)

This will let you know if the if/then in the code is actually working and on what trial numbers.


#8

On updating Psychopy it works!!! Thank you so much!!! One last thing, so for the turns where ‘continueRoutine = False’ I was hoping to get the stimuli (beads) from each of those iterations to still display on the screen for 1 second (before it triggers the routine to end). At the moment it immediately triggers routines to end but I would like to get it so the iterations without ratings still have their stimulus appear for a second or so, Is this possible? I tried a few things such as

if bead_loop.thisN > 9 and bead_loop.thisN % 2 ==0 and t > 1:
      thisN.time = t
      continueRoutine = False

#I also tried this - 

while t > 1:
     thisN.time = t 
     if bead_loop.thisN > 9 and bead_loop.thisN % 2 ==0:
            continueRoutine = False

None of my attempts worked though (I also made my ‘rating’ component in this routine to only start at 1.5 seconds hoping that it would mean for the routines that are forced to end it would not have appeared yet)


#9

I would guess that the easiest thing to do is just create another separate routine that shows the stimulus for 1 second, which runs on every trial. Insert it before the routine with the rating scale.


#10

I can’t believe I didn’t think of that!! I’ve spent so long trying to figure out how to do it via loop. Thank you so so much, this has helped me a real lot!! Cheers again have a great week


#11

Hi everyone. This thread has been very helpful but I have hit a snag. My solution is similar to Jon’s, i.e. I have a separate Excel file that tells PsychoPy which rows to use (from a second Excel file) in each block. The entries of the former file are something like '0:4, '4:8, etc. These entries are in a column named $curr_block_trial_picks_training_phase, and I call this variable in a nested loop using Selected rows.

This works fine when I index the first ten rows (zero to nine). However, whenever I try indexing rows that are greater than a single digit, e.g. '0:10 instead of '0:9 I get the following error:

elif len(selection)>0:
TypeError: object of type ‘float’ has no len()

Note that this does not happen if I e.g. just type 0:10 directly into Selected rows.

What might be going on is that PsychoPy is casting numbers larger than single digits to floats, and then not knowing what to do with them. However, I have no clue how to fix it.

Help!


#12

I think actually that this thread saved my ass> https://github.com/psychopy/psychopy/issues/881


#13

3 posts were split to a new topic: Syntax error when selecting rows


#15

Hello Jon,

I am having a smiliar problem which can’t be fixed with this solution.

I have an images routine and a video routine. They both have loops individually (images picking 3 images at random from its own excel file and videos picking one video randomly from its excel file) I then have an router loop which repeats this 9 times. The problem is for the videos i only want the 1 video that is picked randomly to display once, so 9 different videos are shown. But sometimes the same video shows again. I do not want this but I cannot set rows as I only want it to select one video.

Is there a solution to this?