[open] Psychopy Questhandler and OpenSesame
for my current experiment I want to use a staircase procedure to determine the contrast of a grating flexibly and in dependence of the trial by trial performance of the subject. For that reason I switched to the PsychoPy backend and implemented the Questhandler function (http://www.psychopy.org/api/data.html#questhandler) of PsychoPy. The function allows you to create a QUEST staircase with NTrials as the determining factor for how long the staircase has time to fine the point of subjective equality (PSE).
However, since I have 4 different conditions in which each needs its own staircase, I am experiencing some troubles. Even though everything seems to work flawless (correct values are proposed by the staircase procedure and the correct values are stored by OpenSesame), the function crashes too early. That is, although I set e.g. the Ntrials for each staircase to 10, so each staircase would accept 10 responses as input, it crashes as soon as I reach 10 trials for the whole experiment. That means that each staircase has less than 10 responses but rather around 2-3 maybe (trials and conditions are randomly picked). So for some reason it seems as if Ntrials is not accepted as input for each staircase individually and thus only used by each of them individually, but rather that Ntrials is either updated every single trial for all staircases or only exists a single time and is used by each staircase.
I asked around in the PsychoPy developers group and they could not give me a reason and argued that cant find an indication in the code why that should be a problem. Which is why they suspect that this might be an OpenSesame related problem (see this link: https://groups.google.com/forum/?fromgroups=#!topic/psychopy-users/V2IxyJEPqNo)
All staircases are defined outside the trial and block sequence (seperate sequence) in the run phase and are only executed once. I store the values after the OpenSesame response acquisition according to the PsychoPy code (seedocumentation).
Here is the code I used to create the staircases:
nTrials_high_peripheral = 750 #amount of trials in the staircase nTrials_low_peripheral = 750 nTrials_high_distributed = 750 nTrials_low_distributed = 750 high_startVal = 0.20 #prior threshold estimate or initial guess threshold high_startValSd = 0.5 #SD of starting guess threshold (be generous, more than one SD deviation causes problems) low_startVal = 0.20 low_startValSd = 0.5 pThreshold = 0.82 #desired accuracy # Note: QUEST tries to keep this value in mind and therefore to deliver the best guess at the end of this value. Less trials result thus is conservative guessing and more weight for the first trials. # Either increase the amount of trials or use SD as limitation. # Create four staircase classes, one high peripheral, low peripheral, high distributed and low distributed exp.staircase_high_peripheral = copy.deepcopy(data.QuestHandler(high_startVal, low_startValSd, pThreshold, stepType='log',gamma = 0.01, nTrials=nTrials_high_peripheral, minVal=0.0, maxVal=0.8)) exp.staircase_low_peripheral = copy.deepcopy(data.QuestHandler(low_startVal, low_startValSd, pThreshold, stepType='log',gamma = 0.01, nTrials=nTrials_low_peripheral, minVal=0.0, maxVal=0.8)) exp.staircase_high_distributed = copy.deepcopy(data.QuestHandler(high_startVal, low_startValSd, pThreshold, stepType='log',gamma = 0.01, nTrials=nTrials_high_distributed, minVal=0.0, maxVal=0.8)) exp.staircase_low_distributed = copy.deepcopy(data.QuestHandler(low_startVal, low_startValSd, pThreshold, stepType='log',gamma = 0.01, nTrials=nTrials_low_distributed, minVal=0.0, maxVal=0.8))
As you can see I also tried to deepcopy the objects because I was suspecting that they would use the very same memory. However, they are all stored at different addresses (even without deepcopy). So I figured that cannot be the issue.
The error message is always a stopIteration error which corresponds according to the questhandler documentation to an error that the maximum amount of trials for a staircase has been reached.
My initial idea was then just to trick the staircase by increasing Ntrials to number of staircases * trials per staircase. So in my example above this would be Ntrial for each staircase is 40 (120 in total if it would work correctly). Then in fact it does not crash earlier and each staircase has the amount of trials I want it to have (that is 10).
However, to me it appears than that the staircase adjusts its behavior because 'it thinks' it has now more time to estimate the correct PSE. That results in slower corrections in the proposed next() value and therefore subjects never really end at a propose Pthreshold of e.g. 82% since the values were PPs start to make more errors would be tested in e.g. the last 10 trials. So in fact it appears as if the Ntrials is interpreted correctly since the staircase adjusts testing behavior but it will be stopped nevertheless at the wrong value.
Does someone have a clue why this is not working? Could it be that for some reason OpenSesame interferes with the proper working of this function? Maybe by directly influencing Ntrials?
PS: For those who want to try it, I had to implement the wx module in OpenSesame in order to get the staircase working!
PPS: If you need more code, please do not hesitate to ask!