scientific-skills/neurokit2/references/epochs_events.md
Event-related analysis examines physiological responses time-locked to specific stimuli or events. NeuroKit2 provides tools for event detection, epoch creation, averaging, and event-related feature extraction across all signal types.
Automatically detect events/triggers in a signal based on threshold crossings or changes.
events = nk.events_find(event_channel, threshold=0.5, threshold_keep='above',
duration_min=1, inter_min=0)
Parameters:
threshold: Detection threshold valuethreshold_keep: 'above' or 'below' thresholdduration_min: Minimum event duration (samples) to keepinter_min: Minimum interval between events (samples)Returns:
'onset': Event onset indices'offset': Event offset indices (if applicable)'duration': Event durations'label': Event labels (if multiple event types)Common use cases:
TTL triggers from experiments:
# Trigger channel: 0V baseline, 5V pulses during events
events = nk.events_find(trigger_channel, threshold=2.5, threshold_keep='above')
Button presses:
# Detect when button signal goes high
button_events = nk.events_find(button_signal, threshold=0.5, threshold_keep='above',
duration_min=10) # Debounce
State changes:
# Detect periods above/below threshold
high_arousal = nk.events_find(eda_signal, threshold='auto', duration_min=100)
Visualize event timing relative to signals.
nk.events_plot(events, signal)
Displays:
Use case:
Create epochs (segments) of data around events for event-related analysis.
epochs = nk.epochs_create(data, events, sampling_rate=1000,
epochs_start=-0.5, epochs_end=2.0,
event_labels=None, event_conditions=None,
baseline_correction=False)
Parameters:
data: DataFrame with signals or single signalevents: Event indices or dictionary from events_find()sampling_rate: Signal sampling rate (Hz)epochs_start: Start time relative to event (seconds, negative = before)epochs_end: End time relative to event (seconds, positive = after)event_labels: List of labels for each event (optional)event_conditions: List of condition names for each event (optional)baseline_correction: If True, subtract baseline mean from each epochReturns:
'Label' and 'Condition' columns if providedTypical epoch windows:
Organize events by type and experimental conditions:
# Example: Emotional picture experiment
event_times = [1000, 2500, 4200, 5800] # Event onsets in samples
event_labels = ['trial1', 'trial2', 'trial3', 'trial4']
event_conditions = ['positive', 'negative', 'positive', 'neutral']
epochs = nk.epochs_create(signals, events=event_times, sampling_rate=1000,
epochs_start=-1, epochs_end=5,
event_labels=event_labels,
event_conditions=event_conditions)
Access epochs:
# Epoch by number
epoch_1 = epochs['1']
# Filter by condition
positive_epochs = {k: v for k, v in epochs.items() if v['Condition'][0] == 'positive'}
Remove pre-stimulus baseline from epochs to isolate event-related changes:
Automatic (during epoch creation):
epochs = nk.epochs_create(data, events, sampling_rate=1000,
epochs_start=-0.5, epochs_end=2.0,
baseline_correction=True) # Subtracts mean of entire baseline
Manual (after epoch creation):
# Subtract baseline period mean
baseline_start = -0.5 # seconds
baseline_end = 0.0 # seconds
for key, epoch in epochs.items():
baseline_mask = (epoch.index >= baseline_start) & (epoch.index < baseline_end)
baseline_mean = epoch[baseline_mask].mean()
epochs[key] = epoch - baseline_mean
When to baseline correct:
Visualize individual or averaged epochs.
nk.epochs_plot(epochs, column='ECG_Rate', condition=None, show=True)
Parameters:
column: Which signal column to plotcondition: Plot only specific condition (optional)Displays:
Use cases:
Compute grand average across epochs with statistics.
average_epochs = nk.epochs_average(epochs, output='dict')
Parameters:
output: 'dict' (default) or 'df' (DataFrame)Returns:
'Mean': Average across epochs at each time point'SD': Standard deviation'SE': Standard error of mean'CI_lower', 'CI_upper': 95% confidence intervalsUse case:
Condition-specific averaging:
# Separate averages by condition
positive_epochs = {k: v for k, v in epochs.items() if v['Condition'][0] == 'positive'}
negative_epochs = {k: v for k, v in epochs.items() if v['Condition'][0] == 'negative'}
avg_positive = nk.epochs_average(positive_epochs)
avg_negative = nk.epochs_average(negative_epochs)
Convert epochs dictionary to unified DataFrame.
epochs_df = nk.epochs_to_df(epochs)
Returns:
'Epoch', 'Time', 'Label', 'Condition' columnsUse case:
Convert epochs to 3D NumPy array.
epochs_array = nk.epochs_to_array(epochs, column='ECG_Rate')
Returns:
Use case:
NeuroKit2 provides specialized event-related analysis for each signal type:
ecg_epochs = nk.epochs_create(ecg_signals, events, sampling_rate=1000,
epochs_start=-1, epochs_end=10)
ecg_results = nk.ecg_eventrelated(ecg_epochs)
Computed metrics:
ECG_Rate_Baseline: Heart rate before eventECG_Rate_Min/Max: Minimum/maximum rate during epochECG_Phase_*: Cardiac phase at event onseteda_epochs = nk.epochs_create(eda_signals, events, sampling_rate=100,
epochs_start=-1, epochs_end=10)
eda_results = nk.eda_eventrelated(eda_epochs)
Computed metrics:
EDA_SCR: Presence of SCR (binary)SCR_Amplitude: Maximum SCR amplitudeSCR_Latency: Time to SCR onsetSCR_RiseTime, SCR_RecoveryTimeEDA_Tonic: Mean tonic levelrsp_epochs = nk.epochs_create(rsp_signals, events, sampling_rate=100,
epochs_start=-0.5, epochs_end=5)
rsp_results = nk.rsp_eventrelated(rsp_epochs)
Computed metrics:
RSP_Rate_Mean: Average breathing rateRSP_Amplitude_Mean: Average breath depthRSP_Phase: Respiratory phase at eventemg_epochs = nk.epochs_create(emg_signals, events, sampling_rate=1000,
epochs_start=-0.1, epochs_end=1.0)
emg_results = nk.emg_eventrelated(emg_epochs)
Computed metrics:
EMG_Activation: Presence of activationEMG_Amplitude_Mean/Max: Amplitude statisticsEMG_Onset_Latency: Time to activation onsetEMG_Bursts: Number of activation burstseog_epochs = nk.epochs_create(eog_signals, events, sampling_rate=500,
epochs_start=-0.5, epochs_end=2.0)
eog_results = nk.eog_eventrelated(eog_epochs)
Computed metrics:
EOG_Blinks_N: Number of blinks during epochEOG_Rate_Mean: Blink rateppg_epochs = nk.epochs_create(ppg_signals, events, sampling_rate=100,
epochs_start=-1, epochs_end=10)
ppg_results = nk.ppg_eventrelated(ppg_epochs)
Computed metrics:
import neurokit2 as nk
# 1. Process physiological signals
ecg_signals, ecg_info = nk.ecg_process(ecg, sampling_rate=1000)
eda_signals, eda_info = nk.eda_process(eda, sampling_rate=100)
# 2. Align sampling rates if needed
eda_signals_resampled = nk.signal_resample(eda_signals, sampling_rate=100,
desired_sampling_rate=1000)
# 3. Merge signals into single DataFrame
signals = pd.concat([ecg_signals, eda_signals_resampled], axis=1)
# 4. Detect events
events = nk.events_find(trigger_channel, threshold=0.5)
# 5. Add event labels and conditions
event_labels = ['trial1', 'trial2', 'trial3', ...]
event_conditions = ['condition_A', 'condition_B', 'condition_A', ...]
# 6. Create epochs
epochs = nk.epochs_create(signals, events, sampling_rate=1000,
epochs_start=-1.0, epochs_end=5.0,
event_labels=event_labels,
event_conditions=event_conditions,
baseline_correction=True)
# 7. Signal-specific event-related analysis
ecg_results = nk.ecg_eventrelated(epochs)
eda_results = nk.eda_eventrelated(epochs)
# 8. Merge results
results = pd.merge(ecg_results, eda_results, left_index=True, right_index=True)
# 9. Statistical analysis by condition
results['Condition'] = event_conditions
condition_comparison = results.groupby('Condition').mean()
# Different event types with different markers
event_type1 = nk.events_find(trigger_ch1, threshold=0.5)
event_type2 = nk.events_find(trigger_ch2, threshold=0.5)
# Combine events with labels
all_events = np.concatenate([event_type1['onset'], event_type2['onset']])
event_labels = ['type1'] * len(event_type1['onset']) + ['type2'] * len(event_type2['onset'])
# Sort by time
sort_idx = np.argsort(all_events)
all_events = all_events[sort_idx]
event_labels = [event_labels[i] for i in sort_idx]
# Create epochs
epochs = nk.epochs_create(signals, all_events, sampling_rate=1000,
epochs_start=-0.5, epochs_end=3.0,
event_labels=event_labels)
# Separate by type
type1_epochs = {k: v for k, v in epochs.items() if v['Label'][0] == 'type1'}
type2_epochs = {k: v for k, v in epochs.items() if v['Label'][0] == 'type2'}
# Remove epochs with excessive noise or artifacts
clean_epochs = {}
for key, epoch in epochs.items():
# Example: reject if EDA amplitude too high (movement artifact)
if epoch['EDA_Phasic'].abs().max() < 5.0: # Threshold
# Example: reject if heart rate change too large (invalid)
if epoch['ECG_Rate'].max() - epoch['ECG_Rate'].min() < 50:
clean_epochs[key] = epoch
print(f"Kept {len(clean_epochs)}/{len(epochs)} epochs")
# Analyze clean epochs
results = nk.ecg_eventrelated(clean_epochs)
Cognitive psychology:
Affective neuroscience:
Clinical research:
Psychophysiology:
Human-computer interaction: