py-pupil is a Python GUI and analysis toolkit for estimating mouse pupil size from DeepLabCut (DLC) tracking results. It loads DLC CSV/HDF5 files, fits ellipses to pupil and eye keypoints, detects blinks, performs temporal processing and normalization, and exports analysis-ready time-series data.
The typical workflow is:
- Preprocess eye videos so that the pupil boundary is easy to track.
- Run DeepLabCut and export filtered tracking results as CSV or HDF5.
- Analyze the DLC output with
py-pupil. - Export pupil area, blink masks, normalized traces, metadata, and optional overlay videos.
- Use the exported CSV files for plotting, epoch analysis, peri-event analysis, or downstream statistics.
- Load DeepLabCut CSV and HDF5 outputs with multi-level headers
- Fit ellipses to pupil and eye contour keypoints
- Filter low-confidence points using DLC likelihood values
- Optional video-based edge refinement for pupil boundary detection
- Blink detection, blink masking, interpolation, and temporal smoothing
- Temporal smoothing of ellipse parameters
- Kalman filter
- Independent smoothing
- Moving average
- Pupil area smoothing
- Savitzky-Golay
- Butterworth
- Median
- Gaussian
- Multiple normalization methods
- Raw area
- Eye ratio
- Global z-score
- Baseline z-score
- Percent baseline change
- Min-max scaling
- Robust z-score
- GUI-based analysis with plots and summary statistics
- Batch processing through the Queue tab
- Export to CSV, JSON metadata, blink-event CSV, and pickle (
.pkl) - Overlay video export with pupil ellipse, blink indicators, timestamps, and time-series plots
- Advanced epoch and peri-event analysis
Recommended environment:
- Python 3.10 or later
- Windows, macOS, or Linux
- DeepLabCut tracking output in CSV or HDF5 format
- The original or preprocessed video file, if you want FPS auto-detection, video refinement, or overlay video export
This repository currently does not include packaging metadata such as pyproject.toml, setup.py, or requirements.txt, so install the required packages manually:
pip install numpy pandas scipy pyyaml opencv-python PyQt6 pyqtgraph h5py tablesFor a minimal GUI-only setup:
pip install numpy pandas scipy pyyaml PyQt6 pyqtgraphAdditional notes:
opencv-pythonis required for video loading, image refinement, and overlay video export.tablesis required for reading DLC HDF5 files (.h5,.hdf5).pyqtgraphis required for interactive GUI plots.
git clone https://github.com/mi2e-K/py-pupil.git
cd py-pupil
python -m venv .venvActivate the virtual environment.
Windows PowerShell:
.venv\Scripts\Activate.ps1macOS / Linux:
source .venv/bin/activateInstall dependencies:
pip install --upgrade pip
pip install numpy pandas scipy pyyaml opencv-python PyQt6 pyqtgraph h5py tablesFrom the repository root:
python -m pupil_analysis.gui.appYou can also launch the GUI from Python:
from pupil_analysis.gui import run_gui
run_gui()py-pupil expects standard DeepLabCut output files with a multi-level header containing scorer, bodypart, and coordinate levels.
For most analyses, use the filtered DLC output file, usually named like:
*_filtered.csv
When running DeepLabCut, it is recommended to enable:
Save result(s) as csvFilter predictions
By default, py-pupil expects the following bodypart names.
pupil_Top
pupil_Top-right
pupil_Right
pupil_Bottom-right
pupil_Bottom
pupil_Bottom-left
pupil_Left
pupil_Top-left
eye_Top
eye_Top-right
eye_Right
eye_Bottom-right
eye_Bottom
eye_Bottom-left
eye_Left
eye_Top-left
If these exact names are not found, py-pupil attempts to auto-detect bodyparts that contain pupil or eye in their names. For stable ellipse fitting, label at least four points per contour; eight points per pupil and eye contour are recommended.
-
Launch the GUI:
python -m pupil_analysis.gui.app
-
Open the
Analysistab. -
Select a DLC CSV or HDF5 file.
- Usually, this should be the filtered DLC CSV file.
-
Optionally select the corresponding video file.
- This is used for FPS auto-detection, image refinement, and overlay video export.
-
Check the analysis settings:
- Likelihood threshold
- Blink detection
- Ellipse temporal smoothing
- Interpolation
- Area smoothing
- Baseline duration
- Normalization methods
-
Click
Run Analysis. -
Review the plots, summary, frame counts, valid-frame count, blink count, and pupil-area statistics.
-
Export results with
Export CSV...orExport All....
The Queue tab is designed for processing multiple files.
Typical batch workflow:
- Add one or more DLC CSV/HDF5 files as analysis tasks.
- Review the analysis settings.
- Run the queue to analyze all pending files.
- Save analysis results as
.pklfiles. - Add video export tasks using saved
.pklresults and matching video files. - Run the queue again to create overlay videos.
The queue table shows task name, task type, status, progress, and error messages.
The GUI and exporter can produce the following files.
| File | Description |
|---|---|
*_data.csv |
Frame-by-frame pupil area, normalized traces, quality values, and blink mask |
*_metadata.json |
Analysis summary, statistics, processing notes, blink events, and normalization metadata |
*_blinks.csv |
Detected blink events with frame/time ranges and confidence values |
*.pkl |
Serialized AnalysisResult object for later reuse |
| Overlay video | Video with pupil ellipse, optional eye ellipse, blink indicator, timestamp, and trace plot |
Common CSV columns include:
| Column | Description |
|---|---|
frame_index |
Frame number |
timestamp |
Time in seconds |
pupil_area_raw |
Raw pupil ellipse area |
eye_area_raw |
Raw eye ellipse area |
pupil_area_processed |
Interpolated and/or smoothed pupil area |
eye_area_processed |
Interpolated and/or smoothed eye area |
pupil_eye_ratio |
Pupil area divided by eye area |
pupil_z_global |
Global z-score of pupil area |
pupil_z_baseline |
Baseline-window z-score of pupil area |
pupil_percent_baseline |
Percent change from baseline |
quality |
Frame-level processing quality |
is_blink |
Blink mask; 1 indicates blink/artifact frames |
You can run the analysis without the GUI.
from pupil_analysis.pipeline.analyzer import PupilAnalyzer, AnalysisConfig
from pupil_analysis.pipeline.exporter import ResultExporter
config = AnalysisConfig(
min_likelihood=0.3,
blink_detection=True,
interpolate_blinks=True,
max_interpolation_gap=10,
smooth_data=True,
smoothing_method="savgol",
ellipse_smoothing=True,
ellipse_smoothing_method="kalman",
baseline_seconds=120.0,
normalization_methods=[
"raw",
"eye_ratio",
"z_global",
"z_baseline",
"percent_baseline",
],
)
analyzer = PupilAnalyzer(config=config)
result = analyzer.analyze_from_dlc(
dlc_path="path/to/videoDLC_resnet_filtered.csv",
video_path="path/to/preprocessed_video.avi", # optional
)
exporter = ResultExporter(output_dir="results")
exporter.export(result, basename="sample01")Save and reload an analysis result:
result.save("results/sample01.pkl")
from pupil_analysis.pipeline.analyzer import AnalysisResult
loaded = AnalysisResult.load("results/sample01.pkl")The Advanced Analysis tab provides epoch-based and peri-event analysis tools for an already computed AnalysisResult.
Available analyses include:
- Epoch definition
- baseline
- control
- stimulation
- recovery
- Epoch statistics
- mean
- standard deviation
- SEM
- median
- minimum / maximum
- Change from baseline
- Percent change from baseline
- Peri-event analysis aligned to event times
- Mean trace and SEM across events
Example epoch design:
| Epoch | Time |
|---|---|
| Baseline | 0-120 s |
| Yellow light | 120-180 s |
| Recovery 1 | 180-240 s |
| Blue light | 240-300 s |
| Recovery 2 | 300-360 s |
Overlay video export can add the following elements to the source video:
- Fitted pupil ellipse
- Optional eye ellipse
- Pupil center marker
- Rolling time-series plot
- Current-frame marker on the plot
- Timestamp
- Blink indicator
- Optional captions
Video export requires opencv-python.
pip install opencv-pythonThe input video should be the same video used for DLC tracking or an exactly corresponding preprocessed video. If the crop, rotation, flip, scale, or FPS differs from the DLC input video, the overlay may be misaligned.
DLC tracking quality strongly affects pupil analysis quality.
Recommended preprocessing steps:
- Crop the video so that the eye remains inside the region of interest across all frames.
- Use horizontal flip if needed to keep orientation consistent across sessions.
- Rotate the video so that the eye is approximately horizontal.
- Adjust brightness and contrast so that the pupil and eye boundary are clear.
- Use moderate sharpening only when it improves boundary visibility.
- Avoid excessive denoising or contrast enhancement that destroys the pupil boundary.
- If upscaling is useful, use a consistent scale factor such as 4x.
- Use DLC filtered predictions for downstream pupil analysis.
Make sure PyQt6 and pyqtgraph are installed:
pip install PyQt6 pyqtgraphRun the command from the repository root:
python -m pupil_analysis.gui.appRun scripts from the repository root, or add the repository path to PYTHONPATH.
Windows PowerShell:
$env:PYTHONPATH = (Get-Location)macOS / Linux:
export PYTHONPATH=$(pwd)Install tables:
pip install tablesInstall OpenCV:
pip install opencv-pythonAlso confirm that the selected video corresponds to the DLC tracking file.
Check the following:
- You are using the DLC filtered CSV/HDF5 output.
- Pupil bodypart names contain
pupil, or match the expected default names. - There are enough valid keypoints for ellipse fitting.
- The likelihood threshold is not too high.
- The pupil boundary is visible in the video.
- Video preprocessing did not blur or saturate the pupil boundary.
Use the same video that was used for DLC analysis. If DLC was run on a cropped, rotated, flipped, resized, or otherwise preprocessed video, use that same video for overlay export.
pupil_analysis/
core/ # Data classes and exceptions
config/ # Dataclass-based settings and YAML support
io/ # DLC CSV/HDF5 and video input/output
geometry/ # Ellipse fitting
refinement/ # Video-based edge refinement
temporal/ # Blink detection, interpolation, smoothing
normalization/ # Normalization methods and pipeline
pipeline/ # PupilAnalyzer and result exporters
gui/ # PyQt6 GUI, queue, video export, advanced analysis
This project is licensed under the MIT License. See LICENSE for details.
If you use this tool in published work, please acknowledge both DeepLabCut and this repository.