NeuroKit Logo
latest
  • Introduction
    • Quick Example
    • Installation
    • Contributing
    • Documentation
      • General
      • Examples
    • Citation
    • Physiological Data Preprocessing
      • Simulate physiological signals
      • Electrodermal Activity (EDA/GSR)
      • Cardiac activity (ECG)
      • Respiration (RSP)
      • Electromyography (EMG)
      • Photoplethysmography (PPG/BVP)
      • Electrooculography (EOG)
      • Electrogastrography (EGG)
    • Physiological Data Analysis
      • Event-related
      • Interval-related
    • Miscellaneous
      • Heart Rate Variability (HRV)
      • ECG Delineation
      • Signal Processing
      • Complexity (Entropy, Fractal Dimensions, …)
      • Signal Decomposition
      • Signal Power Spectrum Density (PSD)
      • Statistics
    • Popularity
    • Notes
  • Authors
    • Core team
    • Contributors
  • Installation
    • 1. Python
      • Windows
        • Winpython
        • Miniconda or Anaconda
      • Mac OS
    • 2. NeuroKit
  • Get Started
    • Get familiar with Python in 10 minutes
      • Setup
      • Variables
      • Variables and data types
      • Lists and dictionnaries
      • Basic indexing
      • Indexing starts from 0
      • Control flow (if and else)
      • For loops
      • Functions
      • Packages
      • Lists vs. vectors (arrays)
      • Conditional indexing
      • Dataframes
      • Reading data
      • Next steps
    • Where to start
  • Examples
    • Try the examples in your browser
    • 1. Analysis Paradigm
      • a) Event-related paradigm
      • b) Interval-related paradigm
    • 2. Biosignal Processing
      • a) Custom processing pipeline
    • 3. Heart rate and heart cycles
      • a) Detecting components of the cardiac cycle
      • b) Looking closer at heart beats
    • 4. Electrodermal activity
      • a) Extracting information in EDA
    • 5. Respiration rate and respiration cycles
      • a) Extracting Respiration Rate Variability metrics
    • 6. Muscle activity
    • Simulate Artificial Physiological Signals
      • Cardiac Activity (ECG)
      • Respiration (RSP)
      • Electromyography (EMG)
      • Electrodermal Activity (EDA)
    • Customize your Processing Pipeline
      • The Default NeuroKit processing pipeline
      • Building your own process() function
      • Changing the processing parameters
      • Customize even more!
    • Event-related Analysis
      • The Dataset
      • Find Events
      • Process the Signals
      • Create Epochs
      • Extract Event Related Features
      • Plot Event Related Features
      • Important remarks:
    • Interval-related Analysis
      • The Dataset
      • Process the Signals
      • Extract Features
      • Optional: Segmenting the Data
    • Analyze Electrodermal Activity (EDA)
      • Extract the cleaned EDA signal
      • Locate Skin Conductance Response (SCR) features
      • Decompose EDA into Phasic and Tonic components
      • Quick Plot
    • Analyze Respiratory Rate Variability (RRV)
      • Download Data and Extract Relevant Signals
      • Analyse RRV
        • See documentation for full reference
    • ECG-Derived Respiration (EDR) Analysis
      • Download ECG Data
      • Extraction of ECG Features
      • Analyse EDR
    • Extract and Visualize Individual Heartbeats
      • Extract the cleaned ECG signal
      • Extract R-peaks location
      • Segment the signal around the heart beats
      • Advanced Plotting
        • Custom colors and legend
        • Interactivity
    • How to create epochs
      • One signal with multiple event markings
      • One subject with multiple data files
    • Complexity Analysis of Physiological Signals
      • Basic Concepts
        • Definitions
        • Time-delay embedding
        • Embedding Parameters
      • Entropy as measures of Complexity
        • Shannon Entropy (ShEn)
        • Approximate Entropy (ApEn)
        • Sample Entropy (SampEn)
        • Fuzzy Entropy (FuzzyEn)
        • Multiscale Entropy (MSE)
      • Detrended Fluctuation Analysis (DFA)
    • Analyze Electrooculography EOG data (eye blinks, saccades, etc.)
      • Explore the EOG signal
      • Clean the signal
      • Detect and visualize eye blinks
    • Fit a function to a signal
      • Fit a linear function
      • Non-linear curves
  • Resources
    • Recording good quality signals
      • Recording
      • Signal quality
      • Artifacts and Anomalies
    • What software for physiological signal processing
      • Software vs. programming language (packages)
      • GUI vs. code
      • Matlab vs. Python vs. R vs. Julia
    • Additional Resources
      • General Neuroimaging
      • ECG
      • EDA
      • EEG
  • Functions
    • ECG
    • PPG
    • HRV
    • RSP
    • EDA
    • EMG
    • EEG
    • Signal Processing
    • Events
    • Data
    • Epochs
    • Statistics
    • Complexity
    • Miscellaneous
  • Benchmarks
    • Benchmarking of ECG Preprocessing Methods
      • Introduction
      • Databases
        • Glasgow University Database
        • MIT-BIH Arrhythmia Database
        • MIT-BIH Normal Sinus Rhythm Database
        • Concanate them together
      • Study 1: Comparing Different R-Peaks Detection Algorithms
        • Procedure
        • Results
        • Conclusion
      • Study 2: Normalization
        • Procedure
        • Results
        • Conclusion
    • References
  • Datasets
    • ECG (1000 hz)
    • ECG - pandas (3000 hz)
    • Event-related (4 events)
    • Resting state (5 min)
    • Resting state (8 min)
  • Contributing
    • Understanding NeuroKit
      • 1. readthedocs
        • Example
      • 2. The code on Github
        • Example
      • 3. The code on YOUR machine
        • Python directory
        • Windows
        • Mac
        • Example
    • Contributing guide
      • NeuroKit’s style
        • Structure and code
        • Run code checks
        • Avoid Semantic Errors
        • Development workflow
      • How to use GitHub to contribute
        • Step 1: Fork it
        • Step 2: Clone it
        • Step 3: Find it and fix it
        • Step 4: Commit it and push it
        • Step 4: Create pull request
        • Step 5: Let’s do it
      • Useful reads
      • What’s next?
    • Ideas for first contributions
      • Look for “good first contribution” issues
      • Improving documentation
      • Adding tests
      • Adding examples and tutorials
        • How to write
        • Where to add the files
