psychopy.org | Reference | Downloads | Github

Post trial question after key is selected

Greetings. I currently have a script that increases the transparency of an image over time and the subject is supposed to click the spacebar when the image can be seen. I have another script where I ask the subject which image they saw. However, I am having trouble implementing both in the same script. For example, I would like the transparency to change over time and as soon as they click, the post trial question appears. Any help would be amazing. Thank you!

for i in range(0, prac_num_trials):
    
    fixation_cross.draw()   # iti
    win.flip()
    core.wait(random.choice(iti_duration_list))
    x = random.choice(display_stimuli_list)  # pick a stim to display from display_stimuli_list
    present_true_stimulus = x
    present_similar_stimulus = random.choice(similar_image_list) 
    present_dissimilar_stimulus = random.choice(dissimilar_image_list) 
    mask_stimulus = grey_square_stimulus
    unveil_rate = random.choice(alpha_update_time_list)
    
    # while loop decreasing opacity over time according to the unveil_rate, 
    timer.reset()
    while timer.getTime() < unveil_rate * 12:
        
        current_time = timer.getTime()
        key = kb.getKeys()
        if 'space' in key:
            break

        if current_time < unveil_rate:
            mask_stimulus.opacity = 1
        elif current_time  >= unveil_rate and current_time < unveil_rate * 2:
            mask_stimulus.opacity = .985
        elif  current_time >= unveil_rate * 2 and current_time < unveil_rate * 3:
            mask_stimulus.opacity = .970
        elif  current_time >= unveil_rate * 3 and current_time < unveil_rate * 4:
            mask_stimulus.opacity = .955
        elif  current_time >= unveil_rate * 4 and current_time < unveil_rate * 5:
            mask_stimulus.opacity = .940        
        elif  current_time > unveil_rate * 5 and current_time < unveil_rate * 6:
            mask_stimulus.opacity = .925                
        elif  current_time > unveil_rate * 6 and current_time < unveil_rate * 7:
            mask_stimulus.opacity = .910
        elif  current_time > unveil_rate * 7 and current_time < unveil_rate * 8:
            mask_stimulus.opacity = .895
        elif  current_time > unveil_rate * 8 and current_time < unveil_rate * 9:
            mask_stimulus.opacity = .880
        elif  current_time > unveil_rate * 9 and current_time < unveil_rate * 10:
            mask_stimulus.opacity = .865
        elif  current_time > unveil_rate * 10 and current_time < unveil_rate * 11:
            mask_stimulus.opacity = .850
        elif  current_time > unveil_rate * 11 and current_time < unveil_rate * 12:
            mask_stimulus.opacity = .835
        elif  current_time > unveil_rate * 12 and current_time < unveil_rate * 13:
            mask_stimulus.opacity = .820
        
        # now just have this once:
        present_true_stimulus.draw()
        mask_stimulus.draw()         
        win.flip()

