def test_none_interpolation_method(self, _rri, _welch): random_values = np.random.randn(10) _welch.return_value = (random_values, random_values) _rri.return_value = self.real_rri frequency_domain(self.real_rri, interp_method=None) _welch.assert_called_once_with(fs=4.0, x=self.real_rri)
def test_frequency_domain_function_using_pburg(self, _pburg_psd, _irr, _auc): fake_rri = [1, 2, 3, 4] _irr.return_value = fake_rri _pburg_psd.return_value = (np.array([1, 2]), np.array([3, 4])) frequency_domain(fake_rri, fs=4, method='ar', interp_method='cubic', order=16) _pburg_psd.assert_called_once_with(rri=fake_rri, fs=4, order=16)
def test_uses_cubic_interpolation_method(self, _interp_time, _splrep, _splev): fake_values = np.arange(10) _interp_time.return_value = fake_values _splrep.return_value = fake_values _splev.return_value = fake_values frequency_domain(self.real_rri, interp_method='cubic') _splev.assert_called_once_with(fake_values, fake_values, der=0)
def feature_extraction(recording, signal, labels): data = [] for i in tqdm(range(len(labels)), desc=recording, file=sys.stdout): segment = signal[i * fs * 60:(i + 1) * fs * 60] segment, _, _ = st.filter_signal(segment, ftype='FIR', band='bandpass', order=int(0.3 * fs), frequency=[3, 45], sampling_rate=fs) # Finding R peaks rpeaks, = hamilton_segmenter(segment, sampling_rate=fs) rpeaks, = correct_rpeaks(segment, rpeaks, sampling_rate=fs, tol=0.1) # Extracting feature label = 0 if labels[i] == "N" else 1 if 40 <= len(rpeaks) <= 200: # Remove abnormal R peaks rri_tm, rri = rpeaks[1:] / float(fs), np.diff(rpeaks, axis=-1) / float(fs) rri = medfilt(rri, kernel_size=3) edr_tm, edr = rpeaks / float(fs), segment[rpeaks] # Remove physiologically impossible HR signal if np.all(np.logical_and(60 / rri >= hr_min, 60 / rri <= hr_max)): rri_time_features, rri_frequency_features = time_domain( rri * 1000), frequency_domain(rri, rri_tm) edr_frequency_features = frequency_domain(edr, edr_tm) # 6 + 6 + 6 + 1 = 19 data.append([ rri_time_features["rmssd"], rri_time_features["sdnn"], rri_time_features["nn50"], rri_time_features["pnn50"], rri_time_features["mrri"], rri_time_features["mhr"], rri_frequency_features["vlf"] / rri_frequency_features["total_power"], rri_frequency_features["lf"] / rri_frequency_features["total_power"], rri_frequency_features["hf"] / rri_frequency_features["total_power"], rri_frequency_features["lf_hf"], rri_frequency_features["lfnu"], rri_frequency_features["hfnu"], edr_frequency_features["vlf"] / edr_frequency_features["total_power"], edr_frequency_features["lf"] / edr_frequency_features["total_power"], edr_frequency_features["hf"] / edr_frequency_features["total_power"], edr_frequency_features["lf_hf"], edr_frequency_features["lfnu"], edr_frequency_features["hfnu"], label ]) else: data.append([np.nan] * 18 + [label]) else: data.append([np.nan] * 18 + [label]) data = np.array(data, dtype="float") return data
def test_using_rri_class(self, _interp): """ Test if no time is passed as argument the frequency domain function uses time array from RRi class """ _interp.return_value = [800, 810, 790, 815] rri = RRi([800, 810, 790, 815]) frequency_domain(rri) _interp.assert_called_once_with(rri, rri.time, 4.0, "cubic")
def test_frequency_domain_with_welch_method(self): time = np.cumsum(self.real_rri) / 1000.0 time -= time[0] response = frequency_domain( self.real_rri, time=time, fs=4, method="welch", nperseg=256, noverlap=128, window="hanning", ) expected = { "total_power": 3602.89, "vlf": 844.5, "lf": 1343.50, "hf": 1414.88, "lf_hf": 0.94, "lfnu": 48.70, "hfnu": 51.29, } np.testing.assert_almost_equal(sorted(response.values()), sorted(expected.values()), decimal=2) self.assertEqual(response.keys(), expected.keys())
def test_frequency_domain_with_welch_and_detrended_rri( self, _interpolate_rri, _welch, _auc): _interpolate_rri.return_value = [1, 2, 3, 4] fake_rri = RRiDetrended([-1, -2, -3, -4], time=[5, 6, 7, 8]) frequency_domain(fake_rri, time=fake_rri.time, fs=4, method='welch', nperseg=256, noverlap=128, window='hanning') _welch.assert_called_once_with( x=[1, 2, 3, 4], fs=4, detrend=False, noverlap=128, nperseg=256, window='hanning' )
def calculate_hrv_features(rri, f=360): """ Calculate features for detecting sleep apnea The features contain statistical measures, morphology and periodogram of the ECG signal. Parameters ---------- RR_int: array_like Array containing RR intervals f: float, optional Number corresponding to the sampling frequency of the input signal, must be in Hertz Returns ------- X: array_like Features """ result_td = np.reshape(np.asarray(list(time_domain(rri).values())), (1, 6)) result_fd = np.reshape(np.asarray(list(frequency_domain(rri).values())), (1, 7)) result_nl = np.reshape(np.asarray(list(non_linear(rri).values())), (1, 2)) hrv_features = np.concatenate([result_td, result_fd, result_nl], axis=1) return hrv_features
def test_frequency_domain_with_welch_and_detrended_rri_and_interp( self, _interpolate_rri, _welch, _auc): fake_rri = RRiDetrended( [-1, -2, -3, -4], time=[5, 6, 7, 8], interpolated=True ) frequency_domain(fake_rri, time=fake_rri.time, fs=4, method='welch', nperseg=256, noverlap=128, window='hanning') _interpolate_rri.assert_not_called() _welch.assert_called_once_with( x=fake_rri, fs=4, detrend=False, noverlap=128, nperseg=256, window='hanning' )
def test_frequency_domain_function_using_pburg(self, _pburg_psd, _irr, _auc): fake_rri = [1, 2, 3, 4] _irr.return_value = fake_rri _pburg_psd.return_value = (np.array([1, 2]), np.array([3, 4])) frequency_domain(fake_rri, fs=4, method="ar", interp_method="cubic", order=16) expected_called_rri = [ -0.19565217, 0.15217391, 0.17391304, -0.13043478 ] pburg_args_list = _pburg_psd.call_args_list[0][1] assert isinstance(pburg_args_list["rri"], RRiDetrended) np.testing.assert_almost_equal(expected_called_rri, pburg_args_list["rri"].values) assert 4 == pburg_args_list["fs"] assert 16 == pburg_args_list["order"]
def test_frequency_domain_with_pburg_and_detrend(self, _interpolate_rri, _pburg, _auc, _poly_detrend): "If pburg method is selected use detrend options from hrv module" _interpolate_rri.return_value = [1, 2, 3, 4] _poly_detrend.return_value = [-1, -2, -3, -4] fake_rri = RRi([1, 2, 3, 4], time=[5, 6, 7, 8]) fake_time = fake_rri.time frequency_domain(fake_rri, time=fake_time, fs=4, method="ar", order=16, detrend="linear") _interpolate_rri.assert_called_once_with(fake_rri, fake_time, 4, "cubic") _poly_detrend.assert_called_once_with([1, 2, 3, 4], degree=1) _pburg.assert_called_once_with( rri=[-1, -2, -3, -4], fs=4, order=16, )
def test_frequency_domain_with_welch_method(self): time = np.cumsum(self.real_rri) / 1000.0 time -= time[0] response = frequency_domain(self.real_rri, time=time, fs=4, method='welch', nperseg=256, noverlap=128, window='hanning') expected = {'total_power': 3602.89, 'vlf': 844.5, 'lf': 1343.50, 'hf': 1414.88, 'lf_hf': 0.94, 'lfnu': 48.70, 'hfnu': 51.29} np.testing.assert_almost_equal(sorted(response.values()), sorted(expected.values()), decimal=2) self.assertEqual(response.keys(), expected.keys())
def test_correct_response(self): response = frequency_domain(self.real_rri, fs=4, method='welch', nperseg=256, noverlap=128, window='hanning') expected = { 'total_power': 3602.90, 'vlf': 844.5, 'lf': 1343.51, 'hf': 1414.88, 'lf_hf': 0.94, 'lfnu': 48.71, 'hfnu': 51.28 } np.testing.assert_almost_equal(sorted(response.values()), sorted(expected.values()), decimal=2) self.assertEqual(response.keys(), expected.keys())
def get_hrv(rr_interval): """Get three domain heart rate variability. Get time domain, frequency domain, and non-linear domain heart rate variability. Args: rr_interval: narray, RR-interval. Returns: A dictionary representation of the three domain HRV. Notes: *Authors* - the hrv dev team (https://github.com/rhenanbartels/hrv) *Dependencies* - hrv - numpy *See Also* - hrv: https://github.com/rhenanbartels/hrv """ if np.median(rr_interval) < 1: rr_interval *= 1000 time_domain_analysis = time_domain(rr_interval) frequency_domain_analysis = frequency_domain(rri=rr_interval, fs=4.0, method='welch', interp_method='cubic', detrend='linear') non_linear_domain_analysis = non_linear(rr_interval) hrv_info = { 'time': time_domain_analysis, 'frequency': frequency_domain_analysis, 'non-linear': non_linear_domain_analysis } return hrv_info
from hrv.classical import frequency_domain from hrv.utils import open_rri import csv for name in range(1, 106): rri = open_rri(str(name) + '_.txt') results = frequency_domain(rri=rri, fs=4.0, method='welch', interp_method='cubic', detrend='linear') print("For data sample: " + str(name)) print(results) output_csv_name = str(name) + '_hrvfd.csv' with open(output_csv_name, 'wb') as f: # Just use 'w' mode in 3.x w = csv.DictWriter(f, results.keys()) w.writeheader() w.writerow(results) print(str(name) + ' rri file has been written to csv')
def test_uses_linear_interpolate_method(self, _interp): _interp.return_value = np.arange(10) frequency_domain(self.real_rri, interp_method='linear')