Counterbalancing issues

PennController for IBEX Forums Support Counterbalancing issues

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #8083
    Mieke
    Participant

    Demonstration link to the experiment: https://farm.pcibex.net/r/DcVgRE/

    Hi Jeremy,

    I’m working on an experiment that involves the presentation of four images on each trial (which are presented on the screen with accompanying audio files, e.g., ‘here’s one cheetah’). These four pictures depict (1) the correct agent of the test sentence, (2) a foil agent, (3) the correct theme, and (4) a foil theme. The position in which these pictures appear on the screen vary: The agent-related pictures are always in the top two quadrants (but it differs whether the correct one is on the left or right), and the theme-related pictures are always in the bottom two quadrants (but again, it differs whether the correct one is on the left or right). This yields the following four possible displays:

    A. (clockwise from top-left): CorAgent, FoilAgent, CorTheme, FoilTheme
    B. (clockwise from top-left): FoilAgent, CorAgent, CorTheme, FoilTheme
    C. (clockwise from top-left): CorAgent, FoilAgent, FoilTheme, CorTheme
    D. (clockwise from top-left): FoilAgent, CorAgent, FoilTheme, CorTheme

    I would like to randomise order of these display configurations across trials: They all need to appear an equal number of times (balanced across filler sentences, of which there are 24, and target sentences, of which there are 12). I did this was by first defining a list that specifies the total number in which each display appears, which is then randomised:

    FillerDisplays = ["A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C", "D", "D", "D", "D", "D", "D"].sort(v=>Math.random()-Math.random());
    TargetDisplays = ["A", "A", "A", "B", "B", "B", "C", "C", "C", "D", "D", "D"].sort(v=>Math.random()-Math.random());

    Then, in each trial, I use two variables (nTarget and nFiller) to ‘loop’ over these lists and specify the display configuration (A, B, C, or D) in another variable (“Display”). This variable, in turn, is used to generate the displays, in the following way:

    
            getVar("Display").log()
            
                .test.is("A").success(
                // Display configuration 1 (clockwise from top-left): CorAgent,     FoilAgent,  CorTheme,   FoilTheme
                        newImage("Topleft_image", row.CorAgent)
                            .log()
                            .size("30vw", "30vh")
                            .print("center at 25%", "middle at 25%")
                        ,
                        newImage("Topright_image", row.FoilAgent)
                            .log()
                            .size("30vw", "30vh")   
                            .print("center at 75%", "middle at 25%")
                        ,
                        newImage("Bottomright_image", row.CorTheme)
                            .log()
                            .size("30vw", "30vh")   
                            .print("center at 75%", "middle at 75%")   
                        ,
                        newImage("Bottomleft_image", row.FoilTheme)
                            .log()
                            .size("30vw", "30vh")
                            .print("center at 25%", "middle at 75%") 
                        ,
                        newAudio("Topleft_audio", row.CorAgent_sound)
                        ,
                        newAudio("Topright_audio", row.FoilAgent_sound)
                        ,
                        newAudio("Bottomright_audio", row.CorTheme_sound)
                        ,
                        newAudio("Bottomleft_audio", row.FoilTheme_sound)
                        ,
                        newText("Display A") // <- for testing purposes only
                            .print()
                        )
    
                .test.is("B").success(
                // Display configuration 2 (clockwise from top-left): FoilAgent,    CorAgent,   CorTheme,   FoilTheme
                        newImage("Topleft_image", row.FoilAgent)
                            .log()
                            .size("30vw", "30vh")
                            .print("center at 25%", "middle at 25%")
                        ,
                        newImage("Topright_image", row.CorAgent)
                            .log()
                            .size("30vw", "30vh")   
                            .print("center at 75%", "middle at 25%")
                        ,
                        newImage("Bottomright_image", row.CorTheme)
                            .log()
                            .size("30vw", "30vh")   
                            .print("center at 75%", "middle at 75%")   
                        ,
                        newImage("Bottomleft_image", row.FoilTheme)
                            .log()
                            .size("30vw", "30vh")
                            .print("center at 25%", "middle at 75%") 
                        ,
                        newAudio("Topleft_audio", row.FoilAgent_sound)
                        ,
                        newAudio("Topright_audio", row.CorAgent_sound)
                        ,
                        newAudio("Bottomright_audio", row.CorTheme_sound)
                        ,
                        newAudio("Bottomleft_audio", row.FoilTheme_sound)
                        ,
                        newText("Display B") // <- for testing purposes only
                            .print()
                        )
    
                .test.is("C").success(
                // Display configuration 3 (clockwise from top-left): CorAgent,     FoilAgent,      FoilTheme,  CorTheme
                        newImage("Topleft_image", row.CorAgent)
                            .log()
                            .size("30vw", "30vh")
                            .print("center at 25%", "middle at 25%")
                        ,
                        newImage("Topright_image", row.FoilAgent)
                            .log()
                            .size("30vw", "30vh")   
                            .print("center at 75%", "middle at 25%")
                        ,
                        newImage("Bottomright_image", row.FoilTheme)
                            .log()
                            .size("30vw", "30vh")   
                            .print("center at 75%", "middle at 75%")   
                        ,
                        newImage("Bottomleft_image", row.CorTheme)
                            .log()
                            .size("30vw", "30vh")
                            .print("center at 25%", "middle at 75%") 
                        ,
                        newAudio("Topleft_audio", row.CorAgent_sound)
                        ,
                        newAudio("Topright_audio", row.FoilAgent_sound)
                        ,
                        newAudio("Bottomright_audio", row.FoilTheme_sound)
                        ,
                        newAudio("Bottomleft_audio", row.CorTheme_sound)
                        ,
                        newText("Display C") // <- for testing purposes only
                            .print()
                    )
    
                .test.is("D").success(
                // Display configuration 4 (clockwise from top-left): FoilAgent,    CorAgent,     FoilTheme, CorTheme
                    newImage("Topleft_image", row.FoilAgent)
                        .log()
                        .size("30vw", "30vh")
                        .print("center at 25%", "middle at 25%")
                    ,
                    newImage("Topright_image", row.CorAgent)
                        .log()
                        .size("30vw", "30vh")   
                        .print("center at 75%", "middle at 25%")
                    ,
                    newImage("Bottomright_image", row.FoilTheme)
                        .log()
                        .size("30vw", "30vh")   
                        .print("center at 75%", "middle at 75%")   
                    ,
                    newImage("Bottomleft_image", row.CorTheme)
                        .log()
                        .size("30vw", "30vh")
                        .print("center at 25%", "middle at 75%") 
                    ,
                    newAudio("Topleft_audio", row.FoilAgent_sound)
                    ,
                    newAudio("Topright_audio", row.CorAgent_sound)
                    ,
                    newAudio("Bottomright_audio", row.FoilTheme_sound)
                    ,
                    newAudio("Bottomleft_audio", row.CorTheme_sound)
                    ,
                    newText("Display D") // <- for testing purposes only
                        .print()
                    )

    However, I’ve been struggling a lot to get this to work. A previous version of this code worked, but then I must have done something to break it. In its current form, it can generate display A correctly, but not any of the others. However, it does print ‘Display B’, ‘Display C’ or ‘Display D’ on each trial, suggesting that the does correctly specify the Display variable. I must be missing something (potentially something stupid), but I’ve not been able to locate my mistake.

    By the way, as you can see in the demonstration link, I’ve left out quite some script. In the actual experiment, people need to drag the correct images onto the robot that is presented in the center of the screen, but in this testing script, I’ve commented the DragDrop element out.

    I’m curious if you have any idea about what’s going wrong!

    Best,
    Mieke

    • This topic was modified 2 years, 2 months ago by Mieke.
    • This topic was modified 2 years, 2 months ago by Mieke.
    • This topic was modified 2 years, 2 months ago by Mieke.
    #8088
    Jeremy
    Keymaster

    Hi Mieke,

    As reported in the Errors tab of the debugger, you are creating multiple Image elements with the same name, which causes problems when you refer back to them later (eg. getImage("Topleft_image").visible()). See explanations here

    Here is a possible solution, let me know if it works as you expect:

    FillerDisplays = ["A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C", "D", "D", "D", "D", "D", "D"];
    TargetDisplays = ["A", "A", "A", "B", "B", "B", "C", "C", "C", "D", "D", "D"];
    fisherYates(FillerDisplays)
    fisherYates(TargetDisplays)
    
    DisplayMap = {
        A: {TopLeft: "CorAgent", TopRight: "FoilAgent", BottomRight: "CorTheme", BottomLeft: "FoilTheme"},
        B: {TopLeft: "FoilAgent", TopRight: "CorAgent", BottomRight: "CorTheme", BottomLeft: "FoilTheme"},
        C: {TopLeft: "CorAgent", TopRight: "FoilAgent", BottomRight: "FoilTheme", BottomLeft: "CorTheme"},
        D: {TopLeft: "FoilAgent", TopRight: "CorAgent", BottomRight: "FoilTheme", BottomLeft: "CorTheme"}
    }
    
    Template("trials.csv",
        row => newTrial("Trials",
            defaultImage.hidden()
            ,
            newVar("dropped", 0)
            ,
            newFunction( ()=> $("body").css({width: '100vw',height: '100vh'}) ).call()
            ,
            getVar("nTrials")
                .log()
                .test.is(18)
                .success(
                    newHtml("HalfWay", "Halfway.html")
                        .center()
                        .cssContainer({"width":"720px"})
                        .print("center at 50%", "middle at 50%")
                    ,
                    newButton("continue", "Continue to the next trial")
                        .center()
                        .print("center at 50%", "middle at 80%")
                        .wait()
                    ,
                    fullscreen() 
                    ,
                    clear()
                )
            ,
            newFunction( ()=> $("body").css('cursor','none') ).call()
            ,
            newImage("Al", "Al.png")
                .size("15vw", "20vh")
                .print("center at 50%", "middle at 50%")
            ,
            newImage("Speaker", "speaker_green.png")
                .size("7vw", "7vw")
                .print("center at 50%", "middle at 50%")
            , 
            newAudio("TestSentence", row.TestSentence)
            ,
            displayGroup = (row.StimulusType=="Target"?TargetDisplays.pop():FillerDisplays.pop())
            ,
            defaultImage.log().size("30vw","30vh")
            ,
            newImage("Topleft_image", row[DisplayMap[displayGroup].TopLeft]).print("center at 25%", "middle at 25%")
            ,
            newImage("Topright_image", row[DisplayMap[displayGroup].TopRight]).print("center at 75%", "middle at 25%")
            ,
            newImage("Bottomright_image", row[DisplayMap[displayGroup].BottomRight]).print("center at 75%", "middle at 75%")
            ,
            newImage("Bottomleft_image", row[DisplayMap[displayGroup].BottomLeft]).print("center at 25%", "middle at 75%")
            ,
            newAudio("Topleft_audio", row[DisplayMap[displayGroup].TopLeft+"_sound"])
            ,
            newAudio("Topright_audio", row[DisplayMap[displayGroup].TopRight+"_sound"])
            ,
            newAudio("Bottomright_audio", row[DisplayMap[displayGroup].BottomRight+"_sound"])
            ,
            newAudio("Bottomleft_audio", row[DisplayMap[displayGroup].BottomLeft+"_sound"])
            ,
            newText("Display_"+displayGroup).print()
            ,    
            getImage("Al").visible()
            ,
            newAudio(IntroSentence[Math.floor(Math.random() * 3)]).play().log().wait()
            ,
            getImage("Topleft_image").visible()
            , 
            getAudio("Topleft_audio").play().log().wait()
            ,
            newTimer(300).start().wait()
            ,
            getImage("Topright_image").visible()
            ,
            getAudio("Topright_audio").play().log().wait()
            ,
            newTimer(300).start().wait()
            ,
            getImage("Bottomright_image").visible()
            ,
            getAudio("Bottomright_audio").play().log().wait()
            ,
            newTimer(300).start().wait()
            ,
            getImage("Bottomleft_image").visible()
            ,
            newAudio(And[Math.floor(Math.random() * 12)]).play().log().wait()
            ,
            getAudio("Bottomleft_audio").play().log().wait()
            ,
            newTimer(500).start().wait()
            ,
            getImage("Al").hidden()
            ,
            newTimer(200).start().wait()
            ,
            getImage("Speaker").visible().log()
            ,
            getAudio("TestSentence").play().log().wait()
            ,
            newTimer(200).start().wait()
            ,
            getImage("Speaker").hidden().log()
            ,
            getImage("Al").visible().log()
            ,
            newKey(" ").wait()
            ,
            clear()
            ,
            getVar("nTrials").set( v => v+1) // increase nTrials
        )
        .log("Quantifier", row.Quantifier)  
        .log("Version", row.Version)  
        .log("Item", row.Item)  
        .log("StimulusType", row.StimulusType)  
        .log("Group", row.Group)  
        .log("Sentence", row.Sentence)  
        .log("Verb", row.Verb)  
        .log("CorAgent", row.CorAgent)  
        .log("FoilAgent",row.FoilAgent)   
        .log("CorTheme",row.CorTheme)    
        .log("FoilTheme",row.FoilTheme)   
        .log("TestSentence",row.TestSentence)   
        .log("CorAgent_sound",row.CorAgent_sound)  
        .log("FoilAgent_sound",row.FoilAgent_sound) 
        .log("CorTheme_sound",row.CorTheme_sound)
        .log("FoilTheme_sound",row.FoilTheme_sound)
        .log("DisplayGroup", displayGroup)
    )

    Jeremy

    #8194
    MiekeS
    Participant

    Hey Jeremy,

    My apologies for replying a month later! This fix worked perfectly, thank you again for your great help 🙂

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.