示例#1
0
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
示例#2
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
示例#3
0
 def test_correct_response_with_rri_in_seconds(self):
     response = time_domain(np.array(FAKE_RRI) / 1000)
     expected = {'rmssd': 38.07,
                 'sdnn': 29.82,
                 'nn50': 1,
                 'pnn50': 25,
                 'mrri':  793.75,
                 'mhr': 75.67}
     np.testing.assert_almost_equal(sorted(response.values()),
                                    sorted(expected.values()),
                                    decimal=2)
示例#4
0
 def test_correct_response(self):
     response = time_domain(FAKE_RRI)
     expected = {'rmssd': 38.07,
                 'sdnn': 29.82,
                 'nn50': 1,
                 'pnn50': 25,
                 'mrri':  793.75,
                 'mhr': 75.67}
     np.testing.assert_almost_equal(sorted(response.values()),
                                    sorted(expected.values()),
                                    decimal=2)
     self.assertEqual(response.keys(),
                      expected.keys())
示例#5
0
 def test_correct_response_with_rri_in_seconds(self):
     response = time_domain(np.array(FAKE_RRI) / 1000)
     expected = {
         "rmssd": 38.07,
         "sdnn": 29.82,
         "sdsd": 41.93,
         "nn50": 1,
         "pnn50": 25,
         "mrri": 793.75,
         "mhr": 75.67,
     }
     np.testing.assert_almost_equal(sorted(response.values()),
                                    sorted(expected.values()),
                                    decimal=2)
示例#6
0
 def test_correct_response(self):
     response = time_domain(FAKE_RRI)
     expected = {
         "rmssd": 38.07,
         "sdnn": 29.82,
         "sdsd": 41.93,
         "nn50": 1,
         "pnn50": 25,
         "mrri": 793.75,
         "mhr": 75.67,
     }
     np.testing.assert_almost_equal(sorted(response.values()),
                                    sorted(expected.values()),
                                    decimal=2)
     self.assertEqual(response.keys(), expected.keys())
示例#7
0
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.filters import moving_median

import numpy as np

# def _moving_function(rri, order, func):
# 	offset = int(order / 2)

# 	filt_rri = np.array(rri.copy(), dtype=np.float64)
# 	for i in range(offset, len(rri) - offset, 1):
# 		filt_rri[i] = func(rri[i-offset:i+offset+1])

# 	return filt_rri

# def moving_median(rri, order=3):
# 	return _moving_function(rri, order, np.median)

rri = open_rri('./data/test/extracted/Iris_kangxi_peyin_RRI.txt')
filt_rri = moving_median(rri, order=3)
results = time_domain(filt_rri)
print(results)

results = frequency_domain(rri=filt_rri,
                           fs=4.0,
                           method='welch',
                           interp_method='cubic',
                           detrend='linear')
print(results)

results = non_linear(filt_rri)
print(results)
# change it depending on which one you want output
specifier = 'td'

# this script is GENERAL purpose. you need to change some of these to match the filenames

for i in range(1, 55):  # change range
    filename_header = 'nsr' + str(i).zfill(3)  # change name possibly
    filename = filename_header + 'rri.txt'
    classifier = ''
    try:
        rri = open_rri(filename)
    except:
        continue

    if specifier == 'td':
        results = time_domain(rri)  # output is dict
    elif specifier == 'nl':
        results = non_linear(rri)
    else:
        print("Invalid argument!")

    output_csv_name = filename_header + 'hrv_' + specifier + '.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(filename_header + ' rri file has been processed')
""" print(results)
print(type(results)) """