Jeremy

Forum Replies Created

Viewing 15 posts - 1,231 through 1,245 (of 1,522 total)
  • Author
    Posts
  • in reply to: Catch Trials #5650
    Jeremy
    Keymaster

    Hi Nickolas,

    I think I’d need to see your experiment, would you mind sharing its URL with me?

    Jeremy

    in reply to: Adding break trials #5647
    Jeremy
    Keymaster

    Hi Angelica,

    Rather than using modifyRunningOrder, prefer using a custom function in Sequence, as described on this thread. You could do this to insert a break-labeled trial every 5 trials into your rshuffle subsequence:

    Sequence("practice", sepWithN( "break" , rshuffle("vpe", "fillers") , 5 ) , "exit", "send", "confirmation")

    Best,
    Jeremy

    in reply to: Catch Trials #5643
    Jeremy
    Keymaster

    Hi Nickolas,

    1) I suspect that the audio filenames might not be consistent across groups in your main CSV table, for example maybe you typed uppercase extensions in some rows—you should double-check that
    The internal counter just keeps track of how many times your experiment was taken (since the last time you deleted the counter file, if you deleted it) but PennController (and Ibex, independently) cycle through it based on the number of groups in your design, eg. if you have 16 groups and a participant takes your experiment with counter 243, they’ll be assigned group 243%16=3

    2) You should not use ShuffleInChunks as the argument of modifyRunningOrder, in fact you should not call modifyRunningOrder: Ibex calls it internally. What you can do is (re)define it, and it will be executed after the whole sequence has been computed (from the Sequence command in PennController, from the shuffleSequence variable in native Ibex).
    PennController actually needs to define modifyRunningOrder, and this might cause conflicts with whatever you are trying to do. It’s better if you can avoid using the modifyRunningOrder method altogether. You can easily define your own function to insert an item ever N trials:

    function SepWithN(sep, main, n) {
        this.args = [sep,main];
    
        this.run = function(arrays) {
            assert(arrays.length == 2, "Wrong number of arguments (or bad argument) to SepWithN");
            assert(parseInt(n) > 0, "N must be a positive number");
            let sep = arrays[0];
            let main = arrays[1];
    
            if (main.length <= 1)
                return main
            else {
                let newArray = [];
                while (main.length){
                    for (let i = 0; i < n && main.length>0; i++)
                        newArray.push(main.shift());
                    for (let j = 0; j < sep.length; ++j)
                        newArray.push(sep[j]);
                }
                return newArray;
            }
        }
    }
    function sepWithN(sep, main, n) { return new SepWithN(sep, main, n); }

    Then, assuming you create a break trial labeled break, you can use it like this:

    Sequence(sepWithN( "break" , shuffleInChunks("main",14,"catch",1) , 30))

    Jeremy

    • This reply was modified 4 years, 6 months ago by Jeremy. Reason: replaced main.pop() with main.shift()
    in reply to: Reading results #5642
    Jeremy
    Keymaster

    Hi Zoe,

    1) The log command on a Key element (ie not the one on the closing parenthesis of newTrial), by default, reports a line in the results file for a keypress that validates a corresponding wait command—if you use log but you have no wait command, or if the Key element’s wait command was never validated (eg. because a Timer ended the trial early) then you’ll have a line in your results file that says “NA.” If the participant pressed a key anyway (hence without validating a wait command) you’ll have “(failed keypresses happened)” in the comments.
    As long as your line reports the key that was actually pressed (and that you care about) then you shouldn’t worry about that

    2) The newTrial().log commands append columns to the end of every result line for the corresponding trial, in the order in which they are used. If you have one newTrial with one log command, and another newTrial also with one log command, each trial’s result lines will append one additional column. If you want to use separate columns across trial, you need to keep track of your newTrial().log commands. E.g.:

    newTrial( newKey("press","Enter").wait(),newVar("key").global().set(getKey("press")) )
      .log( "key" , getVar("key") )
      .log( "rating" , "NA" )
    
    newTrial( newScale("scale", 10).print().wait(),newVar("rating").global().set(getScale("scale")) )
      .log( "key" , "NA" )
      .log( "rating" , getVar("rating") )

    Jeremy

    in reply to: Matching Participants on Race/Gender? #5639
    Jeremy
    Keymaster

    Hi Callie,

    I think it should work, yes, because you can configure CORS: you would need to allow GET for https://expt.pcibex.net/

    Note that the Spaces plans will only let you host resources (either individually or zipped) but you won’t be able to send data from your experiment, ie. DigitalOcean Spaces are not compatible with the MediaRecorder element and the EyeTracker element’s data-collection method.

    There are many factors that impact resource preloading. One of them is the bandwidth of the host server, so if you store your images on a fast server, they might load faster than from the PCIbex Farm (especially if the farm’s servers are busy). Using a ZIP file is actually likely to slow the initial preloading a little bit, because the experiment needs to download all the resources at once (the zip file) before it can preload any of them. But it is a more optimal option overall, because (i) one zip file is lighter than the total of all the resource files fetched individually, and (ii) it requires only one request to the server, when multiple concurrent requests can in some cases incur significant slowdowns.

    If preloading time is not that much of an issue, keep in mind that you can always store resource files (but not zip files) on free services like Google Drive or Dropbox (you just need to use a direct link, not a “share” link)

    Jeremy

    in reply to: Matching Participants on Race/Gender? #5636
    Jeremy
    Keymaster

    Hi Callie,

    I’m sorry, I didn’t realize that you can’t run server.py just like that (I tested the code on another server, on which it works)

    Replace server.py with experiment.html (if you’re not planning on using the withsquare method, otherwise simply add it to the list of parameters of window.open and it should also work)

    When I try to run your experiment with a valid URL, I get two errors: “No column named ‘race’ found in the table for filtering” (I looked up your CSV table, all the columns start with an uppercase letter—fix the sex column name too) and “newButton.wait is not a function” (this is your very last command, just add a pair of parentheses after newButton)

    Jeremy

    in reply to: Play Zipped Audio Files in CSV Template #5634
    Jeremy
    Keymaster

    Hi,

    Glad you were able to solve the issue

    Just a comment to say that the 404 messages are expected: PennController tries to locate the resources at different locations, starting with the experiment’s host, and from within the zip file in parallel. The 404 responses just inform you that the resources are not located on the experiment’s host

    Jeremy

    in reply to: Catch Trials #5627
    Jeremy
    Keymaster

    Hi Nickolas,

    So if I understood you correctly, you need to present your trials in blocks of N trials each, each block consisting of N-1 test trials and 1 catch trial presented in a total random order, ie. within each block whether the catch trial occurs at the beginning, in the middle or at the end is random—as a consequence, no two catch trials can be separated by more than 2*(N-1) test trials. Did I get this right?

    I wrote this to do just what I described, but feel free to edit the code if your needs are different:

    function ShuffleInChunks(...args) {
        this.args = [];
        this.numbers = [];
        for (let i = 0; i < args.length; i++){
            if (i%2) this.numbers.push(args[i]);
            else this.args.push(args[i]);
        }
        
        this.run = function(arrays) {
            let newarray = [];
            for (let i = 0; i < arrays.length; i++) fisherYates(arrays[i]);
            while (arrays.filter(a=>a.length>0).length){
                let currentChunk = [];
                for (let i = 0; i < arrays.length; i++) {
                    let currentArray = arrays[i]
                    for (let n = 0; n < this.numbers[i]; n++){
                        if (currentArray.length) currentChunk.push(currentArray.pop());
                        else break;
                    }
                }
                fisherYates(currentChunk);
                newarray = newarray.concat(currentChunk);
            }
            return newarray;
        };
    }
    function shuffleInChunks(...args) { return new ShuffleInChunks(...args) }

    You can use it like this, which would give you blocks of 11 trials---10 test trials and 1 catch trial, randomly shuffled:

    Sequence( shuffleInChunks("test",10,"catch",1) )

    To answer your question, Template does not return an array, it actually feeds the native-Ibex items array with the output of each newTrial loop on the table's row. It is also executed asynchronously, which means that you cannot simply write a Template command in your script and operate on its output by just writing some more code below it. This is why I'm suggesting the solution above: not only is it conceptually cleaner (you can directly tell the trial order just by looking at Sequence) but the trial order as defined by Sequence is computed after the native-Ibex items array has been filled, including with the outputs of Template.

    Let me know if you have questions

    Jeremy

    in reply to: Matching Participants on Race/Gender? #5624
    Jeremy
    Keymaster

    Hi Callie,

    Update your version of PennContoller to 1.8 following this method

    Jeremy

    in reply to: zip downladed but not preloaded #5622
    Jeremy
    Keymaster

    So I took a look at your experiment, and if I understand correctly the audio files that are played more than once only belong to the unique test trial, am I right? So if things work without using a list, and sincecopies you have only one row in your table, why not get rid of the Template and directly code your newTrial there?

    Another solution would be to create duplicates of the repeating files, eg. oven1.mp3 and oven2.mp3

    I understand that neither is an ideal solution, and I’ll try to identify and fix the problem in the next release of PennController. That being said, I didn’t seem to have a problem when I took the experiment. I don’t quite understand why the problem is not systematic and should only happen sporadically…

    Another thing I noted is that the script seemed to freeze (or take a very long time) when sending my recording, so I just quit the page. I guess it’s not very surprising, given that you record a video during the whole duration of the test trial, which is pretty long. The video file is then probably in the order of tens to hundreds of MBs, so it will take a very long time to upload, if it ever succeeds. If it’s a possibility for you, I would strongly suggest you split the recording in smaller chunks, which means splitting your single test trial into smaller chunk trials too. This way, you could use a non-blocking UploadRecordings after each smaller test trial: not only will it start sending the recordings while your participants are still completing the task, it will also send smaller files, which is less likely to hit size limits (some PHP configs come with a 100MB file upload limit by default).

    Jeremy

    in reply to: zip downladed but not preloaded #5619
    Jeremy
    Keymaster

    Hi Irene,

    I’m sorry you’re experiencing this problem. Yes, playing the same file multiple times within a single trial may be the source of the problem. Do you mind sharing the link to your experiment with me?

    Jeremy

    in reply to: Safari Compatibility #5616
    Jeremy
    Keymaster

    Hi Nickolas,

    You can try replacing the fullscreen() command with this:

    newFunction( ()=> {
      if (document.documentElement.requestFullscreen)
        document.documentElement.requestFullscreen();
      else if (document.documentElement.mozRequestFullScreen) /* Firefox */
        document.documentElement.mozRequestFullScreen();
      else if (document.documentElement.webkitRequestFullscreen) /* Chrome, Safari and Opera */
        document.documentElement.webkitRequestFullscreen();
      else if (document.documentElement.msRequestFullscreen) /* IE/Edge */
        document.documentElement.msRequestFullscreen();
    })
    .call()

    Jeremy

    in reply to: Server details #5614
    Jeremy
    Keymaster

    There is no online documentation about these points at the moment

    Florian Schwarz and I currently use Linode’s services to host the PCIbex Farm, where the design materials and the results files are stored. So in addition to you, Florian and I (as admins) can also get access to your results files, and probably some people at Linode too, theoretically. If you want to be the very single person with access to the results files, you will need to set up your own servers on a physical machine of yours (otherwise sysadmins can always, theoretically, get access to your files). Alternatively, institutions like universities often give you access to your own space on their own servers, so the IRB might be happier if you can use your university’s resources—you’ll need to make sure you can set up the proper configuration to run a standalone experiment though. See the original Ibex documentation to learn how to set up your experiment on your server.

    Let me know if you have any questions

    Jeremy

    in reply to: Questionnaire with questions on the same page #5611
    Jeremy
    Keymaster

    Use .failure, like this:

    newButton("next", "Next")
        .print()
        .wait( test.failure( 
            newText("Please answer all the questions").print() 
        ) )

    Jeremy

    in reply to: Safari Compatibility #5609
    Jeremy
    Keymaster

    Hi Nickolas,

    I’m sorry you’re experiencing issues with Safari. PennController’s support of Safari is unfortunately lower, mostly because I don’t really have access to that browser. Do you use fullscreen in your experiment? Or audio playback/recording? Those are features that are known to be problematic with Safari in their current form in PennController. Feel free to send me the link to your experiment so I can take a closer look at it

    Jeremy

Viewing 15 posts - 1,231 through 1,245 (of 1,522 total)