Ongoing (/on-line) adjusted/corrected presentation

Hi the PsychoPy/Python experts here,

I try to find similar posts here but there doesn’t seem to be anything relevant. I will really appreciate anyone who can guide me to a relevant post if it already exists.

Here is a summary of a typical trial.
Each trial starts with presentation of an image stimulus (randomly taken from the linked conditions file, no repetition). Then the participant see a chart that represents the probability of getting a reward. There are 4 variations of this probability, say 20%, 40%, 60%, 80%. The task of the participant is to make a choice out of two, e.g. either ‘yes’ or ‘no’.
For the first 20 trials in the experiment, the occurrence of each probability is the same (that is, the participant will come across each probability for the same number of time, i.e. 5 times for each probability). At the end of the 20th trial, I need some codes or procedures that compute the frequency (proportion) of the participant choosing ‘yes’ / or ‘no’. This frequency measure will determine how the variations of the ‘probability’ chart are shown to the participant from trials 21-40.
For example, if the participant opted ‘yes’ for 16 times or more out of the first 20 trials, the 20%- and 40%-probability chart will then be shown more often than the 60%- and the 80%-probability (e.g. 20%: 7 times; 40%: 7 times; 60%: 3 times; 80%: 3 times) in trials 21-40. // On the other hand, if the participant opted ‘yes’ for only 4 times or less out of the first 20 trials, the 20%- and 40%-probability chart will be shown much less than the other two charts (e.g. 20% and 40%: 3 times each; 60% and 80%: 7 times each). // If the participant’s responses are somewhere in between (4-16 times out of 20 trials), then the occurrence of the probability charts will remain equal (e.g. 5 times for each probability). At the end of the 40th trial, there will be again a frequency measure of how often the participant chose ‘yes’ / ‘no’ in the last 20 trials (i.e. trials 21-40). This ‘new’ frequency measure will determine how often each ‘probability’ chart is shown in the next 20 trials (i.e. trials 41-60).
In other words, for every 20 trials, we calculate the average performance from the participant’s responses.

So far, I have created a ‘stimulus’ routine that incorporates an image component (which is set every repeat) that presents an image stimulus in each trial (by taking a path from the linked condition file). Then, for presenting the ‘probability’ chart, I created another image component. I believe I need to amend and play with parts of the scripts related to this component in the coder view?

These are parts of the codes I think I would need.

trial_no = 0, 1, 2, 3……
resp = ‘yes’, ‘yes’, ‘no’, ‘yes’, ………

sresp = []
for i in range:
sresp.append(resp[i]) #somehow I need to keep track of the participant’s response over trials

if ((trial_no==20 | trial_no==40 | trial_no==60 | trial_no==80):
cresp=sresp[len(sresp)-20:len(sresp)] #this extracts the responses of the last 20 trials when the trial number is 20,40,60, or 80

mcresp= np.mean(cresp)

if mcresp > 0.8:
probability=[20%, 20%, 20%, 20%, 20%, 20%, 20%, 40%, 40%, 40%, 40%, 40%, 40%, 40%, 60%, 60%, 60%, 80%, 80%, 80%]
elif mcresp < 0.2:
probability=[20%, 20%, 20%, 40%, 40%, 40%, 60%, 60%, 60%, 60%, 60%, 60%, 60%, 80%, 80%, 80%, 80%, 80%, 80%, 80%]
else:
probability=[20%, 20%, 20%, 20%, 20%, 40%, 40%, 40%, 40%, 40%, 60%, 60%, 60%, 60%, 60%, 80%, 80%, 80%, 80%, 80%]

Question: However, I am not quite sure how exactly I can implement the ‘probability’ array/variables to actual presentation. What I meant is what I should do to PsychoPy so that the programme will understand for trials 1 to 20 it needs to exhaust a particular list of 20 ‘probability’ variations, then for trials 21 to 40 it will exhaust potentially another list of 20 variations, and so on.

Sorry for my lengthy post. I hope someone can shed some lights on my question or kindly give me some ideas on how to address my problem in a more elegant way?

Many thanks.
Johnny

You could use TrialHandler, with your list being what you posted:

trialList = [20]*3 + [40]*3 + [60]*7 + [80]*7 # python lets you append lists through multiplication and adding
trials = TrialHandler(trialList, 1)

for trial in trials:
    # trial will have value 20, 40, 60 or 80, so do with it what you want,
    # probably use it to index a list of filenames or whatever

Hey Jan,

Thanks so much for your quick reply and suggestion!

To be honest I am still a newbie with Python programming and I am actually struggling a bit in understanding how the TrialHandler works. (I read the relevant section on PsychoPy website as well as the coder demo).

If you don’t mind, can I clarify a few things with you?

In my case, presentation of the list of ‘probability’ is subject to change depending on the participant’s responses in previous trials. I think I would still need a ‘if-loop’ first to determine which list to be chosen for presentation?
e.g.
ListA = [20]* 3 + [40]* 3 + [60]* 7 + [80]* 7

ListB = [20]* 7 + [40]* 7 + [60]* 3 + [80]* 3
ListC = [20]* 5 + [40]* 5 + [60]* 5 + [80]* 5

if average_response < 0.2:
trialList = ListA
elif mcresp < 0.8:
trialList = ListB
else:
trialList = ListC

Then the script should follow with the TrialHandler function? Something like this:
data.TrialHandler(trialList, 1, method=‘random’)

For the actual (image) stimulus presentation bit of the ‘probability’ chart, I would still need an Image component(?) and this should be incorporated under a ‘for-loop’? That is like the ‘for trial in trials:’ you suggest?

Do you think it matters whether I set the Image Component to be constant OR change every repeat (when I am still in the Builder view)? My thought is that since I am going to modify the codes so that I can present the Images in the way I needed anyway, whichever I choose for shouldn’t matter? But, somehow the option ‘set every repeat’ seems to me that it has been designed to call stimuli from a linked external list?

Johnny

Hiya,

no problem at all!

Yes, I think you want to use an if-statement to find out what your list of trials should be, so what you wrote looks right to me.

TrialHandler is a bit confusing, but essentially, it’s a function that you can use to generate trial conditions, so when you write for trial in trials: it generates a new value on each loop iteration, drawn randomly from the list you pass initially (so trial will have either the value 20, 40, 60 or 80. What’s cool is that you can add your response data to the TrialHandler, and then use trials.saveAsText() to save everything to file.

Now, unfortunately I’ve never used the builder view of psychopy so I don’t actually know what you mean by keeping the Image Component constant.

What I would do is create an visual.ImageStim stimulus and then change the picture it shows based on trial. So something like:

stimulus = visual.ImageStim(win)
for trial in trials:
    # trial will be for example 20, so if your image is called 20.jpg, you can do:
    stimulus.image = str(trial) + '.jpg'
    stimulus.draw()
    win.flip()
    # and then do the rest of your trial...

PS: if you enclose your code in triple backticks (```) it gets displayed as code - much more readable :wink:

Hi Jan,

Just want to say thank you for your suggestions, which really helped me contemplate what I needed to do in my script.
At the end I didn’t (should say ‘couldn’t’) use the TrialHandler to present my probability stimuli, but a series of ‘simple’ arrays did the work. It’s a long story - the probability stimuli is presented in a loop within an outer loop, which somehow made things a bit complicated.
Anyway I think I’ve had a better idea of these Handlers now. Thanks again!

Johnny