diff --git a/directed_forgetting_single_task_network/experiment.js b/directed_forgetting_single_task_network/experiment.js index 52ef3c51c..3d0d9deda 100644 --- a/directed_forgetting_single_task_network/experiment.js +++ b/directed_forgetting_single_task_network/experiment.js @@ -136,8 +136,8 @@ var appendProbeData = function(data) { jsPsych.data.addDataToLastTrial({ correct: correct, probe_letter: probe, - directed_forgetting_condition: directed_condition, - trial_num: current_trial, + directed_forgetting_condition: directed_forgetting_condition, + current_trial: current_trial, correct_response: correct_response, exp_stage: exp_stage, cue: cue, @@ -181,23 +181,23 @@ var getCue = function() { }; // Will pop out a probe type from the entire probeTypeArray and then choose a probe congruent with the probe type -var getProbe = function(letters,directed_condition,cue) { +var getProbe = function(letters,directed_forgetting_condition,cue) { var trainingArray = jsPsych.randomization.repeat(stimArray, 1); var lastSet_top = letters.slice(0,numLetters/2) var lastSet_bottom = letters.slice(numLetters/2) - if (directed_condition == 'pos') { + if (directed_forgetting_condition == 'pos') { if (cue == 'BOT') { probe = lastSet_top[Math.floor(Math.random() * numLetters/2)] } else if (cue == 'TOP') { probe = lastSet_bottom[Math.floor(Math.random() * numLetters/2)] } - } else if (directed_condition == 'neg') { + } else if (directed_forgetting_condition == 'neg') { if (cue == 'BOT') { probe = lastSet_bottom[Math.floor(Math.random() * numLetters/2)] } else if (cue == 'TOP') { probe = lastSet_top[Math.floor(Math.random() * numLetters/2)] } - } else if (directed_condition == 'con') { + } else if (directed_forgetting_condition == 'con') { newArray = trainingArray.filter(function(y) { return (y != lastSet_top[0] && y != lastSet_top[1] && y != lastSet_bottom[0] && y != lastSet_bottom[1]) @@ -219,7 +219,7 @@ var getProbeHTML = function(){ var getLettersHTML = function(){ stim = stims.pop() - directed_condition = stim.directed_condition + directed_forgetting_condition = stim.directed_forgetting_condition letters = stim.letters cue = stim.cue probe = stim.probe @@ -259,14 +259,14 @@ var createTrialTypes = function (numTrialsPerBlock,numLetters){ var stims = [] for (var i = 0; i < numTrialsPerBlock; i++){ - var directed_condition = probeTypeArray.pop() + var directed_forgetting_condition = probeTypeArray.pop() var letters = getTrainingSet(used_letters,numLetters) var cue = getCue() - var probe = getProbe(letters,directed_condition,cue) - var correct_response = getCorrectResponse(directed_condition) + var probe = getProbe(letters,directed_forgetting_condition,cue) + var correct_response = getCorrectResponse(directed_forgetting_condition) stim = { - directed_condition:directed_condition, + directed_forgetting_condition:directed_forgetting_condition, letters: letters, cue: cue, probe: probe, @@ -515,7 +515,7 @@ var start_fixation_block = { on_finish: function() { jsPsych.data.addDataToLastTrial({ exp_stage: exp_stage, - trial_num: current_trial + current_trial: current_trial }) } } @@ -534,7 +534,7 @@ var fixation_block = { on_finish: function() { jsPsych.data.addDataToLastTrial({ exp_stage: exp_stage, - trial_num: current_trial + current_trial: current_trial }) } } @@ -552,7 +552,7 @@ var ITI_fixation_block = { on_finish: function() { jsPsych.data.addDataToLastTrial({ exp_stage: exp_stage, - trial_num: current_trial + current_trial: current_trial }) current_trial = current_trial + 1 } @@ -683,7 +683,7 @@ for (i = 0; i < (practice_length); i++) { on_finish: function() { jsPsych.data.addDataToLastTrial({ exp_stage: exp_stage, - trial_num: current_trial + current_trial: current_trial }) } } @@ -703,7 +703,7 @@ for (i = 0; i < (practice_length); i++) { on_finish: function() { jsPsych.data.addDataToLastTrial({ exp_stage: exp_stage, - trial_num: current_trial + current_trial: current_trial }) } } @@ -722,7 +722,7 @@ for (i = 0; i < (practice_length); i++) { on_finish: function() { jsPsych.data.addDataToLastTrial({ exp_stage: exp_stage, - trial_num: current_trial + current_trial: current_trial }) current_trial = current_trial + 1 } diff --git a/flanker_single_task_network/experiment.js b/flanker_single_task_network/experiment.js index 56c9a6af6..52f294573 100644 --- a/flanker_single_task_network/experiment.js +++ b/flanker_single_task_network/experiment.js @@ -409,6 +409,7 @@ for (i = 0; i < practice_len; i++) { if (data.key_press == data.correct_response) { correct_trial = 1 } + current_trial += 1 current_block = practiceCount jsPsych.data.addDataToLastTrial({correct_trial: correct_trial, @@ -533,13 +534,13 @@ for (i = 0; i < numTrialsPerBlock; i++) { if (data.key_press == data.correct_response) { correct_trial = 1 } - + current_trial += 1 current_block = testCount jsPsych.data.addDataToLastTrial({correct_trial: correct_trial, trial_id: 'test_trial', current_block: current_block, - current_trial: i + current_trial: current_trial }) } }; diff --git a/flanker_with_cued_task_switching/experiment.js b/flanker_with_cued_task_switching/experiment.js index 440c034a3..a1e707a8b 100644 --- a/flanker_with_cued_task_switching/experiment.js +++ b/flanker_with_cued_task_switching/experiment.js @@ -288,9 +288,9 @@ var response_keys = {key: [77,90], key_name: ["M","Z"]} var choices = response_keys.key var practice_length = 16 -var test_length = 240 +var exp_len = 240 var numTrialsPerBlock = 40 -var numTestBlocks = test_length / numTrialsPerBlock +var numTestBlocks = exp_len / numTrialsPerBlock var flanker_styles = ['solid','outlined'] diff --git a/go_nogo_single_task_network/experiment.js b/go_nogo_single_task_network/experiment.js index dc161d6c0..504be954a 100644 --- a/go_nogo_single_task_network/experiment.js +++ b/go_nogo_single_task_network/experiment.js @@ -104,7 +104,7 @@ var appendData = function(data) { } jsPsych.data.addDataToLastTrial({ - trial_num: current_trial, + current_trial: current_trial, }) current_trial +=1 diff --git a/n_back_single_task_network__fmri/config.json b/n_back_single_task_network__fmri/config.json new file mode 100644 index 000000000..3e01e1a02 --- /dev/null +++ b/n_back_single_task_network__fmri/config.json @@ -0,0 +1,51 @@ +[ + { + "name": "N-Back Single Task Network fMRI", + "template":"jspsych", + "run": [ + "static/js/math.min.js", + "static/js/jspsych/jspsych.js", + "static/js/jspsych/plugins/jspsych-call-function.js", + "static/js/jspsych/poldrack_plugins/jspsych-poldrack-text.js", + "static/js/jspsych/poldrack_plugins/jspsych-poldrack-instructions.js", + "static/js/jspsych/poldrack_plugins/jspsych-attention-check.js", + "static/js/jspsych/poldrack_plugins/jspsych-poldrack-single-stim.js", + "static/js/jspsych/poldrack_plugins/jspsych-poldrack-categorize.js", + "static/js/jspsych/plugins/jspsych-survey-text.js", + "static/js/jspsych/poldrack_plugins/jspsych-stop-signal.js", + "static/js/utils/poldrack_fmri_utils.js", + "experiment.js", + "static/css/jspsych.css", + "static/css/default_style.css", + "style.css", + "https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.13.3/math.js" + + + ], + "exp_id": "n_back_single_task_network__fmri", + "cognitive_atlas_task_id": "tsk_4a57abb949e1a", + "contributors": [ + "Patrick Bissett", + "Jamie Li", + "McKenzie Hagen", + "Russell Poldrack" + ], + "time":30, + "reference": "http://psycnet.apa.org/journals/xlm/37/2/392/", + "notes": "Condition refers to whether the trial is practice or high_freq/low_freq (the two test conditions) as well as whether it was a go or SS trial", + "publish":"True", + "experiment_variables": [{ + "name":"credit_var", + "type":"credit", + "datatype": "boolean", + "description":"True if avg_rt > 200" + }], + "deployment_variables":{"jspsych_init": + {"fullscreen": true, + "display_element": "getDisplayElement", + "on_trial_finish": "addID('n_back_single_task_network__fmri')"} + } + + } +] + diff --git a/n_back_single_task_network__fmri/experiment.js b/n_back_single_task_network__fmri/experiment.js new file mode 100644 index 000000000..3fe6b5696 --- /dev/null +++ b/n_back_single_task_network__fmri/experiment.js @@ -0,0 +1,753 @@ +/* ************************************ */ +/* Define Helper Functions */ +/* ************************************ */ + +function genITIs() { + mean_iti = .5 //mean and standard deviation of 0.5 secs + min_thresh = 0 + max_thresh = 4 + + lambda = 1/mean_iti + iti_array = [] + for (i=0; i < exp_len; i++) { + curr_iti = - Math.log(Math.random()) / lambda; + while (curr_iti > max_thresh || curr_iti < min_thresh) { + curr_iti = - Math.log(Math.random()) / lambda; + } + iti_array.push(curr_iti*1000) //convert ITIs from seconds to milliseconds + + } + return(iti_array) +} + +function getITI_stim() { //added for fMRI compatibility + var currITI = ITIs_stim.shift() + return currITI +} + +function getITI_resp() { //added for fMRI compatibility + var currITI = ITIs_resp.shift() + return currITI +} + +function getDisplayElement() { + $('
').appendTo('body') + return $('
').appendTo('body') +} + +function addID() { + jsPsych.data.addDataToLastTrial({exp_id: 'n_back_single_task_network__fmri'}) +} + + + +function assessPerformance() { + var experiment_data = jsPsych.data.getTrialsOfType('poldrack-single-stim') + var missed_count = 0 + var trial_count = 0 + var rt_array = [] + var rt = 0 + var correct = 0 + + //record choices participants made + var choice_counts = {} + choice_counts[-1] = 0 + choice_counts[77] = 0 + choice_counts[90] = 0 + for (var k = 0; k < possible_responses.length; k++) { + choice_counts[possible_responses[k][1]] = 0 + } + for (var i = 0; i < experiment_data.length; i++) { + if (experiment_data[i].trial_id == 'test_trial'){ + trial_count += 1 + rt = experiment_data[i].rt + key = experiment_data[i].key_press + choice_counts[key] += 1 + if (rt == -1) { + missed_count += 1 + } else { + rt_array.push(rt) + } + + if (key == experiment_data[i].correct_response){ + correct += 1 + } + } + } + + //calculate average rt + var avg_rt = -1 + if (rt_array.length !== 0) { + avg_rt = math.median(rt_array) + } + //calculate whether response distribution is okay + var responses_ok = true + Object.keys(choice_counts).forEach(function(key, index) { + if (choice_counts[key] > trial_count * 0.85) { + responses_ok = false + } + }) + var missed_percent = missed_count/trial_count + var accuracy = correct / trial_count + credit_var = (missed_percent < 0.25 && avg_rt > 200 && responses_ok && accuracy > 0.60) + jsPsych.data.addDataToLastTrial({final_credit_var: credit_var, + final_missed_percent: missed_percent, + final_avg_rt: avg_rt, + final_responses_ok: responses_ok, + final_accuracy: accuracy}) +} + + +var getResponse = function() { + return correct_response +} + + + +var getFeedback = function() { + return '

' + feedback_text + '

' +} + + +var randomDraw = function(lst) { + var index = Math.floor(Math.random() * (lst.length)) + return lst[index] +}; + + +var createTrialTypes = function(numTrialsPerBlock, delay){ + first_stims = [] + for (var i = 0; i < 3; i++){ + if (i < delay){ + n_back_condition = 'N/A' + } else { + n_back_condition = n_back_conditions[Math.floor(Math.random() * 5)] + } + probe = randomDraw(letters) + correct_response = possible_responses[1][1] + if (n_back_condition == 'match'){ + correct_response = possible_responses[0][1] + probe = randomDraw([first_stims[i - delay].probe.toUpperCase(), first_stims[i - delay].probe.toLowerCase()]) + } else if (n_back_condition == "mismatch"){ + probe = randomDraw('bBdDgGtTvV'.split("").filter(function(y) {return $.inArray(y, [first_stims[i - delay].probe.toLowerCase(), first_stims[i - delay].probe.toUpperCase()]) == -1})) + correct_response = possible_responses[1][1] + } + + + first_stim = { + n_back_condition: n_back_condition, + probe: probe, + correct_response: correct_response, + delay: delay + } + first_stims.push(first_stim) + } + + stims = [] + + for(var numIterations = 0; numIterations < numTrialsPerBlock/n_back_conditions.length; numIterations++){ + for (var numNBackConds = 0; numNBackConds < n_back_conditions.length; numNBackConds++){ + + n_back_condition = n_back_conditions[numNBackConds] + + stim = { + n_back_condition: n_back_condition + } + stims.push(stim) + } + } + + stims = jsPsych.randomization.repeat(stims,1) + stims = first_stims.concat(stims) + + stim_len = stims.length + + new_stims = [] + for (i = 0; i < stim_len; i++){ + if (i < 3){ + stim = stims.shift() + n_back_condition = stim.n_back_condition + probe = stim.probe + correct_response = stim.correct_response + delay = stim.delay + } else { + stim = stims.shift() + n_back_condition = stim.n_back_condition + + if (n_back_condition == "match"){ + probe = randomDraw([new_stims[i - delay].probe.toUpperCase(), new_stims[i - delay].probe.toLowerCase()]) + correct_response = possible_responses[0][1] + } else if (n_back_condition == "mismatch"){ + probe = randomDraw('bBdDgGtTvV'.split("").filter(function(y) {return $.inArray(y, [new_stims[i - delay].probe.toLowerCase(), new_stims[i - delay].probe.toUpperCase()]) == -1})) + correct_response = possible_responses[1][1] + + } + } + + stim = { + n_back_condition: n_back_condition, + probe: probe, + correct_response: correct_response, + delay: delay + } + + new_stims.push(stim) + } + return new_stims +} + + +var getStim = function(){ + stim = stims.shift() + n_back_condition = stim.n_back_condition + probe = stim.probe + correct_response = stim.correct_response + delay = stim.delay + + if (probe == probe.toUpperCase()) { + letter_case = 'uppercase' + } else if (probe == probe.toLowerCase()) { + letter_case = 'lowercase' + } + + return task_boards[0]+ preFileType + letter_case + '_' + probe.toUpperCase() + fileTypePNG + task_boards[1] +} + +var getResponse = function(){ + return correct_response +} + +var appendData = function(){ + curr_trial = jsPsych.progress().current_trial_global + trial_id = jsPsych.data.getDataByTrialIndex(curr_trial).trial_id + current_trial+=1 + + + if (trial_id == 'practice_trial'){ + current_block = practiceCount + } else if (trial_id == 'test_trial'){ + current_block = testCount + } + + jsPsych.data.addDataToLastTrial({ + n_back_condition: n_back_condition, + probe: probe, + correct_response: correct_response, + delay: delay, + current_trial: current_trial, + current_block: current_block, + letter_case: letter_case + }) + + if (jsPsych.data.getDataByTrialIndex(curr_trial).key_press == correct_response){ + jsPsych.data.addDataToLastTrial({ + correct_trial: 1, + }) + + } else if (jsPsych.data.getDataByTrialIndex(curr_trial).key_press != correct_response){ + jsPsych.data.addDataToLastTrial({ + correct_trial: 0, + }) + + } +} + +/* ************************************ */ +/* Define Experimental Variables */ +/* ************************************ */ +// generic task variables +var sumInstructTime = 0 //ms +var instructTimeThresh = 0 ///in seconds +var credit_var = 0 + + +var practice_len = 15 // must be divisible by 5 +var exp_len = 150 // must be divisible by 5 +var numTrialsPerBlock = 50 // 50, must be divisible by 5 and we need to have a multiple of 3 blocks (3,6,9) in order to have equal delays across blocks +var numTestBlocks = exp_len / numTrialsPerBlock +var practice_thresh = 3 // 3 blocks of 15 trials + +var accuracy_thresh = 0.75 +var rt_thresh = 1000 +var missed_thresh = 0.10 + +var delays = jsPsych.randomization.repeat([1, 2, 3], numTestBlocks / 3) + +var delay = 1 + +var pathSource = "/static/experiments/n_back_single_task_network__fmri/images/" +var fileTypePNG = ".png'>" +var preFileType = "Match the current letter to the letter that appeared some number of trials ago' + + '
  • If they match, press your '+possible_responses[0][0]+'
  • ' + + '
  • If they mismatch, press your '+possible_responses[1][0]+'
  • ' + + '' + +var prompt_text = '
    '+ + '

    Match the current letter to the letter that appeared 1 trial ago

    ' + + '

    If they match, press your '+possible_responses[0][0]+'

    ' + + '

    If they mismatch, press your '+possible_responses[1][0]+'

    ' + + '
    ' + +var current_trial = 0 +var current_block = 0 + +//PRE LOAD IMAGES HERE +var pathSource = "/static/experiments/n_back_single_task_network__fmri/images/" +var lettersPreload = ['B','D','G','T','V'] +var casePreload = ['lowercase','uppercase'] +var images = [] + +for(i = 0; i < lettersPreload.length; i++){ + for(x = 0; x < casePreload.length; x++){ + images.push(pathSource + casePreload[x] + '_' + lettersPreload[i] + '.png') + } +} + +jsPsych.pluginAPI.preloadImages(images); +/* ************************************ */ +/* Define Game Boards */ +/* ************************************ */ + +var task_boards = ['
    ','
    '] + +var stims = createTrialTypes(practice_len, delay) + +/* ************************************ */ +/* Set up jsPsych blocks */ +/* ************************************ */ +var SSD_setup_block = { + type: 'survey-text', + data: { + trial_id: "SSD_setup" + }, + questions: [ + [ + "

    SSD:

    " + ] + ], on_finish: function(data) { + SSD = parseInt(data.responses.slice(7, 10)) + SSD = math.max(100,math.min(400,SSD)) + ITIs_stim = genITIs() + ITIs_resp = ITIs_stim.slice(0) //make a copy of ITIs so that timing_stimulus & timing_response are the same + } +} + + + +var end_block = { + type: 'poldrack-text', + data: { + trial_id: "end" + }, + timing_response: 180000, + text: '

    Thanks for completing this task!

    Press enter to continue.

    ', + cont_key: [13], + timing_post_trial: 0, + on_finish: function(){ + assessPerformance() + } +}; + +//Set up post task questionnaire +var post_task_block = { + type: 'survey-text', + data: { + exp_id: "n_back_single_task_network__fmri", + trial_id: "post task questions" + }, + questions: ['

    Please summarize what you were asked to do in this task.

    ', + '

    Do you have any comments about this task?

    '], + rows: [15, 15], + timing_response: 360000, + columns: [60,60] +}; + + +var instructions_block = { + type: 'poldrack-single-stim', + stimulus: '
    '+ + '

    In this task, you will see a letter on every trial.

    '+ + '

    You will be asked to match the current letter, to the letter that appeared either 1, 2, 3 trials ago depending on the delay given to you for that block.

    '+ + '

    Press your '+possible_responses[0][0]+' if the letters match, and your '+possible_responses[1][0]+' if they mismatch.

    '+ + '

    Your delay (the number of trials ago which you must match the current letter to) will change from block to block. You will be given the delay at the start of every block of trials.

    '+ + '

    Capitalization does not matter, so "T" matches with "t".

    '+ + '

    Your delay for this upcoming practice round is 1.

    '+ + '

    During practice, you will see a reminder of the rules. This will be removed for the test.

    '+ + '

    To let the experimenters know when you are ready to begin, please press any button.

    '+ + '
    ', + is_html: true, + choices: [32], + data: { + trial_id: "instruction", + }, + timing_post_trial: 0, + timing_stim: -1, //until response + timing_response: -1, //until response + response_ends_trial: true +}; + +// var instructions_block = { +// type: 'poldrack-instructions', +// data: { +// trial_id: "instruction" +// }, +// pages: [ +// '
    '+ +// '

    In this task, you will see a letter on every trial.

    '+ +// '

    You will be asked to match the current letter, to the letter that appeared either 1, 2, 3 trials ago depending on the delay given to you for that block.

    '+ +// '

    Press your '+possible_responses[0][0]+' if the letters match, and your '+possible_responses[1][0]+' if they mismatch.

    '+ +// '

    Your delay (the number of trials ago which you must match the current letter to) will change from block to block. You will be given the delay at the start of every block of trials.

    '+ +// '

    Capitalization does not matter, so "T" matches with "t".

    '+ +// '

    Your delay for this upcoming practice round is 1.

    '+ +// '

    During practice, you will see a reminder of the rules. This will be removed for the test.

    '+ +// '

    To let the experimenters know when you are ready to begin, please press any button.

    '+ +// '
    ', +// /* +// '
    '+ +// '

    For example, if your delay for the block was 2, and the letters you received for the first 4 trials were V, B, v, and V, you would respond, no match, no match, match, and no match.

    '+ +// '

    The first letter in that sequence, V, DOES NOT have a preceding trial to match with, so press the '+possible_responses[1][0]+' on those trials.

    '+ +// '

    The second letter in that sequence, B, ALSO DOES NOT have a trial 2 ago to match with, so press the '+possible_responses[1][0]+' on those trials.

    '+ +// '

    The third letter in that sequence, v, DOES match the letter from 2 trials, V, so you would respond match.

    '+ +// '

    The fourth letter in that sequence, V, DOES NOT match the letter from 2 trials ago, B, so you would respond no match.

    '+ +// '
    ', +// */ +// '
    ' + +// '

    We will start practice when you finish instructions. Your delay for this practice round is 1. Please make sure you understand the instructions before moving on. During practice, you will receive a reminder of the rules. This reminder will be taken out for test.

    '+ +// '

    To avoid technical issues, please keep the experiment tab (on Chrome or Firefox) active and in full-screen mode for the whole duration of each task.

    '+ +// '
    ' +// ], +// allow_keys: false, +// show_clickable_nav: true, +// timing_post_trial: 1000 +// }; + + + +/* This function defines stopping criteria */ + +var start_test_block = { + type: 'poldrack-text', + data: { + trial_id: "instruction" + }, + timing_response: 180000, + text: '
    '+ + '

    We will now begin the test portion.

    '+ + '

    You will be asked to match the current letter, to the letter that appeared either 1, 2, 3 trials ago depending on the delay given to you for that block.

    '+ + '

    Press your '+possible_responses[0][0]+' if they match, and your '+possible_responses[1][0]+' if they mismatch.

    '+ + '

    Your delay (the number of trials ago which you must match the current letter to) will change from block to block.

    '+ + '

    Capitalization does not matter, so "T" matches with "t".

    '+ + + '

    You will no longer receive the rule prompt, so remember the instructions before you continue. Press Enter to begin.

    '+ + '
    ', + cont_key: [13], + timing_post_trial: 1000, + on_finish: function(){ + feedback_text = "Your delay for this block is "+delay+". Please match the current letter to the letter that appeared "+delay+" trial(s) ago. Press enter to begin." + } +}; + +var start_control_block = { + type: 'poldrack-text', + data: { + trial_id: "instruction" + }, + timing_response: 180000, + text: '
    '+ + '

    For this block of trials, you do not have to match letters. Instead, indicate whether the current letter is a T (or t).

    '+ + '

    Press your '+possible_responses[0][0]+' if the current letter was a T (or t) and your '+possible_responses[1][0]+' if not.

    '+ + '

    You will no longer receive the rule prompt, so remember the instructions before you continue. Press Enter to begin.

    '+ + '
    ', + cont_key: [13], + timing_post_trial: 1000, + on_finish: function(){ + feedback_text = "We will now start this block. Press enter to begin." + } +}; + + +var practice_fixation_block = { + type: 'poldrack-single-stim', + stimulus: '
    +
    ', + is_html: true, + choices: 'none', + data: { + trial_id: "practice_fixation" + }, + timing_response: 500, //500 + timing_post_trial: 0, +} + +var ITI_fixation_block = { + type: 'poldrack-single-stim', + stimulus: '
    +
    ', + is_html: true, + choices: 'none', + data: { + trial_id: "fixation", + }, + timing_post_trial: 0, + timing_stim: getITI_stim, //500 + timing_response: getITI_resp //500 +}; + + + +var feedback_text = + 'Welcome to the experiment. This experiment will take around 5 minutes. Press enter to begin.' +var feedback_block = { + type: 'poldrack-single-stim', + data: { + trial_id: "practice-no-stop-feedback" + }, + choices: 'none', + stimulus: getFeedback, + timing_post_trial: 0, + is_html: true, + timing_response: 10000, + response_ends_trial: false, + +}; + + +/* ************************************ */ +/* Set up timeline blocks */ +/* ************************************ */ + +var practiceTrials = [] +practiceTrials.push(instructions_block) +for (i = 0; i < practice_len + 3; i++) { + var practice_block = { + type: 'poldrack-categorize', + stimulus: getStim, + is_html: true, + choices: [possible_responses[0][1],possible_responses[1][1]], + key_answer: getResponse, + data: { + trial_id: "practice_trial" + }, + correct_text: '
    Correct!
    ' + prompt_text, + incorrect_text: '
    Incorrect
    ' + prompt_text, + timeout_message: '
    Respond Faster!
    ' + prompt_text, + timing_stim: 1000, //1000 + timing_response: 2000, //2000 + timing_feedback_duration: 500, + show_stim_with_feedback: false, + timing_post_trial: 0, + on_finish: appendData, + prompt: prompt_text + } + practiceTrials.push(practice_fixation_block) + practiceTrials.push(practice_block) +} + +var practiceCount = 0 +var practiceNode = { + timeline: practiceTrials, + loop_function: function(data) { + practiceCount += 1 + stims = createTrialTypes(practice_len, delay) + current_trial = 0 + + var sum_rt = 0 + var sum_responses = 0 + var correct = 0 + var total_trials = 0 + var mismatch_press = 0 + + for (var i = 0; i < data.length; i++){ + if (data[i].trial_id == "practice_trial"){ + total_trials+=1 + if (data[i].rt != -1){ + sum_rt += data[i].rt + sum_responses += 1 + if (data[i].key_press == data[i].correct_response){ + correct += 1 + + } + } + + if (data[i].key_press == possible_responses[1][1]){ + mismatch_press += 1 + } + + } + + } + + var accuracy = correct / total_trials + var missed_responses = (total_trials - sum_responses) / total_trials + var ave_rt = sum_rt / sum_responses + var mismatch_press_percentage = mismatch_press / total_trials + + feedback_text = "
    Please take this time to read your feedback and to take a short break." // Press enter to continue" + + if (accuracy > accuracy_thresh){ + feedback_text += + '

    Done with this practice. The test session will begin shortly.' + delay = delays.pop() + stims = createTrialTypes(numTrialsPerBlock, delay) + return false + + } else if (accuracy < accuracy_thresh){ + if (missed_responses > missed_thresh){ + feedback_text += + '

    You have not been responding to some trials. Please respond on every trial that requires a response.' + } + + if (ave_rt > rt_thresh){ + feedback_text += + '

    You have been responding too slowly.' + } + + if (mismatch_press_percentage >= 0.90){ + feedback_text += + '

    Please do not simply press your "'+possible_responses[1][0]+'" to every stimulus. Please try to identify the matches and press your "'+possible_responses[0][0]+'" when they occur.' + } + + if (practiceCount == practice_thresh){ + feedback_text += + '

    Done with this practice. The test session will begin shortly.' + delay = delays.pop() + stims = createTrialTypes(numTrialsPerBlock, delay) + return false + } + + feedback_text += + '

    We are going to try practice again to see if you can achieve higher accuracy. Remember:
    ' + prompt_text_list + + feedback_text += + '

    Press Enter to continue.' + + return true + + } + + } +} + +var testTrials = [] +testTrials.push(feedback_block) +for (i = 0; i < numTrialsPerBlock + 3; i++) { + + var test_block = { + type: 'poldrack-single-stim', + stimulus: getStim, + is_html: true, + data: { + "trial_id": "test_trial", + }, + choices: [possible_responses[0][1],possible_responses[1][1]], + timing_stim: 1000, //1000 + timing_response: 2000, //2000 + timing_post_trial: 0, + response_ends_trial: false, + on_finish: appendData + } + testTrials.push(ITI_fixation_block) + testTrials.push(test_block) +} + +var testCount = 0 +var testNode = { + timeline: testTrials, + loop_function: function(data) { + testCount += 1 + current_trial = 0 + + var sum_rt = 0 + var sum_responses = 0 + var correct = 0 + var total_trials = 0 + var mismatch_press = 0 + + for (var i = 0; i < data.length; i++){ + if (data[i].trial_id == "test_trial"){ + total_trials+=1 + if (data[i].rt != -1){ + sum_rt += data[i].rt + sum_responses += 1 + if (data[i].key_press == data[i].correct_response){ + correct += 1 + } + } + + if (data[i].key_press == possible_responses[1][1]){ + mismatch_press += 1 + } + } + } + + var accuracy = correct / total_trials + var missed_responses = (total_trials - sum_responses) / total_trials + var ave_rt = sum_rt / sum_responses + var mismatch_press_percentage = mismatch_press / total_trials + + feedback_text = "
    Please take this time to read your feedback and to take a short break! Press enter to continue" + feedback_text += "

    You have completed: "+testCount+" out of "+numTestBlocks+" blocks of trials." + + if (accuracy < accuracy_thresh){ + feedback_text += + '

    Your accuracy is too low. Remember:
    ' + prompt_text_list + } + if (missed_responses > missed_thresh){ + feedback_text += + '

    You have not been responding to some trials. Please respond on every trial that requires a response.' + } + + if (ave_rt > rt_thresh){ + feedback_text += + '

    You have been responding too slowly.' + } + + if (mismatch_press_percentage >= 0.90){ + feedback_text += + '

    Please do not simply press your "'+possible_responses[1][0]+'" to every stimulus. Please try to identify the matches and press your "'+possible_responses[0][0]+'" when they occur.' + } + + if (testCount == numTestBlocks){ + feedback_text += + '

    Done with this test. Press Enter to continue.
    If you have been completing tasks continuously for an hour or more, please take a 15-minute break before starting again.' + return false + } else { + delay = delays.pop() + stims = createTrialTypes(numTrialsPerBlock, delay) + feedback_text += "

    For the next round of trials, your delay is "+delay+". Press Enter to continue." + return true + } + } +} + + +/* ************************************ */ +/* Set up Experiment */ +/* ************************************ */ + +var n_back_single_task_network__fmri_experiment = [] + +n_back_single_task_network__fmri_experiment.push(SSD_setup_block); //exp_input + +test_keys(n_back_single_task_network__fmri_experiment, [possible_responses[0][1],possible_responses[1][1]]) +n_back_single_task_network__fmri_experiment.push(practiceNode); +n_back_single_task_network__fmri_experiment.push(feedback_block); + + +//n_back_single_task_network__fmri_experiment.push(start_test_block); +setup_fmri_intro(n_back_single_task_network__fmri_experiment) +n_back_single_task_network__fmri_experiment.push(testNode); +n_back_single_task_network__fmri_experiment.push(feedback_block); + +n_back_single_task_network__fmri_experiment.push(post_task_block); +n_back_single_task_network__fmri_experiment.push(end_block); diff --git a/n_back_single_task_network__fmri/images/lowercase_B.png b/n_back_single_task_network__fmri/images/lowercase_B.png new file mode 100644 index 000000000..9ff98ec94 Binary files /dev/null and b/n_back_single_task_network__fmri/images/lowercase_B.png differ diff --git a/n_back_single_task_network__fmri/images/lowercase_D.png b/n_back_single_task_network__fmri/images/lowercase_D.png new file mode 100644 index 000000000..bc7f2d31c Binary files /dev/null and b/n_back_single_task_network__fmri/images/lowercase_D.png differ diff --git a/n_back_single_task_network__fmri/images/lowercase_G.png b/n_back_single_task_network__fmri/images/lowercase_G.png new file mode 100644 index 000000000..94ea1a98e Binary files /dev/null and b/n_back_single_task_network__fmri/images/lowercase_G.png differ diff --git a/n_back_single_task_network__fmri/images/lowercase_T.png b/n_back_single_task_network__fmri/images/lowercase_T.png new file mode 100644 index 000000000..fda5cbca6 Binary files /dev/null and b/n_back_single_task_network__fmri/images/lowercase_T.png differ diff --git a/n_back_single_task_network__fmri/images/lowercase_V.png b/n_back_single_task_network__fmri/images/lowercase_V.png new file mode 100644 index 000000000..c747297a0 Binary files /dev/null and b/n_back_single_task_network__fmri/images/lowercase_V.png differ diff --git a/n_back_single_task_network__fmri/images/uppercase_B.png b/n_back_single_task_network__fmri/images/uppercase_B.png new file mode 100644 index 000000000..cb6088a9c Binary files /dev/null and b/n_back_single_task_network__fmri/images/uppercase_B.png differ diff --git a/n_back_single_task_network__fmri/images/uppercase_D.png b/n_back_single_task_network__fmri/images/uppercase_D.png new file mode 100644 index 000000000..b97e86e44 Binary files /dev/null and b/n_back_single_task_network__fmri/images/uppercase_D.png differ diff --git a/n_back_single_task_network__fmri/images/uppercase_G.png b/n_back_single_task_network__fmri/images/uppercase_G.png new file mode 100644 index 000000000..809b7730b Binary files /dev/null and b/n_back_single_task_network__fmri/images/uppercase_G.png differ diff --git a/n_back_single_task_network__fmri/images/uppercase_T.png b/n_back_single_task_network__fmri/images/uppercase_T.png new file mode 100644 index 000000000..afd55a738 Binary files /dev/null and b/n_back_single_task_network__fmri/images/uppercase_T.png differ diff --git a/n_back_single_task_network__fmri/images/uppercase_V.png b/n_back_single_task_network__fmri/images/uppercase_V.png new file mode 100644 index 000000000..fbcd74918 Binary files /dev/null and b/n_back_single_task_network__fmri/images/uppercase_V.png differ diff --git a/n_back_single_task_network__fmri/style.css b/n_back_single_task_network__fmri/style.css new file mode 100644 index 000000000..5b528d06c --- /dev/null +++ b/n_back_single_task_network__fmri/style.css @@ -0,0 +1,146 @@ +/*******************************************************/ +/*********** Network Default CSS Styles **********/ +/*******************************************************/ + +.display_stage { + position: fixed; + background: gray; + left: 5vw; + top: 2vh; + height: 94vh; + width: 90vw; + border-radius: 15px; + border: 1vh solid #D0D0D0; + z-index: 0; +} + +.display_stage > div, .display_stage > p { + color: white; +} + +.flanker-text { + text-align: center; + font-size: 50px; + position: relative; + top: 50%; + transform: translateY(-50%); + -webkit-transform: translateY(-50%); +} + + + +.fb_box { + width:35vw; + height: 20vh; + position:absolute; + top:50%; + left:50%; + margin-right:-50%; + transform: translate(-50%,-175%); +} + +.picture_box { + width: 60%; + height: 60%; + position:absolute; + top:50%; + left:50%; + transform: translate(-50%,-50%); + margin-right:0%; + background-color: none; + text-align: center; +} + + +.fixation { + text-align: center; + font-size: 50px; + position: relative; + top: 50%; + transform: translateY(-50%); + -webkit-transform: translateY(-50%); +} + +.cue-text { + width:20vw; + height: 20vh; + position:absolute; + top:50%; + left:50%; + margin-right:-50%; + transform: translate(-50%,-50%); +} + +.bigbox { +width:100%; +margin: auto; +min-height: 100%; +position:absolute; +top:0%; +left:0%; +margin-right:0%; +background-color: none; +text-align: center; +} + +.instructBox { + width: 80vw; + height: 10vw; + position:absolute; + top:10%; + left:50%; + margin-right: 0%; + transform: translate(-50%,-50%); + background-color: none; + font-size: 24px; +} + +.prompt_box { + width: 75%; + height: 20%; + position:absolute; + top:10%; + left:20%; + transform: translate(-50%,-45%); + margin-right:0%; + background-color: none; + text-align: center; +} + +img.center { + height: auto; + width: auto\9; /* ie8 */ + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; + max-height: 65%; +} + +/*******************************************************/ +/*********** Stop Signal CSS Styles **********/ +/*******************************************************/ + +.starbox { + width: 30vw; + height: 30vh; + position:absolute; + top:50%; + left:50%; + margin-right:-50%; + transform: translate(-50%,-50%); +} + + +.gng_number { +width: 5vw; +height: 5vw; +position:absolute; +top:50%; +left:50%; +margin-right:0%; +transform: translate(-50%,-50%); +background-color: none; +} \ No newline at end of file diff --git a/shape_matching_single_task_network/experiment.js b/shape_matching_single_task_network/experiment.js index ffb897882..f2b4b54f3 100644 --- a/shape_matching_single_task_network/experiment.js +++ b/shape_matching_single_task_network/experiment.js @@ -109,7 +109,7 @@ var getStim = function() { } else if (trial_type[2] == 'N'){ distractor_i = 'none' } - currData.trial_num = current_trial + currData.current_trial = current_trial currData.shape_matching_condition = trial_type currData.probe_id = probe_i currData.target_id = target_i diff --git a/shape_matching_with_cued_task_switching/experiment.js b/shape_matching_with_cued_task_switching/experiment.js index e2241e75f..ab62b59ed 100644 --- a/shape_matching_with_cued_task_switching/experiment.js +++ b/shape_matching_with_cued_task_switching/experiment.js @@ -297,7 +297,7 @@ var appendData = function() { task_condition: task_switch.task_switch, cue_condition: task_switch.cue_switch, shape_matching_condition: shape_matching_condition, - trial_num: trial_num, + current_trial: trial_num, probe: probe, target: target, distractor: distractor, diff --git a/shape_matching_with_predictable_task_switching/experiment.js b/shape_matching_with_predictable_task_switching/experiment.js index 5fd328dd0..6faad4403 100644 --- a/shape_matching_with_predictable_task_switching/experiment.js +++ b/shape_matching_with_predictable_task_switching/experiment.js @@ -262,17 +262,18 @@ var getFixation = function(){ var appendData = function(){ curr_trial = jsPsych.progress().current_trial_global trial_id = jsPsych.data.getDataByTrialIndex(curr_trial).trial_id + current_trial += 1 jsPsych.data.addDataToLastTrial({ predictable_condition: predictable_condition, predictable_dimension: predictable_dimension, shape_matching_condition: shape_matching_condition, + current_trial: current_trial, probe: probe, target: target, distractor: distractor, correct_response: correct_response, - whichQuadrant: whichQuadrant - + whichQuadrant: whichQuadrant, }) if (jsPsych.data.getDataByTrialIndex(curr_trial).key_press == correct_response){ @@ -624,6 +625,7 @@ var practiceNode = { loop_function: function(data){ practiceCount += 1 stims = createTrialTypes(practice_len) + current_trial = 0 var sum_rt = 0 var sum_responses = 0 @@ -731,6 +733,7 @@ var testNode = { timeline: testTrials, loop_function: function(data) { testCount += 1 + current_trial = 0 stims = createTrialTypes(numTrialsPerBlock) console.log('hereherhe') diff --git a/stop_signal_single_task_network__fmri/config.json b/stop_signal_single_task_network__fmri/config.json new file mode 100644 index 000000000..cf995a59e --- /dev/null +++ b/stop_signal_single_task_network__fmri/config.json @@ -0,0 +1,52 @@ +[ + { + "name": "Stop Signal Single Task Network fMRI", + "template":"jspsych", + "run": [ + "static/js/math.min.js", + "static/js/jspsych/jspsych.js", + "static/js/jspsych/plugins/jspsych-call-function.js", + "static/js/jspsych/plugins/jspsych-text.js", + "static/js/jspsych/poldrack_plugins/jspsych-poldrack-text.js", + "static/js/jspsych/poldrack_plugins/jspsych-poldrack-instructions.js", + "static/js/jspsych/poldrack_plugins/jspsych-attention-check.js", + "static/js/jspsych/poldrack_plugins/jspsych-poldrack-single-stim.js", + "static/js/jspsych/poldrack_plugins/jspsych-poldrack-categorize.js", + "static/js/jspsych/poldrack_plugins/jspsych-stop-signal.js", + "static/js/jspsych/plugins/jspsych-survey-text.js", + "static/js/utils/poldrack_fmri_utils.js", + "experiment.js", + "static/css/jspsych.css", + "static/css/default_style.css", + "style.css" + + + ], + "exp_id": "stop_signal_single_task_network__fmri", + "cognitive_atlas_task_id": "tsk_4a57abb949e1a", + "contributors": [ + "Patrick Bissett", + "Jamie Li", + "McKenzie Hagen", + "Russell Poldrack", + "Henry Jones", + "Tony Bui" + ], + "time":30, + "reference": "http://psycnet.apa.org/journals/xlm/37/2/392/", + "notes": "Condition refers to whether the trial is practice or high_freq/low_freq (the two test conditions) as well as whether it was a go or SS trial", + "publish":"True", + "experiment_variables": [{ + "name":"credit_var", + "type":"credit", + "datatype": "boolean", + "description":"True if avg_rt > 200" + }], + "deployment_variables":{"jspsych_init": + {"fullscreen": true, + "display_element": "getDisplayElement", + "on_trial_finish": "addID('stop_signal_single_task_network__fmri')"} + } + + } +] diff --git a/stop_signal_single_task_network__fmri/experiment.js b/stop_signal_single_task_network__fmri/experiment.js new file mode 100755 index 000000000..111363182 --- /dev/null +++ b/stop_signal_single_task_network__fmri/experiment.js @@ -0,0 +1,841 @@ +/* ************************************ */ +/* Define Helper Functions */ +/* ************************************ */ + +function genITIs() { + mean_iti = .5 //mean and standard deviation of 0.5 secs + min_thresh = 0 + max_thresh = 4 + + lambda = 1/mean_iti + iti_array = [] + for (i=0; i < exp_len; i++) { + curr_iti = - Math.log(Math.random()) / lambda; + while (curr_iti > max_thresh || curr_iti < min_thresh) { + curr_iti = - Math.log(Math.random()) / lambda; + } + iti_array.push(curr_iti*1000) //convert ITIs from seconds to milliseconds + + } + return(iti_array) +} + + + +function getDisplayElement() { + $('

    ').appendTo('body') + return $('
    ').appendTo('body') +} + +function addID() { + jsPsych.data.addDataToLastTrial({exp_id: 'stop_signal_single_task_network__fmri'}) +} + +function assessPerformance() { + var experiment_data = jsPsych.data.getTrialsOfType('stop-signal') + var missed_count = 0 + var trial_count = 0 + var rt_array = [] + var rt = 0 + var correct = 0 + var all_trials = 0 + + console.log(experiment_data.length) + + //record choices participants made + var choice_counts = {} + choice_counts[-1] = 0 + choice_counts[77] = 0 + choice_counts[90] = 0 + + for (var i = 0; i < experiment_data.length; i++) { + if (experiment_data[i].trial_id == 'test_trial') { + all_trials += 1 + key = experiment_data[i].key_press + choice_counts[key] += 1 + if (experiment_data[i].stop_signal_condition == 'go'){ + trial_count += 1 + } + + if ((experiment_data[i].stop_signal_condition == 'go') && (experiment_data[i].rt != -1)){ + rt = experiment_data[i].rt + rt_array.push(rt) + if (experiment_data[i].key_press == experiment_data[i].correct_response){ + correct += 1 + } + } else if ((experiment_data[i].stop_signal_condition == 'stop') && (experiment_data[i].rt != -1)){ + rt = experiment_data[i].rt + rt_array.push(rt) + } else if ((experiment_data[i].stop_signal_condition == 'go') && (experiment_data[i].rt == -1)){ + missed_count += 1 + } + } + } + + + //calculate average rt + var avg_rt = -1 + if (rt_array.length !== 0) { + avg_rt = math.median(rt_array) + } + //calculate whether response distribution is okay + var responses_ok = true + Object.keys(choice_counts).forEach(function(key, index) { + if (choice_counts[key] > all_trials * 0.85) { + responses_ok = false + } + }) + var missed_percent = missed_count/trial_count + var accuracy = correct / trial_count + credit_var = (missed_percent < 0.25 && avg_rt > 200 && responses_ok && accuracy > 0.60) + jsPsych.data.addDataToLastTrial({final_credit_var: credit_var, + final_missed_percent: missed_percent, + final_avg_rt: avg_rt, + final_responses_ok: responses_ok, + final_accuracy: accuracy}) +} + +var getFeedback = function() { + return '

    ' + feedback_text + '

    ' +} + + +var getCategorizeFeedback = function(){ + curr_trial = jsPsych.progress().current_trial_global - 1 + trial_id = jsPsych.data.getDataByTrialIndex(curr_trial).trial_id + if ((trial_id == 'practice_trial') && (jsPsych.data.getDataByTrialIndex(curr_trial).stop_signal_condition == 'go')){ + if (jsPsych.data.getDataByTrialIndex(curr_trial).key_press == jsPsych.data.getDataByTrialIndex(curr_trial).correct_response){ + + + return '
    Correct!
    ' + prompt_text + } else if ((jsPsych.data.getDataByTrialIndex(curr_trial).key_press != jsPsych.data.getDataByTrialIndex(curr_trial).correct_response) && (jsPsych.data.getDataByTrialIndex(curr_trial).key_press != -1)){ + + + return '
    Incorrect
    ' + prompt_text + + } else if (jsPsych.data.getDataByTrialIndex(curr_trial).key_press == -1){ + + + return '
    Respond Faster!
    ' + prompt_text + + } + } else if ((trial_id == 'practice_trial') && (jsPsych.data.getDataByTrialIndex(curr_trial).stop_signal_condition == 'stop')){ + if (jsPsych.data.getDataByTrialIndex(curr_trial).rt == -1){ + return '
    Correct!
    ' + prompt_text + } else if (jsPsych.data.getDataByTrialIndex(curr_trial).rt != -1){ + return '
    There was a star.
    ' + prompt_text + } + + } +} + +var createTrialTypes = function(numTrialsPerBlock){ + var unique_combos = stop_signal_conditions.length*totalShapesUsed + + var stims = [] + for (var x = 0; x < stop_signal_conditions.length; x++){ + for (var j = 0; j < totalShapesUsed; j++){ + stim = { + stim: shapes[j], + correct_response: possible_responses[j][1], + stop_signal_condition: stop_signal_conditions[x] + } + stims.push(stim) + } + } + + var iteration = numTrialsPerBlock/unique_combos + + stims = jsPsych.randomization.repeat(stims,iteration) + return stims +} + + +var getStopStim = function(){ + return preFileType + 'stopSignal' + fileTypePNG +} + +var getStim = function(){ + + if(exp_phase == "practice1"){ + stim = stims.pop() + shape = stim.stim + correct_response = stim.correct_response + stop_signal_condition = "practice_no_stop" + + } else if ((exp_phase == "test") || (exp_phase == "practice2")){ + stim = stims.pop() + shape = stim.stim + stop_signal_condition = stim.stop_signal_condition + correct_response = stim.correct_response + + + + if(stop_signal_condition == "stop"){ + correct_response = -1 + } + } + + stim = { + image: '
    ' + preFileType + shape + fileTypePNG + '
    ', + data: { + stim: shape, + stop_signal_condition: stop_signal_condition, + correct_response: correct_response + } + } + stimData = stim.data + return stim.image +} + + +function getSSD(){ + return SSD +} + +function getSSType(){ + return stop_signal_condition +} + +function getITI_stim() { //added for fMRI compatibility + var currITI = ITIs_stim.shift() + return currITI +} + +function getITI_resp() { //added for fMRI compatibility + var currITI = ITIs_resp.shift() + return currITI +} + + +var appendData = function(){ + curr_trial = jsPsych.progress().current_trial_global + current_trial+=1 + + if (exp_phase == "practice1"){ + currBlock = practiceCount + } else if (exp_phase == "practice2"){ + currBlock = practiceStopCount + } else if (exp_phase == "test"){ + currBlock = testCount + } + + if ((exp_phase == "practice1") || (exp_phase == "practice2") || (exp_phase == "test")){ + jsPsych.data.addDataToLastTrial({ + stim: stimData.stim, + correct_response: correct_response, + current_block: currBlock, + current_trial: current_trial, + stop_signal_condition: stimData.stop_signal_condition + }) + + if (jsPsych.data.getDataByTrialIndex(curr_trial).key_press == correct_response){ + jsPsych.data.addDataToLastTrial({ + correct_trial: 1, + }) + + } else if (jsPsych.data.getDataByTrialIndex(curr_trial).key_press != correct_response){ + jsPsych.data.addDataToLastTrial({ + correct_trial: 0, + }) + } + } + + + if ((exp_phase == "test") || (exp_phase == "practice2")){ + + if ((jsPsych.data.getDataByTrialIndex(curr_trial).key_press == -1) && (jsPsych.data.getDataByTrialIndex(curr_trial).stop_signal_condition == 'stop') && (SSD < maxSSD)){ + jsPsych.data.addDataToLastTrial({stop_acc: 1}) + SSD+=50 + } else if ((jsPsych.data.getDataByTrialIndex(curr_trial).key_press != -1) && (jsPsych.data.getDataByTrialIndex(curr_trial).stop_signal_condition == 'stop') && (SSD > minSSD)){ + jsPsych.data.addDataToLastTrial({stop_acc: 0}) + SSD-=50 + } + + + if ((jsPsych.data.getDataByTrialIndex(curr_trial).key_press == jsPsych.data.getDataByTrialIndex(curr_trial).correct_response) && (jsPsych.data.getDataByTrialIndex(curr_trial).stop_signal_condition == 'go')){ + jsPsych.data.addDataToLastTrial({go_acc: 1}) + } else if ((jsPsych.data.getDataByTrialIndex(curr_trial).key_press != jsPsych.data.getDataByTrialIndex(curr_trial).correct_response) && (jsPsych.data.getDataByTrialIndex(curr_trial).stop_signal_condition == 'go')){ + jsPsych.data.addDataToLastTrial({go_acc: 0}) + } + + } + +} + +/* ************************************ */ +/* Define Experimental Variables */ +/* ************************************ */ + +//fmri variables +var ITIs_stim = [] +var ITIs_resp = [] + + +// generic task variables +var sumInstructTime = 0 //ms +var instructTimeThresh = 0 ///in seconds +var credit_var = 0 +var run_attention_checks = true + + +var practice_len = 24 // 24 must be divisible by 12 +var exp_len = 144 // must be divisible by 12 +var numTrialsPerBlock = 48 // must be divisible by 12 +var numTestBlocks = exp_len / numTrialsPerBlock +var practice_thresh = 3 // 3 blocks of 12 trials + +var accuracy_thresh = 0.80 +var missed_thresh = 0.10 +var SSD = 350 +var maxSSD = 1000 +var minSSD = 0 +var current_trial = 0 + + +var rt_thresh = 1000; +var missed_response_thresh = 0.10; +var accuracy_thresh = 0.75; + +var maxStopCorrect = 0.70 +var minStopCorrect = 0.30 + +var maxStopCorrectPractice = 1 +var minStopCorrectPractice = 0 + + +var stop_signal_conditions = ['go','go','stop'] +var shapes = ['circle','circle','square','square'] +//'hourglass', 'Lshape', 'moon', 'oval', 'rectangle', 'rhombus', 'tear', 'trapezoid' +var color = "black" +var totalShapesUsed = 4 + + +var possible_responses = [['index finger', 89], ['index finger', 89], ['middle finger', 71], ['middle finger', 71]] //fmri responses - keys: BYGRM = thumb->pinky + + +var postFileType = "'>" +var pathSource = "/static/experiments/stop_signal_single_task_network__fmri/images/" +var fileType = ".png" +var preFileType = "" +var preFileType = "' + shapes[0] + ': ' + possible_responses[0][0] + '' + + '
  • ' + shapes[2] + ': ' + possible_responses[2][0] + '
  • ' + + '
  • Do not respond if a star appears!
  • ' + + '' + +var prompt_text = '
    '+ + '

    ' + shapes[0] + ': ' + possible_responses[0][0] + '

    ' + + '

    ' + shapes[2] + ': ' + possible_responses[2][0] + '

    ' + + '

    Do not respond if a star appears!

    ' + + '
    ' + + + +var stims = createTrialTypes(numTrialsPerBlock) +var exp_phase = "practice2" +var exp_phase = "test" + + + +/* ************************************ */ +/* Set up jsPsych blocks */ +/* ************************************ */ +var end_block = { + type: 'poldrack-text', + data: { + exp_id: "stop_signal_single_task_network__fmri", + trial_id: "end" + }, + timing_response: 180000, + text: '
    '+ + '

    Thanks for completing this task!

    '+ + '
    ', + cont_key: [13], + timing_post_trial: 0, + on_finish: function(){ + assessPerformance() + } +}; + + +var instructions_block = { + type: 'poldrack-single-stim', + stimulus: '
    '+ + '

    In this task you will see shapes appear on the screen one at a time.

    ' + + '

    Only one response is correct for each shape.

    '+ + '

    If the shape is a '+shapes[0]+', press your '+possible_responses[0][0]+'.

    '+ + '

    If the shape is a '+shapes[2]+', press your '+possible_responses[2][0]+'.

    '+ + //'

    You should respond as quickly and accurately as possible to each shape.

    '+ + '

    On some trials, a star will appear around the shape. The star will appear with, or shortly after the shape appears.

    '+ + '

    If you see a star appear, please try your best to withhold your response on that trial.

    '+ + '

    If the star appears on a trial, and you try your best to withhold your response, you will find that you will be able to stop sometimes but not always.

    '+ + '

    Please do not slow down your responses in order to wait for the star. You should respond as quickly and accurately as possible to each shape.

    '+ + '

    During practice, you will see a reminder of the rules. This will be removed for the test.

    '+ + '

    To let the experimenters know when you are ready to begin, please press any button.

    '+ + '
    ', + is_html: true, + choices: [32], + data: { + trial_id: "instruction", + }, + timing_post_trial: 0, + timing_stim: -1, //until response + timing_response: -1, //until response + response_ends_trial: true +}; + + +var ITI_fixation_block = { + type: 'poldrack-single-stim', + stimulus: '
    +
    ', + is_html: true, + choices: 'none', + data: { + trial_id: "fixation", + }, + timing_post_trial: 0, + timing_stim: getITI_stim, //500 + timing_response: getITI_resp //500 +}; + +var practice_fixation_block = { + type: 'poldrack-single-stim', + stimulus: '
    +
    ', + is_html: true, + choices: 'none', + data: { + trial_id: "prompt_fixation", + }, + timing_post_trial: 0, + timing_stim: 500, //500 + timing_response: 500, //500 + prompt: prompt_text +}; + + +var practice_intro = { + type: 'poldrack-single-stim', + stimulus: '

    We will now start the practice for the experiment.

    For these trials, you must press your '+possible_responses[0][0]+', '+ ' or '+possible_responses[2][0]+ ' depending on the shape of the stimulus. Make sure to respond as quickly and accurately as possible to the shape.

    The responses for each shape are as follows: ' + + prompt_text + + '

    Remember these rules before you proceed.

    Press any button to begin.

    ', + is_html: true, + choices: [32], + data: { + trial_id: "stop_intro_phase1" + }, + timing_post_trial: 0, + timing_response: 180000, + response_ends_trial: true +}; + +var feedback_text = 'We will start practice. During practice, you will receive a prompt to remind you of the rules. This prompt will be removed for test!' // Press any button to begin.' +var feedback_block = { + type: 'poldrack-single-stim', + data: { + trial_id: "practice-no-stop-feedback" + }, + choices: [32], + stimulus: getFeedback, + timing_post_trial: 0, + is_html: true, + timing_response: 10000, //10 seconds for feedback + response_ends_trial: false, + +}; + + +var test_intro = { + type: 'poldrack-single-stim', + stimulus: '
    '+ + '

    We will now begin the test portion.

    '+ + '

    You will see a shape on every trial. Please respond to each shape as quickly and accurately as possible!

    '+ + '

    If the shape is a '+shapes[0]+', press your '+possible_responses[0][0]+'.

    '+ + '

    If the shape is a '+shapes[2]+', press your '+possible_responses[2][0]+'.

    '+ + '

    Do not respond if you see a star.

    '+ + '

    You will no longer receive the rule prompt, so remember the instructions before you continue. Press any button to begin.

    '+ + '
    ', + + is_html: true, + choices: [32], + data: { + trial_id: "test_intro" + }, + timing_post_trial: 0, + timing_response: 180000, + response_ends_trial: true, + on_finish: function(){ + feedback_text = 'We will now start the test session. Please concentrate on responding quickly and accurately to each stimulus. Press any button to begin.' + } +}; + +var feedback_text = 'The test will begin shortly.'// Press any button to begin.' +var feedback_block = { + type: 'poldrack-single-stim', + data: { + trial_id: "practice-no-stop-feedback" + }, + choices: 'none', + stimulus: getFeedback, + timing_post_trial: 0, + is_html: true, + timing_response: 10000, //10 seconds + response_ends_trial: false, + +}; +/********************************************/ +/* Set up nodes */ +/********************************************/ + +var SSD_setup_block = { + type: 'survey-text', + data: { + trial_id: "SSD_setup" + }, + questions: [ + [ + "

    SSD:

    " + ] + ], on_finish: function(data) { + SSD = parseInt(data.responses.slice(7, 10)) + SSD = math.max(100,math.min(400,SSD)) + ITIs_stim = genITIs() + ITIs_resp = ITIs_stim.slice(0) //make a copy of ITIs so that timing_stimulus & timing_response are the same + } +} + + +var practiceStopTrials = [] +//practiceStopTrials.push(feedback_block) +practiceStopTrials.push(instructions_block) +for (i = 0; i < practice_len; i++) { + var practice_block = { + type: 'stop-signal', + stimulus: getStim, + SS_stimulus: getStopStim, + SS_trial_type: getSSType, + data: { + trial_id: "practice_trial", + }, + is_html: true, + choices: [possible_responses[0][1], possible_responses[2][1]], + timing_stim: 1000, //1000 + timing_response: 2000, //2000 + response_ends_trial: false, + SSD: getSSD, + timing_SS: 500, //500 + timing_post_trial: 0, + on_finish: appendData, + prompt: prompt_text, + on_start: function(){ + stoppingTracker = [] + stoppingTimeTracker = [] + } + } + + var categorize_block = { + type: 'poldrack-single-stim', + data: { + trial_id: "practice-stop-feedback" + }, + choices: 'none', + stimulus: getCategorizeFeedback, + timing_post_trial: 0, + is_html: true, + timing_stim: 500, //500 + timing_response: 500, //500 + response_ends_trial: false, + + }; + + practiceStopTrials.push(practice_fixation_block) + practiceStopTrials.push(practice_block) + practiceStopTrials.push(categorize_block) + +} + + +var practiceStopCount = 0 +var practiceStopNode = { + timeline: practiceStopTrials, + loop_function: function(data) { + practiceStopCount = practiceStopCount + 1 + current_trial = 0 + stims = createTrialTypes(numTrialsPerBlock) + + var total_trials = 0 + + var sum_stop_rt = 0; + var sum_go_rt = 0; + + var sumGo_correct = 0; + var sumStop_correct = 0; + + var num_go_responses = 0; + var num_stop_responses = 0; + + var go_length = 0; + var stop_length = 0 + + for (i = 0; i < data.length; i++) { + if (data[i].trial_id == "practice_trial"){ + total_trials += 1 + } + + if (data[i].stop_signal_condition == "go"){ + go_length += 1 + if (data[i].rt != -1) { + num_go_responses += 1 + sum_go_rt += data[i].rt; + if (data[i].key_press == data[i].correct_response) { + sumGo_correct += 1 + } + } + } else if (data[i].stop_signal_condition == "stop") { + stop_length += 1 + if (data[i].rt != -1){ + num_stop_responses += 1 + sum_stop_rt += data[i].rt + } else if (data[i].rt == -1){ + sumStop_correct += 1 + } + } + } + + var average_rt = sum_go_rt / num_go_responses; + var missed_responses = (go_length - num_go_responses) / go_length + + var aveShapeRespondCorrect = sumGo_correct / go_length + + var stop_signal_respond = num_stop_responses / stop_length + + + + + feedback_text = "
    Please take this time to read your feedback and to take a short break." //Press any button to continue." + + if (practiceStopCount == practice_thresh) { + feedback_text += '

    Done with this practice. The test session will begin shortly.' + exp_phase = "test" + return false; + + } + + if ((aveShapeRespondCorrect > accuracy_thresh) && (stop_signal_respond < maxStopCorrectPractice) && (stop_signal_respond > minStopCorrectPractice)){ + feedback_text += '

    Done with this practice. The test session will begin shortly.' + exp_phase = "test" + return false; + + } else { + if (aveShapeRespondCorrect < accuracy_thresh) { + feedback_text += + '

    We are going to try practice again to see if you can achieve higher accuracy. Remember:
    ' + + prompt_text_list + } + if (average_rt > rt_thresh) { + feedback_text += + '

    You have been responding too slowly, please respond to each shape as quickly and as accurately as possible.' + } + if (missed_responses > missed_response_thresh){ + if(aveShapeRespondCorrect < accuracy_thresh){ + feedback_text += + '

    We have detected a number of trials that required a response, where no response was made. Please ensure that you are responding accurately and quickly to the shapes.' + + + } else { + feedback_text += + '

    We have detected a number of trials that required a response, where no response was made. Please ensure that you are responding accurately and quickly to the shapes.
    ' + + prompt_text_list + } + } + + + if (stop_signal_respond === maxStopCorrectPractice){ + feedback_text += + '

    You have not been stopping your response when stars are present. Please try your best to stop your response if you see a star.' + } + + if (stop_signal_respond === minStopCorrectPractice){ + feedback_text += + '

    You have been responding too slowly. Please respond as quickly and accurately to each stimulus that requires a response.' + + } + + feedback_text += '

    Redoing this practice.' + return true + + } + } +} + +var testTrials = [] +testTrials.push(feedback_block) +for (i = 0; i < numTrialsPerBlock; i++) { + + var test_block = { + type: 'stop-signal', + stimulus: getStim, + SS_stimulus: getStopStim, + SS_trial_type: getSSType, + data: { + trial_id: "test_trial" + }, + is_html: true, + choices: [possible_responses[0][1], possible_responses[2][1]], + timing_stim: 1000, //1000 + timing_response: 2000, //2000 + response_ends_trial: false, + SSD: getSSD, + timing_SS: 500, //500 + timing_post_trial: 0, + on_finish: appendData, + on_start: function(){ + stoppingTracker = [] + stoppingTimeTracker = [] + } + } + testTrials.push(ITI_fixation_block) + testTrials.push(test_block) +} +//testTrials.push(feedback_block) + +var testCount = 0 +var testNode = { + timeline: testTrials, + loop_function: function(data) { + current_trial = 0 + testCount += 1 + stims = createTrialTypes(numTrialsPerBlock) + + var total_trials = 0 + + var sum_stop_rt = 0; + var sum_go_rt = 0; + + var sumGo_correct = 0; + var sumStop_correct = 0; + + var num_go_responses = 0; + var num_stop_responses = 0; + + var go_length = 0; + var stop_length = 0 + + for (i = 0; i < data.length; i++) { + if (data[i].trial_id == "test_trial"){ + total_trials += 1 + } + + if (data[i].stop_signal_condition == "go"){ + go_length += 1 + if (data[i].rt != -1) { + num_go_responses += 1 + sum_go_rt += data[i].rt; + if (data[i].key_press == data[i].correct_response) { + sumGo_correct += 1 + } + } + } else if (data[i].stop_signal_condition == "stop") { + stop_length += 1 + if (data[i].rt != -1){ + num_stop_responses += 1 + sum_stop_rt += data[i].rt + } else if (data[i].rt == -1){ + sumStop_correct += 1 + } + } + } + + var average_rt = sum_go_rt / num_go_responses; + var missed_responses = (go_length - num_go_responses) / go_length + + var aveShapeRespondCorrect = sumGo_correct / go_length + + var stop_signal_respond = num_stop_responses / stop_length + + + feedback_text = "
    Please take this time to read your feedback and to take a short break. Press any button to continue." + feedback_text += "

    You have completed: "+testCount+" out of "+numTestBlocks+" blocks of trials." + + if (testCount == numTestBlocks) { + feedback_text += '

    Done with this test.' //If you have been completing tasks continuously for an hour or more, please take a 15-minute break before starting again.' + + return false; + } else { + + if (aveShapeRespondCorrect < accuracy_thresh) { + feedback_text += + '

    Your accuracy is too low. Remember:
    ' + + prompt_text_list + } + if (average_rt > rt_thresh) { + feedback_text += + '

    You have been responding too slowly, please respond to each shape as quickly and as accurately as possible.' + } + if (missed_responses > missed_response_thresh){ + if(aveShapeRespondCorrect < accuracy_thresh){ + feedback_text += + '

    We have detected a number of trials that required a response, where no response was made. Please ensure that you are responding accurately and quickly to the shapes.' + + + } else { + feedback_text += + '

    We have detected a number of trials that required a response, where no response was made. Please ensure that you are responding accurately and quickly to the shapes.
    ' + + prompt_text_list + } + } + + if (stop_signal_respond > maxStopCorrect){ + feedback_text += + '

    You have not been stopping your response when stars are present. Please try your best to stop your response if you see a star.' + } + + if (stop_signal_respond < minStopCorrect){ + feedback_text += + '

    You have been responding too slowly. Please respond as quickly and accurately to each stimulus that requires a response.' + + } + + + + return true; + } + } +} + + +/* ************************************ */ +/* Set up Experiment */ +/* ************************************ */ + +var stop_signal_single_task_network__fmri_experiment = [] + +stop_signal_single_task_network__fmri_experiment.push(SSD_setup_block) //exp_input + +test_keys(stop_signal_single_task_network__fmri_experiment, [possible_responses[0][1], possible_responses[2][1]]) +stop_signal_single_task_network__fmri_experiment.push(practiceStopNode) +stop_signal_single_task_network__fmri_experiment.push(feedback_block); + +setup_fmri_intro(stop_signal_single_task_network__fmri_experiment) +stop_signal_single_task_network__fmri_experiment.push(testNode); +stop_signal_single_task_network__fmri_experiment.push(feedback_block); + +stop_signal_single_task_network__fmri_experiment.push(end_block); + + + + + diff --git a/stop_signal_single_task_network__fmri/images/circle.png b/stop_signal_single_task_network__fmri/images/circle.png new file mode 100644 index 000000000..4ed81f99a Binary files /dev/null and b/stop_signal_single_task_network__fmri/images/circle.png differ diff --git a/stop_signal_single_task_network__fmri/images/pentagon.png b/stop_signal_single_task_network__fmri/images/pentagon.png new file mode 100644 index 000000000..51f7dd50a Binary files /dev/null and b/stop_signal_single_task_network__fmri/images/pentagon.png differ diff --git a/stop_signal_single_task_network__fmri/images/rhombus.png b/stop_signal_single_task_network__fmri/images/rhombus.png new file mode 100644 index 000000000..46d9a4746 Binary files /dev/null and b/stop_signal_single_task_network__fmri/images/rhombus.png differ diff --git a/stop_signal_single_task_network__fmri/images/square.png b/stop_signal_single_task_network__fmri/images/square.png new file mode 100644 index 000000000..3a4ef24a0 Binary files /dev/null and b/stop_signal_single_task_network__fmri/images/square.png differ diff --git a/stop_signal_single_task_network__fmri/images/stopSignal.png b/stop_signal_single_task_network__fmri/images/stopSignal.png new file mode 100644 index 000000000..8b8f9fcfe Binary files /dev/null and b/stop_signal_single_task_network__fmri/images/stopSignal.png differ diff --git a/stop_signal_single_task_network__fmri/images/trapezoid.png b/stop_signal_single_task_network__fmri/images/trapezoid.png new file mode 100644 index 000000000..ca28507aa Binary files /dev/null and b/stop_signal_single_task_network__fmri/images/trapezoid.png differ diff --git a/stop_signal_single_task_network__fmri/images/triangle.png b/stop_signal_single_task_network__fmri/images/triangle.png new file mode 100644 index 000000000..93f4bbbc3 Binary files /dev/null and b/stop_signal_single_task_network__fmri/images/triangle.png differ diff --git a/stop_signal_single_task_network__fmri/style.css b/stop_signal_single_task_network__fmri/style.css new file mode 100644 index 000000000..f0766911f --- /dev/null +++ b/stop_signal_single_task_network__fmri/style.css @@ -0,0 +1,118 @@ +/*******************************************************/ +/*********** Network Default CSS Styles **********/ +/*******************************************************/ + +.display_stage { + position: fixed; + background: gray; + left: 5vw; + top: 2vh; + height: 94vh; + width: 90vw; + border-radius: 15px; + border: 1vh solid #D0D0D0; + z-index: 0; +} + +.display_stage > div, .display_stage > p { + color: white; +} + +.flanker-text { + text-align: center; + font-size: 50px; + position: relative; + top: 50%; + transform: translateY(-50%); + -webkit-transform: translateY(-50%); +} + +.fb_box { + width:35vw; + height: 20vh; + position:absolute; + top:50%; + left:50%; + margin-right:-50%; + transform: translate(-50%,-175%); +} + +.picture_box { + width: 60%; + height: 60%; + position:absolute; + top:50%; + left:50%; + transform: translate(-50%,-50%); + margin-right:0%; + background-color: none; + text-align: center; +} + + +.fixation { + text-align: center; + font-size: 50px; + position: relative; + top: 50%; + transform: translateY(-50%); + -webkit-transform: translateY(-50%); +} + +.cue-text { + width:20vw; + height: 20vh; + position:absolute; + top:50%; + left:50%; + margin-right:-50%; + transform: translate(-50%,-50%); +} + +.bigbox { +width:100%; +margin: auto; +min-height: 100%; +position:absolute; +top:0%; +left:0%; +margin-right:0%; +background-color: none; +text-align: center; +} + +.instructBox { + width: 80vw; + height: 10vw; + position:absolute; + top:10%; + left:50%; + margin-right: 0%; + transform: translate(-50%,-50%); + background-color: none; + font-size: 24px; +} + +.prompt_box { + width: 75%; + height: 20%; + position:absolute; + top:10%; + left:12.5%; + transform: translate(-50%,-45%); + margin-right:0%; + background-color: none; + text-align: center; +} + +img.center { + height: auto; + width: auto\9; /* ie8 */ + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; + max-height: 65%; +} \ No newline at end of file