Howdy, Stranger!

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

Supported by

log all key presses

Is it possible to log all keypresses on the keyboard? Even those which are not a specific response or occur erroneously.
E.g. participants are instructed to respond to a stimulus with a target button [f,g,h, or j] and simultaneously the SHIFT key. With the SHIFT key of the stimulus dissappears and the next stimulus is presented.
My script already logs the SHIFT presses. But how do i log the other keypresses? (This is important in order to know whether the participants followed the instructions or not.)

seq_B = [1,2,3,4,5,6]
for i in range(6): #48 at the end
    start_time = seq_B[i].show()
    kb = keyboard(keylist = ['LSHIFT','RSHIFT'])
    key, time = kb.get_key() #wait for SHIFT key press
    var.Stim_time = start_time
    var.Resp_time = time
    var.Resp= key
    log.write_vars() #log all defined variables

Comments

  • Greetings,

    The way you initiated your keyboard, it will only recognize shift presses because these are the only things that are in your keylist.

    Still, there is the problem of the get_key() command only taking in one key at a time. Possibly, you could follow-up on the get_key() command with another get_key() command where you exclude the key that had already been pressed from the list. In order to make it work only when the keys are pressed simultaneously, you could put the commands in a while-loop, with a very short timeout for the 2nd keypress. You exit the while loop when the 2nd keypress was unequal to 'None'.

    Let me know if this works.

    Cheers

    Josh

  • Thanks Josh for the very quick answer.
    I am not sure whether a second get_key command will bring the desired result, as I do not expect the following stimulus to appear with the first response anymore.
    I like to see the experiment go on as it already does, just to log any keypress that occurs during the experiment.

    What I am actually looking for is a command at the beginning of the experiment that says that any key is going to be logged as it is done in "presentation". In a way that i do not have to define the keypresses in advance. I cannot foresee what participants are willing to do, but when its logged i may understand it afterwards.
    Is that possible in OpenSesame?

    Greetz Stephan

  • Hi Stephan,

    How about you put your code into a while loop and in which you keep on sampling key presses e.g., kb.get_key(timeout=10) (After which you flush the keyboard, to get rid of pending key presses). For every key press you append the key to a list of all pressed keys and the response time to all times. Then in the end of your trial (outside the while loop), you loop over your list of key presses and for each write a new line to the log file log.write_vars() or write the entire list to the file. However, if you opt for latter, be aware that the list is converted to a string and is not really accessible any more. You still can retrieve the information, but it requires some hacking during preprocessing your data.

    Does this make sense?

    Eduard

  • Dear Eduard and Josh,

    after 3 days of hard work i found a very nice solution. :)
    Nevertheless i still have one last problem. A fundamental problem.
    When the presses are perfomed synchroneously, it does not log anything.
    I believe that there is a minimum inter onset interval in open sesame that interferes with my code.
    Is there a way to set the inter onset interval (time between two key presses) to 0?

    Here is my code.

        kb = keyboard(keylist = ['f','g','h','j','LSHIFT','RSHIFT','d','k'])
        A = canvas()
        A.text('A')
        B = canvas()
        B.text('B')
    
        #seq=[1,2]
        #print seq, len(seq), (len(seq)-1)
    
    
        seq = [A,B]*5 
        Resp=[None]
        T_Resp=[None]
    
        def Previous ():
            if seq[i-1] == A:
                var.Stim = 'A'
            else:
                var.Stim ='B'
            var.Resp=Resp[i] #starts with 1
            var.T_Resp=T_Resp[i]
            var.Resp2=presses[1]    #list starts with 0
            var.T_Resp2=times[1]    
            log.write_vars()
    
        def Current ():
            if seq[i] == A:
                var.Stim = 'A'
            else:
                var.Stim ='B'
            var.Resp= Resp[i+1]
            var.T_Resp= T_Resp[i+1]
            var.Resp2=presses[1]
            var.T_Resp2=times[1]
            log.write_vars()
    
        def CurrentPress ():
            if seq[i] == A:
                var.Stim = 'A'
            else:
                var.Stim ='B'
            var.Resp= Resp[i+1]
            var.T_Resp= T_Resp[i+1]     
            key, time = kb.get_key()
            var.Resp2=key   #list starts with 0
            var.T_Resp2=time
            log.write_vars()
    
        def Current2 ():
            if seq[i] == A:
                var.Stim = 'A'
            else:
                var.Stim ='B'
            var.Resp= Resp[i+1]
            var.T_Resp= T_Resp[i+1]
            var.Resp2=presses[-1]
            var.T_Resp2=times[-1]
            log.write_vars()
    
        def LOG():
            global presses, times
            presses=[None]
            times=[None]
            key, time = kb.get_key()
            while (key=='d') or (key=='k') or (key=='f') or (key=='g') or (key=='h') or (key=='j'): 
                presses.append(key)
                times.append(time)
                kb.flush()
                key, time = kb.get_key()
            Resp.append(key)
            T_Resp.append(time)
    
            #SHIFT first
            if (i>0) and (len(presses)==2) and ( (times[1]-T_Resp[i]) < (T_Resp[i+1]-times[1]) ) :  #length starts with 1 
                Previous()
                #save last line
                if (i==(len(seq)-1)):
                    CurrentPress()
    
            #target first
            elif (i>0) and (len(presses)==2) and ( (times[1]-T_Resp[i]) > (T_Resp[i+1]-times[1]) ) :  
                Current()
            #target first and first trial
            elif (i==0) and (len(presses)==2) :
                Current()
    
            #two shifts in a row last line
            elif (len(presses)<2) and (i==(len(seq)-1)) :
                CurrentPress()
    
            #two targets in a row
            elif (len(presses)>2):
                #all but first line
                Previous()
                Current2()
    
    
        for i in range(10): 
            seq[i].show()
            LOG()
    
  • That is how my output should look like (and looks like when i do not press in synchrony).

  • I played a little around and found out that the problem lies (at least) in the trial when shift is pressed first.
    I could imagine that it has to do with the refresh rate of the next stimulus. (Just a guess)
    At the moment shift is pressed the next stimulus is presented. During builiding up the next stimulus, the second button is pressed. Still, i do not understand why it is not counted (as it does not count for dissappearence of this stimulus, only logged).

    I am using xpyriment backend.

    Is there a way to handle this?

  • Is there something like a debounce time which i have to set to 0?

  • As i do not find a solution I have now tried to use the coroutines function and rewrote the old script for the inline_script.

        def Simultan():
            kb = keyboard(keylist = ['f','g','h','j','LSHIFT','RSHIFT','d','k'])
            A = canvas()
            A.text('A')
            B = canvas()
            B.text('B')
    
            seq = [A,B]*5 
    
            seq.reverse() #pop wählt von hinten aus
            t =seq[-1].show()
            #var.Stim = seq[-1]
            #var.T_Stim = t
            #log.write_vars()
            seq.pop() #pops out the last
            key, time = kb.get_key()
    
            yield   
    
            while True: 
                if key != 'RSHIFT':
                    kb.flush()
                    key, time = kb.get_key()
                    keep_going=yield
    
                if key == 'RSHIFT':
                    if (len(seq)>0):
                        t = seq[-1].show()
                        seq.pop()
                        #keep_going=yield
                    elif (len(seq)<1):
                        break
    

    First of all i have some simple implementation questions:
    1. Where do i place the inline_script?
    The coroutine item does not allow to put inline_script inside ("inline_script does support coroutines").
    Hence i tried to put the inline_script before and after the coroutine.
    2. How do i refer to the python function "Simultan" in the generator function name field?
    I tried Simultan, 'Simultan', "Simultan", [Simultan] and the same with ==
    But i always get the message that it is not found.

    Thanks Stephan

  • I solved it.
    Here is a version that works fine.
    Mind:
    1. Do not use USB connections for your keyboard.
    2. Do not use SHIFT or CTRL keys

    kb = keyboard(keylist = ['f','g','h','j','<','-','d','k'])
    Break = canvas()
    Break.text('')
    A = canvas()
    A.text('A')
    B = canvas()
    B.text('B')
    seq = [A,B]*5 
    seq.reverse() #pop wählt von hinten aus
    #var.Stim = seq[-1]
    #var.T_Stim = t
    #log.write_vars()
    T_Resp=None
    T_Resp2=None
    last=None
    last2=None
    t =seq[-1].show()
    if seq[-1] == A:
        var.Stim = 'A'
    else:
        var.Stim ='B'
    print var.Stim, t
    seq.pop() #pops out the last
    while True:
        if (len(seq)!=0):
            key, time = kb.get_key(timeout=0)
            if key == 'f':
                T_Resp2=time
                print key, time
                kb.flush()    
            elif key == '-':
                print key, time
                T_Resp=time
                t = seq[-1].show()
                if seq[-1] == A:
                    var.Stim = 'A'
                else:
                    var.Stim ='B'
                print var.Stim, t
                seq.pop()
        if (len(seq)==0): #Last presses
            key, time = kb.get_key(timeout=0)
            if key == 'f':
                T_Resp2=time
                print key, time
                if (time-t)>200:
                    last=time
                kb.flush() 
            elif key == '-':
                print key, time
                T_Resp=time
                last2=time
            elif last>0 and last2>0:
                print "Break", T_Resp, T_Resp2, T_Resp-T_Resp2
                break
    
  • edited November 2016

    Do not use log.write_vars() within the loop. It makes the loop too slow.

    Here is an alternative.

    kb = keyboard(keylist = ['f','g','h','j','<','-','d','k'])
    Break = canvas()
    Break.text('')
    A = canvas()
    A.text('A')
    B = canvas()
    B.text('B')
    seq = [A,B]*5 
    seq.reverse() #pop wählt von hinten aus
    var.T_Resp=[]
    var.T_Resp2=[]
    var.Resp=[]
    var.Resp2=[]
    var.Stim=[]
    var.T_Stim=[]
    last=None
    last2=None
    t =seq[-1].show()
    var.T_Stim.append(t)
    if seq[-1] == A:
        var.Stim.append('A')
    else:
        var.Stim.append('B')
    print var.Stim, t
    seq.pop() #pops out the last
    while True:
        if (len(seq)!=0):
            key, time = kb.get_key(timeout=0)
            if key == 'f':
                var.T_Resp2.append(time)
                var.Resp2.append(key)
                print key, time
                kb.flush()    
            elif key == '-':
                print key, time
                var.T_Resp.append(time)
                var.Resp.append(key)
                t = seq[-1].show()
                var.T_Stim.append(t)
                if seq[-1] == A:
                    var.Stim.append('A')
                else:
                    var.Stim.append('B')
                print var.Stim, t
                seq.pop()
        if (len(seq)==0): #Last presses
            key, time = kb.get_key(timeout=0)
            if key == 'f':
                var.T_Resp2.append(time)
                var.Resp2.append(key)
                print key, time
                if (time-t)>200:
                    last=time
                kb.flush() 
            elif key == '-':
                print key, time
                var.T_Resp.append(time)
                var.Resp.append(key)
                last2=time
            elif last>0 and last2>0:
                print "Break", var.T_Resp, var.T_Resp2
                break
        #log.write_vars() #NOT POSSIBLE: slows down the whole loop
    #You never know what participants do. So I treat each variable independently.  `
    for i in range(len(var.Stim)):
        var.Stim1=var.Stim[i]
        var.T_Stim1=var.T_Stim[i]
        log.write_vars()
        print var.Stim1, var.T_Stim1
    
    for i in range(len(var.Resp)):
        var.Resp1=var.Resp[i]
        var.T_Resp1=var.T_Resp[i]
        log.write_vars()
        print var.Resp1, var.T_Resp1
    
    for i in range(len(var.Resp2)):
        var.Resp2_1=var.Resp2[i]
        var.T_Resp2_1=var.T_Resp2[i]
        log.write_vars()
        print var.Resp2_1, var.T_Resp2_1
    
Sign In or Register to comment.