Howdy, Stranger!

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

Supported by

[open] Breaking from a staircase loop

edited May 2012 in OpenSesame

Hi there again,

My current goal is to implement a staircase algorithm that changes presentation time of the targets until a certain level of accuracy has been reached.

In my experimental setup, this translates to: I want to keep repeating my trial sequence with, for each cycle, settings from the variable wizard (in its block loop) until I'm happy. Then, I'd like to break from it and start my experimental loop with those settings (using the same trial sequence).

Is that possible? The loop object only gives me the possibility to set the number of repeats and the number of cycles. Also, the trial sequence doesn't have a "run if" setting.

At the moment it seems my best option would be to simply set the number of repeats very high, and give every object in the trial sequence the "run if"-condition: "(...) and [staircaseCompleted] = 0" so everything gets skipped once the procedure is completed.

However, the ideal situation would be where I could just make a call like "self.experiment.breakFromLoop(staircase_loop)", or anything like that. Would that be possible? Or does every loop item needs to be run fully everytime?

Thanks!

Comments

  • edited May 2012

    Hi Wouter,

    The easiest way to do is probably using a small inline_script, like so:

    #Uncomment for 0.25 or earlier
    #exp = self.experiment
    while self.get('response_time') > 1000:
        exp.items['trial_sequence'].prepare()
        exp.items['trial_sequence'].run()

    This will repeat trial_sequence until the response time was less than or equal to 1000. If you insert this inline_script right after trial_sequence, it will do what you need (right?). Of course you can set the stop criterion to whatever you like, such as while self.get('continue') == 1: or whatever.

    It might be an idea to add this functionality as a plug-in, so I added it as feature request: https://github.com/smathot/OpenSesame/issues/89

    Hope this helps!

    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

  • edited May 2012

    Hi Sebastian,

    Thanks, it certainly helps, though I don't think my problem is fully solved yet:

    1. first a question on this snippet:
      do
      <br /> exp.items['trial_sequence'].prepare()<br /> exp.items['trial_sequence'].run()<br />
      call 'prepare' and 'run' on 'trial_sequence' or on all items within 'trial_sequence'? (relevant because several items within 'trial_sequence' have their own 'run if' conditions that I do not want to be overruled) I'm assuming it's on 'trial_sequence' itself.

    2. what do you mean by ''If you insert this inline_script right after trial_sequence" precisely? It probably wasn't clear from my question, but the outline of my expt is as follows (in pseudocode):

    <br /> Practice_loop # runs a couple trials with a relatively long presentation time<br /> pr_block_sequence<br /> reset_variables<br /> pr_block_loop # uses variable wizard to generate different trial settings (Cue and target positions) <br /> trial_sequence # <em>does not</em> run the staircase procedure here<br /> Staircase_loop # gradually alters presentation time to stabilize at desired acc level, then should 'break'<br /> sc_block_sequence<br /> reset_variables<br /> sc_block_loop # uses variable wizard to generate different trial settings (Cue and target positions) <br /> trial_sequence # <em>does</em> run the staircase procedure here<br /> Experiment_loop # runs a fixed number of all different trial combinations, randomized, while monitoring accuracy and changing presentation time accordingly. Does <em>not</em> require a 'break'<br /> reset_variables<br /> ex_block_loop # uses variable wizard to generate different trial settings (Cue and target positions) <br /> trial_sequence # <em>does</em> run the staircase procedure here<br />

    So, in the second phase (staircase phase) of the experiment, the loop should be interrupted once accuracy stabilizes, but the trials should still be taken randomly from the possible trial combinations. Now where should I place your code?

    • I can not place it in "sc_block_loop", as it will only allow one item to loop (i.e. trial_sequence)
    • I can not place it within "trial_sequence"; this seems to induce infinite recursive calls of 'trial_sequence'. (yes...I naively tried... :/)
    • I can not simply replace the sc_block_loop with a 'trial_sequence' followed by your code, as my trial sequence should be defined by the variables set in the sc_block_loop item, ("setcycle (...)"). -- or can I?

    Since not all trials in the staircase phase should be the same, I really need to randomly (and in a balanced fashion) assign variables like I normally would in 'sc_block_loop' for each cycle. Is there a simple solution to do this?

    This seems equally relevant for the implementation of the feature request you made. What I -personally!- need right now is not a new 'while' item, but actually an extension of the 'loop' item, i.e. a 'Run If...' field. Such an extension would immediately implement 'while' loop functionality. Perhaps you could take it even further and introduce an option to run 'at least xxx times, then run if yyy'. Then, you'd immediately have all the functionality of all the 'reqular' loops ('do...while', 'for' , 'while' and 'loop').

    ...but maybe you have a different design perspective!

    Cheers,
    Wouter

  • edited 7:06PM
    Do call 'prepare' and 'run' on 'trial_sequence' or on all items within 'trial_sequence'? (relevant because several items within 'trial_sequence' have their own 'run if' conditions that I do not want to be overruled) I'm assuming it's on 'trial_sequence' itself.

    The commands trickle down, as it were. So if you call prepare followed by run on a sequence, it will neatly prepare the sequence and all items in it (where necessary) and then run everything. The same is true for a loop. So you don't need to prepare all individual items.

    Since not all trials in the staircase phase should be the same, I really need to randomly (and in a balanced fashion) assign variables like I normally would in 'sc_block_loop' for each cycle. Is there a simple solution to do this?

    Ah, I see. In that case you should probably have the while loop execute a block at a time.

    while self.get('sc_done') == 0:
        exp.items['sc_block_loop'].prepare()
        exp.items['sc_block_loop'].run()

    The structure would then be something like

    sc_block_loop
    -- trial_sequence
    while_inline_script
    This seems equally relevant for the implementation of the feature request you made. What I -personally!- need right now is not a new 'while' item, but actually an extension of the 'loop' item, i.e. a 'Run If...' field. Such an extension would immediately implement 'while' loop functionality. Perhaps you could take it even further and introduce an option to run 'at least xxx times, then run if yyy'. Then, you'd immediately have all the functionality of all the 'reqular' loops ('do...while', 'for' , 'while' and 'loop').

    Right, yes, that might be something to consider. To specify a 'run while' statement instead of a fixed number of cycles. And perhaps some additional options.

    Good luck!

    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

  • edited 7:06PM

    Btw, you could take a look at, and possible hack on, the implementation of the loop, of course. As you can see, the code is fairly simple (the runtime anyway, the GUI is a bit messy):

    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

  • jpgjpg
    edited 7:06PM

    Hi Sebastiaan,

    I noticed that the feature request on github for this was depreciated?

    I'm trying to break out of a loop when a key is pressed: just a series of sketchpad items being presented until a keypress is detected at which point it moves out to the next part of the experiment. Any ideas?

    Jamie

  • edited January 2014
    I noticed that the feature request on github for this was depreciated?

    Right, yes. That's because a 'break if' statement has been added to the loop in the development snapshot. This effectively serves as a while loop, thus deprecating the feature request.

    In your case, you could make a variation on my first response (see above) but use a different criterion (i.e. while response != 'space' or something). But it might be easier to just handle it with a small inline_script. Something like this should get you started.

    from openexp.canvas import canvas
    from openexp.keyboard import keyboard
    from random import choice
    
    # A list of pictures 
    pic_list = '1.png', '2.png', '3.png', '4.png', '5.png'
    duration = 1000
    
    # Prepare a keyboard object
    my_keyboard = keyboard(exp, timeout=duration)
    
    # Prepare a list of canvases. It is faster to prepare
    # these beforehand
    canvas_list = []
    for pic in pic_list:
        my_canvas = canvas(exp) 
        my_canvas.image(exp.get_file(pic))  
        canvas_list.append(my_canvas)
    
    # Keep showing randomly selected images
    while True:
        my_canvas = choice(canvas_list)
        my_canvas.show()    
        resp, time = my_keyboard.get_key()  
    
        # Until a key is pressed (i.e. a timeout did not occur)
        key = my_keyboard.to_chr(resp)  
        if key not in ['timeout', None]:
            break
    

    Cheers!

    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

Sign In or Register to comment.