Randomization of Stimuli Across Blocks

PennController for IBEX Forums Support Randomization of Stimuli Across Blocks

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #5705
    AndreasK
    Participant

    Hi Jeremy,

    First of all, thank you very much for all the helpful answers on the support page. They’ve helped me a lot so far but I haven’t been able to figure out a solution for my current problem.

    I’m planning a recall task with two blocks. During the first block, participants will hear the stimuli in a familiar accent and during the second block, they will hear it in an unfamiliar accent. In total, there are 24 stimuli, which I have saved in a table.

    What I would like to achieve is that 12 stimuli are randomly selected for the first block. The second block should then include the remaining 12 stimuli. I would like this choice to be randomized for each participant, such that participants A and B will hear different stimuli in the first (and second) block.

    I thought I could use two tables and Templates, one for each block. However, I can only randomize the order within each block in this way. Participants A and B would still hear the same stimuli in each block, just in a different order. Is there a way to randomize it differently to get the desired outcome?

    I also thought that I could simply produce different lists for each participant individually but this seems like a lot of manual effort so I was wondering if there is a way of doing it more easily with pcIBEX.

    Apologies if this query has already been answered elsewhere.

    Andreas

    #5706
    Jeremy
    Keymaster

    Hi Andreas,

    Here’s an example of what you can do. I use left-right vs right-left spelling to represent your design’s different accents, but in your case you probably want to point to different audio files. I’m also defining only 4 items, but set NITEMS to 24 if this is how many items you have (make sure you have 24 corresponding rows in your table—25 including the header)

    AddTable("myTable", `leftRight,rightLeft
    hello,olleh
    world,dlrow
    bye,eyb
    mate,etam`)
    
    NITEMS = 4
    order = [...new Array(NITEMS)].map((v,i)=>i<NITEMS/2).sort(v=>Math.random()>=0.5)
    
    Sequence( randomize("leftRight") , randomize("rightLeft") )
    
    Template( "myTable" , row =>
      newTrial( (order[0]?"leftRight":"rightLeft") ,
        newText( (order.shift()?row.leftRight:row.rightLeft) ).print()
        ,
        newButton("Next").print().wait()
      )
    )

    Let me know if you have any questions

    Jeremy

    #5720
    AndreasK
    Participant

    Hi Jeremy,

    Thanks a lot for your response.

    This code is really helpful but, if I understand it correctly, it always chooses ‘hello’ and ‘world’ for the first two trials (i.e. first block) and then ‘eyb’ and ‘etam’ for the third and fourth trial (i.e. second block). The order of the trials within each block varies from participant to participant, which is what I want.

    However, I would also like to vary the words in the first block across participants. For example, Participant A sees ‘hello’ and ‘world’ in the first block (and ‘eyb’ and ‘etam’ in the second block). Participant B sees ‘hello’ and ‘mate’ in the first block. Participant C sees ‘world’ and ‘bye’ in the first block, etc.

    Could you help with that?

    I was also wondering what the order array does exactly. I started my PhD just a year ago and I am not very familiar with coding but trying my best to learn it at the moment. I tried to look up the individual elements: From what I found, the first part creates an array with four undefined slots. These are then mapped with the .map function and sorted with the .sort function. What I can’t follow are the lambda (?) functions inside .map and .sort. From playing with the code, the .map and .sort functions seem to make sure that not only rightLeft words are displayed but I can’t work out why that is.

    I appreciate if you can’t explain this in detail. Can you recommend any books or websites that I could have a look at to learn this type of coding?

    #5721
    Jeremy
    Keymaster

    Hi Andreas,

    it always chooses ‘hello’ and ‘world’ for the first two trials (i.e. first block) and then ‘eyb’ and ‘etam’ for the third and fourth trial (i.e. second block)

    You’re probably using Chrome (which is fine) just replace

    order = [...new Array(NITEMS)].map((v,i)=>i<NITEMS/2).sort(v=>Math.random()>=0.5)

    with

    order = [...new Array(NITEMS)].map((v,i)=>i<NITEMS/2).sort(v=>1-2*(Math.random()>=0.5))

    I was also wondering what the order array does exactly.

    You got it right for the most part:

    • [...new Array(NITEMS)] indeed creates one array of NITEMS slots with the value undefined
    • map((v,i)=>i<NITEMS/2) loops through every slot, fills the v variable with its value (in this case, always undefined) and i with its index (from 0 to NITEMS-1) and replaces the value in the slot with i<NITEMS/2, which is true for the slots whose index is in the first half and false for the other half of the slots
    • sort(v=>1-2*(Math.random()>=0.5)) loops through every slot of the array returned from map (half true, half false) and depending on the value returned by the lambda function, it moves it forward (value > 0) or backward (value < 0) in the array. In this case, the value is a random number between 1 and -1 for each slot, so you end up with an array with half its slots true and half of them false in a totally random order

    The Template function will then look up the first value of the order array for each trial it generates, and remove it from the array at the same time (that’s the shift() method) so that the next generated trial will look up the next “first” value from order. Then, because of how we defined of order, half your trials will be generated from a true value (-> "leftRight") and the other half will be generated from a false value, in a random (ie. non linear) order.

    Not sure where to start with javascript, I never really followed a single method and the language is now more of a family of languages with many different uses. Ideally PennController lets you abstract away from javascript, but there are some cases (like this one) where it lacks some functionality that can only be implemented using some javascript

    Let me know whether changing the random bit fixed the issue

    Jeremy

    #5723
    AndreasK
    Participant

    Hi Jeremy,

    Yes, it works fine now. Will it work with this code in other browsers as well or do I need to change the code according to which browser my participants use?

    Thanks a lot for explaining the code in detail. That was very helpful for me and I understand the syntax much better now.

    I’d have one more question. Is it possible to add another variable here. For example, both the familiar and the unfamiliar accent will be presented in two voices. I’ve created a table below following your example with leftRight and RightLeft:

    AddTable("myTable",leftRight_1,leftRight_2,rightLeft_1,rightLeft_2
    hello_1,hello_2,olleh_1,olleh_2
    world_1,world_2,dlrow_1,dlrow_2
    bye_1,bye_2,eyb_1,eyb_2
    mate_1,mate_2,etam_1,etam_2)

    The numbers following the words indicate the voices (two for familiar/leftRight and two for unfamiliar/RightLeft). Ideally, the randomization would be such that participant A e.g. hears ‘bye_1’, ‘world_2’, ‘etam_1’, ‘olleh_2’. Participant B hears e.g. ‘mate_1’, ‘hello_2’, ‘dlrow_1’ and ‘eyb_2’. Basically, I would like the same randomization as above but now also including the factor ‘voice’. Is there a way of achieving this?

    I’ve tried to edit the code myself but I only achieved partly what I wanted and I had to use two tables. However, this makes a random choice of sentences impossible as I would have to decide which words will be leftRight or rightLeft by allocating them to the corresponding table.

    Andreas

    • This reply was modified 4 years, 5 months ago by AndreasK.
    • This reply was modified 4 years, 5 months ago by AndreasK.
    #5726
    Jeremy
    Keymaster

    Hi Andreas,

    Yes, the code should work across browsers (or at least, you won’t have to use a different code for Firefox vs Chrome)

    The new design you are describing has 4 conditions instead of 2, so you will need to adapt the code I gave you accordingly. So I worked on a slightly more general version of the code:

    AddTable("myTable", `leftRight_familiar,rightLeft_familiar,leftRight_unfamiliar,rightLeft_unfamiliar
    hello_familiar,olleh_familiar,hello_unfamiliar,olleh_unfamiliar
    world_familiar,dlrow_familiar,world_unfamiliar,dlrow_unfamiliar
    bye_familiar,eyb_familiar,bye_unfamiliar,eyb_unfamiliar
    mate_familiar,etam_familiar,mate_unfamiliar,etam_unfamiliar`)
    
    NITEMS = 4
    CONDITIONS = ['leftRight_familiar','rightLeft_familiar','leftRight_unfamiliar','rightLeft_unfamiliar']
    order = [...new Array(NITEMS)].map((v,i)=>i%CONDITIONS.length).sort(v=>Math.random()>=0.5)
    
    Sequence( 
        randomize("leftRight_familiar"),
        randomize("rightLeft_familiar"),
        randomize("leftRight_unfamiliar"),
        randomize("rightLeft_unfamiliar"),
    )
    
    Template( "myTable" , row =>
      newTrial( CONDITIONS[order[0]] ,
        newText( row[CONDITIONS[order.shift()]] ).print()
        ,
        newButton("Next").print().wait()
      )
    )

    Now if you update your design to use more or less conditions, you only have to change the content of Sequence and the value of CONDITIONS (and NITEMS if you have a different number of items). Notice that I took the liberty to replace 1 and 2 with familiar and unfamiliar for more transparency.

    Let me know if you have any questions

    Jeremy

    #5733
    AndreasK
    Participant

    Hi Jeremy,

    The code works perfectly. Thank you very much. I’ve tried it with different numbers of conditions and it works without any problems. I’ve also inserted the .sort(v=>1-2*(Math.random()>=0.5)) from above to make it work in Chrome.

    Thanks again for all your help. This is fantastic.

    Andreas

Viewing 7 posts - 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.