Dear Chris,
I hope you’re doing well. Here Jaime from the Michael Schmidt group at the University of Fribourg.
I’m interested in using multiple staircases for an experiment and noticed that MWorks includes a staircase optimizer. I was wondering if there is an existing mwell script I could review to help implement this in our experiments.
Additionally, I wanted to ask whether MWorks supports a Quest staircase or if there is a way to implement it in mworks
Thanks a lot in advance
I’ve attached a simple experiment that demonstrates how MWorks’ staircase optimizer works.
MWorks does not currently provide a QUEST staircase, but we could certainly add one. Do you have a description of how the algorithm should work? I found the documentation on PsychoPy’s QUEST staircase, so I could probably extract the algorithm from that code, but it would be easier if I had a clearly-explained procedure to implement.
Thanks for checking this one. About the algorithm:
For some of our experiments, we need to estimate the perceptual threshold at which the subject can detect a change in contrast of a visual stimulus—specifically, a square shown on the screen. The idea is to find the contrast level at which the animal can reliably detect a change, but not so high that it’s always obvious.
The basic approach is similar to a classic staircase method: we present a change in contrast (say, +20%), and observe whether the monkey detects it. If it does, we lower the contrast slightly on the next trial (e.g., to 19%); if it doesn’t, we increase it (e.g., to 21%). Over time, this back-and-forth helps us hone in on the threshold—this is where we see staircase reversals, meaning the contrast direction switches (up to down or vice versa).
In our current experiment we need multiple staircases, for that purpose I wrote the following
var staircase_min_max=[.1,3]
var staircase_step_down=.1
var staircase_step_up=.3
var list_staircase_state=[1,1,1,1,1,1,1,1,1,1,1,1]
var curr_staircase=0
var eval_staircase = 1 {
// calculate current staircase based on active params
curr_staircase=(par_side+par_iscongruent2+par_color4)
I execute the command eval_staircase=1 or =0 depending of the response of the monkey
QUEST follows a similar logic but uses a Bayesian approach, which makes the estimation much more efficient. Instead of using simple rules like “go up/down by 1%”, QUEST maintains a probability distribution (a prior) over the possible values of the threshold. It updates this distribution with each trial based on the subject’s response—whether the stimulus was detected or not.
You start by telling QUEST what kind of psychometric function you’re assuming. This includes parameters like:
The slope (how quickly the detection probability increases with contrast)
The lapse rate (to account for occasional random errors)
The guess rate (chance-level performance, e.g., 50% for a 2AFC task)
The target performance level (e.g., 75% correct), which defines what we consider “threshold”
Once that’s set, QUEST will suggest a contrast value to present. You show that to the monkey, record whether the animal detected it (1) or not (0), and feed that response back into the algorithm. Based on the updated distribution, QUEST picks a new value for the next trial. Over time, the distribution gets narrower and centers on the most likely threshold.
This runs continuously, and you can define stopping criteria however you like—number of trials, number of reversals, or when the uncertainty (posterior width) is small enough.
In practice, QUEST is usually implemented as an object that holds the internal state: the prior, the responses, and the logic to suggest the next stimulus.