-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathSimulation_2stim_3psy_2resp_Watson(2017).html
77 lines (68 loc) · 3.38 KB
/
Simulation_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
<!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]
// 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)
// Note that the response is binominal.
function simulate_observer(freq, contrast){
const true_threshold = -35
const true_c0 = -50
const true_cf = 1.2
if (Math.random() > func_resp0(freq, contrast, true_threshold, true_c0, true_cf)){
return 1 // yes
} else {
return 0 // no
}
}
const nTrials = 32 // This is identical to that of Watson (2017)
for (let i = 0; i < nTrials; i++){
const stim = jsqp.getStimParams()
const resp = simulate_observer(stim[0], stim[1])
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 true threshold, C0, and Cf values as -35, -50, and 1.2, 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]}`)
</script>
</html>