Welcome!

Sign in with your CogSci, Facebook, Google, or Twitter account.

Or register to create a new account.

We'll use your information only for signing in to this forum.

Supported by

Collecting response over multiple sketchpads

SophieGSophieG Posts: 1

Hi! I've come across a problem with response collection in my experiment. I want to send a trigger at time 0 and then present the stimulus from 0-400 ms, and then a blank screen from 400-1500 ms, and to be collecting keypress responses for the entire 1500 ms. Is there a way to do this? I tried using a coroutine, but I'm sending triggers through an inline script which isn't compatible with the coroutine. If I put the inline script immediately before the coroutine, there is a 120-180 ms delay between the trigger and the stimulus onset (I'm assuming due to the program preparing the coroutine), but I need the trigger to be sent exactly at the onset of the stimulus. If I just put the blank screen's duration for 0 ms and the keypress response item after the blank screen, then any keypresses before 400 ms aren't recorded as responses. Is there a way to fix this?

Thanked by 1ohavlicek

Comments

  • sebastiaansebastiaan Posts: 2,670

    Hi Sophie,

    The easiest solution is probably to first forget about the trigger, and simply implement this with coroutines. Next, you add an inline_script that replaces the run() function of the stimulus sketchpad by a chain of functions that also calls a function that sends a trigger. The trigger will then be sent automatically directly after the sketchpad is shown.

    You can see a possible implementation of this below. Here, you would put the code to send a trigger (which you presumably already have) into the body of the send_trigger() function. You need to replace 'my_sketchpad' by the name of the relevant sketchpad in your experiment. Does that make sense?

    def chain(*functions):
    
        """Executes multiple functions"""
    
        return lambda: [f() for f in functions]
    
    
    def send_trigger():
    
        print('Sending trigger')
    
    
    # Monkey patch your sketchpad!
    items['my_sketchpad'].run = chain(items['my_sketchpad'].run, send_trigger)
    

    Cheers!
    Sebastiaan

    Thanked by 1ohavlicek

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • Curse10Curse10 Posts: 1

    Sebastiaan,

    I work with Sophie on this experiment. The only issue is that we would ideally like to have a joystick response instead of a keyboard resp., though this is not supported by the coroutines plugin.

    Could we also replace the run of the keyboard response with an inline for the joystick? Would this create an additional lag in execution?

    Thank you!
    Kirsten

  • sebastiaansebastiaan Posts: 2,670

    Hi Kirsten,

    There will be no additional lag if you incorporate an inline_script into coroutines. (It's just less user friendly.) You can see how to do this here:

    It would make a lot of sense to make more items, such as the joystick, compatible with coroutines. I'll keep that on the radar.

    Cheers,
    Sebastiaan

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • ohavlicekohavlicek Posts: 8

    Thanks, Sebastiaan!
    I wanted to accomplish something similar and after searching through the forum for some time this helped. I was thinking, these questions about various ways of collecting responses seem frequent in the forum: Would you or someone else perhaps find a bit of time and add a few sections on this to the Manual, e.g. under Collecting responses / Keyboard? (If there are more advanced (requiring coding) reasonably frequent scenarios, there could be links to the forum.)

    Some pointers in the manual would be helpful for people like me transitioning from E-Prime, where each stimulus object, like TextDisplay (Sketchpad equivalent) has Duration/Input tab, where one can specify things like independent duration of the stimulus and of response collection, allowed&correct keys, and crucially, whether the stimulus object is terminated after response is provided or waits until the specified duration elapses, or even, whether it should listen for responses even after the stimulus object is terminated and replaced by subsequent stimulus. (And related to this thread, Task Events tab allows sending triggers for onset, response and other events, that's what keeps me using E-Prime now and then, but that's another issue..)

    Hopefully all these use cases can be solved in OpenSesame via various combinations of sketchpad/feedback/sampler, keyboard/mouse response and coroutines. Maybe the section in manual could go a bit like this (maybe it's not all correct:-)) :

    Use case 1: Present stimulus for a maximum of DURATION or until response is provided, collect a response since onset of stimulus.
    Solution: Add sketchpad with a duration set to 0, add keyboard_response after it with a timeout set to DURATION.

    Use case 2: Present stimulus until correct key is pressed.
    Solution: Like Use case 1, also set sketchpad duration to 0, but in keyboard_response set timeout to "infinite" and specify the allowed (optionally also correct) response.

    Use case 3: Present stimulus for a fixed DURATION regardless of whether response was provided, collect response since onset of stimulus.
    Solution a: Create a coroutine with duration set to DURATION. Add sketchpad into the coroutine, its duration may be even zero (if I am correct?). Add keyboard_response into the coroutine, in the coroutine set its End time to DURATION, and in the keyboard_response set timeout to DURATION (right?).
    Additionally, if you want to collect response during a sequence of sketchpads (etc), you can add multiple sketchpads into the coroutine, each with duration zero, and specify their Start time as you like.

    Solution b: If you care only about what key was pressed but not the response time, you can simply (without coroutines) add a sketchpad with some fixed duration, add a keyboard_response after it, set its timeout to 0 and uncheck the Flush pending keypresses box.

    I'm just not sure, when someone presses more buttons during the presentation of the stimulus, in 3a only the first response and in 3b only the last response is recorded?

  • sebastiaansebastiaan Posts: 2,670

    @ohavlicek Thanks for thinking along! I see your point about common scenarios, and it would be convenient to present these as recipes to users in some form or another. Something along the lines of a common scenarios page, or something. Hmmm, I'll give it some thought.

    image.png 46.5K

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • ohavlicekohavlicek Posts: 8

    I am now solving a scenario, which I believe can be also pretty common, but haven't found it in the forum: Using OpenSesame with MRI. This could perhaps also have its own page in the manual.

    Problem: The scanner is sending trigger pulses (they behave as a keyboard, sending the keycode of e.g. spacebar) every TR (e.g. every 1 second) and the presentation of stimuli has to be synchronized to this (and in the scanner settings we apparently have to set a fixed number of pulses the experiment lasts). For example, a stimulus needs to be presented for 3 seconds (3 pulses), so the scanner sends 3 "spacebar" responses, but during this exact time a response to the stimulus can be provided (obviously a different one than spacebar).

    Solution?: I don't know how to do this stimulus presentation and response collection for the exact time of three pulses. But luckily the pulses come reliably, with a jitter of only maybe 1-2 ms (but it seems that compared to the timestamps recorded by OpenSesame the MRI clock runs at slightly different speed, so after ca 10 minutes the pulses come 7 ms sooner). So far I think the only way to solve this is via coroutines, like Use case 3 above: Create a keyboard_response object ("wait_for_pulse"), with Allowed response set to the MR pulse code (spacebar) and Timeout set to infinite. After this add a coroutine: Insert into it stimulus presented for 0 ms and keyboard_response listening for the response we are interested in, with Allowed responses set to some specific values (different from the MR pulse code) and Timeout set to I think a bit less than 3 seconds, like 2950 (to be sure the third pulse comes after this), and 2950 is also set as the End time of the keyboard_response in the coroutine and also as the Duration of the coroutine. Right after the coroutine add another wait_for_pulse object. (In all cases Flush pending keypresses is checked). I hope this will result in synchronized presentation onsets, fixed presentation durations and reliable response collection. Do you think this is the right way to do this?

    Ondrej

  • ohavlicekohavlicek Posts: 8

    Not sure my last solution is ok, because if I run it in window just to test it, pretty much on each trial the window title changes to "... (not responding)" for half a second, i.e., OpenSesame freezes. Maybe something isn't right with the timings I set in the coroutine and its objects, or with preparation or alternating the objects inside coroutine? I am afraid that if it freezes it will miss some synchronization pulse, which might cause trouble. Any ideas?

Sign In or Register to comment.