def get_indices_of_R_peaks(ecg_signal): rp_ind = ecg.engzee_segmenter(signal=ecg_signal, sampling_rate=300.0, threshold=0.48) rp_peaks = [] for i in list(rp_ind[0]): rp_peaks.append(ecg_signal[i]) return list(rp_ind[0]), rp_peaks
def engzee_detect(sig:np.ndarray, fs:Real, **kwargs) -> np.ndarray: """ References: ----------- [1] W. Engelse and C. Zeelenberg, "A single scan algorithm for QRS detection and feature extraction", IEEE Comp. in Cardiology, vol. 6, pp. 37-42, 1979 [2] A. Lourenco, H. Silva, P. Leite, R. Lourenco and A. Fred, "Real Time Electrocardiogram Segmentation for Finger Based ECG Biometrics", BIOSIGNALS 2012, pp. 49-54, 2012 """ rpeaks, = BSE.engzee_segmenter( signal=sig, sampling_rate=fs, threshold=kwargs.get("threshold", 0.48), ) # correct R-peak locations rpeaks, = BSE.correct_rpeaks( signal=sig, rpeaks=rpeaks, sampling_rate=fs, tol=kwargs.get("correct_tol", 0.05), ) return rpeaks
def seek(self): """Locate R peaks and segment ECG cycles.""" self.r_coords = bioecg.engzee_segmenter( np.ravel(self.record), sampling_rate=self.fs)['rpeaks'] cycles, rpeaks_relative, median_rr = self.segment_cycles(self.r_coords) return self.r_coords.copy(), median_rr, cycles, rpeaks_relative
target = feautres_right else: target = feautres_left # low pass filter filtered = butter_lowpass_filter(signal, cutoff, sampling_rate, order) # detrend with a low-pass order = 20 filtered -= filtfilt( [1] * order, [order], filtered) # this is a very simple moving average filter # Rpeaks Rpeaks = engzee_segmenter(signal=filtered, sampling_rate=sampling_rate, threshold=0)['rpeaks'] Rpeaks = correct_rpeaks(signal=filtered, rpeaks=Rpeaks, sampling_rate=sampling_rate, tol=rpeak_tol)['rpeaks'] # peak to peak intervals IBI = [] for i in range(1, len(Rpeaks)): IBI.append(Rpeaks[i] - Rpeaks[i - 1]) IBI = np.array(IBI) / sampling_rate IBI = correct(IBI, 3) # feautres for IBI target.append(RMS(IBI))
def transform(self, X, y=None): X = check_array(X) T = 1.0 / self.sample_rate bio_feature = np.empty(1) for i in range(X.shape[0]): Xi = X[i, :] rpeaks = ecg.engzee_segmenter(Xi, sampling_rate=300, threshold=self.threshold) rpeaks = rpeaks[0] # 1. compute the mean of DFT for one QRS wave QR_int = self.segstart # Q-R interval RS_int = self.segend # R-S interval m_idx = X.shape[1] - RS_int idx = np.where((rpeaks > QR_int) & (rpeaks < m_idx)) idx = idx[0] new_rpeaks = rpeaks[idx] _fft = np.zeros(QR_int + RS_int) for j in range(len(new_rpeaks)): # extract segment around rpeaks QRS = Xi[new_rpeaks[j] - QR_int:new_rpeaks[j] + RS_int] # compute the mean of DFT fft = np.fft.fft(QRS) fft_amp = np.absolute(fft) if j == 0: _fft = fft_amp else: _fft = np.vstack((_fft, fft_amp)) fft_mean = np.mean(_fft, axis=0) if len(new_rpeaks) == 0 or len(new_rpeaks) == 1: fft_mean = _fft # 2. compute the statistics of heart beat out = ecg.ecg(signal=Xi, sampling_rate=300, show=False) [ts, sig, rpeaks, temp_ts, temp, hr_ts, heart_rate] = out heart_stats = [0, 0, 0, 0] if len(heart_rate) != 0: heart_stats[0] = np.mean(heart_rate) heart_stats[1] = np.var(heart_rate) heart_stats[2] = np.amin(heart_rate) heart_stats[3] = np.amax(heart_rate) heart_stats = np.asarray(heart_stats) # 3. compute the statistics of R-R interval RR_int = [] for k in range(1, len(rpeaks)): RR_int.append(T * (rpeaks[k] - rpeaks[k - 1])) RR_int = np.asarray(RR_int) RR_stats = [0, 0, 0, 0] if len(RR_int) != 0: RR_stats[0] = np.mean(RR_int) RR_stats[1] = np.var(RR_int) RR_stats[2] = np.amin(RR_int) RR_stats[3] = np.amax(RR_int) RR_stats = np.asarray(RR_stats) feature = np.hstack((fft_mean, heart_stats)) feature = np.hstack((feature, RR_stats)) if i == 0: bio_feature = feature else: bio_feature = np.vstack((bio_feature, feature)) return bio_feature
import numpy as np import matplotlib as plt import biosppy.signals.ecg as bio samplrate = 3428 / 10 data = np.loadtxt('FilteredData/filtereddata3.txt') rpeaks1 = bio.christov_segmenter(data, 342) bio.ecg(data, 342, True) rpeaks2 = bio.engzee_segmenter(data, 342) rpeaks3 = bio.gamboa_segmenter(data, 342) rpeaks4 = bio.hamilton_segmenter(data, 342) rpeaks5 = bio.ssf_segmenter(data, 342) np.savetxt('FilteredData/peaksdata13.txt', rpeaks1, header=str(len(rpeaks1))) np.savetxt('FilteredData/peaksdata23.txt', rpeaks2, header=str(len(rpeaks2))) np.savetxt('FilteredData/peaksdata33.txt', rpeaks3, header=str(len(rpeaks3))) np.savetxt('FilteredData/peaksdata43.txt', rpeaks4, header=str(len(rpeaks4))) np.savetxt('FilteredData/peaksdata53.txt', rpeaks5, header=str(len(rpeaks5))) #np.savetxt('FilteredData/roundeddata3.txt', introunddata)
@author: Milan """ import pandas as pd import biosppy.signals.ecg as bse import numpy as np #%% Train data_train = pd.read_csv('Dropbox/MK/ETH MSc Statistics/Machine Learning/Advanced Machine Learning/exercises/project/task3/X_train.csv') del data_train['id'] rpeaks_init = [] for i in range(0,data_train.shape[0]): rpeaks_init.append(bse.engzee_segmenter(signal=data_train.iloc[i,:].values, sampling_rate=300)) rpeaks_corrected = [] for i in range(0,data_train.shape[0]): rpeaks_corrected.append(bse.correct_rpeaks(signal=data_train.iloc[i,:].values, rpeaks=rpeaks_init[i][0], sampling_rate=300, tol=0.05)) heartbeats = [] for i in range(0,data_train.shape[0]): heartbeats.append(bse.extract_heartbeats(signal=data_train.iloc[i,:].values, rpeaks=rpeaks_corrected[i][0], sampling_rate=300, before=0.2, after=0.4) ) R_peaks = [] for i in range(0,data_train.shape[0]): R = [] for j in range(0,len(heartbeats[i][1])): R.append(heartbeats[i][1][j])
def run_algo(algorithm: str, sig: numpy.ndarray, freq_sampling: int) -> List[int]: """ run a qrs detector on a signal :param algorithm: name of the qrs detector to use :type algorithm: str :param sig: values of the sampled signal to study :type sig: ndarray :param freq_sampling: value of sampling frequency of the signal :type freq_sampling: int :return: localisations of qrs detections :rtype: list(int) """ detectors = Detectors(freq_sampling) if algorithm == 'Pan-Tompkins-ecg-detector': qrs_detections = detectors.pan_tompkins_detector(sig) elif algorithm == 'Hamilton-ecg-detector': qrs_detections = detectors.hamilton_detector(sig) elif algorithm == 'Christov-ecg-detector': qrs_detections = detectors.christov_detector(sig) elif algorithm == 'Engelse-Zeelenberg-ecg-detector': qrs_detections = detectors.engzee_detector(sig) elif algorithm == 'SWT-ecg-detector': qrs_detections = detectors.swt_detector(sig) elif algorithm == 'Matched-filter-ecg-detector' and freq_sampling == 360: qrs_detections = detectors.matched_filter_detector( sig, 'templates/template_360hz.csv') elif algorithm == 'Matched-filter-ecg-detector' and freq_sampling == 250: qrs_detections = detectors.matched_filter_detector( sig, 'templates/template_250hz.csv') elif algorithm == 'Two-average-ecg-detector': qrs_detections = detectors.two_average_detector(sig) elif algorithm == 'Hamilton-biosppy': qrs_detections = bsp_ecg.ecg(signal=sig, sampling_rate=freq_sampling, show=False)[2] elif algorithm == 'Christov-biosppy': order = int(0.3 * freq_sampling) filtered, _, _ = bsp_tools.filter_signal(signal=sig, ftype='FIR', band='bandpass', order=order, frequency=[3, 45], sampling_rate=freq_sampling) rpeaks, = bsp_ecg.christov_segmenter(signal=filtered, sampling_rate=freq_sampling) rpeaks, = bsp_ecg.correct_rpeaks(signal=filtered, rpeaks=rpeaks, sampling_rate=freq_sampling, tol=0.05) _, qrs_detections = bsp_ecg.extract_heartbeats( signal=filtered, rpeaks=rpeaks, sampling_rate=freq_sampling, before=0.2, after=0.4) elif algorithm == 'Engelse-Zeelenberg-biosppy': order = int(0.3 * freq_sampling) filtered, _, _ = bsp_tools.filter_signal(signal=sig, ftype='FIR', band='bandpass', order=order, frequency=[3, 45], sampling_rate=freq_sampling) rpeaks, = bsp_ecg.engzee_segmenter(signal=filtered, sampling_rate=freq_sampling) rpeaks, = bsp_ecg.correct_rpeaks(signal=filtered, rpeaks=rpeaks, sampling_rate=freq_sampling, tol=0.05) _, qrs_detections = bsp_ecg.extract_heartbeats( signal=filtered, rpeaks=rpeaks, sampling_rate=freq_sampling, before=0.2, after=0.4) elif algorithm == 'Gamboa-biosppy': order = int(0.3 * freq_sampling) filtered, _, _ = bsp_tools.filter_signal(signal=sig, ftype='FIR', band='bandpass', order=order, frequency=[3, 45], sampling_rate=freq_sampling) rpeaks, = bsp_ecg.gamboa_segmenter(signal=filtered, sampling_rate=freq_sampling) rpeaks, = bsp_ecg.correct_rpeaks(signal=filtered, rpeaks=rpeaks, sampling_rate=freq_sampling, tol=0.05) _, qrs_detections = bsp_ecg.extract_heartbeats( signal=filtered, rpeaks=rpeaks, sampling_rate=freq_sampling, before=0.2, after=0.4) elif algorithm == 'mne-ecg': qrs_detections = mne_ecg.qrs_detector(freq_sampling, sig) elif algorithm == 'heartpy': rol_mean = rolling_mean(sig, windowsize=0.75, sample_rate=100.0) qrs_detections = hp_pkdetection.detect_peaks( sig, rol_mean, ma_perc=20, sample_rate=100.0)['peaklist'] elif algorithm == 'gqrs-wfdb': qrs_detections = processing.qrs.gqrs_detect(sig=sig, fs=freq_sampling) elif algorithm == 'xqrs-wfdb': qrs_detections = processing.xqrs_detect(sig=sig, fs=freq_sampling) else: raise ValueError( f'Sorry... unknown algorithm. Please check the list {algorithms_list}' ) cast_qrs_detections = [int(element) for element in qrs_detections] return cast_qrs_detections
def rinfo_engzee(self, threshold=0.48): """Get ECG R peaks by engzee algorithm. """ return ecg.engzee_segmenter(self.__ecg, self.__signal_rate, threshold)
def calculateECGFeatures(dataFrame, smooth=True, normalize=True): ''' Inputs: dataFrame pandas.dataFrame containing clip of raw ECG data, should have two columns of Timestamps (ms) and Sample (V) smooth optional Boolean, default value is True, flag for whether to smooth input raw ECG data or not normalize option Boolean, default value is True, flag for whether to normalize input raw ECG data or not Outputs: features pandas.dataFrame for input clip of data, each column corresponds to a different feature, included features are as follows: - mean - ultra low frequency power - median - very low frequency power - max - low frequency power - variance - high frequency power - standard deviation - LF/HF ratio - absolute deviation - total power - kurtois - R-R interval - skew ''' # ---------------------------------------------------------------------------------------------------- # Data Preprocessing --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- time = dataFrame['Timestamp (ms)'].values data = dataFrame['Sample (V)'].values ## Smooth raw ECG data if smooth: smooth_signal = tools.smoother( data, kernel='median', size=5) # Convolutional 5x5 kernel window data = smooth_signal['signal'] ## Normalize raw ECG data if normalize: norm_signal = tools.normalize(data) data = norm_signal['signal'] # ---------------------------------------------------------------------------------------------------- # Begin Features Extraction Code --------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- ## Calculate basic statistic features s_mean, s_med, s_max, s_var, s_std_dev, s_abs_dev, s_kurtois, s_skew = tools.signal_stats( data) ## Obtain Power Spectra power_freqs, power_spectrum = tools.power_spectrum(data, sampling_rate=2.0, decibel=False) ## Calculate Ultra Low-Frequency Power (ULF Band: <= 0.003 Hz) # power_ulf = tools.band_power(freqs=power_freqs, power=power_spectrum, frequency=[0, 0.003]) # power_ulf = np.absolute(power_ulf['avg_power']) # Calculate Very Low-Frequency Power (VLF Band: 0.0033 - 0.04 Hz) power_vlf = tools.band_power(freqs=power_freqs, power=power_spectrum, frequency=[0.0033, 0.04]) power_vlf = np.absolute(power_vlf['avg_power']) # Calculate Low-Frequency Power (LF Band: 0.04 - 0.15 Hz Hz) power_lf = tools.band_power(freqs=power_freqs, power=power_spectrum, frequency=[0.04, 0.15]) power_lf = np.absolute(power_lf['avg_power']) ## Calculate High-Frequency Power (HF Band: 0.15 - 0.40 Hz) power_hf = tools.band_power(freqs=power_freqs, power=power_spectrum, frequency=[0.15, 0.40]) power_hf = np.absolute(power_hf['avg_power']) ## Calculate LF/HF Ratio lf_hf_ratio = power_lf / power_hf ## Calculate Total Power (VLF + LF + HF power) power_total = power_vlf + power_lf + power_hf # Calculate R peak indices r_peaks = ecg.engzee_segmenter(data, sampling_rate=500.0) if np.size(r_peaks) != 1: rr_indices = time[r_peaks] rr_intervals = np.mean(np.diff(rr_indices)) else: rr_intervals = np.nan # NaN indicates not enough R peaks within window to calculate R-R interval # ---------------------------------------------------------------------------------------------------- # Collect Features and convert into dataFrame -------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- signal_features = { 'mean': s_mean, 'median': s_med, 'max': s_max, 'variance': s_var, 'std_dev': s_std_dev, 'abs_dev': s_abs_dev, 'kurtois': s_kurtois, 'skew': s_skew, # 'ulf_power': power_ulf, 'vlf_power': power_vlf, 'lf_power': power_lf, 'hf_power': power_hf, 'lf_hf_ratio': lf_hf_ratio, 'rr_interval': rr_intervals, } features = pd.Series(signal_features) a = [ s_mean, s_med, s_max, s_var, s_std_dev, s_abs_dev, s_kurtois, s_skew, # power_ulf, power_vlf, power_lf, power_hf, lf_hf_ratio, rr_intervals # rr_indices ] return a