Howdy, Stranger!

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

Supported by

[solved] Choice task multiple options

edited April 2016 in OpenSesame

Hello,

I am developing a multiple choice task in OpenSesame. Subjects are presented with a screen on which 6 cues are shown. Each of the cues corresponds to a certain keyboard key. Subjects should be able to select none or multiple (any number between 1 and 6) of the cues by pressing corresponding keyboard keys. After pressing the key corresponding to a certain cue, a box should appear around the cue. If then a different key is pressed, corresponding to a different cue, a box should appear around that respective cue as well. All keyboard responses should be logged. Subjects indicate by pressing space that they are finished making their selection (and they go to the next trial).

What would be the best approach to accomplish this? I read on the forum that it is not possible to have multiple keyboard inputs on one sketchpad. Therefore, i guess a staged approach (kind of tree diagram) might be the best? That first the screen with the cues (and no boxes) is shown. If key A is pressed, a next screen is shown with the cues and a box around cue A. Then if key B is pressed, a new screen is shown with the cues and boxes around cue A and B. Etc. Etc. This means I would have a tree that splits 6x5x4x3x2 times. Also, I have to make screens with cues and boxes around all different cues and all possible combinations. The logging of the keypresses would also become quite complicated. If this is the only or most appropriate approach, that is fine. However, if you think there is a more practical approach, please let me know.

Thanks,
Nynke

