Random block selection with restrictions


Author
Message
dproost
dproost
Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)
Group: Forum Members
Posts: 7, Visits: 62
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

Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 13K, Visits: 104K
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.
Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 13K, Visits: 104K
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.

dproost
dproost
Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)Associate Member (84 reputation)
Group: Forum Members
Posts: 7, Visits: 62
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!
GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Reading This Topic

Explore
Messages
Mentions
Search