Matching Participants on Race/Gender?

PennController for IBEX Forums Support Matching Participants on Race/Gender?

This topic contains 7 replies, has 2 voices, and was last updated by Jeremy Jeremy 3 weeks, 3 days ago.

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

    Hello,

    I am trying to create a task where the participant sees stimuli (picture of a person) that is the same race/gender as they are. Right now, I have it set up so that in the welcome screen, participants select what race/gender they are from a dropdown menu which is then saved as a variable. Then, I’m planning on using groups in my .csv to indicate which trials should be used for specific race/gender combos. Then, I was going to use GetTable(). filter to make sure that the experiment is running the grouped trials that match the given race/gender. However, I can’t figure out what line of code would need to go into .filter(). Here is what I have so far:

    newTrial("ParticipantID",
        newText("<p>Welcome and thank you for helping us!</p>")
           .center()
           .print()
        ,
        newText("<p>Please select your race and sex. Then, please enter your ID in the box below. You can find your ID XXX, and then press enter.</p>")
            .center()
            .print()
        ,
        newDropDown("race", "Please select the race that best describes you.")
            .add("Black or African American", "Asian or Pacific Islander", "White", "Hispanic or Latinx", "Other")
            .center()
            .print()
        ,
        newDropDown("sex", "Please select the sex that best describes you.")
            .add("Female", "Male")
            .center()
            .print()
        ,
        getDropDown("race")
            .wait()
        ,
        getDropDown("sex")
            .wait()
        ,
         newTextInput("inputID")
            .center()
            .print()
            .wait()
        ,
         newVar("ID")
            .global()
            .set(getTextInput("inputID"))
        ,
        newVar("race")
            .global()
            .set(getDropDown("race"))
        ,
        newVar("sex")
            .global()
            .set(getDropDown("sex"))
    )
    
    .log("ID",  getVar("ID"))
    .log("race", getVar("race"))
    .log("sex", getVar("sex"))
    
    ...
    
    Template(
        GetTable ("practicedatasource.csv")
            .filter("Group", getVar(XXXXXX)
        ,
        variable => newTrial("practicesequence",
            newImage("fixation.jpg")
                .center()
                .print()
            ,
            newAudio(variable.AudioFile)
                .play()
                .wait()

    The bolded part is where I’m stuck. Any help would be appreciated.

    Thanks!
    Callie

    #5569
    Jeremy
    Jeremy
    Keymaster

    Hello Callie,

    All the trials are generated at the very beginning of the experiment, along with the trial sequence, so you will not be able to dynamically select which trials to run the way you are trying to do here.

    What I can suggest is a two-step design; it’s not ideal but it works well. The idea is to re-open the experiment after you participants have filled the initial form, but this time with the values they typed as parameters in the URL.

    I will be assuming a table with a column race and a column sex that list the values in your experiment. For the sake of illustration, I used this command:

    AddTable("practicedatasource.csv", `item,race,sex,sentence
    1,Black or African American,Female,Sentence 1 for Black or African American Female
    1,Asian or Pacific Islander,Female,Sentence 1 for Asian or Pacific Islander Female
    1,Hispanic or Latinx,Female,Sentence 1 for Hispanic or Latinx Female
    1,Other,Female,Sentence 1 for Other Female
    1,Black or African American,Male,Sentence 1 for Black or African American Male
    1,Asian or Pacific Islander,Male,Sentence 1 for Asian or Pacific Islander Male
    1,Hispanic or Latinx,Male,Sentence 1 for Hispanic or Latinx Male
    1,Other,Male,Sentence 1 for Other Male
    2,Black or African American,Female,Sentence 2 for Black or African American Female
    2,Asian or Pacific Islander,Female,Sentence 2 for Asian or Pacific Islander Female
    2,Hispanic or Latinx,Female,Sentence 2 for Hispanic or Latinx Female
    2,Other,Female,Sentence 2 for Other Female
    2,Black or African American,Male,Sentence 2 for Black or African American Male
    2,Asian or Pacific Islander,Male,Sentence 2 for Asian or Pacific Islander Male
    2,Hispanic or Latinx,Male,Sentence 2 for Hispanic or Latinx Male
    2,Other,Male,Sentence 2 for Other Male`)

    Then you need to define your welcome-screen-form trial to run just in case the URL does not provide you with the demographic information:

    if (!GetURLParameter("id")||!GetURLParameter("race")||!GetURLParameter("sex")){
        
        newTrial("ParticipantID",
            defaultText.center(),defaultDropDown.center()
            ,
            newText("<p>Welcome and thank you for helping us!</p>").print()
            ,
            newText("<p>Please select your race and sex. Then, please enter your ID in the box below. "+
                    "You can find your ID XXX, and then press enter.</p>")
                .print()
            ,
            newDropDown("race", "Please select the race that best describes you.")
                .add("Black or African American", "Asian or Pacific Islander", "White", "Hispanic or Latinx", "Other")
                .print()
                .wait()
            ,
            newDropDown("sex", "Please select the sex that best describes you.")
                .add("Female", "Male")
                .print()
                .wait()
            ,
            newTextInput("inputID").center().print().wait()
            ,
            newFunction( ()=>window.open("server.py?"+
                "race="+getDropDown("race").value+"&"+
                "sex="+getDropDown("sex").value+"&"+
                "id="+getTextInput("inputID").value
            ) ).call()
        )
        
        SendResults()
        
        newTrial("end", newText("Another window opened, you can now close this one.").print() , newButton().wait() )
        
    }

    And then define the experimental trials to run upon opening the experiment’s page with the values passed as URL parameters:

    if (GetURLParameter("id") && GetURLParameter("race") && GetURLParameter("sex")){
        
        race = decodeURI(GetURLParameter("race"))
        sex = decodeURI(GetURLParameter("sex"))
        
        Sequence("practicesequence","etc")
        
        Template(
            GetTable("practicedatasource.csv")
                .filter("race", race)
                .filter("sex", sex)
            ,
            row => newTrial( "practicesequence" ,
                newText(row.sentence).print()
                ,
                newButton("Next").print().wait()
            )
            .log( "ID" , GetURLParameter("id") )
            .log( "race" , race )
            .log( "sex" , sex )
        )
        
    }

    Feel free to create two separate script files for each of these to keep your code cleaner

    Jeremy

    #5623
    Avatar
    caljones
    Participant

    Hi Jeremy,
    I’ve added this code, but when I test it the new window opens with a url like this one: https://expt.pcibex.net/ibexexps/caljones/Avatar/server.py?race=Please%20select%20the%20race%20that%20best%20describes%20you.&sex=Please%20select%20the%20sex%20that%20best%20describes%20you.&id=asdf

    It seems like, despite selecting a race/sex, the URL is taking the text of the question rather than the selected dropdown. This results in a 400 Bad Request error when the new window opens. Any ideas on what might be causing this and how to fix it?

    Thanks,
    Callie

    #5624
    Jeremy
    Jeremy
    Keymaster

    Hi Callie,

    Update your version of PennContoller to 1.8 following this method

    Jeremy

    #5635
    Avatar
    caljones
    Participant

    Hi Jeremy,

    Thanks for getting back to me. Although that fixed the issue with the URL, I am still getting a 400 Bad Request when the new window opens. The log shows all commands up to newButton().wait() running. I see the race and sex selected in the URL. This makes me think perhaps something is off within these lines of code:

    if (GetURLParameter("id") && GetURLParameter("race") && GetURLParameter("sex")){
        
        race = decodeURI(GetURLParameter("race"))
        sex = decodeURI(GetURLParameter("sex"))
    
    Sequence("instructions1", randomize("practicesequence"), "Break1", randomize("experimentalsequence1"), "Break2", randomize("experimentalsequence2"), "Break3", randomize("experimentalsequence3"), "send", "Finish")
    
    // Instructions
    Template(
        GetTable("instructionsimage.csv")
            .filter("race", race)
            .filter("sex", sex)
        ,
        variable => newTrial("instructions1",
            defaultText
                .center()
                .print()

    Thank you very much for your help + patience!
    Callie

    #5636
    Jeremy
    Jeremy
    Keymaster

    Hi Callie,

    I’m sorry, I didn’t realize that you can’t run server.py just like that (I tested the code on another server, on which it works)

    Replace server.py with experiment.html (if you’re not planning on using the withsquare method, otherwise simply add it to the list of parameters of window.open and it should also work)

    When I try to run your experiment with a valid URL, I get two errors: “No column named ‘race’ found in the table for filtering” (I looked up your CSV table, all the columns start with an uppercase letter—fix the sex column name too) and “newButton.wait is not a function” (this is your very last command, just add a pair of parentheses after newButton)

    Jeremy

    #5638
    Avatar
    caljones
    Participant

    Hi Jeremy,

    Thank you so much! This worked.

    One last question: would something like https://www.digitalocean.com/docs/spaces/how-to/ this work as a “server” to store my zip file with images? I don’t have my own dedicated server, so I’m looking for alternative options. Storing these images on a server of some sort would make the images/pages load faster in the experiment, right? Are there any other alternative server options for hosting images that you would recommend?

    Thanks,
    Callie

    #5639
    Jeremy
    Jeremy
    Keymaster

    Hi Callie,

    I think it should work, yes, because you can configure CORS: you would need to allow GET for https://expt.pcibex.net/

    Note that the Spaces plans will only let you host resources (either individually or zipped) but you won’t be able to send data from your experiment, ie. DigitalOcean Spaces are not compatible with the MediaRecorder element and the EyeTracker element’s data-collection method.

    There are many factors that impact resource preloading. One of them is the bandwidth of the host server, so if you store your images on a fast server, they might load faster than from the PCIbex Farm (especially if the farm’s servers are busy). Using a ZIP file is actually likely to slow the initial preloading a little bit, because the experiment needs to download all the resources at once (the zip file) before it can preload any of them. But it is a more optimal option overall, because (i) one zip file is lighter than the total of all the resource files fetched individually, and (ii) it requires only one request to the server, when multiple concurrent requests can in some cases incur significant slowdowns.

    If preloading time is not that much of an issue, keep in mind that you can always store resource files (but not zip files) on free services like Google Drive or Dropbox (you just need to use a direct link, not a “share” link)

    Jeremy

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

You must be logged in to reply to this topic.