for i in range(0, num_trials):

    fixation_cross.draw()
    win.flip()
    core.wait(random.choice(iti_duration_list))
    i = random.choice(display_stimuli_list)
    present_true_stimulus = i
    present_similar_stimulus = random.choice(similar_image_list) #
    present_dissimilar_stimulus = random.choice(dissimilar_image_list) #
    mask_stimulus = grey_square_stimulus
    present_true_stimulus.draw()
    mask_stimulus.draw()
    win.flip()
    
    thisResp = None #
    while thisResp == None:
        wait_for_response = event.waitKeys()
        for key in wait_for_response:
            if key == 'space':
                
                thisResp = 1
                shuffled_post_trial_stimulus_position_list = random.sample(post_trial_stimulus_position_list, len(post_trial_stimulus_position_list))
                present_true_stimulus.size = [150,150]
                present_similar_stimulus.size = [150,150]
                present_dissimilar_stimulus.size = [150,150]
                present_true_stimulus.pos = shuffled_post_trial_stimulus_position_list[0]
                present_similar_stimulus.pos = shuffled_post_trial_stimulus_position_list[1]
                present_dissimilar_stimulus.pos = shuffled_post_trial_stimulus_position_list[2]
                mouse = event.Mouse(win=win)
                Pressed = False

                while not Pressed:
                    pattern_question_text.draw()
                    present_true_stimulus.draw()
                    present_similar_stimulus.draw()
                    present_dissimilar_stimulus.draw()
                    win.flip()

                    if mouse.isPressedIn(present_true_stimulus):
                        ratingScale = visual.RatingScale(win, choices=confidence_range,labels=labels, tickMarks=ticks)
                        while ratingScale.noResponse:
                            present_true_stimulus.draw()
                            confidence_text.draw()
                            ratingScale.draw()
                            win.flip()
                        rating = ratingScale.getRating()
                        Pressed = True
                        
                    elif mouse.isPressedIn(present_similar_stimulus):
                        ratingScale = visual.RatingScale(win, choices=confidence_range,labels=labels, tickMarks=ticks)
                        while ratingScale.noResponse:
                            present_similar_stimulus.draw()
                            confidence_text.draw()
                            ratingScale.draw()
                            win.flip()
                        rating = ratingScale.getRating()
                        Pressed = True
                        
                    elif mouse.isPressedIn(present_dissimilar_stimulus):
                        ratingScale = visual.RatingScale(win, choices=confidence_range,labels=labels, tickMarks=ticks)
                        while ratingScale.noResponse:
                            present_dissimilar_stimulus.draw()
                            confidence_text.draw()
                            ratingScale.draw()
                            win.flip()
                        rating = ratingScale.getRating()
                        Pressed = True  
                        
                        
            elif thisKey in ['q', 'escape']:
                core.quit()  # abort experiment

        event.clearEvents()

At the moment you have two for loops running in series. It looks like the first one shows the stimuli, containing within a while loop to handle changing the transparency, while the second one cycles through the responses. I guess you simply want to delete the second for line. That way, its code will be executed within the first loop, gathering a response per trial, rather than all responses in one go.

Thank you. I am having trouble placing it within the first for loop. Where do you suggest I place the second piece? Ideally, after a ‘space’ press in the first loop, I would like to implement the second part starting with the line where shuffled_post_trial_stimulus_position_list is initialized.

I have this at the moment, but after a button press, the screen quickly displays what I want it to and then goes away and the program quits

