pythonpsychopy

Why is my event.getKeys() memory buffer not clearing?


Background:

I have a task which plays a video using VLCMovieStim and, every frame, collects ratings on a continuous bipolar scale. To give an idea of what it looks like. enter image description here event.getKeys() tracks when either the 2 or 3 buttons are pressed, but not yet released. When these conditions are met, a variable keys changes value. For every frame that keys takes a 'LEFT' or 'RIGHT' value because of the key presses, the scale will increment 1% in the respective direction. When keys are released, event.clearEvents() clears the memory buffer, effectively changing the value of keys back to 'STOP'.

Issue:

When the rating scale oscillates enough times, it will break. From wherever the scale currently sits, it progresses to one of the two poles and it stays at that terminal position, no matter what button states exist afterward. print() functions have demonstrated that the value of keys does successfully reset with each frame, but it seems once it gets to the conditionals, it feels that the conditions to change keys to either 'LEFT' or 'RIGHT' have been met, despite no buttons being pressed. It seems like although I'm changing the value of keys I'm not actually clearing the event memory, but I don't know why that's happening. I’m assuming I must have a flaw in my logic somewhere, but after about a week of workshopping this, I'm at a loss:

kb = keyboard.Keyboard()
        if kb.status == STARTED:
            keys = 'STOP'
            # When the left key is pressed and not released, keys = LEFT
            # If either boolean is 'True', simply holding down the button will not yield continuous incrementing in the rating
            if len(kb.getKeys([keyLeft], waitRelease = True, clear = True)) == 0 or len(kb.getKeys([keyRight], waitRelease = True, clear = True)) == 0:
                keys = 'STOP'
                if len(kb.getKeys([keyLeft], waitRelease = False, clear = False)) > 0:
                    keys = 'LEFT'
                    if len(kb.getKeys([keyLeft], waitRelease = True, clear = False)) > 0:
                        kb.clearEvents()
                elif len(kb.getKeys([keyRight], waitRelease = False, clear = False)) > 0:
                    keys = 'RIGHT'
                    if len(kb.getKeys([keyRight], waitRelease = True, clear = False)) > 0:
                        kb.clearEvents()
            if keys == 'LEFT':
                y1 -= round(0.005,3)
                y1 = round(y1,3)
                y3 = ((y1)/2)
                if y1 < 0:
                    keyCount += 1
                if keyCount > 100:
                    keyCount = 100
                if y1 >0:
                    keyCount -= 1
                if y1 == 0.000:
                    keyCount = 0
                if y1 <= -0.5:
                    y1 = -0.5
                    keyCount = 100
            if keys == 'RIGHT':
                y1 += round(0.005,3)
                y1 = round(y1,3)
                y3 = ((y1)/2)
                if y1 > 0:
                    keyCount += 1
                if keyCount > 100:
                    keyCount = 100
                if y1 <0:
                    keyCount -= 1
                if y1 == 0.000:
                    keyCount = 0
                if y1 >= 0.5:
                    y1 = 0.5
                    keyCount = 100 

For the sake of sharing replicable code and not spamming this post, I’ve isolated the necessary code and made it available, along with necessary stimuli, here.

Thanks in advance for your time!


Solution

  • I came up with my own solution. I simply altered the conditional logic to specify that keys can only take a directional value if only one of the keys is currently being pressed. The issue always seems to generate when changing directions, so by limiting one's ability to do that quickly, I seem to have eliminated the problem. For additional insurance, I specified that keys cannot take a directional value if the scale is currently at either pole. I've been trying to break the script for a few hours now and haven't had luck. Of course, I won't know for sure until it reoccurs, but fingers crossed.

            if kb.status == STARTED:
               
                # At the start of the loop, we check whether the scale is at either of its poles, 
                # and if so, we reset the keys variable and clear the event log.
                if abs(y1) >= 0.5:
                    keys = 'STOP'
                    kb.clearEvents()
    
                # If the left button is being pressed, and the right button is not being 
                # pressed, and the scale is not currently at the left pole, change the 
                # value of keys to LEFT. These additional conditionals are crucial for me.
                if len(kb.getKeys([keyLeft], waitRelease = False, clear = False)) == 1 and len(kb.getKeys([keyRight], waitRelease = False, clear = False)) != 1 and y1 > -0.5:
                    keys = 'LEFT'
    
                    # Once the key is released, clear the memory buffer and change 
                    # the value of keys to STOP
                    if len(kb.getKeys([keyLeft], waitRelease = True, clear = False)) > 0:
                         keys = 'STOP'
                         kb.clearEvents()
    
                # Just as above, except for the right key. 
                elif len(kb.getKeys([keyRight], waitRelease = False, clear = False)) == 1 and len(kb.getKeys([keyLeft], waitRelease = False, clear = False)) != 1 and y1 < 0.5 :
                    keys = 'RIGHT'
                    if len(kb.getKeys([keyRight], waitRelease = True, clear = False)) > 0:
                            keys = 'STOP'
                            kb.clearEvents()