Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Building stroop #25

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,161 changes: 1,146 additions & 15 deletions package-lock.json

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions packages/n-back/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# n-back

## Overview

A timeline for the nback task

## Loading

### In browser

```html
<script src="https://unpkg.com/@jspsych-timelines/n-back">
```

### Via NPM

```
npm install @jspsych-timelines/n-back
```

```js
import { createTimeline } from "@jspsych-timelines/n-back"
```

## Compatibility

`@jspsych-timelines/n-back` requires jsPsych v8.0.0 or later.

## Documentation

### createTimeline

#### jsPsychTimelineNBack.createTimeline(jsPsych, { *options* }) ⇒ <code>timeline</code>
This timeline describes an N-back task setup that is customizable based on several parameters, allowing researchers to control the level of difficulty, timing, and data output format.

| Parameter | Type | Default | Description |
|---------------------|---------------------------|---------------|-----------------------------------------------------------------------------------------------|
| `stimuli` | `any` | | Stimuli array used in the N-back task, which can be customized based on the experiment needs. |
| `keyboard_response` | `string` | `"n"` | Key used by participants to respond during trials. |
| `trial_duration` | `number` | `1000` ms | Duration of each trial in milliseconds. |
| `post_trial_gap` | `number` | `500` ms | Gap between trials in milliseconds. |
| `fixation_duration` | `number` | `500` ms | Duration of the fixation cross before each trial. |
| `n` | `number` | `2` | Level of N-back, determining how many trials back the participant should remember. |
| `num_trials` | `number` | `20` | Total number of trials in the experiment. |
| `rep_ratio` | `number` | `0.2` | Probability that a stimulus will repeat in the N-back sequence, affecting task difficulty. |
| `debrief` | `boolean` | `false` | Whether to show a debrief screen at the end of the task. |
| `return_accuracy` | `boolean` | `false` | Whether to return participant accuracy as part of the output data. |
| `data_output` | `"none"`, `"json"`, `"csv"` | `"none"` | Specifies the format for saving output data, if any. |

## Reference for Standard Performance

### Standard N-back Task Performance

The following table summarizes the standard performance (accuracy and reaction times) for control subjects in the 1-back, 2-back, and 3-back tasks, as reported by Harvey et al. (2004).

| Condition | Accuracy (%) | Reaction Time (ms) |
|-----------|-------------------|----------------------------|
| 1-back | 96.5 (±3.6) | 749.3 (±199.0) |
| 2-back | 85.6 (±8.8) | 1005.5 (±247.2) |
| 3-back | 80.0 (±7.4) | 1049.5 (±214.8) |

with a sample size of 22 individuals.

## Reference

Harvey, P. O., Le Bastard, G., Pochon, J. B., Levy, R., Allilaire, J. F., Dubois, B., & Fossati, P. (2004). Executive functions and updating of the contents of working memory in unipolar depression. Journal of Psychiatric Research, 38(6), 567–576. https://doi.org/10.1016/j.jpsychires.2004.03.003

## Author

Feng Wan

51 changes: 51 additions & 0 deletions packages/n-back/docs/n-back.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# n-back

Building n-back experiment templates in JsPsych

## Parameters

### Initialization Parameters

Initialization parameters can be set when calling `initJsPsych()`

```js
initJsPsych({
timelines: [
{type: jsPsychTimelineNBack, params: {...}}
]
})
```

Parameter | Type | Default Value | Description
----------|------|---------------|------------
| | |

### Trial Parameters

Trial parameters can be set when adding the timeline to a trial object.

```js
var trial = {
type: jsPsych...,
timelines: [
{type: jsPsychTimelineNBack, params: {...}}
]
}
```

Parameter | Type | Default Value | Description
----------|------|---------------|------------
| | |

## Data Generated

Name | Type | Value
-----|------|------
| |

## Functions

If the timeline adds any static functions, list them here.

### function()

43 changes: 43 additions & 0 deletions packages/n-back/examples/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>

<head>
<script src="https://unpkg.com/jspsych"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response"></script>
<script src="../dist/index.global.js"></script>
<link rel="stylesheet" href="https://unpkg.com/jspsych/css/jspsych.css">
</head>

<body></body>
<script>

const timeline = [];

const jsPsych = initJsPsych({
on_finish: function() {
jsPsych.data.displayData();
}
});

const stimuli = ["b", "B", "d", "D", "g", "G", "p", "P", "t", "T", "v", "V"];

const timeline2Back = jsPsychTimelineNBack.createTimeline(jsPsych, stimuli, "n", 1000, 500, 500, 1, 12, 0.8, data_output = "csv");

const instructions = {
type: jsPsychHtmlKeyboardResponse,
stimulus: `
<p>Welcome to the N-back task.</p>
<p>You will see a sequence of letters on the screen.</p>
<p>Press "space" if the current letter matches the one seen "2“ steps before.</p>
<p>Press any key to begin.</p>
`
};

timeline.push(instructions)

timeline.push(timeline2Back)

jsPsych.run(timeline);
</script>

