Times, distances and angles can carry units, either from the pypillometry.u
namespace (3*u.min, (-200,800)*u.ms, 60*u.cm,
20*u.deg) or as strings ("3min", "60cm", "20deg").
Class for handling eye-tracking data. This class is a subclass of
GazeData and PupilData
and inherits all their methods and attributes. In addition to the
methods in GazeData which implement functions for eye-tracking data and
those in PupilData for pupillometric data, EyeData provides methods
that need both gaze and pupil data (e.g., foreshortening correction).
time (ndarray) – timing array (in ms) or None, in which case the time-array goes from [0,maxT]
using sampling_rate
left_x (ndarray) – data from left eye (at least one of the eyes must be provided, both x and y)
pupil is optional
left_y (ndarray) – data from left eye (at least one of the eyes must be provided, both x and y)
pupil is optional
left_pupil (ndarray) – data from left eye (at least one of the eyes must be provided, both x and y)
pupil is optional
right_x (ndarray) – data from right eye (at least one of the eyes must be provided, both x and y)
pupil is optional
right_y (ndarray) – data from right eye (at least one of the eyes must be provided, both x and y)
pupil is optional
right_pupil (ndarray) – data from right eye (at least one of the eyes must be provided, both x and y)
pupil is optional
event_onsets (ndarray) – time-onsets of any events in the data (in ms, matched in time vector)
event_labels (ndarray) – for each event in event_onsets, provide a label
sampling_rate (float) – sampling-rate of the signal in Hz; if None, it is estimated from
the median difference in time (either time or sampling_rate
must be provided)
experimental_setup (Optional[ExperimentalSetup]) – Geometric model of the experimental setup including screen geometry,
eye position, camera position, and screen orientation.
name (str) – name of the dataset or None (in which case a random string is selected)
calibration (Optional[Dict[str, SpatialCalibration]]) – Dictionary of SpatialCalibration objects, one per eye (keys: ‘left’, ‘right’)
fill_time_discontinuities (bool) – sometimes, when the eyetracker loses signal, no entry in the EDF is made;
when this option is True, such entries will be made and the signal set to 0 there
(or do it later using fill_time_discontinuities())
keep_orig (bool) – keep a copy of the original dataset? If True, a copy of the object
as initiated in the constructor is stored in member original
info (dict) – optional dictionary with additional information about the dataset
(stored in member info)
inplace (Optional[bool]) – default for methods called with inplace=None: if True, they modify the
object in place; if False, they return a modified copy; if None (default),
use the package-level setting (see set_default_inplace(),
initially True). The method-level inplace argument overrides this.
Correct pupil data using a simple algorithm to correct for foreshortening effects.
Correct the pupil data for foreshortening effects caused
by saccades/eye movements. This method is based on a simple algorithm
that assumes the pupil appears perfectly circular when fixating midpoint:
for each sample, the distance \(\Delta\) (in mm) of the gaze position
from midpoint is computed and the pupil signal is multiplied by the
correction factor \(\sqrt{1+\Delta^2/d^2}\), where \(d\) is the
eye-to-screen distance from the experimental setup.
For a more complete model that also estimates the camera position,
see fit_foreshortening().
[ ] TODO: when using interpolated pupil data, x/y data may still be missing. Make sure that the
pupil data is not touched where x/y is missing
Parameters:
eyes (list) – Which eyes to correct. If empty, correct all available eyes.
midpoint (tuple or None) – The center of the screen (x,y) in pixels where it is assumed that the pupil is completely circular.
If None, the midpoint is taken to be the center of the screen as registered
in the experimental_setup.
store_as (str) – name of the variable in which to store the corrected pupil data
(as data[eye,store_as]); the default “pupil” replaces the
original pupil data
inplace (bool or None) – Whether to modify the object in place or return a new object.
true: modify in place
false: return a new object
None: use the object’s default setting (initialized in __init__)
Fit foreshortening correction model to estimate camera geometry and true pupil size.
This method implements Stage 1 of the foreshortening correction algorithm,
which jointly estimates the camera position (theta, phi) and the temporal
dynamics of true pupil size A0(t) using B-splines. The data is automatically
preprocessed (filtered and downsampled) before fitting.
Parameters:
eye (str) – Which eye to fit (‘left’ or ‘right’)
r (Union[float, str, None]) –
Eye-to-camera distance. If not provided, uses the
r from experimental_setup.
Plain number: assumed to be mm (with warning)
String: e.g., “600 mm”, “60 cm”
Quantity: e.g., 600 * u.mm
d (Union[float, str, None]) –
Eye-to-screen distance. If not provided, uses the
d from experimental_setup.
Plain number: assumed to be mm (with warning)
String: e.g., “700 mm”, “70 cm”
Quantity: e.g., 700 * u.mm
intervals (Optional[Intervals]) – Time intervals to use for fitting. If None, uses all available data.
Useful for fitting only on calibration periods. Intervals in any
time units or in sample indices (units=None) are accepted; a
plain list of (start, end) tuples is taken as ms.
target_fs (float) – Target sampling rate in Hz after downsampling for efficiency.
Pupil dynamics are typically well-preserved at 50 Hz.
lowpass_freq (float) – Lowpass filter cutoff frequency in Hz. Removes high-frequency noise
before downsampling. Should be below target_fs/2 (Nyquist).
lambda_smooth (float) – Smoothness regularization weight. Higher values produce smoother
A0(t) estimates. Tune via cross-validation if needed.
knots_per_second (float) – Number of B-spline knots per second. Controls temporal resolution
of A0(t) model. Typical values: 0.5-2.0.
initial_theta (Union[float, str, None]) –
Initial guess for camera polar angle. If None, uses
pi/2 (horizontal) as starting point.
Plain number: assumed to be radians (with warning)
String: e.g., “20 degrees”, “0.349 radians”
Quantity: e.g., 20 * u.deg
initial_phi (Union[float, str, None]) –
Initial guess for camera azimuthal angle. If None,
uses 0 (camera on x-axis) as starting point.
Plain number: assumed to be radians (with warning)
String: e.g., “-90 degrees”, “-1.57 radians”
Quantity: e.g., -90 * u.deg
verbose (bool) – Print optimization progress and fit statistics.
Returns:
calibration – Fitted calibration object containing camera geometry (theta, phi),
spline coefficients for A0(t), and fit quality metrics.
Return type:
ForeshorteningCalibration
Raises:
ValueError – If specified eye doesn’t exist or lacks gaze/pupil data, if the
experimental setup is not set or lacks required information, if
lowpass_freq is not below the Nyquist frequency or if fewer
than 100 valid samples are available.
time (ndarray) – timing array (in ms) or None, in which case the time-array goes from [0,maxT]
using sampling_rate
left_pupil (ndarray) – data from left eye (at least one of the eyes must be provided)
right_pupil (ndarray) – data from right eye (at least one of the eyes must be provided)
event_onsets (ndarray) – time-onsets of any events in the data (in ms, matched in time vector)
event_labels (ndarray) – for each event in event_onsets, provide a label
sampling_rate (float) – sampling-rate of the signal in Hz; if None, it is estimated from
the median difference in time (either time or sampling_rate
must be provided)
name (str) – name of the dataset or None (in which case a random string is selected)
fill_time_discontinuities (bool) – sometimes, when the eyetracker loses signal, no entry in the EDF is made;
when this option is True, such entries will be made and the signal set to 0 there
(or do it later using fill_time_discontinuities())
keep_orig (bool) – keep a copy of the original dataset? If True, a copy of the object
as initiated in the constructor is stored in member original
info (dict) – optional dictionary with additional information about the dataset
(stored in member info)
inplace (Optional[bool]) – default for methods called with inplace=None: if True, they modify the
object in place; if False, they return a modified copy; if None (default),
use the package-level setting (see set_default_inplace(),
initially True). The method-level inplace argument overrides this.
Detect blinks in the pupillary signal using several strategies.
First, blinks are detected as consecutive sequence of blink_val
(f.eks., 0 or NaN). Second, blinks are defined as everything between
two crossings of the velocity profile (from negative to positive).
Detected blinks are always stored in the object (retrieve them with
get_blinks()). When apply_mask=True,
the blinks are also applied as masks to the data. When apply_mask=False
(default), the detected blinks are returned as Intervals objects.
Finally, detected blinks have to be at least min_duration ms.
Parameters:
eyes (list) – list of eyes to process; if empty, all available eyes are processed
min_duration (float) – minimum duration (in ms, or with units) for a sequence of missing numbers to be treated as blink
blink_val (float) – “missing value” code for the “zero” strategy. Missing samples
(NaN) are always detected; samples equal to blink_val (default
0) are detected in addition. Use np.nan to detect only NaN
(e.g., for baseline-corrected data where 0 is a valid value).
The “zero” strategy always uses the raw data, so regions masked
for other reasons are not detected as blinks.
winsize (float) – window-size for Savitzky-Golay velocity estimation (in ms, or with units)
vel_onset (float or str) –
velocity threshold to detect blink onset (negative value).
If float: threshold in pupil-units per millisecond (e.g., -5.0)
If str: percentile of velocity distribution (e.g., “5%” for bottom 5%)
vel_offset (float or str) –
velocity threshold to detect blink offset (positive value).
If float: threshold in pupil-units per millisecond (e.g., 5.0)
If str: percentile of velocity distribution (e.g., “95%” for top 5%)
vel_onset_min_duration (float) – minimum duration (in ms, or with units) that velocity must exceed threshold to detect as onset
(to avoid noise-induced false detections)
vel_offset_min_duration (float) – minimum duration (in ms, or with units) that velocity must exceed threshold to detect as offset
(to avoid noise-induced false detections)
max_duration (float) – maximum duration (in ms, or with units) of a blink detected by the
“velocity” strategy; an onset without an offset within this time
is dropped. None means no limit. Does not apply to the “zero”
strategy.
strategies (list) – list of strategies to use;
so far, use a list containing any combination of “zero” and “velocity”
apply_mask (bool) – if True, apply detected blinks as masks to the data and return the object
if False (default), return detected blinks as Intervals (or dict of Intervals)
ignore_existing_mask (bool) – if True, use raw data ignoring existing masks
if False (default), only detect blinks in non-masked data (already masked regions are skipped)
inplace (bool or None) – if True, make change in-place and return the object
if False, make and return copy before making changes
if None, use the object-level setting
Returns:
If apply_mask=True: returns the object (for chaining)
If apply_mask=False and single eye: returns Intervals object
If apply_mask=False and multiple eyes: returns dict of Intervals objects
(keys like "left_pupil")
The blinks to interpolate are taken from the blinks stored in the object,
so blinks have to be detected first (e.g., using pupil_blinks_detect()).
The on- and offsets of each blink are refined using the velocity profile
before interpolating. Blinks that are so close that the anchor points
of one fall into the other are merged and interpolated together.
Interpolated samples remain masked; the
interpolated blinks can be retrieved with
get_interpolated_blinks().
This procedure relies heavily on eye-balling (reconstructing visually convincing signal),
so it can help to inspect the result visually (e.g., using
plot_blinks()) to set
good parameter values for winsize, vel_onset, vel_offset and margin
(see paper linked above).
Parameters:
eyes (str | list) – str or list of eyes to process; if empty, all available eyes are processed
store_as (str) – how to store the interpolated data; either “pupil” (default) which replaces
the original pupil data or a string that will be used as the new variable
name in the data (e.g., “pupilinterp”)
method (str) – method to use; so far, only “mahot” is implemented
winsize (float) – size of the Savitzky-Golay window (in ms, or with units)
vel_onset (float or str) –
velocity threshold to detect blink onset (negative value).
If float: threshold in pupil-units per millisecond (e.g., -5.0)
If str: percentile of velocity distribution (e.g., “5%” for bottom 5%)
vel_offset (float or str) –
velocity threshold to detect blink offset (positive value).
If float: threshold in pupil-units per millisecond (e.g., 5.0)
If str: percentile of velocity distribution (e.g., “95%” for top 5%)
margin (Tuple[float, float]) – margin that is subtracted/added to onset and offset (in ms, or
with units, e.g. (10,30)*u.ms)
blinkwindow (float) – how much time before and after each blink to include (in ms, or
with units)
interp_type (str) – type of interpolation accepted by scipy.interpolate.interp1d()
inplace (bool or None) – if True, make change in-place and return the object
if False, make and return copy before making changes
if None, use the object-level setting
eyes (list or str) – str or list of eyes to process; if empty, all available eyes are processed
variable (str) – default is to use the “pupil” but it could be used to process, e.g.,
interpolated pupil data stored in a different variables, e.g., “pupilinterp”
inplace (bool or None) – if True, make change in-place and return the object
if False, make and return copy before making changes
if None, use the object-level setting
Estimate pupil-response based on event-onsets, see
pupil_response().
If a baseline has been estimated (see pupil_estimate_baseline()),
it is subtracted from the pupil signal before estimating the response;
otherwise, a baseline of zero is used.
Parameters:
eyes (list or str) – str or list of eyes to process; if empty, all available eyes are processed
npar (str | float) – npar-parameter for the canonical response-function or “free”;
in case of “free”, the function optimizes for this parameter
tmax (str | float) – tmax-parameter for the canonical response-function or “free”;
in case of “free”, the function optimizes for this parameter
bounds (dict) – in case that one or both parameters are estimated, give the lower
and upper bounds for the parameters
inplace (bool or None) – if True, make change in-place and return the object
if False, make and return copy before making changes
if None, use the object-level setting
The predicted response is stored in data[eye,"response"]; the
estimated parameters (npar, tmax, the coefficients coef and the
bounds) are stored in params["response"][eye].
Lowpass-filter pupil signal using a Butterworth-filter.
Uses an iterative approach to handle NaN/masked values properly,
preventing NaN propagation through the filter
(see lowpass_filter_iterative()).
The filtered signal replaces the pupil data; the mask is preserved.
Parameters:
cutoff (float) – lowpass-filter cutoff frequency in Hz
order (int) – filter order
eyes (list) – list of eyes to filter; if empty, all available eyes are filtered
inplace (bool or None) – if True, make change in-place and return the object
if False, make and return copy before making changes
if None, use the object-level setting
Merge pupil data from both eyes into a single “merged” variable.
This method combines left and right pupil signals, handling missing data
(masked values) intelligently. Where both eyes are valid, the signals are
averaged to reduce noise. Where only one eye is valid, that eye’s data is
used (with offset correction if applicable).
Parameters:
method (str) –
Method for merging the two eyes. Options:
”local_offset” (default): Compute a slowly-varying offset between eyes
using lowpass filtering. This handles drift over the session. The right
eye is shifted to match the left eye’s level before merging.
”offset”: Use a single global offset (mean difference) computed over
the entire signal where both eyes are valid.
”both_available”: Only use data where both eyes are valid (take mean).
Timepoints where only one eye is valid remain masked.
# TODO: Implement “signal_quality” method that weights eyes by their
# local signal quality (SNR), giving more weight to the cleaner eye.
lowpass_cutoff (float) – Cutoff frequency (Hz) for the lowpass filter used in “local_offset” method.
Lower values produce a more stable offset that only tracks very slow drift.
Default is 0.2 Hz (~5 second time constant).
max_iter (int) – Maximum iterations for iterative lowpass filtering in “local_offset” method.
Default is 10.
keep_eyes (bool) – If True (default), keep the original left/right pupil data.
If False, remove the original eye data after merging.
inplace (bool | None) – If True, modify in-place. If False, return a copy.
If None, use the object’s default setting.
Returns:
The object with merged pupil data stored as “merged_pupil”.
ValueError – If only one eye is available (nothing to merge).
If an unknown method is specified.
Notes
The merged signal is stored as “merged_pupil” and can be accessed via
data[“merged”, “pupil”] or data[“merged_pupil”].
The mask for the merged signal reflects which timepoints have valid data:
- For “local_offset” and “offset”: masked only where BOTH eyes are masked
- For “both_available”: masked where EITHER eye is masked
Masked samples still hold the merged stored values (e.g., interpolated
blinks), computed as for valid samples (NaN only if both eyes are NaN).
The “local_offset” method is recommended for most use cases as it:
1. Uses all available data (doesn’t discard single-eye timepoints)
2. Handles session-long drift in the inter-ocular difference
3. Produces smooth transitions at boundaries between single/both-eye regions
Examples
>>> # Default: local offset correction>>> data.pupil_merge_eyes()>>> merged=data["merged","pupil"]
>>> # Use global offset (simpler, assumes no drift)>>> data.pupil_merge_eyes(method="offset")
>>> # Only use timepoints where both eyes are valid>>> data.pupil_merge_eyes(method="both_available")
>>> # Remove original eye data after merging>>> data.pupil_merge_eyes(keep_eyes=False)
See also
merge_eyes
Generic merge method in GenericEyeData (masks if all eyes invalid)
Apply smoothing of the signal using a moving window.
See smooth_window().
The smoothed signal replaces the pupil data; the mask is preserved.
Parameters:
eyes (list) – list of eyes to smooth; if empty, all available eyes are smoothed
window (str) – (the type of window from ‘flat’, ‘hanning’, ‘hamming’, ‘bartlett’, ‘blackman’);
flat window will produce a moving average smoothing.
winsize (float) – the length of the window in ms (or with units, e.g. "20ms")
inplace (bool or None) – if True, make change in-place and return the object
if False, make and return copy before making changes
if None, use the object-level setting
time (ndarray) – timing array (in ms) or None, in which case the time-array goes from [0,maxT]
using sampling_rate
left_x (ndarray) – data from left eye (at least one of the eyes must be provided, both x and y)
left_y (ndarray) – data from left eye (at least one of the eyes must be provided, both x and y)
right_x (ndarray) – data from right eye (at least one of the eyes must be provided, both x and y)
right_y (ndarray) – data from right eye (at least one of the eyes must be provided, both x and y)
event_onsets (ndarray) – time-onsets of any events in the data (in ms, matched in time vector)
event_labels (ndarray) – for each event in event_onsets, provide a label
sampling_rate (float) – sampling-rate of the signal in Hz; if None, it is estimated from
the median difference in time (either time or sampling_rate
must be provided)
experimental_setup (Optional[ExperimentalSetup]) – Geometric model of the experimental setup including screen geometry,
eye position, camera position, and screen orientation.
name (str) – name of the dataset or None (in which case a random string is selected)
calibration (Optional[Dict[str, SpatialCalibration]]) – Dictionary of SpatialCalibration objects, one per eye (keys: ‘left’, ‘right’)
fill_time_discontinuities (bool) – sometimes, when the eyetracker loses signal, no entry in the EDF is made;
when this option is True, such entries will be made and the signal set to 0 there
(or do it later using fill_time_discontinuities())
keep_orig (bool) – keep a copy of the original dataset? If True, a copy of the object
as initiated in the constructor is stored in member original
info (dict) – optional dictionary with additional information about the dataset
(stored in member info)
inplace (Optional[bool]) – default for methods called with inplace=None: if True, they modify the
object in place; if False, they return a modified copy; if None (default),
use the package-level setting (see set_default_inplace(),
initially True). The method-level inplace argument overrides this.
Calculate Euclidean distance between left and right eye coordinates and detect divergences.
This method computes the distance between corresponding (x,y) coordinates in the left
and right eyes. Points where the distance exceeds a threshold are detected as divergences.
When apply_mask=True, these points are masked. When apply_mask=False, the divergences
are returned as Intervals objects.
Parameters:
threshold (float) – If thr_type is “percentile”: percentile value (0-1) for threshold calculation.
If thr_type is “pixel”: maximum allowed distance in pixels.
thr_type (str) –
Type of threshold to apply:
”percentile”: threshold is calculated as the given percentile of the distance distribution
”pixel”: threshold is the maximum allowed distance in pixels
store_as (str | None) – Variable name to store the distance timeseries. If None, distance is not stored.
apply_mask (bool) – If True, apply detected divergences as masks to the data and return self.
If False, return detected divergences as an Intervals object.
ignore_existing_mask (bool) – If True (default), check all data points including those already masked (e.g., from blinks).
If False, only check non-masked data points for divergences.
inplace (bool or None) – If True, make change in-place and return the object.
If False, make and return copy before making changes.
If None, use the object-level setting.
Returns:
If apply_mask=True: returns the object for chaining.
If apply_mask=False: returns Intervals object containing detected divergence intervals.
Detect and mask gaze coordinates that fall outside the screen boundaries.
This method identifies points where the (x,y) coordinates fall outside the
defined screen limits. When apply_mask=True, these points are masked.
When apply_mask=False, the offscreen periods are returned as Intervals objects.
Parameters:
eyes (str | list) – Eye(s) to check for offscreen coordinates. If empty, checks all available eyes.
Can be a single eye name (e.g., “left”) or a list (e.g., [“left”, “right”]).
apply_mask (bool) – If True, apply detected offscreen periods as masks to the data and return self.
If False, return detected offscreen periods as dict of Intervals objects.
ignore_existing_mask (bool) – If False (default), only check non-masked data points for offscreen coordinates.
If True, check all data points including those already masked (e.g., from blinks).
inplace (bool or None) – If True, make change in-place and return the object.
If False, make and return copy before making changes.
If None, use the object-level setting.
Returns:
If apply_mask=True: returns self for chaining.
If apply_mask=False: returns dict of Intervals objects (one per eye) containing
detected offscreen intervals.
Set or update the experimental setup geometry (in-place).
Creates a new ExperimentalSetup or updates the
existing one with the provided parameters (parameters that are not
given are taken from the existing setup). All parameters are passed
through to the ExperimentalSetup constructor.
Parameters:
**kwargs (dict) –
Any parameters accepted by ExperimentalSetup:
screen_resolution: tuple (width, height) in pixels
physical_screen_size: tuple (width, height) with units
eye_to_screen_center: distance from the eye to the screen center
screen_offset: tuple (delta_x, delta_y) - offset of screen center from eye
screen_pitch: tilt angle (alpha_tilt)
screen_yaw: tilt angle (beta_tilt)
camera_offset: tuple (x, y, z) in eye-centric frame
Class for plotting combined gaze and pupil data. It provides all methods of
GazePlotter and PupilPlotter
and additional plots that combine gaze and pupil data.
It is usually not created directly; instead, it is available as the plot
attribute of an EyeData object, e.g.
d.plot.plot_pupil_foreshortening_error_surface().
Parameters:
obj (GenericEyeData) – the data object to plot (stored as obj)
Plot spatial calibration data for one or more eyes in subplots.
Creates a figure with subplots for each eye and calls the plot() method
on each SpatialCalibration object to show calibration accuracy with
target points (black X), measured points (dark blue +), and optional
interpolated error surface.
Parameters:
eyes (Union[str, list, None]) – Which eye(s) to plot. If None or empty list, plots all available eyes.
Can be a single eye name (e.g., ‘left’) or list of eye names (e.g., [‘left’, ‘right’]).
show_surface (bool) – If True, show interpolated error surface as background.
If False, show only the calibration points.
interpolation (str) – Interpolation method for surface (only used if show_surface=True).
Options: ‘rbf’, ‘linear’, ‘cubic’, ‘nearest’
figsize (tuple) – Figure size per subplot (width, height) in inches.
Returns:
fig (matplotlib.figure.Figure) – The figure object
axes (list or matplotlib.axes.Axes) – List of axis objects (or single axis if only one eye)
Raises:
ValueError – If no calibration data is available
Examples
>>> importpypillometryaspp>>> data=pp.EyeData.from_eyelink('data.edf')>>> # Plot all eyes with surface>>> fig,axes=data.plot.plot_calibration()>>>>>> # Plot only left eye without surface>>> fig,ax=data.plot.plot_calibration(eyes='left',show_surface=False)>>>>>> # Plot specific eyes>>> fig,axes=data.plot.plot_calibration(eyes=['left','right'])
Plot visualization of eye-tracking experimental setup geometry.
Shows the spatial relationship between eye, camera, and screen using
the experimental parameters stored in the EyeData object. Delegates
to ExperimentalSetup.plot().
Parameters:
theta (Optional[float]) – Camera polar angle; a float is interpreted as radians, a string
can carry units (e.g., “20 deg”). If None, uses calibration’s theta
(if calibration is given), else setup’s theta.
phi (Optional[float]) – Camera azimuthal angle; a float is interpreted as radians, a string
can carry units (e.g., “-90 deg”). If None, uses calibration’s phi
(if calibration is given), else setup’s phi.
show_gaze_samples (bool) – Show sample gaze vectors to screen positions
n_gaze_samples (int) – Number of sample gaze positions
ax (Optional[Axes]) – Existing axis to plot on (only for ‘3d’ projection)
viewing_angle (tuple) – Viewing angle for 3D projection (elev, azim) or (elev, azim, roll).
Plain numbers are in degrees (as in matplotlib’s view_init);
strings with units (e.g., ("30deg","-60deg")) are parsed.
projection (str) – ‘2d’ for three orthogonal views, ‘3d’ for interactive 3D view
Return type:
tuple
Returns:
fig (matplotlib Figure)
ax (matplotlib axis or array of axes)
Raises:
ValueError – if the data object has no experimental_setup
Examples
>>> # Use camera geometry from setup>>> data.plot.plot_experimental_setup()>>>>>> # Use fitted angles from calibration>>> calib=data.fit_foreshortening(eye='left')>>> data.plot.plot_experimental_setup(calibration=calib)>>>>>> # Override angles>>> data.plot.plot_experimental_setup(theta=np.radians(20),phi=np.radians(-90))
Plot EyeData as a heatmap. Typically used for a large amount of data
to spot the most frequent locations.
To plot a scanpath, use plot_scanpath() instead.
Each eye is plotted in a separate subplot of the current figure
(a new figure is created if none exists); the colorbar shows the
number of samples per bin.
Parameters:
plot_range (tuple) – The time range to plot (in units, or with units, e.g.
(3,5)*u.min). Default is (-np.inf, +np.inf), i.e. all data.
eyes (list) – The eyes to plot. Default is [], which means all available data (“left”, “right”,
average, regression, …)
show_screen (bool) – Whether to plot the screen limits (if an experimental setup is
available). Default is True.
show_masked (bool) – Whether to plot the masked data (because of blinks, artifacts, …). Default is False.
rois (List[ROI]) – List of ROIs (ROI) to plot. Default is None.
roi_style (dict) –
Style for the ROIs, passed as keyword arguments to the ROIs’
plot() method. Default is {} (ROI defaults). Example:
units (str) – The units of plot_range (“ms”, “sec”, “min”, “h”). Default is “sec”.
cmap (str) – The colormap to use. Default is “jet”.
gridsize (int | str) – The gridsize for the hexbin plot or histogram. If “auto”, the square
root of the number of samples in plot_range is used. Default is 30.
min_samples (Optional[int]) – Minimum number of samples required in a bin to display it. Bins with
fewer samples will not be shown. If None, automatically calculates a
threshold at the 10th percentile of bin counts. Default is 1.
smooth (Optional[float]) – If provided, applies Gaussian smoothing to the binned histogram. The value
is the sigma of the Gaussian kernel in bin units (e.g., smooth=1 applies
minimal smoothing with a 1-bin sigma, smooth=2 applies more smoothing).
When smooth is provided, uses a rectangular grid instead of hexbin.
limits (Optional[Tuple[float, float, float, float]]) – Axis limits as (xmin, xmax, ymin, ymax). If not provided, uses screen
limits when available (and data falls within), otherwise uses data extent.
Raises:
ValueError – if plot_range does not overlap with the data
Intervals can be extracted with
get_intervals().
Each interval gets a separate subplot.
The data is plotted for each eye and variable in different colors.
The x-axis is plotted in the units of the Intervals object.
If the intervals contain event onsets, these are marked by a
dashed red line.
Plot masked intervals for specified eyes and variables.
Visualizes masked data segments as horizontal lines on a timeline,
similar to Intervals.plot(). Each interval is shown at a different
y-level. When plotting multiple eyes/variables without merging,
each is shown in a different color with slight y-offsets for clarity.
Parameters:
eyes (str | list) – Eye(s) to plot masks for. If empty, uses all available eyes.
variables (str | list) – Variable(s) to plot masks for. If empty, uses all available variables.
units (str) – Time units for x-axis: “ms”, “sec”, “min”, “h”, or None for indices.
Default is “min”.
merge (bool) – If True, merge all masks into a single set of intervals for plotting.
If False, plot each eye/variable separately with different colors.
Default is False.
show_labels (bool) – Whether to show labels for each interval group. Default is True.
show_events (bool) – Whether to show vertical grey stripes at event positions. Default is False.
**kwargs (dict) – Additional keyword arguments passed to matplotlib plot()
Plot a heatmap showing average pupil size across x/y gaze positions.
This visualizes how pupil size varies across different gaze positions,
which can reveal foreshortening effects (pupils appear smaller when
looking away from the camera) or other spatial artifacts.
Each eye is plotted in a separate subplot.
Parameters:
eyes (Union[str, List[str]]) – Which eye(s) to plot: “left”, “right”, “average”, or a list of these.
Default is [] which plots all available eyes.
plot_range (tuple) – The time range to include in the analysis (in units, or with
units, e.g. (3,5)*u.min). Default is (-np.inf, +np.inf),
i.e. all data.
units (str) – Time units for plot_range. Default is “sec”.
show_screen (bool) – Whether to plot the screen limits. Default is True.
cmap (str) – Colormap to use. Default is “jet”.
gridsize (int) – Number of bins in each direction. Default is 30.
vmin (Optional[float]) – Minimum value for color scale. If None, uses data minimum.
vmax (Optional[float]) – Maximum value for color scale. If None, uses data maximum.
min_samples (Optional[int]) – Minimum number of samples required in a bin to display it. Bins with
fewer samples will not be shown. If None (default), automatically
calculates a threshold at the 10th percentile of bin counts, effectively
displaying only the top 90% of bins by sample count.
smooth (Optional[float]) – If provided, applies Gaussian smoothing to the binned surface. The value
is the sigma of the Gaussian kernel in bin units (e.g., smooth=1 applies
minimal smoothing with a 1-bin sigma, smooth=2 applies more smoothing).
When smooth is provided, uses a rectangular grid instead of hexbin.
limits (Optional[Tuple[float, float, float, float]]) – Axis limits as (xmin, xmax, ymin, ymax). If not provided, uses screen
limits when available (and data falls within), otherwise uses data extent.
Plot EyeData as a scanpath. Typically used for single trials
or another small amount of data. To plot a larger amount of data,
use plot_heatmap() instead.
If several eyes are available, they are plotted in the same figure
in different colors. You can choose between them using the eyes
parameter. The samples are drawn as dots colored by time.
A new figure is created for the plot.
Parameters:
plot_range (tuple) – The time range to plot (in units, or with units, e.g.
(3,5)*u.min). Default is (-np.inf, +np.inf), i.e. all data.
eyes (list) – The eyes to plot. Default is [], which means all available data (“left”, “right”,
average, regression, …)
show_screen (bool) – Whether to plot the screen limits (if an experimental setup is
available). Default is True.
rois (List[ROI]) – List of ROIs (ROI) to plot. Default is None.
roi_style (dict) –
Style for the ROIs, passed as keyword arguments to the ROIs’
plot() method. Default is {} (ROI defaults). Example:
Plot a part of the EyeData. Each data type is plotted in a separate subplot.
Uses the current figure/axes. If no figure exists, creates one automatically.
Parameters:
plot_range (tuple) – The time range to plot (in units). Default is (-np.inf, +np.inf), i.e. all data.
variables (list) – The data to plot. Default is [], which means all available data will be plotted.
Available data are [“x”,”y”,”pupil”] but can be extended by the user.
eyes (list) – The eyes to plot. Default is [], which means all available data (“left”, “right”,
“average”, “regression”, …)
units (Optional[str]) – The units of plot_range and the time axis (“ms”, “sec”, “min”, “h”).
If None (default), use the units in the time vector (ms).
show_onsets (str) – Whether to plot markers for the event onsets. One of “line” (vertical lines),
“label” (text label), “both” (both lines and labels), or “none” (no markers).
Default is “line”.
show_masked (bool) – Whether to plot the data in masked regions. If True (default), plots all data including
masked regions. If False, masked data points are not plotted (gaps in the line).
show_mask_highlight (bool) – Whether to highlight masked regions with a light red background. Default is True.
label_prefix (str) – Prefix to add to labels in the legend. Useful for overlaying multiple datasets.
Default is “” (no prefix).
style (dict) –
Styling for plotted lines. Can be:
Single dict: Applied to all eyes with automatic differentiation (e.g., {‘color’: ‘red’})
Intervals can be extracted with
get_intervals().
Each interval gets a separate subplot.
The data is plotted for each eye and variable in different colors.
The x-axis is plotted in the units of the Intervals object.
If the intervals contain event onsets, these are marked by a
dashed red line.
Plot masked intervals for specified eyes and variables.
Visualizes masked data segments as horizontal lines on a timeline,
similar to Intervals.plot(). Each interval is shown at a different
y-level. When plotting multiple eyes/variables without merging,
each is shown in a different color with slight y-offsets for clarity.
Parameters:
eyes (str | list) – Eye(s) to plot masks for. If empty, uses all available eyes.
variables (str | list) – Variable(s) to plot masks for. If empty, uses all available variables.
units (str) – Time units for x-axis: “ms”, “sec”, “min”, “h”, or None for indices.
Default is “min”.
merge (bool) – If True, merge all masks into a single set of intervals for plotting.
If False, plot each eye/variable separately with different colors.
Default is False.
show_labels (bool) – Whether to show labels for each interval group. Default is True.
show_events (bool) – Whether to show vertical grey stripes at event positions. Default is False.
**kwargs (dict) – Additional keyword arguments passed to matplotlib plot()
Plot a part of the EyeData. Each data type is plotted in a separate subplot.
Uses the current figure/axes. If no figure exists, creates one automatically.
Parameters:
plot_range (tuple) – The time range to plot (in units). Default is (-np.inf, +np.inf), i.e. all data.
variables (list) – The data to plot. Default is [], which means all available data will be plotted.
Available data are [“x”,”y”,”pupil”] but can be extended by the user.
eyes (list) – The eyes to plot. Default is [], which means all available data (“left”, “right”,
“average”, “regression”, …)
units (Optional[str]) – The units of plot_range and the time axis (“ms”, “sec”, “min”, “h”).
If None (default), use the units in the time vector (ms).
show_onsets (str) – Whether to plot markers for the event onsets. One of “line” (vertical lines),
“label” (text label), “both” (both lines and labels), or “none” (no markers).
Default is “line”.
show_masked (bool) – Whether to plot the data in masked regions. If True (default), plots all data including
masked regions. If False, masked data points are not plotted (gaps in the line).
show_mask_highlight (bool) – Whether to highlight masked regions with a light red background. Default is True.
label_prefix (str) – Prefix to add to labels in the legend. Useful for overlaying multiple datasets.
Default is “” (no prefix).
style (dict) –
Styling for plotted lines. Can be:
Single dict: Applied to all eyes with automatic differentiation (e.g., {‘color’: ‘red’})
Plot spatial calibration data for one or more eyes in subplots.
Creates a figure with subplots for each eye and calls the plot() method
on each SpatialCalibration object to show calibration accuracy with
target points (black X), measured points (dark blue +), and optional
interpolated error surface.
Parameters:
eyes (Union[str, list, None]) – Which eye(s) to plot. If None or empty list, plots all available eyes.
Can be a single eye name (e.g., ‘left’) or list of eye names (e.g., [‘left’, ‘right’]).
show_surface (bool) – If True, show interpolated error surface as background.
If False, show only the calibration points.
interpolation (str) – Interpolation method for surface (only used if show_surface=True).
Options: ‘rbf’, ‘linear’, ‘cubic’, ‘nearest’
figsize (tuple) – Figure size per subplot (width, height) in inches.
Returns:
fig (matplotlib.figure.Figure) – The figure object
axes (list or matplotlib.axes.Axes) – List of axis objects (or single axis if only one eye)
Raises:
ValueError – If no calibration data is available
Examples
>>> importpypillometryaspp>>> data=pp.EyeData.from_eyelink('data.edf')>>> # Plot all eyes with surface>>> fig,axes=data.plot.plot_calibration()>>>>>> # Plot only left eye without surface>>> fig,ax=data.plot.plot_calibration(eyes='left',show_surface=False)>>>>>> # Plot specific eyes>>> fig,axes=data.plot.plot_calibration(eyes=['left','right'])
Plot EyeData as a heatmap. Typically used for a large amount of data
to spot the most frequent locations.
To plot a scanpath, use plot_scanpath() instead.
Each eye is plotted in a separate subplot of the current figure
(a new figure is created if none exists); the colorbar shows the
number of samples per bin.
Parameters:
plot_range (tuple) – The time range to plot (in units, or with units, e.g.
(3,5)*u.min). Default is (-np.inf, +np.inf), i.e. all data.
eyes (list) – The eyes to plot. Default is [], which means all available data (“left”, “right”,
average, regression, …)
show_screen (bool) – Whether to plot the screen limits (if an experimental setup is
available). Default is True.
show_masked (bool) – Whether to plot the masked data (because of blinks, artifacts, …). Default is False.
rois (List[ROI]) – List of ROIs (ROI) to plot. Default is None.
roi_style (dict) –
Style for the ROIs, passed as keyword arguments to the ROIs’
plot() method. Default is {} (ROI defaults). Example:
units (str) – The units of plot_range (“ms”, “sec”, “min”, “h”). Default is “sec”.
cmap (str) – The colormap to use. Default is “jet”.
gridsize (int | str) – The gridsize for the hexbin plot or histogram. If “auto”, the square
root of the number of samples in plot_range is used. Default is 30.
min_samples (Optional[int]) – Minimum number of samples required in a bin to display it. Bins with
fewer samples will not be shown. If None, automatically calculates a
threshold at the 10th percentile of bin counts. Default is 1.
smooth (Optional[float]) – If provided, applies Gaussian smoothing to the binned histogram. The value
is the sigma of the Gaussian kernel in bin units (e.g., smooth=1 applies
minimal smoothing with a 1-bin sigma, smooth=2 applies more smoothing).
When smooth is provided, uses a rectangular grid instead of hexbin.
limits (Optional[Tuple[float, float, float, float]]) – Axis limits as (xmin, xmax, ymin, ymax). If not provided, uses screen
limits when available (and data falls within), otherwise uses data extent.
Raises:
ValueError – if plot_range does not overlap with the data
Intervals can be extracted with
get_intervals().
Each interval gets a separate subplot.
The data is plotted for each eye and variable in different colors.
The x-axis is plotted in the units of the Intervals object.
If the intervals contain event onsets, these are marked by a
dashed red line.
Plot masked intervals for specified eyes and variables.
Visualizes masked data segments as horizontal lines on a timeline,
similar to Intervals.plot(). Each interval is shown at a different
y-level. When plotting multiple eyes/variables without merging,
each is shown in a different color with slight y-offsets for clarity.
Parameters:
eyes (str | list) – Eye(s) to plot masks for. If empty, uses all available eyes.
variables (str | list) – Variable(s) to plot masks for. If empty, uses all available variables.
units (str) – Time units for x-axis: “ms”, “sec”, “min”, “h”, or None for indices.
Default is “min”.
merge (bool) – If True, merge all masks into a single set of intervals for plotting.
If False, plot each eye/variable separately with different colors.
Default is False.
show_labels (bool) – Whether to show labels for each interval group. Default is True.
show_events (bool) – Whether to show vertical grey stripes at event positions. Default is False.
**kwargs (dict) – Additional keyword arguments passed to matplotlib plot()
Plot EyeData as a scanpath. Typically used for single trials
or another small amount of data. To plot a larger amount of data,
use plot_heatmap() instead.
If several eyes are available, they are plotted in the same figure
in different colors. You can choose between them using the eyes
parameter. The samples are drawn as dots colored by time.
A new figure is created for the plot.
Parameters:
plot_range (tuple) – The time range to plot (in units, or with units, e.g.
(3,5)*u.min). Default is (-np.inf, +np.inf), i.e. all data.
eyes (list) – The eyes to plot. Default is [], which means all available data (“left”, “right”,
average, regression, …)
show_screen (bool) – Whether to plot the screen limits (if an experimental setup is
available). Default is True.
rois (List[ROI]) – List of ROIs (ROI) to plot. Default is None.
roi_style (dict) –
Style for the ROIs, passed as keyword arguments to the ROIs’
plot() method. Default is {} (ROI defaults). Example:
Plot a part of the EyeData. Each data type is plotted in a separate subplot.
Uses the current figure/axes. If no figure exists, creates one automatically.
Parameters:
plot_range (tuple) – The time range to plot (in units). Default is (-np.inf, +np.inf), i.e. all data.
variables (list) – The data to plot. Default is [], which means all available data will be plotted.
Available data are [“x”,”y”,”pupil”] but can be extended by the user.
eyes (list) – The eyes to plot. Default is [], which means all available data (“left”, “right”,
“average”, “regression”, …)
units (Optional[str]) – The units of plot_range and the time axis (“ms”, “sec”, “min”, “h”).
If None (default), use the units in the time vector (ms).
show_onsets (str) – Whether to plot markers for the event onsets. One of “line” (vertical lines),
“label” (text label), “both” (both lines and labels), or “none” (no markers).
Default is “line”.
show_masked (bool) – Whether to plot the data in masked regions. If True (default), plots all data including
masked regions. If False, masked data points are not plotted (gaps in the line).
show_mask_highlight (bool) – Whether to highlight masked regions with a light red background. Default is True.
label_prefix (str) – Prefix to add to labels in the legend. Useful for overlaying multiple datasets.
Default is “” (no prefix).
style (dict) –
Styling for plotted lines. Can be:
Single dict: Applied to all eyes with automatic differentiation (e.g., {‘color’: ‘red’})
intervals (list of tuples, np.ndarray or Quantity) – Intervals as list of (start, end) tuples or 2D array; can carry
units, e.g. [(0,100),(200,300)]*u.ms or
[("1min","2min")]
units (str, Unit or None) – Units of the intervals (“ms”, “sec”, “min”, “h”, or None for indices).
Can be omitted if intervals carry units; otherwise, intervals with
units are converted to units.
label (str, optional) – Descriptive label for the interval collection
event_labels (list, optional) – Event labels corresponding to each interval
event_indices (np.ndarray, optional) – Indices (into the dataset’s events) of the event corresponding to
each interval
data_time_range (tuple, optional) – Time range (min, max) of the original dataset (in same units as intervals)
event_onsets (list or np.ndarray, optional) – Original event onset times (in same units as intervals)
sampling_rate (float, optional) – Sampling rate in Hz. Required to convert index-based intervals to time units.
time_offset (float, optional) – Time offset in milliseconds. When intervals are stored in indices (units=None),
this offset is added when converting to time units. This is needed when the
dataset’s time vector doesn’t start at 0. Default is 0.
interval_window (tuple, optional) – The relative time window around events, in same units as intervals
(e.g., (-200, 800) for 200ms before to 800ms after). When set, indicates that intervals are event-locked and
zero corresponds to event onset. Used by
SegmentedEyeData to create the appropriate time axis.
DataFrame with columns start, end, and duration. When metadata
is available, columns event_label, event_index, and event_onset
are included. If the intervals have units, the column units is added.
Filter intervals and return a new Intervals object.
This method supports multiple filtering criteria that can be combined:
- Custom function: applied to each interval
- Duration constraints: minimum and/or maximum duration
- Time range: intervals must overlap with the specified range
All specified criteria are combined with AND logic.
Parameters:
selector (callable) – Function called as selector(start,end) for each interval that
returns bool: True to keep the interval, False to discard it.
min_duration (float) – Minimum duration of intervals to keep (in current units, unless
it carries units, e.g. "50ms")
max_duration (float) – Maximum duration of intervals to keep (as min_duration)
time_range (tuple) – (start, end) time range (in current units, unless it carries
units, e.g. (1,2)*u.min). Only keeps intervals that overlap with this range.
An interval overlaps if its end > range_start AND its start < range_end.
Returns:
New Intervals object containing only the filtered intervals
units (str or None, optional) – Units for the intervals. Default is None (indices). Time units
(“ms”, “sec”, …) require sampling_rate; the sample indices
are converted with to_units().
label (str) – Label for the intervals.
sampling_rate (float) – Sampling rate in Hz.
time_offset (float) – Time offset in milliseconds for index-to-time conversion
(time of the first sample).
When intervals are merged, metadata is handled as follows:
- event_labels: Labels of merged intervals are joined with merge_sep
- event_indices: First index of merged group is kept
- event_onsets: First onset of merged group is kept
Parameters:
merge_sep (str, optional) – Separator to use when joining event labels of merged intervals.
Default is ‘_’.
distance (float) –
Maximum gap (in milliseconds, or with units such as
50*u.ms) between intervals to still merge them.
If two intervals are separated by less than or equal to this distance,
they will be merged. Default is 0 (only merge overlapping intervals).
Example: If distance=2 and intervals are (10, 15) and (17, 22), they
will be merged into (10, 22) because the gap (17-15=2) is <= distance.
Returns:
New Intervals object with merged intervals and updated metadata.
Add padding to the left (start) and right (end) of each interval.
The padding is in the current units of the Intervals object, unless
it carries units (e.g., left=50*u.ms).
Padding is applied independently to each interval without merging.
Use .merge() after padding if you want to merge overlapping intervals.
Intervals are clipped to stay within valid bounds:
- If data_time_range is set, intervals are clipped to that range
- Otherwise, intervals are clipped to start at 0 (or time_offset for time units)
Parameters:
left (float) – Amount to subtract from the start of each interval (expand left).
Default is 0.
right (float) – Amount to add to the end of each interval (expand right).
Default is 0.
Returns:
New Intervals object with padded intervals, clipped to valid bounds.
>>> # Padding that would go out of bounds is clipped>>> intervals=Intervals([(10,50)],units="ms",data_time_range=(0,100))>>> intervals.pad(left=20).intervals# Would go to -10, clipped to 0[(0, 50)]
>>> # Pad and then merge overlapping intervals>>> intervals.pad(left=50,right=50).merge()
Notes
Negative padding values will shrink intervals (left adds to start,
right subtracts from end)
Draw highlighted backgrounds for each interval on existing plot(s).
Uses matplotlib’s axvspan to draw semi-transparent vertical spans
for each interval. This is useful for highlighting regions of interest
on top of timeseries plots.
Parameters:
ax (Axes, list of Axes, Figure, or None) – Where to draw highlights:
- None: Apply to ALL axes in current figure (useful after plot_timeseries)
- Single Axes: Apply only to that axes
- List of Axes: Apply to each axes in the list
- Figure: Apply to all axes in that figure
color (str) – Color for the highlighted regions (default ‘lightblue’)
**kwargs (dict) – Additional keyword arguments passed to ax.axvspan()
(e.g., label, linestyle, edgecolor, zorder); zorder defaults
to 0 (behind the data)
Returns:
List of matplotlib patches created
Return type:
list
Examples
>>> # Highlight on a single pupil plot>>> data.plot.pupil_plot(units="sec")>>> intervals=data.get_intervals("stim",units="sec")>>> intervals.plot_highlight(color='green',alpha=0.2)
>>> # Highlight on all subplots from plot_timeseries>>> data.plot.plot_timeseries(units="ms")>>> intervals=data.get_intervals("stim",units="ms")>>> intervals.plot_highlight()# Applies to all subplots
>>> # Highlight only specific subplot>>> fig=plt.gcf()>>> intervals.plot_highlight(ax=fig.axes[0])# Only first subplot
Notes
Make sure the intervals are in the same units as the plot’s x-axis.
Use intervals.to_units(“sec”) to convert if needed.
Dictionary with summary statistics (n, mean, sd, min, max, total_duration, units);
for empty Intervals, mean/sd/min/max are NaN and total_duration is 0
>>> # Time-based intervals are auto-converted>>> intervals=Intervals([(0,100),(200,300)],units="ms",... data_time_range=(0,500),sampling_rate=1000)>>> mask=intervals.to_mask()# Converts to indices automatically
ValueError – If conversion requires sampling_rate but it is not set
Examples
>>> intervals=data.get_intervals("stim",units="ms")>>> intervals_sec=intervals.to_units("sec")>>> intervals_seconds=intervals.to_units("seconds")# alias works too
Convert from indices to time units (requires sampling_rate):
Combine multiple Intervals objects into a single Intervals object.
Takes multiple Intervals objects and concatenates them into one, preserving
all intervals and their metadata. Does NOT merge overlapping intervals -
call .merge() on the result if you want to merge overlapping intervals.
All input Intervals must have the same units.
Parameters:
*args (Intervals objects, list, or dict) – Variable number of Intervals objects, or a single list/dict of Intervals.
If dict, keys are ignored and all Intervals are combined.
label (str) – Label for the resulting Intervals object. Default is “merged”.
Returns:
A single Intervals object containing all intervals from all input
Intervals objects with their metadata preserved.
This class wraps arrays of event onsets and labels and provides additional
functionality such as unit conversion, filtering, and display capabilities.
The events of a dataset are obtained with
get_events(). An (e.g., filtered)
Events object can be passed as event_select to
get_intervals() or stored in a dataset
with set_events().
Parameters:
onsets (Union[ndarray, List]) – Event onset times (stored as float array); can carry units, e.g.
[100,500]*u.ms
labels (Union[ndarray, List]) – Event labels (stored as array of strings), same length as onsets
units (Optional[str]) – Units of the onsets (“ms”, “sec”, “min”, “h”, or None for indices).
Default is “ms”, or the units of onsets if they carry units
(otherwise, onsets with units are converted to units).
data_time_range (Optional[Tuple[float, float]]) – Time range (min, max) of the original dataset (in same units as onsets)
Raises:
ValueError – If onsets and labels differ in length.
Examples
>>> events=Events(onsets=[100,500,1000],labels=["A","B","C"],units="ms")>>> len(events)3>>> foronset,labelinevents:... print(f"{label} at {onset}")
This method supports multiple types of selectors for flexible filtering:
- String: matches labels containing the substring
- Callable: applies function to each label, keeps events where it returns True
- Tuple: filters by time range (min_time, max_time)
Parameters:
selector (str, callable, or tuple) –
Filtering criterion:
str: substring to search for in labels
callable: function that takes a label and returns bool
tuple: (min_time, max_time) to filter by onset time range
(inclusive, in the units of the Events object)
Returns:
New Events object containing only the filtered events
Class representing segmented eye data (e.g., event-related pupil dilation).
Holds equal-length segments of a single eye data variable (e.g., “left_pupil”,
“right_x”) extracted around events. Tracks masked/missing data.
Usually created with get_segments()
from the Intervals returned by
get_intervals(), e.g.
d.get_segments(d.get_intervals("F",interval=(-200,800),units="ms"),"left_pupil"). Segments of several subjects can be combined with
group_segments().
Parameters:
name (str) – Name of the dataset (e.g., “cue-locked”, “conflict-trials”)
variable (str) – Variable name in “eye_variable” format (e.g., “left_pupil”, “right_x”)
tx (ndarray) – Time axis relative to segment onset (in ms)
data (MaskedArray) – Masked array with shape (n_timepoints, n_segments)
intervals (Intervals, optional) – Source Intervals object with event metadata
sampling_rate (float) – Original sampling rate in Hz
The window is specified in milliseconds relative to the zero-point of the
intervals (typically the event onset). For example, window=(-200, 0) uses
the 200ms before the event as baseline.
Can be used standalone for a quick look, or with ax parameter to
overlay multiple segments on the same plot or across subplots.
Parameters:
meanfct (callable) – Function to compute mean across segments (default: np.mean)
varfct (callable or None) – Function to compute error bands (e.g., np.std, scipy.stats.sem)
If None, no error bands are plotted.
Both functions are called as fct(data,axis=1), so they must
accept an axis argument, and they must ignore masked values
(e.g., np.ma.median, not np.median; a warning is logged otherwise).
show_missing (bool) – Plot percentage of missing data per time point on secondary y-axis.
If None, defaults to True in standalone mode, False in overlay mode.
show_zero_line (bool) – Show vertical line at time 0 (default: True)
show_legend (bool) – Show legend. If None, only shows legend in standalone mode (ax=None)
title (str) – Plot title. If None and ax is None, uses the dataset name.
Ignored when ax is provided (for overlay use).
label (str) – Label for legend. If None, uses self.name
ribbon_alpha (float) – Alpha (transparency) for error ribbon (default: 0.3)
ax (matplotlib.axes.Axes, optional) – Axes to plot on. If None, uses current axes (standalone mode)
Group-level segmented eye data combining multiple subjects.
This class inherits from SegmentedEyeData and adds group-level functionality.
It combines multiple SegmentedEyeData objects (one per subject) into a single
group-level object, either by stacking or aggregating.
The data keep their mask: stacked segments keep their own mask, and in
aggregate mode a subject’s mean is masked where all of their segments are
masked. In addition, mask_percent stores the average percentage of masked
trials per subject at each timepoint.
Parameters:
name (str) – Name of the dataset
variable (str) – Variable name in “eye_variable” format
tx (ndarray) – Time axis relative to segment onset (in ms)
data (MaskedArray) – Masked array with shape (n_timepoints, n_subjects) or (n_timepoints, n_segments)
mask_percent (ndarray) – Percentage of masked data per subject at each timepoint (shape: n_timepoints)
Create GroupLevelSegmentedData by combining multiple SegmentedEyeData objects.
Parameters:
segments (list) – List of SegmentedEyeData objects (one per subject)
meanfct (callable or None) – Function to aggregate within each subject, called as
meanfct(data,axis=1); it must accept an axis argument and
ignore masked values (e.g., np.mean or np.ma.median, but not
np.median; a warning is logged otherwise).
If None, all segments from all subjects are stacked (concatenated).
name (str) – Name for the group-level dataset. If None, uses "group_" + first
segment’s name
Overrides SegmentedEyeData.plot() to use mask_percent for the
missing-data display. Mean and error are computed across the columns
of data (subjects when aggregated, all segments when stacked).
Parameters:
meanfct (callable) – Function to compute mean across columns (default: np.mean)
varfct (callable or None) – Function to compute error bands (e.g., np.std, scipy.stats.sem;
default: scipy.stats.sem). If None, no error bands are plotted.
Both functions are called as fct(data,axis=1), so they must
accept an axis argument, and they must ignore masked values
(e.g., np.ma.median, not np.median; a warning is logged otherwise).
show_missing (bool) – Plot mask_percent (average percentage of missing data per
subject) on secondary y-axis. If None, defaults to True in
standalone mode, False in overlay mode.
show_zero_line (bool) – Show vertical line at time 0 (default: True)
show_legend (bool) – Show legend. If None, only shows legend in standalone mode (ax=None)
title (str) – Plot title. If None and ax is None, uses the dataset name.
Ignored when ax is provided (for overlay use).
label (str) – Label for legend. If None, uses self.name
ribbon_alpha (float) – Alpha (transparency) for error ribbon (default: 0.3)
ax (matplotlib.axes.Axes, optional) – Axes to plot on. If None, uses current axes (standalone mode)
Combine multiple SegmentedEyeData objects into a GroupLevelSegmentedData.
Convenience function that wraps GroupLevelSegmentedData.from_segments().
Parameters:
segments (list or dict of SegmentedEyeData) – SegmentedEyeData objects to combine. If dict, values are used.
meanfct (callable or None) – Function to aggregate within each subject, called as
meanfct(data,axis=1); it must accept an axis argument and
ignore masked values (e.g., np.mean or np.ma.median, but not
np.median; a warning is logged otherwise).
If None, all segments from all subjects are stacked (concatenated).
name (str) – Name for the group-level dataset. If None, uses "group_" + first
segment’s name
This class provides common functionality for different types of ROIs.
Subclasses should implement the contains() method to define their specific
containment logic (coordsinroi uses it for single points) and the
plot() method.
Coordinates are specified in pixels with origin at the upper-left corner
of the screen (y increases downward). Use factory methods from_mm() or
from_degrees() on subclasses for alternative coordinate systems.
Parameters:
name (str) – Name of the ROI
setup (Optional[ExperimentalSetup]) – Experimental setup for coordinate conversions. If provided, enables
coordinate system conversion methods.
Circular Region of Interest defined by center point and radius.
Coordinates are in pixels (origin at upper-left, y increases downward) by default.
Use from_mm() or from_degrees() factory methods for alternative coordinate systems.
Parameters:
center (Tuple[float, float]) – (x, y) coordinates of the center point in pixels
radius (float) – radius of the circle in pixels (must not be negative)
name (str) – Name of the ROI
setup (Optional[ExperimentalSetup]) – Experimental setup for coordinate conversions
Create circular ROI from visual angle coordinates.
Parameters:
center (Tuple[Union[float, str], Union[float, str]]) – (x, y) center in visual angle from screen center.
Positive x = right, positive y = up.
Each coordinate can be:
- float: assumed to be radians
- str: with units, e.g., “5 deg”, “0.087 rad”
- with a unit, e.g., 5 * u.deg
radius (Union[float, str]) – Radius in visual angle. Can be:
- float: assumed to be radians
- str: with units, e.g., “2 deg”, “0.035 rad”
- with a unit, e.g., 5 * u.deg
setup (ExperimentalSetup) – Experimental setup with screen geometry and eye distance
(screen_resolution, physical_screen_size, and eye_to_screen_center
must be set)
ax (matplotlib.axes.Axes, optional) – The axes to plot on. If None, the current axes will be used.
**kwargs (dict) – Additional keyword arguments passed to patches.Circle.
Common options include:
- facecolor: color of the circle fill
- edgecolor: color of the circle edge
- alpha: transparency
- fill: whether to fill the circle
- label: label for the legend
Rectangular Region of Interest defined by two corners.
Coordinates are in pixels (origin at upper-left, y increases downward) by default.
Use from_mm() or from_degrees() factory methods for alternative coordinate systems.
Parameters:
corner1 (Tuple[float, float]) – (x, y) coordinates of the first corner in pixels
corner2 (Tuple[float, float]) – (x, y) coordinates of the opposite corner in pixels (the order of
the corners does not matter)
name (str) – Name of the ROI
setup (Optional[ExperimentalSetup]) – Experimental setup for coordinate conversions
Create rectangular ROI from visual angle coordinates.
Parameters:
corner1 (Tuple[Union[float, str], Union[float, str]]) – (x, y) first corner in visual angle from screen center.
Positive x = right, positive y = up.
Each coordinate can be:
- float: assumed to be radians
- str: with units, e.g., “-5 deg”, “-0.087 rad”
- with a unit, e.g., 5 * u.deg
corner2 (Tuple[Union[float, str], Union[float, str]]) – (x, y) second corner in visual angle from screen center.
Positive x = right, positive y = up.
Each coordinate can be:
- float: assumed to be radians
- str: with units, e.g., “5 deg”, “0.087 rad”
- with a unit, e.g., 5 * u.deg
setup (ExperimentalSetup) – Experimental setup with screen geometry and eye distance
(screen_resolution, physical_screen_size, and eye_to_screen_center
must be set)
ax (matplotlib.axes.Axes, optional) – The axes to plot on. If None, the current axes will be used.
**kwargs (dict) – Additional keyword arguments passed to patches.Rectangle.
Common options include:
- facecolor: color of the rectangle fill
- edgecolor: color of the rectangle edge
- alpha: transparency
- fill: whether to fill the rectangle
- label: label for the legend
eyes (list) – eye(s) to process; if empty, all available eyes
variables (list) – variable(s) to process; if empty, all available variables
distance (float) – Merge blinks closer than this distance, e.g. 100*u.ms or
"0.1sec"; plain numbers are in units given by units.
Default 100.
units (str) – Units for distance if it is a plain number. Can be “ms”,
“sec”, “min”, or “h”. Default “ms”.
apply_mask (bool) – If True, store the merged blinks, apply them as masks to the data
and return the object.
If False, return merged blinks as dict of Intervals objects without
storing them or applying masks (same default as
pupil_blinks_detect()).
inplace (bool | None) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor).
Only relevant when apply_mask=True.
Returns:
If apply_mask=True: returns modified object for chaining.
If apply_mask=False: returns dict of Intervals objects (one per eye/variable combination).
Simple downsampling scheme using mean within the downsampling window.
All data fields and the time-vector are downsampled simultaneously.
See pypillometry.signal.baseline.downsample(). Masked samples are
left out of the window means; a new sample is masked only if all
samples in its window were masked. Stored blinks (in sample indices)
are rescaled to the new sampling rate.
Parameters:
fsd (float) – new sampling-rate (in Hz) or decimate-factor
dsfac (bool) – if False (default), fsd is the new sampling rate (the decimate
factor is int(fs/fsd));
if True, fsd is the decimate factor
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the downsampled object (self or a copy, depending on inplace)
Drop specified eyes and/or variables from the data and return a new object.
This method never works in place - it always returns a new object.
All data of the given eyes and all data of the given variables are
dropped (together with their stored blinks).
The returned object’s class is determined by what data remains:
If only pupil variables remain: returns PupilData
If only x/y variables remain: returns GazeData
If both pupil and x/y remain: returns EyeData
Parameters:
eyes (list) – Eyes to drop (e.g., [‘left’] or [‘right’] or [‘left’, ‘right’]);
if empty, no eye is dropped
variables (list) – Variables to drop (e.g., [‘pupil’] or [‘x’, ‘y’]);
if empty, no variable is dropped
Returns:
A new object with the specified data removed, cast to the appropriate class.
Return type:
GenericEyeData subclass
Raises:
ValueError – If dropping would result in no data remaining.
Examples
>>> # Drop left eye data>>> right_only=data.drop_data(eyes=['left'])>>>>>> # Drop pupil data, keep only gaze>>> gaze_only=data.drop_data(variables=['pupil'])>>>>>> # Drop right eye and pupil data>>> left_gaze=data.drop_data(eyes=['right'],variables=['pupil'])
Drop original dataset from record (e.g., to save space).
Sets the original attribute (stored when the object was created
with keep_orig=True) to None.
Parameters:
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the object without the original data (self or a copy,
depending on inplace)
Find gaps in the time-vector and fill them in (in-place).
A gap is a step between consecutive time points that is larger than
twice the median step. New time points are inserted into each gap
at the median step size and all data variables are set to yval
at these new time points; they are masked as missing. Existing masks
are kept and stored blinks (in sample indices) are moved to the new
sample positions. This is called by the constructor when
fill_time_discontinuities=True.
Parameters:
yval (float, optional) – value used for the data in the filled-in gaps; default NaN,
so the filled-in samples are masked as missing data
print_info (bool, optional) – if True (default), log the number of gaps that are filled in
All “messages” are stored as event_labels (can be filtered later) and
it tries to be smart to detect different information from the EDF file.
Spatial calibration/validation data is automatically parsed and stored
in the calibration attribute as SpatialCalibration objects.
Eyelink codes missing pupil samples (e.g., during blinks) as 0; these
are converted to NaN (and therefore masked).
However, the EDF file may contain other information of interest, e.g.,
eyelink-detected saccades, etc.
If you need more control, use the “eyelinkio” package directly and
create the object manually.
Parameters:
fname (str) – filename of the EDF file, HTTP(S) URL or SSH URL
(ssh://server/folder/file.edf, see
pypillometry.io.fetch_url())
return_edf_obj (bool) – if True, return a tuple with the eyedata object and the object
returned by the “eyelinkio” package;
if False (default), return only the eyedata object
remove_eyelink_triggers (bool) – if True (default), remove all Eyelink triggers from the event_labels
(related to eye-tracker settings, calibration, validation etc)
Get interpolated blinks as Intervals object or dict of Intervals.
Interpolated blinks are the blink regions that were successfully interpolated
by pupil_blinks_interpolate(). These may differ from detected blinks because:
Blink boundaries are refined using velocity thresholds
Some blinks may be skipped if they’re too short to interpolate
If no interpolated blinks are stored for an eye/variable, an empty
Intervals object is returned for it.
Parameters:
eyes (str | list) – Eye(s) to get interpolated blinks for; if empty, all available eyes.
If multiple, returns dict.
variables (str | list) – Variable(s) to get interpolated blinks for; if empty, all available
variables. If multiple, returns dict.
units (str | None) – Units for intervals: “ms”, “sec”, “min”, “h”, or None for indices
Returns:
If single eye and variable: returns Intervals object.
If multiple eyes/variables: returns dict with keys like “left_pupil”.
Return an Intervals object containing intervals relative to event-onsets.
For example, extract the interval before and after a stimulus has been presented.
It is possible to select based on the event label, e.g. only select
events matching “stimulus” or “response”. It is also
possible to select the intervals situated between two different events,
e.g., trial start and response by specifying event_select as a tuple
with two entries.
variable describing which events to select and align to
if str: use all events whose label contains the string
if function: apply function to all labels, use those where the
function returns True
if tuple: use the intervals between the events selected by the
first and the second entry (each a str or function); interval[0]
is added to the first and interval[1] to the second event
(so interval=(0,0) gives exactly the span between them).
Both selectors must result in identical number of events;
events are paired by order (n-th first with n-th second event)
and a ValueError is raised if a second event comes before
its first event.
if Events: use the events from the
Events object directly
interval (tuple) – time-window relative to event-onset (0 is event-onset); i.e., negative
numbers are before the event, positive numbers after, e.g.
(-200,800)*u.ms or ("-0.2sec","0.8sec"). Plain numbers
are in units given by the units parameter. Default (-200,200).
units (str | None) – units of the returned intervals (one of “ms”, “sec”, “min”, “h”, or
None for sampling units, i.e., indices into the time-array); plain
numbers in interval are in these units, an interval with units
is converted to them. If not given, the units of interval are used
(sampling units if interval has no units).
label (str | None) – optional label for the Intervals object. If None, a label is automatically
generated from the event_select parameter
**kwargs – passed onto the event_select function
Returns:
Intervals object containing interval on- and offsets for each match,
with associated metadata (event labels, indices, units)
This function replaces data within the specified intervals with interpolated
values based on boundary points outside each interval. The
interpolated samples are also marked as masked. Intervals without
valid (non-NaN) boundary points on both sides are skipped with a
warning.
margin (tuple, default (-20, 20)) – Time window (in ms) before and after the interval to collect boundary
points for interpolation, relative to the start and end of each
interval: points are taken from start+margin[0] to the start
and from the end to end+margin[1], so margin[0] must be
<= 0 and margin[1] >= 0. Masked or NaN samples are not used.
For higher-order methods like “cubic” or “quadratic”, more
boundary points from this margin are used to fit the
interpolation curve.
store_as_suffix (str or None, default None) – If None, replace the original data.
If a string, store interpolated data in a new variable with this suffix
(e.g., “_interp” creates “left_pupil_interp”).
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
The object with interpolated data (self or a copy, depending on inplace).
Each contiguous run of masked samples becomes one interval.
Parameters:
eyes (str | list) – Eye(s) to get masks for; if empty, all available eyes.
If multiple, returns dict.
variables (str | list) – Variable(s) to get masks for; if empty, all available variables.
If multiple, returns dict (combinations not present in the data
are left out).
units (str | None) – Units for intervals: “ms”, “sec”, “min”, “h”, or None for indices.
Default is None (indices).
label (str | None) – Descriptive label for the intervals. Default is None.
Returns:
If single eye and variable: returns Intervals object.
If multiple eyes/variables: returns dict with keys like “left_pupil”.
Takes detected intervals (e.g., blinks, artifacts) and applies them
as masks to specified eyes and variables. Existing masks are kept
(the new mask is added to them).
A single Intervals object: applied to all specified eyes/variables
A dict of Intervals: keys like “left_pupil”, “right_x”, etc.
When dict is provided, eyes and variables are ignored.
eyes (str or list of str, optional) – eye(s) to apply mask to (e.g., ["left","right"]);
if empty, all available eyes. Ignored if intervals is a dict.
variables (str or list of str, optional) – variable(s) to apply mask to (e.g., ["pupil","x","y"]);
if empty, all available variables. Ignored if intervals is a dict.
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
The object with masks applied (self or a copy, depending on inplace).
The merged data is stored under the eye name “mean” (e.g.,
obj["mean","pupil"]). Each sample is the mean over the eyes
in which it is not masked; it is masked in the merged data only if
it is masked in all merged eyes (it then holds the mean of the
stored values, e.g., of interpolated blinks).
Parameters:
eyes (str or list of str, optional) – eye(s) to merge; if empty, all available eyes
variables (str or list of str, optional) – variable(s) to merge; if empty, all available variables
method (str, optional) – which method to use for merging; currently only “mean” is
implemented, by default “mean”
keep_eyes (bool, optional) – keep original eye data (True, default) or drop it together
with its stored blinks (False)
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the object with merged data (self or a copy, depending on inplace)
Merge masks of all variables into a single joint mask.
This function creates a joint mask by taking the logical OR of all individual masks
using get_mask(), then applies this joint mask to all variables.
Parameters:
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the object with merged masks (self or a copy, depending on inplace)
t0 is subtracted from the time-vector and from the event onsets.
Parameters:
t0 (float | None) – time (in ms) that becomes the new time zero; if None, use the first
time point (so that the time-vector starts at zero)
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the object with shifted time (self or a copy, depending on inplace)
Scale the signal by subtracting mean and dividing by sd.
If these variables are not provided, use the signal’s mean and std.
Specify whether to scale x, y, pupil or other variables.
Parameters:
variables (str or list of str, optional) – variables to scale; can be “pupil”, “x”,”y”, “baseline”, “response” or any other variable
that is available in the dataset; either a string or a list of strings;
available variables can be checked with obj.variables; empty list means all variables
mean (Union[float, dict, None]) – mean to subtract from signal; if None, use the signal’s mean
(of the non-masked samples);
if float, use the same value for all eyes and variables;
if dict, provide mean for each eye and variable as
{eye:{variable:value}}
sd (Union[float, dict, None]) – sd to scale with; if None, use the signal’s std (of the
non-masked samples);
if float, use the same value for all eyes and variables;
if dict, provide sd for each eye and variable as
{eye:{variable:value}}
eyes (str or list of str, optional) – eye(s) to consider; if empty, all available eyes
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the scaled object (self or a copy, depending on inplace)
a single Intervals object: stored for all
specified eyes/variables;
a dict of Intervals (or None) with keys like “left_pupil”,
“right_x”, etc.; when a dict is provided, eyes and
variables are ignored;
None: remove the stored blinks for the specified
eyes/variables (the mask is not changed).
eyes (str or list of str, optional) – eye(s) to set blinks for (e.g., ["left","right"]);
if empty, all available eyes. Ignored if intervals is a dict.
variables (str or list of str, optional) – variable(s) to set blinks for (e.g., ["pupil","x","y"]);
if empty, all available variables. Ignored if intervals is a dict.
apply_mask (bool, optional) – If True, also apply the intervals as mask to the data
(existing masks are kept). If False, only store intervals.
Default is True.
Replace event onsets and labels from an Events object.
This method updates the internal event_onsets and event_labels arrays
from an Events object. The Events object’s onsets are automatically
converted to milliseconds (the internal storage format) if needed.
Parameters:
events (Events) – Events object containing the new events to set
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the object with updated events (self or a copy, depending on inplace)
Return result of applying a statistical function to data in a
given interval relative to event-onsets. For example, extract mean
pupil-size in interval before trial onset.
Parameters:
intervals (Intervals, optional) – Intervals object to use, in any time units or in sample indices
(units=None, the default of get_intervals()). If
provided, interval and event_select are ignored.
interval (Tuple[float, float]) – time-window relative to event-onset (0 is event-onset), e.g.
(-200,0)*u.ms; plain numbers are in units given by units.
Required if intervals is not provided.
event_select (str or function, optional) – variable describing which events to select and align to
see get_intervals() for details.
Required if intervals is not provided.
eyes (str | list) – eye(s) to consider; if empty, all available eyes
variables (str | list) – variable(s) to consider; if empty, all available variables
statfct (Callable) – function mapping a masked array to a single number; it must
ignore masked samples (e.g., np.mean (default) or
np.ma.median, but not np.median; a warning is logged
otherwise). Intervals where all samples are masked give NaN.
units (str) – units for plain numbers in interval (if used); default “ms”
**kwargs – passed onto the event_select function
Returns:
one array per eye/variable (keys like “left_pupil”), with one
value per interval/event
The result contains all data (and events) between start and end
(inclusive), e.g. d.sub_slice(3*u.min,5*u.min) or
d.sub_slice("3min","5min").
start and end refer to the values of the time-vector (not to
the time since the start of the recording). Masks are kept; stored
blinks (in sample indices) are shifted and cut to the new range.
Parameters:
start (float) – start for new dataset; default: beginning of the data
end (float) – end of new dataset; default: end of the data
units (str) – time units of start and end if they are plain numbers
(one of “ms”, “sec”, “min”, “h”). If units is None, plain
numbers are ms (the units of the time vector).
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the shortened object (self or a copy, depending on inplace)
Scale back to original values using either values provided as arguments
or the values stored in params[“scale”] by scale().
The signal is multiplied by sd and mean is added.
Parameters:
variables (str or list of str, optional) – variables to unscale; can be “pupil”, “x”,”y”, “baseline”, “response” or any other variable
that is available in the dataset; either a string or a list of strings;
available variables can be checked with obj.variables; empty list means all variables
mean (None, float or dict, optional) – mean to add to the signal; a number (same for all eyes and
variables) or {eye:{variable:value}};
if None, use the mean stored by scale()
sd (None, float or dict, optional) – sd to multiply the signal with; a number (same for all eyes and
variables) or {eye:{variable:value}};
if None, use the sd stored by scale()
eyes (str or list of str, optional) – eye(s) to consider; if empty, all available eyes
inplace (bool or None, optional) – if True, make change in-place and return the object;
if False, make and return copy before making changes;
if None, use the object-level setting (specified in the constructor)
Returns:
the unscaled object (self or a copy, depending on inplace)
A dictionary that contains 1-dimensional ndarrays of equal length
and with the same datatype (float).
Drops empty entries (None or length-0 ndarrays).
Keys stored in this dictionary have the following shape:
(eye)_(variable) where eye can be any string identifier (e.g., “left”, “right”,
“mean”, “median”, “regress”, or any other custom identifier) and variable is any
string identifier (e.g., “x”, “y”, “pupil”, “baseline”, “response”, or any other
custom identifier).
Values are stored as given (converted to float); NaN values are masked.
No other values are treated as missing (e.g., a pupil size of 0 is kept);
converting missing-value codes to NaN is up to the code that reads the data.
The dictionary can be indexed by a string “eye_variable” or by a tuple
(“eye”, “variable”) like data[“left”,”x”] or data[“left_x”].
Count the number of missing values based on masks.
Parameters:
per_key (bool) – If True, return a dictionary with counts per key.
If False, return maximum count across all keys.
Default is False.
Returns:
If per_key is False, returns maximum number of missing values across all keys.
If per_key is True, returns a dictionary mapping keys to their missing value counts.
Return type:
Union[int, Dict[str, int]]
Examples
>>> d=EyeDataDict(left_x=[1,2,3],left_y=[4,5,6])>>> d.set_mask("left_x",[0,1,0])# second value is missing>>> d.set_mask("left_y",[1,0,1])# first and last values are missing>>> d.count_masked()# max missing values2>>> d.count_masked(per_key=True)# missing values per key{'left_x': 1, 'left_y': 2}
This method provides more control over mask handling than __setitem__,
which always resets the mask to zeros (except for NaN values).
Parameters:
key (Union[str, Tuple[str, str]]) – Dictionary key for the data (e.g., “left_pupil” or (“left”, “pupil”))
value (NDArray) – Data array to store
mask (Optional[NDArray]) – Mask array to use. If None and preserve_mask=True, keeps existing mask.
If None and preserve_mask=False, creates new zero mask (with NaNs masked).
preserve_mask (bool) – If True and mask is None, preserve the existing mask for this key.
Ignored if mask is explicitly provided.
Return type:
None
Examples
>>> # Set data and preserve existing mask>>> data_dict.set_with_mask("left_pupil",new_values,preserve_mask=True)
>>> # Set data with explicit mask>>> data_dict.set_with_mask("left_pupil",new_values,mask=new_mask)
>>> # Set data with fresh zero mask (same as __setitem__)>>> data_dict.set_with_mask("left_pupil",new_values)
Extract baseline based on the lower envelope of the (filtered) signal.
Steps:
filter away noise
detect high-prominence troughs in the signal
calculate lower envelope based on these peaks
Parameters:
tx (np.ndarray) – time-vector (any unit; the baseline is evaluated at tx)
sy (np.ndarray) – raw pupil signal (must not contain NaN)
event_onsets (np.ndarray) – onsets of events (stimuli/responses); currently not used
fs (float) – sampling rate in Hz
lp (float) – low-pass filter cutoff in Hz for removing random noise
prominence_thr (float) – percentile (in [0, 100]) of the prominence distribution (of the peaks) to
use for determining prominent peaks (see scipy.signal.peak_prominences())
interp_method ({"cubic", "linear", "spline"}) –
“linear”: linear interpolation between the high-prominence peaks
”cubic”: cubic interpolation through all high-prominence peaks
”spline”: a smoothing spline that is guaranteed to go through all
high-prominence peaks and smoothes through all the other
(lower-prominence) peaks
Returns:
base – baseline estimate (same length as tx)
Return type:
np.ndarray
Raises:
ValueError – if interp_method is not one of the supported methods
Extract baseline based on (re-)estimating the lower envelope using B-splines.
The signal is downsampled (to fsd Hz) for speed.
The B-spline fits are done with a Stan model
(baseline_model_asym_laplac.stan, variational inference via
cmdstanpy); in between, the event-related responses are
estimated with pupil_response() (fixed npar=10, tmax=917) and
removed before the second round of peak detection.
Parameters:
tx (np.ndarray) – time-vector in milliseconds
sy (np.ndarray) – raw pupil signal (must not contain NaN)
event_onsets (np.ndarray) – onsets of events (stimuli/responses) in milliseconds
fs (float) – sampling rate in Hz
fsd (float) – downsampled sampling rate in Hz (if too slow, decrease)
lp (float) – lowpass-filter cutoff in Hz (applied before downsampling)
lam_sig (float) – parameter steering how much the baseline is shaped by the non-peaks of the signal
lam_min (float) – weight given to the lowest-prominence peaks; peak prominences are
mapped linearly to [lam_min, lam_max]
lam_max (float) – weight given to the highest-prominence peaks
verbose (int) – not used (progress is reported via the logger)
seed (int or None) – random seed for the variational inference (for reproducible results)
Returns:
txd (np.ndarray) – downsampled time-vector (ms)
syd (np.ndarray) – downsampled and lowpass-filtered pupil signal
base2 (np.ndarray) – final baseline estimate (after the second round), sampled at txd
base1 (np.ndarray) – baseline estimate after the first round, sampled at txd
Simple downsampling scheme using mean within the downsampling window.
The signal is split into consecutive windows of R samples and each
window is replaced by its mean (ignoring NaN). If the length of y is
not a multiple of R, the last window is shorter.
Parameters:
y (np.ndarray) – signal to downsample
R (int) – decimate-factor (number of samples per window)
Uses asymmetric Savitzky-Golay velocity estimation:
- Backward-looking velocity for onset detection (so future zeros/NaN don’t affect the estimate)
- Forward-looking velocity for offset detection (so past zeros/NaN don’t affect the estimate)
The asymmetric approach naturally handles blink regions (zeros/NaN) because:
- At blink onset: backward velocity only sees valid data before the blink → detects the drop
- At blink offset: forward velocity only sees valid data after the blink → detects the rise
Parameters:
sy (np.ndarray) – pupil data (can contain NaN or zeros for missing values)
blinks (np.ndarray or Intervals) – blink onset/offset sample indices (nblinks x 2), e.g. from
detect_blinks_zero() or an Intervals
object in index units; anything that iterates over
(start, end) pairs works
smooth_winsize (int) – size of the Savitzky-Golay window in samples (odd)
vel_onset (float) – velocity-threshold to detect the onset of the blink; in units per sample (negative value)
vel_offset (float) – velocity-threshold to detect the offset of the blink; in units per sample (positive value)
margin (tuple of int) – (before, after) margin that is subtracted/added to onset and offset (in samples)
blinkwindow (int) – how much time before and after each blink to search for the
on-/offset (in samples)
min_onset_len (int) – minimum number of consecutive samples in an onset run to be considered valid
min_offset_len (int) – minimum number of consecutive samples in an offset run to be considered valid
Returns:
array (n x 2) of refined onset/offset sample indices; blinks for
which no valid velocity-threshold crossing was found are dropped,
so n can be smaller than the number of input blinks
Detect blinks as everything between a fast downward and a fast upward-trending PD-changes.
Uses asymmetric Savitzky-Golay velocity estimation to handle NaN values properly:
- Backward-looking velocity for onset detection (so future NaN doesn’t affect the estimate)
- Forward-looking velocity for offset detection (so past NaN doesn’t affect the estimate)
sy (np.ndarray) – pupil data (can contain NaN or zeros for missing values)
smooth_winsize (int) – size of the Savitzky-Golay window in samples (odd)
vel_onset (float) – velocity-threshold to detect the onset of the blink; in units per sample (negative value)
vel_offset (float) – velocity-threshold to detect the offset of the blink; in units per sample (positive value)
min_onset_len (int) – number of consecutive samples that must cross the threshold to detect an onset
(runs must have at least min_onset_len samples)
min_offset_len (int) – number of consecutive samples that must cross the threshold to detect an offset
(runs must have at least min_offset_len samples)
min_blink_samples (int) – minimum duration of a blink in samples; offsets that would create shorter intervals
are skipped during matching (to avoid spurious short offsets stealing real onsets)
max_blink_samples (int or None) – maximum duration of a blink in samples; an onset without an offset
within this many samples is not a blink and is dropped (otherwise it
would be paired with an arbitrarily distant offset); None means no
limit
Returns:
array (nblinks x 2) of blink onset/offset sample indices (both
inclusive); the offset is the last sample of the matching offset run,
or the last sample of sy if no offset was found after the last
onset (and max_blink_samples allows it); empty array if no blinks
were found
Detect blinks as consecutive sequence of blink_val (e.g., 0 or NaN) of at least
min_duration successive values in the signal sy.
Detected blinks are put a matrix blinks (nblinks x 2) where start and end
are stored as indexes.
blink_val=np.nan matches NaN values; any other value is compared with
sy == blink_val.
Parameters:
sy (np.ndarray) – signal
min_duration (int) – minimum number of samples for a sequence of missing numbers to be
treated as blink
blink_val (float) – “missing value” code, e.g. 0 or np.nan (default 0)
Returns:
array (nblinks x 2) containing the indices of the start/end of the
blinks (both inclusive); empty array if no blinks were found
Smooth the data using a window with requested size.
This method is based on the convolution of a scaled window with the signal.
The direction parameter controls whether the smoothing uses past, future,
or both samples relative to each point.
Note: If using backward or forward smoothing, the smoothed signal will be shifted
by half the window size. This is intentional for onset and offset detection,
where the smoothed signal is used to detect the onset and offset of the blink.
Compute velocity (first derivative) using Savitzky-Golay filter.
This computes velocity by fitting a polynomial to a window of samples
and evaluating its derivative, which is more robust than simple differencing.
The direction parameter controls whether the velocity estimate uses past,
future, or both samples relative to each point.
Parameters:
x (np.ndarray) – The input signal
window_len (int) – The dimension of the smoothing window; should be an odd integer.
Must be greater than polyorder.
polyorder (int) – Order of the polynomial to fit. Default is 2 (quadratic).
direction (str) – ‘center’ - symmetric, uses both past and future samples (default)
‘backward’ - only uses current and past samples (useful for onset detection)
‘forward’ - only uses current and future samples (useful for offset detection)
Returns:
The velocity (first derivative) in units per sample (same length as input)
Return type:
np.ndarray
Examples
>>> # Standard centered velocity>>> vel=velocity_savgol(signal,window_len=11)>>>>>> # Backward-looking for onset detection>>> vel_back=velocity_savgol(signal,window_len=11,direction='backward')>>>>>> # Forward-looking for offset detection>>> vel_fwd=velocity_savgol(signal,window_len=11,direction='forward')
Lowpass filter that handles NaN values via iterative interpolation.
NaN values are initially filled with the signal mean, then iteratively
replaced with filtered values until convergence. This avoids sharp
artifacts at gap boundaries that would occur with simple interpolation.
Parameters:
signal (np.ndarray) – Input signal (can contain NaN values)
cutoff (float) – Lowpass filter cutoff frequency in Hz
fs (float) – Sampling rate in Hz
order (int, optional) – Butterworth filter order (default: 2)
max_iter (int, optional) – Maximum number of iterations (default: 5)
Returns:
filtered – Lowpass-filtered signal with NaN gaps smoothly filled
Return type:
np.ndarray
Notes
The iterative approach works by:
1. Fill NaN positions with the signal mean
2. Apply lowpass filter to the filled signal
3. Replace NaN positions with the filtered values
4. Repeat steps 2-3 until max_iter reached
This converges to a smooth solution that respects the observed data
while filling gaps with values consistent with the surrounding signal.
max_duration (float or "estimate") – either maximum duration in milliseconds or string “estimate” which
causes the function to determine an appropriate duration based on the
kernel parameters npar and tmax
Returns:
x1 – design matrix (nevents x n), where n is the length of tx
Compute a slowly-varying offset between left and right pupil signals.
This function calculates the local inter-ocular difference (left - right)
to account for drift over an experimental session. The offset is computed
where both eyes have valid data, and lowpass filtered using an iterative
method that properly handles missing values (NaN gaps).
Parameters:
left (np.ndarray or np.ma.MaskedArray) – Left eye pupil signal. Can be:
- A regular numpy array (requires left_mask)
- A numpy masked array (mask is extracted automatically)
right (np.ndarray or np.ma.MaskedArray) – Right eye pupil signal. Same format options as left.
fs (float) – Sampling rate in Hz.
left_mask (np.ndarray, optional) – Boolean mask for left eye where True = invalid/masked.
Required if left is a regular numpy array.
Ignored if left is a masked array.
right_mask (np.ndarray, optional) – Boolean mask for right eye where True = invalid/masked.
Required if right is a regular numpy array.
Ignored if right is a masked array.
lowpass_cutoff (float, optional) – Cutoff frequency for lowpass filtering the offset (default: 0.2 Hz).
Lower values produce a more stable offset that only tracks very slow
drift. Higher values allow faster changes but may introduce noise.
max_iter (int, optional) – Maximum iterations for iterative lowpass filtering (default: 10).
The iterative filter fills NaN gaps by repeatedly filtering and
replacing NaN values until convergence.
Returns:
offset – The local offset signal (left - right), smoothly lowpass filtered.
Can be added to right eye data to align it with left eye level:
right_corrected = right + offset.
Return type:
np.ndarray
Notes
The offset is computed as follows:
1. Calculate raw difference (left - right) where both eyes are valid
2. Apply iterative lowpass filter that handles NaN gaps properly
The iterative filtering approach (see lowpass_filter_iterative) ensures
that only actual measurements influence the result, not interpolated values.
NaN gaps are filled with values consistent with the surrounding signal
through an iterative process that converges to a smooth solution.
This handles session-long drift by allowing the offset to vary slowly
over time, rather than assuming a constant inter-ocular difference.
For typical pupillometry experiments, a lowpass cutoff of 0.1-0.5 Hz
is recommended. This corresponds to changes over 2-10 seconds, which
captures drift while ignoring trial-by-trial noise.
Examples
>>> # With masked arrays>>> offset=pupil_eye_offset(left_ma,right_ma,fs=500)>>> right_corrected=right_ma+offset>>>>>> # With explicit masks>>> offset=pupil_eye_offset(left,right,fs=500,... left_mask=left_mask,right_mask=right_mask)>>>>>> # Merge eyes using the offset>>> both_valid=~left_mask&~right_mask>>> merged=np.where(both_valid,... (left+right+offset)/2,... np.where(~left_mask,left,right+offset))
Get the time when the PRF with parameters \(n\) and \(t_{max}\) is decayed to
thr. This gives an indication of how long the duration parameter
in pupil_kernel() should be chosen.
The amplitudes of one PRF per event (see pupil_kernel()) are
estimated with non-negative least-squares (NNLS). If npar and/or
tmax are “free”, they are optimized (minimizing the sum of squared
residuals) within bounds.
Parameters:
tx (np.ndarray) – time-vector in milliseconds
sy (np.ndarray) – (baseline-corrected) pupil signal
event_onsets (np.ndarray) – onsets of events (stimuli/responses) in milliseconds
fs (float) – sampling rate in Hz
npar (float or "free") – npar-parameter for the canonical response-function or “free”;
in case of “free”, the function optimizes for this parameter
tmax (float or "free") – tmax-parameter (in ms) for the canonical response-function or “free”;
in case of “free”, the function optimizes for this parameter
verbose (int) – not used (progress is reported via the logger)
bounds (dict) – in case that one or both parameters are estimated, give the lower
and upper bounds for the parameters (keys “npar” and “tmax”, tmax
in ms)
display_progress (bool) – show the progress of the optimization (if both parameters are free,
each iteration is logged; otherwise passed as disp option to
scipy.optimize.minimize_scalar())
Returns:
pred (np.ndarray) – predicted signal (same length as sy)
coef (np.ndarray) – non-negative amplitude of each event’s PRF
npar (float) – npar used (estimated if “free”)
tmax (float) – tmax used in ms (estimated if “free”)
Compute local signal quality metric for pupil signal.
Estimates signal quality by separating the signal into a slow “true signal”
component (via lowpass filtering) and a fast “noise” component (the residual).
Quality is then computed in sliding windows.
Parameters:
signal (np.ndarray or np.ma.MaskedArray) –
Pupil signal. Can be either:
A regular numpy array, in which case mask must be provided
A numpy masked array, in which case its mask is used
fs (float) – Sampling rate in Hz
mask (np.ndarray, optional) – Boolean mask where True indicates invalid/masked samples.
Required if signal is a regular numpy array.
Ignored if signal is a masked array.
lowpass_cutoff (float, optional) – Cutoff frequency for separating signal from noise (default: 4.0 Hz).
Pupil responses are typically < 4 Hz, so higher frequencies are noise.
window_size_ms (float, optional) – Window size for local quality estimation in milliseconds (default: 500 ms)
metric (str, optional) –
Quality metric to return:
”snr”: signal-to-noise ratio (signal_power / noise_power)
”snr_db”: SNR in decibels, 10 * log10(snr)
(0 dB = equal, +10 dB = 10x better, -10 dB = 10x worse)
”noise_power”: raw noise power (signal units squared)
”noise_cv”: coefficient of variation (noise_std / signal),
interpretable as fractional noise (0.05 = 5% noise)
Returns:
quality – Local quality metric as a masked array (same length as input).
Masked at the same locations as the input.
Return type:
np.ma.MaskedArray
Raises:
ValueError – If metric is not one of the supported options.
If signal is a regular array and mask is not provided.
If there are NaN values in the unmasked (valid) portion of the signal.
Notes
The signal-noise separation assumes pupil dynamics are slow (< lowpass_cutoff Hz).
The “signal” estimate is the lowpass-filtered version, and “noise” is the
high-frequency residual (original - lowpass).
Local power is computed as the mean of squared values in a sliding window.
SNR = signal_power / noise_power indicates how much true signal there is
relative to measurement noise.
Examples
>>> # With explicit mask>>> mask=pupil==0# e.g., blinks marked as 0>>> snr=pupil_signal_quality(pupil,fs=500,mask=mask,metric="snr")>>>>>> # With masked array>>> pupil_ma=np.ma.array(pupil,mask=(pupil==0))>>> snr=pupil_signal_quality(pupil_ma,fs=500,metric="snr")>>>>>> # Get noise as coefficient of variation (percentage)>>> noise_cv=pupil_signal_quality(pupil,fs=500,mask=mask,metric="noise_cv")>>> print(f"Average noise level: {np.mean(noise_cv[~mask])*100:.1f}%")
tmax (float) – parameter \(t_{max}\) (in ms) for pupil_kernel()
Returns:
coef (np.ndarray) – purely-positive regression coefficients (one per event)
pred (np.ndarray) – predicted signal
resid (np.ndarray) – residuals (sy-pred)
Synthetic data generation functions for testing and validation.
This module provides stateless functions for generating individual components
of eye-tracking data. Functions use abstract names (true_pupil, correction_factor)
to maintain generality. High-level orchestrator functions combine these generators
and use algorithm-specific names (e.g., A0, cos_alpha for foreshortening).
Generate step-function gaze positions (fixations with random locations and durations).
Creates gaze time series by:
1. Determining fixation times (random durations)
2. Selecting random fixation locations within screen bounds
3. Creating step functions for x and y coordinates
Parameters:
duration (float) – Duration in seconds
fs (float) – Sampling rate in Hz
fixation_duration_mean (float) – Mean fixation duration (ms)
fixation_duration_std (float) – Standard deviation of fixation duration (ms)
screen_bounds (tuple of tuples) – ((xmin, xmax), (ymin, ymax)) screen boundaries in pixels
n_fixations (int, optional) – Number of fixations (if None, determined by duration and mean fixation time);
the fixation durations are scaled so that the fixations fill duration
seed (int, optional) – Random seed for reproducibility
Generate smooth baseline pupil size via filtered noise.
Creates pupil size time series by:
1. Generating white noise
2. Low-pass filtering at specified frequency with edge handling
3. Scaling to desired amplitude and mean
Parameters:
duration (float) – Duration in seconds
fs (float) – Sampling rate in Hz
mean (float, default 750) – Mean pupil size in arbitrary units (typical EyeLink range: 500-1000 AU).
Corresponds to area-proportional measurements, not diameter.
amplitude (float, default 100) – Amplitude of slow fluctuations (standard deviation of baseline variations)
freq (float, default 0.5) – Cutoff frequency for low-pass filter (Hz), controls fluctuation speed.
Typical values: 0.1-0.5 Hz for spontaneous fluctuations, 0.5-1 Hz for
cognitive load changes, 1-3 Hz for fast responses.
filter_order (int, default 4) – Order of Butterworth filter. Higher order = sharper cutoff.
Roll-off is (filter_order * 6) dB/octave.
seed (int, optional) – Random seed for reproducibility
Returns:
t (np.ndarray) – Time vector (ms)
true_pupil (np.ndarray) – True pupil size time series
Generate complete synthetic dataset for testing foreshortening correction algorithm.
Orchestrates:
1. Generate true pupil size A0(t) with slow fluctuations (~0.5 Hz by default)
2. Generate fixation-based gaze positions (x, y)
3. Apply foreshortening: measured_pupil = A0 * cos(alpha(x,y))
4. Package into FakeEyeData with all metadata and ground truth
Uses algorithm-specific names (A0, cos_alpha) since this function is specifically
designed for testing the foreshortening correction algorithm.
Parameters:
experimental_setup (ExperimentalSetup) – Experimental setup containing screen geometry (resolution, physical size),
eye-to-screen distance (d), and camera position (theta, phi, r).
If None, uses defaults: 1920x1080 screen (52x29 cm), d=60cm,
camera at theta=20°, phi=-90°, r=70cm.
duration (float) – Duration in seconds
fs (float) – Sampling rate in Hz
eye (str) – Which eye (‘left’ or ‘right’)
A0_mean (float) – Mean true pupil size in arbitrary units (typical EyeLink range: 500-1000 AU).
Corresponds to area-proportional measurements, not diameter.
A0_amplitude (float) – Amplitude of pupil fluctuations (standard deviation of slow variations)
A0_freq (float) – Frequency of pupil fluctuations in Hz (controls speed of baseline changes)
fixation_duration_mean (float) – Mean fixation duration in ms
fixation_duration_std (float) – Standard deviation of fixation duration in ms
measurement_noise (float) – Standard deviation of Gaussian measurement noise added to pupil signal (in AU)
seed (int) – Random seed for reproducibility
**kwargs – additional parameters passed to FakeEyeData
Returns:
data – Synthetic eye-tracking data with:
sim_fct: reference to this function
sim_fct_name: ‘generate_foreshortening_data’
sim_params: all generation parameters
sim_data: EyeDataDict with ‘{eye}_A0’ and ‘{eye}_cosalpha’ ground truth
Times, distances and angles can be given with units, either multiplied by a
unit from pypillometry.u or as strings:
frompypillometryimportud.sub_slice(3*u.min,5*u.min)# or ("3 min", "5 min")d.get_intervals("stim",(-200,800)*u.ms)d.pupil_blinks_detect(min_duration="20 ms")d.plot.pupil_plot(plot_range=(3,5)*u.min)ExperimentalSetup(eye_to_screen_center=60*u.cm,screen_pitch="-5 deg")
Internally, all values are converted to ms, mm and radians. Plain numbers
are interpreted as documented for each function (usually ms for times).
Available units: u.ms, u.sec, u.min, u.h, u.samples,
u.mm, u.cm, u.m, u.inch, u.deg, u.rad (plus aliases
such as u.seconds or u.degree).
Usually created by multiplying with a unit, e.g. 3*u.min or
(-200,800)*u.ms. Tuples and lists are stored as numpy arrays.
Iterating over or indexing an array quantity gives quantities.
By default, the log-level is set to INFO which results in a moderate amount of logging information.
The logging can be turned off by running logging_disable() and turned back on by running logging_enable().
You can also set the log-level to DEBUG or WARN by running logging_set_level().
Reading EDF files is slow: read_eyelink() (and
from_eyelink()) takes about a minute
for a 90 MB EDF file (64 min of binocular data at 1000 Hz), mostly in the
eyelinkio package. It is therefore recommended to convert EDF files once
and to work with the converted files, e.g., with the command-line program
edf2pypil (edf2pypilrecording.edf writes recording.pkl) or
with write_pickle(). Reading the pickle file with read_pickle()
is more than 100 times faster. write_pickle() compresses the file
with zstd by default: a 400 MB pickle (90 MB EDF file) shrinks to about
31 MB, takes 0.5 s to write and 0.35 s to read (uncompressed: 0.2 s from
a warm cache, more from a slow disk or network). Pickle files should only
be read from trusted sources.
Download an HTTP(S) or SSH URL to a local file, with caching.
HTTP(S) URLs are downloaded with download() (OSF client URLs
such as https://osf.io/<id> are converted to download URLs).
SSH URLs have the form ssh://[user@]host[:port]/path and are
downloaded with the system’s scp, which uses ~/.ssh/config
(host aliases, users, keys). Only key-based login is supported: password
prompts are disabled (BatchMode=yes). The path is absolute on the
server; use ssh://host/~/path for a path relative to the home
directory. An SSH URL ending in / downloads the whole folder.
Parameters:
url (str) – HTTP(S) or SSH URL
cache_file (Optional[str]) – local filename to store the download in
cache_dir (Optional[str]) – directory to store the download in (used if cache_file is None);
see cache_layout. If both are None, a new temporary directory is
used. The location is logged.
force_download (bool) – if False (default), an existing local copy is reused; if True, the
file is downloaded again
session (Optional[Session]) – requests session for HTTP(S) downloads (e.g., from
osf_authenticate() for private OSF projects)
cache_layout (str) – where in cache_dir the download is stored: "flat" (default)
uses the file name only (cache_dir/<file>), "mirror" the
full remote path (cache_dir/<host>/<path>). With "flat",
files with the same name from different URLs share one local copy,
so the first one would be reused; use "mirror" (or
force_download) in that case.
autodelete (Optional[bool]) – if True, the downloaded copy (also in cache_file/cache_dir) is
deleted when the context is left, i.e. after the file was read; a
temporary directory is removed completely. If None (default), only
a temporary directory (no cache_file/cache_dir) is removed.
Read an Eyelink file/URL and return the object returned by the “eyelinkio” package.
Requires the optional package eyelinkio. Its console output is only
shown when the log level is “DEBUG”. URLs are downloaded with
fetch_url().
Parameters:
source (str) – filename of the Eyelink EDF file, HTTP(S) URL (OSF client URLs such
as https://osf.io/<id> are converted to download URLs) or SSH URL
(ssh://server/folder/file.edf)
cache_file (Optional[str]) – local filename to store a downloaded file in
cache_dir (Optional[str]) – directory to store a downloaded file in (as cache_dir/<file>,
see cache_layout), used if cache_file is None. If both are
None, a temporary directory is used.
force_download (bool) – if True, download again even if a local copy exists in
cache_file/cache_dir
session (Optional[Session]) – requests session for HTTP(S) downloads (e.g., from
osf_authenticate() for private projects)
autodelete (Optional[bool]) – if True, the downloaded copy is deleted after it was read (also in
cache_file/cache_dir). If None (default), only a temporary
download (no cache_file/cache_dir) is deleted. Local files are
never deleted.
cache_layout (str) – "flat" (default) or "mirror" (cache_dir/<host>/<path>),
see fetch_url()
fname (str) – filename, HTTP(S) URL or SSH URL (ssh://server/folder/file.pd)
cache_file (Optional[str]) – local filename to store a downloaded file in
cache_dir (Optional[str]) – directory to store a downloaded file in (as cache_dir/<file>,
see cache_layout), used if cache_file is None. If both are
None, a temporary directory is used.
force_download (bool) – if True, download again even if a local copy exists in
cache_file/cache_dir
session (Optional[Session]) – requests session for HTTP(S) downloads (e.g., from
osf_authenticate() for private projects)
autodelete (Optional[bool]) – if True, the downloaded copy is deleted after it was read (also in
cache_file/cache_dir). If None (default), only a temporary
download (no cache_file/cache_dir) is deleted. Local files are
never deleted.
cache_layout (str) – "flat" (default) or "mirror" (cache_dir/<host>/<path>),
see fetch_url()
Load a complete study (all subjects) from a local directory, an SSH URL or
an OSF project, based on a user-provided configuration file
(pypillometry_conf.py) that defines a dict raw_data and a function
read_subject(info).
Read a study from a local directory (or an SSH URL) using the configuration file.
The configuration file must define a dict raw_data (subject ID ->
dict of data files, relative to path) and a function
read_subject(info) that returns the data for one subject; it is
called with the working directory changed to path.
If path is an SSH URL (ssh://server/folder/, see
fetch_url()), the configuration file and the data files of the
selected subjects are downloaded to cache_dir before they are read.
Parameters:
path (str) – Local path or SSH URL where the study data is stored
config_file (str) – Name of the configuration file. Default is “pypillometry_conf.py”.
It is first looked up in the current working directory and, if
not found there, in path.
subjects (list[str]) – List of subject IDs to load. If None, all subjects will be loaded.
If a subject ID is provided that doesn’t exist in the data, it will be skipped.
cache_dir (Optional[str]) – only for SSH URLs: directory to download the files to; if None, a
temporary directory is used
autodelete (Optional[bool]) – only for SSH URLs: if True, the data files of each subject are
deleted after they were read (and a temporary directory is removed
at the end). If None (default), this is done only when a temporary
directory is used (no cache_dir).
force_download (bool) – only for SSH URLs: download files again even if they are already
in cache_dir
Returns:
study_data (dict) – Dictionary containing the loaded study data (subject ID -> result
of read_subject)
config (module) – Module containing the configuration (pypillometry_conf.py imported as a module)
The configuration file (downloaded from the project) must define a
dict raw_data (subject ID -> dict of data files; entries that are not
files in the project are passed on unchanged) and a function
read_subject(info) that returns the data for one subject. The
listing of the project’s files is cached in path/info_osf.pkl and
data files are only downloaded if they are not yet in path.
Parameters:
osf_id (str) – The OSF project ID
path (str) – Local path where files should be downloaded/stored
subjects (list[str]) – List of subject IDs to load. If None, all subjects will be loaded.
If a subject ID is provided that doesn’t exist in the data, it will be skipped.
force_download (bool) – If True, force re-download (including the file listing) even if
files exist locally. Default False.
config_file (str) – Name of the configuration file. Default is “pypillometry_conf.py”
session (Optional[Session]) – Authenticated session for accessing private projects. If None, uses unauthenticated requests.
Returns:
study_data (dict) – Dictionary containing the loaded study data (subject ID -> result
of read_subject)
config (module) – Module containing the configuration (pypillometry_conf.py imported as a module)
This module provides example datasets for pypillometry. The datasets are
used in the documentation and for testing purposes. Most of them are stored on
OSF: https://osf.io/p2u74/
Returns a dictionary that displays as a nicely formatted pandas DataFrame
in Jupyter notebooks but can be used as a normal dict otherwise.
Returns:
A dictionary (subclass of dict) containing all dataset metadata.
When displayed in Jupyter, it will render as a pandas DataFrame
with columns for Dataset name, Type, and Description.
Return type:
DatasetDict
Examples
>>> datasets=get_available_datasets()>>> # In Jupyter, this displays as a nice DataFrame>>> datasets>>> # But you can still use it like a normal dict>>> datasets['rlmw_002']
Load example data for a given example (see example_datasets).
Parameters:
key (str) – Key of the example dataset. Available keys are in the dictionary
example_datasets.
cache_dir (str, optional) – directory to store downloaded files in (reused in later calls);
default $XDG_CACHE_HOME/pypillometry (~/.cache/pypillometry).
Ignored for datasets included in the package.
Returns:
The example dataset as an EyeData, GazeData or PupilData object.