Forum Replies Created
-
AuthorPosts
-
Jeremy
KeymasterHi,
The
pick
function only accepts IBEX-style predicates as an argument (eg.randomize("label")
) butfeatures
is a 10-ary array, so passing it topick
directly won’t workYou can create a (sub)sequence from it though, using IBEX’s
seq
function:seq(...features)
So you could do that:
featuresSeq = seq(...features) Sequence("WelcomeConsent", "counter", "demographics", "instructions1", "exercise", "startofexp", pick(featuresSeq,500),"break", pick(featuresSeq,500),"break", pick(featuresSeq,500), SendResults(), "Bye");
Jeremy
November 1, 2022 at 12:43 pm in reply to: Media recordings not uploading to server after crash #9659Jeremy
KeymasterHi Val,
So just to make sure we’re on the same page, you don’t even get a zip file for the practice items?
I just took a test run of the practice+B1 items, and the two corresponding POST requests were responsed with
uploads/f9c2be0d-3a62-5b8d-cdd3-12477feb343e.zip
(practice) anduploads/8ee6d91a-d111-d194-0528-341f049e8478.zip
(B1); are you saying you don’t see those two zip files in the uploads subfolder on your server?Jeremy
Jeremy
KeymasterHi Jet,
I checked the database and the good news is, all submissions seem to have 57 rows each, so the mostly empty results file you get does not mean that there was a problem during data collection, but only during the download process
The farm has been slow again for the past few hours, but it looks like it’s doing a little better now. Let me know if you still have trouble accessing your results file, and if you do, I will generate one for you
Jeremy
Jeremy
KeymasterHi,
When I try your code with the table you posted above (adding a “Sentence” column) I do get both “Long” and “Short” trials included in the experimental sequence. Do you have a link to your experiment so I can help troubleshoot?
Jeremy
Jeremy
KeymasterHi Jeff,
If you know in advance that you want 10 trials to use column 2 (let’s call it “Joke”) and 10 to use column 3 (let’s call it “NonJoke”) you can simply generate an array of 20 entries, half
true
halffalse
, shuffle that array and scan it withinTemplate
:Sequence( rshuffle("trial-joke","trial-non-joke") ) var jokings = [...new Array(20)].map((v,i)=>i<10); fisherYates(jokings); var joking; Template( row => newTrial( "trial-" + ((joking=jokings.pop()) ? "joke" : "non-joke") , newText( "prompt" , ( joking ? row.Joke : row.NonJoke ) ).print() // ... ) .log( "joking" , joking ) )
Jeremy
Jeremy
KeymasterHello,
Are you still experiencing this issue? I just took a partial test run, and the upload requests were responded with a zip filename, which signals that the PHP script ran successfully. However, I can’t check your server to see if the zip file did end up in the upload folder
Jeremy
Jeremy
KeymasterHi,
If you are not familiar with the way (PC)Ibex offers control over the sequence of trials, I recommend reading the PCIbex documentation on labels and the original IBEX manual
In your case, all you need to do to get 1+2 is properly label the trials so you can reference them appropriately in predicates (
randomize
) in theSequence
command:Template( row => newTrial( row.Condition+"_Set"+row.Set , // etc. Sequence( randomize(startsWith("Short")) , randomize(startsWith("Long")) )
Mixing fillers in is more complex if you have a single set of fillers that should be distributed across the “Short” and “Long” trials. If you know in advance how many filler trials you’ll have (say, 40) you could use the custom
pick
function to randomly pick half (20) of those trials and mix them in with the “Short” trials, and mix the other half in with the “Long” trials:fillers = randomize("Filler") // assuming all your filler trials are labeled "Filler" Sequence( rshuffle( startsWith("Short") , pick(fillers,20) ), rshuffle( startsWith("Long") , pick(fillers,20) ) )
Jeremy
-
This reply was modified 2 years, 8 months ago by
Jeremy. Reason: added missing closing parentheses
Jeremy
KeymasterHi Laia,
Place the code you have after the first
wait
incallback
instead:newTrial("location", newText("Where do you live?").print().cssContainer({"margin":"1em"}) , defaultScale.radio().labelsPosition("right").log() , newButton("go") , newScale("us", 'California', 'New York'), newScale("uk", 'England', 'Scotland') , newScale("country", "US", "UK").print().cssContainer({"margin":"1em"}) .callback( getButton("go").remove(), getScale("uk").remove().test.selected().success(self.unselect()), getScale("us").remove().test.selected().success(self.unselect()) , self.test.selected("US") .success( getScale("us").print().wait(),getButton("go").print() ) .failure( getScale("uk").print().wait(),getButton("go").print() ) ) , getButton("go").wait() )
Jeremy
October 28, 2022 at 4:25 pm in reply to: Randomizing trials, with 1/5 of trials followed by a comprehension question #9641Jeremy
KeymasterHi,
Some elements are missing from the pieces of code you posted (how
color_order_label
,leftColor
,centerColor
,rightColor
andgetImageEmotion
are defined, where/whethercreateColorGroup
is called elsewhere) but if I understand your question correctly, you should be able to do something like this:function createColorGroup(int) { var bugba = ["blue", "green", "black", "bugba"]; var gbuba = ["green", "blue", "black", "gbuba"]; var bagbu = ["black", "green", "blue", "bagbu"]; var gbabu = ["green", "black", "blue", "gbabu"]; var babug = ["black", "blue", "green", "babug"]; var bubag = ["blue", "black", "green", "bubag"]; var groups = [bugba, gbuba, bagbu, gbabu, babug, bubag]; return groups[int]; } color_group = createColorGroup(Math.round(6*Math.random())) leftColor = color_group[0] centerColor = color_group[1] rightColor = color_group[2] color_order_label = color_group[3] Template( "emoMusicGroupedPracticeV2.csv" , row => newTrial("PracticeEmoMusic", newAudio(row.audiofile).center().print().wait() , newText("Q", "<p>Whose face matches the music?</p>").center().css("font-size", "1.5em").print() , newSelector("eugenies").once().frame("dashed 0px white") , defaultImage.cssContainer({border:"solid 2px black","background-color":"white"}) , newImage(String(getImageEmotion(row.leftImage)), leftColor+row.leftImage), newImage("calmImage", centerColor + "calmnolabel.jpg"), newImage(String(getImageEmotion(row.rightImage)), rightColor+row.rightImage) , newCanvas("labels", 600, 200) .add("center at 18%", "middle at 50%", getImage(String(getImageEmotion(row.leftImage)))) .add("center at 50%", "middle at 50%", getImage("calmImage")) .add("center at 82%", "middle at 50%", getImage(String(getImageEmotion(row.rightImage)))) .color("yellow") .cssContainer("border", "solid 2px black") .center() .print() // etc. ) .log("id", getVar("subjID")) .log("color_group", color_order_label) )
Jeremy
Jeremy
KeymasterHello,
Thank you for your messages. The farm was having issues handling traffic yesterday and crashed earlier today. I have restarted the servers and it is now running normally again
Apologies for the inconvenience,
JeremyOctober 27, 2022 at 12:31 pm in reply to: Picture resources not printed during experimentation #9633Jeremy
KeymasterHello,
Do you still experience the problem today? Everything runs smoothly when I open your demonstration links
Best,
JeremyJeremy
KeymasterHello Jinyoung,
As you found out, the problem with the command
disable
is that it doesn’t prevent the participant from playing the audio again by simply pressing the spacebar (which is something I should fix). Another problem is there’s nocallback
command on the Audio element that you could use afterwait
to execute some commands after later playbacksSo one solution is to use another element’s
callback
command to execute some code that will run in parallel to the main script, which still needs to be runningwait
on the Selector element:newAudio("audio", variable.audio).center().print().wait(), newTimer("callback",1).callback( getAudio("audio").wait().remove() ).start()
This way, if the participant plays the Audio element again, it will simply disappear from the page
Now, another problem with your script is you print a Canvas element at the center of the page that you scale to fit the page’s dimensions, which results in that Canvas element covering the other elements already on the page, notably the Audio element, which you can no longer click because clicks now target the Canvas element on top of it instead. You should probably rethink the way you display the different elements (eg. by printing everything, including the texts and the Audio element inside the Canvas element) but if you want to keep things how they currently are, a straightforward solution is to make the clicks on the Canvas element “transparent”:
newCanvas("canvas", 1800, 1000) .add(200, 380, getImage("nrc") ) .add(1000, 380, getImage("rrc") ) .scaling("page") .print("center at 50vw", "middle at 50vh") .cssContainer("pointer-events", "none")
Jeremy
Jeremy
KeymasterHi Laia,
The code you posted in your message works perfectly well (except for the missing
"
after"practice1
) but the code in your project has additional commands. In particular, it has this:defaultText.cssContainer({"margin-top":"1em", "margin-bottom":"1em"}).print()
. This will silently add.print()
right next to anynewText
command, which is why you see both sentence1 and sentence2 appear below each other as soon as they are created. Just remove.print()
:defaultText.cssContainer({"margin-top":"1em", "margin-bottom":"1em"})
The audios are not all played in the same order: I just had a test run where the first trial played audio2 then audio1, and the second trial played audio1 then audio2. Granted, there are only three trials, so it’s not unlikely that some test runs will play all three pairs of audios in the same order, just by chance
Jeremy
Jeremy
KeymasterHi Laia,
This line
newVar("tag1").global().set(getScale("input_tag1"))
will set the Var element to the last selected value, so you won’t exactly get what you want indeed: if the participant checks “oi” and later on also checks “fa”, then the Var element’s value will be “fa” and you won’t detect that “oi” is still checkedBecause the Scale element only detects the most recent selection, you’ll need to use a workaround:
newTrial("pretest", newScale("input_tag1", "eh", "no", "oi", "fa") .checkbox().log().vertical().print(), newButton("go", "Endavant").print().wait(), newVar("tag1").global().set( ()=>document.querySelector("input[value='oi']").checked ) ) newTrial("exp", getVar("tag1").test.is(true).success( newText("instrus1", "You selected 'oi'!.") .print(), newButton("go", "Endavant") .print() .wait() ) )
Jeremy
Jeremy
KeymasterHi Laia,
Your first trial (“pretest”) shows a Scale element, immediately sets the Var element “tag1” to the currently selected value on the scale (ie. no value, since the participant hasn’t had time to make a choice yet) then prints the “go” button and wait for a click before moving on to the next trial
You second trial (“exp”) actually contains a fatal error, so it won’t be run, but if it were, it would check that the value of that Var element corresponds to the value of the variable
oi
, which is not only undefined (as far as I can tell) but most importantly not declared: the script does not know whatoi
refers to and crashes at that point, never creating the second trial nor executing any of the code that comes after that (ie. it doesn’t create the “end” trial either)So you’ll want to switch the order of the last two lines of your first trial and add double quotes around
oi
in the second trial:newTrial("pretest", newScale("input_tag1", "eh", "no", "oi", "fa") .checkbox().log().vertical().print(), newButton("go", "Endavant") .print() .wait(), newVar("tag1").global().set(getScale("input_tag1")) ) newTrial("exp", getVar("tag1").test.is("oi").success( newText("instrus1", "You selected 'oi'!.") .print(), newButton("go", "Endavant") .print() .wait() ) )
If by “selecting at least oi” you mean selecting “oi” or “fa”, you can add a disjunct to your test:
getVar("tag1").test.is("oi").or( getVar("tag1").test.is("fa") ).success(
Jeremy
-
This reply was modified 2 years, 8 months ago by
-
AuthorPosts