NeuroKit
  • Docs »
  • Examples »
  • Event-related Analysis
  • Edit on GitHub

Event-related Analysis¶

This example shows how to use Neurokit to extract epochs from data based on events localisation and its corresponding physiological signals. That way, you can compare experimental conditions with one another.

[1]:
# Load NeuroKit and other useful packages
import neurokit2 as nk
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
[2]:
plt.rcParams['figure.figsize'] = [15, 5]  # Bigger images
plt.rcParams['font.size']= 14

The Dataset¶

Use the nk.data() function to load the dataset located on Neurokit data folder.

It contains 2.5 minutes of biosignals recorded at a frequency of 100Hz (2.5 x 60 x 100 = 15000 data points).

Biosignals : ECG, RSP, EDA + Photosensor (event signal)

[3]:
# Get data
data = nk.data("bio_eventrelated_100hz")

This is the data from 1 participant to whom was presented 4 images (emotional stimuli, IAPS-like emotional faces), which we will refer to as events.

Importantly, the images were marked by a small black rectangle on the screen, which led to the photosensor signal to go down (and then up again after the image). This is what will allow us to retrieve the location of these events.

They were 2 types (the condition) of images that were shown to the participant: “Negative” vs. “Neutral” in terms of emotion. Each picture was presented for 3 seconds. The following list is the condition order.

[4]:
condition_list = ["Negative", "Neutral", "Neutral", "Negative"]

Find Events¶

These events can be localized and extracted using events_find().

Note that you should also specify whether to select events that are higher or below the threshold using the ``threshold_keep`` argument.

[5]:
# Find events
events = nk.events_find(data["Photosensor"], threshold_keep='below', event_conditions=condition_list)
events
[5]:
{'onset': array([ 1024,  4957,  9224, 12984]),
 'duration': array([300, 300, 300, 300]),
 'label': array(['1', '2', '3', '4'], dtype='<U11'),
 'condition': ['Negative', 'Neutral', 'Neutral', 'Negative']}

As we can see, events_find() returns a dict containing onsets and durations for each corresponding event, based on the label for event identifiers and each event condition. Each event here lasts for 300 data points (equivalent to 3 seconds sampled at 100Hz).

[6]:
# Plot the location of event with the signals
plot = nk.events_plot(events, data)
../_images/examples_eventrelated_13_0.png

The output of events_plot() shows the corresponding events in the signal, with the blue dashed line representing a Negative event and red dashed line representing a Neutral event.

Process the Signals¶

Now that we have the events location, we can go ahead and process the data.

Biosignals processing can be done quite easily using NeuroKit with the bio_process() function. Simply provide the appropriate biosignal channels and additional channels that you want to keep (for example, the photosensor), and bio_process() will take care of the rest. It will return a dataframe containing processed signals and a dictionary containing useful information.

[7]:
# Process the signal
df, info = nk.bio_process(ecg=data["ECG"], rsp=data["RSP"], eda=data["EDA"], sampling_rate=100)

# Visualize
df.plot()
                                            # theres is a ton of features now, but not in epochs
[7]:
<matplotlib.axes._subplots.AxesSubplot at 0x1c6b9b8c898>
../_images/examples_eventrelated_17_1.png

Create Epochs¶

We now have to transform this dataframe into epochs, i.e. segments (chunks) of data around the events using epochs_create().

1. We want it to start *1 second before the event onset*

2. and end *6 seconds* afterwards

These are passed into the epochs_start and epochs_end arguments, respectively.

Our epochs will then cover the region from -1 s to +6 s (i.e., 700 data points since the signal is sampled at 100Hz).

[8]:
# Build and plot epochs
epochs = nk.epochs_create(df, events, sampling_rate=100, epochs_start=-1, epochs_end=6)

Let’s plot some of the signals of the first epoch (and transform them to the same scale for visualization purposes).

[9]:
for i, epoch in enumerate (epochs):
    epoch = epochs[epoch]  # iterate epochs",

    epoch = epoch[['ECG_Clean', 'ECG_Rate', 'RSP_Rate',
                   'RSP_Phase', 'EDA_Phasic', 'EDA_Tonic']]  # Select relevant columns",

    title = events['condition'][i] # get title from condition list",

    nk.standardize(epoch).plot(title=title, legend=True)  # Plot scaled signals"
../_images/examples_eventrelated_22_0.png
../_images/examples_eventrelated_22_1.png
../_images/examples_eventrelated_22_2.png
../_images/examples_eventrelated_22_3.png

Extract Event Related Features¶

With these segments, we are able to compare how the physiological signals vary across the different events. We do this by: 1. Iterating through our object epochs

  1. Storing the mean value of :math:`X` feature of each condition in a new dictionary

  2. Saving the results in a readable format

We can call them epochs-dictionary, the mean-dictionary and our results-dataframe.

[10]:
df = {}  # Initialize an empty dict,

for epoch_index in epochs:
    df[epoch_index] = {}  # then Initialize an empty dict inside of it with the iterative

    # Save a temp var with dictionary called <epoch_index> in epochs-dictionary
    epoch = epochs[epoch_index]

    # We want its features:

    # Feature 1 ECG
    ecg_baseline = epoch["ECG_Rate"].loc[-100:0].mean()  # Baseline
    ecg_mean = epoch["ECG_Rate"].loc[0:400].mean()  # Mean heart rate in the 0-4 seconds
    # Store ECG in df
    df[epoch_index]["ECG_Rate"] = ecg_mean - ecg_baseline  # Correct for baseline


    # Feature 2 EDA - SCR
    scr_max = epoch["SCR_Amplitude"].loc[0:600].max()  # Maximum SCR peak
    # If no SCR, consider the magnitude, i.e.  that the value is 0
    if np.isnan(scr_max):
        scr_max = 0
    # Store SCR in df
    df[epoch_index]["SCR_Magnitude"] = scr_max

    # Feature 3 RSP
    rsp_baseline = epoch["RSP_Rate"].loc[-100:0].mean()  # Baseline
    rsp_rate = epoch["RSP_Rate"].loc[0:600].mean()
    # Store RSP in df
    df[epoch_index]["RSP_Rate"] = rsp_rate - rsp_baseline  # Correct for baseline


df = pd.DataFrame.from_dict(df, orient="index")  # Convert to a dataframe
df["Condition"] = condition_list  # Add the conditions
df  # Print DataFrame
[10]:
ECG_Rate SCR_Magnitude RSP_Rate Condition
1 -4.286137 3.114808 2.729480 Negative
2 -5.387987 0.000000 2.094437 Neutral
3 -1.400696 0.000000 -0.062720 Neutral
4 -3.804883 1.675922 -1.674218 Negative

Plot Event Related Features¶

You can now plot and compare how these features differ according to the event of interest.

[11]:
sns.boxplot(x="Condition", y="ECG_Rate", data=df)
[11]:
<matplotlib.axes._subplots.AxesSubplot at 0x1c6bd25e828>
../_images/examples_eventrelated_28_1.png
[12]:
sns.boxplot(x="Condition", y="RSP_Rate", data=df)
[12]:
<matplotlib.axes._subplots.AxesSubplot at 0x1c6bd673c50>
../_images/examples_eventrelated_29_1.png
[13]:
sns.boxplot(x="Condition", y="SCR_Magnitude", data=df)
[13]:
<matplotlib.axes._subplots.AxesSubplot at 0x1c6a621a160>
../_images/examples_eventrelated_30_1.png

Then interpret : As we can see, there seems to be a difference between the negative and the neutral pictures. Negative stimuli, as compared to neutral stimuli, were related to a stronger cardiac deceleration (i.e., higher heart rate variability), an accelerated breathing rate, and higher SCR magnitude.

Important remarks:¶

You can’t break anything if you’re on Binder, so have fun. Keep in mind that this is for illustration purposes only.

Data size limits on Github force us to downsample and have only one participant (sample rate would have to be >250 Hz, and you can’t do stats with 4 observations in 1 subjects).

We invite you to read on reporting guidelines for biosignal measures. For ECG-PPG/HRV : Quintana, Alvarez & Heathers, 2016 - GRAPH

Next Previous

© Copyright 2020, Dominique Makowski Revision a90f157b.