Institute for Language Sciences Labs

How-tos

Enabling grouping in a ZEP experiment

Last updated on 5 November 2018 by Ty Mees

If you have suggestions on how to improve this document, or find mistakes, please send them to ilslabs@nulluu.nl

In this how-to, we will discuss how to add different groups with different stimuli for each group to an existing (basic) experiment. This guide assumes that you are familiar with latin square and other methods and thus focuses on the implementation of groups in ZEP.

Furthermore, this guide only looks at the actual test items. You can also modify your practice stimuli in exactly the same manner if needed.

Before we can use groups, we need to define them. This is done in the grouping.zm module file (in the modules sub-folder). Your experiment probably doesn’t have this file, so you’ll need to download it from here: ZEP 1 or ZEP 2.

Place it in your modules sub-folder, and open it with your text-editor of choice (like Gedit or Notepad++). Groups are defined in the TestGroup enum. By default, there is only one defined: All. This suits most experiments, but we want to add more.

Remove the ‘All’ from the enum and add your own groups to it (separated by commas). You can add as many as you need, and you can name them any way you want. For this how-to we will define four groups: GRP1, GRP2, GRP3, GRP4.

The final result will look like this:

...
enum TestGroup
{
    GRP1,
    GRP2,
    GRP3,
    GRP4
};
...


As we want to use different stimuli for each group, we will need to specify separate stimuli for each of the groups.
Normally, you’d store the stimuli in a list, like so:

TestItem[..] test_items = 
{
    {1, CORRECT, "The donkey went to the doctor"},
    {2, CORRECT, "A cat was sleeping"},
    {3, CORRECT, "Bruce became Batman"},
    {4, INCORRECT, "The rope breaked in the storm"}
};

When using multiple groups, we want to store our stimuli in such a way that each group has their own set. The easiest way is to actually make a new list, with each entry containing the stimuli for a single group.

In our example experiment, our stimuli would look like this:

TestItem[..][..] test_items = 
{
    // GRP1
    {
        {1, CORRECT, "The donkey went to the doctor"},
        {2, CORRECT, "A cat was sleeping"},
        {3, CORRECT, "Bruce became Batman"},
        {4, INCORRECT, "The rope breaked in the storm"}
    },
    // GRP2
    {
        {1, INCORRECT, "The donkey goed to the doctor"},
        {2, CORRECT, "A cat was sleeping"},
        {3, CORRECT, "Bruce became Batman"},
        {4, CORRECT, "The rope broke in the storm"}
    },
    // GRP3
    {
        {1, CORRECT, "The donkey went to the doctor"},
        {2, INCORRECT, "A cat ised sleeping"},
        {3, CORRECT, "Bruce became Batman"},
        {4, CORRECT, "The rope broke in the storm"}
    },
    // GRP4
    {
        {1, CORRECT, "The donkey went to the doctor"},
        {2, CORRECT, "A cat was sleeping"},
        {3, INCORRECT, "Bruce becomeed Batman"},
        {4, CORRECT, "The rope broke in the storm"}
    },
};

As you can see, we’ve added a second set of curly brackets around the original stimuli. Then we added 3 extra sets of stimuli inside this second pair of brackets for a total of 4 list, one for each group. Note that we’ve also added a second ‘[..]’ to the first line.

The comments are optional, but it’s a bit easier to see what is happening when we do comment them like this.

We can now address the stimuli like this:

test_items[group][stimulus];

In which the [group] will select which of the four sets we want, and the [stimulus] will select the specific stimulus in that group.


Now that we’ve prepared our stimuli, we need to modify our task to be able to select the right set of stimuli.

Taking the right element for a trial (task.zm)
Traditionally, you select the right stimulus for a trial in the entry event of a Trial like this:

item = test_items[test.cycle];

We need to replace this with:

item = test_items[selected_group][test.cycle];

The selected_group variable is created by ZEP itself, you can use it without defining it yourself.

Search through your test trials for references like this, and modify them by adding the [selected_group].

Specifying the right number of trials (task.zm)
In most experiments, the number of trials is calculated by looking at the number of specified stimuli. As our stimuli are now specified in a different manner, we also need to change that calculation. In the entry event of the block containing your test trials, you will find something similar to this:

num_cycles = test_items.size;

Like before, we just need to add the [selected_group]:

num_cycles = test_items[selected_group].size;

As you might have noticed, this change is actually not required in this example as we have the same amount of stimuli per group as the amount of groups. However, it’s still highly advisable to change this, as it can avoid issues later on.

Changing the shuffle function (shuffle.zm)
If you use stimuli shuffling in your experiment, you also need to change your shuffling function. If you do not, the stimuli groups will be shuffled instead of the stimuli.

As usual, just add [selected_group] to any references to test_items

For example:

int shuffle_test_items()
{
    test_items[selected_group].shuffle(0, -1);

    return OK;
}


By default, ZEP assigns every participant to the default group. (Which will be the first group listed). You can still manually assign participants to different groups manually when starting the experiment, but you can also let ZEP assign participants to groups automatically.

In grouping.zm you will find a function called int assign_participant_to_group(). This function is called by ZEP to assign participants to groups. The default implementation calls select_group_default(), which assigns the first group to the participant.

Other functions you can call instead are:

  • select_group_random(), which will pick a group at random
  • select_group_from_num_sessions(), which will assign the group with the least amount of participants to a participant. This means that each group will have an equal amount of participants. (Providing there are exactly enough participants to fill the groups equally).
  • select_group_random_balanced(int per_group), which will randomly assign participants to a group, but will also ensure every group has the provided number of participants per group.

There are some more examples on the Beexy Website here