Signal Analysis
- class meyelens.analysis.AdaptiveGazeFilter(min_cutoff=0.8, beta=0.08, d_cutoff=1.0, jump_reset=None)[source]
Bases:
objectAdaptive gaze filter for live gaze pointer smoothing.
It uses a One Euro filter: - strong smoothing when gaze is stable - weaker smoothing when gaze moves quickly
- Parameters:
min_cutoff – Base smoothing. Lower = smoother during fixation, but more lag. Try 0.6 to 1.2.
beta – Motion adaptation. Higher = faster response during eye movements. Try 0.02 to 0.15.
d_cutoff – Smoothing applied to velocity estimate. Usually 1.0 is fine.
jump_reset – If prediction jumps more than this distance, optionally reset the filter. Useful for very large gaze shifts or recovery from bad samples. In PsychoPy norm units, try 0.5 or None.
- class meyelens.analysis.DeBlink(threshold=0.25, flankers=3, interpolation='linear', interpolation_order=2, fill_edges=True, remove_zeros=True, zero_value=0.0)[source]
Bases:
objectBlink cleaner for pupil traces.
Main logic
A sample is marked as blink/artifact if:
abs(derivative) / max(abs(derivative)) > threshold
or, if remove_zeros=True:
signal == zero_value
Then flankers are added around the detected samples. The detected samples are replaced with NaN and interpolated.
Main use
deblink = DeBlink(threshold=0.25, flankers=5)
pupil_clean = deblink.clean(pupil_area) blink_mask = deblink.get_blink_mask(pupil_area) diagnostics = deblink.get_diagnostics(pupil_area)
- get_blink_mask(signal)[source]
Return the final blink/artifact mask.
True means that the sample is marked as blink/artifact and will be interpolated.
- get_zero_mask(signal)[source]
Return the mask for zero-valued samples.
If remove_zeros=False, this returns an all-False mask.
- clean_dataframe(df, column='pupil_area', output_column=None, blink_column=None, zero_column=None, derivative_column=None)[source]
Return a copy of df with a cleaned pupil column.
- Parameters:
df – Input pandas DataFrame.
column – Input signal column.
output_column – Output cleaned signal column. If None, uses f”{column}_clean”.
blink_column – Optional output column for the final blink mask.
zero_column – Optional output column for zero-valued samples.
derivative_column – Optional output column for abs(derivative) / max(abs(derivative)).
- static compute_derivative(signal)[source]
Compute derivative while preserving signal length.
np.gradient is used instead of np.diff so the derivative and mask have the same length as the original signal.
- static normalize_by_max(x)[source]
Normalize a non-negative signal by its maximum.
Intended for abs(derivative):
0 = no change 1 = largest detected change
- plot_diagnostics(signal, time=None, show_clean=True)[source]
Plot the pupil trace, cleaned trace, derivative, threshold, and mask.
- Parameters:
signal – One-dimensional pupil trace.
time – Optional time vector. If None, sample index is used.
show_clean – If True, plot the cleaned interpolated trace.
- class meyelens.analysis.Filters(fs, order=4, method='sos')[source]
Bases:
objectFrequency filter for pupil traces.
- Supports:
lowpass
highpass
bandpass
Main use
filt = PupilFilter(fs=30)
pupil_low = filt.lowpass(pupil, cutoff=4.0) pupil_high = filt.highpass(pupil, cutoff=0.05) pupil_band = filt.bandpass(pupil, lowcut=0.05, highcut=4.0)
- param fs:
Sampling frequency in Hz.
- type fs:
float
- param order:
Butterworth filter order.
- type order:
int
- param method:
“sos” or “ba”.
“sos” is recommended because it is more numerically stable.
- type method:
str
- class meyelens.analysis.MeyeReader(path, sep=';', comment='#')[source]
Bases:
objectMinimal reader for files created with MeyeRecorder.
The path must be provided explicitly.
Expected file format
# metadata_key: metadata_value # metadata_key: metadata_value frame_index;t_call;t_frame;…;trg1;trg2;… 0;0.001;0.010;…
Basic usage
reader = MeyeReader(“path/to/recording.txt”)
df = reader.data metadata = reader.metadata
reader.print_summary()
- class meyelens.analysis.TrialEpochs(signal, time, triggers)[source]
Bases:
objectExtract stimulus-locked epochs from one signal and one or more trigger traces.
This class does not perform trial rejection or signal cleaning. Clean/filter the signal before passing it here.
Example
trialer = TrialEpochs( signal=pupil_signal, time=time, triggers={ "standard": trg_standard, "oddball": trg_oddball, "distractor": trg_distractor, }, ) epochs = trialer.extract( tmin=-1.0, tmax=4.0, baseline=(-1.0, 0.0), transform="zscore", )
Transform options
"none": raw epoch."delta": epoch minus baseline mean."percent": percent change from baseline mean."zscore": baseline-normalized z-score.
- extract(tmin=-1.0, tmax=4.0, baseline=None, transform='none', trigger_value=1, edge='rising', n_points=300, exclude_first=0, exclude_last=0)[source]
Extract epochs for all trigger traces.
- Parameters:
tmin – Epoch window in seconds relative to trigger onset.
tmax – Epoch window in seconds relative to trigger onset.
baseline – None or tuple, for example (-1.0, 0.0). Baseline window is relative to trigger onset.
transform – “none”, “delta”, “percent”, or “zscore”.
trigger_value – Trigger value marking stimulus onset.
edge –
"rising"detects transitions into the trigger value."level"detects every sample equal to the trigger value.n_points – Number of points in the interpolated epoch time base.
exclude_first – Number of first detected events to exclude for each condition.
exclude_last – Number of last detected events to exclude for each condition.
- Returns:
Contains the common epoch time base and a
conditionsmapping. Each condition stores epochs, event indices, event times, mean, SEM, and trial count. With one trigger, those fields are also exposed at the top level.- Return type:
dict
- get_event_times(trigger_name=None, trigger_value=1, edge='rising')[source]
Return event times for one trigger.
- get_event_indices(trigger_name=None, trigger_value=1, edge='rising')[source]
Return event indices for one trigger.