# 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:
Load dataset under analysis
Preprocess and segment the dataset
Compute SQI for each dataset segment
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