Jeremy

Forum Replies Created

Viewing 15 posts - 1,021 through 1,035 (of 1,522 total)
  • Author
    Posts
  • in reply to: Pausing experiment #6408
    Jeremy
    Keymaster

    Hi,

    Would you mind sharing the link to your experiment with me, either here or privately at support@pcibex.net? The end command only stops the current trial, so if it runs through the end of your experiment, it may be coming from an interaction with your specific design

    Oh and I forgot to address the “pause” component from your first message. One option is to add a Header that will pause execution if a Var element has been set to true when clicking the button, eg:

    Header(
      newVar("pause", false).global().test.is(true).success(
        newButton("Resume").print().wait().remove(),
        getVar("pause").set(false)
      )
    )

    Of course you also want to add getVar("pause").set(true) before end in the callback of your pause button

    Jeremy

    Jeremy
    Keymaster

    Glad you found a solution!

    For reference, b64_md5 is a function defined as part of Ibex, it is not a standard javascript function. It expects a string passed as its argument (Date.now() + Math.random() is a number, which is why it needs to be converted into a string with .toString()) and outputs an encoded string uniquely corresponding to the input string

    Jeremy

    in reply to: Adding break trials #6406
    Jeremy
    Keymaster

    Hi Aliona,

    One option would be to use the pick function defined in this thread:

    critical = randomize("critical_trials")
    fillers = randomize("fillers")
    
    Sequence( 
      rshuffle(pick(critical,7),pick(fillers,10)),"break",
      rshuffle(pick(critical,7),pick(fillers,10)),"break",
      rshuffle(pick(critical,6),pick(fillers,10))
    )

    Let me know if you have questions

    Jeremy

    in reply to: Response time limit #6404
    Jeremy
    Keymaster

    Hi Rosa,

    I am not able to reproduce your keypress problem: the experiment does proceed to the next trial as soon as I press the spacebar when I see the “Press SPACEBAR” message, regardless of whether or which key I pressed during the 2000ms. Do you have another Key element named “spacebar” in your trial by any chance, or any other conflicting Key element in a Header or a Footer? You could also try disabling Key elements after you’re done with them, e.g. add getKey("response").disable() before your “spacebar” Key element (but again, I can’t identify your problem so it’s just a wild guess)

    Regarding the conditional feedback messages, you can do something like this:

    getKey("response")    
        .test.pressed()
        .success( getKey("response").test.pressed(row.answer)
            .failure(newText("negative feedback", "Wrong answer!")
                .log()
                .print()
                .center()
                .cssContainer({"font-size": "160%", "color": "red"})
            )
        )
        .failure(newText("slow", "Too slow...")
            .log()
            .print()
            .center()
            .cssContainer({"font-size": "160%", "color": "red"})  
        )

    Let me know if you have questions

    Jeremy

    in reply to: change the length/color of the slider #6397
    Jeremy
    Keymaster

    Hi August,

    Apparently there is a max-width CSS property that’s being set to content in some versions of PennController, which limits the maximum size you can pass. Just add .css("max-width", "unset") after your size command and that should do the trick

    As for the color, the default rendering of the slider is handled different by each browser. If you want to modify its aesthetics, you’ll have to do some CSS magic

    Jeremy

    in reply to: Some results not captured #6396
    Jeremy
    Keymaster

    Sorry, my explanations of the timeline weren’t clear, so I will walk through them in more detail.

    The first lines, the ones with “0ms” on the left, correspond to the execution of the lines from your script starting with newImage("fixationpoint", row.Fixation), which is executed immediately after the end of your Header, up to newTimer(700).start().wait(): all of them are executed so quickly that they virtually take no time, which is why I associated them all to the 0ms time point.

    After the two wait commands on your first (unnamed) Timer elements have finished running, the script reaches the line getImage("fixationpoint"): that’s where the timeline reaches the time point “1850ms.” All the lines from that one up to newTimer("exposure", 300).start().wait() are executed in the blink of an eye, including the callback command of your Key element. Crucially, that command has an effect lasting for most of the rest of the timeline: from that time point on, whenever the participant presses the left or the right arrow, both the “exposure” and the “timeout” Timer elements will be stopped (if they were running during the keypress, that is).

    After that time point, the timeline is no longer purely deterministic, because the course of events will depend on whether the participant does or doesn’t press a key during the execution of the Timer elements. Starting at time point 1850ms, the “exposure” Timer element starts and will run for 300ms unless the participant presses the left-arrow or right-arrow key. If the participant does not press a key, then the “exposure” Timer element elapses entirely and you are 2150ms in the trial. If the participant does press one the two arrows before that, the “exposure” Timer element is stopped prematurely and you are anywhere between 1850ms and (strictly before) 2150ms.

    In either case, the “exposure” Timer element has stopped (either because it elapsed fully, or because it was ended prematurely) and the script reaches line getKey("pressOnArrow").test.pressed() and the corresponding failure command. That failure command will take effect only if the participant has not pressed one of the two arrows until then. Now remember, at this point, there are two possibilities: either the timer was ended prematurely by a keypress on one of the two arrows and the time point is not 2150ms yet, or the “exposure” Timer element has elapsed fully because no key was pressed and it has been 2150ms. Only in the latter case will the failure command take effect, and will the “timeout” Timer element start running and logging. If the participant did press a key (and it hasn’t even been 2150ms), then the “timeout” Timer element will not run and will not report any line to the results file.

    This means that if your results file does report lines for the “timeout” Timer element for an item, your participant has not pressed one of the two arrow keys during the 300ms “exposure” Timer element: any relevant keypress therefore happened more than 2150ms after the end of the Header. However, if you see no such lines for an item, it means that the participant did press one of the two arrow keys before the 300ms of the “exposure” Timer element elapsed entirely, and therefore the keypress happened before 2150ms-after-the-end-of-Header. Item 60 corresponds to the first case: subtracting the time event for the keypress from the time event for the end of the Header gives 3956ms, which is well past the 2150ms signaling the end of the (uninterrupted) “exposure” Timer element. Item 68, on the other hand, corresponds to the second case: the same subtraction gives 2044ms, which is before the “exposure” Timer element has had time to fully elapse, and so the failure command did not take effect and the “timeout” Timer element was not run at all for item 68.

    I hope the timecourse of events of your trials is clearer now. As I said, if you’re planning to re-run this, you could add a log command to your “exposure” Timer element so you get lines added to your results file reporting when that Timer element started (it should always be around 1850ms) and when it ended (anywhere between 1850ms and 2150ms).

    Let me know if you have any questions

    Jeremy

    in reply to: Change box size for question #6392
    Jeremy
    Keymaster

    Hi,

    It depends on how you implemented those multiple choice questions.

    You can see the general structure of any PennController element printed on the page here. You can also open your browser’s inspector to get a finer look at how the different elements are structured on the page and, most importantly, their CSS classes, and write rules accordingly in a file named global_z.css

    Or you can directly use the css and/or cssContainer commands on your elements, if it makes sense with the particular way you implemented your multiple choice questions

    Jeremy

    in reply to: Some results not captured #6390
    Jeremy
    Keymaster

    Hi,

    This doesn’t happen at random, it’s just consistent with your script: you only start and log the “timeout” Timer element if no key was pressed during the exposure period, otherwise you just never even deal with that Timer element, so it won’t appear in your results files. Here’s a step-by-step reading of your script (the “any time”s correspond to whether the participant pressed a key that would stop the timers prematurely):

        0ms     print "fixationpoint" ; print "primero"
                start playing "primero" ; start 700ms timer and wait
      
        [     ...     ]
    
      700ms     start playing "segundo" ; start 1150ms timer and wait
    
        [     ...     ]
    
     1850ms     remove "fixationpoint" ; print "num"
                listen to keypresses on left/right arrow (will be logged)
                associate keypresses with [ stop "exposure" ; stop "timeout" ]
                start 300ms "exposure" timer and wait
    
        [     ...     ]
    
    any time    remove "num"
    btw 1850    **if NO key was pressed (2150ms)**:
    & 2150ms      [ start 5000ms "timeout" timer (will be logged) and wait ]
    
    any time    stop listening to keypresses
    btw 1850    **if correct key was pressed*:
    & 7150ms      [ play "coin7" and wait ]
              
    any time    end of current trial
    btw 1850    move to next trial
    & 7150 +
    audio ms

    Consistently, you’ll find that for item 60, 3956ms elapsed between the reported keypress and the end of your Header, which necessarily means that no key was pressed during the exposure timer (which takes place between 1850 and 2150ms). For item 68, however, the keypress happened 2044ms after the end of your Header, which means approximately 100ms before the end of the “exposure” timer (or, 200ms after it started). So the failure command on the Key was just not validated (ie. a key had been pressed indeed at that point) and the “timeout” timer was just never started nor told to be logged. So there’s not really any data to recover here, because the “data” doesn’t correspond to anything that actually happened.

    Don’t you get the desired reaction time by subtracting the Header-end time event from the keypress time event though, the way I just did?

    You could also add log onto your “exposure” Timer element, which will add a line reporting when it started (and ended), so you can subtract the start time event from the keypress. It would probably more accurately reflect the reaction time you’re after, as I understand your design

    Jeremy

    in reply to: Conditional training phase #6387
    Jeremy
    Keymaster

    Hi Susanne,

    Sorry, I hadn’t understood your question. You are correct, it’s not possible to re-loop through training.csv using PCIbex at the moment.

    Let me know if you have more questions

    Jeremy

    in reply to: Conditional training phase #6385
    Jeremy
    Keymaster

    Hi Susanne,

    You can increment a Var element upon success, check the value of that Var element at the beginning of your trials and only run them if it’s below 2. No need to resort to plain javascript:

    Template("training.csv", row =>
        newTrial("training",
            newVar("training_successes", 0)
                .global()
                .test.is( v => v > 2 )
                .success( end() )
            ,
            newController("Maze", {s: row.Sentence, a: row.Distractor})
                .css("font-size", "1.5em")
                .css("font-family", "Verdana")
                .print()
                .log()
                .wait()
                .remove()
                .test.passed()
                .failure( newText("<br/>oops!").css("font-size", "1.5em").css("color", "red").print() )
                .success(
                    getVar("training_successes").set( v => v+1 ),
                    newText("<br/>great!").css("font-size", "1.5em").css("color", "green").print()
                )
            ,
            newTimer(500).start().wait()
        )
    )

    Let me know if you have questions

    Jeremy

    in reply to: Mouse cursor in the center of the screen #6380
    Jeremy
    Keymaster

    Hi Nicoletta,

    You cannot control the mouse cursor for security reasons, but what you can do is print a button at the center of the screen that needs to be clicked before proceeding:

    newButton("Go").print("center at 50vw", "middle at 50vh").wait().remove()

    Cross-referencing this topic: Centering mouse cursor at the start of the trial

    Jeremy

    in reply to: varying word presentation depending on length #6377
    Jeremy
    Keymaster

    Hi Yana,

    I think you’re doing the right thing inserting your code in the wordPauseTimeout function, but when I open the js file I see that line 152 is part of the wordTimeout function, so I just want to make sure you’re editing the right function.

    However I’m afraid that directly modifying t.wordTime will cause problems after encountering the first over-12-character word, because the subsequent words will inherit the extra duration. Here is how I rewrote the whole if statement, and it seems to be working smoothly:

    if (this.mode == "speeded acceptability") {
        var t = this;
        function wordTimeout() {
            t.blankWord(t.currentWord);
            ++(t.currentWord);
            if (t.currentWord >= t.stoppingPoint)
                t.finishedCallback([[["Sentence (or sentence MD5)", t.sentenceDesc]]]);
            else
                t.utils.setTimeout(wordPauseTimeout, t.wordPauseTime);
        }
        function wordPauseTimeout() {
            t.showWord(t.currentWord);
            t.utils.clearTimeout(wordPauseTimeout);
            let duration = t.wordTime;
            if (t.words[t.currentWord].length > 12) {
                var extraTime = (t.words[t.currentWord].length - 12) * 200;
                duration += extraTime;
            }
            t.utils.setTimeout(wordTimeout, duration);
        }
        wordPauseTimeout();
    }

    I used 200 so I could clearly tell when the extra time was added to the normal display time. For reference, here are the parameters I used to test the DashedSentence:

    {
      s: "Extralongitudinal is not a word that makes much anticonstitutional sense",
      wordTime: 250,
      mode: "speeded acceptability"
    }

    Jeremy

    in reply to: Editing red "recording…" message #6374
    Jeremy
    Keymaster

    Oh, right, my bad, that makes perfect sense actually, because the aesthetics changes along with the message by default. You’ll have to use the second, runtime method described above then

    Jeremy

    in reply to: Pausing experiment #6372
    Jeremy
    Keymaster

    Hi Nikhil,

    “Finish the trial” can mean vastly different things depending on your task and your desiderata. You’ll need to make decisions as to what, precisely, should happen with each element in your task when the button is clicked. A very radical and easy-to-implement option is to just drop everything altogether, all you need to do is print a button whose callback will call end:

    newButton("Stop").callback( end() ).print()

    You can use as many commands as you want in the callback, so if you need to do anything with your existing elements (eg. stop some audio playback) before ending the trial, just do it there too

    Let me know if you have questions as you implement your own solution

    Jeremy

    in reply to: Editing red "recording…" message #6371
    Jeremy
    Keymaster

    Hi,

    If you can live with the message having the same background color whether it says “Not recording” or “Recording…”, all you need to do is upload a file named global_z.css with the following:

    #bod table + div:last-child {
        background-color: lightblue !important;
    }

    If you want to use different custom colors for the two states, you’ll need to use the method from the message above:

    newTrial(
        newButton("Go fullscreen").print().wait().remove()
        ,
        fullscreen()
        ,
        newMediaRecorder("video").print().log().record()
        ,
        newFunction(()=>$("div:contains(Recording...)").css('background-color','lightblue')).call()
        ,
        newTimer(60000).start().wait() // Record for 1min
        ,
        newFunction(()=>$("div:contains(Recording...)").css('background-color','lightgray')).call()
        ,
        getMediaRecorder("video").stop()
        ,
        newButton("Next").print().wait()
    )

    Let me know if you still have questions

    Jeremy

Viewing 15 posts - 1,021 through 1,035 (of 1,522 total)