for i in range(0, prac_num_trials):
    
    fixation_cross.draw()   # iti
    win.flip()
    core.wait(random.choice(iti_duration_list))
    x = random.choice(display_stimuli_list)  # pick a stim to display from display_stimuli_list
    present_true_stimulus = x
    present_similar_stimulus = random.choice(similar_image_list) 
    present_dissimilar_stimulus = random.choice(dissimilar_image_list) 
    mask_stimulus = grey_square_stimulus
    unveil_rate = random.choice(alpha_update_time_list)
    # present_true_stimulus.draw()
    # mask_stimulus.draw()
    # win.flip()
        # while loop decreasing opacity over time according to the unveil_rate, 
    timer.reset()
    while timer.getTime() < unveil_rate * 25:
        
        current_time = timer.getTime()
        key = kb.getKeys()
        if 'space' in key:
            break


        if current_time < unveil_rate:
            mask_stimulus.opacity = 1
        elif current_time  >= unveil_rate and current_time < unveil_rate * 2:
            mask_stimulus.opacity = .985
        elif  current_time >= unveil_rate * 2 and current_time < unveil_rate * 3:
            mask_stimulus.opacity = .970
        elif  current_time >= unveil_rate * 3 and current_time < unveil_rate * 4:
            mask_stimulus.opacity = .955
        elif  current_time >= unveil_rate * 4 and current_time < unveil_rate * 5:
            mask_stimulus.opacity = .940        
        elif  current_time > unveil_rate * 5 and current_time < unveil_rate * 6:
            mask_stimulus.opacity = .925                
        elif  current_time > unveil_rate * 6 and current_time < unveil_rate * 7:
            mask_stimulus.opacity = .910
        elif  current_time > unveil_rate * 7 and current_time < unveil_rate * 8:
            mask_stimulus.opacity = .895
        elif  current_time > unveil_rate * 8 and current_time < unveil_rate * 9:
            mask_stimulus.opacity = .880
        elif  current_time > unveil_rate * 9 and current_time < unveil_rate * 10:
            mask_stimulus.opacity = .865
        elif  current_time > unveil_rate * 10 and current_time < unveil_rate * 11:
            mask_stimulus.opacity = .850
        elif  current_time > unveil_rate * 11 and current_time < unveil_rate * 12:
            mask_stimulus.opacity = .835
        elif  current_time > unveil_rate * 12 and current_time < unveil_rate * 13:
            mask_stimulus.opacity = .820

        # now just have this once:
        present_true_stimulus.draw()
        mask_stimulus.draw()         
        win.flip()

       
    shuffled_post_trial_stimulus_position_list = random.sample(post_trial_stimulus_position_list, len(post_trial_stimulus_position_list))
    present_true_stimulus.size = [150,150]
    present_similar_stimulus.size = [150,150]
    present_dissimilar_stimulus.size = [150,150]
    present_true_stimulus.pos = shuffled_post_trial_stimulus_position_list[0]
    present_similar_stimulus.pos = shuffled_post_trial_stimulus_position_list[1]
    present_dissimilar_stimulus.pos = shuffled_post_trial_stimulus_position_list[2]
    mouse = event.Mouse(win)
    Pressed = False

    while not Pressed:
        pattern_question_text.draw()
        present_true_stimulus.draw()
        present_similar_stimulus.draw()
        present_dissimilar_stimulus.draw()
        win.flip()
    
        if mouse.isPressedIn(present_true_stimulus):
            ratingScale = visual.RatingScale(win, choices=confidence_range,labels=labels, tickMarks=ticks)
            while ratingScale.noResponse:
                present_true_stimulus.draw()
                confidence_text.draw()
                ratingScale.draw()
                win.flip()
            rating = ratingScale.getRating()
            Pressed = True
            
        elif mouse.isPressedIn(present_similar_stimulus):
            ratingScale = visual.RatingScale(win, choices=confidence_range,labels=labels, tickMarks=ticks)
            while ratingScale.noResponse:
                present_similar_stimulus.draw()
                confidence_text.draw()
                ratingScale.draw()
                win.flip()
            rating = ratingScale.getRating()
            Pressed = True
            
        elif mouse.isPressedIn(present_dissimilar_stimulus):
            ratingScale = visual.RatingScale(win, choices=confidence_range,labels=labels, tickMarks=ticks)
            while ratingScale.noResponse:
                present_dissimilar_stimulus.draw()
                confidence_text.draw()
                ratingScale.draw()
                win.flip()
                rating = ratingScale.getRating()
                Pressed = True  
                
                
        elif thisKey in ['q', 'escape']:
            core.quit()

That code would make your experiment quit, but we can’t see where thisKey is set.

On a general recommendation, you should strive to reduce repetition in your code. It will make it both more readable and more maintainable. For example, you could do things much more concisely like this:

    # only define this once, preferably before the experiment even starts:
    ratingScale = visual.RatingScale(win, choices=confidence_range,labels=labels, tickMarks=ticks)

    while not Pressed:
        pattern_question_text.draw()
        present_true_stimulus.draw()
        present_similar_stimulus.draw()
        present_dissimilar_stimulus.draw()
        win.flip()

        # choose which stimulus to draw:
        for stimulus in [present_true_stimulus, present_similar_stimulus, present_dissimilar_stimulus]
            if mouse.isPressedIn(stimulus):
                stim_to_draw = stimulus

                while ratingScale.noResponse:
                    stim_to_draw.draw()
                    confidence_text.draw()
                    ratingScale.draw()
                    win.flip()
                rating = ratingScale.getRating()
                Pressed = True
                break
            

Thanks for the advice! I managed to incorporate it in the loop. One last thing if you do not mind. The post trial question involving the rating scale only happens on the first trial. I am trying to clear events, but don’t know the best way to incorporate this. Any help would be wonderful. Thank you!

Can you explain this more fully? I’m not sure from this what the actual issue is.

Essentially, the rating scale is only drawn on the first trial. Once it gets to the second trial and beyond, I click on the stimulus and it goes to the next trial instead of drawing the rating scale.

OK, we’ll need to see the full section of code again, in its current state. And please do this so we can read it properly formatted (I edited the posts above to do this):

Ok thank you. Here is what I have at the moment. The rating scale is only drawn on the first trial, but not the rest.

