Change from event-related to block design

OS (e.g. Win10):
PsychoPy version (v2023.2.3):

What are you trying to achieve?:
I was setting up an experiment in psychopy in which pairs are formed between instruction (‘Visualizar’ or ‘Reavaliar’) and images (60 negative images, 30 neutral images). Note that in total I will have 90 trials, in which each image is shown once and randomly paired with one of the two instructions (‘Visualizar’ or ‘Reavaliar’).
Besides that, a neutral image will never be presented with the instruction ‘Reavaliar’.
I already have the code for this part and it’s working perfectly:

#Define lists of images and shuffle:
block_instruction = []
conditions = []
useRows = []
trialTypes = [1,1,1,2,2,2,3,3,3]

neutral = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29]
shuffle(neutral)
negative = [30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89]
shuffle(negative)

for Idx in range(10):
     shuffle(trialTypes)
     for Jdx in range(9):
          if trialTypes[Jdx] == 1:
               block_instruction.append('Reavaliar')
               useRows.append(negative.pop())
               conditions.append('Rneg')
          elif trialTypes[Jdx] == 2:
               block_instruction.append('Visualizar')
               useRows.append(negative.pop())
               conditions.append('Vneg')
          else:
               block_instruction.append('Visualizar')
               useRows.append(neutral.pop())
               conditions.append('Vneu')

For the instruction, i set the text component as $instruction[trials.thisN] and then add data via thisExp.addData(‘instruction’,instruction[trials.thisN]).

That experiment is a pseudorandomized event-related design.

What i need to do now is change the experiment to a block design, i.e., i need the instruction to appear in the beggining of a block, and then show 3 images of the same valence. I need 30 blocks of 3 images each, so in total it still gonna be 90 images.

What did you try to make it work?:
I tried to create a different list of each condition, like this:

useRows_neu = []
useRows_neg_vis = []
useRows_neg_rea = []

blockTypes = [1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3]

neutral = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29]
shuffle(neutral)
negative = [30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89]
shuffle(negative)

for Idx in range(10):
    shuffle(blockTypes)
    for Jdx in range(10):
        if blockTypes[Jdx] == 1:
            useRows_neu.append(neutral.pop())

for Idx in range(10):
    shuffle(blockTypes)
    for Jdx in range(3):
        if blockTypes[Jdx] == 2:
            useRows_neg_vis.append(negative.pop())
        
for Idx in range(10):
    shuffle(blockTypes)
    for Jdx in range(3):
        if blockTypes[Jdx] == 3:
            useRows_neg_rea.append(negative.pop())

and created a loop like this:

What specifically went wrong when you tried that?:
However, the experiment is running through all the first list, instead of showing only 3 images and going to the next condition.

Hello

I have two questions.

  1. The lists of neutral items, useRows_neu, contains 10 elements, not 3 elements, am I correct? That part of code should fail.
  2. What do you specify in your loops?

BTW, it is not neccessary to create two “different” routines for neutral and negative stimuli, rather use one routine and add a column to your result file to indicate the presented condition.

Best wishes Jens

Hello,

IMHO, the code does not do what you want. Using your code, I got the lists useRows_new, useRows_neg_vis aso, of varying lengths, but never the intended list length. Take for example

for Idx in range(10):
    shuffle(blockTypes)
    for Jdx in range(3):
        if blockTypes[Jdx] == 2:
            useRows_neg_vis.append(negative.pop())

You shuffle blockTypes 10 times. Then you check 10 times if the first 3 elements of blockTypes are 2, and if they are, you assign an element to the useRows_neg_vis list. In an extreme case, the first three elements of blockTypes can never be 2. The shuffling of blockTypes can create an order such that, in an extreme case, the first three elements are never 2. Am I missing something?

Best wishes Jens

Hi!

Please go to my other post, in which i explained better the situation:

Hello taicmac

the following code creates an index that you can use as an argument for the Selected row argument $Idx of a loop. I did not include shuffle-commands to simplify testing.

stimulus = "oops"
IdxList = []
Idx = []

neuIdx = list(range(0,30))
negvisIdx = list(range(30,60))
negneaIdx = list(range(60,90))
tmpIdx = [0,1,2]*10

for i in tmpIdx:
    if tmpIdx[i] == 0:
        for Jdx in range(3):
            IdxList.append(neuIdx.pop())
    elif tmpIdx[i] == 1:
        for Jdx in range(3):
            IdxList.append(negvisIdx.pop())
    elif tmpIdx[i] == 2:
        for Jdx in range(3):
            IdxList.append(negneaIdx.pop())

Idx = [str(i) for i in IdxList]

Best wishes Jens