Dual-kernel pupil deconvolution for attentional pulse estimation
Project description
pupildeconvolve
Dual-kernel pupil deconvolution for estimating attentional pulse dynamics from pupil-size recordings.
Overview
pupildeconvolve is a Python package for modeling pupil responses using a dual-kernel deconvolution framework inspired by pupil deconvolution approaches in cognitive neuroscience.
The package estimates:
- attentional pulse amplitudes
- slow drift/slope components
- participant-level attentional profiles
The package is designed primarily for:
- cognitive neuroscience
- attention research
- emotional face processing
- attentional blink experiments
- Faced Paced Stimuli Presenttaion like RSVP, Video
- pupillometry experiments
Key Features
- Dual-kernel pupil modeling
- Participant-wise averaging before fitting
- Attention pulse estimation
- PLR (pupillary light reflex) modeling
- Drift/slope estimation
- Confidence interval plotting
- Multi-participant support
- DataFrame-based workflow
- Synthetic data simulation support
- Compatible with DataMatrix workflows
Installation
Local editable installation
Clone the repository:
git clone https://github.com/YOUR_USERNAME/pupildeconvolve.git
Move into the repository:
cd pupildeconvolve
Install locally:
pip install -e .
Dependencies
The package depends on:
- numpy
- pandas
- scipy
- matplotlib
- tqdm
These are installed automatically.
Basic Workflow
The recommended workflow is:
Trials
→ Participant average
→ Dual-kernel fitting
→ Attention pulse estimation
→ Group plotting
The package intentionally performs:
average first
fit second
instead of:
fit each trial separately
average afterward
because participant-level averaging produces:
- more stable fits
- reduced noise
Quick Start
Step 1 — Import
import numpy as np
import pandas as pd
from pupildeconvolve import (
fit_dataframe,
plot_pupil_and_pulses
)
Step 2 — Create a DataFrame
The package expects:
- one row = one trial
- timepoints as columns
- participant column
Example:
rows = []
for trial in range(20):
row = {}
row["participant"] = "P1"
for t in range(200):
row[t] = np.random.randn()
rows.append(row)
df = pd.DataFrame(rows)
Define pupil columns:
pupil_cols = list(range(200))
Step 3 — Fit the model
res_df = fit_dataframe(
df,
pupil_cols=pupil_cols,
participant_col="participant",
sampling_rate=100,
pulse_interval=150,
n_runs=10
)
Step 4 — View results
print(res_df.head())
Output columns:
| Column | Description |
|---|---|
| participant | participant ID |
| slope | slow drift estimate |
| plr_latency_ms | estimated PLR latency |
| Pulse1...PulseN | attentional pulse amplitudes |
Plotting
Example
plot_pupil_and_pulses(
pupil=pupil_matrix,
result={
"attention_amplitude": attention_matrix,
"attention_time": attention_time
},
time=time
)
The plotting function computes:
- grand mean
- confidence intervals
- participant-level averaging
for both:
- pupil traces
- attentional pulses
DataFrame API
fit_dataframe()
fit_dataframe(
df,
pupil_cols,
participant_col,
condition_col=None,
sampling_rate=100,
pulse_interval=150,
pulse_times=None,
save_csv=False,
output_path="results.csv",
show_progress=True,
verbose=True,
n_runs=1
)
Parameters
df
Pandas DataFrame containing trial-wise pupil recordings.
pupil_cols
List of columns containing pupil timepoints.
Example:
pupil_cols = list(range(243))
participant_col
Column containing participant IDs.
Example:
participant_col="participant"
condition_col
Optional condition column.
Example:
condition_col="Condition"
If provided:
- fitting occurs separately for each condition
- output contains one row per participant × condition
sampling_rate
Sampling rate in Hz.
Example:
sampling_rate=100
pulse_interval
Spacing between attentional pulses in milliseconds.
Example:
pulse_interval=150
pulse_times
Optional custom pulse times.
Example:
pulse_times=[0,100,400,700]
If omitted:
regular pulse spacing is generated automatically.
n_runs
Number of optimization restarts.
Higher values:
- improve stability
- increase runtime
Recommended:
| Dataset size | Recommended n_runs |
|---|---|
| small | 30-50 |
| publication-quality | 50-100 |
Core Model
The model contains:
1. PLR kernel
Models early constriction dynamics.
2. Attention kernel
Models slower attentional recruitment.
3. Drift/slope term
Models slow pupil drift.
Optimization
The package uses:
L-BFGS-B optimization
with:
- bounded optimization
- multiple restarts
- participant-level averaging
Important Modeling Choice
The package intentionally uses:
participant-average fitting
instead of:
trial-wise fitting
because trial-wise deconvolution produced:
- unstable late pulses
- noisy pulse estimates
- unrealistic optimization collapse
- poor identifiability
Participant averaging substantially improves:
- robustness
- physiological interpretability
- stability of attentional profiles
Handling Different Recording Lengths
Participants may have:
- different recording durations
- different trial lengths
- missing tails
The package handles this automatically using:
NaN padding
and:
np.nanmean()
during participant averaging.
Missing segments are not treated as zero.
Working with DataMatrix
Example:
from datamatrix import io
Load:
dm = io.readbin("participant.dm")
Extract pupil matrix:
pupil = np.asarray(dm["ptrace_RSVP"], dtype=float)
Convert to DataFrame:
rows = []
for i in range(len(dm)):
row = {}
row["participant"] = "P1"
for t in range(pupil.shape[1]):
row[t] = pupil[i, t]
rows.append(row)
df = pd.DataFrame(rows)
Then run:
fit_dataframe(...)
Example Scripts
The repository contains:
| File | Description |
|---|---|
| examples/basic_usage.py | synthetic dataset example |
| examples/test_run.py | DataMatrix Workflow |
| tests/test_api.py | API tests |
Running Tests
Install pytest:
pip install pytest
Run:
pytest
Example Output
Typical outputs include:
- participant-wise pulse amplitudes
- condition-level attentional dynamics
- grand-average pupil traces
- confidence intervals
Citation
If you use this package in research, please cite:
@software{maity2026pupildeconvolve, author = {Sangramjit Maity}, title = {pupildeconvolve}, year = {2026} }
License
MIT License.
Author
Sangramjit Maity
Cognitive Neuroscience / Computational Modeling
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pupildeconvolve-1.0.tar.gz.
File metadata
- Download URL: pupildeconvolve-1.0.tar.gz
- Upload date:
- Size: 13.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e1fb02c64ba6dff29a19c94512354e5928ac7a8aaab8f4c2446a7224af7f121
|
|
| MD5 |
fab551419eacfdbf7e2e8b5ad531f101
|
|
| BLAKE2b-256 |
4234dc49382dc49f6fca01cf20aab978829b8fb56c082a5bd3b684ceb534fc77
|
File details
Details for the file pupildeconvolve-1.0-py3-none-any.whl.
File metadata
- Download URL: pupildeconvolve-1.0-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28f00a8f59ed530f93c43267f4a368c7366991f65031ebf66edde4d427479ee1
|
|
| MD5 |
552b19c1520741d85c4e380fc1f3617b
|
|
| BLAKE2b-256 |
cfacd39862ce7a8ebf20084cf244996b58a654b330d9b446f7c75e92c995126d
|