psychopy.org | Reference | Downloads | Github

Presenting sound within a fixed time period

Hi everyone,

I’m currently making stop signal task with Psychopy, but the code does not work properly.

The stimuli are presented, but the timing is not correct, and it seems that it doesn’t get key responses accurately.

I think I haven’t got used to using loops and conditionals, but I can’t figure out what is exactly the problem in my code.

The following code is what I made to do SST:

# Start trial
    for trial in trials:
        timer.reset()
        
        # Draw fixation point
        fixation.draw()
        window.flip()
        core.wait(1.7)
        window.flip()
        
        if trial['go_stop'] == 0:
            go_stim.draw()
            time_flip = window.flip()
            key, time_key = event.waitKeys(maxWait=1.5, keyList=['space'],
                                           timeStamped=True)

            if key == 'space':
                window.flip()
                right_feedback.draw()
                window.flip()
                trials.addData('isCorrect', 1)
                trials.addData('RT', (time_key - time_flip) * 1000)
                core.wait(1.0)
            else:
                window.flip()
                tooLate_feedback.draw()
                window.flip()
                trials.addData('isCorrect', 0)
                trials.addData('RT', 'None')
                core.wait(1.0)

        else:
            while timer < 1.5:
                go_stim.draw()
                time_flip = window.flip()
                if timer > 0.6:
                    winsound.Beep(1000, 0.2)
                key, time_key = event.waitKeys(keyList=['space'],
                                               timeStemped=True)[0]

            if key == 'space':
                window.flip()
                wrong_feedback.draw()
                window.flip()
                trials.addData('isCorrect', 0)
                trials.addData('RT', (time_key - time_flip) * 1000)
                core.wait(1.0)
            else:
                window.flip()
                right_feedback.draw()
                window.flip()
                trials.addData('isCorrect', 1)
                trials.addData('RT', 'None')
                core.wait(1.0)

    #  Code for saving data here

    win.close()
    core.quit()

It will be really appreciated if anyone give me an advice on how to change the code so that the task works well.

Hi, there are a few apparent issues but you really to need to describe what the actual issues are in detail to get useful feedback (i.e. " the timing is not correct, and it seems that it doesn’t get key responses accurately." doesn’t really tell us anything useful).

But things to note:

  • timer is a clock object. It is not a number. So the result of the test while timer < 1.5: will always be False. You should get an actual number from the clock to test, like while timer.getTime() < 1.5:
  • Then in that same loop, you are using event.waitKeys(). In a time-based loop, is it more likely that you actually want event.getKeys(), to check the current state of the keyboard, rather than wait for an unspecified time?
  • Unrelated, but not sure why you win.flip() before and after drawing stimuli. This will cause a brief flicker of a blank screen (although that may be what you intend).

@Michael

Thanks for feedback.
I think all the issues you mentioned caused the problem in my code.
I’ve working on my code after the posting, and the code works much better than before

    for trial in trials:
        
        # Draw fixation point
        fixation.draw()
        window.flip()
        core.wait(1.7)
        window.flip()
        
        if trial['go_stop'] == 0:
            event.clearEvents()
            timer.reset()
            for i in range(60):
                go_stim.draw()
                window.flip()
                response = event.getKeys(keyList=['space'])
                if len(response):
                    trials.addData('RT', timer.getTime() * 1000)
                    break

            if len(response):  # If the subject responded correctly,
                window.flip()
                right_feedback.draw()
                window.flip()
                core.wait(1.0)
                window.flip()
                trials.addData('isCorrect', 1)
            else:  # If the subject didn't respond to the stmulus,
                window.flip()
                tooLate_feedback.draw()
                window.flip()
                core.wait(1.0)
                window.flip()
                trials.addData('isCorrect', 0)
                trials.addData('RT', -1)
        else:
            event.clearEvents()
            timer.reset()
            for i in range(60):
                go_stim.draw()
                window.flip()
                response = event.getKeys(keyList=['space'])
                if i == 30: 
                    winsound.Beep(1000, 300)
                if len(response):
                    trials.addData('RT', timer.getTime() * 1000)
                    break
            if len(response):
                window.flip()
                wrong_feedback.draw()
                window.flip()
                core.wait(1.0)
                window.flip()
                trials.addData('isCorrect', 0)
            else:
                window.flip()
                right_feedback.draw()
                window.flip()
                core.wait(1.0)
                window.flip()
                trials.addData('RT', -1)
                trials.addData('isCorrect', 1)

The code seems to work much better with timing based on frame, rather than clock method.
I use timer just for checking the response time.

However, the issue is that the accuracy of RT with the above code is probably not accurate, since the timer.getTime() is called after the response is initiated.

I tried to do like this:

response, time = event.getKeys(keyList=['space'], timeStamped=True)

But it returns error since (presumably) event.getKeys() method returns 'None ’ when timeStamped=True.

How can I fix this issue?

And about the window.flip(), I thought I should flip the window before a new stimulus is presented to erase the previous stimulus… that’s why the screen was flickering just like you said. Thank for that!

Your code above is fine, compared to the alternative of requesting a time stamp. They would both give basically the same thing. The issue here is that (in a common PsychoPy design pattern), you are checking for a response just once every screen refresh. This means that there will be approx. a 16.7 ms resolution to reaction times for a 60 Hz screen. This wouldn’t be any different if you requested a time stamp from the getKeys function: the time would still be the time when that function was called, not when the actual key press occurred. To get better resolution, consider running a faster display or using the more complicated ioHub functions to test the keyboard in an asynchronous manner that isn’t governed by the screen refresh rate.

A win.flip() without any .draw() functions just flips the empty buffer to the screen. Anything you draw and then flip will erase the entirety of the previous screen. So only do an isolated win.flip() if you truly just want to show a blank screen.

@Michael

I got it now.
Thank you Michael:)