Jeremy

Forum Replies Created

Viewing 15 posts - 46 through 60 (of 1,522 total)
  • Author
    Posts
  • in reply to: Eyetracking data analysis #10814
    Jeremy
    Keymaster

    Hi,

    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 where time is lower than that number

    3. 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 want

    Jeremy

    in reply to: About timeouts #10812
    Jeremy
    Keymaster

    Hi 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 the wait on the Selector element has been released, is one solution to make sure that the trial doesn’t end before the audio is done playing

    Jeremy

    in reply to: About timeouts #10804
    Jeremy
    Keymaster

    It won’t make a difference, since the wait command will be released as soon as getTimer("timeout").stop() from the callback command has been executed; the command getAudio('keyPressAudio').play() inside callback will just run in parallel to getImage('stimuli').remove() and the commands coming after that (including the set commands further down) from the main thread

    Jeremy

    in reply to: About timeouts #10801
    Jeremy
    Keymaster

    You want to replace getKey("answerKey").disable().test.pressed("K", "S") with getKey("answerKey").disable().test.pressed(): this line is in a failure 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 pressed

    Other than that I don’t see any problems with this piece of code

    Jeremy

    in reply to: About timeouts #10799
    Jeremy
    Keymaster

    Hi,

    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 the callback command: here, the script learns that whenever the participant presses S or K, the command getTimer("timeout").stop() should take effect. But importantly, there is no wait 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 a wait 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 preceding callback 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

    Jeremy
    Keymaster

    Hi,

    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 of rshuffle 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 row

    If you don’t want the sort of even distribution you get from rshuffle, then randomizeNoMoreThan is the way to go. Just make sure you have proper references to your trials’ labels

    Jeremy

    in reply to: Media Recorder Technical Details #10793
    Jeremy
    Keymaster

    Hi,

    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

    Jeremy
    Keymaster

    Hi,

    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

    in reply to: GetVar Error #10787
    Jeremy
    Keymaster

    Hi,

    You cannot reference a Var element in a newX command, because elements are created upon opening the experiment but evaluated upon runtime

    The 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

    in reply to: Update a var only after button click #10785
    Jeremy
    Keymaster

    This issue was reported as resolved in a private email exchange, through the use of the callback command

    Jeremy

    in reply to: Eyetracking output file timestamps #10783
    Jeremy
    Keymaster

    Hi,

    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 the times 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’s start timestamp (not sure which of the two starts though, but you can determine that using the timestamps of print on the Left and Right Canvas elements, since you print those between the tracker’s first and second starts). 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 trial

    Jeremy

    in reply to: Subject missing #10780
    Jeremy
    Keymaster

    This issue was addressed in a private email exchange

    Jeremy

    in reply to: Can we change the recording authorization text? #10771
    Jeremy
    Keymaster

    Hi,

    My bad, I read your message too fast. There’s no problem with changing the message in PennController.js

    Jeremy

    in reply to: Can we change the recording authorization text? #10768
    Jeremy
    Keymaster

    Hi,

    Pass a custom message as the second parameter of InitiateRecorder

    Jeremy

    Jeremy
    Keymaster

    Hi Kate,

    Your Sequence contains rshuffle("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. Use startsWith("experiment_") instead

    The 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 of newTrial() instead (the one before the comma you placed above Sequence)

    Jeremy

Viewing 15 posts - 46 through 60 (of 1,522 total)