Comprehensive PPG Analysis ========================== .. raw:: html Colab Notebook In this tutorial we will learn how to extract biomarkers from a photoplethysmogram (PPG) signal. Our objectives are to: * Detect the standard fiducial points on PPG pulse waves * Calculate pulse wave biomarkers from the fiducial points * Saving data in different data format You can use the sample PPG data by downloading it from the following link: `Sample PPG data `__. Setup ______ Import Python packages: ----------------------- * Install the pyPPG toolbox for PPG analysis .. code-block:: python pip install pyPPG==1.0.41 * Import required components from pyPPG .. code-block:: python from pyPPG import PPG, Fiducials, Biomarkers from pyPPG.datahandling import load_data, plot_fiducials, save_data import pyPPG.preproc as PP import pyPPG.fiducials as FP import pyPPG.biomarkers as BM import pyPPG.ppg_sqi as SQI * Import other packages .. code-block:: python import numpy as np import sys import json import pandas as pd Setup input parameters: ----------------------- The following input parameters are inputs to the `pyPPG.example `__ module (see the documentation for further details). .. code-block:: python data_path = "Sample_PPG_MAT_125Hz.mat" # the path of the file containing the PPG signal to be analysed start_sig = 0 # the first sample of the signal to be analysed end_sig = -1 # the last sample of the signal to be analysed (here a value of '-1' indicates the last sample) savingfolder = 'temp_dir' savingformat = 'csv' Loading a raw PPG signal: ------------------------- .. code-block:: python # Load the raw PPG signal signal = load_data(data_path=data_path, start_sig=start_sig, end_sig=end_sig, use_tk=False) signal.v = signal.v [0:20*signal.fs] # 20 second long signal to be analysed Plot the raw PPG signal: ------------------------ .. code-block:: python # import plotting package from matplotlib import pyplot as plt # setup figure fig, ax = plt.subplots() # create time vector t = np.arange(0, len(signal.v))/signal.fs # plot raw PPG signal ax.plot(t, signal.v, color = 'blue') ax.set(xlabel = 'Time (s)', ylabel = 'raw PPG') # show plot plt.show() .. image:: raw_PPG.png :align: center PPG signal processing _______________________ Prepare the PPG data: --------------------- Filter the PPG signal and obtain first, second and third derivatives (vpg, apg, and jpg respectively). .. code-block:: python signal.filtering = True # whether or not to filter the PPG signal signal.fL=0.5000001 # Lower cutoff frequency (Hz) signal.fH=12 # Upper cutoff frequency (Hz) signal.order=4 # Filter order signal.sm_wins={'ppg':50,'vpg':10,'apg':10,'jpg':10} # smoothing windows in millisecond for the PPG, PPG', PPG", and PPG'" prep = PP.Preprocess(fL=signal.fL, fH=signal.fH, order=signal.order, sm_wins=signal.sm_wins) signal.ppg, signal.vpg, signal.apg, signal.jpg = prep.get_signals(s=signal) Plot the derived signals .. code-block:: python # setup figure fig, (ax1,ax2,ax3,ax4) = plt.subplots(4, 1, sharex = True, sharey = False) # create time vector t = np.arange(0, len(signal.ppg))/signal.fs # plot filtered PPG signal ax1.plot(t, signal.ppg) ax1.set(xlabel = '', ylabel = 'PPG') # plot first derivative ax2.plot(t, signal.vpg) ax2.set(xlabel = '', ylabel = 'PPG\'') # plot second derivative ax3.plot(t, signal.apg) ax3.set(xlabel = '', ylabel = 'PPG\'\'') # plot third derivative ax4.plot(t, signal.jpg) ax4.set(xlabel = 'Time (s)', ylabel = 'PPG\'\'\'') # show plot plt.show() .. image:: PPG_derivs.png :align: center Store the derived signals in a class .. code-block:: python # Initialise the correction for fiducial points corr_on = ['on', 'dn', 'dp', 'v', 'w', 'f'] correction=pd.DataFrame() correction.loc[0, corr_on] = True signal.correction=correction # Create a PPG class s = PPG(signal) Identify fiducial points: -------------------------- Initialise the fiducials package .. code-block:: python fpex = FP.FpCollection(s=s) Extract fiducial points .. code-block:: python fiducials = fpex.get_fiducials(s=s) Display the results .. code-block:: python print("Fiducial points:\n",fiducials + s.start_sig) # here the starting sample is added so that the results are relative to the start of the original signal (rather than the start of the analysed segment) Plot fiducial points: ---------------------- .. code-block:: python # Create a fiducials class fp = Fiducials(fp=fiducials) # Plot fiducial points plot_fiducials(s, fp, savingfolder, legend_fontsize=12) PPG fiducial points .. image:: PPG_MAT_sample.png :align: center Calculate PPG SQI: _________________________ .. code-block:: python # Get PPG SQI ppgSQI = round(np.mean(SQI.get_ppgSQI(ppg=s.ppg, fs=s.fs, annotation=fp.sp)) * 100, 2) print('Mean PPG SQI: ', ppgSQI, '%') Calculate PPG biomarkers: _________________________ .. code-block:: python # Init the biomarkers package bmex = BM.BmCollection(s=s, fp=fp) # Extract biomarkers bm_defs, bm_vals, bm_stats = bmex.get_biomarkers() tmp_keys=bm_stats.keys() print('Statistics of the biomarkers:') for i in tmp_keys: print(i,'\n',bm_stats[i]) # Create a biomarkers class bm = Biomarkers(bm_defs=bm_defs, bm_vals=bm_vals, bm_stats=bm_stats) Save PPG data: ______________ .. code-block:: python # Save PPG struct, fiducial points, biomarkers fp_new = Fiducials(fp.get_fp() + s.start_sig) # here the starting sample is added so that the results are relative to the start of the original signal (rather than the start of the analysed segment) save_data(s=s, fp=fp_new, bm=bm, savingformat=savingformat, savingfolder=savingfolder) Extracted fiducial points .. image:: FID_vals.png :align: center Extracted biomarkers .. image:: BM_vals.png :align: center Biomarkers statistics .. image:: BM_stats.png :align: center Biomarkers definitions .. image:: BM_defs.png :align: center