Forum Replies Created
-
AuthorPosts
-
Jeremy
KeymasterHi Nickolas,
I think you’ve identified the problem: referring to a Timer that is created in a trial from within the header does not work. But I think the opposite should work, namely referring to a Timer that is created in the header from within a trial. So you could try creating (but not starting) your Timer in the header, and manipulating it in your trial. This way you can use stop on it before SendResults in the header.
Jeremy
Jeremy
KeymasterHi,
You results file should not be empty, even if the trial fail to record the relevant bits: you should at least have a report that a run took place. Did you make sure to take your experiment until the end (ie. until you get a confirmation message: “The results were successfully sent to the server. Thanks!”)?
The code above already includes a trial without a comprehension question, namely trial 2. As you can tell from the table, you just leave the Question column empty and it will skip that bit. So just don’t write anything into Question in the rows of your filler table where you don’t want a comprehension question to appear
Jeremy
Jeremy
KeymasterHi Nickolas,
Here is an updated version of the code above that should work with PennController 1.8:
PennController.ResetPrefix(null) AddTable("myTable", `Label,Text target,Hello filler,hello target,World filler,world`) Sequence("welcome", rshuffle("target","filler")) Header( newCanvas("confirmation", '75vw', '80vh') .css({'background-color': "floralwhite", 'z-order': 9999}) .add( "center at 50%", "middle at 25%" , newText("Are you sure you want to send your incomplete results now?") ) .add( "center at 50%", "middle at 75%" , newScale("quit", "Yes", "No").size("10em","auto").button() ) , newButton("stop", "Stop").callback( getCanvas("confirmation") .print("center at 50vw", "middle at 50vh") , getScale("quit").wait() , getCanvas("confirmation").remove() , getScale("quit").test.selected("Yes") .success( clear() , SendResults() ) ) .print("right at 98vw","bottom at 98vh") ) newTrial( "welcome" , newButton("Start").print().wait() ).noHeader() Template( "myTable", row => newTrial( newButton(row.Text).print().wait() ) )
Let me know if this solved your timer issue too
Jeremy
Jeremy
KeymasterHi,
You will need to create one Selector per Image, as Selectors were designed to represent exclusive choices. You will also need to create a Var element to determine whether a click on the image should select or unselect it. Since you will have to do this for all of your images, it’s best to just define a function that you call on each of your images, like this:
const newToggleImage = (name,file) => [ newVar(name+"-var", 1), newSelector(name+"-sel") .frame("solid 6px black") .callback( getVar(name+"-var").set(v=>1-v).test.is(1).success(getSelector(name+"-sel").unselect()) ) .log() , newImage(name, file) .size(200,200) .selector("shapes").selector(name+"-sel") ] Template( GetTable("myTable_testing").filter( row => (row.n_correct == "2c") & (row.pol == "pos")) , row => newTrial("testing_2cor_pos", newSelector("shapes").disable() , newText( "Click on any and all pictures corresponding to "+row.word.toUpperCase() ) .css("font-size", "30px") .center() .bold() .print() , newToggleImage("target_1", row.picture), newToggleImage("target_2", row.p1), newToggleImage("d2", row.p2), newToggleImage("d3", row.p3), newToggleImage("d4", row.p4), newToggleImage("d5", row.p5) , newCanvas( 'myCanvas', 700, 500) .add( 20, 40, getImage("target_1"), 0 ) .add( 20, 270, getImage("target_2"), 1 ) .add( 257, 40, getImage("d2"), 2 ) .add( 257, 270, getImage("d3"), 3 ) .add( 495, 40, getImage("d4"), 4 ) .add( 495, 270, getImage("d5"), 5 ) .center() .print() , getSelector("shapes").shuffle() , newButton("confirm") .print() .wait() ) .log("target_1", row.picture) .log("target_2", row.p1) .log("d2", row.p2) .log("d3", row.p3) .log("d4", row.p4) .log("d5", row.p5) )
Given that several people have expressed the need for a checkbox-like behavior, I will consider implementing this option in a future release of PennController
Jeremy
Jeremy
KeymasterHi,
Right now, your code looks up every row from your table and for every single one of them, it outputs one corresponding trial presenting the value of the Description column onto the page, waiting for a keypress on the spacebar, and showing the values of the answer1 and answer2 column, waiting for a click on one of them. Once a click happens, it goes to the next trial, ie. the next row, and it does all of this all over again. This is how the Template command works.
From the description of your problem, I am guessing that you split each of your items across several rows in your table, and that you want each row’s Description corresponding to the same item to appear on the screen one at a time, moving on to the next one by pressing the spacebar. Then you want to show the Question(s?) along with answer1 and answer2. Did I get it right?
If what I described is what you want to do, you need to use the Controller element, using DashedSentence with the option display set to "in place"—you’d also need to make sure your table has the right format. Here is an example of how to implement what I described, adding the subtlety of optional questions:
AddTable("myTable", `Item,Sentence,Question,answer1,answer2 1,This_is_region1_of_item1 and_this_is_region2_of_item1,Question for item 1,Answer1 for item1,Answer2 for item1 2,This_is_region1_of_item2 and_this_is_region2_of_item2,,, 3,This_is_region1_of_item3 and_this_is_region2_of_item3,Question for item 3,Answer1 for item3,Answer2 for item3`) Template( variable => newTrial( "experiment" , newController("DashedSentence", {s: variable.Sentence, display: "in place", hideUnderscores: true}) .print() .log() .wait() .remove() , ( variable.Question ? [ newText( variable.Question ).print() , newText( "answer1" , variable.answer1 ).print() , newText( "answer2" , variable.answer2 ).print() , newSelector("answer").add( getText("answer1") , getText("answer2") ).log().wait() ] : [ null ]) ) .log( "Item" , variable.Item ) )
Jeremy
Jeremy
KeymasterThe reading time for “But…” (first line) was 262ms, the one for “Bill” (second line) was 276ms, etc.
Jeremy
Jeremy
KeymasterHi Irene,
Unfortunately the MediaRecorder element is mostly supported by Firefox desktop and Chrome desktop only for now. I’m not sure what are the capacities of Chrome on iOS, whether there are any OS-wide limitations
I know it’s technically feasible to record audio streams in a browser from an iPhone, but developers seem to use a different API than MediaRecorder. I know I should work on implementing alternatives in the future, but it’s not a priority at the moment
Unless you are willing to code your own voice-recording system, I’m afraid you’ll have to tell your iPhone participants to use a computer indeed, I’m sorry
Jeremy
Jeremy
KeymasterHi,
Not sure what is happening in your case, as in mine it works just fine. Here are four (non-consecutive) lines from my results file:
1592492904,MD5,PennController,0,0,trials,NULL,Controller-DashedSentence,test,4,first,1592492877807,This is the first dashed sentence,C1,C2,C2,A,227,false,This is the first dashed sentence,Any addtional parameters were appended as additional columns 1592492904,MD5,PennController,1,0,trials,NULL,Controller-DashedSentence,test,4,second,1592492884440,This is the second dashed sentence,C1,C2,C2,A,174,false,This is the second dashed sentence,Any addtional parameters were appended as additional columns 1592492904,MD5,PennController,2,0,trials,NULL,Controller-DashedSentence,test,4,third,1592492891879,This is the third dashed sentence,C1,C2,C2,A,191,false,This is the third dashed sentence,Any addtional parameters were appended as additional columns 1592492904,MD5,PennController,3,0,trials,NULL,Controller-DashedSentence,test,4,fourth,1592492900624,This is the fourth dashed sentence,C1,C2,C2,A,1142,false,This is the fourth dashed sentence,Any addtional parameters were appended as additional columns
As you can see, and as described in the comments of the results file, column 18 (the one after “A”—the group) reports reading times. In this case, I spend 227ms reading “first” in the sentence “This is the first dashed sentence,” 174ms reading “second” in “This is the second dashed sentence,” etc.
When you say it shows only some of the dashed sentence, do you mean that the RTs get reported fine but you’re missing lines corresponding to an entire DashedSentence element in your results file?
Jeremy
Jeremy
KeymasterHi Nickolas,
Adding ?withsquare=N to experiment.html will not override the internal counter, only server.py is able to handle this, so your experiment probably breaks because of a mismatch between the value of the internal counter and whatever you do with withsquare in your script (eg. retrieving it using GetURLParameter). If you need to use withsquare, always use it with server.py.
Could you use .log to add a tag (effectively, a value in an extra column) to the lines of your last trial? Alternatively you could also give it a unique label, e.g. “final.” Or note down its ID number by taking the experiment yourself once and use it in your analyses.
The CSS of the progress bar is defined in global_main.css—if you can’t directly modify this file, you should be able to upload a file named global_z.css and override the rules (use !important if necessary).
You can define the value of the variable sendingResultsMessage to modify the corresponding text, as documented here
Jeremy
-
This reply was modified 5 years ago by
Jeremy.
Jeremy
KeymasterHi Callie,
There is a bug in how .log("first") and .log("last") are coded—I’ve fixed it for the next release, thank you for pointing it out to me
In the meantime, I think you can use .log("all") instead and it should work, and if you ever see more than one line for one Key element in your results file, just use the last one to conduct your analyses
Jeremy
Jeremy
KeymasterHi Max,
Replace this line:
for (let j = 0; j < sep.length; ++j)
with this:
for (let j = 0; j < sep.length && main.length>0; ++j)
Jeremy
Jeremy
KeymasterHi Callie,
I created a duplicate of your experiment to test it, and all the fields were logged just fine in my results file. Here’s an example of one line:
1592357826,fe0dad65f46cfd47ed714d7c0045b9a5,PennController,127,0,experimentalsequence3,NULL,Key,FJ,Key,NA,Never,dsfasdfasd,White,Female,1,SHE,1,0,0,1,LCWW00.jpg,0,(failed keypresses happened)
As you can see, columns 13-15 (starting after “Never”) report the ID-race-gender values
Since you’re not logging these values for the trials labeled practicesequence however, they are not reported on the corresponding lines—if you want them there too, just add .log commands to the corresponding newTrial(...)
Another thing you probably want to change is use .log("last") instead of .log() on your Key elements: by default only keypresses that validate a wait command are recorded, and since you have no wait command in your trials (because you use a Timer as a proxy) you will never see which key was pressed. Passing "last" as the parameter will report a line for the last key that was pressed during the trial, if any (ie. the one that will end the Timer early). This way the same line will also report a timestamp indicating when the key was pressed. You could then subtract the timestamp from the previous line (_Trial_,Start) to get a reaction time, but if you’d rather calculate your RT from when the image was printed, use .log() on your Image element too so your results file reports a line indictating when print was executed
Let me know if you have any questions
Jeremy
Jeremy
KeymasterWe resolved this issue by email
The problem was coming from the assumption that newImage commands embedded in the success would only be evaluated in case of a successful test, but all new* commands are evaluated at the beginning of the experiment, even if they are embedded in a test command that will be evaluated upon runtime. One reason for this behavior is to let PennController preload the resources as soon as possible.
In this case, the solution was to carry out the same tests using javascript’s ternary conditional, which will effectively include the PennController commands in Template only if the test is successful, like this:
Template( "myTable.csv" , row => newTrial( "trial" ( row.Image.match(/png$/) ? newImage( row.Image ).print() : newText( row.Text ).print() ) , newButton("Next").print().wait() ) )
Jeremy
Jeremy
KeymasterHi,
Did you use log on the Controller element? It should report one line per word in the results file, the same way that the original IBEX controller does, including reading times
Jeremy
Jeremy
KeymasterHi Daniela,
There is no built-in support in PennController for this sort of thing, I should probably work on adding it somewhere
One solution would be to run a function after you’ve printed your Scale elements that will take care of toggling selection, like this
newFunction( () => { $(".PennController-Scale input[type='radio']").click(function(){ $(this).attr("toggle", $(this).attr("toggle") != "true" ); if ($(this).attr("toggle")=="false") $(this).removeAttr("checked"); }) }).call()
Jeremy
-
This reply was modified 5 years ago by
-
AuthorPosts