@decidables/accumulable-elements 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,208 @@
1
+
2
+ // import DDMMath from '@decidables/accumulable-math';
3
+
4
+ import DDMExample from './ddm-example';
5
+
6
+ /*
7
+ DDMExampleHuman element
8
+ <ddm-example-human>
9
+ */
10
+ export default class DDMExampleHuman extends DDMExample {
11
+ constructor() {
12
+ super();
13
+
14
+ this.trialCount = 0;
15
+ }
16
+
17
+ connectedCallback() {
18
+ super.connectedCallback();
19
+
20
+ this.accumulableControl = this.querySelector('accumulable-control');
21
+ this.rdkTask = this.querySelector('rdk-2afc-task');
22
+ this.accumulableResponse = this.querySelector('accumulable-response');
23
+ this.accumulableTable = this.querySelector('accumulable-table');
24
+ this.ddmParameters = this.querySelector('ddm-parameters');
25
+ this.ddmModel = this.querySelector('ddm-model');
26
+ this.ddmFit = this.querySelector('ddm-fit');
27
+
28
+ // Initialize
29
+ this.ddmModel.clear();
30
+
31
+ if (this.accumulableControl && this.accumulableControl.hasAttribute('trials')) {
32
+ this.accumulableControl.addEventListener('accumulable-control-trials', (event) => {
33
+ if (this.rdkTask) {
34
+ this.rdkTask.trials = event.detail.trials;
35
+ }
36
+
37
+ if (this.accumulableResponse) {
38
+ this.accumulableResponse.trialTotal = event.detail.trials;
39
+ }
40
+ });
41
+ }
42
+
43
+ if (this.accumulableControl && this.accumulableControl.hasAttribute('duration')) {
44
+ this.accumulableControl.addEventListener('accumulable-control-duration', (event) => {
45
+ if (this.rdkTask) {
46
+ this.rdkTask.duration = event.detail.duration;
47
+ this.rdkTask.wait = event.detail.duration;
48
+ this.rdkTask.iti = event.detail.duration;
49
+ }
50
+ });
51
+ }
52
+
53
+ if (this.accumulableControl && this.accumulableControl.hasAttribute('coherence')) {
54
+ this.accumulableControl.addEventListener('accumulable-control-coherence', (event) => {
55
+ if (this.rdkTask) {
56
+ this.rdkTask.coherence = event.detail.coherence;
57
+ }
58
+ });
59
+ }
60
+
61
+ if (this.accumulableControl && this.accumulableControl.hasAttribute('color')) {
62
+ this.accumulableControl.addEventListener('accumulable-control-color', (event) => {
63
+ if (this.accumulableTable) {
64
+ this.accumulableTable.color = event.detail.color;
65
+ }
66
+ });
67
+ }
68
+
69
+ if (this.accumulableControl && this.accumulableControl.hasAttribute('run')) {
70
+ this.accumulableControl.addEventListener('accumulable-control-run', (/* event */) => {
71
+ if (this.rdkTask) {
72
+ this.rdkTask.running = true;
73
+ }
74
+ });
75
+ }
76
+
77
+ if (this.accumulableControl && this.accumulableControl.hasAttribute('pause')) {
78
+ this.accumulableControl.addEventListener('accumulable-control-pause', (/* event */) => {
79
+ if (this.rdkTask) {
80
+ this.rdkTask.running = false;
81
+ }
82
+ });
83
+ }
84
+
85
+ if (this.accumulableControl && this.accumulableControl.hasAttribute('reset')) {
86
+ this.accumulableControl.addEventListener('accumulable-control-reset', (/* event */) => {
87
+ if (this.rdkTask) {
88
+ this.rdkTask.reset();
89
+ }
90
+
91
+ if (this.accumulableResponse) {
92
+ this.accumulableResponse.reset();
93
+ }
94
+
95
+ if (this.accumulableTable) {
96
+ this.accumulableTable.correctCount = NaN;
97
+ this.accumulableTable.errorCount = NaN;
98
+ this.accumulableTable.nrCount = NaN;
99
+ this.accumulableTable.accuracy = NaN;
100
+ this.accumulableTable.correctMeanRT = NaN;
101
+ this.accumulableTable.errorMeanRT = NaN;
102
+ this.accumulableTable.meanRT = NaN;
103
+ this.accumulableTable.correctSDRT = NaN;
104
+ this.accumulableTable.errorSDRT = NaN;
105
+ this.accumulableTable.sdRT = NaN;
106
+ }
107
+
108
+ // if (this.ddmParameters) {
109
+ // }
110
+
111
+ if (this.ddmModel) {
112
+ this.ddmModel.clear();
113
+ }
114
+
115
+ if (this.ddmFit) {
116
+ this.ddmFit.clear();
117
+ }
118
+ });
119
+ }
120
+
121
+ if (this.rdkTask) {
122
+ if (this.accumulableResponse) {
123
+ this.accumulableResponse.trialTotal = this.rdkTask.trials;
124
+ }
125
+ }
126
+
127
+ if (this.rdkTask) {
128
+ this.rdkTask.addEventListener('rdk-trial-start', (event) => {
129
+ if (this.accumulableResponse) {
130
+ this.accumulableResponse.start(event.detail.signal, event.detail.trial);
131
+ }
132
+ });
133
+ }
134
+
135
+ if (this.rdkTask) {
136
+ this.rdkTask.addEventListener('rdk-trial-end', (/* event */) => {
137
+ if (this.accumulableResponse) {
138
+ this.accumulableResponse.stop();
139
+ }
140
+ });
141
+ }
142
+
143
+ if (this.rdkTask) {
144
+ this.rdkTask.addEventListener('rdk-block-end', (/* event */) => {
145
+ if (this.accumulableControl) {
146
+ this.accumulableControl.complete();
147
+ }
148
+ });
149
+ }
150
+
151
+ if (this.accumulableResponse) {
152
+ this.accumulableResponse.addEventListener('accumulable-response', (event) => {
153
+ if (this.accumulableTable) {
154
+ this.accumulableTable.correctCount = event.detail.correctCount;
155
+ this.accumulableTable.errorCount = event.detail.errorCount;
156
+ this.accumulableTable.nrCount = event.detail.nrCount;
157
+ this.accumulableTable.accuracy = event.detail.accuracy;
158
+ this.accumulableTable.correctMeanRT = event.detail.correctMeanRT;
159
+ this.accumulableTable.errorMeanRT = event.detail.errorMeanRT;
160
+ this.accumulableTable.meanRT = event.detail.meanRT;
161
+ this.accumulableTable.correctSDRT = event.detail.correctSDRT;
162
+ this.accumulableTable.errorSDRT = event.detail.errorSDRT;
163
+ this.accumulableTable.sdRT = event.detail.sdRT;
164
+ }
165
+
166
+ if (this.ddmModel) {
167
+ this.ddmModel.trial({
168
+ index: event.detail.trial,
169
+ rt: event.detail.rt,
170
+ outcome: event.detail.outcome,
171
+ });
172
+ }
173
+
174
+ if (this.ddmFit) {
175
+ this.ddmFit.set({
176
+ accuracy: event.detail.accuracy,
177
+ correctMeanRT: event.detail.correctMeanRT,
178
+ errorMeanRT: event.detail.errorMeanRT,
179
+ meanRT: event.detail.meanRT,
180
+ correctSDRT: event.detail.correctSDRT,
181
+ errorSDRT: event.detail.errorSDRT,
182
+ sdRT: event.detail.sdRT,
183
+ });
184
+ }
185
+ });
186
+ }
187
+
188
+ if (this.ddmFit) {
189
+ this.ddmFit.addEventListener('ddm-fit-update', (event) => {
190
+ if (this.ddmParameters) {
191
+ this.ddmParameters.a = event.detail.a;
192
+ this.ddmParameters.z = 0.5; // event.detail.z;
193
+ this.ddmParameters.v = event.detail.v;
194
+ this.ddmParameters.t0 = event.detail.t0;
195
+ }
196
+
197
+ if (this.ddmModel) {
198
+ this.ddmModel.a = event.detail.a;
199
+ this.ddmModel.z = 0.5; // event.detail.z;
200
+ this.ddmModel.v = event.detail.v;
201
+ this.ddmModel.t0 = event.detail.t0;
202
+ }
203
+ });
204
+ }
205
+ }
206
+ }
207
+
208
+ customElements.define('ddm-example-human', DDMExampleHuman);
@@ -0,0 +1,4 @@
1
+
2
+ export {default as DDMExampleHuman} from './human';
3
+ export {default as DDMExampleInteractive} from './interactive';
4
+ export {default as DDMExampleModel} from './model';
@@ -0,0 +1,150 @@
1
+
2
+ import DDMExample from './ddm-example';
3
+
4
+ /*
5
+ DDMExampleInteractive element
6
+ <ddm-example-interactive>
7
+ */
8
+ export default class DDMExampleInteractive extends DDMExample {
9
+ static get properties() {
10
+ return {
11
+ trials: {
12
+ attribute: 'trials',
13
+ type: Number,
14
+ reflect: true,
15
+ },
16
+ a: {
17
+ attribute: 'boundary-separation',
18
+ type: Number,
19
+ reflect: true,
20
+ },
21
+ z: {
22
+ attribute: 'starting-point',
23
+ type: Number,
24
+ reflect: true,
25
+ },
26
+ v: {
27
+ attribute: 'drift-rate',
28
+ type: Number,
29
+ reflect: true,
30
+ },
31
+ t0: {
32
+ attribute: 'nondecision-time',
33
+ type: Number,
34
+ reflect: true,
35
+ },
36
+ };
37
+ }
38
+
39
+ constructor() {
40
+ super();
41
+
42
+ this.trials = 10;
43
+ this.a = 1.2;
44
+ this.z = 0.35;
45
+ this.v = 1.5;
46
+ this.t0 = 150;
47
+
48
+ this.accumulableControl = null;
49
+ this.accumulableTable = null;
50
+ this.ddmParameters = null;
51
+ this.ddmModel = null;
52
+
53
+ this.data = undefined;
54
+ this.model = undefined;
55
+ }
56
+
57
+ connectedCallback() {
58
+ super.connectedCallback();
59
+
60
+ this.accumulableControl = this.querySelector('accumulable-control');
61
+ this.accumulableTable = this.querySelector('accumulable-table');
62
+ this.ddmParameters = this.querySelector('ddm-parameters');
63
+ this.ddmModel = this.querySelector('ddm-model');
64
+
65
+ if (this.accumulableControl) {
66
+ this.accumulableControl.addEventListener('accumulable-control-resample', (/* event */) => {
67
+ this.ddmModel?.resample();
68
+ this.requestUpdate();
69
+ });
70
+ this.accumulableControl.addEventListener('accumulable-control-trials', (event) => {
71
+ this.trials = event.detail.trials;
72
+ });
73
+ }
74
+
75
+ if (this.ddmParameters) {
76
+ this.ddmParameters.addEventListener('ddm-parameters-a', (event) => {
77
+ this.a = event.detail.a;
78
+ });
79
+ this.ddmParameters.addEventListener('ddm-parameters-z', (event) => {
80
+ this.z = event.detail.z;
81
+ });
82
+ this.ddmParameters.addEventListener('ddm-parameters-v', (event) => {
83
+ this.v = event.detail.v;
84
+ });
85
+ this.ddmParameters.addEventListener('ddm-parameters-t0', (event) => {
86
+ this.t0 = event.detail.t0;
87
+ });
88
+ }
89
+
90
+ if (this.ddmModel) {
91
+ this.ddmModel.addEventListener('ddm-model-a', (event) => {
92
+ this.a = event.detail.a;
93
+ });
94
+ this.ddmModel.addEventListener('ddm-model-z', (event) => {
95
+ this.z = event.detail.z;
96
+ });
97
+ this.ddmModel.addEventListener('ddm-model-v', (event) => {
98
+ this.v = event.detail.v;
99
+ });
100
+ this.ddmModel.addEventListener('ddm-model-t0', (event) => {
101
+ this.t0 = event.detail.t0;
102
+ });
103
+ this.ddmModel.addEventListener('ddm-model-output', (event) => {
104
+ this.data = event.detail.data;
105
+ this.model = event.detail.model;
106
+ this.requestUpdate();
107
+ });
108
+ }
109
+
110
+ this.requestUpdate();
111
+ }
112
+
113
+ update(changedProperties) {
114
+ super.update(changedProperties);
115
+
116
+ if (this.accumulableControl) {
117
+ this.accumulableControl.trials = this.trials;
118
+ }
119
+
120
+ if (this.accumulableTable && this.data) {
121
+ this.accumulableTable.correctCount = this.data.correctCount;
122
+ this.accumulableTable.errorCount = this.data.errorCount;
123
+ this.accumulableTable.nrCount = this.data.nrCount;
124
+ this.accumulableTable.accuracy = this.data.accuracy;
125
+ this.accumulableTable.correctMeanRT = this.data.correctMeanRT;
126
+ this.accumulableTable.errorMeanRT = this.data.errorMeanRT;
127
+ this.accumulableTable.meanRT = this.data.meanRT;
128
+ this.accumulableTable.correctSDRT = this.data.correctSDRT;
129
+ this.accumulableTable.errorSDRT = this.data.errorSDRT;
130
+ this.accumulableTable.sdRT = this.data.sdRT;
131
+ }
132
+
133
+ if (this.ddmParameters) {
134
+ this.ddmParameters.a = this.a;
135
+ this.ddmParameters.z = this.z;
136
+ this.ddmParameters.v = this.v;
137
+ this.ddmParameters.t0 = this.t0;
138
+ }
139
+
140
+ if (this.ddmModel) {
141
+ this.ddmModel.trials = this.trials;
142
+ this.ddmModel.a = +this.a;
143
+ this.ddmModel.z = +this.z;
144
+ this.ddmModel.v = +this.v;
145
+ this.ddmModel.t0 = +this.t0;
146
+ }
147
+ }
148
+ }
149
+
150
+ customElements.define('ddm-example-interactive', DDMExampleInteractive);
@@ -0,0 +1,307 @@
1
+
2
+ // import DDMMath from '@decidables/accumulable-math';
3
+
4
+ import DDMExample from './ddm-example';
5
+
6
+ /*
7
+ DDMExampleModel element
8
+ <ddm-example-model>
9
+ */
10
+ export default class DDMExampleModel extends DDMExample {
11
+ static get properties() {
12
+ return {
13
+ trials: {
14
+ attribute: 'trials',
15
+ type: Number,
16
+ reflect: true,
17
+ },
18
+ duration: {
19
+ attribute: 'duration',
20
+ type: Number,
21
+ reflect: true,
22
+ },
23
+ coherence: {
24
+ attribute: 'coherence',
25
+ type: Number,
26
+ reflect: true,
27
+ },
28
+ color: {
29
+ attribute: 'color',
30
+ type: String,
31
+ reflect: true,
32
+ },
33
+
34
+ a: {
35
+ attribute: 'boundary-separation',
36
+ type: Number,
37
+ reflect: true,
38
+ },
39
+ z: {
40
+ attribute: 'starting-point',
41
+ type: Number,
42
+ reflect: true,
43
+ },
44
+ v: {
45
+ attribute: 'drift-rate',
46
+ type: Number,
47
+ reflect: true,
48
+ },
49
+ t0: {
50
+ attribute: 'nondecision-time',
51
+ type: Number,
52
+ reflect: true,
53
+ },
54
+ };
55
+ }
56
+
57
+ constructor() {
58
+ super();
59
+
60
+ this.trials = 10;
61
+ this.duration = 2000;
62
+ this.coherence = 0.5;
63
+ this.colors = ['none', 'measure', 'outcome', 'all'];
64
+ this.color = 'outcome';
65
+
66
+ this.a = 1.2;
67
+ this.z = 0.35;
68
+ this.v = 1.5;
69
+ this.t0 = 150;
70
+
71
+ this.accumulableControl = null;
72
+ this.rdkTask = null;
73
+ this.ddmParameters = null;
74
+ this.ddmModel = null;
75
+ this.accumulableResponse = null;
76
+ this.accumulableTable = null;
77
+
78
+ this.trialCount = 0;
79
+ this.signals = ['left', 'right']; // Possible values of 'signal'
80
+ this.signal = undefined; // Signal for current trial
81
+ this.data = undefined;
82
+ this.model = undefined;
83
+ }
84
+
85
+ connectedCallback() {
86
+ super.connectedCallback();
87
+
88
+ this.accumulableControl = this.querySelector('accumulable-control');
89
+ this.rdkTask = this.querySelector('rdk-2afc-task');
90
+ this.ddmParameters = this.querySelector('ddm-parameters');
91
+ this.ddmModel = this.querySelector('ddm-model');
92
+ this.accumulableResponse = this.querySelector('accumulable-response');
93
+ this.accumulableTable = this.querySelector('accumulable-table');
94
+
95
+ if (this.accumulableControl) {
96
+ if (this.accumulableControl.hasAttribute('trials')) {
97
+ this.accumulableControl.addEventListener('accumulable-control-trials', (event) => {
98
+ this.trials = event.detail.trials;
99
+ });
100
+ }
101
+
102
+ if (this.accumulableControl.hasAttribute('duration')) {
103
+ this.accumulableControl.addEventListener('accumulable-control-duration', (event) => {
104
+ this.duration = event.detail.duration;
105
+ });
106
+ }
107
+
108
+ if (this.accumulableControl.hasAttribute('color')) {
109
+ this.accumulableControl.addEventListener('accumulable-control-color', (event) => {
110
+ this.color = event.detail.color;
111
+ });
112
+ }
113
+
114
+ if (this.accumulableControl.hasAttribute('run')) {
115
+ this.accumulableControl.addEventListener('accumulable-control-run', (/* event */) => {
116
+ if (this.rdkTask) {
117
+ this.rdkTask.running = true;
118
+ }
119
+
120
+ if (this.ddmModel) {
121
+ this.ddmModel.resumeTrial();
122
+ }
123
+ });
124
+ }
125
+
126
+ if (this.accumulableControl.hasAttribute('pause')) {
127
+ this.accumulableControl.addEventListener('accumulable-control-pause', (/* event */) => {
128
+ if (this.rdkTask) {
129
+ this.rdkTask.running = false;
130
+ }
131
+
132
+ if (this.ddmModel) {
133
+ this.ddmModel.pauseTrial();
134
+ }
135
+ });
136
+ }
137
+
138
+ if (this.accumulableControl.hasAttribute('reset')) {
139
+ this.accumulableControl.addEventListener('accumulable-control-reset', (/* event */) => {
140
+ this.trialCount = 0;
141
+ this.signal = undefined;
142
+
143
+ if (this.rdkTask) {
144
+ this.rdkTask.reset();
145
+ }
146
+
147
+ if (this.ddmModel) {
148
+ this.ddmModel.trials = this.trialCount;
149
+ }
150
+
151
+ if (this.accumulableResponse) {
152
+ this.accumulableResponse.reset();
153
+ }
154
+
155
+ if (this.accumulableTable) {
156
+ // this.accumulableTable.clear();
157
+ }
158
+ });
159
+ }
160
+ }
161
+
162
+ if (this.rdkTask) {
163
+ this.rdkTask.addEventListener('rdk-trial-start', (event) => {
164
+ this.signal = event.detail.signal;
165
+
166
+ if (this.accumulableResponse) {
167
+ this.accumulableResponse.start(
168
+ event.detail.signal,
169
+ event.detail.trial,
170
+ );
171
+ }
172
+
173
+ if (this.ddmModel) {
174
+ this.trialCount += 1;
175
+ this.ddmModel.trial();
176
+ }
177
+ });
178
+
179
+ this.rdkTask.addEventListener('rdk-trial-end', (/* event */) => {
180
+ this.signal = undefined;
181
+
182
+ if (this.accumulableResponse) {
183
+ this.accumulableResponse.stop();
184
+ }
185
+ });
186
+
187
+ this.rdkTask.addEventListener('rdk-block-end', (/* event */) => {
188
+ if (this.accumulableControl) {
189
+ this.accumulableControl.complete();
190
+ }
191
+ });
192
+ }
193
+
194
+ if (this.ddmParameters) {
195
+ this.ddmParameters.addEventListener('ddm-parameters-a', (event) => {
196
+ this.a = event.detail.a;
197
+ });
198
+ this.ddmParameters.addEventListener('ddm-parameters-z', (event) => {
199
+ this.z = event.detail.z;
200
+ });
201
+ this.ddmParameters.addEventListener('ddm-parameters-v', (event) => {
202
+ this.v = event.detail.v;
203
+ });
204
+ this.ddmParameters.addEventListener('ddm-parameters-t0', (event) => {
205
+ this.t0 = event.detail.t0;
206
+ });
207
+ }
208
+
209
+ if (this.ddmModel) {
210
+ this.ddmModel.addEventListener('ddm-model-a', (event) => {
211
+ this.a = event.detail.a;
212
+ });
213
+ this.ddmModel.addEventListener('ddm-model-z', (event) => {
214
+ this.z = event.detail.z;
215
+ });
216
+ this.ddmModel.addEventListener('ddm-model-v', (event) => {
217
+ this.v = event.detail.v;
218
+ });
219
+ this.ddmModel.addEventListener('ddm-model-t0', (event) => {
220
+ this.t0 = event.detail.t0;
221
+ });
222
+ this.ddmModel.addEventListener('ddm-model-output', (event) => {
223
+ this.data = event.detail.data;
224
+ this.model = event.detail.model;
225
+ this.requestUpdate();
226
+ });
227
+
228
+ if (this.ddmModel) {
229
+ this.ddmModel.addEventListener('accumulable-response', (event) => {
230
+ if (this.accumulableResponse) {
231
+ const response = (event.detail.outcome === 'correct')
232
+ ? this.signal
233
+ : (this.signal === 'left')
234
+ ? 'right'
235
+ : 'left';
236
+ this.accumulableResponse.responded(response);
237
+ }
238
+
239
+ this.data = event.detail.data;
240
+ this.model = event.detail.model;
241
+ this.requestUpdate();
242
+ });
243
+ }
244
+ }
245
+
246
+ this.requestUpdate();
247
+ }
248
+
249
+ update(changedProperties) {
250
+ super.update(changedProperties);
251
+
252
+ if (this.trialCount > this.trials) {
253
+ this.trialCount = this.trials;
254
+ }
255
+
256
+ if (this.accumulableControl) {
257
+ this.accumulableControl.trials = this.trials;
258
+ this.accumulableControl.duration = this.duration;
259
+ this.accumulableControl.coherence = this.coherence;
260
+ this.accumulableControl.color = this.color;
261
+ }
262
+
263
+ if (this.rdkTask) {
264
+ this.rdkTask.trials = this.trials;
265
+ this.rdkTask.duration = this.duration;
266
+ this.rdkTask.coherence = this.coherence;
267
+ }
268
+
269
+ if (this.ddmParameters) {
270
+ this.ddmParameters.a = this.a;
271
+ this.ddmParameters.z = this.z;
272
+ this.ddmParameters.v = this.v;
273
+ this.ddmParameters.t0 = this.t0;
274
+ }
275
+
276
+ if (this.ddmModel) {
277
+ this.ddmModel.trials = this.trialCount;
278
+ this.ddmModel.a = +this.a;
279
+ this.ddmModel.z = +this.z;
280
+ this.ddmModel.v = +this.v;
281
+ this.ddmModel.t0 = +this.t0;
282
+ }
283
+
284
+ if (this.accumulableResponse) {
285
+ this.accumulableResponse.trialTotal = this.trials;
286
+ }
287
+
288
+ if (this.accumulableTable) {
289
+ this.accumulableTable.color = this.color;
290
+ }
291
+
292
+ if (this.accumulableTable && this.data) {
293
+ this.accumulableTable.correctCount = this.data.correctCount;
294
+ this.accumulableTable.errorCount = this.data.errorCount;
295
+ this.accumulableTable.nrCount = this.data.nrCount;
296
+ this.accumulableTable.accuracy = this.data.accuracy;
297
+ this.accumulableTable.correctMeanRT = this.data.correctMeanRT;
298
+ this.accumulableTable.errorMeanRT = this.data.errorMeanRT;
299
+ this.accumulableTable.meanRT = this.data.meanRT;
300
+ this.accumulableTable.correctSDRT = this.data.correctSDRT;
301
+ this.accumulableTable.errorSDRT = this.data.errorSDRT;
302
+ this.accumulableTable.sdRT = this.data.sdRT;
303
+ }
304
+ }
305
+ }
306
+
307
+ customElements.define('ddm-example-model', DDMExampleModel);
package/src/index.js ADDED
@@ -0,0 +1,6 @@
1
+
2
+ // Internal dependencies
3
+ export {default as AccumulableElement} from './accumulable-element';
4
+ export * from './components';
5
+ export * from './equations';
6
+ export * from './examples';