Conditional Randomization

PennController for IBEX Forums Support Conditional Randomization

This topic contains 7 replies, has 2 voices, and was last updated by Avatar leaena 4 weeks, 1 day ago.

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #4105
    Avatar
    leaena
    Participant

    Hi Jeremy,

    We are wondering about conditional randomization for template items. For instance, would it be possible to randomize everything but never have a given condition follow a specific other condition? Is there any such thing in the works? I don’t know how difficult that would be so I just figured I’d ask, since it would be handy to have.

    Thank you!
    Leo

    #4106
    Jeremy
    Jeremy
    Keymaster

    Hi Leo,

    Playing with the order of trials is probably Ibex’s least handy aspect. If you look up Ibex’s documentation manual, you’ll see that the function rshuffle in part does what you want: it makes sure that specifically labeled trials are evenly spaced. Say you have 6 trials in your experiment, two labeled typeA, two labeled typeB and two labeled typeB. Using PennController.Sequence( rshuffle("typeA", "typeB", "typeC") ) will give you one of these six possible patterns:

    • typeA, typeB, typeC, typeA, typeB, typeC
    • typeA, typeC, typeB, typeA, typeC, typeB
    • typeB, typeA, typeC, typeB, typeA, typeC
    • typeB, typeC, typeA, typeB, typeC, typeA
    • typeC, typeA, typeB, typeC, typeA, typeB
    • typeC, typeB, typeA, typeC, typeB, typeA

    I understand your request to be slightly different though. You don’t necessarily want to define a specific pattern that should repeat itself, you would be okay with having C, B, A in the first block and A, B, C in the second block as long as, say, no C follows an A directly. Am I right3

    One of the problems with implementing a general solution to such a request is that, depending on how many trials you have per label, what you ask may or may not be feasible. So you need to make sure, as the designer, that your set of trials are labeled in a way that makes it possible to create a sequence with the desired properties. Then you could define this function at the top of your script:

    function RandomizeExcludeSequence(ar, type1, type2) {
      this.args = ar;
    
      this.run = function(arrays) {
          let sequence = arrays[0];
          let shuffle = true;
          while (shuffle){
            shuffle = false;
            fisherYates(sequence);
            let prev = "", next = "";
            for (let i = 0; i < sequence.length; i++){
              if (i>0) prev = sequence[i-1][0].type;
              next = sequence[i][0].type;
              if (prev==type1&&next==type2){
                shuffle = true;
                break;
              }
            }
          }
          return sequence;
      }
    }
    function randomizeExcludeSequence(ar, type1, type2) { return new RandomizeExcludeSequence([ar], type1, type2); }

    and use it like this:

    PennController.Sequence( randomizeExcludeSequence( anyOf("typeA", "typeB", "typeC") , "typeA", "typeC" ) )
    
    PennController("typeA", newButton("typeA i").print().wait() )
    PennController("typeA", newButton("typeA ii").print().wait() )
    PennController("typeB", newButton("typeB i").print().wait() )
    PennController("typeB", newButton("typeB ii").print().wait() )
    PennController("typeC", newButton("typeC i").print().wait() )
    PennController("typeC", newButton("typeC ii").print().wait() )

    This generates any random sequence using all the trials labeled typeA, typeB or typeC that does not contain any pair of trials successively labeled typeA then typeC.

    Jeremy

    #4107
    Avatar
    leaena
    Participant

    Hi Jeremy,

    Thank you for this information!

    I am confused about the code you provided, though.
    What are the buttons for?
    What do the i and ii indicate?
    How would we integrate this with a template? If the .csv file contains rows in which the conditions are typeA, typeB, and typeC, for instance? Where in this code does the template go? Or would we have to read in all of the types separately with separate templates?

    Would this be a thing that would be labeled and then called in the normal ibex ShuffleSequence?
    e.g. something like:
    PennController.Sequence( randomizeExcludeSequence( anyOf(“typeA”, “typeB”, “typeC”) , “typeA”, “typeC” ) ).label(“allitems”)
    where the ShuffleSequence goes seq(“instructions”, “practice”, “allitems”, “end_experiment”) or something?

    Best,
    Leo

    #4108
    Jeremy
    Jeremy
    Keymaster

    My “use it like this” code is just a standard PennController example, with dummy one-button trials. I just use ‘i’ and ‘ii’ so you can identify the trial from the buttons’ text when you take the experiment.

    Using a template shouldn’t make a difference: just label your template-generated trials consistently with your definition of the sequence of trials (see the other post on how to label template-generated trials—the simplest solution is to have a Label column in your table).

    The command PennController.Sequence is just the standard PennController way of defining the sequence of trials, it replaces and standardizes the more obscure var shuffleSequence = native-Ibex method. You cannot use .label on it since it’s not used to create trials, but just order the ones defined elsewhere in your script, based on their labels.

    Jeremy

    #4109
    Avatar
    leaena
    Participant

    Thank you, Jeremy! I will see what I can make of this. (But may well have more questions later.)

    Best,
    Leo

    #4110
    Avatar
    leaena
    Participant

    Hi Jeremy,

    This code does seem to work, or at least, I have it working here: http://spellout.net/ibexexps/leaena/test/experiment.html
    However, the way that I understand to implement it is to copy the template and make one template for each type (a, b, c and d in my case). If I just have one template and name it “items” or something, PennController.Sequence does not find things named A or B or C or D and so it thinks there is nothing in the running order. However, when I copy the template 4 times, even though I use .filter() with each one so that it should only apply to one of the types, it repeats all of the items …twice? I am not sure if I’m doing something wrong or if it is not working the way it is supposed to. Probably the first. :]

    Advice would be appreciated!
    Best,
    Leo

    #4111
    Jeremy
    Jeremy
    Keymaster

    Hi Leo,

    Since your example uses the exact same template for all your trials, I would simply call Template once, like this:

    PennController.Template( "items.csv" ,
        item => PennController(
            newButton("thisTrialButton", item.text)
              .print()
              .wait()
        )
    )

    No need to explicitly label your trials, since your table already contains a Label column.

    #4112
    Avatar
    leaena
    Participant

    I’m not sure what I was doing wrong, since I thought I had tried that already, but it works! Thank you so very much!

    Best,
    Leo

Viewing 8 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.