2.2 How does a jsPsych experiment work?

As shown in the previous section, experiments in jsPsych are created by specifying a timeline. Timelines contain a set of ordered trials, and each trial is associated with a particular plugin. When the experiment runs, the core jsPsych code (in jspsych.js) parses the timeline to determine what trials should run during the experiment. The jsPsych code then calls the plugin for the first trial, passing it all the parameters specified in the trial object, and the plugin gains control of the experiment. The plugin then specifies what happens during the trial, including the presentation of any stimuli and collection of responses. When the trial is done, the plugin sends control back to the core jsPsych library to determine what the next trial is, and which plugin should have control next. This continues until all of the trials in the timeline array have finished.

add some kind of a visual representation of a timeline of trials?

This section goes into detail about basic features of plugins and timelines. Advanced features are covered in later chapters with experiments that require more complicated timeline and plugin designs.

2.2.1 Plugins

Plugins define a basic framework for trials, tasks, or events that can be used in a jsPsych experiment. Some plugins define very general events, like displaying text and recording a keyboard response, or playing a sound file and recording a button response. Other plugins are more specific, like those that display particular kinds of stimuli (e.g. Random-Dot Kinematogram, visual search circle), or run a specific version of particular kind of task (e.g. the Implicit Association Test). Creating an experiment with jsPsych involves figuring out which plugins are needed to create the tasks you want your participants to perform.

Plugins provide a basic structure for running a particular trial and collecting a response, but they generally allow for significant customization and flexibility through the use of parameters. For example, the image-keyboard-response plugin defines a simple structure for showing an image and collecting a keyboard response. You can specify the what the stimulus is, what keys the subject is allowed to press, and how long the stimulus should be on the screen, how long the subject has to respond, and so on. Many of these options have reasonable default values; even though the image plugin has many different parameters, you only need to specify the image stimulus in order to use it.

Each plugin has its own documentation page, which describes (1) what the plugin does, (2) what parameters (options) are available (including whether the parameter is required or optional, and what its default value is), and (3) what kind of data the plugin collects. The plugin documentation pages can be found in the “Plugins” section of the jsPsych website.

You can find an up-to-date list of plugins here: https://www.jspsych.org/plugins/list-of-plugins/. Often the easiest way to understand what each plugin does is to run its example file. Each plugin has its own example HTML file in the jspsych/plugins folder. If you open an example file in your web browser, you will see a live demo of a few basic trials using that plugin. You can also open the HTML file in your text editor to see the code that is used to run the example trials.

One of the great things about plugins is that they can be modified, and you can create your own custom plugins. The official set of jsPsych plugins provide enough flexibilty and breadth to cover an enormous range of possible tasks and experiments. But if your experiment requires something that can’t be achieved using existing plugins, you can always opt to modify or create plugins, and therefore still take advantage of the general jsPsych framework for managing the experiment timeline and data. This will be covered in CHAPTER XXX.

2.2.1.1 Using a plugin

To use a plugin, you’ll need to load the plugin’s JavaScript file in your experiment’s HTML page. All jsPsych experiments also need to load the “jspsych.js” file before any plugin files.

<head>
  <script src="jspsych/jspsych.js" type="text/javascript"></script>
  <script src="jspsych/plugins/jspsych-image-keyboard-response.js" type="text/javascript"></script>
</head>

Once a plugin is loaded, you can define a trial that uses that plugin. All jsPsych trials must have a type, which tells jsPsych what plugin to use to run the trial. The trial’s type is the plugin name, which usually the same as the plugin file name, but without the “jspsych-” prefix.

The following JavaScript code defines a trial using the image-keyboard-response plugin to display an image file. This trial uses the default values for all of the other parameters, such as the valid key choices, stimulus duration, and trial duration.

var image_trial = {
    type: 'image-keyboard-response', 
    stimulus: 'images/happy_face.jpg'
}

You can override any default parameter values by adding them into your trial object. Here’s an exampe of overriding the default values for trial_duration, choices, and post_trial_gap. Unlike the previous example trial, this trial will only accept the “h” and “s” keys as valid responses (choices parameter), and it will automatically end after 3 seconds if no valid response is made before then (trial_duration parameter). There will be a 2 second delay between the end of this trial and the start of the next one (post_trial_gap parameter).

var image_trial = {
  type: 'image-keyboard-response',
  stimulus: 'images/happy_face.jpg',
  trial_duration: 3000,
  choices: ['h','s'],
  post_trial_gap: 2000
}
  • what every plugin does (start, stop, collect data)
  • kinds of plugins
    • advantages of generic and specific plugins
  • how to use a plugin
    • docs and syntax
    • default parameters

2.2.2 The timeline

  • array of trials
  • executed in order
  • how to create a timeline in code (style guide).
  • repeating trials (timeline node with repetitions parameter)
  • pointer to advanced features (single paragraph).

2.2.3 Static and dynamic parameters

Move this to its own chapter?

In a typical declaration of a jsPsych trial, the parameters values are known at the start of the experiment. These are called static parameters, because the value is known in advance and does not change. This makes it impossible to alter the content or nature of the trial based on things that happen during the experiment.

However, most trial parameters can also be specified as functions. When functions are used as the parameter value, the function is evaluated during the experiment, right before the trial starts, and the return value of the function is used as the parameter value for that trial. This enables dynamic updating of trial parameters based on data that a subject has generated, or any other information that you do not know before the experiment has started.

Below is a sketch of how this can be used to display feedback about a participant’s response. This feedback trial uses the html-keyboard-response plugin to display text to the participant indicating whether their response in the last trial was correct or incorrect.

var feedback = {
  type: 'html-keyboard-response',
  stimulus: function(){
    var last_trial_correct = jsPsych.data.get().last(1).values()[0].correct;
    if (last_trial_correct) {
      return "Correct!"; 
    } else {
      return "Wrong."; 
    }
  },
  choices: jsPsych.NO_KEYS
}

It’s fine if you don’t understand exactly what this code is doing - some of this will be explained in later chapters. The important thing to note here is that the stimulus parameter isn’t a normal text string, like we’ve seen in previous example trials. Instead, it’s a function, which uses the syntax function() { }. When functions are used as trial parameters, they will be typically written like this:

stimulus: function() {
  // code here...
}

In the feedback trial example, the code inside the stimulus function first checks whether the last response was correct or incorrect, and then uses that information to return one of two different text strings: “Correct! if the response was correct, or”Wrong." if it was incorrect. The return keyword is used to return a value from a function.

  • KEY IDEA: most of the code that you are writing runs before the experiment even begins.
  • need simple situation where we want dynamic parameter (but need a few more concepts… so maybe this moves to next chapter, and we do big 5 there. or do it again?