An example of how to code this up
There are two more challenging questions this week, so I will provide the code first (containing both) then talk you through the questions in turn. Note the scare quotes around “model answer” - this is one way to do these things, and it’s what I had in mind when I wrote the questions, but it’s certainly not the only or the best way to do it!
You can download my code through the following two links:
If you drop these into your perceptual_learning
folder they will be able to access the various stimuli folders that are already there.
save_questionnaire_data
, which runs at the end of the questionnaire trial and saves that data to a file on the server? You can just dump it into a file as an undigested string (i.e. with various curly brackets etc in there), or if you are feeling ambitious you can try to save some more nicely formatted data using the same tricks we use in save_perceptual_learning_data
, in which case the first thing you are probably going to want to do is use console.log
to get a look at the data generated by the questionnaire trial and take it from there.I am basically going to do this in exactly the same way I save the normal trial data after each trial - call a function in the on_finish
of the questionnaire trial which will save the data. That part is easy:
var social_network_questionnaire = {
type: jsPsychSurveyHtmlForm,
preamble:
"<p style='text-align:left'> <b>Social network questionnaire</b></p>\
<p style='text-align:left'> In this questionnaire we would like to \
gather information about your linguistic interactions. We realize \
that some of the estimates are difficult to make. Please do your \
best and be as accurate as possible.</p> \
<p style='text-align:left'> Important: When providing estimates for \
your exposure in a week, keep in mind that your habits may vary \
considerably depending on the day of the week (e.g., weekday vs. weekend). \
Please be as accurate as possible and do not simply multiply your \
estimate for one day by 7.</p>",
html: "<p style='text-align:left'>How old are you? <br> \
<input required name='age' type='number'></p> \
<p style='text-align:left'>With how many people do you converse orally \
in a typical week? (Please only include people with whom you regularly \
talk for longer than 5 minutes)<br> \
<input required name='n_speak_to' type='number'></p> \
<p style='text-align:left'>How many hours do you usually spend on \
conversing orally with people in a typical week?<br>\
<input required name='hours_speak_to' type='number'></p>",
//when the trial finishes, take the data generated by the trial and save it
on_finish: function (data) {
save_questionnaire_data(data);
}
};
So all I have to do now is write the save_questionnaire_data
function! That takes the data generated by the survey-html-form
trial and save it to a file. As per my suggestion, the first thing I actually did was just use console.log
to get a look at that data - so I initially just made the on_finish
show the trial data in the console, like this
var social_network_questionnaire = {
type: jsPsychSurveyHtmlForm,
preamble: "...as before",
html: "... as before",
on_finish: function (data) {
console.log(data); //let me see the data in the console
},
Once I had done that I could see that the data generated by this survey plugin looks like this in the javascript console (initially it appears as Object, but I can click to expand it):
{
response: {age: '99', n_speak_to: '1', hours_speak_to: '10'},
time_elapsed: 9621,
rt: 6050,
trial_index: 3,
trial_type: 'survey-html-form',
...
}
So my responses to the questionnaire are buried in data.response
(I entered my age as 99, the number of people I speak to as 1, and the time I spent talking to them as 10 hours), which is the standard place where jsPsych puts participant response info. So to save that, all I have to do is retrieve data.responses
and save it to a file, which I could easily do using the save_data
function I am using elsewhere. But I decided to be a bit more ambitious - I’d like to save this as a nice CSV file, with a header. Again I can just use the same technique that I used when saving the data line by line, writing a header line and saving the specific fields I want, which is what my save_questionnaire_data
function does:
function save_questionnaire_data(data) {
//console logging these so you can see what the
//data generated by the survey trial looks like
console.log(data);
console.log(data.response);
var questionnaire_data = data.response;
var data_to_save = [
questionnaire_data.age,
questionnaire_data.n_speak_to,
questionnaire_data.hours_speak_to
];
//headers - gives the names of the 3 columns
var headers = "age,n_speak_to,hours_speak_to\n";
// join these with commas and add a newline
var line = headers + data_to_save.join(",") + "\n";
save_data("perceptuallearning_questionnaire_data.csv", line);
}
selection_trials
, e.g. using a for-loop to work through the trials in selection_trials
, extract the image names from the choices
of each trial, and add them to a preload list.There’s a pretty strong hint about how to answer this one - loop through selection_trials
, pick out the choices
, and build your image preload list from those. If we use console.log
to look at selection_trials
we should see it looks something like this:
[
{button_html: ...,
choices: ['fresh_dill', 'dry_dill'],
stimulus: "picture_selection_sounds/fresh_dill_man.mp3",
...},
{button_html: ...,
choices: ['animal_ear', 'animal_nose'],
stimulus: "picture_selection_sounds/animal_ear.mp3"
...},
{button_html: ...,
choices: ['angel_wing', 'airplane_wing'],
stimulus: "picture_selection_sounds/angel_wing.mp3",
...}
...
]
So basically we can loop through this, grab the choices
and then add them to a list of image stimuli to preload. But choices
is itself a list, so I am going to include an embedded for-loop which iterates through choices
, adding each of those in turn. The one additional thing I need to do while I am doing that is add path information for each image. You’ll notice that for each trial in selection_trials
we just have the basic info on the image - e.g. the images are things like “fresh_dill”, “animal_ear” etc, then the button_html
parameter adds all the path info etc for us. The image files are actually in a folder called picture_selection_images/
, which the preloader needs to know, plus we need to add the extension indicating the filetype (all the image file names end in “.jpg”). We can add that information to each image name as we build our preload list, in the inner for-loop.
//start with an empty list of images to preload
var image_preload_list = [];
//first for-loop - build a list of plain image names (minus path)
for (var this_trial of selection_trials) {
this_choices = this_trial.choices;
//embedded for-loop - for each item in this_choices, add path info and push to image_preload_list
for (var this_filename of this_choices) {
var this_filename_with_path =
"picture_selection_images/" + this_filename + ".jpg";
image_preload_list.push(this_filename_with_path);
}
}
Now we have image_preload_list
which we can just give to our preload trial as a manual preload list of images:
var preload = {
type: jsPsychPreload,
auto_preload: true,
images: image_preload_list,
};
Note that we are still auto-preloading the audio in each audio-button-response
trial, but now you should notice that the images appear instantly on each trial too, with no lag. If you want you can also experiment and see what happens if you remove the path or .jpg extension information from each file when you build image_preload_list
.
All aspects of this work are licensed under a Creative Commons Attribution 4.0 International License.