Repository navigation
Expand file tree
/
Copy pathImageDifferenceDetection.js
More file actions
280 lines (258 loc) · 12.3 KB
/
Copy pathImageDifferenceDetection.js
File metadata and controls
280 lines (258 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
function ImageDifferenceDetection(jsPsychHandle, urlParameters) {
jsPsychHandle.data.addProperties(urlParameters);
const IMAGES_PER_SUBJECT = 40;
let manifest = [];
// START MODIFY NEEDED
let sessionBuilder = new SessionBuilder();
sessionBuilder.createSession(RunExperiment)
function ChooseImageSet(session) {
DisplayLoader('Please wait while we set up the experiment...');
session.getImageUsage(IMAGE_MANIFEST, (totalManifest) => {
manifest = Shuffle(totalManifest)
.sort((left, right) => {
if (left.usage > right.usage)
return 1;
if (right.usage > left.usage)
return -1;
return 0;
})
.slice(0, IMAGES_PER_SUBJECT);
RunExperiment(session);
})
}
// END
function RunExperiment(session) {
let welcomeTrial = {
type: 'html-keyboard-response',
stimulus: `
<p>Welcome to the experiment.</p>
<p>Press any key to begin.</p>
`
}
let consentFormTrial = {
type: 'external-html',
url: 'resources/Consent.html',
cont_btn: 'consent-button'
}
let getSex = {
type: 'survey-multi-choice',
questions: [
{
name: 'sex',
prompt: 'What is your sex assigned at birth?',
options: ['Male', 'Female', 'Other'],
required: true
}
]
}
let getAge = {
type: 'survey-text',
questions: [{
name: 'age',
prompt: 'What is your age (e.g. 20, 45, 63)?',
required: true,
columns: 3
}]
}
let experimentInstructionsTrial = {
type: 'instructions',
show_clickable_nav: true,
pages: [
'<h1> Welcome to the Experiment </h1>' +
'<p>Welcome to the experiment! In this task, you will be asked to provide ratings' +
' about pairs of images. Each pair of images contains a specific change, and we will' +
' ask you questions about it.</p>'
,
'<p>For each pair of pictures, we will ask you how much the <b>meaning</b> changes from' +
' one picture to another.</p>'
,
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/soldier with kids 2.jpg"></img>' +
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/soldier with kids 2_2.jpg"></img>' +
'<p>Above is an example where the meaning has a <b>Very Significant Change</b>.</p>'
,
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/casino.jpg"></img>' +
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/casino_2.jpg"></img>' +
'<p>Above is an example where the meaning has an <b>Insignificant Change</b>.</p>'
,
'<p>For each pair of pictures, we will also ask you how <b>likely</b> it is for the <b>image on the right</b> to appear in the real world.</p>'
,
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/kid eating cereal.jpg"></img>' +
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/kid eating cereal_2.jpg"></img>' +
'<p>Above is an example where the image on the right is <b>Very Unlikely</b> to appear in the real world.</p>'
,
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/graduation.jpg"></img>' +
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/graduation_2.jpg"></img>' +
'<p>Above is an example where the image on the right is <b>Very Likely</b> to appear in the real world.</p>'
,
'<p>For each pair of pictures, we will also ask you how <b>complicated</b> the images are.</p>'
,
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/fruit market stand.jpg"></img>' +
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/fruit market stand_2.jpg"></img>' +
'<p>Above is an example where the images are <b>Very Complicated</b></p>'
,
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/dumbo.jpg"></img>' +
'<img class="differenceDetectionElement differenceDetectionImage" src="resources/dumbo_2.jpg"></img>' +
'<p>Above is an example where the images are <b>Very Simple</b></p>'
,
'<p>Finally, we will also ask you about how hard it is to identify the change between the images in a given pair.</p>' +
'<p>We will not give you a reference for this question. Simply report how hard it was for <b>you</b> to identify the difference.</p>'
,
'<p>If you have difficulty spotting the change, you can wait 20 seconds and a button will appear that will allow you to reveal the change.</p>' +
'<p>The change will be highlighted with a light blue box</p>'
,
'<p>When you are ready, continue to the experiment. Please do your best to provide quick and accurate ratings. Thank you in advance for your hard work!</p>'
]
}
function createDifferenceDetectionStimulus(suffix = '') {
return () => `
<div class="differenceDetectionElement differenceDetectionContainer">
<img class="differenceDetectionElement differenceDetectionImage" src="resources/${jsPsychHandle.timelineVariable('leftImage', true)}"/>
<img style="display:inline-block;" id="differenceDetectionRightMain" class="differenceDetectionElement differenceDetectionImage" src="resources/${jsPsychHandle.timelineVariable('rightImage', true)}"/>
<img style="display:none;" id="differenceDetectionRightAlt" class="differenceDetectionElement differenceDetectionImage" src="resources/${jsPsychHandle.timelineVariable('rightAltImage', true)}"/>
</div>
<button style="display:none;" id="viewAlt">Reveal Change</button>
<div>${suffix}</div>`
};
function createStandardLikert(name, question, leftlabel, rightlabel, scale) {
return {
type: 'survey-likert',
scale_width: 500,
preamble: createDifferenceDetectionStimulus(),
questions: [
{
name: name,
prompt: question,
labels: function () {
let labels = [];
labels.push(leftlabel);
for (let i = 0; i < scale - 2; i++)
labels.push('');
labels.push(rightlabel);
return labels;
}(),
required: true
}
]
}
};
function createContinuousSlider(question, leftlabel, rightlabel) {
return {
stimulus: createDifferenceDetectionStimulus(question),
type: 'html-slider-response',
slider_width: 500,
start: () => Math.random() * 100,
labels: [leftlabel, rightlabel],
require_movement: true
}
}
let differenceDetection = {
button_label: 'Submit',
on_start: function () {
this.on_finish = DelayedReveal('viewAlt', 20000);
},
timeline: [
createContinuousSlider('How much does the meaning change from one picture to the other?', 'Insignificant Change', 'Very Significant Change'),
createStandardLikert('Likely', 'How likely is it for the <b>image on the right</b> to appear in the real world?', 'Very Unlikely', 'Very Likely', 7),
createStandardLikert('Complicated', 'How visually complicated are the images?', 'Very Simple', 'Very Complicated', 7),
createStandardLikert('Hard', 'How hard is it to identify the change in the image?', 'Very Easy', 'Very Hard', 7)
],
data: function () {
return {
image: jsPsychHandle.timelineVariable('leftImage', true)
}
},
timeline_variables: function () {
let variables = [];
let images = jsPsych.randomization.sampleWithoutReplacement(manifest);
for (let i = 0; i < images.length; i++) {
variables.push({
leftImage: `${images[i].name}.${images[i].extension}`,
rightImage: `${images[i].name}_2.${images[i].extension}`,
rightAltImage: `${images[i].name}_3.${images[i].extension}`
})
}
return variables;
}()
}
let finalTrial = {
type: 'instructions',
pages: [`Thanks for participating! Push the right arrow key to finish the experiment.`],
}
// Configure and Start Experiment
jsPsychHandle.init({
timeline: [
welcomeTrial,
consentFormTrial,
getSex,
getAge,
experimentInstructionsTrial,
differenceDetection,
finalTrial
],
// START MODIFY NEEDED
on_trial_finish: function (data) {
session.insert(data);
},
on_finish: function () {
DisplayLoader('Please wait while we clean up...');
session.updateImageUsage(manifest);
setTimeout(() => { }, 5000);
window.top.location.href = 'https://www.prolific.co/';
}
// END
})
}
function Shuffle(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array.slice(0);
}
function DisplayLoader(text) {
const waitText = document.createElement('h1');
waitText.id = 'loader-text';
waitText.innerHTML = text;
document.body.appendChild(waitText);
const waitLoader = document.createElement('div');
waitLoader.id = 'loader';
document.body.appendChild(waitLoader);
}
function DelayedReveal(id, delay) {
let trialIsFinished = false;
const [SwapRightImage, ResetSwapRightImage] = function () {
let showAltImage = true;
return [
function () {
let hiddenImage = document.getElementById('differenceDetectionRightAlt');
let shownImage = document.getElementById('differenceDetectionRightMain');
if (showAltImage) {
let temp = hiddenImage;
hiddenImage = shownImage;
shownImage = temp;
}
hiddenImage.style.display = 'none';
shownImage.style.display = 'inline-block';
showAltImage = !showAltImage;
},
function () {
showAltImage = true;
}
];
}()
async function reveal() {
setTimeout(() => {
if (!trialIsFinished)
document.getElementById(id).style.display = '';
document.getElementById(id).onclick = SwapRightImage;
}, delay)
}
reveal();
return function () {
trialIsFinished = true;
ResetSwapRightImage();
}
}
}