pupilio is a lightweight Python SDK for the Pupil.IO eye-trackers developed by Hangzhou Shenning Technology Co., Ltd. It offers a user-friendly interface that covers core eye-tracking functions like data recording, calibration, validation, and real-time access to gaze data. "pupilio" seamlessly integrates with popular platforms such as PsychoPy and PyGame, it enables quick development of eye-tracking studies.
The Pupil.IO eye-tracker
Pupil.IO is a high-speed, high-precision eye-tracking system featuring an all-in-one (AIO) plug-and-play design that is ideal for both scientific research and clinical applications. With minimal setup (just power on and start tracking), it delivers lab-grade accuracy in a compact, user-friendly form factor.
- Precision Tracking: Capture high-frequency eye movement and pupil dynamics with lab-grade accuracy.
- Seamless Compatibility: Native integration with PsychoPy, PyGame, and other Python experimental platforms.
- Multi-Modal Synchronization: Native support for LabStreamingLayer (LSL) to synchronize gaze, pupil dynamics, and event markers with EEG, fNIRS, and EMG via LabRecorder.
- Intuitive Workflow: Simplified calibration, validation, and recording with minimal setup.
Specifications
| Specifications | AIO (Commercial Use) |
PRO (Research) |
DVS-2K¹ (Premier Research) |
|---|---|---|---|
| Sampling Rate | 200 Hz | 200 Hz / 400 Hz | 2000 Hz |
| Tracking Accuracy | 0.5-1.0 deg | 0.3-0.8 deg | 0.3-0.8 deg |
| Spatial Precision² | 0.01/0.07 deg | 0.02/0.09 deg | 0.02 deg |
| System Latency³ | 12.16 ms / SD = 1.22 | 4.91 ms / SD = 1.42 | 2.5 ms |
| Tracking Algorithm | Neural Network | Neural Network | Neural Network |
| Development Support | C++/Python/Matlab | C++/Python/Matlab | C++/Python/Matlab |
| Operating System | Windows 11 | Windows 11 | Windows 11 |
| Head Support | No | No | Yes |
| Head Box⁴ | 28 x 28 cm @ 70 cm | 28 x 28 cm @ 70 cm | - |
| Psychology Experiment Software | PsychoPy/PsychToolBox | PsychoPy/PsychToolBox | PsychoPy/PsychToolBox |
| Research Support | No | Yes | Yes |
1 DVS-2K edition available in Q4 2026. Final specifications subject to change.
2 S2S-RMS, measured using artificial eyes with the filter turned on/off.
3 Measured against an industry-standard eye-tracker operating at 2000 Hz.
4 When operating at 200 Hz and both eyes are reliably tracked at a camera-to-eye distance of 70 cm.
Installation
Currently, all eye trackers shipped with Pupilio are pre-configured with the necessary Pupilio Python packages. If we need to upgrade this package, please enter the following command in the command prompt or PowerShell window:
pip install -U pupilio
Quick Start
Here is a simple example to get started with Pupilio:
# load PyGame library
import pygame
from pygame.locals import FULLSCREEN, HWSURFACE
# initialize PyGame
pygame.init()
# define the scree size
scn_width, scn_height = (1920, 1080)
# set a fullscreen mode with the above size
win = pygame.display.set_mode((scn_width, scn_height), FULLSCREEN|HWSURFACE)
# load Pupilio library
from pupilio import Pupilio
# instantiate a connection to the tracker
pupil_io = Pupilio()
# create a task session, and set a session name.
# The session name must contain only letters, digits or underscores without any special characters.
pupil_io.create_session(session_name="quick_start")
# calibration and validation (recommended)
# set 'validate' to True if we would like to verify the calibration results
pupil_io.calibration_draw(screen=win, validate=True)
# start retrieving gaze
pupil_io.start_sampling()
# hang the main thread for 5 seconds by game
# eye tracking sampling are running on the background thread
pygame.time.wait(5 * 1000)
# stop eye tracking sampling
pupil_io.stop_sampling()
# sleep for 100 ms to capture ending samples
pygame.time.wait(100)
# save eye movement data
pupil_io.save_data("eye_movement.csv")
# release the tracker instance
# clean up Pupilio resources
pupil_io.release()
# quit pygame
pygame.quit()
Multi-Modal Synchronization (LabStreamingLayer)
Pupilio natively supports LabStreamingLayer (LSL) to synchronize eye-tracking data (gaze, pupil diameter, triggers) with EEG, fNIRS, and other biosensors via LabRecorder.
from pupilio import Pupilio, DefaultConfig
config = DefaultConfig()
config.enable_lsl = True
config.lsl_stream_mode = "standard" # 12 channels (or "full" for 39 channels)
pupil_io = Pupilio(config=config)
pupil_io.create_session("eeg_eyetracking_session")
# Start sampling (LSL starts broadcasting automatically)
pupil_io.start_sampling()
# Forward numeric triggers to both LSL continuous Gaze (channel 11) & discrete Markers stream
pupil_io.set_trigger(101)
# Broadcast custom semantic string annotations
pupil_io.send_lsl_marker("STIMULUS_ONSET")
# Stop sampling (LSL stops automatically)
pupil_io.stop_sampling()
pupil_io.release()
For detailed stream specifications and integration with EEGLAB / MNE, see the LabStreamingLayer Integration Guide or GitHub Wiki.
Preprocessing for eye tracking data
Detect fixations and saccades using the I-DT (Identification by Dispersion Threshold) algorithm. The I-DT algorithm identifies fixations as groups of consecutive samples where the dispersion (sum of x and y ranges) remains below a specified threshold for a minimum duration.
Example:
import glob
import os
from pupilio import EventDetection
ed = EventDetection()
out_dir = 'output'
os.makedirs(out_dir, exist_ok=True)
f = open('error.txt', 'w')
for i in glob.glob(r'example.csv'):
try:
ed.detect(i, output_dir=out_dir, which_eye='right')
except Exception as e:
f.write(i + ',' + str(e) + '\n')
f.flush()
Documentation
Comprehensive documentation is available at Pupilio Documentation.
Support
If you encounter any issues or have questions, please open an issue on GitHub or contact zhugc2016@gmail.com.
License
Pupilio is a proprietary software developed by Hangzhou Shenning Technology Co., Ltd. All rights reserved. Unauthorized use, distribution, or modification is prohibited without explicit permission. For licensing inquiries, please contact zhugc2016@gmail.com.
Acknowledgments
Pupilio is developed and maintained by Hangzhou Shenning Technology Co., Ltd. Special thanks to the community for their valuable feedback and support.
Metadata
Release files for pupilio 1.5.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pupilio-1.5.2.tar.gz | 49.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pupilio-1.5.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 98.7 MB
Release files / pupilio-1.5.2.tar.gz
| Download URL | pupilio-1.5.2.tar.gz |
|---|---|
| Size | 49.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
99dcdec425786446e84bde41295eaeb47b49fd066606bc5bbbf6384b58eaf5c3
|
|
BLAKE2b-256 checksum How to use checksums |
84d349279c5686622bc868839b01eab2d032d77738b58504c593829d2d0c9cab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pupilio-1.5.2-py3-none-any.whl
| Download URL | pupilio-1.5.2-py3-none-any.whl |
|---|---|
| Size | 49.4 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8c320f66181e76adb346b3dd4368870a2d09c4161849f4c77a364360b1635511
|
|
BLAKE2b-256 checksum How to use checksums |
4866556dae2884855e38885f5a78aa2c4a86b339c483806a200e62465fbb8b21
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|