Comments

  • edited 2:44AM

    Hi Nynke,

    Your idea with the tree is logically correct and therefore possible, but as you already reckoned, too much of a hassle. It'll be best for you to use an inline_script. You could basically create the whole trial in a single inline_script, but it will require a bit of coding.

    Instead of sketchpads, you use the canvas command (see http://osdoc.cogsci.nl/python/canvas/). As you can see on this page, there are different commands to draw different things on that canvas, and the first step will be to draw the different cues for that trial. I don't know the details of your experiment, but I suppose the place and identity of the cues depend on certain experimental variables (defined in your loop item). The drawing process will therefore probably consist of a couple of if-then statements (e.g. if exp.condition = 5: my_canvas.image('cue5.jpg',x=100,y=300)).

    When your canvas is drawn in the prepare phase, you can show it (starting the trial) in the run-phase with the my_canvas.show() command. You then want to enter a while-loop where you await one or more keyboard responses (to initiate the keyboard, see http://osdoc.cogsci.nl/python/keyboard/). A while loop could look like this:

      coordinates=[(100,200), (200,200), (300,200)] # example coordinates
                                                                             # to indicate where box needs
                                                                           #to be drawn.
    
    
      key_presses = []
      while len(key_presses) < 4: # if you'd need to give 4 responses
            key, time = my_keyboard.get_key(keylist=[1,2,3,4,5,6],timeout=3000)
            key_presses.append(key)
            if key != 'none':
                  my_canvas.polygon([(coordinates[key][0]-20,coordinates[key][1]-20),\
                  (coordinates[key][0]+20,coordinates[key][1]-20),\
                  (coordinates[key][0]-20,coordinates[key][1]+20),\
                  (coordinates[key][0]+20,coordinates[key][1]+20)])
                  # draws a rectangle of height and width 40, around the set of 
                  # coordinates from the coordinate list, corresponding to key.
    
            my_canvas.show() # and then shows the updated canvas.
    

    Good luck!

    Cheers

    Josh

  • edited 2:44AM

    Hi Josh,
    Thank you you so much! After a few small modifications it works!
    For others that want to use the same paradigm:
    In prepare tab:

    my_canvas = canvas()
    path = exp.pool[u'choicescr_blank.png'] # To get the absolute path to the image in the file pool. 
    my_canvas.image(path)
    

    In run tab:

    # coordinate 0, 0 is the center of the screen
    my_canvas.show()
    my_keyboard = keyboard()
    coordinates=[(-560,-200), (0,-200), (560,-200), (-560,200), (0,200), (560,200)] # example coordinates to indicate where box needs to be drawn. 
    key_presses = []
    while len(key_presses) < 4: # if you'd need to give 4 responses # Ik moet ervan maken een bepaalde tijd voor timeout of totdat op spatie gedrukt. 
        key, time = my_keyboard.get_key(keylist=[1,2,3,4,5,6],timeout=None)
        key_presses.append(key)
        if key != 'none':
            print(key)
            print(type(key))
            my_canvas.rect(coordinates[int(key)-1][0], coordinates[int(key)-1][1], 100, 100) # The left x coordinate, the top y coordinate, width, height. Draws a rectangle around the set of coordinates from the coordinate list, corresponding to key.
        my_canvas.show() # and then shows the updated canvas.
    
    var.choice_responses = key_presses # To log the keyresponses in the variable choice_responses
    
  • edited 2:44AM

    Great that you solved it!

    Cheers

  • edited 2:44AM

    I have an additional question (if its better to open a new topic, please let me know). I want to continue to the next trial after a certain duration and not after a certain amount of keypresses. Therefore, I adapted the while loop and incorporated a timer in it. However, it appears that, with the script below, the trial only continues to the next when a button is pressed after the 'time_to_respond'. When no button is pressed, the trial just keeps on the screen and it does not continue. Since there is no requirement for button pressing in the while statement, I do not understand this behavior. Any suggestions what the problem might be?

    time_to_respond = 5000
    my_canvas.show()
    my_keyboard = keyboard()
    my_keyboard.flush() # To flush any keypresses that occured during the previous screen (choicescreen)
    key_coordinate = {u'num_7': (-810, -374), u'num_8':(-260, -374), u'num_9':(290, -374), u'num_4':(-810, 26), u'num_5':(-260, 26), u'num_6':(290, 26) };
    response_keys = list(key_coordinate.keys())
    key_presses = []
    t0 = self.time()
    while self.time() - t0 < time_to_respond: # get keypresses until time_to_respond. 
        key, time = my_keyboard.get_key(keylist=response_keys,timeout=None)
        print(key)
        key_presses.append(key)
        if key != 'none':
            if key_presses.count(key)%2==1: # If odd:
                my_canvas.rect(key_coordinate[key][0], key_coordinate[key][1], 520, 350, color=u'yellow', penwidth = 5) # The left x coordinate, the top y coordinate, width, height. Draws a rectangle around the set of coordinates from the coordinate list, corresponding to key.
            else: # if even
                my_canvas.rect(key_coordinate[key][0], key_coordinate[key][1], 520, 350, color=u'black', penwidth = 5)
        my_canvas.show() # and then shows the updated canvas.
    
    var.choice_responses = key_presses # To log the keyresponses in the variable choice_responses
    
    
  • edited 2:44AM

    Any ideas? Any suggestion is welcome and might steer me in the right direction for solving this issue.

  • edited April 2016

    Hi Nynke,

    I think it should work if you change the while-loop in a way that it constantly updates the current time within the loop. Now, you only check the timing once at the start of the loop.

    Try something like this:

    time_to_respond = 5000
    start_time = self.time()
    passed_time = 0
    
    while passed_time < time_to_respond:
    
        # Gather keyboard responses here
    
        # Update time
        passed_time = self.time() - start_time
    
        # And update the canvas
        my_canvas_show()
    
    
  • edited 2:44AM

    Dear Knante,
    Thank you for your help. I have adapted the task to what you suggested but it still doesn't give the desired behavior. What now happens with the adapted script, is that the trial stays on the screen forever if no button is pushed. When a button is pushed, and this is within the time_to_respond the canvas is updated everytime you push a button. Still the next trial only appears after you pushed a button after the time_to_respond. So it is still needed to push a button to continue.
    It seems like the while loop is not contineously updating the time.
    Does anyone understand this behavior?

  • edited 2:44AM

    Also if others have ideas or suggestions for other approaches to get the wanted behavior, I would be very thankful! I'm kind of in a hurry to get this task running properly.. so any hints in the right direction are welcome!

  • edited 2:44AM

    Hi Nynke, I'm not sure, but I think the culprit is the timeout parameter in your get_key() function. If you set it to None, the function will block until it receives a keypress. If you change the parameter to timeout=0, it should show the behaviour you want (that is, simply continue and don't wait for keypresses).

  • edited 2:44AM

    That did it, the function indeed kept running forever if no button was pressed, disturbing the behavior of the while loop.
    Thanks!

Sign In or Register to comment.