Skip to main content

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} }


Attentional Pulse Example

License

MIT License.


Author

Sangramjit Maity

Cognitive Neuroscience / Computational Modeling

Project details


Release history Release notifications | RSS feed

This version

1.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pupildeconvolve-1.0.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pupildeconvolve-1.0-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

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

Hashes for pupildeconvolve-1.0.tar.gz
Algorithm Hash digest
SHA256 4e1fb02c64ba6dff29a19c94512354e5928ac7a8aaab8f4c2446a7224af7f121
MD5 fab551419eacfdbf7e2e8b5ad531f101
BLAKE2b-256 4234dc49382dc49f6fca01cf20aab978829b8fb56c082a5bd3b684ceb534fc77

See more details on using hashes here.

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

Hashes for pupildeconvolve-1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 28f00a8f59ed530f93c43267f4a368c7366991f65031ebf66edde4d427479ee1
MD5 552b19c1520741d85c4e380fc1f3617b
BLAKE2b-256 cfacd39862ce7a8ebf20084cf244996b58a654b330d9b446f7c75e92c995126d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page