-
Hi everyone! I've hit a wall trying to accomplish something that I think should be rather straightforward: I'd like to present participants with their own previously recalled words. This previous recall will be free recall, such that different participants will recall different words, in different overall quantities, in different orders, and they are expected to recall some non-presented words. Following this recall task, I'd like to show them each word and collect a confidence rating Currently I'm using the following plugin to facilitate free recall: https://www.npmjs.com/package/@pcllab/plugin-free-recall?activeTab=readme - this works well and produces data as expected. I've successfully used To present each word following recall, I'm thinking that a using a timeline variable makes sense. That is, I've tried using // create variable for subsequent confidence task, which should reference recall data
var recall_phase_1_words = {
type: jsPsychHtmlKeyboardResponse,
stimulus: function() {
return `<p>How confident (1-9) that you saw:<p></b><p style="font-size: 48px; font-family: monospace;"> ${jsPsych.timelineVariable('response')}</p>`
}
}; Then I set up a timeline variable to cycle through the responses, using the // cycle through recalled words, showing each and asking for a response
var recall_phase_1_conf_task = {
timeline: [fixation, recall_phase_1_words],
//timeline_variables: jsPsych.data.get().filter({recall_phase: "recall-1"}), // can't access property response
//timeline_variables: jsPsych.data.get().filter({recall_phase: "recall-1"}).json(), // stimuli = undefined; timeline variable response not found
randomize_order: true
}; In the above example, I've commented-out a few unsuccessful attempts and noted what warning/error comes up. I'm thinking this is just an issue of not understanding how to navigate the DataCollection object so I can pull out responses dynamically, but I'm not sure. I'd greatly appreciate any and all help! Please let me know if I can provide any more information or context. Below is a fully reproducible example - there is no study/encoding phase, but any words can be entered to work through the example: <!DOCTYPE html>
<html>
<head>
<title>Prior Recall Responses in Timeline</title>
<script src = "https://unpkg.com/[email protected]"></script>
<script src = "https://unpkg.com/@jspsych/[email protected]"></script>
<script src = "https://unpkg.com/react@18/umd/react.development.js"></script>
<script src = "https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src = "https://unpkg.com/@pcllab/plugin-free-recall"></script>
<link href = "https://unpkg.com/[email protected]/css/jspsych.css" rel="stylesheet" type="text/css" />
</head>
<body></body>
<script>
// initialize jsPsych
var jsPsych = initJsPsych(
{
on_finish: function() {
jsPsych.data.displayData();
}
}
);
// set timeline as empty array, to be filled later on
var timeline = [];
// Recall 1 - Task
// https://www.npmjs.com/package/@pcllab/plugin-free-recall?activeTab=readme
var recall_phase_1 = {
type: pcllabFreeRecall,
stimulus: "<p>Enter words one at a time, pressing the ENTER key to submit each word.</p><p>The words you enter will appear below the text-box.</p>",
button_label: "Done Recalling!",
//show_button: false,
data: {recall_phase: "recall-1"}
};
// feedback on performance
var recall_phase_1_you_recalled_n = {
type: jsPsychHtmlKeyboardResponse,
stimulus: function () {
//var last_item_recalled = jsPsych.data.get().filter({recall_phase: "recall-1"}).values()[0].response;
var recall_1_count = jsPsych.data.get().filter({recall_phase: "recall-1"}).count();
var recall_1_count_corrected = Math.round(recall_1_count - 1); // one additional blank trial at end for submitting page - remove this
return `<p>You recalled ${recall_1_count_corrected} words.</p></b><p>Next you'll rate your confidence in each word...(ENTER to get started)</p>`
},
choices: ['Enter']
};
// fixation - not strictly needed, but fine to include
var fixation = {
type: jsPsychHtmlKeyboardResponse,
stimulus: `<p style="font-size: 48px; font-family: monospace;">+</p>`,
choices: 'NO_KEYS',
trial_duration: 1000
};
// following pulls out specific recalled word, specifically the last word recalled
// note that [0] response is undefined because the final recall trial is the submission, so [1] points to last valid submission
//var last_item_recalled = jsPsych.data.get().filter({recall_phase: "recall-1"}).values()[1].response;
// create variable for subsequent confidence task, which should reference recall data
var recall_phase_1_words = {
type: jsPsychHtmlKeyboardResponse,
stimulus: function() {
return `<p>How confident (1-9) that you saw:<p></b><p style="font-size: 48px; font-family: monospace;"> ${jsPsych.timelineVariable('response')}</p>`
}
};
// cycle through recalled words, randomly, showing each and asking for a response
var recall_phase_1_conf_task = {
timeline: [fixation, recall_phase_1_words],
//timeline_variables: jsPsych.data.get().filter({recall_phase: "recall-1"}), // can't access property response
timeline_variables: jsPsych.data.get().filter({recall_phase: "recall-1"}).json(), // stimuli = undefined; timeline variable response not found
randomize_order: true
};
// build experiment
timeline.push(recall_phase_1);
timeline.push(recall_phase_1_you_recalled_n);
timeline.push(recall_phase_1_conf_task);
// run
jsPsych.run(timeline);
</script>
</html> |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
Following up on this, based on #2256, it seems like using a function in So, adding to the question above, if using a function isn't possible in |
Beta Was this translation helpful? Give feedback.
-
Hi @ggreeley, One issue here is that Normally the solution to something like this is to wrap the parameter value in a function, which delays execution until the relevant moment in the experiment. But we don't support that for timeline variables yet. Definitely still on the list of things to do. My typical pattern for this situation is to use a looping timeline. let word_counter = 0;
const looping_timeline = {
timeline: [fixation, recall_phase_1_words],
loop_function: () => {
// return true to repeat, false to continue to next part of experiment
word_counter++;
return word_counter <= jsPsych.data.get().filter({recall_phase: "recall-1"}).values()[0].response.length;
}
} To change the word that shows up in var recall_phase_1_words = {
type: jsPsychHtmlKeyboardResponse,
stimulus: function() {
return `<p>How confident (1-9) that you saw:<p></b><p style="font-size: 48px; font-family: monospace;"> ${ jsPsych.data.get().filter({recall_phase: "recall-1"}).values()[0].response[word_counter}</p>`
}
}; I didn't confirm that this works yet, but I think it's the right general idea. It'll depend a bit on how the plugin saves its data. |
Beta Was this translation helpful? Give feedback.
Got it! The following works:
Thank you again for your help! Figuring the issue was with the
loop_function
syntax, I did some digging and came across #1911 - combined with the docs on the main page, I was able to work it out.Thanks again @jodeleeuw!