Howdy, Stranger!

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

Supported by

[open] "nested lists" functionality

edited March 2014 in OpenSesame

Hi there,

I'm teaching an Experimental Psychology course during which I teach students how to design experiments. I've been using E-Prime so far but switched to OpenSesame for this semester. Everything goes great except that I can't find how to implement something like the "nested lists" functionality that E-Prime offers. Here's an example of what I need: let's say I have a visual search experiment with a number of fixed positions on the screen that I would like to fill out randomly with one target (e.g., a T) and many distractors (e.g., L's). In E-Prime I would create a nested list with the T and a number of L's and then have the main list sample them randomly from the nested list. I don't seem to find a way to do this with OpenSesame. Any help?

Thanks,
marios

Comments

  • edited 2:43PM

    Hi Marios,

    That's an interesting question. Could you give a concrete example of when a nested list is necessary/ really convenient? It might be interesting to implement something similar for OpenSesame.

    At any rate, there is no direct analogue of a nested list in OpenSesame, but you can mimic the behavior with a little Python script. Let's assume that you have two loop items, loop1 and loop2, each of which defines respectively var1 and var2. What you can do is extract the columns var1 and var2 from the two loops and save them as a list, like so:

    from random import shuffle
    
    # Extract the column `var1` from the loop item `loop1` and save it as a list
    # as self.experiment.list1 (self.experiment == exp).
    loop1 = exp.items['loop1']
    exp.list1 = []
    for i in sorted(loop1.matrix):
        val = loop1.matrix[i]['var1']
        exp.list1.append(val)
    # Shuffle the list1, so that we will pop the items from it in a random order.
    shuffle(list1)
    
    
    # Extract the column `var2` from the loop item `loop2` and save it as a list
    # as self.experiment.list2 (self.experiment == exp).
    loop2 = exp.items['loop2']
    exp.list2 = []
    for i in sorted(loop2.matrix):
        val = loop2.matrix[i]['var2']
        exp.list2.append(val)
    # Reverse the list. This is necessary because we will `pop` from the list, which
    # means we start with the last item.
    list2.reverse()
    

    In a third loop, you can then use a Python statement in the loop table to pop values from this list (i.e. to take and remove the last value from the list), like so:

    =self.experiment.list1.pop()
    

    and

    =self.experiment.list2.pop()
    

    For a small functional example, see also:

    I've been using E-Prime so far but switched to OpenSesame for this semester.

    Great! >:D<

    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 2:43PM

    Hi Sebastiaan, thanks for your response. I was hoping that there was a way to do this without code. I'm using Python myself but for the class I teach I prefer to stick to the basics. So, may I suggest this as a possible feature for the future?
    In essence, nested lists in E-Prime allow you to assign values to variables (attributes in E-Prime lingo) using other attributes. A simple example is this: I have 3 positions on the screen (let's name them pos1, pos2, and pos3 ) at which I want to present 3 stimuli (let's call them stim1, stim2, stim3) but select randomly on each trial which stimulus goes to which position. In E-Prime I would have in the main list (the same as an openSesame loop) 3 columns named pos1, pos2, and pos3 and in a nested list a single column (let's call it stimulus) with three rows, one for each stimulus (stim1, stim2, stim3). Then, the value assigned to each of the three positions of the main list would be set by drawing at random a row from the stimulus variable in the nested list. Hope this makes sense! In my opinion, this is a fantastic feature to have as it allows people to create experiments with fairly complex randomizations without touching code at all (...which is perfect for psychology students) :)

  • edited March 2014

    Wouldn't it be a solution to nest a loop in a way that does go with the OpenSesame interface:

     loop 1
    ---- loop 2
    -------- trial_sequence
    

    Where loop 1 is the loop in which you define everything apart from the stimulus position. In loop 2, you add three variables: pos1, pos2, and pos3. Now add cycles: one for each possible configuration of positions. Then set the order to random, and the number of cycles to run to 1.

    Example in script:

    # Generated by OpenSesame 2.8.0 (Gutsy Gibson)
    # Wed Mar  5 17:19:09 2014 (posix)
    # 
    
    set foreground "white"
    set subject_parity "even"
    set description "Default description"
    set title "New experiment"
    set compensation "0"
    set coordinates "relative"
    set height "768"
    set mouse_backend "xpyriment"
    set width "1024"
    set sampler_backend "legacy"
    set keyboard_backend "legacy"
    set background "black"
    set subject_nr "0"
    set canvas_backend "xpyriment"
    set start "experiment"
    set synth_backend "legacy"
    
    define sequence sequence
        run sketchpad "always"
    
    define sketchpad welcome
        set duration "keypress"
        set start_response_interval "no"
        set description "Displays stimuli"
        draw textline 0 0 "OpenSesame 2.8.0 Gutsy Gibson" center=1 color=white font_family="serif" font_size=32 font_italic=no font_bold=no show_if="always" html="yes"
    
    define sketchpad sketchpad
        set duration "keypress"
        set description "Displays stimuli"
        draw fixdot [pos1] 0 color=[stim1col] show_if="always"
        draw fixdot [pos2] 0 color=[stim2col] show_if="always"
        draw fixdot [pos3] 0 color=[stim3col] show_if="always"
    
    define sequence experiment
        run welcome "always"
        run loop1 "always"
    
    define loop loop2
        set repeat "0.12"
        set description "Repeatedly runs another item"
        set item "sequence"
        set column_order "pos2;pos3;pos1"
        set cycles "9"
        set order "random"
        setcycle 0 pos2 "0"
        setcycle 0 pos3 "300"
        setcycle 0 pos1 "-300"
        setcycle 1 pos2 "0"
        setcycle 1 pos3 "300"
        setcycle 1 pos1 "-300"
        setcycle 2 pos2 "0"
        setcycle 2 pos3 "300"
        setcycle 2 pos1 "-300"
        setcycle 3 pos2 "300"
        setcycle 3 pos3 "-300"
        setcycle 3 pos1 "0"
        setcycle 4 pos2 "300"
        setcycle 4 pos3 "-300"
        setcycle 4 pos1 "0"
        setcycle 5 pos2 "300"
        setcycle 5 pos3 "-300"
        setcycle 5 pos1 "0"
        setcycle 6 pos2 "-300"
        setcycle 6 pos3 "0"
        setcycle 6 pos1 "300"
        setcycle 7 pos2 "-300"
        setcycle 7 pos3 "0"
        setcycle 7 pos1 "300"
        setcycle 8 pos2 "-300"
        setcycle 8 pos3 "0"
        setcycle 8 pos1 "300"
        run sequence
    
    define loop loop1
        set repeat "1"
        set description "Repeatedly runs another item"
        set item "loop2"
        set column_order "stim1col;stim2col;stim3col"
        set cycles "5"
        set order "random"
        setcycle 0 stim3col "white"
        setcycle 0 stim1col "green"
        setcycle 0 stim2col "red"
        setcycle 1 stim3col "white"
        setcycle 1 stim1col "green"
        setcycle 1 stim2col "red"
        setcycle 2 stim3col "white"
        setcycle 2 stim1col "green"
        setcycle 2 stim2col "red"
        setcycle 3 stim3col "white"
        setcycle 3 stim1col "green"
        setcycle 3 stim2col "red"
        setcycle 4 stim3col "white"
        setcycle 4 stim1col "green"
        setcycle 4 stim2col "red"
        run loop2
    
  • edited 2:43PM

    Hi Edwin. Thank you very much for your input....I really appreciate it. I followed your suggestion, and although it took me a while to figure out how to have a loop run a second loop that runs a sequence, when I managed to do it everything worked fine. However, the whole idea is to avoid writing all the possible configurations in loop 2. It's pretty easy to do when you have 3 positions and 3 colors, but what about in a visual search experiment in which one may have 60-70 positions on the screen and assign a target to only one position, distractors to many others, and leave others empty? Also, ideally I would want to have multiple nested loops (attached to the main loop) and run one of them depending on a value on the main loop. In the example of the visual search, I would want to run target absent and target present trials. It would have been nice if I could have a variable in the main loop coding whether the trial is target is absent or present and depending on the value run a different nested loop. Is this possible by any chance? In the experiment I prepared based on your suggestion I have a "run if" for the main loop in the experiment sequence but how can I control whether the nested loops are run?
    marios

  • edited March 2014

    In essence, your comment boils down to two things: (1) how to run multiple nested loops based on a value in the main loop, and (2) how to use nested loop functionality without having to do a lot of typing.

    (1) multiple nested loops

    You could nest a number of subloops in the sequence of a single main loop. Each of the subloops run the same single trial sequence, and contain the same variables, but use different values for each. The idea is shown in the following three images.

    image

    figure 1 - multiple nested loops

    image

    figure 2 - the main sequence's contents; note the loop2run variable, which determines which subloop should be used

    image

    figure 3 - using the Run If statements and a variable from the main loop to run the subloops

    image

    figure 4 - this is how a subloop looks like; note the amount of cycles being run: it's set to one ninth, as there are nine possible stimulus configurations defined and only one of those should be run in a trial

    (2) nested loops without the typing

    Have you tried using the variable wizard? You can use the tool by clicking the Variable Wizard button in a loop. You can define all possible individual values per variable, and it will automatically create a full loop, containing all possible combinations of the values of each variable.

    Otherwise, I don't see any other option than coding. Would you care to elaborate a bit on how E-Prime's nested loop handles this? I seem to recall it requiring a lot of typing as well, as it did require a fully filled out list, did it not?

    Thanks!

  • edited 2:43PM

    Hi
    I had similar need for nested function similar to that of e-prime.
    It is actually possible to do it here too:

    First, after the main loop you should include a sub-loop to run from the main loop.
    In the main loop you can define a column with variables (by writing them inside [ ] ).
    For example, if you want the letter you are presenting to differ independently of other variables, in the main loop, create a column called "LetterType" and the values will be [Letter] in all the lines.

    In the sub-loop, created a variable called "Letter" and the values will be all the letters you wish to present.

    The trial sequence will follow the sub-loop (will run as an item of the sub-loop)

    Hope that helps...

  • edited 2:43PM

    Signed in after a long time to see what's new (yeah..back to teaching after a sabbatical) and saw this reply. This is awesome!! It was the one thing that I thought was missing from Opensesame and I'm so glad that I was wrong!! :) Thanks for letting us know.
    marios

  • edited 2:43PM

    Getting back to this after a long time (i.e., teaching OpenSesame this semester) and I have a quick related question (or suggestion for future update). Let's say I want to run 5 trials that will randomly present a letter on the screen at a predefined position. I created one loop with variable "position1" and filled up 5 rows with [letter] and a subloop with "letter" as the variable. In the subloop I added 5 rows, put 5 different letters in, and set each cycle to run .20 times. Works great. Now, let's say I want to present 2 different letters at 2 predefined positions. I can add "position2" in the main loop but is there a way to grab a second value from the "letter" variable of the subloop as opposed to adding a "letter2" variable? In E-Prime, you can say [letter:0], [letter:1] etc to grab a first, second etc value from the same nested variable....is there something similar in OS? I have my students design a visual search experiment with many predefined positions and something like this could save much typing time. And it's too early for them to get into code.
    Cheers,
    marios

  • edited 2:43PM

    Hi Marios,

    Not really, or at least not in a way that is simple enough to be useful for teaching. For 3.1, I'm actually working on a large update to the loop item though. This will implement a lot of functionality that is often requested (notably pseudorandomisation and nested loops) + a lot more. But this release is still some time off.

    Here's a question for you, regarding nested loops: Say that you have a loop table with two columns: word and position:

    word  position
    cat   left
    dog   right
    

    And say that you could shuffle the order these two column independently of each other, so that sometimes 'cat' would be paried with 'left', and sometimes with 'right'. Wouldn't this solve the same problem as nested loops--but more elegantly? Or are there cases in which this wouldn't do the trick?

    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 2:43PM

    Hi Sebastian, thanks for your response. Glad to hear that more cool stuff are coming our way with 3.1 :) What you are describing will be a useful feature, especially if you can add some weights in the pairing. For example, if "cat" can be paired let's say 5 times out of 6 with "left" and the remaining one with "right". But, I'm still not sure if this can achieve the scenario I described in my earlier post. If we stick to a visual search paradigm, think of a display with 20 items, one of which is the target. In E-Prime style, you would add 20 variable names in a loop indicating the possible positions in the display. In a nested loop you would have a single variable with 20 values (e.g., one T and 19 L) and all these values would randomly fill the variables in the main loop. Basically, the functionality that is needed is to be able to choose more than one value from a variable in a subloop.
    Cheers,
    marios

  • edited 2:43PM

    Hi Marios,

    I'm not familiar with this design pattern. Could you make it a bit more concrete for me? What I understand is that you have a nested loop (A) with one column and several (say 3) rows:

    stim
    ----
    T
    T
    L
    

    And you then have another loop (B) in which you take the three rows from loop A to fill three columns of a single row in loop B. Like so:

    stim1 stim2 stim3
    ----- ----- -----
    T     T     L    
    

    And you then use loop B to determine where the stimuli appear. Do I understand that correctly?

    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 2:43PM

    Hey Sebastian, you understood it perfectly :) I paste below two screenshots to show how this is implemented in E-Prime. Basically, you have a main List (Loop in OS) with the three variable names (first pic) and you pick their values on each trial from a nested List (second pic). You can even specify a different nested list for each trial which is handy if you want to have let's say target present and target absent trial. In my example, listb has T, T, and L as possible values while listc has 3 T's. And they both hava a variable with the same name (i.e. stim)

    image

    image

  • I just implemented this, and it seems to work fine. However, I noticed in the output that it is not the case that it applies all rows from the subloop in random order, which would mean every row would occur only once in the output. Rather, it repeatedly picks a row from the subloop randomly, leaving some unlucky rows feeling left out.

    Is there a way of ensuring that each row from the subloop occurs only once in the output, so that every row is included?

  • edited February 2018

    .

  • Hi JasperdeWaadrd,

    I found the same problem that you proposed above, that is, the main list picks a row from the subloop randomly, leaving some rows not being displayed. I created the experiment with E-prime 3. 0 and was wondering do you know how to fix this problem up?

    I am looking forward to hearing from you.

    Thanks

    Yanping

Sign In or Register to comment.