Millisecond Forums

Random block selection with restrictions

https://forums.millisecond.com/Topic32416.aspx

By dproost - 11/2/2021

Hi all
My goal is to randomly select different blocks to be presented at certain moments in my experiment, but with a few restrictions on the order.
I have basically four kind of blocks: neutral blocks (block.neutral), negative low arousing blocks (block.low), negative high arousing blocks (block.high) and blocks with attention checks (block.attentioncheck1). In the experiment, there should be in total: 4 neutral blocks, 2 negative low arousing blocks, 2 negative high arousing blocks and 3 attention check blocks. They should be randomly selected, but with the restriction that no lists of the same valence should be presented consecutively three times or more (so no 3 neutral blocks or 3 negative blocks after each other). The difficulty is that negative blocks can be both low and high arousal, so you can't simply place restrictions on the repetition of block.low or block.high.

I previously used:
<expt>
/ blocks = [
    1 = block.newwordgeneration;
    2-12 = noreplacenorepeat (block.neutral, block.neutral, block.neutral, block.neutral, block.low, block.low, block.high, block.high, block.attentioncheck1, block.attentioncheck1, block.attentioncheck1);
...

Is there another way to implement this? Thanks for your time!
Kind regards
Dora
By Dave - 11/2/2021

dproost - 11/2/2021
Hi all
My goal is to randomly select different blocks to be presented at certain moments in my experiment, but with a few restrictions on the order.
I have basically four kind of blocks: neutral blocks (block.neutral), negative low arousing blocks (block.low), negative high arousing blocks (block.high) and blocks with attention checks (block.attentioncheck1). In the experiment, there should be in total: 4 neutral blocks, 2 negative low arousing blocks, 2 negative high arousing blocks and 3 attention check blocks. They should be randomly selected, but with the restriction that no lists of the same valence should be presented consecutively three times or more (so no 3 neutral blocks or 3 negative blocks after each other). The difficulty is that negative blocks can be both low and high arousal, so you can't simply place restrictions on the repetition of block.low or block.high.

I previously used:
<expt>
/ blocks = [
    1 = block.newwordgeneration;
    2-12 = noreplacenorepeat (block.neutral, block.neutral, block.neutral, block.neutral, block.low, block.low, block.high, block.high, block.attentioncheck1, block.attentioncheck1, block.attentioncheck1);
...

Is there another way to implement this? Thanks for your time!
Kind regards
Dora

<expt>
/ blocks = [1-11 = list.blocklist]
</expt>

<list blocklist>
/ items = (block.neutral, block.neutral, block.neutral, block.neutral,
    block.negative, block.negative, block.negative, block.negative,
    block.attentioncheck, block.attentioncheck, block.attentioncheck)
/ maxrunsize = 3
</list>

<block neutral>
/ trials = [1=mytrial]
</block>

// dummy block
<block negative>
/ branch = [
    list.negativeblocks.nextvalue;
]
</block>

<list negativeblocks>
/ items = (block.low, block.low, block.high, block.high)
</list>

<block low>
/ trials = [1=mytrial]
</block>

<block high>
/ trials = [1=mytrial]
</block>

<block attentioncheck>
/ trials = [1=mytrial]
</block>

<trial mytrial>
/ stimulusframes = [1=mytext]
/ validresponse = (0)
/ trialduration = 2000
</trial>

<text mytext>
/ items = ("block.<%script.currentblock%>")
</text>


This will obviously not prevent multiple attention check blocks in a row. Worst case is all three occurring in a row, as permitted with /maxrunsize = 3.
By Dave - 11/2/2021

Dave - 11/2/2021
dproost - 11/2/2021
Hi all
My goal is to randomly select different blocks to be presented at certain moments in my experiment, but with a few restrictions on the order.
I have basically four kind of blocks: neutral blocks (block.neutral), negative low arousing blocks (block.low), negative high arousing blocks (block.high) and blocks with attention checks (block.attentioncheck1). In the experiment, there should be in total: 4 neutral blocks, 2 negative low arousing blocks, 2 negative high arousing blocks and 3 attention check blocks. They should be randomly selected, but with the restriction that no lists of the same valence should be presented consecutively three times or more (so no 3 neutral blocks or 3 negative blocks after each other). The difficulty is that negative blocks can be both low and high arousal, so you can't simply place restrictions on the repetition of block.low or block.high.

I previously used:
<expt>
/ blocks = [
    1 = block.newwordgeneration;
    2-12 = noreplacenorepeat (block.neutral, block.neutral, block.neutral, block.neutral, block.low, block.low, block.high, block.high, block.attentioncheck1, block.attentioncheck1, block.attentioncheck1);
...

Is there another way to implement this? Thanks for your time!
Kind regards
Dora

<expt>
/ blocks = [1-11 = list.blocklist]
</expt>

<list blocklist>
/ items = (block.neutral, block.neutral, block.neutral, block.neutral,
    block.negative, block.negative, block.negative, block.negative,
    block.attentioncheck, block.attentioncheck, block.attentioncheck)
/ maxrunsize = 3
</list>

<block neutral>
/ trials = [1=mytrial]
</block>

// dummy block
<block negative>
/ branch = [
    list.negativeblocks.nextvalue;
]
</block>

<list negativeblocks>
/ items = (block.low, block.low, block.high, block.high)
</list>

<block low>
/ trials = [1=mytrial]
</block>

<block high>
/ trials = [1=mytrial]
</block>

<block attentioncheck>
/ trials = [1=mytrial]
</block>

<trial mytrial>
/ stimulusframes = [1=mytext]
/ validresponse = (0)
/ trialduration = 2000
</trial>

<text mytext>
/ items = ("block.<%script.currentblock%>")
</text>


This will obviously not prevent multiple attention check blocks in a row. Worst case is all three occurring in a row, as permitted with /maxrunsize = 3.

For anything more complex, just code a simple sequence generator that generates a conforming block sequence up-front.

<expt>
/ blocks = [1= generateSequence; 2-12 = runSequence]
</expt>

<block generateSequence>
/ trials = [1=gen]
</block>

<values>
/ sequence = ""
/ nextblock = ""
/ blockcount = 0
</values>

// "0" = neutral
// "1" = negative (without regard to hi/lo)
// "A" = attention check
<list blocktypelist>
/ items = ("0", "0", "0", "0",
    "1", "1", "1", "1",
    "A", "A", "A")
/ maxrunsize = 3
/ selectionrate = always
</list>

<list generatedblocksequence>
/ selectionmode = sequence
</list>

<trial gen>
/ ontrialbegin = [
    values.sequence = "";
    list.blocktypelist.reset();
    list.generatedblocksequence.reset();
    
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);    
]
/ branch = [
    if (startswith(values.sequence, "A") || contains(values.sequence, "AA") || contains(values.sequence, "1111") || contains(values.sequence, "0000")) {
        trial.gen;
    };
]
/ validresponse = (0)
/ trialduration = 0
/ recorddata = false
</trial>

<block runSequence>
/ onblockbegin = [
    values.nextblock = list.generatedblocksequence.nextvalue;
    values.blockcount += 1;
]
/ branch = [
    if (values.nextblock == "0"){
        block.neutral;
    } else if (values.nextblock == "1") {
        block.negative;
    } else {
        block.attentioncheck;
    };
]
</block>

<block neutral>
/ trials = [1=mytrial]
</block>

// dummy block
<block negative>
/ branch = [
    list.negativeblocks.nextvalue;
]
</block>

<list negativeblocks>
/ items = (block.low, block.low, block.high, block.high)
</list>

<block low>
/ trials = [1=mytrial]
</block>

<block high>
/ trials = [1=mytrial]
</block>

<block attentioncheck>
/ trials = [1=mytrial]
</block>

<trial mytrial>
/ stimulusframes = [1=mytext]
/ validresponse = (0)
/ trialduration = 1000
</trial>

<text mytext>
/ items = ("block.<%script.currentblock%>")
</text>

<data>
/ columns = (date time subject group values.blockcount blockcode trialnum trialcode values.sequence)
/ separatefiles = true
</data>


The above will ensure that:
- The sequence does not start with an attention check block.
- There are no consecutive attention check blocks in the sequence.
- There are no more than three negative (regardless of hi/lo) blocks in a row.
- There are no more than three neutral blocks in a row.
By dproost - 11/3/2021

Dave - 11/2/2021
Dave - 11/2/2021
dproost - 11/2/2021
Hi all
My goal is to randomly select different blocks to be presented at certain moments in my experiment, but with a few restrictions on the order.
I have basically four kind of blocks: neutral blocks (block.neutral), negative low arousing blocks (block.low), negative high arousing blocks (block.high) and blocks with attention checks (block.attentioncheck1). In the experiment, there should be in total: 4 neutral blocks, 2 negative low arousing blocks, 2 negative high arousing blocks and 3 attention check blocks. They should be randomly selected, but with the restriction that no lists of the same valence should be presented consecutively three times or more (so no 3 neutral blocks or 3 negative blocks after each other). The difficulty is that negative blocks can be both low and high arousal, so you can't simply place restrictions on the repetition of block.low or block.high.

I previously used:
<expt>
/ blocks = [
    1 = block.newwordgeneration;
    2-12 = noreplacenorepeat (block.neutral, block.neutral, block.neutral, block.neutral, block.low, block.low, block.high, block.high, block.attentioncheck1, block.attentioncheck1, block.attentioncheck1);
...

Is there another way to implement this? Thanks for your time!
Kind regards
Dora

<expt>
/ blocks = [1-11 = list.blocklist]
</expt>

<list blocklist>
/ items = (block.neutral, block.neutral, block.neutral, block.neutral,
    block.negative, block.negative, block.negative, block.negative,
    block.attentioncheck, block.attentioncheck, block.attentioncheck)
/ maxrunsize = 3
</list>

<block neutral>
/ trials = [1=mytrial]
</block>

// dummy block
<block negative>
/ branch = [
    list.negativeblocks.nextvalue;
]
</block>

<list negativeblocks>
/ items = (block.low, block.low, block.high, block.high)
</list>

<block low>
/ trials = [1=mytrial]
</block>

<block high>
/ trials = [1=mytrial]
</block>

<block attentioncheck>
/ trials = [1=mytrial]
</block>

<trial mytrial>
/ stimulusframes = [1=mytext]
/ validresponse = (0)
/ trialduration = 2000
</trial>

<text mytext>
/ items = ("block.<%script.currentblock%>")
</text>


This will obviously not prevent multiple attention check blocks in a row. Worst case is all three occurring in a row, as permitted with /maxrunsize = 3.

For anything more complex, just code a simple sequence generator that generates a conforming block sequence up-front.

<expt>
/ blocks = [1= generateSequence; 2-12 = runSequence]
</expt>

<block generateSequence>
/ trials = [1=gen]
</block>

<values>
/ sequence = ""
/ nextblock = ""
/ blockcount = 0
</values>

// "0" = neutral
// "1" = negative (without regard to hi/lo)
// "A" = attention check
<list blocktypelist>
/ items = ("0", "0", "0", "0",
    "1", "1", "1", "1",
    "A", "A", "A")
/ maxrunsize = 3
/ selectionrate = always
</list>

<list generatedblocksequence>
/ selectionmode = sequence
</list>

<trial gen>
/ ontrialbegin = [
    values.sequence = "";
    list.blocktypelist.reset();
    list.generatedblocksequence.reset();
    
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);
    values.sequence = concat(values.sequence, list.blocktypelist.nextvalue);
    list.generatedblocksequence.appenditem(list.blocktypelist.currentvalue);    
]
/ branch = [
    if (startswith(values.sequence, "A") || contains(values.sequence, "AA") || contains(values.sequence, "1111") || contains(values.sequence, "0000")) {
        trial.gen;
    };
]
/ validresponse = (0)
/ trialduration = 0
/ recorddata = false
</trial>

<block runSequence>
/ onblockbegin = [
    values.nextblock = list.generatedblocksequence.nextvalue;
    values.blockcount += 1;
]
/ branch = [
    if (values.nextblock == "0"){
        block.neutral;
    } else if (values.nextblock == "1") {
        block.negative;
    } else {
        block.attentioncheck;
    };
]
</block>

<block neutral>
/ trials = [1=mytrial]
</block>

// dummy block
<block negative>
/ branch = [
    list.negativeblocks.nextvalue;
]
</block>

<list negativeblocks>
/ items = (block.low, block.low, block.high, block.high)
</list>

<block low>
/ trials = [1=mytrial]
</block>

<block high>
/ trials = [1=mytrial]
</block>

<block attentioncheck>
/ trials = [1=mytrial]
</block>

<trial mytrial>
/ stimulusframes = [1=mytext]
/ validresponse = (0)
/ trialduration = 1000
</trial>

<text mytext>
/ items = ("block.<%script.currentblock%>")
</text>

<data>
/ columns = (date time subject group values.blockcount blockcode trialnum trialcode values.sequence)
/ separatefiles = true
</data>


The above will ensure that:
- The sequence does not start with an attention check block.
- There are no consecutive attention check blocks in the sequence.
- There are no more than three negative (regardless of hi/lo) blocks in a row.
- There are no more than three neutral blocks in a row.

Thanks a lot for your extensive answer! It works now!