def test_hrv_time(): ecg_slow = nk.ecg_simulate(duration=60, sampling_rate=1000, heart_rate=70, random_state=42) ecg_fast = nk.ecg_simulate(duration=60, sampling_rate=1000, heart_rate=110, random_state=42) _, peaks_slow = nk.ecg_process(ecg_slow, sampling_rate=1000) _, peaks_fast = nk.ecg_process(ecg_fast, sampling_rate=1000) hrv_slow = nk.hrv_time(peaks_slow, sampling_rate=1000) hrv_fast = nk.hrv_time(peaks_fast, sampling_rate=1000) assert np.all(hrv_fast["HRV_RMSSD"] < hrv_slow["HRV_RMSSD"]) assert np.all(hrv_fast["HRV_MeanNN"] < hrv_slow["HRV_MeanNN"]) assert np.all(hrv_fast["HRV_SDNN"] < hrv_slow["HRV_SDNN"]) assert np.all(hrv_fast["HRV_CVNN"] < hrv_slow["HRV_CVNN"]) assert np.all(hrv_fast["HRV_CVSD"] < hrv_slow["HRV_CVSD"]) assert np.all(hrv_fast["HRV_MedianNN"] < hrv_slow["HRV_MedianNN"]) assert np.all(hrv_fast["HRV_MadNN"] < hrv_slow["HRV_MadNN"]) assert np.all(hrv_fast["HRV_MCVNN"] < hrv_slow["HRV_MCVNN"]) assert np.all(hrv_fast["HRV_pNN50"] == hrv_slow["HRV_pNN50"]) assert np.all(hrv_fast["HRV_pNN20"] < hrv_slow["HRV_pNN20"]) assert np.all(hrv_fast["HRV_TINN"] < hrv_slow["HRV_TINN"]) assert np.all(hrv_fast["HRV_HTI"] > hrv_slow["HRV_HTI"])
def showData(ecg, data, sampling_rate): #Funkcja umożliwiająca wyświetlenie przeanalizowanych danych a.clear() a.plot(ecg[0], ecg[1]) a.plot(data["R_peaks"][0], data["R_peaks"][1], "ro", label = "R peaks") a.plot(data["P_peaks"][0], data["P_peaks"][1], "bv", label = "P peaks") a.plot(data["Q_peaks"][0], data["Q_peaks"][1], "kv", label = "Q peaks") a.plot(data["S_peaks"][0], data["S_peaks"][1], "wv", label = "S peaks") a.plot(data["T_peaks"][0], data["T_peaks"][1], "yv", label = "T peaks") a.plot(data["P_onsets"][0], data["P_onsets"][1], "b^", label = "P onsets") a.plot(data["P_offsets"][0], data["P_offsets"][1], "b^", label = "P offsets") a.plot(data["R_onsets"][0], data["R_onsets"][1], "r^", label = "R onsets") a.plot(data["R_offsets"][0], data["R_offsets"][1], "r^", label = "R offsets") a.plot(data["T_onsets"][0], data["T_onsets"][1], "y^", label = "T onsets") a.plot(data["T_offsets"][0], data["T_offsets"][1], "y^", label = "T offsets") plt.xlabel('time [s]') plt.ylabel('voltage [mV]') plt.legend() canvas.draw() hrv_time = nk.hrv_time(data["R_peaks"][1], sampling_rate=sampling_rate, show=True) hrv_non = nk.hrv_nonlinear(data["R_peaks"][1], sampling_rate=sampling_rate, show=True) plt.figure(2).show() plt.figure(3).show()
def get_HRVs_values(data, header_data): filter_lowcut = 0.001 filter_highcut = 15.0 filter_order = 1 tmp_hea = header_data[0].split(' ') ptID = tmp_hea[0] num_leads = int(tmp_hea[1]) sample_Fs = int(tmp_hea[2]) gain_lead = np.zeros(num_leads) for ii in range(num_leads): tmp_hea = header_data[ii + 1].split(' ') gain_lead[ii] = int(tmp_hea[2].split('/')[0]) # for testing, we included the mean age of 57 if the age is a NaN # This value will change as more data is being released for iline in header_data: if iline.startswith('#Age'): tmp_age = iline.split(': ')[1].strip() age = int(tmp_age if tmp_age != 'NaN' else 57) elif iline.startswith('#Sex'): tmp_sex = iline.split(': ')[1] if tmp_sex.strip() == 'Female': sex = 1 else: sex = 0 elif iline.startswith('#Dx'): label = iline.split(': ')[1].split(',')[0] signal = data[1] gain = gain_lead[1] ecg_signal = nk.ecg_clean(signal * gain, sampling_rate=sample_Fs, method="biosppy") _, rpeaks = nk.ecg_peaks(ecg_signal, sampling_rate=sample_Fs) hrv_time = nk.hrv_time(rpeaks, sampling_rate=sample_Fs) # hrv_non = nk.hrv_nonlinear(rpeaks, sampling_rate=sample_Fs) try: signal_peak, waves_peak = nk.ecg_delineate(ecg_signal, rpeaks, sampling_rate=sample_Fs) p_peaks = waves_peak['ECG_P_Peaks'] except ValueError: print('Exception raised!') pass p_peaks = np.asarray(p_peaks, dtype=float) p_peaks = p_peaks[~np.isnan(p_peaks)] p_peaks = [int(a) for a in p_peaks] mean_P_Peaks = np.mean([signal[w] for w in p_peaks]) hrv_time['mean_P_Peaks'] = mean_P_Peaks hrv_time['age'] = age hrv_time['label'] = label # df = pd.concat([hrv_time, hrv_non], axis=1) return hrv_time
def nothing(): # Quality check algorithms # qcqrs = run_qc(signal=data.filtered, epoch_len=15, fs=fs, algorithm="averageQRS", show_plot=False) # Removing invalid data based on QC thresholdling #t = threshold_averageqrs_data(signal=data.filtered, qc_signal=qc, epoch_len=10, fs=fs, pad_val=0, # thresh=.95, method='exclusive', plot_data=False) p, pc = find_peaks(signal=data.filtered, fs=fs, show_plot=True, peak_method="pantompkins1985", clean_method='neurokit') hrv = nk.hrv_time(peaks=pc, sampling_rate=data.sample_rate, show=False) freq = nk.hrv_frequency(peaks=pc, sampling_rate=data.sample_rate, show=True) # df_events, info = test_ecg_process_func(signal=data.filtered[15000:15000+1250], start=0, n_samples=int(10*125), fs=fs, plot_builtin=True, plot_events=False) # heartbeats = segment_ecg(signal=d, fs=fs) waves, sigs = nk.ecg_delineate(ecg_cleaned=data.filtered, rpeaks=pc, sampling_rate=data.sample_rate, method='dwt', show=False) intervals, ecg_rate, ecg_hrv = nk.ecg_intervalrelated() # TODO # Organizing # Signal quality in organized section --> able to pick which algorithm
def process_bvp(bvp, show_fig=False): """ Compute BVP signal features (more info: https://neurokit2.readthedocs.io/en/latest/functions.html#module-neurokit2.ppg). Compute HRV indices (more info: https://neurokit2.readthedocs.io/en/latest/functions.html#module-neurokit2.hrv) Parameters ---------- bvp : dict [timestamp : value] EDA signal. Returns ------- bvp_signals : DataFrame bvp_info : dict """ bvp_signals, bvp_info = nk.ppg_process(bvp['value'], sampling_rate=64) # First 5 seconds of the signal. # Find peaks peaks = bvp_signals['PPG_Peaks'][:320] # Compute HRV indices time_hrv = nk.hrv_time(peaks, sampling_rate=64, show=show_fig) hrv_base = time_hrv hrv_base['type'] = 'base' # The rest part of the signal. # Find peaks peaks = bvp_signals['PPG_Peaks'][320:] # Compute HRV indices phase_hrv = nk.hrv_frequency(peaks, sampling_rate=64, show=show_fig) time_hrv = nk.hrv_time(peaks, sampling_rate=64, show=show_fig) nonlinear_hrv = nk.hrv_nonlinear(peaks, sampling_rate=64, show=show_fig) hrv_indices = pd.concat([phase_hrv, time_hrv, nonlinear_hrv], axis=1) hrv_indices['type'] = 'stimul' hrv_indices = pd.concat([hrv_indices, hrv_base]) return bvp_signals, bvp_info, hrv_indices
def my_hrv(peaks, sampling_rate): result = [] result.append(nk.hrv_time(peaks, sampling_rate=sampling_rate)) result.append( nk.hrv_frequency(peaks, sampling_rate=sampling_rate, vlf=(0.01, 0.04), lf=(0.04, 0.15), hf=(0.15, 0.4), vhf=(0.4, 1))) return pd.concat(result, axis=1)
import warnings warnings.filterwarnings("ignore") ecg_leads, ecg_labels, fs, ecg_names = load_references( ) # Importiere EKG-Dateien, zugehörige Diagnose, Sampling-Frequenz (Hz) und Name # Sampling-Frequenz 300 Hz features = np.array([]) detectors = Detectors(fs) # Initialisierung des QRS-Detektors labels = np.array([]) for idx, ecg_lead in enumerate(ecg_leads): if (ecg_labels[idx] == "N") or (ecg_labels[idx] == "A"): peaks, info = nk.ecg_peaks(ecg_lead, sampling_rate=fs) peaks = peaks.astype('float64') hrv = nk.hrv_time(peaks, sampling_rate=fs) hrv = hrv.astype('float64') features = np.append(features, [ hrv['HRV_CVNN'], hrv['HRV_CVSD'], hrv['HRV_HTI'], hrv['HRV_IQRNN'], hrv['HRV_MCVNN'], hrv['HRV_MadNN'], hrv['HRV_MeanNN'], hrv['HRV_MedianNN'], hrv['HRV_RMSSD'], hrv['HRV_SDNN'], hrv['HRV_SDSD'], hrv['HRV_TINN'], hrv['HRV_pNN20'], hrv['HRV_pNN50'] ]) features = features.astype('float64') labels = np.append(labels, ecg_labels[idx]) features = features.reshape(int(len(features) / 14), 14) x = np.isnan(features) # replacing NaN values with 0 features[x] = 0
def signals_analysis(signals, is_out=False, is_show=False, out_path="figs"): """ 数据的分析 主要是特征参数的获取 :param signals: 初步处理过的数据 :param is_out: :param is_show: :param out_path: :return: """ sampling_rate = signals["Sampling Rate"] feature_points = signals["Feature Points"] cleaned_pulses = feature_points["Cleaned Pulses"] peaks = feature_points["Peaks"] title = "Time Analysis" hrv_time = nk.hrv_time(peaks, sampling_rate, show=is_show) if is_out: no = datetime.datetime.now().strftime("%Y%m%d%H%M%S") out_name = os.path.join("outputs", str(out_path) + "___" + no + title + ".png") plt.savefig(out_name, dpi=300) if is_show: plt.show() title = "Frequency Analysis" hrv_freq = nk.hrv_frequency(peaks, sampling_rate, show=is_show) if is_out: no = datetime.datetime.now().strftime("%Y%m%d%H%M%S") out_name = os.path.join("outputs", str(out_path) + "___" + no + title + ".png") plt.savefig(out_name, dpi=300) if is_show: plt.show() title = "Nonlinear Analysis" hrv_nonlinear = nk.hrv_nonlinear(peaks, sampling_rate, show=is_show) if is_out: no = datetime.datetime.now().strftime("%Y%m%d%H%M%S") out_name = os.path.join("outputs", str(out_path) + "___" + no + title + ".png") plt.savefig(out_name, dpi=300) if is_show: plt.show() # 傅里叶分析 对应给的文章 xFFT = np.abs(np.fft.rfft(cleaned_pulses) / len(cleaned_pulses)) xFFT = xFFT[:600] xFreqs = np.linspace(0, sampling_rate // 2, len(cleaned_pulses) // 2 + 1) xFreqs = xFreqs[:600] # 滤波处理 平滑去噪 只处理前200个信号即可 # TODO 去噪方法可以调节 cleaned_xFFT = nk.signal_smooth(xFFT, method="loess") # 计算特征值 # F1值 cleaned_FFT = cleaned_xFFT.copy() locmax, props = spsg.find_peaks(cleaned_xFFT) hr_hz_index = np.argmax(cleaned_xFFT) f1 = np.argmax(xFFT) fmax = np.argmax(cleaned_xFFT[locmax]) cleaned_xFFT[locmax[fmax]] = np.min(cleaned_xFFT) f2s = np.argmax(cleaned_xFFT[locmax]) if f2s - fmax != 1: hr_hz_index = locmax[0] + int(np.sqrt(locmax[1] - locmax[0])) # F2值 f2 = locmax[np.argmax(cleaned_xFFT[locmax])] F1 = np.round(xFreqs[f1], 2) F2 = np.round(xFreqs[f2], 2) # 相位差 F2_F1 = F2 - F1 # 心率 HR_FFT = xFreqs[hr_hz_index] * 60 print(HR_FFT) if is_show: plt.plot(xFreqs, cleaned_FFT) plt.scatter(xFreqs[f1], cleaned_FFT[f1], color="red", label="F1 = " + str(F1) + "HZ") plt.scatter(xFreqs[f2], cleaned_FFT[f2], color="orange", label="F2 = " + str(F2) + "HZ") plt.legend(loc="upper right") plt.ylabel("Power") plt.xlabel("Freq(Hz)") title = "FFT analysis" plt.title(title) if is_out: no = datetime.datetime.now().strftime("%Y%m%d%H%M%S") out_name = os.path.join( "outputs", str(out_path) + "___" + no + title + ".png") plt.savefig(out_name, dpi=300) plt.show() hrv_new = { "Power": xFFT, "Freq": cleaned_FFT, "X": xFreqs, "F1": F1, "F2": F2, "F2_F1": F2_F1, "HR_FFT": HR_FFT } return { "HRV New": hrv_new, "HRV Time": hrv_time, "HRV Frequency": hrv_freq, "HRV Nonlinear": hrv_nonlinear }
def compute_features(data, condition, sampling_rate=700, window_size=60, window_shift=0.25): index = 0 init = time.time() # data cleaning ## ECG ecg_cleaned = nk.ecg_clean(data["ECG"][condition].flatten(), sampling_rate=sampling_rate) ## == OLD # ecg_rpeaks, _ = nk.ecg_peaks(ecg_cleaned, sampling_rate=sampling_rate) # ecg_hr = nk.signal_rate(ecg_rpeaks, sampling_rate=sampling_rate) ## == ## EDA ## 5Hz lowpass filter eda_highcut = 5 eda_filtered = nk.signal_filter(data['EDA'][condition].flatten(), sampling_rate=sampling_rate, highcut=eda_highcut) eda_cleaned = nk.standardize(eda_filtered) # TODO: not sure about the approach. cvxeda takes longer periods # phasic_tonic = nk.eda_phasic(cleaned, sampling_rate=700, method='cvxeda') eda_phasic_tonic = nk.eda_phasic(eda_cleaned, sampling_rate=sampling_rate) eda_phasic_tonic['t'] = [(1 / sampling_rate) * i for i in range(eda_phasic_tonic.shape[0])] eda_scr_peaks, scr_info = nk.eda_peaks(eda_phasic_tonic['EDA_Phasic'], sampling_rate=sampling_rate) ## EMG ## For 5 sec window signal ## More on DC Bias https://www.c-motion.com/v3dwiki/index.php/EMG:_Removing_DC_Bias emg_lowcut = 50 emg_filtered_dc = nk.signal_filter(data['EMG'][condition].flatten(), sampling_rate=sampling_rate, lowcut=emg_lowcut) # OR 100 Hz highpass Butterworth filter followed by a constant detrending # filtered_dc = nk.emg_clean(chest_data_dict['EMG'][baseline].flatten(), sampling_rate=700) ## For 60 sec window signal # 50Hz lowpass filter emg_highcut = 50 emg_filtered = nk.signal_filter(data['EMG'][condition].flatten(), sampling_rate=sampling_rate, highcut=emg_highcut) ## Resp ## Method biosppy important to appply bandpass filter 0.1 - 0.35 Hz resp_processed, _ = nk.rsp_process(data['Resp'][condition].flatten(), sampling_rate=sampling_rate, method='biosppy') print('Elapsed Preprocess', str(timedelta(seconds=time.time() - init))) init = time.time() chest_df_5 = pd.DataFrame() # For 5 sec window size chest_df = pd.DataFrame() window = int(sampling_rate * window_size) for i in range(0, data['ACC'][condition].shape[0] - window, int(sampling_rate * window_shift)): # ACC w_acc_data = data['ACC'][condition][i: window + i] acc_x_mean, acc_y_mean, acc_z_mean = np.mean(w_acc_data, axis=0) # Feature acc_x_std, acc_y_std, acc_z_std = np.std(w_acc_data, axis=0) # Feature acc_x_peak, acc_y_peak, acc_z_peak = np.amax(w_acc_data, axis=0) # Feature acc_x_absint, acc_y_absint, acc_z_absint = np.abs(np.trapz(w_acc_data, axis=0)) # Feature xyz = np.sum(w_acc_data, axis=0) xyz_mean = np.mean(xyz) # Feature xyz_std = np.std(xyz) # Feature xyz_absint = np.abs(np.trapz(xyz)) # Feature # == OLD # ## ECG # w_ecg_rpeaks = ecg_rpeaks[i: window + i] # # HR # w_ecg_hr = ecg_hr[i: window + i] # hr_mean = np.mean(w_ecg_hr) # Feature # hr_std = np.std(w_ecg_hr) # Feature # # HRV Time-domain Indices # # HRV_MeanNN # # HRV_SDNN # # HRV_pNN50 # # HRV_RMSSD -> Root mean square of the HRV # # HRV_HTI -> Triangular interpolation index # hrv_time = nk.hrv_time(w_ecg_rpeaks, sampling_rate=sampling_rate, show=False) # hrv_mean = hrv_time.loc[0, 'HRV_MeanNN'] # Feature # hrv_std = hrv_time.loc[0, 'HRV_SDNN'] # Feature # # TODO: NN50 # # hrv_NN50 = # hrv_pNN50 = hrv_time.loc[0, 'HRV_pNN50'] # Feature # hrv_TINN = hrv_time.loc[0, 'HRV_HTI'] # Feature # hrv_rms = hrv_time.loc[0, 'HRV_RMSSD'] # Feature # # HRV Frequency-domain Indices # # TODO: get NaN values within windows (*) # # HRV_ULF * # # HRV_LF * # # HRV_HF # # HRV_VHF # # HRV_LFHF - Ratio LF/HF * # # HRV_LFn * # # HRV_HFn # hrv_freq = nk.hrv_frequency(w_ecg_rpeaks, sampling_rate=sampling_rate, ulf=(0.01, 0.04), lf=(0.04, 0.15), hf=(0.15, 0.4), vhf=(0.4, 1.)) # hrv_ULF = hrv_freq.loc[0, 'HRV_ULF'] # Feature # hrv_LF = hrv_freq.loc[0, 'HRV_LF'] # Feature # hrv_HF = hrv_freq.loc[0, 'HRV_HF'] # Feature # hrv_VHF = hrv_freq.loc[0, 'HRV_VHF'] # Feature # hrv_lf_hf_ratio = hrv_freq.loc[0, 'HRV_LFHF'] # Feature # hrv_f_sum = np.nansum(np.hstack((hrv_ULF, hrv_LF, hrv_HF, hrv_VHF))) # # TODO: rel_f # # hrv_rel_f = # hrv_LFn = hrv_freq.loc[0, 'HRV_LFn'] # Feature # hrv_HFn = hrv_freq.loc[0, 'HRV_HFn'] # Feature # == ## ECG w_ecg_cleaned = ecg_cleaned[i: window + i] _, ecg_info = nk.ecg_peaks(w_ecg_cleaned, sampling_rate=sampling_rate) w_ecg_rpeaks = ecg_info['ECG_R_Peaks'] ecg_nni = pyhrv.tools.nn_intervals(w_ecg_rpeaks) # HR rs_hr = pyhrv.time_domain.hr_parameters(ecg_nni) hr_mean = rs_hr['hr_mean'] # Feature hr_std = rs_hr['hr_std'] # Feature # HRV-time rs_hrv = pyhrv.time_domain.nni_parameters(ecg_nni) hrv_mean = rs_hrv['nni_mean'] # Feature hrv_std = pyhrv.time_domain.sdnn(ecg_nni)['sdnn'] # Feature rs_nn50 = pyhrv.time_domain.nn50(ecg_nni) hrv_NN50 = rs_nn50['nn50'] # Feature hrv_pNN50 = rs_nn50['pnn50'] # Feature hrv_time = nk.hrv_time(w_ecg_rpeaks, sampling_rate=sampling_rate, show=False) hrv_TINN = hrv_time.loc[0, 'HRV_TINN'] # Feature hrv_rms = pyhrv.time_domain.rmssd(ecg_nni)['rmssd'] # Feature # HRV-freq hrv_freq = pyhrv.frequency_domain.welch_psd(ecg_nni, fbands={'ulf': (0.01, 0.04), 'vlf': (0.04, 0.15), 'lf': (0.15, 0.4), 'hf': (0.4, 1)}, mode='dev') # hrv_freq = hrv_freq.as_dict() hrv_freq = hrv_freq[0] hrv_ULF = hrv_freq['fft_abs'][0] # Feature hrv_LF = hrv_freq['fft_abs'][1] # Feature hrv_HF = hrv_freq['fft_abs'][2] # Feature hrv_VHF = hrv_freq['fft_abs'][3] # Feature hrv_lf_hf_ratio = hrv_freq['fft_ratio'] # Feature hrv_f_sum = hrv_freq['fft_total'] # Feature hrv_rel_ULF = hrv_freq['fft_rel'][0] # Feature hrv_rel_LF = hrv_freq['fft_rel'][1] # Feature hrv_rel_HF = hrv_freq['fft_rel'][2] # Feature hrv_rel_VHF = hrv_freq['fft_rel'][3] # Feature hrv_LFn = hrv_freq['fft_norm'][0] # Feature hrv_HFn = hrv_freq['fft_norm'][1] # Feature # EDA w_eda_data = eda_cleaned[i: window + i] w_eda_phasic_tonic = eda_phasic_tonic[i: window + i] eda_mean = np.mean(w_eda_data) # Feature eda_std = np.std(w_eda_data) # Feature eda_min = np.amin(w_eda_data) # Feature eda_max = np.amax(w_eda_data) # Feature # dynamic range: https://en.wikipedia.org/wiki/Dynamic_range eda_slope = get_slope(w_eda_data) # Feature eda_drange = eda_max / eda_min # Feature eda_scl_mean = np.mean(w_eda_phasic_tonic['EDA_Tonic']) # Feature eda_scl_std = np.std(w_eda_phasic_tonic['EDA_Tonic']) # Feature eda_scr_mean = np.mean(w_eda_phasic_tonic['EDA_Phasic']) # Feature eda_scr_std = np.std(w_eda_phasic_tonic['EDA_Phasic']) # Feature eda_corr_scl_t = nk.cor(w_eda_phasic_tonic['EDA_Tonic'], w_eda_phasic_tonic['t'], show=False) # Feature eda_scr_no = eda_scr_peaks['SCR_Peaks'][i: window + i].sum() # Feature # Sum amplitudes in SCR signal ampl = scr_info['SCR_Amplitude'][i: window + i] eda_ampl_sum = np.sum(ampl[~np.isnan(ampl)]) # Feature # TODO: # eda_t_sum = scr_peaks, scr_properties = scisig.find_peaks(w_eda_phasic_tonic['EDA_Phasic'], height=0) width_scr = scisig.peak_widths(w_eda_phasic_tonic['EDA_Phasic'], scr_peaks, rel_height=0) ht_scr = scr_properties['peak_heights'] eda_scr_area = 0.5 * np.matmul(ht_scr, width_scr[1]) # Feature # EMG ## 5sec w_emg_data = emg_filtered_dc[i: window + i] emg_mean = np.mean(w_emg_data) # Feature emg_std = np.std(w_emg_data) # Feature emg_min = np.amin(w_emg_data) emg_max = np.amax(w_emg_data) emg_drange = emg_max / emg_min # Feature emg_absint = np.abs(np.trapz(w_emg_data)) # Feature emg_median = np.median(w_emg_data) # Feature emg_perc_10 = np.percentile(w_emg_data, 10) # Feature emg_perc_90 = np.percentile(w_emg_data, 90) # Feature emg_peak_freq, emg_mean_freq, emg_median_freq = get_freq_features(w_emg_data) # Features # TODO: PSD -> energy in seven bands # emg_psd = ## 60 sec peaks, properties = scisig.find_peaks(emg_filtered[i: window + i], height=0) emg_peak_no = peaks.shape[0] emg_peak_amp_mean = np.mean(properties['peak_heights']) # Feature emg_peak_amp_std = np.std(properties['peak_heights']) # Feature emg_peak_amp_sum = np.sum(properties['peak_heights']) # Feature emg_peak_amp_max = np.abs(np.amax(properties['peak_heights'])) # https://www.researchgate.net/post/How_Period_Normalization_and_Amplitude_normalization_are_performed_in_ECG_Signal emg_peak_amp_norm_sum = np.sum(properties['peak_heights'] / emg_peak_amp_max) # Feature # Resp w_resp_data = resp_processed[i: window + i] ## Inhalation / Exhalation duration analysis idx = np.nan count = 0 duration = dict() first = True for j in w_resp_data[~w_resp_data['RSP_Phase'].isnull()]['RSP_Phase'].to_numpy(): if j != idx: if first: idx = int(j) duration[1] = [] duration [0] = [] first = False continue # print('New value', j, count) duration[idx].append(count) idx = int(j) count = 0 count += 1 resp_inhal_mean = np.mean(duration[1]) # Feature resp_inhal_std = np.std(duration[1]) # Feature resp_exhal_mean = np.mean(duration[0]) # Feature resp_exhal_std = np.std(duration[0]) # Feature resp_inhal_duration = w_resp_data['RSP_Phase'][w_resp_data['RSP_Phase'] == 1].count() resp_exhal_duration = w_resp_data['RSP_Phase'][w_resp_data['RSP_Phase'] == 0].count() resp_ie_ratio = resp_inhal_duration / resp_exhal_duration # Feature resp_duration = resp_inhal_duration + resp_exhal_duration # Feature resp_stretch = w_resp_data['RSP_Amplitude'].max() - w_resp_data['RSP_Amplitude'].min() # Feature resp_breath_rate = len(duration[1]) # Feature ## Volume: area under the curve of the inspiration phase on a respiratory cycle resp_peaks, resp_properties = scisig.find_peaks(w_resp_data['RSP_Clean'], height=0) resp_width = scisig.peak_widths(w_resp_data['RSP_Clean'], resp_peaks, rel_height=0) resp_ht = resp_properties['peak_heights'] resp_volume = 0.5 * np.matmul(resp_ht, resp_width[1]) # Feature # Temp w_temp_data = data['Temp'][condition][i: window + i].flatten() temp_mean = np.mean(w_temp_data) # Feature temp_std = np.std(w_temp_data) # Feature temp_min = np.amin(w_temp_data) # Feature temp_max = np.amax(w_temp_data) # Feature temp_drange = temp_max / temp_min # Feature temp_slope = get_slope(w_temp_data.ravel()) # Feature # chest_df_5 = chest_df_5.append({ # 'ACC_x_mean': acc_x_mean, 'ACC_y_mean': acc_y_mean, 'ACC_z_mean': acc_z_mean, 'ACC_xzy_mean': xyz_mean, # 'ACC_x_std': acc_x_std, 'ACC_y_std': acc_y_std, 'ACC_z_std': acc_z_std, 'ACC_xyz_std': xyz_std, # 'ACC_x_absint': acc_x_absint, 'ACC_y_absint': acc_y_absint, 'ACC_z_absint': acc_z_absint, 'ACC_xyz_absint': xyz_absint, # 'ACC_x_peak': acc_x_peak, 'ACC_y_peak': acc_y_peak, 'ACC_z_peak': acc_z_peak, # 'EMG_mean': emg_mean, 'EMG_std': emg_std, 'EMG_drange': emg_drange, 'EMG_absint': emg_absint, 'EMG_median': emg_median, 'EMG_perc_10': emg_perc_10, # 'EMG_perc_90': emg_perc_90, 'EMG_peak_freq': emg_peak_freq, 'EMG_mean_freq': emg_mean_freq, 'EMG_median_freq': emg_median_freq # }, ignore_index=True) chest_df = chest_df.append({ 'ACC_x_mean': acc_x_mean, 'ACC_y_mean': acc_y_mean, 'ACC_z_mean': acc_z_mean, 'ACC_xzy_mean': xyz_mean, 'ACC_x_std': acc_x_std, 'ACC_y_std': acc_y_std, 'ACC_z_std': acc_z_std, 'ACC_xyz_std': xyz_std, 'ACC_x_absint': acc_x_absint, 'ACC_y_absint': acc_y_absint, 'ACC_z_absint': acc_z_absint, 'ACC_xyz_absint': xyz_absint, 'ACC_x_peak': acc_x_peak, 'ACC_y_peak': acc_y_peak, 'ACC_z_peak': acc_z_peak, 'ECG_hr_mean': hr_mean, 'ECG_hr_std': hr_std, 'ECG_hrv_NN50': hrv_NN50, 'ECG_hrv_pNN50': hrv_pNN50, 'ECG_hrv_TINN': hrv_TINN, 'ECG_hrv_RMS': hrv_rms, 'ECG_hrv_ULF': hrv_ULF, 'ECG_hrv_LF': hrv_LF, 'ECG_hrv_HF': hrv_HF, 'ECG_hrv_VHF': hrv_VHF, 'ECG_hrv_LFHF_ratio': hrv_lf_hf_ratio, 'ECG_hrv_f_sum': hrv_f_sum, 'ECG_hrv_rel_ULF': hrv_rel_ULF, 'ECG_hrv_rel_LF': hrv_rel_LF, 'ECG_hrv_rel_HF': hrv_rel_HF, 'ECG_hrv_rel_VHF': hrv_rel_VHF, 'ECG_hrv_LFn': hrv_LFn, 'ECG_hrv_HFn': hrv_HFn, 'EDA_mean': eda_mean, 'EDA_std': eda_std, 'EDA_mean': eda_mean, 'EDA_min': eda_min, 'EDA_max': eda_max, 'EDA_slope': eda_slope, 'EDA_drange': eda_drange, 'EDA_SCL_mean': eda_scl_mean, 'EDA_SCL_std': eda_scl_mean, 'EDA_SCR_mean': eda_scr_mean, 'EDA_SCR_std': eda_scr_std, 'EDA_corr_SCL_t': eda_corr_scl_t, 'EDA_SCR_no': eda_scr_no, 'EDA_ampl_sum': eda_ampl_sum, 'EDA_scr_area': eda_scr_area, 'EMG_mean': emg_mean, 'EMG_std': emg_std, 'EMG_drange': emg_drange, 'EMG_absint': emg_absint, 'EMG_median': emg_median, 'EMG_perc_10': emg_perc_10, 'EMG_perc_90': emg_perc_90, 'EMG_peak_freq': emg_peak_freq, 'EMG_mean_freq': emg_mean_freq, 'EMG_median_freq': emg_median_freq, 'EMG_peak_no': emg_peak_no, 'EMG_peak_amp_mean': emg_peak_amp_mean, 'EMG_peak_amp_std': emg_peak_amp_std, 'EMG_peak_amp_sum': emg_peak_amp_sum, 'EMG_peak_amp_norm_sum': emg_peak_amp_norm_sum, 'RESP_inhal_mean': resp_inhal_mean, 'RESP_inhal_std': resp_inhal_std, 'RESP_exhal_mean': resp_exhal_mean, 'RESP_exhal_std': resp_exhal_std, 'RESP_ie_ratio': resp_ie_ratio, 'RESP_duration': resp_duration, 'RESP_stretch': resp_stretch, 'RESP_breath_rate': resp_breath_rate, 'RESP_volume': resp_volume, 'TEMP_mean': temp_mean, 'TEMP_std': temp_std, 'TEMP_min': temp_min, 'TEMP_max': temp_max, 'TEMP_drange': temp_drange, 'TEMP_slope': temp_slope }, ignore_index=True) # index += 1 # if index % 10 == 0: # break print('Elapsed Process', condition.shape[0], str(timedelta(seconds=time.time() - init))) return chest_df, chest_df_5
def process_epochs_neurokit(signal, window_len=300, jump_len=300): t = datetime.now() indexes = np.arange(0, len(signal), int(jump_len * data.sample_rate)) print( f"\nRunning NeuroKit analysis in {window_len}-second windows with jump interval of {jump_len} seconds" f"({len(indexes)} iterations)...") # Within-epoch processing using NeuroKit to match Cardioscope output df_nk = pd.DataFrame([[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]).transpose() df_nk.columns = [ "Timestamp", "Index", "Quality", "HR", "meanRR", "sdRR", "meanNN", "SDNN", "pNN20", 'pNN50', "VLF", "LF", "HF", "LF/HF", "LFn", "HFn" ] print("\nProcessing data in epochs with NeuroKit2...") for start in indexes: print(f"{round(100*start/len(signal), 1)}%") try: s, i = nk.ecg_process(signal[start:start + int(data.sample_rate * window_len)], sampling_rate=data.sample_rate) s = s.loc[s["ECG_R_Peaks"] == 1] inds = [i for i in s.index] hrv = nk.hrv_time(peaks=inds, sampling_rate=data.sample_rate, show=False) freq = nk.hrv_frequency(peaks=inds, sampling_rate=data.sample_rate, show=False) rr_ints = [(d2 - d1) / data.sample_rate for d1, d2 in zip(inds[:], inds[1:])] mean_rr = 1000 * np.mean(rr_ints) sd_rr = 1000 * np.std(rr_ints) out = [ data.timestamps[start], start, 100 * s["ECG_Quality"].mean(), s["ECG_Rate"].mean().__round__(3), mean_rr, sd_rr, hrv["HRV_MeanNN"].iloc[0], hrv["HRV_SDNN"].iloc[0], hrv["HRV_pNN20"].iloc[0], hrv["HRV_pNN50"].iloc[0], freq["HRV_VLF"].iloc[0], freq["HRV_LF"].iloc[0], freq["HRV_HF"].iloc[0], freq["HRV_LFHF"].iloc[0], freq["HRV_LFn"].iloc[0], freq["HRV_HFn"].iloc[0] ] df_out = pd.DataFrame(out).transpose() df_out.columns = df_nk.columns df_nk = df_nk.append(df_out, ignore_index=True) except (ValueError, IndexError): out = [ data.timestamps[start], start, None, None, None, None, None, None, None, None, None, None, None, None, None ] df_out = pd.DataFrame(out).transpose() df_out.columns = df_nk.columns df_nk = df_nk.append(df_out, ignore_index=True) t1 = datetime.now() td = (t1 - t).total_seconds() print(f"100% ({round(td, 1)} seconds)") df_nk["Timestamp"] = pd.date_range(start=bf["Timestamp"].iloc[0], freq=f"{jump_len}S", periods=df_nk.shape[0]) return df_nk
def predict_labels(ecg_leads, fs, ecg_names, use_pretrained=False): ''' Parameters ---------- model_name : str Dateiname des Models. In Code-Pfad ecg_leads : list of numpy-Arrays EKG-Signale. fs : float Sampling-Frequenz der Signale. ecg_names : list of str eindeutige Bezeichnung für jedes EKG-Signal. Returns ------- predictions : list of tuples ecg_name und eure Diagnose ''' #------------------------------------------------------------------------------ # Euer Code ab hier # model_name = "model.npy" # if use_pretrained: # model_name = "model_pretrained.npy" # with open(model_name, 'rb') as f: # th_opt = np.load(f) # Lade simples Model (1 Parameter) # # detectors = Detectors(fs) # Initialisierung des QRS-Detektors # # predictions = list() # # for idx,ecg_lead in enumerate(ecg_leads): # r_peaks = detectors.hamilton_detector(ecg_lead) # Detektion der QRS-Komplexe # sdnn = np.std(np.diff(r_peaks)/fs*1000) # if sdnn < th_opt: # predictions.append((ecg_names[idx], 'N')) # else: # predictions.append((ecg_names[idx], 'A')) # if ((idx+1) % 100)==0: # print(str(idx+1) + "\t Dateien wurden verarbeitet.") # # # #------------------------------------------------------------------------------ # return predictions # Liste von Tupels im Format (ecg_name,label) - Muss unverändert bleiben! # Load test-dataset # from tqdm import tqdm # import os # from os import listdir # from os.path import isfile, join # import cv2 ##### # THRESHOLD = 0.5 # def precision(y_true, y_pred, threshold_shift=0.5 - THRESHOLD): # # just in case # y_pred = K.clip(y_pred, 0, 1) # # shifting the prediction threshold from .5 if needed # y_pred_bin = K.round(y_pred + threshold_shift) # tp = K.sum(K.round(y_true * y_pred_bin)) + K.epsilon() # fp = K.sum(K.round(K.clip(y_pred_bin - y_true, 0, 1))) # precision = tp / (tp + fp) # return precision # def recall(y_true, y_pred, threshold_shift=0.5 - THRESHOLD): # # just in case # y_pred = K.clip(y_pred, 0, 1) # # shifting the prediction threshold from .5 if needed # y_pred_bin = K.round(y_pred + threshold_shift) # tp = K.sum(K.round(y_true * y_pred_bin)) + K.epsilon() # fn = K.sum(K.round(K.clip(y_true - y_pred_bin, 0, 1))) # recall = tp / (tp + fn) # return recall # def fbeta(y_true, y_pred, threshold_shift=0.5 - THRESHOLD): # beta = 1 # # just in case # y_pred = K.clip(y_pred, 0, 1) # # shifting the prediction threshold from .5 if needed # y_pred_bin = K.round(y_pred + threshold_shift) # tp = K.sum(K.round(y_true * y_pred_bin)) + K.epsilon() # fp = K.sum(K.round(K.clip(y_pred_bin - y_true, 0, 1))) # fn = K.sum(K.round(K.clip(y_true - y_pred, 0, 1))) # precision = tp / (tp + fp) # recall = tp / (tp + fn) # beta_squared = beta ** 2 # return (beta_squared + 1) * (precision * recall) / (beta_squared * precision + recall) ##### # ecg_leads,ecg_labels,fs,ecg_names = load_references('../test/') # Importiere EKG-Dateien, zugehörige Diagnose, Sampling-Frequenz (Hz) und Name # Sampling-Frequenz 300 Hz # test_set = ecg_leads # if os.path.exists("../test/ecg_images"): # print("File exists.") # else: # os.mkdir("../test/ecg_images") # for i in tqdm(range(len(test_set))): # data = ecg_leads[i].reshape(len(ecg_leads[i]), 1) # plt.figure(figsize=(60, 5)) # plt.xlim(0, len(ecg_leads[i])) # # plt.plot(data, color='black', linewidth=0.1) # plt.savefig('../test/ecg_images/{}.png'.format(ecg_names[i])) # onlyfiles = [f for f in listdir("../test/ecg_images") if isfile(join("../test/ecg_images", f))] # df = pd.read_csv("../test/REFERENCE.csv", header=None) # x = [] # y = [] # name_test =[] # for i in range(len(onlyfiles)): # if (df.iloc[i][1] == "N") or (df.iloc[i][1] == "A"): # image = cv2.imread("../test/ecg_images/{}".format(onlyfiles[i])) # gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # resize_x = cv2.resize(gray, (128, 1024)) # reshape_x = np.asarray(resize_x).reshape(resize_x.shape[0], resize_x.shape[1], 1) # x.append(reshape_x) # y.append(df.iloc[i][1]) # name_test.append(df.iloc[i]) # for n, i in enumerate(y): # if i == "N": # y[n] = 0 # elif i == "A": # y[n] = 1 # x = np.asarray(x).astype(int) # y = np.asarray(y).astype(int) # test_images, test_labels = x, y # # Normalize pixel values to be between 0 and 1 # test_images = test_images / 255.0 # import keras # import tensorflow as tf # from keras.models import load_model # model = load_model('./pred_model.h5', custom_objects={'fbeta': fbeta}) # model = tf.keras.models.load_model('./pred_model.h5', custom_objects={'fbeta': fbeta}) # model = tf.keras.models.load_model('./pred_model.h5', custom_objects={'fbeta': fbeta}) # converter = tf.lite.TFLiteConverter.from_keras_model(model) # .from_saved_model(saved_model_dir) # tflite_model = converter.convert() # open("model.tflite", "wb").write(tflite_model) # pred_labels = model.predict_classes(test_images) # pred_labels = np.asarray(pred_labels).astype('str') # for n, i in enumerate(pred_labels): # if i == '0': # pred_labels[n] = "N" # elif i == '1': # pred_labels[n] = "A" #------------------------------------------------------------------------------- ''' Gradient Boosting Classfier ''' # import warnings # warnings.filterwarnings("ignore") # # test_features = np.array([]) # # for idx, ecg_lead in enumerate(ecg_leads): # peaks, info = nk.ecg_peaks(ecg_lead, sampling_rate= 200) # peaks = peaks.astype('float64') # hrv = nk.hrv_time(peaks, sampling_rate= fs) # hrv = hrv.astype('float64') # test_features = np.append(test_features, [hrv['HRV_CVNN'], hrv['HRV_CVSD'], hrv['HRV_HTI'], hrv['HRV_IQRNN'], hrv['HRV_MCVNN'], hrv['HRV_MadNN'], hrv['HRV_MeanNN'], hrv['HRV_MedianNN'], hrv['HRV_RMSSD'], hrv['HRV_SDNN'], hrv['HRV_SDSD'], hrv['HRV_TINN'], hrv['HRV_pNN20'],hrv['HRV_pNN50'] ]) # test_features = test_features.astype('float64') # # test_features= test_features.reshape(int(len(test_features)/14), 14) # x = np.isnan(test_features) # # replacing NaN values with 0 # test_features[x] = 0 # # X_test = test_features # # # with trained model to predict # loaded_model = joblib.load('GradientBoostingClassifier') # pred_labels = loaded_model.predict(X_test) # # a list of tuple # predictions = list() # # for idx in range(len(X_test)): # predictions.append((ecg_names[idx], pred_labels[idx])) #------------------------------------------------------------------ ''' Convolutional Neural Network ''' # import warnings # warnings.filterwarnings("ignore") # from tensorflow.keras.models import load_model # from tensorflow.keras.optimizers import SGD # import numpy as np # # ### # def f1(y_true, y_pred): # def recall(y_true, y_pred): # """Recall metric. # # Only computes a batch-wise average of recall. # # Computes the recall, a metric for multi-label classification of # how many relevant items are selected. # """ # true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1))) # possible_positives = K.sum(K.round(K.clip(y_true, 0, 1))) # recall = true_positives / (possible_positives + K.epsilon()) # return recall # # def precision(y_true, y_pred): # """Precision metric. # # Only computes a batch-wise average of precision. # # Computes the precision, a metric for multi-label classification of # how many selected items are relevant. # """ # true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1))) # predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1))) # precision = true_positives / (predicted_positives + K.epsilon()) # return precision # # precision = precision(y_true, y_pred) # recall = recall(y_true, y_pred) # return 2 * ((precision * recall) / (precision + recall + K.epsilon())) # # def f1_weighted(true, pred): # shapes (batch, 4) # # # for metrics include these two lines, for loss, don't include them # # these are meant to round 'pred' to exactly zeros and ones # # predLabels = K.argmax(pred, axis=-1) # # pred = K.one_hot(predLabels, 4) # # ground_positives = K.sum(true, axis=0) + K.epsilon() # = TP + FN # pred_positives = K.sum(pred, axis=0) + K.epsilon() # = TP + FP # true_positives = K.sum(true * pred, axis=0) + K.epsilon() # = TP # # all with shape (4,) # # precision = true_positives / pred_positives # recall = true_positives / ground_positives # # both = 1 if ground_positives == 0 or pred_positives == 0 # # shape (4,) # # f1 = 2 * (precision * recall) / (precision + recall + K.epsilon()) # # still with shape (4,) # # weighted_f1 = f1 * ground_positives / K.sum(ground_positives) # weighted_f1 = K.sum(weighted_f1) # # return 1 - weighted_f1 # for metrics, return only 'weighted_f1' # ### # # cnn_best_model = load_model('cnn_best_model.h5', custom_objects={'f1_weighted': f1_weighted, 'f1': f1}) # # sgd = SGD(lr=0.00005, decay=1e-6, momentum=0.9, nesterov=True) # cnn_best_model.compile(optimizer=sgd, # change: use SGD # loss=f1_weighted, # 'binary_crossentropy' #'mean_squared_error' #categorical_crossentropy # metrics=[f1, "binary_accuracy"]) # # test_features = np.array([]) # # for idx, ecg_lead in enumerate(ecg_leads): # peaks, info = nk.ecg_peaks(ecg_lead, sampling_rate= 200) # peaks = peaks.astype('float64') # hrv = nk.hrv_time(peaks, sampling_rate= fs) # hrv = hrv.astype('float64') # test_features = np.append(test_features, [hrv['HRV_CVNN'], hrv['HRV_CVSD'], hrv['HRV_HTI'], hrv['HRV_IQRNN'], hrv['HRV_MCVNN'], hrv['HRV_MadNN'], hrv['HRV_MeanNN'], hrv['HRV_MedianNN'], hrv['HRV_RMSSD'], hrv['HRV_SDNN'], hrv['HRV_SDSD'], hrv['HRV_TINN'], hrv['HRV_pNN20'],hrv['HRV_pNN50'] ]) # test_features = test_features.astype('float64') # # test_features= test_features.reshape(int(len(test_features)/14), 14) # x = np.isnan(test_features) # # replacing NaN values with 0 # test_features[x] = 0 # # X_test = test_features # X_test_arr = np.array(X_test).reshape(np.array(X_test).shape[0], np.array(X_test).shape[1], 1) # # with trained model to predict # y_pred = cnn_best_model.predict(X_test_arr) # pred_labels = [np.argmax(y, axis=None, out=None) for y in y_pred] # # for n, i in enumerate(pred_labels): # if i == 0: # pred_labels[n] = 'N' # if i == 1: # pred_labels[n] = 'A' # # predictions = list() # # for idx in range(len(X_test)): # predictions.append((ecg_names[idx], pred_labels[idx])) # ------------------------------------------------------------------------------ # ------------------------------------------------------------------ ''' AdaBoost Classifier ''' # import warnings # warnings.filterwarnings("ignore") # # test_features = np.array([]) # # for idx, ecg_lead in enumerate(ecg_leads): # peaks, info = nk.ecg_peaks(ecg_lead, sampling_rate= 200) # peaks = peaks.astype('float64') # hrv = nk.hrv_time(peaks, sampling_rate= fs) # hrv = hrv.astype('float64') # test_features = np.append(test_features, [hrv['HRV_CVNN'], hrv['HRV_CVSD'], hrv['HRV_HTI'], hrv['HRV_IQRNN'], hrv['HRV_MCVNN'], hrv['HRV_MadNN'], hrv['HRV_MeanNN'], hrv['HRV_MedianNN'], hrv['HRV_RMSSD'], hrv['HRV_SDNN'], hrv['HRV_SDSD'], hrv['HRV_TINN'], hrv['HRV_pNN20'],hrv['HRV_pNN50'] ]) # test_features = test_features.astype('float64') # # test_features= test_features.reshape(int(len(test_features)/14), 14) # x = np.isnan(test_features) # # replacing NaN values with 0 # test_features[x] = 0 # # X_test = test_features # # # with trained model to predict # loaded_model = joblib.load('AdaBoostClassifier') # pred_labels = loaded_model.predict(X_test) #----------------------------------------------------------------------------------------- ''' XGBoost Classifier ''' import warnings warnings.filterwarnings("ignore") test_features = np.array([]) for idx, ecg_lead in enumerate(ecg_leads): peaks, info = nk.ecg_peaks(ecg_lead, sampling_rate=fs) peaks = peaks.astype('float64') hrv = nk.hrv_time(peaks, sampling_rate=fs) hrv = hrv.astype('float64') test_features = np.append(test_features, [ hrv['HRV_CVNN'], hrv['HRV_CVSD'], hrv['HRV_HTI'], hrv['HRV_IQRNN'], hrv['HRV_MCVNN'], hrv['HRV_MadNN'], hrv['HRV_MeanNN'], hrv['HRV_MedianNN'], hrv['HRV_RMSSD'], hrv['HRV_SDNN'], hrv['HRV_SDSD'], hrv['HRV_TINN'], hrv['HRV_pNN20'], hrv['HRV_pNN50'] ]) test_features = test_features.astype('float64') test_features = test_features.reshape(int(len(test_features) / 14), 14) x = np.isnan(test_features) # replacing NaN values with 0 test_features[x] = 0 X_test = test_features # with trained model to predict loaded_model = joblib.load('XGBoostClassifier') pred_labels = loaded_model.predict(X_test) # a list of tuple predictions = list() for idx in range(len(X_test)): predictions.append((ecg_names[idx], pred_labels[idx])) return predictions # Liste von Tupels im Format (ecg_name,label) - Muss unverändert bleiben!
ecg_array[unique_id]['P_width_mean'] = np.nanmean(waves_cwt['ECG_P_width']) ecg_array[unique_id]['P_width_median'] = np.nanmedian( waves_cwt['ECG_P_width']) ecg_array[unique_id]['P_width_std'] = np.nanstd(waves_cwt['ECG_P_width']) ecg_array[unique_id]['P_width_min'] = np.nanmin(waves_cwt['ECG_P_width']) ecg_array[unique_id]['P_width_max'] = np.nanmax(waves_cwt['ECG_P_width']) ecg_array[unique_id]['QRS_width_mean'] = np.nanmean( waves_cwt['ECG_QRS_width']) ecg_array[unique_id]['QRS_width_median'] = np.nanmedian( waves_cwt['ECG_QRS_width']) ecg_array[unique_id]['QRS_width_std'] = np.nanstd( waves_cwt['ECG_QRS_width']) ecg_array[unique_id]['QRS_width_min'] = np.nanmin( waves_cwt['ECG_QRS_width']) ecg_array[unique_id]['QRS_width_max'] = np.nanmax( waves_cwt['ECG_QRS_width']) hrv = nk.hrv_time(rpeaks, sampling_rate=500, show=True) ecg_array[unique_id]['HRV_MeanNN'] = hrv['HRV_MeanNN'][0] ecg_array[unique_id]['HRV_SDNN'] = hrv['HRV_SDNN'][0] ecg_array[unique_id]['HRV_MedianNN'] = hrv['HRV_MedianNN'][0] ecg_array[unique_id]['label'] = df_train[df_train['unique_id'] == unique_id]['label'][i] if (i % 100 == 0): plt.cla() # Clear the current axes plt.clf() # Clear the current figure plt.close() i += 1
def get_HRVs_values(data, header_data): filter_lowcut = 0.001 filter_highcut = 15.0 filter_order = 1 tmp_hea = header_data[0].split(' ') ptID = tmp_hea[0] num_leads = int(tmp_hea[1]) sample_Fs= int(tmp_hea[2]) gain_lead = np.zeros(num_leads) for ii in range(num_leads): tmp_hea = header_data[ii+1].split(' ') gain_lead[ii] = int(tmp_hea[2].split('/')[0]) # for testing, we included the mean age of 57 if the age is a NaN # This value will change as more data is being released for iline in header_data: if iline.startswith('#Age'): tmp_age = iline.split(': ')[1].strip() age = int(tmp_age if tmp_age != 'NaN' else 57) # age = int(tmp_age) elif iline.startswith('#Sex'): tmp_sex = iline.split(': ')[1] if tmp_sex.strip()=='Female': sex =1 else: sex=0 elif iline.startswith('#Dx'): label = iline.split(': ')[1].split(',')[0] signal = data[1] gain = gain_lead[1] ecg_signal = nk.ecg_clean(signal*gain, sampling_rate=sample_Fs, method="biosppy") _ , rpeaks = nk.ecg_peaks(ecg_signal, sampling_rate=sample_Fs) hrv_time = nk.hrv_time(rpeaks, sampling_rate=sample_Fs) peaks, idx = detect_peaks(signal, sample_Fs, gain) # print(len(signal), len(idx)) rr_intervals = idx / (sample_Fs * 1000) rr_intervals = pd.Series(rr_intervals) rr_ma = rr_intervals.rolling(3) try: signal_peak, waves_peak = nk.ecg_delineate(ecg_signal, rpeaks, sampling_rate=sample_Fs) p_peaks = waves_peak['ECG_P_Peaks'] except ValueError: print('Exception raised!') pass p_peaks = np.asarray(p_peaks, dtype=float) p_peaks = p_peaks[~np.isnan(p_peaks)] p_peaks = [int(a) for a in p_peaks] p_time = [x/sample_Fs for x in p_peaks] p_diff = np.diff(p_time) # mean_P_Peaks = np.mean([signal[w] for w in p_peaks]) hrv_time['var_P_time'] = stats.tvar(p_diff) hrv_time['var_P_peaks'] = stats.tvar(signal[np.array(p_peaks)]) hrv_time['age'] = age hrv_time['label'] = label return hrv_time