Some notes on answers to the practical questions
perceptuallearning_data.csv
file to make sure it makes sense to you. You can also compare the data saved in the server with the data dumped in the browser. Run the code again and see what happens to that file, and think about how you might want to save your data for a real experiment.Because we are saving the data trial-by-trial, and only saving the critical trials (and not e.g. the instruction screens), the data saved on the server is a bit more compact and neat than the data dumped in the browser window at the end. But even though we are saving the data trial-by-trial, we are still just appending new data to the end of the CSV file (including the header row). As I said last week, that’s pretty messy, and not really what you want if you are collecting real data, so next week we’ll show you how to create a separate CSV file for each participant (using a unique participant ID in the file name).
perceptual_learning_stims.csv
file to see the full list of stimuli).This just involves adding some more lines using the make_picture_selection_trial
and make_categorization_trial
functions to make trials. So our current code for creating a list of picture selection trials is:
var selection_trials_unshuffled = [
make_picture_selection_trial("fresh_dill_man", "fresh_dill", "dry_dill"),
make_picture_selection_trial("orange_telephone","orange_telephone","black_telephone"),
make_picture_selection_trial("angel_wing", "angel_wing", "airplane_wing"),
make_picture_selection_trial("animal_ear", "animal_ear", "animal_nose"),
];
var selection_trials = jsPsych.randomization.shuffle(
selection_trials_unshuffled
);
(Then the list is shuffled and eventually added to the timeline). So we can just add more trials, like this:
var selection_trials_unshuffled = [
//same 4 trials as before
var selection_trials_unshuffled = [
make_picture_selection_trial("fresh_dill_man", "fresh_dill", "dry_dill"),
make_picture_selection_trial("orange_telephone","orange_telephone","black_telephone"),
make_picture_selection_trial("angel_wing", "angel_wing", "airplane_wing"),
make_picture_selection_trial("animal_ear", "animal_ear", "animal_nose"),
//2 new trials
make_picture_selection_trial("falling_dominoes_man","falling_dominoes","standing_dominoes"),
make_picture_selection_trial("eiffel_tower","eiffel_tower","pisa_tower"),
];
That’s the first /d/ and /t/ trial from the perceptual_learning_stims.csv
, and I set it so that the dominoes trial will get a manipulated /d/ (as indicated by \_man
at the end of the sound file name) but the tower trial gets a normal /t/ (no \_man
at the end).
Similarly, here’s our code for the categorization trials:
var categorization_trials_unshuffled = [
make_categorization_trial("samespeaker_VOT5"),
make_categorization_trial("samespeaker_VOT10"),
make_categorization_trial("samespeaker_VOT15"),
make_categorization_trial("samespeaker_VOT20"),
make_categorization_trial("samespeaker_VOT25"),
make_categorization_trial("samespeaker_VOT30"),
make_categorization_trial("samespeaker_VOT50"),
make_categorization_trial("samespeaker_VOT80"),
];
var categorization_trials = jsPsych.randomization.shuffle(
categorization_trials_unshuffled
);
I could just copy and paste some extra lines featuring make_categorization_trial
in there (yawn), or I could use jsPsych.randomization.repeat
to repeat that list a few times, to test people on each dean/teen decision a few times, e.g.
var categorization_trials = jsPsych.randomization.repeat(
categorization_trials_unshuffled,
2
);
Note that jsPsych.randomization.repeat
repeats and shuffles, so that will give me 2 copies of all the categorization trials.
To do this manually is pretty simple. Remember that in the manipulated /d/ condition, all instances of /d/ in the picture selection trials are manipulated - that’s actually what I have in the trial list above, you’ll notice that whenever the trial involves a /d/ (dill, dominoes) the file name ends in “_man”, so they hear the manipulated audio.
To flip this to manipulated /t/ I just need to remove the “_man” for the /d/ trials and add it for the /t/ trials so that they hear normal /d/ and manipulated /t/:
var selection_trials_unshuffled = [
//same 4 trials as before
var selection_trials_unshuffled = [
make_picture_selection_trial("fresh_dill", "fresh_dill", "dry_dill"),
make_picture_selection_trial("orange_telephone_man","orange_telephone","black_telephone"),
make_picture_selection_trial("angel_wing", "angel_wing", "airplane_wing"),
make_picture_selection_trial("animal_ear", "animal_ear", "animal_nose"),
//2 new trials
make_picture_selection_trial("falling_dominoes","falling_dominoes","standing_dominoes"),
make_picture_selection_trial("eiffel_tower_man","eiffel_tower","pisa_tower"),
];
How about switching from the same-speaker condition to the new speaker condition? Remember, the same- vs new-speaker manipulation affects the sound files you hear in the categorization test - thanks to the sensible and clear names of the sound files, I can just change the names of the sound files there to play the new (male) voice:
var categorization_trials_unshuffled = [
make_categorization_trial("newspeaker_VOT5"),
make_categorization_trial("newspeaker_VOT10"),
make_categorization_trial("newspeaker_VOT15"),
make_categorization_trial("newspeaker_VOT20"),
make_categorization_trial("newspeaker_VOT25"),
make_categorization_trial("newspeaker_VOT30"),
make_categorization_trial("newspeaker_VOT50"),
make_categorization_trial("newspeaker_VOT80"),
];
I actually did this above, using jsPsych.randomization.repeat
.
This should be pretty easy, since we are doing this for the picture selection trials - so we can just use the same trick, randomising the trial choices in on_start
:
function make_categorization_trial(sound) {
//add the path and file extension
var sound_file = "phoneme_categorization_sounds/" + sound + ".mp3";
var trial = {
type: jsPsychAudioButtonResponse,
stimulus: sound_file,
choices: ["dean", "teen"], //placeholder choices
post_trial_gap: 500,
on_start: function (trial) {
var shuffled_choices = jsPsych.randomization.shuffle(trial.choices); //shuffle
trial.choices = shuffled_choices; //set trial.choices to shuffled choices
trial.data = {
block: "phoneme_categorization",
button_choices: trial.choices,
};
},
on_finish: function (data) {
var button_number = data.response;
data.button_selected = data.button_choices[button_number];
save_perceptual_learning_data_line(data);
},
};
return trial;
}
audio-button-response
plugin is interruptible - if you click part-way through the audio it will register your response and move to the next trial. Can you fix it to produce a non-interruptible audio, i.e. you can’t click until the audio is done? Hint: the trick here is going to look at the documentation) for the audio-button-response
plugin.jsPsych makes it pretty easy - we can just set the response_ends_trial
parameter for audio-button-response
trials to false. E.g. adding that to my make_categorization_trial
function:
function make_categorization_trial(sound) {
//add the path and file extension
var sound_file = "phoneme_categorization_sounds/" + sound + ".mp3";
var trial = {
type: jsPsychAudioButtonResponse,
stimulus: sound_file,
choices: ["dean", "teen"],
response_ends_trial: false,
post_trial_gap: 500,
on_start: function (trial) {
var shuffled_choices = jsPsych.randomization.shuffle(trial.choices); //shuffle
trial.choices = shuffled_choices; //set trial.choices to shuffled choices
trial.data = {
block: "phoneme_categorization",
button_choices: trial.choices,
};
},
on_finish: function (data) {
var button_number = data.response;
data.button_selected = data.button_choices[button_number];
save_perceptual_learning_data_line(data);
},
};
return trial;
}
All we are looking for at this point is a manual preload list - I can look through my trials (e.g. using the expanded list above), and note that I am using the following images: “fresh_dill”, “dry_dill”, “orange_telephone”, “black_telephone”, “angel_wing”, “airplane_wing”, “animal_ear”, “animal_nose”, “falling_dominoes”, “standing_dominoes”, “eiffel_tower”, “pisa_tower”. I need to put those in a list, but I also need to add the information on the path (they are all in picture_selection_images/
) and the extension (they are all .jpg
). So my preload image will look like this:
var preload_image_list =
[
"picture_selection_images/fresh_dill.jpg",
"picture_selection_images/dry_dill.jpg",
"picture_selection_images/orange_telephone.jpg",
"picture_selection_images/black_telephone.jpg",
//etc
];
Then I can just use this in the preloading trial:
var preload = {
type: jsPsychPreload,
auto_preload: true,
images: preload_image_list
};
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.You can already access our answers for the harder questions here - this covers this question and the next.
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.You can already access our answers for the harder questions here.
All aspects of this work are licensed under a Creative Commons Attribution 4.0 International License.