psychopy.org | Reference | Downloads | Github

Adaptive Staircase Question

Hello all,

I am trying to create an auditory digit span task, where participants will hear the stimulus (digits 1-9) being read out loud, and will respond accordingly. I am running PsychoPy 3 on Windows, using primarily the Builder with some Code Components in between.

The following are the constraints of the test:

  • There will be two types of assessment: forwards (FA) & backwards (BA).
  • The baseline number of stimuli per trial is 3 for FA and 2 for BA. For example, a trial with 3 stimuli would be 4 - 8 - 1 being read aloud consecutively.
  • A response is correct if responded in both digits and order of presentation. For example, a 4 - 8 - 1 response for the trial above, in that exact order (this is for FA, while for BA the correct response = 1 - 8 - 4)
  • If a correct response is given, the next trial will increase by 1 digit (e.g. the next trial will have 4 stimuli, for the trial above).
  • If an incorrect response is given, the next trial will remain with the same amount of digits.
  • If two consecutive incorrect response is given, the next trial will decrease by 1 digit.
  • There will be a total of 14 trials each for both FA & BA.
  • By default, participants run through the forward assessment first, then backwards.

The following is what I’ve done so far:

  • I have created a loop for the stimulus presentation (Stimulus_Trials looped by Stimulus_Loop, surrounded by Fixation_Block_Start & Fixation_Block_End) that is attached to an Excel conditions file (with the stimuli digits 1-9 in the corresponding rows linked to a .wav sound file, and a correct answer column corresponding to the sound file digits). This loop is in a random order (sampling without replacement from the .wav stimuli list), with the number of repeats (total stimulus per trial) dependent on the participant’s performance on the previous trial, starting with 3 on the first trial.

Here is my stimulus .xlsx file:
Stimulus.xlsx (8.4 KB)

  • Following this is a pair of routines surrounded by a loop. The first routine is to intake a keyboard response constrained by key presses 1-9, and the second routine is to display a feedback to the participants for the key pressed. The loop is there to intake the responses corresponding to the total number of stimuli for that particular trial.
  • The above works without issues, and I am able to iterate the first trial (3 stimulus loop presentation) and the response routines (able to retrieve the corresponding correct answers in the response loop)

Here is my experiment flow:
Experiment%20Flow

