Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Supported by

[solved] Dyadic experiment

edited December 2013 in OpenSesame

Dear all,

I was wondering whether opensesame would let me record response times in a dyadic experiment. So I want 2 individuals, each with their own mouse, to respond to stimuli on the same screen.
Is this in any way possible?

Wouter

«1

Comments

  • edited 12:51PM

    Does it have to be a mouse? Could you assign them their own key and then create a script that accepts independent keypresses?

  • edited 12:51PM

    Well, key-presses are not really ideal because of latency issues. I would be able to get response buttons (which would delay the experiment a bit), but I would really prefer that or a mouse.

  • edited 12:51PM

    That's a fair comment, I'm not sure how you would get dual mouse input... I can see having 'my_mouse1' and 'my_mouse2', I see the problem as getting OS to recognise the two peripherals...

  • edited 12:51PM

    Hi Wouter,

    I don't think that having two seperate mouse cursors on a single PC is possible in general, and it for sure won't work with any of the OpenSesame back-ends. (You can attach multiple mice, of course, but they will simply end up controlling the same cursor.)

    Latency-wise, I'm not aware of any systematic differences between the mouse and the keyboard, although it might differ from device to device. So if you don't care about motion trajectories, I agree with Lee that a keyboard would be a good (and simple!) alternative.

    Cheers!
    Sebastiaan

  • edited 12:51PM

    And would for example 2 response boxes, or 1 response box and one mouse work?

  • edited 12:51PM

    Or for example 2 joysticks?

  • edited 12:51PM

    It should be no problem to connect multiple joysticks:

    With response boxes it depends on what type of response box you are talking about, but unless it emulates a keyboard or mouse I think it should be fine.

    Cheers!

  • edited 12:51PM

    Great! thanks!

    So would I need a specific Python script to allow me to record the response times of both joysticks to the same stimuli? Or can I somehow do that through a Opensesame button?

  • edited 12:51PM

    Yes, you would need to implement this through a script. There is a joystick plug-in for OpenSesame, but it will not allow you to use multiple joysticks. On the PyGame website you will find some example scripts:

    And of course don't hesitate to post a question here if you get stuck.

  • edited 12:51PM

    Ok, so the final decision was to use two response boxes (rather than joysticks). Do these work with a similar python script? or do I need to go about this differently?

    Cheers

  • edited 12:51PM

    Hi Wouter,

    A button box is not a standard device, like a joystick or a keyboard, so it depends on what type of button box you have. For example, the SR Box communicates via the serial port, whereas some other button boxes are really just keyboards or joysticks in a different casing. What exactly are you using?

    Cheers,
    Sebastiaan

  • edited 12:51PM

    They will be RB Series response pads:

    http://cedrus.com/responsepads/

  • edited 12:51PM

    Hi Wouter,

    Cedrus provides Python libraries, which you can use in OpenSesame. You should be able to download the Python library, copy the pyxid folder into your OpenSesame program folder, and simply use the library as illustrated in the readme.txt:

    You're not the only one interested in this btw, @Madjid posted a question about this on the Cedrus forums:

    For more information I would ask around on the Cedrus forum. I can give you some general tips, but for device-specific information you really need to ask the manufacturer.

    Cheers!
    Sebastiaan

  • edited 12:51PM

    After importing the pyxid library the python code is the code underneath.

    So I have three questions:

    1. Where should I place this code in my experiment?

    2. "The response is a python dict with the following keys:" So what is a python dict? and should I do (program) anything to collect it within a trial?

    3. "port: Device port the response was from (typically 0)". Will this work on two response boxes as well? so that it automatically saves the port the response was given on, and I would be able to distinguish responses from different participants by the port number that is saved along with their response?

    Best
    Wouter

    import pyxid

    # get a list of all attached XID devices
    devices = pyxid.get_xid_devices()
    
    dev = devices[0] # get the first device to use
    if dev.is_response_device():
        dev.reset_base_timer()
        dev.reset_rt_timer()
    
        while True:
            dev.poll_for_response()
            if dev.response_queue_size() > 0:
                response = dev.get_next_response()
                # do something with the response
    

    The response is a python dict with the following keys:

    pressed: True if the key was pressed, False if it was released
    key: Response pad key pressed by the subject
    port: Device port the response was from (typically 0)
    time: value of the Response Time timer when the key was hit/released
    
  • edited November 2013

    Hi Wouter,

    I appreciate that you want to get started as soon as possible, but you will have familiarize yourself with the basics of Python to get this working: It's not simply a matter of copy-pasting the code in the right location. You will need to create a script that initializes the button boxes at the start of the experiment, and during each trial you need to collect and save the responses. Nothing terribly difficult, but still something that you'll have to figure out yourself, because you have the device!

    There are some great tutorials available:

    Once you have a basic understanding of Python, I don't mind helping you out, as far as I can without having a device myself.

    Cheers,
    Sebastiaan

  • edited November 2013

    Hi Sebastiaan,

    thanks for the honest advice. :-)
    I''m working my way through a codecademy python introduction course (which so far has proven to be worthwile), but I thought that I might verify how my current (improved) understanding of python helps me interpreting the response box syntax.

    So, am I making sense when I'm saying:

    1. the first line of the syntax deals with importing the device, and should just be incorporated at the very beginning of the program.

    2. the second part is concerned with setting the parameters for the responses. that is: the .is_response part indicate that when a response is recorded, the timers will be reset. But it will check whether the response time is larger than zero before going on to saving a new response. This is essentially the collect response part of the syntax, and thus has to be part of the response collect syntax.

    3. The syntax will save the response in a dictionary like for example {pressed: True, key: left, port : 0, time: 300} for every time participants hit the response boxes.

    4. I will then have to write a syntax that writes the dictionary to a data file after every trial (which is the last chapter of the tutorial, so I hope I'll know how to do that in a week).

    So the tricky bit in terms of duality is then to get the program to go to the next trial only when it has collected a response from both participants. So for example:
    if dev1.response == True and dev2.response == True:
    continue
    (although I'm not sure yet how that would work in Opensesame).

    I'm I sort of on the right track? or is my interpretation of the problem wrong?

    Best
    Wouter

  • edited 12:51PM

    the first line of the syntax deals with importing the device, and should just be incorporated at the very beginning of the program.

    Yes, that would be these:

    # get a list of all attached XID devices
    devices = pyxid.get_xid_devices()
    dev = devices[0] # get the first device to use
    

    the second part is concerned with setting the parameters for the responses. that is: the .is_response part indicate that when a response is recorded, the timers will be reset. But it will check whether the response time is larger than zero before going on to saving a new response. This is essentially the collect response part of the syntax, and thus has to be part of the response collect syntax.

    No the logic is slightly different. First it checks whether dev is even a response device, and not something else. If so, it first resets the timers and then enters a loop. In the loop, it checks whether there is a response in the queue (i.e. if the queue size is larger than 0) and if so it gets the response from the queue.

    The syntax will save the response in a dictionary like for example {pressed: True, key: left, port : 0, time: 300} for every time participants hit the response boxes.

    Yes.

    I will then have to write a syntax that writes the dictionary to a data file after every trial (which is the last chapter of the tutorial, so I hope I'll know how to do that in a week).

    Yes, you could go with:

    # Assuming that `response` is a response dict
    exp.set('response', response['key'])
    exp.set('response_time', response['time'])
    

    I'm I sort of on the right track? or is my interpretation of the problem wrong?

    You're definitely getting there!

  • edited November 2013

    Ok, so I'm working on it now.
    I placed the following code at the beginning of the experiment, in the prepare phase:

    import pyxid 
    
    # get a list of all attached XID devices
    devices = pyxid.get_xid_devices()
    
    dev = devices[0] # get the first device to use
    

    This seems to work, because if i put in

    print str(device[0])
    

    It gives me "Cedrus RB-530" in the debug window, so it recognized the device.

    Then I put this in the beginning of the trial sequence (I've tried both the prepare and run phase):

    if dev.is_response_device():
        dev.reset_base_timer()
        dev.reset_rt_timer()
    
        while True:
            dev.poll_for_response()
            if dev.response_queue_size() > 0:
                response = dev.get_next_response()
                                             # Do something with the response
    

    When I run it like this, it crashes.
    So I'm asuming that it is a loop thats not finishing, causing the program to jam. Is that correct? and if so, how should I stop it?

    Also, it says 'do something with the response'. What do they mean by that? Should I define the response variables there?

    Cheers

  • edited 12:51PM

    When I run it like this, it crashes. So I'm asuming that it is a loop thats not finishing, causing the program to jam. Is that correct? and if so, how should I stop it?

    With 'it crashes' I assume you mean that the script becomes unresponsive? The way to debug these things is to add print statements throughout the code, to see where things gets stuck. For example, something like this ...

    print 'calling dev.poll_for_response()'
    dev.poll_for_response()
    print 'ok'
    

    ... allows you to see if the code hangs at poll_for_response(): If it does, you won't see the 'ok' in the debug window. Similarly, this ...

    if dev.response_queue_size() > 0:
        print 'response_queue_size > 0'
        response = dev.get_next_response()
        print 'response = %s' % response
    else:
        print 'response_queue_size <= 0'
    

    ... would allow you to check what exactly happens in this piece of code.

    In general, if you get stuck, just print everything to the debug window until you know exactly where things go wrong.

    Also, it says 'do something with the response'. What do they mean by that? Should I define the response variables there?

    Yes it does! See my previous comment.

    Cheers,
    Sebastiaan

  • edited November 2013

    Well, the problem is a bit that when I run the code, Opensesame becomes unresponsive, and I have to shut it down. (that's what I meant by 'crashed'). So even if I print something, I wont be able to see the result in the debug window because Opensesame stops responding...
    That's why I suggested that it might be an infinite loop (because these tend to crash the entire program rather than the script just being unresponsive right?)

    Cheers

  • edited 12:51PM

    So even if I print something, I wont be able to see the result in the debug window because Opensesame stops responding

    Ah right, yes. To get around this you can force OpenSesame to abort at strategic points in the script, by raising an exception:

    print 'calling dev.poll_for_response()'
    dev.poll_for_response()
    raise Exception('dev.poll_for_response() was finished')
    

    That's why I suggested that it might be an infinite loop (because these tend to crash the entire program rather than the script just being unresponsive right?)

    Yes indeed, it is probably an infinite loop.

    Cheers!

  • edited November 2013

    Ok, so it seems that it sort of works now, but it doesnt save the data correctly:

    this is the code I've been using for a loop of 5 cycles (I put the inline script after the stimulus).

    if dev.is_response_device():
    
        dev.reset_base_timer()
    
        dev.reset_rt_timer()
    
        while True:
    
                dev.poll_for_response()
    
                if dev.response_queue_size() > 0:
    
                    response = dev.get_next_response()
    
                    exp.set('responsetime', response['time'])
    
                    exp.set('responseyn', response['pressed'])
    
                    exp.set('responsekey', response['key'])
    
                    exp.set('responseport', response['port'])
    
                break
    

    This is the .csv output that I get

    responsekey 4 4 1 1 0

    responseport 0 0 0 0 0

    responsetime 1802 1906 1773 1885 1764

    responseyn yes no yes no yes

    So:

    1. It's not properly saving whether or not I pressed the button: I only pressed it the first three times. However, the responseyn variable seems to have nothing to do with me pressing the buttons

    2. Also, for everytime responseyn = no, it simply copies the responsekey of the previous time. I pressed different buttons every time

    3. when you dont respond in the first cycle, it will just say NA for all the variables. shouldnt it do so for all the times it receives no responses?

    4. Finally, the response times are not at all what they should be. The stimulus is only presented for 1000 ms, so these response times are not possible. Shouldnt the dev.reset commands reset the timers in the device?

    Do you have any idea what might go wrong? Is it the Opensesam Loop that is causing problems?

    Cheers!

  • edited 12:51PM

    Note the logic of the loop! Here ...

        if dev.response_queue_size() > 0:
            response = dev.get_next_response()
        break
    

    ... the break statement will be executed regardless of whether the queue size is larger than 0. Here ...

        if dev.response_queue_size() > 0:
            response = dev.get_next_response()
            break
    

    ... the break statement is only executed when a response has actually been collected, which is what you want. Does that make sense?

  • edited November 2013

    Well, I already tried that, but it doesnt matter for the data collection. It's giving the same output as with the break indented a level earlier.

    Also, the only reason I get the response times around 1800 ms is because I put an inline script before the stimulus which says dev.reset_base_timer and dev.reset_rt_timer in the prepare phase. If I don't do that, then the response time are more like 18000 ms.

    So something is not working inside the loop, or the program is somehow not calling the loop during the stimulus.

    1. apparently the base timer is not reset during the loop (because if it would, putting in the reset commands would not have made a difference).

    2. it's also not properly storing the rest of the data.

    3. Something that is quite strange, is that even though the stimulus is presented 1000 ms, the program only goes on the 2nd and 4th time (the trials in which responseyn was 'no'). In the 1st, 3rd and 5th trial the program won't go on until I've clicked the response box. If the loop would work properly, it would do the same thing in every trial, but somehow it doesn't.

    I'm not sure whether it's the python coding, or if it's maybe the way I've set it up in opensesame, so I'll give you a short discription of the Opensesame program:

    image

    Startsequence

    Inlinsescript 'import devices' (Prepare phase) containing:

    import pyxid

    pyxid.use_response_pad_timer = True

    devices = pyxid.get_xid_devices()

    dev = devices[0]

    Then it shows a sketchpad which says 'control' (so I have to press a key in order to start the following loop).

    Next a loop containing a sequence.

    this sequence contains a stimulus which says 'dont press', which is presented for 1500 ms, and a new sequence, which is the actual trial.

    the TrialSequence contains 4 items

    1 an inlinescript 'SetTimers' (prepare phase) containing:

    dev.reset_base_timer()

    dev.reset_rt_timer()

    2 the stimulus (stimulusPush), appearing for 1000 ms

    3 another inline script 'collectresponse' (run phase), containing the response collection, so:

    'if dev.is_response_device():

    while True:
    
            dev.poll_for_response()
    
            if dev.response_queue_size() > 0:
    
                dev.reset_base_timer()
    
                response1 = dev.get_next_response()
    
                print response1
    
                if response1['pressed']: 
    
                    exp.set('responsetime1', response1['time'])
    
                    exp.set('responseyn1', response1['pressed'])
    
                    exp.set('responsekey1', response1['key'])
    
                    exp.set('responseport1', response1['port'])
    
                    break
    
               else: 
                    break   
    

    `

    4 a logger, logging 'responsetime1', 'responseyn1', 'responsekey1', and 'responseport1'.

    Based on the code, or the Opensesame Structure, do you have any idea why the response collection is flawed?

    I'm sorry to ask for so much of your time, but there are hardly any Python users around in my research group, and none of them are familiar with Opensesame.

    Best
    Wouter

  • edited November 2013

    I think I've partly figured out what the problem is by using print response1. So if we have this output (which what I posted before):

    responsekey 4 4 1 1 0

    responseport 0 0 0 0 0

    responsetime 1802 1906 1773 1885 1764

    responseyn yes no yes no yes

    what it apparently does, is it saves the first response for when the button was pressed (e.g. 1802), and the second response for when the button was released (e.g. 1906). Thats why pairs of responses are always in a 100-150 ms range of each other. Also, it explains why the responskey variable is always twice the same (4 and 4, then 1 and 1), and it means that the responseyn variable indicates that the first of the two trials is always pressed (responseyn = yes) and the second is relieved (responseyn = no).

    Do you have an idea why the loops saves the press-response in the first trial, and the release-response in the second? Because I just want it to save the press-response in every trial.

  • edited November 2013

    Hi Wouter,

    I've deleted your accidental comment for you. To do so yourself, pressing 'Edit' on the top of your post, then 'Delete' should do the trick. At least, I believe users should be able to do so themselves, but I'm not quite sure on that one. Otherwise, just do as you've done in this case and simply request removal within the post itself.

    (I'll let Sebastiaan answer your real question ;) )

    Good luck!

  • edited 12:51PM

    Do you have an idea why the loops saves the press-response in the first trial, and the release-response in the second? Because I just want it to save the press-response in every trial.

    As you posted above, response should a dictionary with the following keys:

    pressed: True if the key was pressed, False if it was released
    key: Response pad key pressed by the subject
    port: Device port the response was from (typically 0)
    time: value of the Response Time timer when the key was hit/released
    

    So I would say that you loop is correct and should skip the button releases. But apparently it doesn't. I would start by checking what value and type the response1['pressed'] really has, by printing some debug info after you have collected it:

    # ...
    response1 = dev.get_next_response()
    print 'response1["pressed"] == %s (%s)' % (response1['pressed'], type(response1['pressed']))
    # ...
    

    Is it really a bool with the values False or True or is it something else?

  • edited November 2013

    I already did something like that (by just printing response1), and using your command gives this output (which I sort of suspected):

    response1["pressed"] == True (<type 'bool'>)
    
    response1["pressed"] == False (<type 'bool'>)
    
    response1["pressed"] == True (<type 'bool'>)
    
    response1["pressed"] == False (<type 'bool'>)
    
    response1["pressed"] == True (<type 'bool'>)
    
    response1["pressed"] == False (<type 'bool'>)
    

    This is for 6 trials.
    So somehow it saves the press response of the first trial correctly in the first trial, and then saves the release response of the first trial in the next trial (whileI want it to collect the press response of the second trial).

    Apparently, this syntax doesn't collect both the true (pressed) and false (released) responses in the same trial, but it just collects the true one, and then saves the false one in the subsequent trial (even if I don't press a button).
    So somehow, I need to make sure that at the start of every trial, the program just clears whatever it still 'remembers' from the round before, and starts with an empty dictionary again.

    Cheers

  • edited 12:51PM

    Ow wait, I think I see the/ an issue. Note the logic in your script:

    if response1['pressed']: 
        # (Some stuff)
        break
    else: 
        break
    

    This means that the loop will break, even when a button is released, although on a release the response variables will not be set. So basically, you should break the loop only on a button press. Does that make sense?

Sign In or Register to comment.

agen judi bola , sportbook, casino, togel, number game, singapore, tangkas, basket, slot, poker, dominoqq, agen bola. Semua permainan bisa dimainkan hanya dengan 1 ID. minimal deposit 50.000 ,- bonus cashback hingga 10% , diskon togel hingga 66% bisa bermain di android dan IOS kapanpun dan dimana pun. poker , bandarq , aduq, domino qq , dominobet. Semua permainan bisa dimainkan hanya dengan 1 ID. minimal deposit 10.000 ,- bonus turnover 0.5% dan bonus referral 20%. Bonus - bonus yang dihadirkan bisa terbilang cukup tinggi dan memuaskan, anda hanya perlu memasang pada situs yang memberikan bursa pasaran terbaik yaitu http://45.77.173.118/ Bola168. Situs penyedia segala jenis permainan poker online kini semakin banyak ditemukan di Internet, salah satunya TahunQQ merupakan situs Agen Judi Domino66 Dan BandarQ Terpercaya yang mampu memberikan banyak provit bagi bettornya. Permainan Yang Di Sediakan Dewi365 Juga sangat banyak Dan menarik dan Peluang untuk memenangkan Taruhan Judi online ini juga sangat mudah . Mainkan Segera Taruhan Sportbook anda bersama Agen Judi Bola Bersama Dewi365 Kemenangan Anda Berapa pun akan Terbayarkan. Tersedia 9 macam permainan seru yang bisa kamu mainkan hanya di dalam 1 ID saja. Permainan seru yang tersedia seperti Poker, Domino QQ Dan juga BandarQ Online. Semuanya tersedia lengkap hanya di ABGQQ. Situs ABGQQ sangat mudah dimenangkan, kamu juga akan mendapatkan mega bonus dan setiap pemain berhak mendapatkan cashback mingguan. ABGQQ juga telah diakui sebagai Bandar Domino Online yang menjamin sistem FAIR PLAY disetiap permainan yang bisa dimainkan dengan deposit minimal hanya Rp.25.000. DEWI365 adalah Bandar Judi Bola Terpercaya & resmi dan terpercaya di indonesia. Situs judi bola ini menyediakan fasilitas bagi anda untuk dapat bermain memainkan permainan judi bola. Didalam situs ini memiliki berbagai permainan taruhan bola terlengkap seperti Sbobet, yang membuat DEWI365 menjadi situs judi bola terbaik dan terpercaya di Indonesia. Tentunya sebagai situs yang bertugas sebagai Bandar Poker Online pastinya akan berusaha untuk menjaga semua informasi dan keamanan yang terdapat di POKERQQ13. Kotakqq adalah situs Judi Poker Online Terpercayayang menyediakan 9 jenis permainan sakong online, dominoqq, domino99, bandarq, bandar ceme, aduq, poker online, bandar poker, balak66, perang baccarat, dan capsa susun. Dengan minimal deposit withdraw 15.000 Anda sudah bisa memainkan semua permaina pkv games di situs kami. Jackpot besar,Win rate tinggi, Fair play, PKV Games