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
def get_peak_error_features(data_sample, sample_rate=100, rpeak_detector=0, low_rri=300, high_rri=2000): rules = ["malik", "karlsson", "kamath", "acar"] try: wd, m = hp.process(data_sample, sample_rate, calc_freq=True) except: try: wd, m = hp.process(data_sample, sample_rate) except: error_dict = {rule + "_error": np.nan for rule in rules} error_dict["outlier_error"] = np.nan return error_dict if rpeak_detector in [1, 2, 3, 4]: detector = PeakDetector(wave_type='ecg') peak_list = detector.ppg_detector(data_sample, rpeak_detector, preprocess=False)[0] wd["peaklist"] = peak_list wd = calc_rr(peak_list, sample_rate, working_data=wd) wd = check_peaks(wd['RR_list'], wd['peaklist'], wd['ybeat'], reject_segmentwise=False, working_data=wd) wd = clean_rr_intervals(working_data=wd) rr_intervals = wd["RR_list"] rr_intervals_cleaned = remove_outliers(rr_intervals, low_rri=low_rri, high_rri=high_rri) number_outliers = len(np.where(np.isnan(rr_intervals_cleaned))[0]) outlier_ratio = number_outliers / (len(rr_intervals_cleaned) - number_outliers) error_sqi = {} error_sqi['outlier_error'] = outlier_ratio interpolated_rr_intervals = interpolate_nan_values(rr_intervals_cleaned) for rule in rules: nn_intervals = remove_ectopic_beats(interpolated_rr_intervals, method=rule) number_ectopics = len(np.where(np.isnan(nn_intervals))[0]) ectopic_ratio = number_ectopics / (len(nn_intervals) - number_ectopics) error_sqi[rule + "_error"] = ectopic_ratio return error_sqi
def analyzeECG(request, version): response_data = {} if version == 'v1': if request.method == "GET": path = getECG(request.GET.get('id'), 0) data = hp.get_data(path) # print(data) working_data, measures = hp.process(data, 100.0) clean_dict = { k: measures[k] for k in measures if not isnan(measures[k]) } # print(measures['bpm']) # print(measures['rmssd']) # print(measures) # hp.plotter(working_data, measures) response_data['status'] = "success" response_data['data'] = clean_dict print(type(clean_dict)) return JsonResponse(response_data) else: response_data['status'] = "error" response_data['message'] = "invalid request" return JsonResponse(response_data) else: response_data['status'] = 'failure' response_data['message'] = 'API version does not exist' return JsonResponse(response_data)
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
def process_ecg(self): """Runs heartpy.process on up-sampled data and creates a timestamp for each detected beat""" print("\n" + "Detecting peaks using the HeartPy algorithm...") # Upsamples data by a factor of 4 to improve peak index resolution self.ecg_resampled = resample( self.ecg_filtered, len(self.ecg_filtered) * self.resample_factor) self.ecg_scaled = heartpy.scale_data( [float(i) for i in self.ecg_resampled]) # Processes data using standard heartpy processing self.wd, self.summary = heartpy.process( hrdata=self.ecg_scaled, sample_rate=self.signal_frequency * self.resample_factor) # Retrieves peaks that got removed in check process for peak in self.wd["peaklist"]: if peak not in self.wd["peaklist_cor"]: self.corrected_peaks.append(peak) # Creates a timestamp for every beat using peak indexes for peak in self.wd["peaklist_cor"]: self.beat_timestamps.append(self.starttime + timedelta( seconds=peak / (self.signal_frequency * self.resample_factor))) print("Peak detection complete.")
def clicked1(): wd, m = hp.process(np.array(d), 150) for measure in m.keys(): #configfile.insert(END, (measure, m[measure])) print('%s: %f' % (measure, m[measure])) configfile.insert(END, m['bpm'])
def EvaluateNEATBiostate(BVP_array, EDA_array, genomeList, currentGenomeID): working_data, hb_measure = hb.process(BVP_array, 64.0, report_time=True) processed_eda = nk.eda_process(EDA_array, freq=1.9, sampling_rate=4) #Do the evaluation stuff return 0
def get_heartrate(ppg_signal, sample_rate): try: _, measures = hp.process(ppg_signal, sample_rate) hr = measures['bpm'] return hr except Exception as exc: return 'HeartPy Exception'
def get_heartbeats(ecg, hz=360, constant=90): import heartpy try: if type(ecg) is list: w, m = heartpy.process(pd.Series(ecg), hz) else: w, m = heartpy.process(ecg, hz) except BadSignalWarning: raise BadFeatureGenerationException() peaklist = w["peaklist_cor"] heartbeats = [] for i in range(len(peaklist) - 1): if i == 0 and peaklist[i] - constant < 0: continue ii = peaklist[i] - constant jj = ii + 300 heartbeats.append(ecg[ii:jj]) return heartbeats, w, m
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
def getPPGfeatures(sampleRate, PPG): wd, m = hp.process(PPG, sample_rate = sampleRate, calc_freq = True) #Without that comment the lib will plot the pieces of PPG and you can see how is doing '''plt.figure(figsize=(12,4)) #call plotter hp.plotter(wd, m)''' #display measures computed #for measure in m.keys(): # print('%s: %f' %(measure, m[measure])) return m
def get_bpm(ecg_signal, sample_rate): """ calculate bpm filtering the signal and upsampling it for better results :param ecg_signal: 1 lead from an ecg :param sample_rate: the sample rate of the ecg :param start_at: this defines the start portion of the ecg that you want to analyse :param finish_at: this defines the end portion of the ecg that you want to analyse :return: the bpm for the given sequence """ upsampled = scipy.signal.resample(ecg_signal, len(ecg_signal) * 4) wd, m = hp.process(hp.scale_data(upsampled), sample_rate * 4) for measure in m.keys(): if measure == 'bpm': return m[measure]
def wave_slicing(sig_data, pre_num, after_num, fs, slices_num): data_length = slices_num *(pre_num + after_num) if sig_data.shape[0] < data_length : print('data is less than ', data_length ) return np.array() sig_data = denoise(sig_data[0:data_length]) #print('sig_data shape',sig_data.shape) #print(sig_data) data_scale = hp.scale_data(sig_data) record_sliced = [] try: # get the location of R wave working_data, measures = hp.process(hrdata= data_scale, sample_rate = fs, bpmmin=5, bpmmax= 300) # get index of R waves peaklists = working_data['peaklist'] # remove the first one and last one peaklists = peaklists[1:-1] print("index of R waves:", peaklists , '\n len(peaklists):', len(peaklists)) # get the wave for i in peaklists[0:slices_num]: #print(i) tem_data = data_scale[i - pre_num: i + after_num] #print('sliced data shape', tem_data.shape) #print('tem_data type:', type(tem_data)) record_sliced.append(tem_data) #print('append tem_data') #plot sample #plt.plot(record_sliced[-1]) #title = str(peaklists[-1]) #plt.title(title) #plt.show() record_sliced = np.array(record_sliced).T print('record_sliced shape:',record_sliced.shape) except Exception as e: print('error:', e) return record_sliced
def resamples(data, filtered, sample_rate): """ функция для нормализации сигнала :param data: исходные данные :param filtered: отфильтрованный сигнал :param sample_rate: шаг :return: wd -содержит пары пиков и множество других характеристик сигнала, m - статистика по сигналу """ resampled_data = resample(data, len(filtered)) #scale_data - функция, которая масштабирует передаваемые данные так, чтобы они указали границы #в любом другом исполнении не работает print(hp.scale_data(resampled_data)) wd, m = hp.process(hp.scale_data(resampled_data), sample_rate * 2) # plt.figure(figsize=(12, 4)) # hp.plotter(wd, m) return wd, m
def get_ppg_info(self, ppg_data, time, id): # 5000*4 = 20 seconds seconds = 5 points = seconds / 0.004 bpm = 0 if len(self.ppg_list) >= points: try: working_data, measures = hp.process(np.array(self.ppg_list), 250.0) bpm = measures['bpm'] except: print('bad signal: check connection') self.ppg_list.clear() ppg = PPG(bpm, time, id) self.insert_heart_info(ppg) print(ppg.bpm) return ppg self.ppg_list.append(float(ppg_data)) return 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
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
def check_signal(data, sample_rate=100.0, bpmmin=30, bpmmax=150, window_size=128, thresh_val=0.8, thresh_pct=0.5): # nan 을 이전 값으로 채움 data = pd.DataFrame(data).fillna(method='ffill', axis=0).fillna(method='bfill', axis=0).values.ravel() is_valid_signal = True # run the analysis try: wd, m = hp.process( data, sample_rate=sample_rate, bpmmin=bpmmin, bpmmax=bpmmax, ) # except hp.exceptions.BadSignalWarning: except: is_valid_signal = False if not is_valid_signal: return False peaks = np.array(wd["peaklist"]) if len(peaks) == 0: return False is_normal = topological_abnorality_check(data, peaks, window_size=window_size, thresh_val=thresh_val, thresh_pct=thresh_pct) return is_valid_signal & is_normal
def replace(data, sampleRate): working_data, measures = hp.process(data, sampleRate, bpmmax=220) peaks = working_data['peaklist'] prev_loc = 0 hr_list = [] ibi_list = [] for loc in peaks: frame = loc - prev_loc hr = 60/(frame/sampleRate) hr_list.extend([hr]*frame) ibi = (frame/sampleRate)*1000 ibi_list.extend([-1.0]*(frame-1)+[ibi]) prev_loc = loc hr_list.extend([hr]*(len(data) - prev_loc)) ibi_list.extend([-1.0]*(len(data) - prev_loc)) return hr_list, ibi_list
def get_ppg_info(self, ppg_data, time, id): # 5000*4 = 20 seconds seconds = 5 points = seconds / 0.004 bpm = 0 measures = {} ppg = {} if len(self.ppg_list) >= points: try: working_data, measures = hp.process(np.array(self.ppg_list), 250.0) bpm = measures['bpm'] except: print('bad signal, continue') self.ppg_list.clear() if bpm > 100 or measures == {}: bpm = 99.99 ppg = PPG(bpm, time, id, measures) self.insert_heart_info(ppg) print(ppg.bpm) return ppg self.ppg_list.append(float(ppg_data)) return 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
def findPeaks(filteredValues, fs): windowData, measure = hp.process(filteredValues, sample_rate=fs, calc_freq=True) peaks = windowData['peaklist'] # remove very close peaks - probably false peak detected peakFindingIteration = 3 # TODO: change values if there are VERY CLOSE fake peaks detected for q in range(peakFindingIteration): peaksToRemove = [] # TODO: change value if threshold too high or too low peakWidthThreshold = np.mean( np.diff(peaks)) * 0.60 # 60% of average peak widths # print(f"peak finding iteration {q}: threshold: {peakWidthThreshold}, aveWidth: {np.mean(np.diff(peaks))}") for i in range(len(peaks) - 1): cur, nxt = peaks[i], peaks[i + 1] if (abs(nxt - cur) < peakWidthThreshold): peaksToRemove.append( cur if filteredValues[cur] < filteredValues[nxt] else nxt) peaks = [x for x in peaks if x not in peaksToRemove] return peaks
def preprocess_data(self): print('DM - preprocess_data') # run analysis self.heartpy_params['wd'], self.heartpy_params['m'] = hp.process( self.raw_data, self.fs) print(self.heartpy_params['wd']['peaklist']) print(self.heartpy_params['wd']['peaklist'][1]) print(type(self.heartpy_params['wd']['peaklist'])) peaklist = self.heartpy_params['wd']['peaklist'] beats = [] for count, value in enumerate(peaklist, start=2): print(value, count) if count < len(peaklist): t1 = peaklist[count - 2] t2 = peaklist[count - 1] beats.append(self.raw_data[t1:t2]) # display computed measures for measure in self.heartpy_params['m'].keys(): print('%s: %f' % (measure, self.heartpy_params['m'][measure])) return beats
import heartpy as hp from scipy.io import wavfile sample_rate, samples = wavfile.read("heartbeat.wav") working_data, measures = hp.process(samples, sample_rate, report_time=True) print(measures['bpm']) #returns BPM value print(measures['rmssd']) # returns RMSSD HRV measure
def PPNet_preprocess_Mat(path): ''' :param path: label file path :return: delta pulse ''' data = loadmat(path)['p'] #size = 125 time = 2 fs = 125 interval = time * fs # 250 down_sample = 4 ppg = [] sbp = [] # Systolic Blood Pressure dbp = [] # Diastolic Blood Pressue hr = [] # Heart Rate for i in range(1000): temp_mat = data[0, i] max_bp = max(temp_mat[1]) min_bp = min(temp_mat[1]) if max_bp > 180 or max_bp < 80: continue if min_bp > 130 or min_bp < 60: continue try: wd, m = hp.process(temp_mat[0], sample_rate=fs, bpmmax=max_bp, bpmmin=min_bp) if m['bpm'] < 40 or m['bpm'] > 220: continue except hp.exceptions.BadSignalWarning: continue temp_mat_ppg = temp_mat[0] temp_mat_ppg -= np.mean(temp_mat_ppg) temp_mat_ppg /= np.std(temp_mat_ppg) temp_length = temp_mat.shape[1] iteration = (int)((temp_length - 1000) / 250 + 1) ppg_tmp = [] sbp_tmp = [] dbp_tmp = [] hr_tmp = [] for j in range(iteration): temp_ppg = temp_mat_ppg[j * interval:j * interval + 1000] temp_bp = temp_mat[1, j * interval:j * interval + 1000] bpmax = max(temp_bp) bpmin = min(temp_bp) try: wd, m = hp.process(temp_ppg, sample_rate=fs, bpmmax=bpmax, bpmmin=bpmin) except hp.exceptions.BadSignalWarning: continue ppg_tmp.append(temp_ppg.reshape(-1, down_sample).mean(axis=1)) sbp_tmp.append(max(temp_bp)) dbp_tmp.append(min(temp_bp)) hr_tmp.append(np.mean(wd['hr'])) sbp_tmp -= np.mean(sbp_tmp) sbp_tmp /= np.std(sbp_tmp) dbp_tmp -= np.mean(dbp_tmp) dbp_tmp /= np.std(dbp_tmp) hr_tmp -= np.mean(hr_tmp) hr_tmp /= np.std(hr_tmp) ppg.extend(ppg_tmp) sbp.extend(sbp_tmp) dbp.extend(dbp_tmp) hr.extend(hr_tmp) return ppg, sbp, dbp, hr
def EvaluateAdaptiveBiostate(BVP_array=None, EDA_array=None): global hb_measures global m_baseHR global m_baseHRV global m_previousHR global m_previousHRV global EDA_measures global m_baseTonic global m_basePhasic global m_previousTonic global m_previousPhasic global m_prevLevel global m_curLevel global m_lastAction global levelStatesList global progressionStateList global m_Iteration #1: higher arousal #0: no notificable change #-1: lower arousal hr_rate = 0 hrv_rate = 0 tonic_rate = 0 phasic_rate = 0 if BVP_array is not None: working_data, hb_measure = hb.process(BVP_array, 64.0, report_time=True) #TODO: Test the difference between resting and playing against the easiest possible character # High heart rate and high HRV = decrease level if EDA_array is not None: current_EDA = nk.eda_process(EDA_array, freq=1.9, sampling_rate=4) current_HR = hb_measure['bpm'] current_HRV = hb_measure['rmssd'] current_Tonic = current_EDA['df']['EDA_Tonic'] current_Phasic = current_EDA['df']['EDA_Phasic'] current_Tonic_mean = np.mean(current_Tonic) current_Phasic_mean = np.mean(current_Phasic) # Firstly, is he excited compared to baseline this is for HR and EDA # Secondly, is he exicted compared to previous # 1:0 : Might need to switch back # 0:1 : switch up # 0:0 : switch up # 1:1 : stay #Do the evaluation stuff #If there is NO difference significantly between HR & EDA and the arousal was higher before, switch back #HR hr_state = m_baseHR * percentage_change < current_HR if m_previousHR == None: hr_rate = 1 if hr_state else 0 elif hr_state == 1: prev_hr_state = m_previousHR * percentage_change if prev_hr_state < current_HR: hr_rate = 1 elif current_HR * percentage_change < m_previousHR: hr_rate = -1 else: hr_rate = 0 else: hr_rate = 0 #HRV, use HRV in the end. hrv_state = m_baseHRV > current_HRV * percentage_change if m_previousHRV == None: hrv_rate = 1 if hrv_state else 0 #Compare with previous set elif hrv_state == 1: prev_hrv_state = m_previousHRV if prev_hrv_state > current_HRV * percentage_change: hrv_rate = 1 elif current_HRV > m_previousHRV * percentage_change: hrv_rate = -1 else: hrv_rate = 0 else: if current_HRV > m_previousHRV * percentage_change: hrv_rate = -1 elif current_HRV * percentage_change < m_previousHRV: hrv_rate = 1 else: hrv_rate = -1 if current_HRV > m_baseHRV * percentage_change else 0 #EDA Tonic tonic_stats = mw(current_Tonic, m_baseTonic, alternative='greater') if m_previousTonic is None: if tonic_stats.pvalue <= p_value: tonic_rate = 1 #Increase or stay else: tonic_rate = 0 #Increase! else: if tonic_stats.pvalue > p_value: tonic_rate = 1 #must upgrade else: tonic_greater_stats = mw(current_Tonic, m_previousTonic, alternative='greater') tonic_less_stats = mw(current_Tonic, m_previousTonic, alternative='less') if tonic_greater_stats.pvalue <= p_value: # This is good. Stay or increase tonic_rate = 1 elif tonic_less_stats.pvalue <= p_value: tonic_rate = -1 #Revert back to the previous! else: tonic_rate = 0 #EDA Phasic phasic_stats = mw(current_Phasic, m_basePhasic, alternative='greater') if m_previousPhasic is None: if phasic_stats.pvalue <= p_value: phasic_rate = 1 else: phasic_rate = 0 else: if phasic_stats.pvalue > p_value: phasic_rate = 1 else: phasic_greater_stats = mw(current_Phasic, m_previousPhasic, alternative='greater') phasic_less_stats = mw(current_Phasic, m_previousPhasic, alternative='less') if phasic_greater_stats.pvalue <= p_value: #stay! Or increae phasic_rate = 1 elif phasic_less_stats.pvalue <= p_value: #Revert back phasic_rate = -1 else: #increase! depending on the previous action phasic_rate = 0 #Phasic component is the main,as result = 0 #Higher arousal if ((phasic_rate + tonic_rate + hr_rate) / 3.0) > 0.5: #Check last action if m_lastAction == m_DECREASE: if m_curLevel == 1: result = 0 m_lastAction = m_STAY elif levelStatesList[m_curLevel - 2]['HR_mean'] is None: result = -1 m_lastAction = m_DECREASE else: lowerAffectiveState = ( (1 if levelStatesList[m_curLevel - 2]['HR_mean'] < current_HR else 0) + (1 if levelStatesList[m_curLevel - 2]['HRV'] > current_HRV else 0) + (1 if levelStatesList[m_curLevel - 2]['Tonic_mean'] < current_Tonic_mean else 0) + (1 if levelStatesList[m_curLevel - 2]['Phasic_mean'] < current_Phasic_mean else 0)) / 4 if levelStatesList[m_curLevel - 2]['HR_mean'] is None: result = -1 m_lastAction = m_DECREASE elif lowerAffectiveState > 0.5: result = -1 m_lastAction = m_DECREASE else: result = 0 m_lastAction = m_STAY elif m_lastAction == m_INCREASE: if m_curLevel == 5: result = 0 m_lastAction = m_STAY elif levelStatesList[m_curLevel]['HR_mean'] is None: result = 1 m_lastAction = m_INCREASE else: upperAffectiveState = ( (1 if levelStatesList[m_curLevel]['HR_mean'] < current_HR else 0) + (1 if levelStatesList[m_curLevel]['HRV'] > current_HRV else 0) + (1 if levelStatesList[m_curLevel]['Tonic_mean'] < current_Tonic_mean else 0) + (1 if levelStatesList[m_curLevel]['Phasic_mean'] < current_Phasic_mean else 0)) / 4 if upperAffectiveState > 0.5: if hrv_rate == -1: result = -1 m_lastAction = m_DECREASE else: result = 1 m_lastAction = m_INCREASE else: result = 0 m_lastAction = m_STAY else: if hrv_rate == -1: result = -1 m_lastAction = m_DECREASE elif hrv_rate == 0: result = 0 m_lastAction = m_STAY else: result = 1 m_lastAction = m_INCREASE # significant lower arousal -- SHOULD NOT STAY elif ((phasic_rate + tonic_rate + hr_rate) / 3.0) < 0.0: #REVERT! if m_curLevel == 1: result = 1 m_lastAction = m_INCREASE elif m_curLevel == 5: result = -1 m_lastAction = m_DECREASE elif m_lastAction == m_DECREASE: result = 1 m_lastAction = m_INCREASE elif m_lastAction == m_INCREASE: result = -1 m_lastAction = m_DECREASE else: upperAffectiveState = ( (1 if levelStatesList[m_curLevel]['HR_mean'] < current_HR else 0) + (1 if levelStatesList[m_curLevel]['HRV'] > current_HRV else 0) + (1 if levelStatesList[m_curLevel]['Tonic_mean'] < current_Tonic_mean else 0) + (1 if levelStatesList[m_curLevel]['Phasic_mean'] < current_Phasic_mean else 0)) / 4 lowerAffectiveState = ( (1 if levelStatesList[m_curLevel - 2]['HR_mean'] < current_HR else 0) + (1 if levelStatesList[m_curLevel - 2]['HRV'] > current_HRV else 0) + (1 if levelStatesList[m_curLevel - 2]['Tonic_mean'] < current_Tonic_mean else 0) + (1 if levelStatesList[m_curLevel - 2]['Phasic_mean'] < current_Phasic_mean else 0)) / 4 if upperAffectiveState > 0.5: m_lastAction = m_DECREASE result = -1 elif lowerAffectiveState > 0.5: m_lastAction = m_INCREASE result = 1 else: m_lastAction = m_DECREASE result = -1 #No real change between this and the previous, do the same action again else: if m_previousPhasic is None: result = 1 m_lastAction = m_INCREASE elif m_curLevel == 1: result = 1 m_lastAction = m_INCREASE elif m_curLevel == 5: result = -1 m_lastAction = m_DECREASE elif m_lastAction == m_DECREASE: result = -1 elif m_lastAction == m_INCREASE: result = 1 else: result = 0 m_lastAction = m_STAY #Finish off m_prevLevel = m_curLevel m_curLevel += result if m_curLevel > 5: m_curLevel = 5 elif m_curLevel < 1: m_curLevel = 1 m_previousHR = current_HR m_previousHRV = current_HRV levelStatesList[m_prevLevel - 1]['HR_mean'] = m_previousHR levelStatesList[m_prevLevel - 1]['HRV'] = m_previousHRV progressionStateList[m_Iteration]['HR_mean'] = m_previousHR progressionStateList[m_Iteration]['HRV'] = m_previousHRV m_previousTonic = current_Tonic m_previousPhasic = current_Phasic levelStatesList[m_prevLevel - 1]['Tonic_mean'] = current_Tonic_mean levelStatesList[m_prevLevel - 1]['Phasic_mean'] = current_Phasic_mean progressionStateList[m_Iteration]['Tonic_mean'] = current_Tonic_mean progressionStateList[m_Iteration]['Phasic_mean'] = current_Phasic_mean progressionStateList[m_Iteration]['Level'] = m_prevLevel m_Iteration += 1 print("Baseline HR: {0} HRV: {1}".format(m_baseHR, m_baseHRV)) print( "Phasic:{0}, tonic: {1}, hr: {2}(BPM){3:.3f}, hrv: {4}(RMSSD){5:.3f}". format(phasic_rate, tonic_rate, hr_rate, current_HR, hrv_rate, current_HRV)) print("Done with result: {0}".format(result)) return result
def ectopic_sqi( data_sample, rule_index=0, sample_rate=100, rpeak_detector=0, wave_type='ppg', low_rri=300, high_rri=2000, ): """ Evaluate the invalid peaks (which exceeds normal range) base on HRV rules: Malik, Karlsson, Kamath, Acar Output the ratio of invalid Parameters ---------- data_sample : rule_index: 0: Default Outlier Peak 1: Malik 2: Karlsson 3: Kamath 4: Acar (Default rule is Malik) sample_rate : (Default value = 100) rpeak_detector : (Default value = 0) To explain other detector options low_rri : (Default value = 300) high_rri : (Default value = 2000) Returns ------- """ rules = ["malik", "karlsson", "kamath", "acar"] try: wd, m = hp.process(data_sample, sample_rate, calc_freq=True) except: try: wd, m = hp.process(data_sample, sample_rate) except: error_dict = {rule + "_error": np.nan for rule in rules} error_dict["outlier_error"] = np.nan return error_dict # if rpeak_detector in [1, 2, 3, 4]: if wave_type == 'ecg': detector = PeakDetector(wave_type='ecg') peak_list = detector.ecg_detector(data_sample, rpeak_detector)[0] else: detector = PeakDetector(wave_type='ppg') peak_list = detector.ppg_detector(data_sample, rpeak_detector, preprocess=False)[0] wd["peaklist"] = peak_list wd = calc_rr(peak_list, sample_rate, working_data=wd) wd = check_peaks(wd['RR_list'], wd['peaklist'], wd['ybeat'], reject_segmentwise=False, working_data=wd) wd = clean_rr_intervals(working_data=wd) rr_intervals = wd["RR_list"] rr_intervals_cleaned = remove_outliers(rr_intervals, low_rri=low_rri, high_rri=high_rri) number_outliers = len(np.where(np.isnan(rr_intervals_cleaned))[0]) outlier_ratio = number_outliers / (len(rr_intervals_cleaned) - number_outliers) if rule_index == 0: return outlier_ratio # error_sqi = {} # error_sqi['outlier_error'] = outlier_ratio interpolated_rr_intervals = interpolate_nan_values(rr_intervals_cleaned) rule = rules[rule_index] nn_intervals = remove_ectopic_beats(interpolated_rr_intervals, method=rule) number_ectopics = len(np.where(np.isnan(nn_intervals))[0]) ectopic_ratio = number_ectopics / (len(nn_intervals) - number_ectopics) return ectopic_ratio
def get_all_features_heartpy(data_sample, sample_rate=100, rpeak_detector=0): """ Parameters ---------- data_sample : Raw signal sample_rate : (Default value = 100) rpeak_detector : (Default value = 0) Returns ------- """ # time domain features td_features = [ "bpm", "ibi", "sdnn", "sdsd", "rmssd", "pnn20", "pnn50", "hr_mad", "sd1", "sd2", "s", "sd1/sd2", "breathingrate" ] # frequency domain features fd_features = ["lf", "hf", "lf/hf"] try: wd, m = hp.process(data_sample, sample_rate, calc_freq=True) except Exception as e: try: wd, m = hp.process(data_sample, sample_rate) except: time_domain_features = {k: np.nan for k in td_features} frequency_domain_features = {k: np.nan for k in fd_features} return time_domain_features, frequency_domain_features if rpeak_detector in [1, 2, 3, 4]: detector = PeakDetector(wave_type='ecg') peak_list = \ detector.ppg_detector(data_sample, rpeak_detector, preprocess=False)[0] wd["peaklist"] = peak_list wd = calc_rr(peak_list, sample_rate, working_data=wd) wd = check_peaks(wd['RR_list'], wd['peaklist'], wd['ybeat'], reject_segmentwise=False, working_data=wd) wd = clean_rr_intervals(working_data=wd) rr_diff = wd['RR_list'] rr_sqdiff = np.power(rr_diff, 2) wd, m = calc_ts_measures(wd['RR_list'], rr_diff, rr_sqdiff, working_data=wd) m = calc_poincare(wd['RR_list'], wd['RR_masklist'], measures=m, working_data=wd) try: measures, working_data = calc_breathing(wd['RR_list_cor'], data_sample, sample_rate, measures=m, working_data=wd) except: measures['breathingrate'] = np.nan wd, m = calc_fd_measures(measures=measures, working_data=working_data) time_domain_features = {k: m[k] for k in td_features} frequency_domain_features = {} for k in fd_features: if k in m.keys(): frequency_domain_features[k] = m[k] else: frequency_domain_features[k] = np.nan # frequency_domain_features = {k:m[k] for k in fd_features if k in m.keys} # frequency_domain_features = {k:np.na for k in fd_features if k not in m.keys} return time_domain_features, frequency_domain_features
label_records[0].p_signal #!pip install heartpy #!pip install heartpy import heartpy as hp import pandas as pd import matplotlib.pyplot as plt data = hp.scale_data(label_records[0].p_signal.T[0]) data0 = label_records[0].p_signal.T[0] data0.shape # get the location of R wave working_data, measures = hp.process(data, 1000.0) hp.plotter(working_data, measures) # get index of R waves peaklists = working_data['peaklist'] # remove the first one and last one peaklists = peaklists[1:-1] print("index of R waves:", peaklists) # get the wave records_sliced = [] for i in peaklists: tem_data = data0[i - 400:i + 600] records_sliced.append(tem_data)
import heartpy as hp import numpy import csv # convert txt file to csv #txt_file_address = 'E:\\Lithic\\data\\heart\\heart-bill.txt' txt_file_address = 'HR_2019-09-22T14-19-17.txt' csv_file_address = txt_file_address.replace('txt','csv') in_txt = csv.reader(open(txt_file_address, "r"), delimiter = ',') out_csv = csv.writer(open(csv_file_address, 'w')) out_csv.writerows(in_txt) print(csv_file_address) hrdata = hp.get_data(csv_file_address, column_name='Analog1_chB') timerdata = hp.get_data(csv_file_address, column_name='Timestamp') working_data, measures = hp.process(hrdata, hp.get_samplerate_mstimer(timerdata)) hp.plotter(working_data, measures, title='good plot')