Forum Replies Created
-
AuthorPosts
-
Jeremy
KeymasterHi,
1. The analysis part is up to you. If you discard the (0,0) data points to focus on (0,1) vs (1,0), you’ll be looking at left-vs-right preference when the participant is (estimated to be) looking at either left or right; but keep in mind that it could be that the participant is not looking at either the left or right image for some time. For example, you could get a 30% left vs 70% right distribution when discarding the (0,0) data points, but only (15% left vs 35% right) vs 50% neither when factoring in all the data points
2. Subtract the EventTime value of the tracker element from the EventTime value of the audio element from your results file: you’ll get the offset for when the audio started relative to when the tracker started. Then add 697 to that number, and you’ll get the offset relative to the tracker’s start time for the word onset. Then you can compare that number to the
time
values from the eye-tracker data file and, for example, discard all the lines wheretime
is lower than that number3. It is not possible to add a column to the eye-tracking data file during runtime. However you can use the
trial
column from that file to cross-reference the PennController trial ID from the results file, and add an “itemNo” column during analysis if you wantJeremy
Jeremy
KeymasterHi Larissa,
If you end the trial immediately after a selection is made, there just won’t be enough time to hear the audio which starts playing but is stopped immediately, along with the trial’s end. Using
wait
on the Audio element, as in your last message, after thewait
on the Selector element has been released, is one solution to make sure that the trial doesn’t end before the audio is done playingJeremy
Jeremy
KeymasterIt won’t make a difference, since the
wait
command will be released as soon asgetTimer("timeout").stop()
from thecallback
command has been executed; the commandgetAudio('keyPressAudio').play()
insidecallback
will just run in parallel togetImage('stimuli').remove()
and the commands coming after that (including theset
commands further down) from the main threadJeremy
Jeremy
KeymasterYou want to replace
getKey("answerKey").disable().test.pressed("K", "S")
withgetKey("answerKey").disable().test.pressed()
: this line is in afailure
command which already corresponds to a situation where the correct key wasn’t pressed so if, in that situation,test.pressed()
succeeds it means that the incorrect key was pressed, and if it fails it means that no key was pressedOther than that I don’t see any problems with this piece of code
Jeremy
Jeremy
KeymasterHi,
callback
commands inform the script of what to do whenever the relevant event happens, and immediately move on to the next line in the script. By contrast,wait
commands halt the execution of the script until the relevant event happens, after which only do they move on to the next line in the script. When you have these lines in a script:newTimer("timeout", 5000).start() // A , newVar("RT").global().set( v => Date.now() ) // B , newKey("answerKey","SK").log("all").callback( getTimer("timeout").stop() ) // C , getTimer("timeout").wait() // D , getVar("RT").set( v => Date.now() - v ) // E
The script first executes (A): it starts a 5s timer and moves on to (B) without waiting for the timer to elapse (because there is no
wait
command in A). At (B), which is executed immediately after (A), the scripts sets the Var element to the current timestamp, ie. a timestamp that corresponds to when the timer was started. The script immediately moves on to (C), which evaluates thecallback
command: here, the script learns that whenever the participant presses S or K, the commandgetTimer("timeout").stop()
should take effect. But importantly, there is nowait
command in (C) so the script immediately moves on to (D), but it now keeps in mind what should happen were the participant to press S or K at any point. At (D) the script sees await
command so it stays on (D) until the timer has stopped. This could happen because the 5s have elapsed, the normal course of events for a timer; or it could happen because the timer was stopped early, which is precisely what we instructed the script to do if the participant ever presses S or K, in the precedingcallback
command. So when the timer stops, regardless of which scenario we’re in, the script then moves on to (E) and sets the Var element to the current timestamp minus the previous one. If we’re in a scenario where the participant didn’t press S or K, then the script must have reached this line after waiting 5s, so the subtraction will result in that duration. But if we’re in a scenario where the timer was stopped because the user pressed S or K, then it hasn’t been 5s yet, and the subtraction will reflect that, and the result of the subtraction will be a lesser value. Once the Var element has been set, the script immediately moves on to the next line (if any)Jeremy
August 2, 2023 at 2:30 am in reply to: Question about assigning conditions, groups + randomization #10796Jeremy
KeymasterHi,
As per the IBEX documentation,
rshuffle
will evenly distribute the trials as identified by the labels you pass to the function. If you label your filler trials differently from the other ones, and one argument ofrshuffle
captures those labels, then it will try to separate any two filler trials by the same number of other trials. Using that method, as long as you don’t have 6 times as many filler trials as other trials, you shouldn’t end up with 6 fillers in a rowIf you don’t want the sort of even distribution you get from
rshuffle
, thenrandomizeNoMoreThan
is the way to go. Just make sure you have proper references to your trials’ labelsJeremy
Jeremy
KeymasterHi,
The MediaRecorder element does not place any constraints over transfer, it is the browser that requires CORS validation when sending a POST request from one domain (farm.pcibex.net) to a different domain (where your server is hosted). It could be that you somehow overrode the certificate’s invalidity in your instance of Firefox, but other browsers will just refuse to proceed with the POST request in the absence of a valid certificate
It is possible to use a self-signed certificate, but you’ll likely run into issues like the one you describe here. If possible, I recommend using certbot to automatically get letsencrypt certificates, which won’t necessitate manual approval
Jeremy
July 24, 2023 at 10:27 am in reply to: Question about assigning conditions, groups + randomization #10789Jeremy
KeymasterHi,
You don’t have to make them uniform, but one thing you can do is check for the presence of columns before logging them, eg:
.log("adjectivenumber", "adjectivenumber" in row ? row.adjectivenumber : "") .log("adjectiveclass", "adjectiveclass" in row ? row.adjectiveclass : "") .log("pair", "pair" in row ? row.pair : "") .log("context_adjective", "context_adjective" in row ? row.context_adjective : "") .log("target_adjective", "target_adjective" in row ? row.target_adjective : "") .log("target_polarity", "target_polarity" in row ? row.target_polarity : "") .log("contextcomparative", "contextcomparative" in row ? row.contextcomparative : "") .log("comparativequestion", "comparativequestion" in row ? row.comparativequestion : "") .log("contextequative", "contextequative" in row ? row.contextequative : "") .log("equativequestion", "equativequestion" in row ? row.equativequestion : "") .log("questionquestion", "questionquestion" in row ? row.questionquestion : "")
Jeremy
Jeremy
KeymasterHi,
You cannot reference a Var element in a
newX
command, because elements are created upon opening the experiment but evaluated upon runtimeThe solution is to use the
.text
command:newTrial('test', newVar('var-int','hello') , newText('text') .text( getVar('var-int') ) .print() , newButton('button','Click') .print() .wait() )
Jeremy
Jeremy
KeymasterThis issue was reported as resolved in a private email exchange, through the use of the
callback
commandJeremy
Jeremy
KeymasterHi,
You are not supposed to call
start
on an EyeTracker element that’s already started. When.log
is called on the EyeTracker element, lines are added to the results file, including one line that tells you when.start
was executed and reporting the corresponding timestamp. Then you can use thetimes
column from the .csv output file to calculate when each gaze estimate was recorded (EventTime
+times
). For example, the value of 0 in your sample simply corresponds to the tracker’sstart
timestamp (not sure which of the twostart
s though, but you can determine that using the timestamps ofprint
on the Left and Right Canvas elements, since you print those between the tracker’s first and secondstart
s). Comparing those values with the timestamps reported in your results file for other events, such as audio start/stop, will give you an idea of where the participant was looking during the unfolding of the event in the trialJeremy
Jeremy
KeymasterThis issue was addressed in a private email exchange
Jeremy
Jeremy
KeymasterHi,
My bad, I read your message too fast. There’s no problem with changing the message in PennController.js
Jeremy
Jeremy
KeymasterJuly 20, 2023 at 3:40 am in reply to: Question about assigning conditions, groups + randomization #10767Jeremy
KeymasterHi Kate,
Your
Sequence
containsrshuffle("experiment", startsWith("experiment"))
and both your target and filler/MP trials have labels that start with “experiment” (it actually is the whole label for the latter) so the latter are included twice. UsestartsWith("experiment_")
insteadThe stack of
.log
commands starting with.log("adjectivenumber", row.adjectivenumber)
are attached to the preceding.wait()
command relative to the Scale element. You want to attach it to the closing parenthesis ofnewTrial()
instead (the one before the comma you placed aboveSequence
)Jeremy
-
AuthorPosts