# Configure Plotly to render inline figures via CDN so they display
# in the rendered Sphinx output (RTD).  Safe to ignore when running
# locally in Jupyter.
import plotly.io as pio
pio.renderers.default = 'notebook_connected'

Example analysis of a PPG/ECG waveform using the vital_sqi package

The following notebook shows an example of PPG/ECG waveform processing using the vital_sqi package. The aim of the package is to automate signal quality classification for PPG/ECG waveforms. It is achieved by computing various signal quality indices for each signal segment and using them to form a decision.

The pipeline can be briefly summarized as follows:

  1. Load dataset under analysis

  2. Preprocess and segment the dataset

  3. Compute SQI for each dataset segment

  4. Make decision for each segment

Global Imports

import numpy as np
import warnings
import os
import pandas as pd 
import matplotlib.pyplot as plt
import vital_sqi
from vital_sqi.data.signal_io import ECG_reader,PPG_reader

Start by importing the signal via the PPG_reader function

The function expects a .csv or similar data format with named columns. The column names are used to separate between data column, timestamp columns and any additional information columns. This returns a SignalSQI class that is compatible with other vital_sqi package functions, the main class members of interest are:

  • signals: an ndarray of shape (m, n) where m is the number of rows and n is the number of channels of the signal

  • sqis: an ndarray of shape (m, n) where m is the number of signal segments, n is the number of SQIs.

  • sampling_rate: sampling rate in hertz (Hz)

from vital_sqi.pipeline.pipeline_highlevel import get_ppg_sqis