for i in range(0, num_trials):

    fixation_cross.draw()
    win.flip()
    core.wait(random.choice(iti_duration_list))
    select_trial_list = random.choice(list_of_all_trials) ```
    list_of_all_trials = list_of_all_trials - select_trial_list
    present_true_stimulus = select_trial_list[0]
    present_similar_stimulus = select_trial_list[1]
    present_dissimilar_stimulus = select_trial_list[2]
    unveil_rate = select_trial_list[3]
    mask_stimulus = grey_square_stimulus
    
    timer.reset()
    #while timer.getTime() < unveil_rate * 25:
    while timer.getTime() > 0:
        current_time = timer.getTime()
        key = kb.getKeys()
        if 'space' in key:
            break
        if current_time < unveil_rate:
            mask_stimulus.opacity = 1
        elif current_time  >= unveil_rate and current_time < unveil_rate * 2:
            mask_stimulus.opacity = .985
        elif  current_time >= unveil_rate * 2 and current_time < unveil_rate * 3:
            mask_stimulus.opacity = .970
        elif  current_time >= unveil_rate * 3 and current_time < unveil_rate * 4:
            mask_stimulus.opacity = .955
        elif  current_time >= unveil_rate * 4 and current_time < unveil_rate * 5:
            mask_stimulus.opacity = .940        
        elif  current_time > unveil_rate * 5 and current_time < unveil_rate * 6:
            mask_stimulus.opacity = .925                
        elif  current_time > unveil_rate * 6 and current_time < unveil_rate * 7:
            mask_stimulus.opacity = .910
        elif  current_time > unveil_rate * 7 and current_time < unveil_rate * 8:
            mask_stimulus.opacity = .895
        elif  current_time > unveil_rate * 8 and current_time < unveil_rate * 9:
            mask_stimulus.opacity = .880
        elif  current_time > unveil_rate * 9 and current_time < unveil_rate * 10:
            mask_stimulus.opacity = .865
        elif  current_time > unveil_rate * 10 and current_time < unveil_rate * 11:
            mask_stimulus.opacity = .850
        elif  current_time > unveil_rate * 11 and current_time < unveil_rate * 12:
            mask_stimulus.opacity = .835
        elif  current_time > unveil_rate * 12 and current_time < unveil_rate * 13:
            mask_stimulus.opacity = .820
        else:
            missed_trial_screen.draw()
            win.flip()
            core.wait(missed_trial_duration)
            break    

        # now just have this once:
        present_true_stimulus.draw()
        mask_stimulus.draw()         
        win.flip()
    
    shuffled_post_trial_stimulus_position_list = random.sample(post_trial_stimulus_position_list, len(post_trial_stimulus_position_list))
    present_true_stimulus.size = [150,150]
    present_similar_stimulus.size = [150,150]
    present_dissimilar_stimulus.size = [150,150]
    present_true_stimulus.pos = shuffled_post_trial_stimulus_position_list[0]
    present_similar_stimulus.pos = shuffled_post_trial_stimulus_position_list[1]
    present_dissimilar_stimulus.pos = shuffled_post_trial_stimulus_position_list[2]
    mouse = event.Mouse(win)
    Pressed = False

    while not Pressed:
        pattern_question_text.draw()
        present_true_stimulus.draw()
        present_similar_stimulus.draw()
        present_dissimilar_stimulus.draw()
        win.flip()

        # choose which stimulus to draw:
        for stimulus in [present_true_stimulus, present_similar_stimulus, present_dissimilar_stimulus]:
            if mouse.isPressedIn(stimulus):
                stim_to_draw = stimulus

                while ratingScale.noResponse:
                    stim_to_draw.draw()
                    confidence_text.draw()
                    ratingScale.draw()
                    win.flip()
                rating = ratingScale.getRating()
                Pressed = True
                break

OK, I guess that is due to this:

because once a rating has been made, it will presumably stick around from one trial to the next, and needs to be reset.

I’m not that familiar with the RatingScale class, but we generally recommend that people now use the simpler but more flexible Slider class instead:

https://www.psychopy.org/api/visual/slider.html

Note that it has a reset() method which could be called at the end or beginning of each trial (maybe the RatingScale has something similar, I don’t know).

I was able to reset it. Thanks a bunch for your help, Michael!