@jspsych/extension-tobii 0.1.1

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.
Files changed (71) hide show
  1. package/README.md +220 -0
  2. package/dist/index.browser.js +1005 -0
  3. package/dist/index.browser.js.map +1 -0
  4. package/dist/index.browser.min.js +3 -0
  5. package/dist/index.browser.min.js.map +1 -0
  6. package/dist/index.cjs +1004 -0
  7. package/dist/index.cjs.map +1 -0
  8. package/dist/index.d.ts +410 -0
  9. package/dist/index.js +1002 -0
  10. package/dist/index.js.map +1 -0
  11. package/package.json +52 -0
  12. package/src/coordinate-utils.d.ts +33 -0
  13. package/src/coordinate-utils.d.ts.map +1 -0
  14. package/src/coordinate-utils.js +70 -0
  15. package/src/coordinate-utils.js.map +1 -0
  16. package/src/coordinate-utils.ts +80 -0
  17. package/src/data-export.d.ts +12 -0
  18. package/src/data-export.d.ts.map +1 -0
  19. package/src/data-export.js +75 -0
  20. package/src/data-export.js.map +1 -0
  21. package/src/data-export.spec.d.ts +2 -0
  22. package/src/data-export.spec.d.ts.map +1 -0
  23. package/src/data-export.spec.js +95 -0
  24. package/src/data-export.spec.js.map +1 -0
  25. package/src/data-export.spec.ts +111 -0
  26. package/src/data-export.ts +84 -0
  27. package/src/data-manager.d.ts +57 -0
  28. package/src/data-manager.d.ts.map +1 -0
  29. package/src/data-manager.js +107 -0
  30. package/src/data-manager.js.map +1 -0
  31. package/src/data-manager.spec.d.ts +2 -0
  32. package/src/data-manager.spec.d.ts.map +1 -0
  33. package/src/data-manager.spec.js +162 -0
  34. package/src/data-manager.spec.js.map +1 -0
  35. package/src/data-manager.spec.ts +195 -0
  36. package/src/data-manager.ts +123 -0
  37. package/src/device-time-sync.d.ts +69 -0
  38. package/src/device-time-sync.d.ts.map +1 -0
  39. package/src/device-time-sync.js +150 -0
  40. package/src/device-time-sync.js.map +1 -0
  41. package/src/device-time-sync.ts +173 -0
  42. package/src/index.d.ts +200 -0
  43. package/src/index.d.ts.map +1 -0
  44. package/src/index.js +431 -0
  45. package/src/index.js.map +1 -0
  46. package/src/index.spec.d.ts +2 -0
  47. package/src/index.spec.d.ts.map +1 -0
  48. package/src/index.spec.js +212 -0
  49. package/src/index.spec.js.map +1 -0
  50. package/src/index.spec.ts +257 -0
  51. package/src/index.ts +535 -0
  52. package/src/time-sync.d.ts +39 -0
  53. package/src/time-sync.d.ts.map +1 -0
  54. package/src/time-sync.js +76 -0
  55. package/src/time-sync.js.map +1 -0
  56. package/src/time-sync.ts +91 -0
  57. package/src/types.d.ts +222 -0
  58. package/src/types.d.ts.map +1 -0
  59. package/src/types.js +5 -0
  60. package/src/types.js.map +1 -0
  61. package/src/types.ts +251 -0
  62. package/src/validation.d.ts +25 -0
  63. package/src/validation.d.ts.map +1 -0
  64. package/src/validation.js +54 -0
  65. package/src/validation.js.map +1 -0
  66. package/src/validation.ts +60 -0
  67. package/src/websocket-client.d.ts +55 -0
  68. package/src/websocket-client.d.ts.map +1 -0
  69. package/src/websocket-client.js +189 -0
  70. package/src/websocket-client.js.map +1 -0
  71. package/src/websocket-client.ts +227 -0
