; PSY 1903
PSY 1903 Programming for Psychologists

Blocks

In some experiments, you may want to group the conditions into different blocks, and you might want to have a info screen before each block begins.

For example, in our Lexical Decision Task, we might expand to have three blocks:

  • Block 1: 3 character words/pseudo-words
  • Block 2: 4 character words/pseudo-words
  • Block 3: 5 character words/pseudo-words

To accomplish this “blocked” experiment, we can expand our conditions array as follows::

let conditions = [
    {
        title: 'Part 1',
        count: 3,
        conditions: [
            { characters: 'cat', isWord: true },
            { characters: 'pin', isWord: true },
            { characters: 'jgb', isWord: false },
            { characters: 'mub', isWord: false },
        ],
    },
    {
        title: 'Part 2',
        count: 4,
        conditions: [
            { characters: 'food', isWord: true },
            { characters: 'burn', isWord: true },
            { characters: 'mnut', isWord: false },
            { characters: 'plut', isWord: false },
        ]
    },
    {
        title: 'Part 3',
        count: 5,
        conditions: [
            { characters: 'apple', isWord: true },
            { characters: 'jumps', isWord: true },
            { characters: 'pilde', isWord: false },
            { characters: 'kandy', isWord: false },
        ]
    }
];

Then, using a nested for loop we will loop through our blocks of conditions. For each block, we will have an intro trial, followed by a loop through the conditions within that block.

Code:

let jsPsych = initJsPsych();

let timeline = [];

// let conditions = [...redacted for brevity - see above...]

let welcomeTrial = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: `
    <h1>Welcome to the Lexical Decision Task!</h1> 
    <p>In this experiment, you will be shown a series of characters and asked to categorize whether the characters make up a word or not.</p>
    <p>There are three parts to this experiment.</p>
    <p>Press SPACE to begin the first part.</p>
    `,
    choices: [' '],
};
timeline.push(welcomeTrial);

for (let block of conditions) {

    let blockIntroTrial = {
        type: jsPsychHtmlKeyboardResponse,
        stimulus: `
            <h1>${block.title}</h1>
            <p>You are about to see a series of ${block.count} characters.</p>
            <p>If the characters make up a word, press the F key.</p>
            <p>If the characters do not make up a word, press the J key.</p>
            <p>Press SPACE to begin.</p>
            `,
        choices: [' '],
    };

    timeline.push(blockIntroTrial);

    // Randomize the conditions in this block
    blockConditions = jsPsych.randomization.repeat(block.conditions, 1);

    for (let condition of blockConditions) {
        let conditionTrial = {
            type: jsPsychHtmlKeyboardResponse,
            stimulus: `<h1>${condition.characters}</h1>`,
            data: {
                collect: true,
                characters: condition.characters,
                blockId: block.title, // ⭐ Add a block id to our results data
            },
            choices: ['f', 'j'],
            on_finish: function (data) {
                if (data.response == 'f' && condition.isWord == true) {
                    data.correct = true;
                } else if (data.response == 'j' && condition.isWord == false) {
                    data.correct = true;
                } else {
                    data.correct = false;
                }
            }
        }
        timeline.push(conditionTrial);
    }
}

let debriefTrial = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: `
    <h1>Thank you for participating!</h1> 
    <p>You can close this tab.</p>
    `,
    choices: 'NO_KEYS',
    on_start: function () {
        let data = jsPsych.data
            .get()
            .filter({ collect: true })
            .ignore(['stimulus', 'trial_type', 'trial_index', 'plugin_version', 'collect'])
            .csv();
        console.log(data);
    }
};
timeline.push(debriefTrial);

jsPsych.run(timeline);

Move conditions externally

In the above example, our conditions array (called conditions) grew from 6 lines to 30, and we can expect a “real world” experiment to have many more conditions which would cause it to grow even further.

Anticipating this, it makes sense to extract our conditions array to its own file.

To do this, create a new file in at /psy1903/docs/projects/lexical-decision/conditions.js and paste in the code that defines the conditions array:

let conditions = [
    {
        title: 'Part 1',
        count: 3,
        conditions: [
            { characters: 'cat', isWord: true },
            { characters: 'pin', isWord: true },
            { characters: 'jgb', isWord: false },
            { characters: 'mub', isWord: false },
        ],
    },
    {
        title: 'Part 2',
        count: 4,
        conditions: [
            { characters: 'food', isWord: true },
            { characters: 'burn', isWord: true },
            { characters: 'mnut', isWord: false },
            { characters: 'plut', isWord: false },
        ]
    },
    {
        title: 'Part 3',
        count: 5,
        conditions: [
            { characters: 'apple', isWord: true },
            { characters: 'jumps', isWord: true },
            { characters: 'pilde', isWord: false },
            { characters: 'kandy', isWord: false },
        ]
    }
];

Then, in your psy1903/docs/projects/lexical-decision/index.html file, add a line to import the conditions:

<!DOCTYPE html>
<html>

<head>
    <title>Lexical Decision Task</title>
    <link href=data:, rel=icon>

    <link href='https://unpkg.com/jspsych/css/jspsych.css' rel='stylesheet' type='text/css'>

    <script src='https://unpkg.com/jspsych'></script>
    <script src='https://unpkg.com/@jspsych/plugin-html-keyboard-response'></script>

    <!-- ⭐ NEW ⭐ -->
    <script src='conditions.js'></script>

    <!-- Make sure conditions.js is imported BEFORE experiment.js -->
    <script src='experiment.js'></script>
</head>

<body></body>

</html>

Finally, you can remove the conditions initialization code from experiment.js.

Refresh and test your experiment in the browser to make sure it’s still working as expected after this reorganization.