PennController for IBEX › Forums › Support › html layout/event times/selector vs. scale/ compatibility
- This topic has 47 replies, 2 voices, and was last updated 2 years, 5 months ago by Jeremy.
-
AuthorPosts
-
October 19, 2021 at 11:00 am #7398HPIParticipant
Dear Jeremy,
I have a few questions, I apologize in advance if they require a bit of time to answer, but I don’t have much support at the very moment, so I want to make sure I am coding in the proper way.
1) Html:
I am not the most expert in HTML but I am trying to improve the layout and graphics of my experiment.
I was wondering if there is a place to set some graphic info that I am not considering because either declaring the info in the separate HTML file, or trying to modify the global main.css I am not obtaining the effect I want.Normally, without any additional specification, the HTML file starts to print aligning the text on the very left, on the other hand, Pcibex automatically loads the instructions, for example, centering as wells as the trial at the center of the screen horizontally, with quite a spacious top margin.
Even imposing to align the text left ( in the separate html file and in the global main file) and setting a 0 top margin, the text keeps being aligned in the center with unused space on top.
Is there something I am not considering to set these parameters correctly?
Also, I managed to change the font size, with the labels small, medium…but I was wondering if it’s possible to precisely set the size like Italic, 15, with the number not for the entire interface but only for what is printed on the screen when the experiment runs (now the entire platform increased the font size).
2) Log time, Response time:
A second question I have is that I want to make sure I am correctly recording the responses and reaction times.
Is the command .log() after each relevant event everything I need to correctly calculate the times? Is it correct that the smartest strategy is to insert the log, thus I get the event time of each step and in a separate moment, after collecting the results, I have to calculate by myself the difference in the event times of what I consider the meaningful start and end.
Is there a way to have the calculation of end-start time already in the output file with the results?3) I am designing an experiment for children, so I have a picture, a sentence, and an acceptability judgment scale that rewards a puppet with 1 cookie, 2 cookies, 3 cookies, according to the degree of acceptability of the sentence with reference to the picture.
Instead of using the controller acceptability judgment scale, I have created a canvas with the 3 pictures of the cookies, and I record the selection of 1 of the 3 buttons using the function “selector”.
Do you think this is equivalent to using the pre-done module of a scale, or do I risk missing some meaningful info in the results?
Checking the result file, I know whether they selected 1 2 or 3 cookies and the time of when they selected one button. My impression is that it is a good solution.4) I have been informed that my university has some reserved space on a local server to record the data, but they have set up this system using the old ibexfarm. I got the info that the syntax of pcibex will be compatible if the penncontroller is correctly loaded. Is it correct that the new syntax of pcibex is completely readable by the old platform simply loading the controllers?
Thank you in advance,
Sorry for the many questions,
HPIOctober 19, 2021 at 12:24 pm #7402JeremyKeymasterHello HPI,
1) You will be interested in this guide on adding custom CSS and in the standard
css
andcssContainer
commandsDelete these CSS rules from Aesthetics/PennController.css and everything will start aligned with the page’s left edge:
.PennController { width: 40em !important; /* controls the witdth of the content area */ margin-left: 50vw; /* aligns the content area's left edge with the vertical center of the page */ transform: translateX(-50%); /* aligns the *vertical center* of the content area instead */ }
To remove the spacing on top, delete
margin-top: 5em;
from thebody
CSS rule from Aesthetics/global_main.cssUse the
.css
/.cssContainer
commands, or CSS rules that target all non-interface elements according to the guide above to only apply size/italics/etc. to non-interface elements2) Insert
.log
commands where you think they are relevant, then test-run your experiment and open your results file and calculate reaction times: if you are able to do it, chances are you’re doing things right. It’s your call what elements you log: for example, I rarely log Text elements because they often are not relevant to the timecourse of unfolding events in my trial. If you want to be extra-safe, you can be redundant about which elements you.log
, but your results file will rapidly get very big, with submissions taking more time to be saved for each participants and your results file taking longer to be generatedYou can calculate differences between two time points in your experiment using javascript’s
Date.now()
and use a global Var element to report that value in an extra cell:newTrial( newVar("rt", 0).global().set(v=>Date.now()) , newButton("Click me!").print().wait() , getVar("rt").set(v=>Date.now()-v) ) .log("RT", getVar("rt"))
This will add a column named “RT” reporting how many milliseconds elapsed between before the Button was created-then-printed and after it was clicked
3) I don’t know how to answer that question: the Selector element’s
.log
command will report which element was selected last. If this is the info you need, then it’s the right way to go4) Yes, PennController is an IBEX controller just like DashedSentence is an IBEX controller. Just include PennController.js in the js_includes folder (also, the PCIbex Farm lets you upload resource files to the Resources folder, but the python script server.py won’t serve those from there, so you need to place the audio/image/video files in the
www
folder instead)Jeremy
October 20, 2021 at 6:05 am #7409HPIParticipantThank you for all the information, I will implement your suggestions!
two more things:
1) can I add a fixation point before the sequence of objects appears on the screen on each trial for like 200 ms? Should I use the commands related to the eyetracking tools? I searched the documentation but I haven’t found an entry for fixation point/star.
2) I have implemented a sort of safe pace advance in the experiment, so it’s the participant that makes objects appearing on the screen, now with the space bar.
We are discussing whether to keep everything on the keyboard or use the mouse, is it possible to have the mouse click left button for example as key for advancing without having a button on the screen? Like there is the empty screen or with a fixation point, the user clicks the mouse and the picture appears, clicks and the sentence appear, evaluates by clicking on the scale the empty screen for the next trial appears.
If we go for this solution then I would be interested in trying the mouse tracking options so I will try to add them to catch whether they first evaluated the sentence with 3 points and then changed their mind and evaluated with 2.
Do you think this is doable in principle? (also with this drawback that the university server is set up with ibexfarm and not pcIBEX?)
Thank you!
HPIOctober 20, 2021 at 10:53 am #7411JeremyKeymasterHi,
1) I have seen people use an image of a cross, eg:
newImage("cross.png").print("center at 50vw","middle at 50vh") , newTimer(200).start().wait() , getImage("cross.png").remove()
2) Use the Selector element to make elements clickable on the page. If you want to catch any click anywhere on the page, you could print an empty Canvas of 100vw*100vh at (50vw,50vh) and add that Canvas to a Selector (make sure to delete the Canvas elements when you’re done listening to those clicks)
The MouseTracker tracks the cursor’s movements, it does not make elements on the page clickable. If you have a Scale element and want to have a historic of choices, pass
"all"
to the.log
commandAs I said above, PennController is an IBEX controller just like DashedSentence, it doesn’t matter whether you run it on the PCIbex Farm or on a dedicated server
Jeremy
October 21, 2021 at 4:55 am #7415HPIParticipantHi,
Thank you for your help. I am not sure I have understood the canvas suggestion. Right now to self-pace the experiment I used this strategy, so the participant advances with the spacebar. I got the input to allow the participant to advance with a mouse click and not with a keypress.newTrial("welcome", newHtml("welcome", "welcome.html") .css("line-height","1.4") .settings.log() .print() , newKey("Go_to_page2"," ") .log() .wait() , ).setOption("hideProgressBar",true);
Do you mean to implement something like this?
newTrial("welcome", newCanvas( "clicks", 100, 100) .settings.css( "border" , "solid 1px white" ) .print("center at 50vw","middle at 50vh") , newHtml("welcome", "welcome.html") .css("line-height","1.4") , newSelector("clicks_1") .add(getCanvas("clicks"), getHtml("welcome")) .print() .refresh() .log() .once() .wait() , //newKey("Go_to_page2"," ") //.log() //.wait() //, )
This right now does not work. I was wondering if with something like “newKey” I could catch the key of the mouse without placing buttons.
I am not sure I understood what I should remove with the canvas strategy.
Thank you for your time,
HPIOctober 21, 2021 at 12:01 pm #7416JeremyKeymasterHi,
I was thinking something more like this:
newTrial("welcome", newHtml("welcome", "welcome.html") .css("line-height","1.4") , newCanvas("clicks", "100vw", "100vh") .print("center at 50vw","middle at 50vh") , newSelector("clicks_1") .add(getCanvas("clicks")) .wait() )
The Key element only reacts to keys pressed on the keyboard. All its commands are listed here: https://doc.pcibex.net/key/, as you can see there is no command that relates to the mouse (as expected, for a keyboard-specific element)
Note that the Selector element has no visual content, it merely makes other elements (which themselves have visual content, like a Canvas element) selectable, so calling
.print
or.refresh
on them won’t have any effectJeremy
October 25, 2021 at 9:11 am #7427HPIParticipantHi,
thank you for your help, I am back again, struggling a bit.
So I tried the canvas option to get a mouse click to advance but it didn’t work, also I think the canvas go in conflict with loading a pre-written HTML page like the one having the instructions.
So I went back to the solution of using only the keyboard.a) First: I don’t get the logic for the graphic layout set-up (if I run it on a PC or apple the position of the images changes, the position changes also if for some reason I change the zoom settings on the chrome browser).
I would like that the images and the text keep the same position no matter where the script is run.
What is the difference in using .center(), in using “vw, vh”, and in setting a position (500, 500)?
I thought vw would adapt to the hardware opening the script, but it goes off by changing the zoom settings of the browser, plus it centers pictures, but it doesn’t work in the same way with text, which is actually centered in a more efficient way with .center.b) Then regarding the logic of the script:
(a picture is loaded with the spacebar, then a sentence is loaded with the spacebar, then 3 images appear representing a scale and the participant has to select one picture using 3 possible keys of the keyboard – before it was the mouse click and it worked, but I don’t want to implement the advancing with the space bar and the selection with the mouse, I want to use only one device, at first I thought the mouse was easier and more comfortable for the user, but this system seems not designed to code the fingers of the mouse, so I changed my mind and decided to use only the keyboard instead)Once the scale appeared I would like that a message appears on the bottom saying “press the space bar to advance” (before there was a button, but avoiding the use of the mouse, means avoiding the use of buttons, and it’s better because only the stuff relevant for the tested processing mechanism appears on the screen).
This message has to appear only if they press one of the 3 selected keys, only if they selected at least one. The experiment cannot move forward without the answer of the participant.Since it is a sequence of canvas, the text has to stay on a canvas too otherwise it appears underneath I guess. If they press the space bar before having given a judgement a warning text “please provide a judgement” should appear.
I tried several options, but something is not working, either I get errors, or the sequence doesn’t appear the way I want it.
b.1) Could you check if I am doing something logically wrong with the Wait(test.selected().failure) commands?
b.2)Can I specify to verify whether the participant has pressed “a” “g” “l” in the wait command? (does it matter if I declare “a” or “A”? )
b.3) To load the pictures and the scale I first created a canvas, then called it with getcanvas. For this last selector which has to appear only if the previous selector has been completed should I create first a canvas, then tell the system to print only if the selector has been closed, or should I create a newcanvas and say “print it only if the previous selector has registered either “a” “g” “l”?
The run messes up if I test the possibility that a participant presses a random key… the warning doesn’t come out and that either I place “once()” or not, the final command to press the space bar to advance does not appear, so the experiment crash.
getCanvas("Smiley_Scale") .refresh() .log() , getCanvas("Smiley_Scale_Label") .refresh() .log() , newText("warning", "Please provide a judgment before you can continue") .center() .color("red") .hidden() .print() , newSelector("smileys") .disableClicks() .add( getImage("inappropriate"), getImage("infelicitous"), getImage("appropriate")) .keys( "A" , "G" , "L" ) .once() .log() .wait() , newCanvas( "End_of_trial_page" , 1000 , 35 ) .wait(getSelector("smileys").test.selected().failure(getText("warning").visible()) ) .settings.css( "border" , "solid 1px black" ) .settings.center() .settings.add( 300,0, newText("move_on_to_new_trial", "PRESS THE SPACEBAR TO LOAD A NEWTRIAL" ) ) .print() .log() , //getCanvas("End_of_trial_page") //.wait(getSelector("smileys").test.selected().failure(getText("warning").visible()) ) //.print() //.log() //, newKey("endtrial_newtrial"," ") .log() .wait() )
Thanks, sorry for using so much of your time,
HPIOctober 28, 2021 at 5:05 pm #7452JeremyKeymasterHi, sorry for the late reply
a) If you really want to have as close a constant visual layout as possible (which, technically, is never possible given the variety of screens and resolutions) you should use a constant unit (for example, pixels) to create your Canvas element(s) and place elements on it, and then you can use
.scaling("page").print("center at 50vw","middle at 50vh")
on the main Canvas element to display it in the middle of the page, scaled (with its content) to fit the page while preserving ratios (ie if the Canvas element is a square and the page is rectangular, there will be blank spaces on the right and left edges of the Canvas element)The vw and vh and relative units, where one unit represents 1% of the page’s width/height, respectively. When you use
.print("center at 50vw","middle at 50h")
on an element, it prints it so that the element’s central point is at the center of the page. If the box of your Text element is wider than its textual content, the text won’t appear perfectly center, but rather a bit off to the left. The.center()
command will center the (box corresponding to the) element relative to its parent HTML node’s box. When you use.center().print()
on a Text element, it will usually center it on the page because most project’s CSS rules for the main PennController node center it too. Using.print(500,500)
will align the element’s top-left edge at 500px right of left edge of the page, and 500px down from the top edge of the pageb) I will address each subpoint below, but first let me give you a code that, I think, accomplishes what you’re after:
newText("warning", "Please provide a judgment before you can continue") .center() .color("red") .hidden() .print() , newSelector("smileys") .disableClicks() .add( getImage("inappropriate"), getImage("infelicitous"), getImage("appropriate")) .keys( "A" , "G" , "L" ) .once() .log() , newCanvas( "End_of_trial_page" , 1000 , 35 ) .css( "border" , "solid 1px black" ) .center() .add( 300,0, newText("move_on_to_new_trial", "PRESS THE SPACEBAR TO LOAD A NEWTRIAL" ) ) .print() .log() , newKey("endtrial_newtrial"," ") .log() .wait( getSelector("smileys").test.selected().failure( getText("warning").visible() ) ) )
b.1) There is no
.wait
command on the Canvas element. I think you wanted to place the test inside the Key element’s wait command (ie. the message should appear when the spacebar is being pressed, but no selection has been made)b.2) You can test which element was selected by passing a reference to
.test.selected
as an argument. Because there is a one-to-one correspondance between which key was pressed and which element is selected, that should do the trick. For example, given your Selector’s setup,getSelector("smileys").test.selected( getImage("appropriate") )
will succeed only if L was pressed (at the moment of making the selection, that is)b.3) I’m not sure which second Selector you have in mind, but if I understand your design correctly, you want the message “press the spacebar” to be visible even before the participant has pressed one of
A
,G
orL
(and, consistently, have a warning message appear if they press the spacebar beforeA
,G
orL
). So you don’t want to wait for a selection to happen before printing the “press the spacebar” message and listening to a keypress on the spacebar. In other words, you don’t want to put the script on hold by using await
command on the Selector’s element before getting to your Key element’swait
command. But you only want to validate that Key element’swait
command if a selection has been made, hence thetest
command inside itJeremy
November 5, 2021 at 11:00 am #7484HPIParticipantHi,
I think I made it to solve almost all the issues of this thread, the only thing remaining is that I don’t get a column with RT if I calculate it within the script.I tried what you suggested:
newTrial( newVar("rt", 0).global().set(v=>Date.now()) , newButton("Click me!").print().wait() , getVar("rt").set(v=>Date.now()-v) ) .log("RT", getVar("rt"))
And the newTrial is actually the running trial reading a line of the template.
So as summary: the participant press the spacebar, a picture appears, press the spacebar and a sentence appears, press the spacebar and a ratingscale appears.
Now I am trying to have a column for the time they need to read the sentence, so I want the time from the pressing to load the sentence to the pressing to loading the scale.
So I placed newVar before the first target key press, and getVar after they pressed to load the scale.
Then when the trial ended and there is the all logging of conditions and results I added .log(“RT”..)The problem is that I don’t see this RT “column” in the results table.
In addition, either that I open the results with plain excel, or that I load them in R with the function, the results are in a format in which each event is a line (press the key, load this and that…everything is a line) and a trial is like the block of ten lines. In this logic I don’t understand how this new RT datum should be formatted, should it appear as a line? If it has to appear as a column then it must add a column RT (meaningless when reading a single line) to each line with the value of RT calculated in that point.Is there a way to process this result table in a more meaningful way? Like having a line corresponding to a trial, and all the parallel info (like the time to load the instructions, as a column : Time of instructions, which would be constant with the respect to the trial, the instructions are loaded once and that’s it). If a trial is a line, then it would have a sense to a column RT.
I hope I explained the issue sufficiently well.
HPINovember 5, 2021 at 1:39 pm #7485JeremyKeymasterHi,
1) If you want the time between the sentence and the scale, you should place the
newVar
command before the second key press (the one just before the sentence appears) and thegetVar
command after the third key press (the one that precedes the scale appearing)2) That “RT” column will only be included in the lines that correspond to that
newTrial
command. If you have lines in your results file coming from, say, intro/welcome/end/etc. trials, they won’t include an “RT” column because their correspondingnewTrial
s don’t have the same.log
command (because there’s no RT to compute for those trials). Is the RT column missing from the lines corresponding to thenewTrial
that was embedded inTemplate
too?3) You can find an example of how to analyze data in R in the advanced tutorial: in this example, reaction times are calculated post-hoc by subtracting event times coming from different lines from the same trial. Note that the table resulting from the piece of code below (copied from the tutorial page) follows the one-line/one-trial format that you seek:
tidied_results <- tidied_results %>% mutate(reaction_time = selection_time - canvas_time, correct = if_else(condition == selection, 1, 0))
Jeremy
November 25, 2021 at 12:08 pm #7526HPIParticipantDear Jeremy,
I have noticed that the calculation of RT within the script is reported in the results, but it’s not correctly reported if I pass the table in R with the tidyverse function.
Do you know what might be the reason?Then:
I am implementing the practice, and the practice must provide feedback so that it can be “assured” the participant has understood the task, and should allow to start the experiment over X trials correctly answered, otherwise it should reload the practice.
Summary: spacebar – loadpicture; spacebar – load sentence – spacebar – load a canva with smileys representing 3 level oc categorical judgment.I guess I have to make a column for the expected key each trial of the practice, then after each answer it should check whether the key match or not, if the pressed key is different it should provide the feedback like a text message, and a counter must go up of 1. If the counter at the end of the practice is higher than, let’s say 5, it should reload the trial practice, if it’s below 5, it should load the experimental trial.
Do you think is implementable? Do you have any tips on how to write in javascript?
I attach the piece of code that loads the scale with the keypress.
Thank you so much for your help,
HPInewText("How appropriate is the sentence describing the picture?") .css("font-size", 18) .css("font-family", "Verdana", "sans-serif") .center() .print() .log() , newCanvas( "Smiley_Scale_practice" , 1000 , 107 ) .settings.css( "border" , "solid 1px white" ) .settings.center() .settings.add( 100,0, newImage("inappropriate", "sad.jpg") ) .settings.add( 450,0, newImage("infelicitous", "neutral.jpg") ) .settings.add( 800,0, newImage("appropriate", "happy.jpg") ) .print() .log() , newCanvas( "Smiley_Scale_Label_practice" , 1000 , 35 ) .settings.css( "border" , "solid 1px white" ) .settings.css("font-size", 18) .settings.css("font-family", "Verdana", "sans-serif") .settings.center() .settings.add( 70,0, newText("1 sad", "V - inappropriate" ) ) .settings.add( 325,0, newText("2 neutral", "B - neither inappropriate nor appropriate ") ) .settings.add( 780,0, newText("3 happy", "N - appropriate") ) .print() .log() , newVar("RT_smiley_practice", 0).global().set(t_s =>Date.now()) , getCanvas("Smiley_Scale_practice") .refresh() .log() , getCanvas("Smiley_Scale_Label_practice") .refresh() .log() , newText("warning_practice", "Please provide a judgment before you can continue") .css("font-size", 20) .css("font-family", "Verdana", "sans-serif") //.css("width", "40em") .center() .color("red") .hidden() .print() ,
November 26, 2021 at 3:13 pm #7527JeremyKeymasterHi,
I have noticed that the calculation of RT within the script is reported in the results, but it’s not correctly reported if I pass the table in R with the tidyverse function.
Do you know what might be the reason?By “the tidyverse” function, do you mean this?
tidied_results <- tidied_results %>% mutate(reaction_time = selection_time - canvas_time, correct = if_else(condition == selection, 1, 0))
This piece of code calculates reaction times post-data-collection, based on the timestamps of each event reported in the results file. In our messages, we had discussed using a Var element to calculate reaction times during runtime and report them as an extra column in every row of the corresponding trial. That solution doesn’t require the table transformation illustrated in the piece of code above
I guess I have to make a column for the expected key each trial of the practice, then after each answer it should check whether the key match or not, if the pressed key is different it should provide the feedback like a text message, and a counter must go up of 1. If the counter at the end of the practice is higher than, let’s say 5, it should reload the trial practice, if it’s below 5, it should load the experimental trial.
This is what I would do indeed. You don’t need to write (non-PennController) javascript code for that, PennController will provide you with what you need
I’ll illustrate with an example here, as I lack information to give a solution adapted to your case, and I actually think doing that would obscure the reasoning anyway. In this example, I want the participant to give more than 2 correct responses before they can proceed:
Sequence( "prepractice", randomize("practice"), "postpractice" ) // (Re)set the Var element to 0 before running the practice session newTrial("prepractice", newVar("practice_score").global().set(0) ) // Very simple trial structure for illustration Template( "table.csv" , row => newTrial( "practice", newText( row.question ).print() , newScale("answer", "Yes", "No") .button() .print() .wait() .test.selected( row.correct ) // Increment if correct answer .success( getVar("practice_score").set(v=>v+1) ) ) ) newTrial("postpractice", // Check the value after the practice session getVar("practice_score").test.is(v=>v>2) .failure( newText("Sorry, you do not meet the threshold").print() , newButton("Take the practice again").print().wait() , // jump will make the experiment go back to "prepractice" after this trial jump("prepractice") ) )
This is the table I used:
question,correct say yes,Yes say no,No don't say yes,No don't say no,Yes
Let me know if you have questions
Jeremy
November 29, 2021 at 12:15 pm #7534HPIParticipantHi,
sorry for the late reply, I didn’t get or notice the notification you replied.. THANK YOU! 😀The training (counting the correct answers) works perfectly, I didn’t know I could do it this way.
newSelector("smileys_practice") .disableClicks() .add( getImage("inappropriate"), getImage("infelicitous"), getImage("appropriate")) .keys( "V" , "B" , "N" ) .once() .log() .wait() .test.selected( variable_practice.Right_Key ) // Increment if correct answer .success( getVar("practice_score").set(s_p=>s_p+1) ) .failure(newText("negative feedback", "Wrong answer!") .log() .print() .center() .cssContainer({"font-size": "160%", "color": "red"}) ) ,
I was trying to implement the feedback in case the answer is wrong. This, I don’t know if it’s doable or not, cause I should provide different feedback in case the participant doesn’t answer correctly to a trial belonging to the specific condition (inappropriate, infelicitous, appropriate), like “this sentence is not appropriate because in the picture ABC is depicted”. (The participant is exposed to a picture, then to a sentence, and has 3 keys to rate the sentence, matching 3 emoticons, happy sad neutral).
So in this way, I would have 3 standard feedback to assign in case they get some trials wrong in condition “inappropriate”, some trials wrong in condition “infelicitous”, some trials wrong in condition “appropriate”.
Maybe I should train them as 3 separate practices, but I am not sure whether it would become too “complicated” for the participant. 3 practices and the experiment.
The idea was that the trials were in one single practice, and considering the total amount of trials, they should pass the threshold value.Is there a way to provide feedback according to the condition of the wrong trial?
——————————-
Latin Square: Does the system recognize to load the items belonging to a single group, by simply adding the column “Group” to the template? Should I specify something in the code?
(Should the items belonging to Group 1 be lined up one after the other or is it ok if the table loads line 1 belonging to Group 1, line 2 belonging to Group 2 etc… )November 29, 2021 at 12:43 pm #7536JeremyKeymasterHi,
Is there a way to provide feedback according to the condition of the wrong trial?
Could you pass it in a column? Like
newText("negative feedback", variable_practice.negative_feedback )
. Or you could map a condition column to each message using a Javascript hash:newText("negative feedback", { appropriate: "Wrong answer!", inappropriate: "This sentence is not appropriate because in the picture ABC is depicted", infelicitous: "This sentence is not felicitous because blablabla" }[variable_practice.condition] )
Latin Square: Does the system recognize to load the items belonging to a single group, by simply adding the column “Group” to the template? Should I specify something in the code?
Yes it does: PennController will choose one value out of all the different values listed in the Group column, and only use the rows that contain that selected value in that Group column to generate trials, as explained here
(Should the items belonging to Group 1 be lined up one after the other or is it ok if the table loads line 1 belonging to Group 1, line 2 belonging to Group 2 etc… )
It doesn’t matter how you order your rows. PennController will list the different values in an alphanumeric order, and automatically pick one based on the value of the counter: if you have 3 groups named “A”, “B” and “C” and a participant takes your experiment with a counter value of 5, PennController will only use the rows where the Group column is “C” (because the mapping is {0->A; 1->B; 2->C} and 5 modulo 3 is 2)
Jeremy
November 29, 2021 at 1:00 pm #7538HPIParticipantThank you!
-
AuthorPosts
- You must be logged in to reply to this topic.