Personalising Stimuli

I’m currently programming an experiment to run online that involves stimuli being personalised to each participant.

At the beginning of the task participants will rate their liking of 48 stim (h1a, h2a, h3a etc). Based on their ratings, I would like to then select 12 of these stimuli; 6 to be used in a training task, and 6 to remain “untrained”.
For the 6 stim that are used in the training task, I would also like to use 3 exemplars e.g. h1a, h1b, h1c, h2a, h2b…

So far I’ve not been able to find anyone who has used specific stimuli for each participant and I’m struggling to get started.

If anyone could point me towards anyone who may have done this I’d be very grateful.

Hi @jemmasedgmond,

I think what you’re trying to do can be achieved using a Code component, what you’d need to do is add something in the Begin Routine tab to define the names of possible images. Are your images names according to a scheme? You could do something like this:

imgs = []
for _ in range(12): # Repeating 12 times...
   n = random.randint(0, 10) # Replace this bit with whatever method you like of choosing the stimulus
   imgs += ['h' + str(n) + 'a.png']  # Take that number and turn it into a filename according to your naming scheme

To choose 12 random numbers, then make each into a filename. You would then set the Image property of each of your 12 stimuli to equal the corresponding value of imgs, you could do this manually or string them into a list and go through it with a for loop.

This will take some tweaking to work it to your specific design but the basic principles should be the same!

Thanks for the response @TParsons

Yes, the images are labelled based on whether they’re healthy or unhealthy;
h1a, h2a, un1a, un2a etc
And then the additional exemplars are labelled b and c.

So would I put this code in the routine where participants are making the ratings, or in the next routine where I want to select the specific stimuli?
Apologies, I’ve only worked with builder up until now.

I would put the code after they’ve made the ratings, so that their ratings are available to you to do the image selection, but before the stimuli are loaded in to be presented. So at the end of the rating routine or the beginning of the next one.

Brilliant thanks; I’ll have a play around!

Hi @TParsons

Finally managed to get back to programming and I just wanted to check I’ve interpreted this correctly.

In order to select the stimuli that have been rated (only the ‘a’ stim are rated) I’ve done the following:

imgs = []
for _ in range(12):
n = random.randint(-90, -10)
imgs += [‘h1a.jpg’]
imgs += [‘h2a.jpg’]
imgs += [‘h3a.jpg’]
imgs += [‘h4a.jpg’]
imgs += [‘h5a.jpg’]
imgs += [‘h6a.jpg’]
imgs += [‘h7a.jpg’]
imgs += [‘h8a.jpg’]
imgs += [‘h9a.jpg’]
imgs += [‘h10a.jpg’]
imgs += [‘h11a.jpg’]
imgs += [‘h12a.jpg’]

imgs = []
for _ in range(12):
n = random.randint(10, 90)
imgs += [‘u1a.jpg’]
imgs += [‘u2a.jpg’]
imgs += [‘u3a.jpg’]
imgs += [‘u4a.jpg’]
imgs += [‘u5a.jpg’]
imgs += [‘u6a.jpg’]
imgs += [‘u7a.jpg’]
imgs += [‘u8a.jpg’]
imgs += [‘u9a.jpg’]
imgs += [‘u10a.jpg’]
imgs += [‘u11a.jpg’]
imgs += [‘u12a.jpg’]

I’m just a bit confused about where I state how many of these images I want to use, and at what point the corresponding exemplars are also selected.

Apologies if I’ve misunderstood.

Ah, so what you’re doing there is creating a list of all 12 of those stimuli, when what you need is to construct the filenames using n. So:

hImgs += ['h' + str(n) + 'a.jpg']

and:

uImgs += ['u' + str(n) + 'a.jpg']

So if n was, for example, 13, then the string made would be:

'u13a.jpg'

Doing for _ in range(12): means that it will do this 12 times, making a list of 12 strings, made using random numbers between the values you supplied to random.randint() (so -90 to -10 in one and 10 to 90 in the other, from what you’ve sent).

To assign them, make a list of the names of the components for each image, and do something like:

for i in range(12):
    uStimComponents[i].Image = uImg[i]
for i in range(12:
    hStimComponents[i].Image = hImg[i]

Does this make more sense?

The first part does - thank you!

The second part I’m still a bit confused about sorry. When you say make a list of the components are you referring to the image parameters that I’d usually set in the image properties, or do you mean this is where I would specify how many images I want and where I’d also specify the related exemplars?

Oh no I mean a list of the components themselves!

PsychoPy components are what’s called an object - if you put this in a list, rather than copying its value, it creates what’s called a handle to that object. For an example of the difference:

x = 1
y = 2
z = [1,2]

This is not an object, so if I change one of the values in z, it would not affect the values of x or y. They are stored in the list as values, not handles. Whereas, if I did:

x = psychopy.ImageStim()
y = psychopy.ImageStim()
z = [x, y]

and then did something like this:

z[0].Image = 'image.png'

That would change the Image property of x, as x and y here are objects, so they’re stored n z as handles.

When you define a component in Builder view, PsychoPy automatically does all the object definition for you, creating an object with the same name as what you named the component in Builder. So, for example, if you named the u stimuli uStimComp1 to uStimComp12 in Builder, then you would make a list like this:

uStimComponents = [uStimComp1,
                   uStimComp2,
                   uStimComp3,
                   uStimComp4,
                   uStimComp5,
                   uStimComp6,
                   uStimComp7,
                   uStimComp8,
                   uStimComp9,
                   uStimComp10,
                   uStimComp11,
                   uStimComp12
]

Meaning that you can cycle through and set the .Image property of each component using a for loop, as I did above. Does this make more sense?