@jspsych/extension-tobii
v0.2.1
Published
jsPsych extension for Tobii eye tracker integration via WebSocket
Downloads
13
Readme
@jspsych/extension-tobii
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.
Installation
npm install @jspsych/extension-tobiiCompatibility
This extension requires jsPsych v8.0.0 or later.
Usage
Loading the Extension
import { initJsPsych } from 'jspsych';
import TobiiExtension from '@jspsych/extension-tobii';
const jsPsych = initJsPsych({
extensions: [
{
type: TobiiExtension,
params: {
connection: {
url: 'ws://localhost:8080',
autoConnect: true,
},
},
},
],
});Enabling Eye Tracking on Trials
Add the extension to any trial to collect gaze data during that trial:
const trial = {
type: jsPsychHtmlKeyboardResponse,
stimulus: '<p>Look at this text</p>',
extensions: [{ type: TobiiExtension }],
};Initialization Parameters
Parameters passed to the extension in the params object when initializing jsPsych.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| connection | object | {} | Connection settings (see below) |
| connection.url | string | undefined | WebSocket server URL (e.g., 'ws://localhost:8080') |
| connection.autoConnect | boolean | undefined | Automatically connect on initialization |
| connection.reconnectAttempts | number | undefined | Number of reconnection attempts |
| connection.reconnectDelay | number | undefined | Delay between reconnection attempts in ms |
On Start Parameters
Parameters passed to the extension in the extensions array on individual trials.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| trialId | string | number | undefined | Trial ID or index |
Data Generated
When the extension is added to a trial, the following data is appended to the trial's data object.
| Name | Type | Description |
|------|------|-------------|
| tobii_data | array | Array of gaze data samples collected during the trial. Each sample is a GazeData object (see below). |
GazeData Object
Each element in the tobii_data array contains:
| Field | Type | Description |
|-------|------|-------------|
| x | number | X coordinate (normalized 0-1 or pixels, depending on config) |
| y | number | Y coordinate (normalized 0-1 or pixels, depending on config) |
| timestamp | number | Timestamp in ms (Tobii device clock) |
| browserTimestamp | number | Device timestamp mapped to performance.now() domain |
| leftValid | boolean | Whether the left eye data is valid |
| rightValid | boolean | Whether the right eye data is valid |
| leftPupilDiameter | number | Left eye pupil diameter |
| rightPupilDiameter | number | Right eye pupil diameter |
Extension API
All methods are accessible via jsPsych.extensions.tobii.*. See the full API reference for detailed documentation.
Connection
| Method | Returns | Description |
|--------|---------|-------------|
| connect() | Promise<void> | Connect to WebSocket server |
| disconnect() | Promise<void> | Disconnect from server |
| isConnected() | boolean | Check connection status |
| getConnectionStatus() | ConnectionStatus | Get detailed connection status |
Eye Tracking Control
| Method | Returns | Description |
|--------|---------|-------------|
| startTracking() | Promise<void> | Start gaze data collection |
| stopTracking() | Promise<void> | Stop gaze data collection |
| isTracking() | boolean | Check tracking status |
Calibration
| Method | Returns | Description |
|--------|---------|-------------|
| startCalibration() | Promise<void> | Start calibration procedure |
| collectCalibrationPoint(x, y) | Promise<{ success }> | Collect data for a point (0-1) |
| computeCalibration() | Promise<CalibrationResult> | Compute calibration |
| getCalibrationData() | Promise<CalibrationResult> | Get calibration quality metrics |
Validation
| Method | Returns | Description |
|--------|---------|-------------|
| startValidation() | Promise<void> | Start validation procedure |
| collectValidationPoint(x, y, samples?) | Promise<void> | Collect data for a point (0-1) |
| computeValidation() | Promise<ValidationResult> | Compute validation metrics |
Data Access
| Method | Returns | Description |
|--------|---------|-------------|
| getCurrentGaze() | Promise<GazeData \| null> | Get current gaze position |
| getGazeData(start, end) | Promise<GazeData[]> | Get gaze data for a time range |
| getRecentGazeData(durationMs) | GazeData[] | Get recent data from buffer |
| getUserPosition() | Promise<UserPositionData \| null> | Get head position data |
| clearGazeData() | void | Clear stored gaze data |
Coordinate Utilities
| Method | Returns | Description |
|--------|---------|-------------|
| normalizedToPixels(x, y) | Coordinates | Convert normalized (0-1) to pixels |
| pixelsToNormalized(x, y) | Coordinates | Convert pixels to normalized (0-1) |
| windowToContainer(x, y, el?) | Coordinates | Convert window to container-relative coords |
| getScreenDimensions() | ScreenDimensions | Get window dimensions |
| getContainerDimensions(el?) | ScreenDimensions | Get container dimensions |
| isWithinContainer(x, y, el?) | boolean | Check if point is inside container |
| calculateDistance(p1, p2) | number | Euclidean distance between two points |
Data Export
| Method | Returns | Description |
|--------|---------|-------------|
| exportToCSV(data, filename) | void | Export data to CSV file |
| exportToJSON(data, filename) | void | Export data to JSON file |
Time Synchronization
| Method | Returns | Description |
|--------|---------|-------------|
| getTimeOffset() | number | Get browser-server time offset (ms) |
| isTimeSynced() | boolean | Check if time is synced with server |
| toDeviceTime(performanceNow) | number | Convert performance.now() to device time |
| toLocalTime(deviceTime) | number | Convert device time to performance.now() |
| isDeviceTimeSynced() | boolean | Check if device time sync is established |
| getTimeSyncStatus() | DeviceTimeSyncStatus | Get full sync status and diagnostics |
| validateTimestampAlignment(samples) | TimestampAlignmentResult \| null | Validate timestamp alignment |
Configuration
| Method | Returns | Description |
|--------|---------|-------------|
| setConfig(config) | void | Update extension configuration |
| getConfig() | InitializeParameters | Get current configuration |
Example
import { initJsPsych } from 'jspsych';
import TobiiExtension from '@jspsych/extension-tobii';
import TobiiCalibrationPlugin from '@jspsych/plugin-tobii-calibration';
import HtmlKeyboardResponsePlugin from '@jspsych/plugin-html-keyboard-response';
const jsPsych = initJsPsych({
extensions: [
{
type: TobiiExtension,
params: {
connection: { url: 'ws://localhost:8080', autoConnect: true },
},
},
],
on_finish: () => {
const data = jsPsych.data.get().values();
jsPsych.extensions.tobii.exportToCSV(data, 'gaze_data.csv');
},
});
const timeline = [];
timeline.push({
type: TobiiCalibrationPlugin,
calibration_points: 9,
});
timeline.push({
type: HtmlKeyboardResponsePlugin,
stimulus: '<p>Look at this stimulus</p>',
extensions: [{ type: TobiiExtension }],
});
jsPsych.run(timeline);Citation
If you use this extension in your research, please cite it. See CITATION.cff.