</html>
1 change: 1 addition & 0 deletions packages/n-back/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require("@jspsych/config/jest").makePackageConfig(__dirname);
37 changes: 37 additions & 0 deletions packages/n-back/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "@jspsych-timelines/n-back",
"version": "0.0.1",
"description": "Building n-back experiment templates in JsPsych",
"type": "module",
"main": "dist/index.mjs",
"types": "dist/index.d.ts",
"unpkg": "dist/index.browser.min.js",
"scripts": {
"build": "tsup src/index.ts --format esm,iife --sourcemap --dts --treeshake --clean --global-name jsPsychTimelineNBack"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jspsych/jspsych-timelines.git"
},
"keywords": [
"jsPsych"
],
"author": {
"name": "Feng Wan",
"url": "https://github.com/CharlieHFFF"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/jspsych/jspsych-timelines/issues"
},
"homepage": "https://github.com/jspsych/jspsych-timelines/packages/n-back#readme",
"peerDependencies": {
"jspsych": "^8.0.1"
},
"dependencies": {
},
"devDependencies": {
"tsup": "^6.7.0",
"typescript": "^5.0.2"
}
}
109 changes: 109 additions & 0 deletions packages/n-back/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { JsPsych } from "jspsych";
import jsPsychHtmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response'

export function createTimeline(jsPsych: JsPsych,
stimuli: any,
keyboard_response: string = "n", // Default key for response
trial_duration: number = 1000, // Default trial duration in ms
post_trial_gap: number = 500, // Default gap between trials in ms
fixation_duration: number = 500, // Default fixation duration in ms
n: number = 2, // Default value for N-back level
num_trials: number = 20, // Default number of trials
rep_ratio: number = 0.2,
debrief: boolean = false,
return_accuracy: boolean = false,
data_output: "none" | "json" | "csv" = "none") {

const trial_sequence: any[] = [];

for (var i = 0; i < num_trials; i++) {
if (i >= n && Math.random() < rep_ratio) {
trial_sequence.push(trial_sequence[i - n]);
} else {
const possible_stimuli = stimuli.filter(function (s: any) {
return (i < n || s !== trial_sequence[i - n]);
});
const random_stimulus = jsPsych.randomization.sampleWithoutReplacement(possible_stimuli, 1)[0];
trial_sequence.push(random_stimulus)
}
}

const timeline: any[] = [];

for (var i = 0; i < trial_sequence.length; i++) {

timeline.push({
type: jsPsychHtmlKeyboardResponse,
stimulus: `<p style="font-size: 48px; color: gray;">+</p>`,
choices: "NO_KEYS",
trial_duration: fixation_duration
});

timeline.push({
type: jsPsychHtmlKeyboardResponse,
stimulus: `<p style="font-size: 48px;">${trial_sequence[i]}</p>`,
choices: [keyboard_response],
trial_duration: trial_duration,
post_trial_gap: post_trial_gap,
data: { correct: i >= n && trial_sequence[i].toLowerCase() === trial_sequence[i - n].toLowerCase() },
on_finish: function (data: any) {
data.correct_response = data.correct && data.response != null;
data.correct_no_response = !data.correct && data.response === null;
}
})
}


if (debrief){
if (return_accuracy){
timeline.push(
{
type: jsPsychHtmlKeyboardResponse,
stimulus: function(){
var correct_responses = jsPsych.data.get().filter({correct_response: true}).count();
var correct_no_responses = jsPsych.data.get().filter({correct_no_response: true}).count();
var total_trials = jsPsych.data.get().count();
var accuracy = Math.round(((correct_responses + correct_no_responses) / total_trials) * 100);
const return_prompt = (correct_response: number, correct_no_response: number, accuracy: number): string => {
return `<p>Thank you for participating!</p>
<p>You correctly responded to <strong>${correct_response}</strong> matching trials.</p>
<p>You correctly did not respond to <strong>${correct_no_response}</strong> non-matching trials.</p>
<p>Your accuracy was <strong>${accuracy}%</strong>.</p>
<p>Press any key to finish the experiment.</p>`;
};
return return_prompt(correct_responses, correct_no_responses, accuracy)
},
choices: "ALL_KEYS",
on_start: function () {
if (data_output == "csv"){
jsPsych.data.get().localSave('csv', `n_back.csv`);} else if (data_output == "json") {
jsPsych.data.get().localSave('json', `n_back.json`);
} else {return null}
},
simulation_options: {
simulate: false
}
})
} else {
timeline.push(
{
type: jsPsychHtmlKeyboardResponse,
stimulus: function(){
return `<p>Thank you for participating!</p>
<p>Press any key to finish the experiment.</p>`;
},
choices: "ALL_KEYS",
on_start: function () {
if (data_output == "csv"){
return jsPsych.data.get().localSave('csv', `n_back.csv`);} else if (data_output == "json") {
return jsPsych.data.get().localSave('json', `n_back.json`)
} else {return null}
},
simulation_options: {
simulate: false
}
})
}}

return timeline
}
10 changes: 10 additions & 0 deletions packages/n-back/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "@jspsych/config/tsconfig.contrib.json",
"compilerOptions": {
"baseUrl": "."
},
"include": [
"src",
"../cli/src/build.js"
]
}
Loading
Loading