Implement PsiHandler staircase within the Builder

Hey,

My experiment is simple:

  • I’ve got a set of images that can be either A or B
  • I display them during short duration of time and participants have to answer whether they saw an image type A or type B
  • Ideally, I’d like to have the psychometric function of participants before conducting some other experiments. At least, I need to know with which duration they fall under 55% of correct answers or alternatively their identification threshold so that I can use that after.

So first, I want to use a staircase, and the PsiHandler class seems very appropriate. I’ve got a routine with an image stimulus, a response keyboard element, a code element and a loop around all that with a condition file that randomly pick an image type A or type B. Here is what I’ve tried in the code element:

“Before experiment”: I calibrate my staircase

stairs = PsiHandler(
        nTrials=30, intensRange=[10,2000], alphaRange=[30,400], betaRange=[0.9,10], delta=0.5,
        intensPrecision=1, alphaPrecision, betaPrecision,
        stepType='lin', expectedMin=0.5, prior=None
    )

In “Each frame”: I use the duration of the stimulus called “optim_stim” to display it on my device. Beforehand, I give an arbitrary value to optim_stim for the first trial.

in “End routine”:

response_r = int(response_keyboard.keys == correct_response_key) 
#Basically just a variable that is 0 if the participant is incorrect and that is 1 if they are correct. Works well
stairs.addResponse(response_r)
stairs_list=list(stairs) #So here I'm creating a list to use the tuple object that is "stairs"
optim_stim = stairs_list[-1] #optim_stim is the duration of the stimulus and I want it to be the last value of the staircase tuple
print(response_r)
print(stairs_list)
print(optim_stim)

The issue is that since the very first trial of my loop, the staircase creates a tuple of 30 identical values (cf nTrials) out of one value of response (either 0 or 1). Every trial afterwards, the staircase is an empty tuple, such as:

1
[250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250]
250

And nothing more afterwards! Well it is even creating an error because my stairs_list becomes an empty list [].
The way I understand it is that it doesn’t work anymore because “job done”. I feel like there is some kind of conflict between the staircase procedure and the loop, since both are creating several trials.
My conclusion is that this PsiHandler staircase might not work within the Builder and that I should implement it directly in the code, smoothly with my loop. I do not mind letting go the Builder since my whole experiment is set but I really struggle to understand how to incorporate it within the loop.

Any help would be very much appreciated!!

Thanks,

David

I’ve also found a code that works well on GitHub but it is just to test the staircase procedure so you have to give the staircase with an array of correct or incorrect answers:

from __future__ import print_function
from psychopy.data import PsiHandler

if __name__ == '__main__':
    nTrials = 10
    intensRange = [0.01, 100]
    alphaRange = [0.01, 10]
    betaRange = [0.01, 10]
    delta = 0.01
    intensPrecision, alphaPrecision, betaPrecision = 1, 0.1, 0.1
    stepType = 'lin'
    TwoAFC = False
    prior = None

    stairs = PsiHandler(
        nTrials, intensRange, alphaRange, betaRange, delta,
        intensPrecision, alphaPrecision, betaPrecision, TwoAFC=TwoAFC,
        stepType=stepType, prior=prior
    )

    responses = [1, 1, 0, 0, 1, 1, 0, 0, 1, 1]

    for trial, intensity in enumerate(stairs):
        stairs.addResponse(responses[trial])
        print(intensity)

Output:

4.71
3.51
2.54
4.76
6.24
5.97
2.16
6.25
7.53
1.47