file_in = os.path.abspath('test_data/ppg_smartcare.csv') #FIle input location
sqi_dict = os.path.abspath('test_data/sqi_dict.json') #input dictionary -> which sqi features 
segments, signal_obj = get_ppg_sqis(file_in,
                                    signal_idx=['PLETH'], 
                                    timestamp_idx=['TIMESTAMP_MS'], 
                                    sqi_dict_filename = sqi_dict)
  0%|          | 0/21 [00:00<?, ?it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 14%|█▍        | 3/21 [00:00<00:00, 22.14it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 29%|██▊       | 6/21 [00:00<00:00, 23.38it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 43%|████▎     | 9/21 [00:00<00:00, 24.49it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 57%|█████▋    | 12/21 [00:00<00:00, 25.77it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 71%|███████▏  | 15/21 [00:00<00:00, 25.59it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 86%|████████▌ | 18/21 [00:00<00:00, 25.73it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
100%|██████████| 21/21 [00:00<00:00, 26.59it/s]
100%|██████████| 21/21 [00:00<00:00, 25.54it/s]

signal_obj.sqis[0].describe()
perfusion kurtosis_1 skewness_mean_sqi skewness_median_sqi skewness_std_sqi entropy kurtosis_2 skewness_1 signal_to_noise ectopic ... hr_median hr_min hr_max hr_range sd1 sd2 area ratio start_idx end_idx
count 21.000000 21.000000 21.000000 21.000000 21.000000 21.000000 21.000000 21.000000 21.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 21.000000 21.000000
mean 187.404653 -0.672482 0.070404 0.075317 0.101161 1.977680 -0.966196 0.086825 2.035108 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 30000.000000 32917.761905
std 20.712381 0.691682 0.042471 0.029481 0.116187 0.088978 0.395934 0.113371 0.732970 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 18614.510469 18478.664053
min 112.313216 -1.356624 -0.038761 0.016719 0.023804 1.753606 -1.349569 -0.318782 1.643501 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 0.000000 3000.000000
25% 183.541473 -1.103032 0.058056 0.055595 0.034796 1.941826 -1.277692 0.063396 1.745911 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 15000.000000 18000.000000
50% 186.970824 -0.999315 0.069111 0.071990 0.057725 2.005315 -1.103788 0.081037 1.861523 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 30000.000000 33000.000000
75% 195.615534 -0.308043 0.079637 0.086653 0.125601 2.021756 -0.822027 0.132159 1.987712 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 45000.000000 48000.000000
max 215.095923 1.112154 0.151694 0.141310 0.527707 2.139797 0.067313 0.269913 5.115181 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 60000.000000 61273.000000

8 rows × 40 columns

Get decision

from vital_sqi.pipeline.pipeline_highlevel import get_qualified_ppg
rule_dict_filename = os.path.abspath('test_data/rule_dict_test.json') #  location dictionary contain threshold
ruleset_order = {3: 'skewness_1',
                  2: 'entropy',
                  1: 'perfusion'}
file_in = os.path.abspath('test_data/ppg_smartcare.csv') #FIle input location
sqi_dict = os.path.abspath('test_data/sqi_dict.json') #input dictionary -> which sqi features 
signal_obj = get_qualified_ppg(file_in,
                                    signal_idx=['PLETH'], 
                                    timestamp_idx=['TIMESTAMP_MS'], 
                                    sqi_dict_filename = sqi_dict,
                                    rule_dict_filename = rule_dict_filename,
                                    ruleset_order=ruleset_order,
                                    output_dir=None)
  0%|          | 0/21 [00:00<?, ?it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 14%|█▍        | 3/21 [00:00<00:00, 24.40it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 29%|██▊       | 6/21 [00:00<00:00, 24.45it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 43%|████▎     | 9/21 [00:00<00:00, 25.44it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 57%|█████▋    | 12/21 [00:00<00:00, 26.72it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 71%|███████▏  | 15/21 [00:00<00:00, 26.05it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
 86%|████████▌ | 18/21 [00:00<00:00, 25.94it/s]
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
WARNING:root:No Q valleys available for P peak detection.
WARNING:root:No S valleys available for T peak detection.
WARNING:root:No Q or S sessions detected for QRS session detection.
100%|██████████| 21/21 [00:00<00:00, 26.71it/s]
100%|██████████| 21/21 [00:00<00:00, 26.10it/s]

Saving segments: 0it [00:00, ?it/s]
Saving segments: 0it [00:00, ?it/s]

Saving segments:   0%|          | 0/21 [00:00<?, ?it/s]
Saving segments:  76%|███████▌  | 16/21 [00:00<00:00, 159.90it/s]
Saving segments: 100%|██████████| 21/21 [00:00<00:00, 161.00it/s]

signal_obj.sqis[0].describe()
perfusion kurtosis_1 skewness_mean_sqi skewness_median_sqi skewness_std_sqi entropy kurtosis_2 skewness_1 signal_to_noise ectopic ... hr_median hr_min hr_max hr_range sd1 sd2 area ratio start_idx end_idx
count 21.000000 21.000000 21.000000 21.000000 21.000000 21.000000 21.000000 21.000000 21.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 21.000000 21.000000
mean 187.404653 -0.672482 0.070404 0.075317 0.101161 1.977680 -0.966196 0.086825 2.035108 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 30000.000000 32917.761905
std 20.712381 0.691682 0.042471 0.029481 0.116187 0.088978 0.395934 0.113371 0.732970 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 18614.510469 18478.664053
min 112.313216 -1.356624 -0.038761 0.016719 0.023804 1.753606 -1.349569 -0.318782 1.643501 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 0.000000 3000.000000
25% 183.541473 -1.103032 0.058056 0.055595 0.034796 1.941826 -1.277692 0.063396 1.745911 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 15000.000000 18000.000000
50% 186.970824 -0.999315 0.069111 0.071990 0.057725 2.005315 -1.103788 0.081037 1.861523 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 30000.000000 33000.000000
75% 195.615534 -0.308043 0.079637 0.086653 0.125601 2.021756 -0.822027 0.132159 1.987712 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 45000.000000 48000.000000
max 215.095923 1.112154 0.151694 0.141310 0.527707 2.139797 0.067313 0.269913 5.115181 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 60000.000000 61273.000000

8 rows × 40 columns