-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathExample_2stim_3psy_2resp_Watson(2017).html
86 lines (73 loc) · 4.14 KB
/
Example_2stim_3psy_2resp_Watson(2017).html
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
<!DOCTYPE html>
<html>
<head>
<script src="../dist/jsQuestPlus.js"></script>
</head>
<body>
<p>This program simulates <a href="https://doi.org/10.1167/17.3.10">Watson (2017)'s</a> forth example: "Contrast sensitivity function {2, 3, 2}".</p>
<p>Watson wrote that:</p>
<blockquote>
<p>In this example, we illustrate a case of multiple stimulus dimensions.
The example describes rapid estimation of a parametrically defined contrast sensitivity function.
Our approach is effectively the same as that of <a href="https://jov.arvojournals.org/article.aspx?articleid=2158170">Lesmes et al. (2010)</a>
except that we use a different model for the contrast sensitivity function.
Our main point is to show that their qCSF method can be easily accommodated into the QUEST+ framework.
</p>
</blockquote>
<p>Please open the JavaScript console window in your browser. If you are using Chrome on Windows, press Ctrl + Shift + I to open the console.</p>
</body>
<script>
// Example: 2 stimulus parameters x 3 PF parameters x 2 responses
// Psychometric function corresponding to the first response (response = 0)
// You can specify the function or use the weibull/normcdf function jsQuest provides.
function func_resp0(freq, contrast, threshold, c0, cf){
const max = Math.max(threshold, c0 + cf*freq)
return jsQuestPlus.weibull(contrast, max, 3, 0.5, 0.01)
}
// Psychometric function corresponding to the second response (response = 1).
function func_resp1(freq, contrast, threshold, c0, cf){
return 1 - func_resp0(freq, contrast, threshold, c0, cf)
}
const spatial_frequency = jsQuestPlus.array(0, 2, 40) // [0, 2, 4, ..., 38, 40]
const contrast = jsQuestPlus.array(-50, 2, 0) // [-50, -48, -46, ..., -2, 0]
const threshold = jsQuestPlus.array(-50, 2, -30) // [-50, -48, -46, ..., -32, -30]
const c0 = jsQuestPlus.array(-60, 2, -40) // [-60, -58, -56, ..., -42, -40]
const cf = jsQuestPlus.array(0.8, 0.2, 1.6) // [0.8, 1, 1.2, 1.4, 1.6]
// These values are written in Watson (2017)
// Note that, in Watson (2017), the first answer corresponds to 1 and the second answer to 2.
const simulated_answers = [1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1]
const simulated_stim = [[40, 0], [40, -4], [34, 0], [36, 0], [0, -38], [38, 0], [0, -40], [38, 0], [18, -26], [18, -26],
[40, 0], [0, -36], [0, -36], [40, 0], [20, -26], [20, -26], [40, -2], [22, -26], [40, -6], [20, -26], [40, 0],
[18, -26], [40, 0], [18, -26], [0, -32], [0, -32], [0, -34], [0, -34], [40, 0], [18, -26], [38, 0], [18, -26]]
// jsqp means jsQuestPlus. You can use any variable name you like.
const jsqp = new jsQuestPlus({
psych_func: [func_resp0, func_resp1],
stim_samples: [spatial_frequency, contrast],
psych_samples: [threshold, c0, cf]
})
console.log(jsqp)
console.log(simulated_answers.length)
for (let i = 0; i < simulated_answers.length; i++){
const stim = jsqp.getStimParams()
const resp = simulated_answers[i]
// Spatial frequency
if (stim[0] !== simulated_stim[i][0]) console.error(`Check the first stim parameter of trial ${i+1}. ${stim}`)
// Contrast
if (stim[1] !== simulated_stim[i][1]) console.error(`Check the second stim parameter of trial ${i+1}. ${stim}`)
console.log(`Trial ${i+1}: Spatial frequency = ${stim[0]}; Contrast = ${stim[1]}; Response = ${resp}`)
jsqp.update(stim, resp)
}
const estimates = jsqp.getEstimates()
console.log(`Watson (2017) wrote the estimated threshold, C0, and Cf values as -32, -56, and 1.4, respectively.`)
console.log(`jsQuestPlus estimates as follows:`)
console.log(`Threshold estimate is ${estimates[0]}`)
console.log(`C0 estimate is ${estimates[1]}`)
console.log(`Cf estimate is ${estimates[2]}`)
//////////////////////////////
// This is optional
// const estimates_mean = jsqp.getEstimates('mean')
// console.log(estimates_mean)
// const sd = jsqp.getSDs()
// console.log(sd)
</script>
</html>