[Python] Downsampling PPG peaks with python

Discussão em 'Python' iniciado por Stack, Fevereiro 18, 2025.

  1. Stack

    Stack Membro Participativo

    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))

    Continue reading...

Compartilhe esta Página