Note
Click here to download the full example code
PPG pipeline¶
Warning
Include code to show how to create a pipeline to clean an ecg signal. It is probably in one of the jupyter notebooks (maybe ecg_qc.ipynb).
Load the data¶
17 # First, lets load the data (ppg sample data)
18
19 # Libraries
20 import pandas as pd
21
22 # Load data
23 #data = pd.read_csv(path)
Preprocessing¶
Wearable devices need some time to pick up stable signals. For this reason, it is a common practice to trim the data. In the following example, the f first and last 5 minutes of each recording are trimmed to exclude unstable signals.
35 # Trim data
36 #data = trim(data, start=5, end=5)
Now, lets remove the following noise:
PLETHis 0 or unchanged values for xxx time
SpO2< 80
Pulse> 200 bpm orPulse< 40 bpm
Perfusion< 0.2
Lost connection: sampling rate reduced due to (possible) Bluetooth connection lost. Timestamp column shows missing timepoints. If the missing duration is larger than 1 cycle (xxx ms), recording is split. If not, missing timepoints are interpolated.
50 # Remove invalid PLETH
51 #idxs_1 = data.PLETH == 0
52 #idxs_2 = unchanged(period=xxxx)
53 #data = data[~(idxs_1 | idxs_2)]
54
55 # Remove invalid ranges
56 #data = data[data.SpO2>=80]
57 #data = data[data.Pulse.between(40, 200)]
58 #data = data[data.Perfusion>=0.2]
59
60 # Remove lost connection
61 #data = data[lost_connection(min_fs, max_fs) ??
62
63 # The recording is then split into files.
Lets filter the data with a band pass filter; high pass filter (cut off at 1Hz)
Lets detrend the signal
71 # Lets split the data
72 #4.1. Cut data by time domain. Split data into sub segments of 30 seconds
73 #4.2. Apply the peak and trough detection methods in peak_approaches.py to get single PPG cycles in each segment
74 #4.3. Shift baseline above 0 and tapering each single PPG cycle to compute the mean template
75 #Notes: the described process is implemented in split_to_segments.py
SQI scores¶
Lets compute the SQI scores
Visualization¶
Final notes¶
Initially, it might have a lot of code. If the library grows, as Stefan mentioned it might be possible to create a generalised pipeline from sub-methods or classes. Or allow the user to configure the process and then automate all the run.
97 # Create steps
98 #step1 = Trim(start=5, end=5)
99 #step2 = Unchanged(param1=x, param2=y)
100 #step3 = LostConnection(param1=20, param2=30)
101
102 # Create pipeline
103 #pipe = Pipeline(steps=[('step1', step1),
104 # ('step2', step2),
105 # ('step3', step3))
106
107 # Data
108 #data = pipe.fit_transform(data)
Total running time of the script: ( 0 minutes 0.001 seconds)