Selection from a group & randomization
Many experiments require selecting a particular stimulus from a group of stimuli and presenting it. Once a group is defined, tags that denote particular stimuli can be chosen in BITTSy, with or without replacement, either in the order in which they are listed in the group or with randomization. This is done with choose statements.
Choose statements can occur on their own, but they are often employed within loops, sections of steps that repeat until a specific condition is met. For example, a particular STEP
could select and display an image from a group, and a loop could repeat that STEP
until all of the images have been chosen and displayed. After covering the basics of choose statements and loops individually, more about how they work together can be seen in the "putting it all together" section.
Choose statements and dynamic tags
Remember dynamic tags? Unlike other tags, they are not defined at the start of a protocol. Rather, they get defined through choose statements, within the steps of your protocol, and refer to the result of that choose statement on its most recent execution.
The syntax above shows how to create a dynamic tag. The name you give it within the LET
statement is its new name: this will be what you use later to refer to whatever tag or stimulus was selected. The part in parentheses on the right side of the equals sign is the choose statement (we'll talk more about the syntax and options for choose statements later.)
The restrictions on valid dynamic tag names are the same as for other tags. Unlike static tags that directly denote files or groups, there is no restriction on defining the same dynamic tag name twice - indeed, this is extremely common, as you are often creating and overwriting dynamic tags via executing a choose statement within a loop. However, they must not have the same name as any static tag.
In the example above, we have a group dogs
that contains several tags referencing image files. We want to pick a random one and display it. We don't know which tag out of the group dogs
will be chosen on any given run of this particular STEP
. Therefore, we can't refer to the result by directly using any of the tags referencing files (dalmatian
, deerhound
, boxer
, etc.) Instead, we create a dynamic tag, to which we can assign whatever tag we randomly select.
You can think of dynamic tags like arrows. If the choose statement selects beagle
from the group, dog
points to beagle
, and in the subsequent action statement to display the image, BITTSy follows the arrow back from dog
to beagle
to the actual file on your computer it will access and display.
Dynamic tags keep referring back to the same tag until a later choose statement changes their reference - that is, the arrow stays pointing in the same direction until another choose statement moves it. If beagle
was selected above, you could refer to dog
many steps later and it would still mean beagle
, as long as there were no intervening choose statements that also assigned their result to dog
. If there were more choose statements that assigned to the same dynamic tag, dog
would always refer to the result of the most recently-executed choose statement.
Often, dynamic tags are used within a loop. Loops repeatedly execute a set of STEPs within a protocol. When a dynamic tag and choose statement are defined within a loop, the choose statement is executed each time the loop runs, and the assignment of the dynamic tag changes each time.
Once a dynamic tag is reassigned via another choose statement to mean a different static tag, there is no way to use it to reference what it used to mean. Therefore, any experiment that needs to call back up "stimulus that was chosen two trials ago," after having chosen more things, will need to assign results of choose statements to new dynamic tags so that the older results are not overwritten. This can require not using a loop structure, as a loop repeatedly executes a single section of protocol and cannot allow modifications to the included lines.
Fixed order and random order
Whenever you create a choose statement, you must specify whether to choose the items from the group in order (by always selecting the FIRST
tag that is eligible for selection), or to select in a random order (using the flag RANDOM
).
More on these and how they work in different types of choose statements below!
Selection without replacement
TAKE
clauses specify selection that is strictly without replacement. Whatever tag is chosen is no longer available to be chosen from that group in any subsequent choose statements, whether they occur in later steps or in the same step via a loop. (However, tags that are chosen still belong to the group for the purposes of tracking accumulated looking time or logging experiment data.)
Whether or not a particular tag is eligible for selection is tracked per group. If a particular static tag belongs to two groups, and is chosen via TAKE
from one of those groups, it could still later be selected when using a choose statement that is set to pull from the second group. (The same applies to choosing with FROM
statements in the next section!)
Choosing items with RANDOM
, as in the example above, does just that - picks any random remaining tag in that group, with equal probability.
Choosing items in order, via FIRST
, is really designed for choosing without replacement with TAKE
. Doing this allows you to set up a particular, fixed order of tags while defining the group, and then present those tags in that order. For example, the items from this group...
...would display dalmatian
, then deerhound
, then boxer
- the order in which they appear in the definition of dogs. This set-up is completely deterministic, which means you could equivalently set up your protocol to directly reference the static tags:
However, when designing experiments that present files in a fixed order, there are often multiple fixed-orders to create and assign across study participants. Using choose statements with FIRST
allows you to refer back to these tags generically within the steps of the protocol. Therefore, when you are creating multiple fixed-order protocols for one experiment, all you need to do is change one line: the group definition.
Selection with replacement
Choosing from groups with FROM
marks the resulting tag as having been chosen, but does not bar it from being selected again from that group later.
For example, selecting with FROM dogs RANDOM
two times on the following group...
...could result in:
dalmatian, deerhound dalmatian, dalmatian deerhound, dalmatian deerhound, deerhound
Selecting with FROM dogs FIRST
, on the other hand, would always yield dalmatian
.
Repeat clauses
There are additional clauses you can add to a FROM
statement that place restrictions on the repeated selection of tags.
These repeat clauses are:
A common mistake with all of these is confusing the number of repeats with the total number of presentations. If you don't want it to repeat at all, it has to be listed as zero repeats, not one repeat. One repeat means it could present the item twice: the initial time, plus one repetition of it.
max <number> repeats
This type of clause allows you to restrict how many times a particular item is selected from a group, overall.
This means that each side, LEFT
or RIGHT
, can be chosen for stimulus presentation up to 5 times. Once one side has been picked 5 times, any remaining repetitions will be forced to pick the other side. There are valid sides remaining for exactly 10 selections; if this step is executed 11 times, BITTSy will crash on the last one because it won't be allowed to pick either one!
More generally - ensure that when you are placing selection criteria, they are appropriate for the number of times a step will execute in your protocol, and there will always be a valid selection that BITTSy can make.
Selecting {with max 0 repeats}
in a FROM
statement is completely equivalent to using a TAKE
statement - it specifies to not allow repeats, which is what selecting without replacement is! TAKE
is just shorter to write, and easier for someone reading your protocol to understand.
max <number> repeats in succession
This type of clause allows you to restrict how many times a single item can be chosen from a group in a row.
In the above example, each side can be chosen up to 3 times in a row. Whenever one is chosen 3 times in a row, the next selected side must be the other one.
Using {with 0 repeats in succession}
specifies to never make the same selection twice in a row. For a group that contains just two items, like sides
in our example, this forces selections to alternate.
max <number> repeats in <number> trials
This type of clause can be used when you wish to restrict how many times an item can be repeated within a particular window of trials.
This means that in any set of four consecutive selections, each item can appear a maximum of two times. For example, this would be a valid possible selection order:
boxer, bulldog, bulldog, beagle, dalmatian, bulldog, deerhound
Because every set of four contains only up to two of the same item.
{boxer, bulldog, bulldog, beagle}, dalmatian, bulldog, deerhound boxer, {bulldog, bulldog, beagle, dalmatian}, bulldog, deerhound boxer, bulldog, {bulldog, beagle, dalmatian, bulldog}, deerhound boxer, bulldog, bulldog, {beagle, dalmatian, bulldog, deerhound}
This type of clause is good for when you want to restrict how frequent one thing can be within a certain time frame, beyond whether they are strictly all in a row (which is repeats in succession
).
Here's another example.
This means that as each item is selected, it cannot be selected again in any of the next 5 selections that are made from that group. For example, if boxer
is chosen first, it cannot appear again until trial 7 at the earliest; beagle
, if chosen second, cannot appear again until trial 8, and so on.
On the surface, the above example might seem like a good way to create a block structure in BITTSy (displaying all of the stimuli from a set in a random order without repeats, then showing the set again in a different random order). However, you would typically want stimuli within a block to be randomized independently, and this selection criteria always works along a moving window, meaning that there is never a point where the current selection is independent of the previous ones. For example, if repeated executions of the above line made the following selections:
whippet, dalmatian, deerhound, beagle, boxer, bulldog, ______
Because the last selection is considering the five previous, and won't allow any repeats within that frame...
whippet, {dalmatian, deerhound, beagle, boxer, bulldog, ______}
...that selection must be whippet - it is the only item that wouldn't be a repetition within that set of most recent 6 picks - and next would have to be dalmatian, and then deerhound... Essentially, what you get is a random permutation of the six items when moving through the group for the first time, but thereafter it repeats that same ordering of the six tags.
How, then, do you make a block structure with BITTSy? See below!
Selection and groups of groups (and groups of groups of groups!)
Let's go back to the basic formulation of a choose statement.
When a group tag is referenced, BITTSy doesn't care what type of tags it contains, as long as it's defined as a group and has at least one tag in it that is eligible for selection, according to your selection criteria. It simply picks one and makes the dynamic tag point at it. That group can contain tags that denote files, it can contain SIDES
, or it can contain other groups. Going back to our example from the groups section:
Let's say we're writing a protocol in which we want to display one of these images. We start with animals
, a group whose members are other groups. We need two choose statements before we can display an image tag - first to select either mammals
or reptiles
out of animals
, and second to select a particular mammal or reptile from that resulting group (which we've called class
).
Now let's say we want to make an experiment that displays these images in a block structure. One block of trials will be mammals, one will be reptiles. We'll randomly select which block comes first, and within each block, we'll randomly order the two animals that belong to that phylogenetic class. Below is an example of how this can be constructed.
Or equivalently, with loops:
Defining animals
as a group of groups allows you to set up choose statements that create this type of simple block structure, and gives the following possibilities.
1
2
3
4
5
6
7
8
Block 1: mammals
cat
dog
Block 1: mammals
dog
cat
Block 1: mammals
cat
dog
Block 1: mammals
dog
cat
Block 1: reptiles
snake
turtle
Block 1: reptiles
turtle
snake
Block 1: reptiles
snake
turtle
Block 1: reptiles
turtle
snake
Block 2: reptiles
snake
turtle
Block 2: reptiles
snake
turtle
Block 2: reptiles
turtle
snake
Block 2: reptiles
turtle
snake
Block 2: mammals
cat
dog
Block 2: mammals
cat
dog
Block 2: mammals
dog
cat
Block 2: mammals
dog
cat
Last updated