package/README.md ADDED
@@ -0,0 +1,220 @@
1
+ # @jspsych/extension-tobii
2
+
3
+ Core jsPsych extension for Tobii eye tracker integration via WebSocket. Provides real-time gaze data streaming, calibration control, time synchronization, and coordinate utilities for eye tracking experiments.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @jspsych/extension-tobii
9
+ ```
10
+
11
+ ## Compatibility
12
+
13
+ This extension requires jsPsych v8.0.0 or later.
14
+
15
+ ## Usage
16
+
17
+ ### Loading the Extension
18
+
19
+ ```javascript
20
+ import { initJsPsych } from 'jspsych';
21
+ import TobiiExtension from '@jspsych/extension-tobii';
22
+
23
+ const jsPsych = initJsPsych({
24
+ extensions: [
25
+ {
26
+ type: TobiiExtension,
27
+ params: {
28
+ connection: {
29
+ url: 'ws://localhost:8080',
30
+ autoConnect: true,
31
+ },
32
+ },
33
+ },
34
+ ],
35
+ });
36
+ ```
37
+
38
+ ### Enabling Eye Tracking on Trials
39
+
40
+ Add the extension to any trial to collect gaze data during that trial:
41
+
42
+ ```javascript
43
+ const trial = {
44
+ type: jsPsychHtmlKeyboardResponse,
45
+ stimulus: '<p>Look at this text</p>',
46
+ extensions: [{ type: TobiiExtension }],
47
+ };
48
+ ```
49
+
50
+ ## Initialization Parameters
51
+
52
+ Parameters passed to the extension in the `params` object when initializing jsPsych.
53
+
54
+ | Parameter | Type | Default | Description |
55
+ |-----------|------|---------|-------------|
56
+ | connection | object | `{}` | Connection settings (see below) |
57
+ | connection.url | string | `undefined` | WebSocket server URL (e.g., `'ws://localhost:8080'`) |
58
+ | connection.autoConnect | boolean | `undefined` | Automatically connect on initialization |
59
+ | connection.reconnectAttempts | number | `undefined` | Number of reconnection attempts |
60
+ | connection.reconnectDelay | number | `undefined` | Delay between reconnection attempts in ms |
61
+
62
+ ## On Start Parameters
63
+
64
+ Parameters passed to the extension in the `extensions` array on individual trials.
65
+
66
+ | Parameter | Type | Default | Description |
67
+ |-----------|------|---------|-------------|
68
+ | trialId | string \| number | `undefined` | Trial ID or index |
69
+
70
+ ## Data Generated
71
+
72
+ When the extension is added to a trial, the following data is appended to the trial's data object.
73
+
74
+ | Name | Type | Description |
75
+ |------|------|-------------|
76
+ | tobii_data | array | Array of gaze data samples collected during the trial. Each sample is a `GazeData` object (see below). |
77
+
78
+ ### GazeData Object
79
+
80
+ Each element in the `tobii_data` array contains:
81
+
82
+ | Field | Type | Description |
83
+ |-------|------|-------------|
84
+ | x | number | X coordinate (normalized 0-1 or pixels, depending on config) |
85
+ | y | number | Y coordinate (normalized 0-1 or pixels, depending on config) |
86
+ | timestamp | number | Timestamp in ms (Tobii device clock) |
87
+ | browserTimestamp | number | Device timestamp mapped to `performance.now()` domain |
88
+ | leftValid | boolean | Whether the left eye data is valid |
89
+ | rightValid | boolean | Whether the right eye data is valid |
90
+ | leftPupilDiameter | number | Left eye pupil diameter |
91
+ | rightPupilDiameter | number | Right eye pupil diameter |
92
+
93
+ ## Extension API
94
+
95
+ All methods are accessible via `jsPsych.extensions.tobii.*`. See the [full API reference](../../README.md#extension-api-reference) for detailed documentation.
96
+
97
+ ### Connection
98
+
99
+ | Method | Returns | Description |
100
+ |--------|---------|-------------|
101
+ | `connect()` | `Promise<void>` | Connect to WebSocket server |
102
+ | `disconnect()` | `Promise<void>` | Disconnect from server |
103
+ | `isConnected()` | `boolean` | Check connection status |
104
+ | `getConnectionStatus()` | `ConnectionStatus` | Get detailed connection status |
105
+
106
+ ### Eye Tracking Control
107
+
108
+ | Method | Returns | Description |
109
+ |--------|---------|-------------|
110
+ | `startTracking()` | `Promise<void>` | Start gaze data collection |
111
+ | `stopTracking()` | `Promise<void>` | Stop gaze data collection |
112
+ | `isTracking()` | `boolean` | Check tracking status |
113
+
114
+ ### Calibration
115
+
116
+ | Method | Returns | Description |
117
+ |--------|---------|-------------|
118
+ | `startCalibration()` | `Promise<void>` | Start calibration procedure |
119
+ | `collectCalibrationPoint(x, y)` | `Promise<{ success }>` | Collect data for a point (0-1) |
120
+ | `computeCalibration()` | `Promise<CalibrationResult>` | Compute calibration |
121
+ | `getCalibrationData()` | `Promise<CalibrationResult>` | Get calibration quality metrics |
122
+
123
+ ### Validation
124
+
125
+ | Method | Returns | Description |
126
+ |--------|---------|-------------|
127
+ | `startValidation()` | `Promise<void>` | Start validation procedure |
128
+ | `collectValidationPoint(x, y, samples?)` | `Promise<void>` | Collect data for a point (0-1) |
129
+ | `computeValidation()` | `Promise<ValidationResult>` | Compute validation metrics |
130
+
131
+ ### Data Access
132
+
133
+ | Method | Returns | Description |
134
+ |--------|---------|-------------|
135
+ | `getCurrentGaze()` | `Promise<GazeData \| null>` | Get current gaze position |
136
+ | `getGazeData(start, end)` | `Promise<GazeData[]>` | Get gaze data for a time range |
137
+ | `getRecentGazeData(durationMs)` | `GazeData[]` | Get recent data from buffer |
138
+ | `getUserPosition()` | `Promise<UserPositionData \| null>` | Get head position data |
139
+ | `clearGazeData()` | `void` | Clear stored gaze data |
140
+
141
+ ### Coordinate Utilities
142
+
143
+ | Method | Returns | Description |
144
+ |--------|---------|-------------|
145
+ | `normalizedToPixels(x, y)` | `Coordinates` | Convert normalized (0-1) to pixels |
146
+ | `pixelsToNormalized(x, y)` | `Coordinates` | Convert pixels to normalized (0-1) |
147
+ | `windowToContainer(x, y, el?)` | `Coordinates` | Convert window to container-relative coords |
148
+ | `getScreenDimensions()` | `ScreenDimensions` | Get window dimensions |
149
+ | `getContainerDimensions(el?)` | `ScreenDimensions` | Get container dimensions |
150
+ | `isWithinContainer(x, y, el?)` | `boolean` | Check if point is inside container |
151
+ | `calculateDistance(p1, p2)` | `number` | Euclidean distance between two points |
152
+
153
+ ### Data Export
154
+
155
+ | Method | Returns | Description |
156
+ |--------|---------|-------------|
157
+ | `exportToCSV(data, filename)` | `void` | Export data to CSV file |
158
+ | `exportToJSON(data, filename)` | `void` | Export data to JSON file |
159
+
160
+ ### Time Synchronization
161
+
162
+ | Method | Returns | Description |
163
+ |--------|---------|-------------|
164
+ | `getTimeOffset()` | `number` | Get browser-server time offset (ms) |
165
+ | `isTimeSynced()` | `boolean` | Check if time is synced with server |
166
+ | `toDeviceTime(performanceNow)` | `number` | Convert `performance.now()` to device time |
167
+ | `toLocalTime(deviceTime)` | `number` | Convert device time to `performance.now()` |
168
+ | `isDeviceTimeSynced()` | `boolean` | Check if device time sync is established |
169
+ | `getTimeSyncStatus()` | `DeviceTimeSyncStatus` | Get full sync status and diagnostics |
170
+ | `validateTimestampAlignment(samples)` | `TimestampAlignmentResult \| null` | Validate timestamp alignment |
171
+
172
+ ### Configuration
173
+
174
+ | Method | Returns | Description |
175
+ |--------|---------|-------------|
176
+ | `setConfig(config)` | `void` | Update extension configuration |
177
+ | `getConfig()` | `InitializeParameters` | Get current configuration |
178
+
179
+ ## Example
180
+
181
+ ```javascript
182
+ import { initJsPsych } from 'jspsych';
183
+ import TobiiExtension from '@jspsych/extension-tobii';
184
+ import TobiiCalibrationPlugin from '@jspsych/plugin-tobii-calibration';
185
+ import HtmlKeyboardResponsePlugin from '@jspsych/plugin-html-keyboard-response';
186
+
187
+ const jsPsych = initJsPsych({
188
+ extensions: [
189
+ {
190
+ type: TobiiExtension,
191
+ params: {
192
+ connection: { url: 'ws://localhost:8080', autoConnect: true },
193
+ },
194
+ },
195
+ ],
196
+ on_finish: () => {
197
+ const data = jsPsych.data.get().values();
198
+ jsPsych.extensions.tobii.exportToCSV(data, 'gaze_data.csv');
199
+ },
200
+ });
201
+
202
+ const timeline = [];
203
+
204
+ timeline.push({
205
+ type: TobiiCalibrationPlugin,
206
+ calibration_points: 9,
207
+ });
208
+
209
+ timeline.push({
210
+ type: HtmlKeyboardResponsePlugin,
211
+ stimulus: '<p>Look at this stimulus</p>',
212
+ extensions: [{ type: TobiiExtension }],
213
+ });
214
+
215
+ jsPsych.run(timeline);
216
+ ```
217
+
218
+ ## Citation
219
+
220
+ If you use this extension in your research, please cite it. See [CITATION.cff](CITATION.cff).