The problems I am facing:
1. I am having trouble creating a custom adaptive staircase that is able to handle the conditions above. Specifically, this staircase should be able to identify if the participant has entered a correct response (FA: 4 - 8 - 1 // BA: 1 - 8 - 4) for the first trial and increase the level by 1 (4 stimulus being read aloud for the next trial iteration). Conversely, if the response was incorrect, the next trial should be at the same level. Lastly, the next trial should decrease by 1 level after every 2 consecutive incorrect responses. The problem is that I do not know where I could add a custom code component to make this specific loop/adaptive staircase, and what that code should look like.

I am able to extract correct answer responses via the variable Response_Trials.corr (that compares with the variable corrAns from my Stimulus.xlsx list) from the data file output, but only for FA right now.

Here is a sample of the data file output (column AJ: Response_Trials.corr = 1 per stimulus, but the actual ‘correct answer’ must be that all Response_Trials.corr = 1 for every stimulus in that trial):

001_Auditory Digit Span Task_2019_Jun_05_1704.csv (3.9 KB)

2. This adaptive staircase should switch to BA after 14 iterations/trials of FA. I think it should continue as a separate routine/loop in the experiment flow, as the input for correct answers only accounts for FA? I believe this would be cleaner than inputting a code to repeat the routine after FA?

Here are my interleave staircase options & staircase conditions .xlsx file:
Staircase_Loop

Conditions_Staircase.xlsx (8.1 KB)

Lastly, I have attached the PsychoPy experiment file & .wav audio stimulus for reference.

Auditory Digit Span Task.psyexp (43.8 KB)

1: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/2/2e15f4715c5b1a7bf3390e7e08bed0746af33084.wav

2: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/6/6dfba389f0bd70f9d90cf42db32fb811f4ccdc75.wav

3: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/3/36affc3ed80689193486baaeff80f152722d45c6.wav

4: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/9/97a58d65117cf70633a4b3c16c39051a1c81edce.wav

5: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/3/3975981578226414f74e9aabcf0b73aa30f18c33.wav

6: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/7/7f7fb9382c868170e122ceef059c0b22ed110f4c.wav

7: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/6/6c2b15528e7491b3f8a8bbf3f88659d7ec55037b.wav

8: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/4/462a1517dccc3db75200fbea9d56744b5ef59029.wav

9: https://aws1.discourse-cdn.com/standard14/uploads/psychopy/original/2X/c/c8651194041144906115cce18398606465370491.wav

Any help would be greatly appreciated - if you could point me in right direction, or some online tutorial is building something like this.

Cheers!

D

To get the forwards and backwards conditions requires nothing more than inserting one more loop, around your current staircase loop. Connect that outer loop to a conditions file that looks like this:

direction
forwards
backwards

and set the loop to be “sequential” and with an nReps value of 1.

Your staircase loop should just be a simple one, not interleaved. It will run once for the forwards condition, and once again for the backwards condition.

If I remember the details of your code from another post, you check each response against its corresponding entry in the stimulus list. All that needs to happen is that you reverse the order of the stimulus list prior to making those comparisons in the “backwards” condition:

if Response_Trial_Loop.thisN == 0: # only do this once per trial
    if direction == 'backwards':
        # use whatever your actual list of stimuli is:
        stimulus_list.reverse()

Don’t do that reversing until after you’ve saved the list of stimuli in the data file, or things will get confusing.

Lastly, you need to tell the staircase what the result of the current trial was (correct or incorrect), so it can do its magic with setting the level for the next trial. I think this goes something like this:

Staircase_Loop.addResponse(your_trial_correct_variable_name)

Hey Michael, thanks for helping me out again!

That seems like a much cleaner solution, I have added that accordingly.

I see. I have added that, but am unsure of the settings. Right now I have a following code (for the stimulus presentation loop) that ensures the first trial repeats 3 times (for FA):

At Begin Experiment Code Component of Stimulus_Trials Routine:

Stim_Loop_N = 2

At Begin Routine Code Component of Stimulus_Trials Routine:

if Stimulus_Loop.thisN == Stim_Loop_N: 
Stimulus_Loop.finished = True 

The above routine is surrounded by a loop with the following settings:

Stim_Loop

From the other post, I maintained the Is Trials as I wanted to see what stimulus was actually presented in the data file output, as they were presented randomly.

This is my current settings for the trial staircase loop:

Staircase_Loop

1. I am unsure of these parameters. My guess is that the start value = 1 (increase level by 1 if response was correct), and am unsure about max and min value. Also, unsure of how to define the step sizes and type in this case. Lastly, the N up & N down should actually be reversed in this case, as the value/level should go up by 1 for every correct response, instead of incorrect response as defined by default by PsychoPy.

I have several questions about this:

1. I added the following code at Begin Experiment Code Component of Keyboard Response Routine:

Correct_rel_answer = 0
Correct_rel_answer_counter = 0

As well as this at the End Routine Code Component of Keyboard Response Routine:

if Response_Trials.corr == 1:
    Correct_rel_answer_counter = Correct_rel_answer_counter + 1

This is so that for every response entered, it would increase the variable Correct_rel_answer_counter by 1 for every correct response.

Next, by the end of the keyboard response loop, I added the following code at End Routine Code Component of Keyboard Response Routine to check for the actual correct response:

if Correct_rel_answer_counter == len(correct_answers):
    Correct_rel_answer = 1
else:
    Correct_rel_answer = 0

My question: How do I add a Try/Except code block to test if the previous two consecutive responses were incorrect, then decrease the next level by 1? I believe I have to check the index of the previous & previous two responses if both their Correct_rel_answer == 0. Or am I going about the staircase the wrong way?

I have added this last, but did not test this yet due to the problems above.

Cheers, D.

I don’t really understand the formatting of the code snippets you posted. Can you follow this guide, and edit your post above accordingly?

1 Like

Sorry for the confusion. I edited the formatting accordingly.

I’m not actually very familiar with the PsychoPy staircase handler, so am not the best to give advice. I guess the “level” attribute you want the staircase to control is the number of digits in your task, so the minimum would be 1 and the maximum would be 9 or whatever you think, and I guess the step size would always be 1.

As for how to handle the direction of the N up and N down, that is a bit beyond me I’m afraid.

The handling of all of this is what the staircase is supposed to provide for you, I think. If you tell it whether each trial is correct or not, it handles setting its “level” attribute for you automatically, using the parameters you specify for it. And you then use that “level” variable to control the number of digits presented on each trial.

Bump!