Sub-experiments with different number of conditions

PennController for IBEX Forums Support Sub-experiments with different number of conditions

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

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #5234
    Avatar
    angelica
    Participant

    Hi Jeremy,

    Is there a way to counterbalance sub-experiments that have a different number of conditions? I have one experiment (SC) with 4 conditions (A, B, C, D), and one experiment (Rep) with 2 conditions (1, 2). I’d like one participant to see items from SC-A and Rep-1; the next participant to see SC-B and Rep-2; the next to see SC-C and Rep-1; the next to see SC-D and Rep-2; and so on.

    My workaround is to name the “group” variable for the Rep spreadsheet to “AC” and “BD”, and use GetTable.filter() with a regular expression.

    PennController.ResetPrefix(null);                       // Initiates PennController
    var showProgressBar = false;                            // Don't show progress bar
    
    Sequence(shuffle(randomize("test_sc_items"), randomize("test_rep_items")))
    
    // Trial item template 
    customTrial = label => variable => newTrial( label ,
        defaultText
            .center()
            .cssContainer({"width": "350px"})
        ,
        // Display target word 
        newText("listen_for", "Listen for:")
            .italic()
        ,
        newText("target_word", variable.target)
            .css({"font-size": "200%"})        
        ,
        newText("next", "Press the spacebar to continue.")
            .italic()
        ,
        newCanvas(350, 300)
            .add(0, 100, getText("listen_for"))
            .add(0, 150, getText("target_word"))
            .add(0, 225, getText("next"))
            .print()
        ,
        newKey(" ")
            .wait()
        ,
        clear()
        ,
        // Play audio stimulus and record reaction time
        newImage("fixation_cross", "fixation_cross.png")
            .size(300, 300)
        ,
        newCanvas(300, 300)
            .add(0, 25, getImage("fixation_cross"))
            .print()
        ,
        newKey("reaction_time", " ")          
            .log("all")                         
        ,
        newAudio("stimulus", variable.stimulus)
            .play()
            .wait() 
        ,
    	clear()
    )
    .log("group",               variable.group)
    .log("item",                variable.item)
    .log("condition",           variable.condition)
    .log("target",              variable.target)
    
    AddTable("test_rep",
    	"group,item,condition,stimulus,target\n"+
    	"AC,1,ambig,Rep_Ambig_1.wav,WATCH\n"+
    	"BD,1,unambig,Rep_Unambig_1.wav,SCARF\n"+
    	"BD,2,ambig,Rep_Ambig_2.wav,FINISH\n"+
    	"AC,2,unambig,Rep_Unambig_2.wav,CONCLUSION\n"+
    	"AC,3,ambig,Rep_Ambig_3.wav,GLARE\n"+
    	"BD,3,unambig,Rep_Unambig_3.wav,LIGHT\n"+
    	"BD,4,ambig,Rep_Ambig_4.wav,DRILL\n"+
    	"AC,4,unambig,Rep_Unambig_4.wav,REHEARSAL"
    )
    
    AddTable("test_sc",
    	"group,item,condition,stimulus,target\n"+
    	"A,1,Clash.NoShift,SC_Clash_NoShift_1.wav,MEN\n"+
    	"B,1,Clash.Shift,SC_Clash_Shift_1.wav,MEN\n"+
    	"C,1,NoClash.NoShift,SC_NoClash_NoShift_1.wav,MEN\n"+
    	"D,1,NoClash.Shift,SC_NoClash_Shift_1.wav,MEN\n"+
    	"B,2,Clash.NoShift,SC_Clash_NoShift_2.wav,GUEST\n"+
    	"C,2,Clash.Shift,SC_Clash_Shift_2.wav,GUEST\n"+
    	"A,2,NoClash.NoShift,SC_NoClash_NoShift_2.wav,GUEST\n"+
    	"D,2,NoClash.Shift,SC_NoClash_Shift_2.wav,GUEST\n"+
    	"C,3,Clash.NoShift,SC_Clash_NoShift_3.wav,BOSS\n"+
    	"D,3,Clash.Shift,SC_Clash_Shift_3.wav,BOSS\n"+
    	"B,3,NoClash.NoShift,SC_NoClash_NoShift_3.wav,BOSS\n"+
    	"A,3,NoClash.Shift,SC_NoClash_Shift_3.wav,BOSS\n"+
    	"D,4,Clash.NoShift,SC_Clash_NoShift_4.wav,DOGS\n"+
    	"A,4,Clash.Shift,SC_Clash_Shift_4.wav,DOGS\n"+
    	"C,4,NoClash.NoShift,SC_NoClash_NoShift_4.wav,DOGS\n"+
    	"B,4,NoClash.Shift,SC_NoClash_Shift_4.wav,DOGS"
    )
    
    // Experimental items    
    Template(
        GetTable("test_sc")
            .filter("group", /A/)
        , 
        customTrial("test_sc_items"))
        
    Template(
        GetTable("test_rep")
            .filter("group", /A/)
        , 
        customTrial("test_rep_items"))

    I like that I can specify a specific group to be run (I can run participants in batches and change the group in between batches), but I was wondering if there’s a way to create something like a regular expression variable (in case I add more sub-experiments), or if there’s a different, better way in general.

    Something like

    newVar("grouping", RegExp(/A/))
    
    Template(
        GetTable("test_sc")
            .filter("group", getVar("grouping"))
        , 
        customTrial("test_sc_items"))
        
    Template(
        GetTable("test_rep")
            .filter("group", getVar("grouping"))
        , 
        customTrial("test_rep_items"))

    Best,
    Angelica

    #5237
    Jeremy
    Jeremy
    Keymaster

    Hi Angelica,

    That’s a smart solution! Though I reckon it would be best if there was a straightforward way of crossing the groups from the different tables. Your solution is probably optimal at the moment.

    You can pass the group letter directly in the URL (eg. https://expt.pcibex.net/ibexexps/example/example/experiment.html?group=A) and retrieve it with GetURLParameter, like this:

    Template(
        GetTable("test_sc")
            .filter( "group" , new RegExp(GetURLParameter("group")) )
        , 
        customTrial("test_sc_items")
    )
        
    Template(
        GetTable("test_rep")
            .filter( "group" , new RegExp(GetURLParameter("group")) )
        , 
        customTrial("test_rep_items")
    )

    EDIT: do you ever want a participant to see SC-A + Rep-2? If not, I’m not sure you even need any of this: PennController cycles through the groups independently from one table to the other, so SC-A (=0) and SC-C (=2) should always be paired with Rep-1 (=0), and SC-B (=1) and SC-D (=3) with Rep-2 (=1), because 2 mod 2 = 0 and 3 mod 2 = 1.

    Example:

    AddTable("firstTable", `group,item,Text
    A,1,Item 1 Group A
    B,1,Group B Item 1
    C,1,item 1 group C
    D,1,group D item 1
    B,1,Item 2 Group B
    C,1,Group C Item 2
    D,1,item 2 group D
    A,1,group A item 2`)
    
    AddTable("secondTable", `group,item,Text
    a,1,Item-Group: 1-a
    b,1,Group-Item: b-1
    b,2,Item-Group: 2-b
    a,2,Group-Item: 2-a`)
    
    SetCounter()
    
    Template( "firstTable",  row => newTrial( newText("first table").print(),newButton(row.Text).print().wait() ) )
    Template( "secondTable",  row => newTrial( newText("second table").print(),newButton(row.Text).print().wait() ) )

    Jeremy

    • This reply was modified 2 weeks, 2 days ago by Jeremy Jeremy.
    #5258
    Avatar
    angelica
    Participant

    Hi Jeremy,

    Passing the group letter in the URL is a good idea, thank you for pointing it out. And I didn’t realize the PennController built-in grouping would work that way, so that’s good to know. Thanks again!

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

You must be logged in to reply to this topic.