Ejemplo n.º 1
0
    def get_heartrate_and_breathing(self, data):
        framerate = self.framerate
        if self.resample != -1:
            data = resample(data,
                            (len(data) // self.framerate) * self.resample)
            framerate = self.resample

        if self.filter:
            data = hp.filter_signal(data, [0.7, 3.5],
                                    sample_rate=framerate,
                                    order=3,
                                    filtertype='bandpass')
            data = hp.scale_data(data)

        wd, m = hp.process(data, framerate, high_precision=True, clean_rr=True)

        self.m = m
        self.wd = wd
        hr = m["bpm"]
        rr = m["breathingrate"]

        if self.show:
            hp.plotter(wd, m)

        if self.save_path != '':
            save_plot(data, x_label="Time", y_label="BVP Signal")

        return hr, rr * 60
Ejemplo n.º 2
0
def calculate_hr(signal_data, timestamps=None):
    sampling_rate = 47.63
    if timestamps is not None:
        sampling_rate = hp.get_samplerate_mstimer(timestamps)
        try:
            wd, m = hp.process(signal_data, sample_rate=sampling_rate)
            hr_bpm = m["bpm"]
        except:
            hr_bpm = 75.0

        if np.isnan(hr_bpm):
            hr_bpm = 75.0
        return hr_bpm

    else:
        # We are working with predicted HR:
        # need to filter and do other stuff.. lets see
        signal_data = hp.filter_signal(signal_data,
                                       cutoff=[0.7, 2.5],
                                       sample_rate=sampling_rate,
                                       order=6,
                                       filtertype='bandpass')
        try:
            wd, m = hp.process(signal_data,
                               sample_rate=sampling_rate,
                               high_precision=True,
                               clean_rr=True)
            hr_bpm = m["bpm"]
        except:
            print(
                "BadSignal received (could not be filtered) using def HR value = 75bpm"
            )
            hr_bpm = 75.0
        return hr_bpm
Ejemplo n.º 3
0
def upsample(data, low, high):
    # x = np.arange(low, high, 1/1000)
    # y = np.interp(x, data["Time"], data["PPG"])
    sf = len(data)/(high-low)
    y = hp.filter_signal(data["PPG"], [0.7, 3.5], sample_rate=sf, 
                            order=3, filtertype='bandpass')
    return y
Ejemplo n.º 4
0
def ppg_preprocessing(data, sampling_rate, low_pass=0.7, high_pass=2.5):
    filtered = hp.filter_signal(data, [low_pass, high_pass],
                                sample_rate=sampling_rate,
                                order=3,
                                filtertype='bandpass')

    return filtered
Ejemplo n.º 5
0
def clean_ppg(data: np.ndarray, sampling_rate: int, low_pass: float=0.7, high_pass: float=2.5):
    '''
    Removes high frequency noises

    It uses `heartpy <https://github.com/paulvangentcom/heartrate_analysis_python>` library

    Parameters
    -----------
    data: numpy.ndarray
        An 1D array of PPG data

    smpling_rate: int, default: 128
        sampling rate

    low_pass: float, default: 0.7
        The low cut frequency for filtering
    
    high_pass: float, default: 2.5
        The high cut frequency for filtering
    
    Returns
    -------
    cleaned_data: numpy.array
        An 1D array of cleaned PPG data

    '''
    filtered = hp.filter_signal(data,
                                [low_pass, high_pass],
                                sample_rate=sampling_rate,
                                order=3,
                                filtertype='bandpass')

    return filtered
Ejemplo n.º 6
0
def clean_ppg(data, sampling_rate, low_pass=0.7, high_pass=2.5):
    '''
    Removes high frequency noises
    '''
    filtered = hp.filter_signal(data,
                                [low_pass, high_pass],
                                sample_rate=sampling_rate,
                                order=3,
                                filtertype='bandpass')

    return filtered
Ejemplo n.º 7
0
 def analyse_data(self):
     try:
         sample_rate = 250
         data = hp.get_data('najnowszy2.csv')
         filtered = hp.filter_signal(
             data, cutoff=0.05, sample_rate=sample_rate, filtertype='notch')
         working_data, measures = hp.process(filtered, sample_rate)
         return data, working_data, measures
     except hp.exceptions.BadSignalWarning as err:
         print(err)
         return None, None, None
Ejemplo n.º 8
0
    def filter_ecg(self):
        """Applies a 0.5-30Hz, 2nd order bandpass filter to raw data."""

        print("\n" +
              "Filtering data with {}-{}Hz, 2nd order bandpass filter...".
              format(self.low_f, self.high_f))

        # Runs bandpass filter on data
        self.ecg_filtered = heartpy.filter_signal(
            data=[float(i) for i in self.ecg_raw],
            cutoff=[self.low_f, self.high_f],
            sample_rate=self.signal_frequency,
            filtertype="bandpass",
            order=2)
        print("Filtering complete.")
Ejemplo n.º 9
0
def filter_signal(filtered, sample_rate, data):
    """
    функция для избавляения от ненужных компонентов, не задевая QRS
    :param filtered: отфильтрованный ранее сигнал
    :param sample_rate: шаг
    :param data: первоначальные данные, используются для сранении при прописовке графиков
    :return: отфильтрованный сигнал
    """

    filtered = hp.filter_signal(filtered,
                                cutoff=0.05,
                                sample_rate=sample_rate,
                                filtertype='notch')
    # plt.figure(figsize=(12, 4))
    # plt.title('Original and Filtered signal')
    # plt.plot(data, label='original data')
    # plt.plot(filtered, alpha=0.5, label='filtered data')
    # plt.legend()

    return filtered
def filter_data(time, raw_volt):
    """This function filters out noise below 10 Hz and above 50Hz

    This filter takes the time and raw_volt data as input and
    filters out noises below 10 Hz and above 50 Hz using the heartpy
    function filter_signal. See documentation on the filter_signal function
    at: https://python-heart-rate-analysis-toolkit.readthedocs.io/en/
    latest/_modules/heartpy/filtering.html

    Args:
        time (list): list of time values for the ECG data
        volts (list): list of ECG voltage magnitudes

    Returns:
        list : the filtered ECG voltage values
    """
    logging.info('Filtering Data')
    sample_rate = 1 / (time[1] - time[0])
    volt = hp.filter_signal(raw_volt, [5, 20], sample_rate, 2, 'bandpass')
    return volt
Ejemplo n.º 11
0
    def get_bpm_estimate(self, time_data, cam_data):

        fps = hp.get_samplerate_datetime(time_data, '%S.%f')

        cam_bpm = 0

        filtered_ppg_r = hp.filter_signal(cam_data,
                                          cutoff=[0.8, 1],
                                          filtertype='bandpass',
                                          sample_rate=fps,
                                          order=4,
                                          return_top=False)
        try:
            working_data, measures = hp.process(cam_data, fps)
        except BadSignalWarning:
            print("Bad signal")
        else:
            if (measures['bpm'] > 40 and measures['bpm'] < 180):
                cam_bpm = measures['bpm']

        return filtered_ppg_r, cam_bpm
Ejemplo n.º 12
0
    def run_analysis(self, plot=False):

        # Filter the signal
        filtered = hp.filter_signal(self.data,
                                    cutoff=0.05,
                                    sample_rate=self.sample_rate,
                                    filtertype='notch')

        # Run analysis
        wd, m = hp.process(hp.scale_data(filtered), self.sample_rate)

        if plot:
            # Visualise in plot of custom size
            plt.figure(figsize=(12, 4))
            hp.plotter(wd, m)

        # Display computed measures
        for measure in m.keys():
            print('%s: %f' % (measure, m[measure]))

        return m
Ejemplo n.º 13
0
def process_ecg(data, show=False, framerate=BASE_FREQUENCY):
    filtered = hp.filter_signal(data, [0.7, 3.5],
                                sample_rate=framerate,
                                order=3,
                                filtertype='bandpass')
    #filtered = hp.remove_baseline_wander(filtered, FREQUENCY)
    wd, m = hp.process(hp.scale_data(filtered), framerate)
    if show:
        print(wd.keys())
        print(m.keys())
        hp.plotter(wd, m)

    save_plot(wd["breathing_signal"],
              str(framerate) + "breathing_signal_hp.png",
              framerate,
              x_label='Time (' + str(framerate) + 'hz)',
              y_label='Breathing Signal')

    hr = m["bpm"]
    rr = m["breathingrate"]
    RR_list = wd["RR_list"]

    return hr, rr, RR_list
Ejemplo n.º 14
0
    points = data_influx.get_points()
    analog_list = []
    time_list = []
    for p in points:
        analog_list.append(p['analog'])
        time_list.append(p['time'])
    analog_list.reverse()
    time_list.reverse()
    data = np.array(analog_list)
    datetime_data = np.array(time_list)

    fs = hp.get_samplerate_datetime(datetime_data,
                                    timeformat='%Y-%m-%dT%H:%M:%S.%fZ')

    filtered = hp.enhance_peaks(data, iterations=2)
    filtered = hp.filter_signal(filtered, cutoff=3, sample_rate=fs, order=2)
    try:
        working_data, measures = hp.process(filtered,
                                            fs,
                                            report_time=True,
                                            calc_freq=True)
    except:
        print("error calculating RR")
        sys.exit(0)

#     hp.plotter(working_data, measures)

    filtered_body = []
    for i in range(0, len(filtered)):
        point = {
            "measurement": "sensor_filtered",
Ejemplo n.º 15
0
    def analyze(self, a):

        # Correct the orientation of the frame.
        frame = np.fliplr(np.rot90(a))

        print('frame.shape = {}'.format(frame.shape))

        global camData, camBPMData, psData, psBPMData, time

        signal_window = frame[self.row:self.row + self.window,
                              self.column:self.column + self.window, :]

        if (LIGHT_COLOR == 'RED'):
            signal_window = signal_window[:, :, 0]
        elif (LIGHT_COLOR == 'BLUE'):
            signal_window = signal_window[:, :, 1]

        signal = np.mean(np.mean(signal_window))

        # shift data in the arrays one sample left
        camData[:-1] = camData[1:]
        camBPMData[:-1] = camBPMData[1:]
        psData[:-1] = psData[1:]
        psBPMData[:-1] = psBPMData[1:]
        time[:-1] = time[1:]

        camData[-1] = signal

        time[-1] = (datetime.now() - self.START_TIME).total_seconds()

        fps = 1 / (time[1] - time[0])

        cam_bpm = 0

        if (fps < 0):
            print('negative fps: {}'.format(fps))

        elif USE_RT_ANALYSIS:
            camSig = camData - np.mean(camData)
            filtered_ppg_r = hp.filter_signal(camSig,
                                              cutoff=[0.8, 1],
                                              filtertype='bandpass',
                                              sample_rate=fps,
                                              order=4,
                                              return_top=False)
            try:
                working_data, measures = hp.process(camSig, 10.0)
            except BadSignalWarning:
                print("Bad signal")
            else:
                if (measures['bpm'] > 50 and measures['bpm'] < 120):
                    cam_bpm = measures['bpm']

        data = pulseOx.get_data()

        psData[-1] = data['pulseWaveform']
        psBPMData[-1] = data['pulseRate']
        camBPMData[-1] = cam_bpm

        if (USE_GUI):
            ppg_gui.update(self.draw_window(frame), data_dict)

        writer.save_to_csv(data_dict)

        tracker.track_performance(False, True)
        print('(cam_bpm={} , fps={})'.format(int(cam_bpm), int(fps)))
Ejemplo n.º 16
0
def main(writer):
    """
    A function to extract the bpm from PPG data in a .csv file.
    
    Parameters
    ----------
    writer: PPG_Writer
            A PPG_Writer object initialized with the desired .csv file.
    """
    global bpms, snrs
    '''
    Get/Display raw data and sampling rate.
    '''
    # Acquire time-series data from the .csv file
    # Ignore the first second of data, since it's very different from the other data.
    timeData = writer.get_time_data()[30:]
    camDataRed = writer.get_cam_data_red()[30:]
    camDataGreen = writer.get_cam_data_green()[30:]
    pulseData = writer.get_pulseox_data()[30:]

    # Acquire sampling rate and ground truth BPM from the .csv file
    sampling_rate = hp.get_samplerate_datetime(timeData, '%S.%f')
    BPM_TRUTH = writer.get_bpm()

    # If desired, graph the raw PPG time-series data for both channels.
    if DISPLAY:
        plt.title("Raw PPG Data")
        #plt.plot(timeData, camDataRed,   "-r", label="Red")
        plt.plot(timeData, camDataGreen, "-g", label="Green")
        plt.legend(loc="lower right")
        plt.ylabel("Mean Pixel Intensity")
        plt.xlabel("Time (seconds)")
        plt.show()
    '''
    Interpolate PPG signals
    '''
    new_fs = 30
    sampling_interval = 1 / new_fs

    # Quantize beginning + ending time to the nearest multiple of sampling_interval.
    initial_time = int(timeData[0] * new_fs) / new_fs
    end_time = int(timeData[-1] * new_fs) / new_fs

    # Figure out number of samples.
    elapsed_time = end_time - initial_time
    num_samples = int(elapsed_time * new_fs) + 1

    # Generate uniform time scale and interpolation function
    uniform_time = np.linspace(initial_time,
                               end_time,
                               num=num_samples,
                               endpoint=True)
    f_red = interp1d(timeData, camDataRed, fill_value="extrapolate")
    f_green = interp1d(timeData, camDataGreen, fill_value="extrapolate")

    # Use interpolation function to generate wave.
    new_red = f_red(uniform_time)
    new_green = f_green(uniform_time)
    N = len(new_red)
    '''
    Filter/Enhance Signals
    '''

    # Filter the interpolated PPG signals with a [0.7, 4] Hz bandpass filter.
    LOWER_CUTOFF = 0.7
    UPPER_CUTOFF = 4
    new_red = hp.filter_signal(new_red,
                               cutoff=[LOWER_CUTOFF, UPPER_CUTOFF],
                               filtertype='bandpass',
                               sample_rate=new_fs,
                               order=4,
                               return_top=False)

    new_green = hp.filter_signal(new_green,
                                 cutoff=[LOWER_CUTOFF, UPPER_CUTOFF],
                                 filtertype='bandpass',
                                 sample_rate=new_fs,
                                 order=4,
                                 return_top=False)

    # If desired, graph the filtered PPG time-series for both color channels.
    if DISPLAY:
        plt.title("Filtered PPG Data")
        #plt.plot(uniform_time, new_red,   '-r', label='Red')
        plt.plot(uniform_time, new_green, '-g', label='Green')
        plt.legend(loc="lower right")
        plt.ylabel("Mean Pixel Intensity")
        plt.xlabel("Time (seconds)")
        plt.show()
    '''
    Take FFT of PPGs
    '''
    # Calculate FFT magnitude of both PPG signals.
    # Remove frequencies above the sampling frequency.
    fft_red = np.fft.fft(new_red) / N
    fft_green = np.fft.fft(new_green) / N
    fft_red = fft_red[range(N // 2)]
    fft_green = fft_green[range(N // 2)]
    fft_red = abs(fft_red)
    fft_green = abs(fft_green)

    # Get frequency axis corresponding to the FFTs.
    values = np.arange(N // 2)
    timePeriod = N * sampling_interval
    frequencies = values / timePeriod

    # Find indices corresponding to f_bpm-0.1, f_bpm, and f_bpm+0.1,
    # Where f_bpm = the ground truth BPM in Hz.
    f_bpm = BPM_TRUTH / 60
    bpm_index = np.abs(frequencies - f_bpm).argmin()
    upper_index = np.abs(frequencies - f_bpm - 0.1).argmin()
    lower_index = np.abs(frequencies - f_bpm + 0.1).argmin()

    # Find the peaks of the FFTs for both color channels.
    red_peak_index = np.argmax(fft_red)
    red_bpm = int(frequencies[red_peak_index] * 60)

    green_peak_index = np.argmax(fft_green)
    green_bpm = int(frequencies[green_peak_index] * 60)
    '''
    Calculate SNR
    '''
    # Find indices corresponding to the cutoff frequencies of the bandpass filter from earlier.
    lower_cutoff_index = np.abs(frequencies - LOWER_CUTOFF).argmin()
    upper_cutoff_index = np.abs(frequencies - UPPER_CUTOFF).argmin()

    red_signal = 0
    red_noise = 0
    green_signal = 0
    green_noise = 0

    # Iterate through all indices between the lower and upper cutoff frequencies
    for x in range(lower_cutoff_index, upper_cutoff_index + 1):
        # If current index's frequency is close to the ground truth BPM frequency,
        # then add its power (magnitude squared) to the signal variable.
        if (x >= lower_index and x <= upper_index):
            red_signal = red_signal + fft_red[x]**2
            green_signal = green_signal + fft_green[x]**2
        # Else, add its power to the noise variable.
        else:
            red_noise = red_noise + fft_red[x]**2
            green_noise = green_noise + fft_green[x]**2

    red_snr = red_signal / red_noise
    green_snr = green_signal / green_noise

    print('ppg analysis done')

    bpms = {'truth': BPM_TRUTH, 'red': red_bpm, 'green': green_bpm}
    snrs = {'red': red_snr, 'green': green_snr}

    # If desired, graph the FFTs of both color channels,
    # with dots indicating the frequencies of the BPM estimates and ground truth.
    if DISPLAY:
        '''
        plt.title('Red FFT. BPM Estimate = {},Truth = {}'.format(red_bpm, BPM_TRUTH))
        plt.plot(frequencies, fft_red)
        plt.ylabel('Spectral Power')
        plt.xlabel('Frequency (Hz)')
    
        plt.plot(frequencies[red_peak_index], fft_red[red_peak_index], 'ro', label='Estimate')
        plt.plot(frequencies[bpm_index],      fft_red[bpm_index],      'go', label='Reality')
        plt.legend(loc='upper right')
        plt.show()
        '''

        plt.title('Green FFT. BPM Estimate = {},Truth = {}'.format(
            green_bpm, BPM_TRUTH))
        plt.plot(frequencies, fft_green)
        plt.ylabel('Spectral Power')
        plt.xlabel('Frequency (Hz)')

        plt.plot(frequencies[green_peak_index],
                 fft_green[green_peak_index],
                 'ro',
                 label='Estimate')
        plt.plot(frequencies[bpm_index],
                 fft_green[bpm_index],
                 'go',
                 label='Reality')
        plt.legend(loc='upper right')
        plt.show()

    # If desired, graph the results from the heart rate variability algorithm,
    # with the input being the green channel signal,
    # and plot the pulseox hrv for comparison.
    if DISPLAY:

        # PulseOx interpolation and filtering
        f_pox = interp1d(timeData, pulseData, fill_value="extrapolate")
        new_pox = hp.filter_signal(
            f_pox(uniform_time),
            cutoff=[LOWER_CUTOFF / 4, UPPER_CUTOFF],
            filtertype='bandpass',
            sample_rate=new_fs,  #sampling_rate 
            order=4,
            return_top=False)

        # PulseOx FFT and BPM Estimation
        fft_pox = abs(np.fft.fft(new_pox) / N)
        fft_pox = fft_pox[range(N // 2)]
        pox_bpm = int(frequencies[np.argmax(fft_pox)] * 60)

        print('pulse ox bpm: {}'.format(pox_bpm))
        print('ground truth: {}'.format(BPM_TRUTH))
        '''
        plt.plot(uniform_time, f_pox(uniform_time))
        plt.show()
        '''

        performance_tracker = PerformanceTracker()
        # Calculate + plot pulse oximeter hrv
        hrv, thrv, lfcam, hfcam, lf_hfcam, BRcam, sdnncam, sdsdcam, rmssdcam = hrv_function(
            new_pox, fs=int(30 * BPM_TRUTH / pox_bpm), bpm=BPM_TRUTH)
        performance_tracker.track_performance()
        pox_hrv = hrv
        pox_thrv = thrv
        print('Pulse Ox Statistics:')
        print('lfcam: {:.2f}'.format(lfcam))
        print('hfcam: {:.2f}'.format(hfcam))
        print('lf_hfcam: {:.2f}'.format(lf_hfcam))
        print('BRcam: {:.2f}'.format(BRcam))
        print('sdnncam: {:.2f}'.format(sdnncam))
        print('sdsdcam: {:.2f}'.format(sdsdcam))
        print('rmssdcam: {:.2f}'.format(rmssdcam))
        print()
        print()

        performance_tracker.reset()
        # Calculate + plot green channel hrv
        num = int(len(new_green) * pox_bpm / BPM_TRUTH)
        hrv, thrv, lfcam, hfcam, lf_hfcam, BRcam, sdnncam, sdsdcam, rmssdcam = hrv_function(
            new_green[:num], fs=30, bpm=green_bpm)
        performance_tracker.track_performance()
        print('PPG Statistics:')
        print('lfcam: {:.2f}'.format(lfcam))
        print('hfcam: {:.2f}'.format(hfcam))
        print('lf_hfcam: {:.2f}'.format(lf_hfcam))
        print('BRcam: {:.2f}'.format(BRcam))
        print('sdnncam: {:.2f}'.format(sdnncam))
        print('sdsdcam: {:.2f}'.format(sdsdcam))
        print('rmssdcam: {:.2f}'.format(rmssdcam))

        plt.title("BPM as a function of HRV Algorithm")
        plt.plot(thrv / 1000, 60000 / hrv, label="ppg")
        plt.plot(pox_thrv / 1000, 60000 / pox_hrv, label="pulseox")
        plt.xlabel("Time Window 30s")
        plt.ylabel("BPM")
        plt.legend(loc="lower right")
        plt.show()
        '''
Ejemplo n.º 17
0
def main(writer):
    global bpms, snrs
    '''
    Get/Display raw data and sampling rate.
    '''

    # Ignore the first second of data, since it's very different from the other data.
    timeData = writer.get_time_data()[30:]
    camDataRed = writer.get_cam_data_red()[30:]
    camDataGreen = writer.get_cam_data_green()[30:]
    pulseData = writer.get_pulseox_data()[30:]

    sampling_rate = hp.get_samplerate_datetime(timeData, '%S.%f')
    BPM_TRUTH = writer.get_bpm()

    if DISPLAY:
        plt.title("Raw PPG Data")
        plt.plot(timeData, camDataRed, "-r", label="Red")
        plt.plot(timeData, camDataGreen, "-g", label="Green")
        plt.legend(loc="lower right")
        plt.ylabel("Mean Pixel Intensity")
        plt.xlabel("Time (seconds)")
        plt.show()
    '''
    Interpolate PPG signals
    '''
    new_fs = 30
    sampling_interval = 1 / new_fs

    # Quantize time
    initial_time = int(timeData[0] * new_fs) / new_fs
    end_time = int(timeData[-1] * new_fs) / new_fs

    # Figure out number of samples.
    elapsed_time = end_time - initial_time
    num_samples = int(elapsed_time * new_fs) + 1

    # Generate uniform time scale and interpolation function
    uniform_time = np.linspace(initial_time,
                               end_time,
                               num=num_samples,
                               endpoint=True)
    f_red = interp1d(timeData, camDataRed, fill_value="extrapolate")
    f_green = interp1d(timeData, camDataGreen, fill_value="extrapolate")

    # Use interpolation function to generate wave.
    new_red = f_red(uniform_time)
    new_green = f_green(uniform_time)
    N = len(new_red)
    '''
    Filter/Enhance Signals
    '''

    # Display the filtered PPG, print the heartpy bpm estimate
    LOWER_CUTOFF = 0.7
    UPPER_CUTOFF = 4
    #filtered_red_ppg = hp.filter_signal(camDataRed,
    new_red = hp.filter_signal(
        new_red,
        cutoff=[LOWER_CUTOFF, UPPER_CUTOFF],
        filtertype='bandpass',
        sample_rate=new_fs,  #sampling_rate 
        order=4,
        return_top=False)

    #filtered_green_ppg = hp.filter_signal(camDataGreen,
    new_green = hp.filter_signal(
        new_green,
        cutoff=[LOWER_CUTOFF, UPPER_CUTOFF],
        filtertype='bandpass',
        sample_rate=new_fs,  #sampling_rate 
        order=4,
        return_top=False)

    if DISPLAY:
        plt.title("Filtered PPG Data")
        plt.plot(uniform_time, new_red, '-r', label='Red')
        plt.plot(uniform_time, new_green, '-g', label='Green')
        #plt.plot(timeData, filtered_red_ppg, "-r", label="Red")
        #plt.plot(timeData, filtered_green_ppg, "-g", label="Green")
        plt.legend(loc="lower right")
        plt.ylabel("Mean Pixel Intensity")
        plt.xlabel("Time (seconds)")
        plt.show()
    '''
    Take FFT of PPGs
    '''
    # Take FFT of waves. Remove frequencies above the sampling frequency.
    fft_red = np.fft.fft(new_red) / N
    fft_green = np.fft.fft(new_green) / N
    fft_red = fft_red[range(N // 2)]
    fft_green = fft_green[range(N // 2)]
    fft_red = abs(fft_red)
    fft_green = abs(fft_green)

    # Get frequency spectrum of FFTs.
    values = np.arange(N // 2)
    timePeriod = N * sampling_interval
    frequencies = values / timePeriod

    # Find indices of bpm spike.
    f_bpm = BPM_TRUTH / 60
    bpm_index = np.abs(frequencies - f_bpm).argmin()
    upper_index = np.abs(frequencies - f_bpm - 0.1).argmin()
    lower_index = np.abs(frequencies - f_bpm + 0.1).argmin()

    red_peak_index = np.argmax(fft_red)
    red_bpm = int(frequencies[red_peak_index] * 60)

    green_peak_index = np.argmax(fft_green)
    green_bpm = int(frequencies[green_peak_index] * 60)
    '''
    Calculate SNR
    '''
    lower_cutoff_index = np.abs(frequencies - LOWER_CUTOFF).argmin()
    upper_cutoff_index = np.abs(frequencies - UPPER_CUTOFF).argmin()

    red_signal = 0
    red_noise = 0
    green_signal = 0
    green_noise = 0

    for x in range(lower_cutoff_index, upper_cutoff_index + 1):
        if (x >= lower_index and x <= upper_index):
            red_signal = red_signal + fft_red[x]**2
            green_signal = green_signal + fft_green[x]**2
        else:
            red_noise = red_noise + fft_red[x]**2
            green_noise = green_noise + fft_green[x]**2

    red_snr = red_signal / red_noise
    green_snr = green_signal / green_noise

    print('ppg analysis done')

    bpms = {'truth': BPM_TRUTH, 'red': red_bpm, 'green': green_bpm}
    snrs = {'red': red_snr, 'green': green_snr}

    if DISPLAY:
        plt.title('Red FFT. Estimate = {},Truth = {}'.format(
            red_bpm, BPM_TRUTH))
        plt.plot(frequencies, fft_red)
        plt.ylabel('Spectral Power')
        plt.xlabel('Frequency (Hz)')

        plt.plot(frequencies[red_peak_index],
                 fft_red[red_peak_index],
                 'ro',
                 label='Estimate')
        plt.plot(frequencies[bpm_index],
                 fft_red[bpm_index],
                 'go',
                 label='Reality')
        plt.legend(loc='upper right')
        plt.show()

        plt.title('Green FFT. Estimate = {},Truth = {}'.format(
            green_bpm, BPM_TRUTH))
        plt.plot(frequencies, fft_green)
        plt.ylabel('Spectral Power')
        plt.xlabel('Frequency (Hz)')

        plt.plot(frequencies[green_peak_index],
                 fft_green[green_peak_index],
                 'ro',
                 label='Estimate')
        plt.plot(frequencies[bpm_index],
                 fft_green[bpm_index],
                 'go',
                 label='Reality')
        plt.legend(loc='upper right')
        plt.show()
Ejemplo n.º 18
0
_subsetLen = 20  # in seconds
_subsetStart = 300000  # SET

data_loaded_subset = PPG_data_loaded[_subsetStart:_subsetStart +
                                     (_subsetLen * _sampleRate)]

plt.figure(figsize=(22, 6))
plt.plot(data_loaded_subset)
plt.show()

bandpass_low = 1
bandpass_high = 3

filtered_ppg = hp.filter_signal(data_loaded_subset.fillna(0).astype('int32'),
                                cutoff=[bandpass_low, bandpass_high],
                                filtertype='bandpass',
                                sample_rate=_sampleRate,
                                order=3,
                                return_top=False)

plt.figure(figsize=(22, 6))
plt.plot(filtered_ppg)
plt.show()

wd, m = hp.process(filtered_ppg,
                   sample_rate=_sampleRate,
                   high_precision=True,
                   clean_rr=True,
                   clean_rr_method='iqr')

plt.figure(figsize=(22, 6))
hp.plotter(wd, m)