I have a PPG data series and I have extracted the R-R peaks with 100Hz frequency. I have estimate the peaks using Neurokit:
import neurokit2 as nk
ini_fs=100
signals, info = nk.ppg_process(ppg_signal, sampling_rate=ini_fs)
ppg_interval=0.01 # seconds per sample
time= np.arange(0, len(ppg_signal) * ppg_interval, ppg_interval) # time in seconds
ppg_peaks=info['PPG_Peaks']
print(ppg_peaks) # indices where PPG peaks are
[ 38 173 308 431 551 676 815 960 1099 1236 1370 1498
1621 1746 1872 1997 2121 2245 2371 2499 2626 2751 2879 3012
3154 3289 3419 3554 3696 3839 3978 4116 4247 4370 4492 4617
4749 4883 5024 5163 5297 5431 5571 5712 5847 5973 6101 6233
6365 6492 6625 6762 6901 7034 7173 7316 7454 7585 7716 7848
7976 8105 8239 8369 8492 8616 8743 8867 8990 9119 9248 9371
9490 9612 9734 9860 9987 10116 10250 10387 10528 10665 10802 10942
11083 11219 11356 11495 11637 11773 11915 12063 12208 12347 12496 12646
12793 12936 13081 13222 13357 13486 13616 13747 13874 13999 14133 14272
14404 14535 14669 14806 14935 15063 15188 15311 15438 15575 15707 15840
15976 16107 16232 16355 16478 16597 16712 16826 16935 17043 17156 17270
17392 17528 17669 17808 17953 18095 18234 18364 18493 18625 18764 18903
19034 19171 19322 19470 19619 19771 19925 20071 20220 20367 20510 20652.....71366]
ppi_intervals = np.diff(ppg_peaks) / fppg # Convert peak indices to time intervals (seconds)
ppi_timestamps = np.cumsum(ppi_intervals) # Time of each PPI event in seconds
print(ppi_timestamps) # time of peaks in seconds from start of recording
[ 1.35 2.7 3.93 5.13 6.38 7.77 9.22 10.61 11.98 13.32 14.6 15.83 17.08 18.34 19.59 20.83 22.07 23.33 24.61 25.88
27.13 28.41 29.74 31.16 32.51 33.81 35.16 36.58 38.01 39.4
40.78 42.09 43.32 44.54 45.79 47.11 48.45 49.86 51.25 52.59
53.93 55.33 56.74 58.09 59.35 60.63 61.95 63.27 64.54 65.87
67.24 68.63 69.96 71.35 72.78 74.16 75.47 76.78 78.1 79.38
80.67 82.01 83.31 84.54 85.78 87.05 88.29 89.52 90.81 92.1
93.33 94.52 95.74 96.96 98.22 99.49 100.78 102.12 103.49 104.9
106.27 107.64 109.04 110.45 111.81 113.18 114.57 115.99 117.35 118.77
120.25 121.7 123.09 124.58 126.08 127.55 128.98 130.43 131.84 133.19
134.48 135.78 137.09 138.36 139.61 140.95 142.34 143.66 144.97 146.31
147.68 148.97 150.25 151.5 152.73 154. 155.37 156.69 158.02 159.38
160.69 161.94 163.17 164.4 165.59 166.74 167.88 168.97 170.05 171.18
172.32 173.54 174.9 176.31 177.7 179.15 180.57 181.96 183.26 184.55
185.87 187.26 188.65 189.96 191.33 192.84 194.32 195.81 197.33 198.87
200.33 201.82 203.29 204.72 206.14 207.59 209.05 210.44 211.83 213.23
214.66 216.06 217.45 218.9 220.37 221.77 223.14 224.53 225.92 227.23, ..713.28]
Now I want to downsample this to 2 Hz but the peaks are not in equidistant locations so I am not sure what the next steps are. Do I interpolate first and then downsample? I can not downsample the original ppg signal as I will lose a lot of the peaks.
Edit: If you want to create a synthetic PPG signal to test the code:
import numpy as np
import matplotlib.pyplot as plt
fs = 100 # Sampling frequency in Hz
duration = 10 * 60 # 10 minutes in seconds
heart_rate = 45 # BPM
ppg_freq = heart_rate / 60 # Convert BPM to Hz
t = np.linspace(0, duration, duration * fs) #time vector
ppg_signal = 0.6 * np.sin(2 * np.pi * ppg_freq * t) + \
0.2 * np.sin(4 * np.pi * ppg_freq * t) + \
0.1 * np.sin(6 * np.pi * ppg_freq * t)
# Add random noise to simulate real PPG signal variations
ppg_signal += 0.05 * np.random.randn(len(t))