skills/neurokit2/references/epochs_events.md
Checked 2026-07-23 against NeuroKit2 0.2.13 stable source/runtime and the live Events and Epochs API pages.
Choose one canonical representation before analysis:
events_find() uses zero-based sample positions. Its start_at, end_at,
duration_min, duration_max, and inter_min arguments are sample counts, not
seconds.
events = nk.events_find(
trigger,
threshold=0.5,
threshold_keep="above",
duration_min=2,
inter_min=5,
event_conditions=["A", "B", "A"],
)
Stable signature:
events_find(
event_channel, threshold="auto", threshold_keep="above",
start_at=0, end_at=None, duration_min=1, duration_max=None,
inter_min=0, discard_first=0, discard_last=0,
event_labels=None, event_conditions=None
)
The default return is a dict containing onset, duration, and label; optional
conditions use the singular key condition. Multi-channel input can add
events_channel and generates conditions from the digital combination.
Do not infer trigger semantics from amplitude alone. Verify polarity, threshold, debouncing, pulse width, dropped triggers, device latency, and whether simultaneous digital inputs are encoded as expected.
events = nk.events_create(
event_onsets=[1000, 2500, 4000],
event_durations=[100, 100, 100],
event_labels=["1", "2", "3"],
event_conditions=["A", "B", "A"],
)
Labels must be unique. Keep experimental trial IDs outside participant-identifying names.
epochs_create() semantics in 0.2.13epochs_create(
data, events=None, sampling_rate=1000,
epochs_start=0, epochs_end="from_events",
event_labels=None, event_conditions=None,
baseline_correction=False
)
epochs_start and epochs_end are seconds relative to each event.[start_sample, end_sample) (end-exclusive).Index.numpy.linspace(..., endpoint=True), so the
displayed last index equals epochs_end even though the end sample is excluded.Label and optional Condition are added as columns.The pinned probe for one signal, -0.2 to 0.5 s at 100 Hz, produced 70 rows with
an index from exactly -0.2 through 0.5. Do not derive sample count from that
floating index. Use Index, the known sampling rate, and explicit half-open bounds.
Decide before analysis:
drop: remove incomplete trials and report condition-wise counts;pad: retain them with an explicit validity mask; orerror: stop and repair event/window definitions.Do not let NaN padding or integer zero padding silently become a physiological baseline. The dependency-free planner reports affected trials:
python skills/neurokit2/scripts/plan_epochs.py \
--events 1000,2500,4000 --event-unit samples \
--sampling-rate 100 --recording-samples 5000 \
--epoch-start -0.2 --epoch-end 0.8 \
--baseline-start -0.2 --baseline-end 0
For events supplied in seconds, use --event-unit seconds; the planner rejects
onsets/windows that do not map exactly to samples.
baseline_correction=True subtracts the mean from epoch start through t=0
(inclusive in the rebuilt time index). If the epoch starts after zero, it uses the
epoch start. The operation is applied broadly to numeric columns present at that
point, including marker/index columns.
Prefer selective, manual correction:
epochs = nk.epochs_create(
processed,
events,
sampling_rate=100,
epochs_start=-0.2,
epochs_end=0.8,
baseline_correction=False,
)
amplitude_columns = ["EDA_Phasic"]
for epoch in epochs.values():
baseline = epoch.loc[(epoch.index >= -0.2) & (epoch.index < 0), amplitude_columns]
epoch.loc[:, amplitude_columns] = (
epoch.loc[:, amplitude_columns] - baseline.mean()
)
Prespecify baseline interval and estimand. Baseline subtraction is not universally appropriate for rates, binary peaks, phase, quality, or absolute tonic levels. Reject/flag a trial if its baseline has missing data or artifact rather than quietly using fewer samples.
epochs_to_df() stacks epochs and adds a Time column; the stable probe observed
Signal, Index, Label, Condition, and Time.
epochs_to_array() does not take a column argument in 0.2.13. Equal-length,
single-signal epochs produced shape (time, epochs) in the pinned probe. Multiple
signal columns add an intermediate dimension. Unequal epochs are not supported.
epochs_average() signature is:
epochs_average(epochs, which=None, indices=["mean", "std", "ci"], show=False)
For which="Signal", the pinned schema contained Time, Signal_Mean,
Signal_SD, Signal_CI_low, and Signal_CI_high (plus a reset-index column).
This is not a universal event-related feature schema.
Functions such as ecg_eventrelated(), eda_eventrelated(),
rsp_eventrelated(), ppg_eventrelated(), emg_eventrelated(), and
eog_eventrelated() inspect available processed columns. Their output changes when
quality, phase, amplitude, condition, or trend columns are absent.
Use explicit dispatch:
ecg_features = nk.ecg_analyze(
epochs, sampling_rate=100, method="event-related"
)
method="auto" chooses event-related analysis when mean duration is under 10 seconds.
That software threshold is not scientific justification for a window or analysis.
Before averaging:
There is no universal minimum number of trials or universal epoch window. Determine both from the expected response, acquisition, study design, reliability, and power analysis.