Redefining stimuli after each timeline block #2750
-
Hey! I am trying to put together a test and would like to redefine the stimuli after each fixation-test-feedback timeline ends. Simply I defined a function stimuli_reroll wich takes an array test_stimuli and fills it up with according random stimulus. I want this function to execute before every timeline repetition to get blocks of randomized stimuli via the function. I have tried this with the jsPsychCallFunction plugin. I have tried the on_timeline_start property in the timeline node too with no success. I think the problem lies somewhere as i try to call the stimulus with the jspsych.timelinevariable function. My error is so "cannot read "stimulus" (undefined).If i fill up test_stimuli array only once and not trying to execute the function blockwise, the experiment runs smoothly. Any advice or help is greatly appriciated! See the code below. //------This script generates a random order of stimuli with the rules of the predefined methods-----
stimulus_set = []
var relay = 0
const fp_con_list = [
["FFFFF", "no_conflict", "1"],
["PPPPP", "no_conflict", "9"]
]
const fp_inc_list = [
["FPPPF", "low_conflict", "9"],
["PFFFP", "low_conflict", "1"],
["FFPFF", "high_conflict", "9"],
["PPFPP", "high_conflict", "1"]
]
const hn_con_list = [
["HHHHH", "no_conflict", "2"],
["NNNNN", "no_conflict", "8"]
]
const hn_inc_list = [
["HNNNH", "low_conflict", "8"],
["NHHHN", "low_conflict", "2"],
["HHNHH", "high_conflict", "8"],
["NNHNN", "high_conflict", "2"]
]
const fp_group = [fp_con_list, fp_inc_list]
const hn_group = [hn_con_list, hn_inc_list]
function stimulus_finder(group) {
congruency = Math.floor(Math.random() * group.length) //randomly choosing from congruent or incongruent stimuli (50-50%)
stimulus = Math.floor(Math.random() * group.length) // randomly choosing a stimulus from the list (25% low conflict, 25% high conflict, 50% no conflict)
stimulus_set.push(group[congruency][stimulus])
}
function group_relay() { // kindergarden way to switch between fp and hn groups
if (relay === 0) {
stimulus_finder(fp_group)
relay = 1
} else {
stimulus_finder(hn_group)
relay = 0
}
}
function set_factory(total) {
for (var i = 0; i <= total; i += 1) {
group_relay()
}
}
var jsPsych = initJsPsych({
on_finish: function () {
jsPsych.data.displayData();
},
override_safe_mode : true
})
var test_stimuli = []
function stimuli_reroll(){
stimulus_set = []
test_stimuli = []
set_factory(1)
for (i = 0; i < stimulus_set.length; i+=1) { //unwrapping nested array to access wanted stimuli (strc of stimulus_set: [(Array(3)), (Array(3)), etc...], strc of new array: {stimulus: 'NNNNN', congruency: 'no_conflict', correct_response: '8'}
test_stimuli.push({stimulus : stimulus_set[i][0], congruency : stimulus_set[i][1], correct_response : stimulus_set[i][2]})
}
}
var timeline = []
var test = {
type: jsPsychHtmlKeyboardResponse,
stimulus:jsPsych.timelineVariable("stimulus"),
choices: ["1","2","8","9"],
trial_duration: 1500,
response_ends_trial: false,
data: {
task: "response",
correct_response: jsPsych.timelineVariable("correct_response"),
congruency: jsPsych.timelineVariable("congruency")
},
on_finish: function (data) {
data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);
},
}
var fixation = {
type: jsPsychHtmlKeyboardResponse,
stimulus: '<div style="font-size:60px; color: gray;">+</div>',
choices: "NO_KEYS",
trial_duration: 500,
response_ends_trial: false,
data: {
task: 'fixation'
},
save_trial_parameters: {
stimulus: false
}
}
var feedback = {
type: jsPsychHtmlKeyboardResponse,
stimulus: function(){
var last_trial_correct = jsPsych.data.get().last(1).values()[0].correct;
if(last_trial_correct){
return "<p></p>";
} else {
return "<p>Incorrect / No response detected</p>";
}
},
trial_duration: 800,
response_ends_trial: false,
}
var test_procedure = {
timeline: [fixation, test, feedback],
timeline_variables: test_stimuli,
repetitions: 6,
on_timeline_start: function() {
return stimuli_reroll
}
}
timeline.push(test_procedure)
jsPsych.run(timeline) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Hi @vargamartonaron, sorry for the slow response! I could be wrong, and hopefully @jodeleeuw will correct me if so, but I'm pretty sure the If that doesn't work, then instead of using var trial_index = 0;
var test_stimuli = []
// initialize the test_stimuli array ...
var test = {
type: jsPsychHtmlKeyboardResponse,
stimulus: function() {
return test_stimuli[trial_index]]
},
// more parameters...
}
// more trial objects
var loop = {
timeline: [fixation, test, feedback],
loop_function: function(data) {
trial_index++;
// check if we've reached the last trial in test_stimuli
if (trial_index == test_stimuli.length) {
// logic here to modify the test_stimuli array or stop the loop
} else {
return true;
}
}
}
timeline.push(loop) Does that help at all? Let us know if you want further guidance with implementing either of these approaches. |
Beta Was this translation helpful? Give feedback.
Hi @vargamartonaron, sorry for the slow response!
I could be wrong, and hopefully @jodeleeuw will correct me if so, but I'm pretty sure the
timeline_variables
array can't be modified dynamically after the experiment has started. Have you looked at whether you could use acustom sampling function
to achieve what you're after here? The custom sampling function receives an argumentt
which is "an array of integers from 0 to n-1, where n is the number of trials in the timeline_variables array", and the function should return an array of indices that specifies the order of the trials. So maybe you could stick all of your stimulus information into a single array, pass that totimeline_variables
,…