Forum Replies Created
-
AuthorPosts
-
Jeremy
KeymasterHi Adam,
Unfortunately the only way to add columns to your results file at the moment is to use .log which is only defined on the object returned by PennController(), so it’s not possible to use it with the DashedSentence controller…
One option would be to re-code the DashedSentence controller, but unfortunately there seems to be a bug with having multiple Key elements using the same key within the same trial… So the code below is functional but will fail to log response times!
dashed = (sentence, remove) => { let words = sentence.split(' '); let blanks = sentence.split(' ').map(w=>w.split('').map(c=>'_').join('')); let textName = 'dashed'+words.join(''); let cmds = [ newText(textName, blanks.join(' ')) .print() ]; for (let i = 0; i < words.length; i++){ cmds.push(newKey('dashed'+i+words[i], " ").settings.log().wait()); cmds.push(getText(textName).settings.text( blanks.map((w,n)=>(n==i?words[n]:w)).join(' ') )); } cmds.push(newKey('dashed'+words.length+" end", " ").settings.log().wait()); cmds.push(getText(textName).settings.text( blanks.join(' ') )); if (remove) cmds.push(getText(textName).remove()); return cmds; } PennController.Template( "mytable" , row => PennController( ...dashed(row.Sentence) ) .log('Condition', row.Condition) )
I’ll work on fixing the key bug for the next release, and in the meantime I’ll try to see if I can find a hack adapted to your situation
Jeremy
Jeremy
KeymasterGlad we got it to work eventually!
Just a quick question though: do you remember if you had the debugger turned off when you were trying to log with row instead of item? I’m asking because you should get a related error message in the debugger’s Error tab in those cases, and I can’t seem to reproduce an absence-of-error-message bug (which I’d like to fix if it indeed occurs).
Also, FYI, the next release of PennController will trigger specific error messages when you attempt to use a command on Template() that should be used on PennController().
Jeremy
KeymasterHi Cory,
All the experiment is technically run on the client side: the browser interprets the javascript code and executes it, which means that once it has downloaded the script, it doesn’t really need an internet connection anymore. Of course things are more subtle—there could be asynchronous scripts for example, but we can ignore that here. The browsers still need to download any resources you use though, but that won’t impact performance per se: it might just introduce preloading delays. So the reaction times will be accurate but it could be that, if preloading fails, audio playback starts late for example. But if you use .settings.log("play") on your audio element (still an example of course) then you should be able to subtract its timestamp from a key.settings.log()‘s timestamp (again, for example) to measure the actual time that elapsed between the start of playback and the key press.
I don’t use iPads so I can’t test it for you now, but if you can run python on it you might want to give a shot at a local setup.
Jeremy
KeymasterThanks—I’ll give it a closer look later, but just double-checking first: did you try calling .log("Class", item.Class) on the closing parenthesis of PennController() too since you changed to item? Looking at your current script, it is called on the closing parenthesis of PennController.Template(), which it shouldn’t
Jeremy
KeymasterDo you have a link to your experiment?
If I adapt your example table to my example code above, the content of the “Class” cell gets recorded:
PennController.ResetPrefix(null); PennController.AddTable("dummyTable", `Label,Class,Group,Sentence,Sagen,Claim,Question Rating,VF-1,A,bla,bla,bla,bla Rating,V2-1,B,bla,bla,bla,bla Rating,EVF-1,C,bla,bla,bla,bla Rating,EV2-1,D,bla,bla,bla,bla`); PennController.Template( "dummyTable" , item => PennController( newButton( item.Sentence ).print().wait() ).log( "Class" , item.Class ) )
Jeremy
KeymasterDid you make sure that the colum name in your table’s header row matches the case of row.Class (i.e. are you sure you column’s name is exactly Class)?
Here is a very short illustration:
PennController.AddTable( "dummyTable" , `Class,Word,Group Upper,Hello,A Lower,hello,B Lower,world,A Upper,World,B` ); PennController.Template( "dummyTable" , item => PennController( newButton(item.Word).print().wait() ).log( "Class" , item.Class ) )
Jeremy
KeymasterHi Sander,
It looks like you named your pointer item and not row (expression to the immediate left of =>) so you should use item.Class
Jeremy
Jeremy
KeymasterCan you try updating your version of PennController to this dev version?
repo url: https://github.com/PennController/Sync
branch/revision:dev-cory
Jeremy
KeymasterHi Cory,
There seem to be issues with the preloading of audio files, maybe your problem is related. What resources does your experiment use?If you have a link to your experiment, feel free to share it with us so we can look into the script.
Jeremy
Jeremy
KeymasterIn terms of aesthetics, I can’t find anywhere how I can put boxes around a canvas. Do I need to add a separate script for that into the chunk_includes/resources? Or is there a way I can write that in my main script in such a way that all canvases are boxed?
You can use the standard .settings.css or .settings.cssContainer commands. To make it a default on every Canvas element in your current trial, use defaultCanvas in the script of your current trial. If you want to make it a default on everyCanvas element for every trial in your script, place the command in PennController.Header:
PennController.Header( defaultCanvas .settings.cssContainer("outline", "solid 2px black") );
Or you can have a PennController.css file in your Aesthetics folder (css_includes on Ibex Farm) with the following script:
.Canvas-container { outline: solid 2x black; }
Note: I use outline rather than border because the latter can mess with the actual size of the element (outline adds inner borders).
See the Aesthetics documentation page for more details.
Jeremy
-
This reply was modified 5 years, 7 months ago by
Jeremy. Reason: misspelled Ibex Farm's aesthetics folder's name
Jeremy
KeymasterHi Sander,
First, I see from your code that you are using a mix of native-Ibex and PennController code, and some obsolete function names (e.g. FeedItems). This is fine and functional, but you might want to consider updating your code (see the documentation and in particular the tutorial for pointers):
// No need for manualSendResults = true if you use PennController.SendResults (see below) // No need for showProgressBar = true (it's a default) // No need for shuffleSequence = seq() when using PennController.Sequence PennController.Sequence("setcounter","consent","instructions","scaleinstr","distract", "debrief","send","thanks"); PennController.ResetPrefix(null); // ... // Template now replaces FeedItems PennController.Template( "CSV_ITEMS_Diff.csv" , // No need to setGroup: columns named "Group" are automatically detected as such item => PennController( // You might want to consider having a label here, e.g. "scaleinstr" or "distract"? newTimer("blank", 1000) .start() .wait() , // ... PennController.SendResults("send"); // No need for setting manualSendResults
As you see from the code above, you are probably not seeing your items because their labels do not match the ones listed in your sequence. Take a look at the first example of the documentation page for PennController.Template to see how you can label table-generated trials.
Let me know if you have any questions
Jeremy
Jeremy
KeymasterHi Leo,
Thank you for letting me know. I don’t know what is happening exactly in your case, but maybe a comparison with a functional example would help identify the source of the problem:
PennController( newText("sentence").print() , newVar("sentenceDisplayTime").set(v=>Date.now()) , newScale(10).print().wait() , newVar("ratingRT").set( v => Date.now() - getVar("sentenceDisplayTime")._element.value ) , newText("") .settings.text( getVar("ratingRT") ) .print() , newButton("Push").print().wait() )
Will display how long it took to select an value on the scale.
Jeremy
Jeremy
KeymasterYes, it’s a general concern with Ibex’s default handling of the internal counter. Maybe next releases of PennController should replace the default behavior so it increments the counter at the very beginning of the experiment instead, but I’m afraid that people used to the original Ibex wouldn’t notice the change and make the wrong assumptions.
In any case, you have multiple solutions:
- You can manually set the counter using PennController.SetCounter (place its label where you see fit in your sequence of trials, probably at the very beginning or immediately after the welcome screen)
- You can replace experiment.html in your experiment’s URL with server.py?withsquare=N where N is a number from 0 to the total-1 of different values appearing in your Group column. Then you have two options:
- You collect data in as many batches of participants as different N-based links (this is what I usually do: I collect one batch of participants, then update the link and collect another batch).
- You find a solution to automatically fill N, for example passing the participant’s ID in its place if the ID is a number: N is modulo-based so if your participants’ IDs are evenly distributed, you should get a reasonable output distribution.
Let me know if you have questions
Jeremy
Jeremy
KeymasterHey Mogli,
I’m sorry about that. What I do is I usually test-run my experiments so I can spot this kind of problems.
There could be several explanations. The easiest for me would be if you shared your script or the link to your experiment with me.
How was your group distribution method? Did you rely on the internal counter? Or did you force a group assignment as a parameter in the URL?
When relying on the internal counter, and in absence of explicit manipulation in the script, if all your participants take the experiment within seconds/minutes, they could very well all end up in the same group (because the counter is only incremented when participants have completed the whole experiment).Jeremy
Jeremy
KeymasterIt can start with anything, all that PCIbex cares about is the set of different values listed in the Group column: it will just pick one of them and automatically subset the table to the rows in which the Group cell contains the value it picked.
Jeremy
-
This reply was modified 5 years, 7 months ago by
-
AuthorPosts