예제 #1
0
    def test_moving_median_order_5(self):
        fake_rri = np.array([810, 830, 860, 790, 804, 801, 800])

        rri_filt = moving_median(fake_rri, order=5)

        expected = [810, 830, 810.0, 804.0, 801.0, 801, 800]
        np.testing.assert_almost_equal(rri_filt, expected, decimal=2)
예제 #2
0
    def test_moving_median_oder_3(self):
        fake_rri = np.array([810, 830, 860, 790, 804])

        rri_filt = moving_median(fake_rri, order=3)

        expected = [810, 830.0, 830.0, 804, 804]

        assert isinstance(rri_filt, RRi)
        np.testing.assert_almost_equal(rri_filt.values, expected, decimal=2)
예제 #3
0
    def test_movinng_filters_receiving_and_return_rri_class(self):
        fake_rri = RRi([810, 830, 860, 790, 804, 801, 800], time=[0, 1, 2, 3, 4, 5, 6])

        rri_filt = moving_median(fake_rri)

        expected_rri = [810, 830, 830, 804, 801, 801, 800]
        expected_time = [0, 1, 2, 3, 4, 5, 6]

        assert isinstance(rri_filt, RRi)
        np.testing.assert_almost_equal(rri_filt.values, expected_rri, decimal=2)
        np.testing.assert_almost_equal(rri_filt.time, expected_time, decimal=2)
예제 #4
0
        qrs_ann = wfdb.rdann(data_path + train_data_name[data_index],
                             'qrs',
                             sampfrom=samp_from - (MARGIN * 100),
                             sampto=samp_to + (MARGIN * 100)).sample
        apn_ann = wfdb.rdann(data_path + train_data_name[data_index],
                             'apn',
                             sampfrom=samp_from,
                             sampto=samp_to - 1).symbol

        qrs_amp = get_qrs_amp(signals, qrs_ann)

        rri = np.diff(qrs_ann)
        rri_ms = rri.astype('float') / FS * 1000.0
        try:
            rri_filt = moving_median(rri_ms)

            if len(rri_filt) > 5 and (np.min(rri_filt) >= MIN_RRI
                                      and np.max(rri_filt) <= MAX_RRI):
                time_intp, rri_intp = interp_cubic_spline(rri_filt, FS_INTP)
                qrs_time_intp, qrs_intp = interp_cubic_spline_qrs(
                    qrs_ann, qrs_amp, FS_INTP)
                rri_intp = rri_intp[(time_intp >= MARGIN)
                                    & (time_intp < (60 + MARGIN))]
                qrs_intp = qrs_intp[(qrs_time_intp >= MARGIN)
                                    & (qrs_time_intp < (60 + MARGIN))]
                #time_intp = time_intp[(time_intp >= MARGIN) & (time_intp < (60+MARGIN))]

                if len(rri_intp) != (FS_INTP * 60):
                    skip = 1
                else:
예제 #5
0
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)
예제 #6
0
        qrs_ann = wfdb.rdann(data_path + train_data_name[data_index],
                             'qrs',
                             sampfrom=samp_from - (MARGIN * 100),
                             sampto=samp_to + (MARGIN * 100)).sample
        apn_ann = wfdb.rdann(data_path + train_data_name[data_index],
                             'apn',
                             sampfrom=samp_from,
                             sampto=samp_to - 1).symbol

        qrs_amp = get_qrs_amp(signals, qrs_ann)

        rri = np.diff(qrs_ann)
        rri_ms = rri.astype('float') / FS * 1000.0

        rri_filt = moving_median(rri_ms)
        qrs_filt = moving_median(qrs_amp)
        if rri_filt.shape[0] > 5 and (np.min(rri_filt) >= MIN_RRI
                                      and np.max(rri_filt) <= MAX_RRI):
            time_intp, rri_intp = interp_cubic_spline(rri_filt, FS_INTP)
            qrs_time_intp, qrs_intp = interp_cubic_spline_qrs(
                qrs_ann, qrs_amp, FS_INTP)
            rri_intp = rri_intp[(time_intp >= MARGIN)
                                & (time_intp < (60 + MARGIN))]
            qrs_intp = qrs_intp[(qrs_time_intp >= MARGIN)
                                & (qrs_time_intp < (60 + MARGIN))]
            #time_intp = time_intp[(time_intp >= MARGIN) & (time_intp < (60+MARGIN))]

            if len(rri_intp) != (FS_INTP * 60):
                skip = 1
            else:
def apnea_preproc():
    import wfdb
    import matplotlib.pyplot as plt
    import numpy as np
    from hrv.filters import quotient, moving_median
    from scipy import interpolate
    from tqdm import tqdm
    import os
    FS = 100.0

    # From https://github.com/rhenanbartels/hrv/blob/develop/hrv/classical.py
    def create_time_info(rri):
        rri_time = np.cumsum(rri) / 1000.0  # make it seconds
        return rri_time - rri_time[0]  # force it to start at zero

    def create_interp_time(rri, fs):
        time_rri = create_time_info(rri)
        return np.arange(0, time_rri[-1], 1 / float(fs))

    def interp_cubic_spline(rri, fs):
        time_rri = create_time_info(rri)
        time_rri_interp = create_interp_time(rri, fs)
        tck = interpolate.splrep(time_rri, rri, s=0)
        rri_interp = interpolate.splev(time_rri_interp, tck, der=0)
        return time_rri_interp, rri_interp

    def interp_cubic_spline_qrs(qrs_index, qrs_amp, fs):
        time_qrs = qrs_index / float(FS)
        time_qrs = time_qrs - time_qrs[0]
        time_qrs_interp = np.arange(0, time_qrs[-1], 1 / float(fs))
        tck = interpolate.splrep(time_qrs, qrs_amp, s=0)
        qrs_interp = interpolate.splev(time_qrs_interp, tck, der=0)
        return time_qrs_interp, qrs_interp

    data_path = f'{DATASET_DIR}/apnea/'
    train_data_name = [
        'a01',
        'a02',
        'a03',
        'a04',
        'a05',
        'a06',
        'a07',
        'a08',
        'a09',
        'a10',
        'a11',
        'a12',
        'a13',
        'a14',
        'a15',
        'a16',
        'a17',
        'a18',
        'a19',
        'b01',
        'b02',
        'b03',
        'b04',
        'c01',
        'c02',
        'c03',
        'c04',
        'c05',
        'c06',
        'c07',
        'c08',
        'c09',
    ]
    test_data_name = ['a20', 'b05', 'c10']
    age = [
        51, 38, 54, 52, 58, 63, 44, 51, 52, 58, 58, 52, 51, 51, 60, 44, 40, 52,
        55, 58, 44, 53, 53, 42, 52, 31, 37, 39, 41, 28, 28, 30, 42, 37, 27
    ]
    sex = [
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
        1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1
    ]

    def get_qrs_amp(ecg, qrs):
        interval = int(FS * 0.250)
        qrs_amp = []
        for index in range(len(qrs)):
            curr_qrs = qrs[index]
            amp = np.max(ecg[curr_qrs - interval:curr_qrs + interval])
            qrs_amp.append(amp)

        return qrs_amp

    MARGIN = 10
    FS_INTP = 4
    MAX_HR = 300.0
    MIN_HR = 20.0
    MIN_RRI = 1.0 / (MAX_HR / 60.0) * 1000
    MAX_RRI = 1.0 / (MIN_HR / 60.0) * 1000
    train_input_array = []
    train_label_array = []

    for data_index in range(len(train_data_name)):
        print(train_data_name[data_index])
        win_num = len(
            wfdb.rdann(os.path.join(data_path, train_data_name[data_index]),
                       'apn').symbol)
        signals, fields = wfdb.rdsamp(
            os.path.join(data_path, train_data_name[data_index]))
        for index in tqdm(range(1, win_num)):
            samp_from = index * 60 * FS  # 60 seconds
            samp_to = samp_from + 60 * FS  # 60 seconds

            qrs_ann = wfdb.rdann(data_path + train_data_name[data_index],
                                 'qrs',
                                 sampfrom=samp_from - (MARGIN * 100),
                                 sampto=samp_to + (MARGIN * 100)).sample
            apn_ann = wfdb.rdann(data_path + train_data_name[data_index],
                                 'apn',
                                 sampfrom=samp_from,
                                 sampto=samp_to - 1).symbol

            qrs_amp = get_qrs_amp(signals, qrs_ann)

            rri = np.diff(qrs_ann)
            rri_ms = rri.astype('float') / FS * 1000.0
            try:
                rri_filt = moving_median(rri_ms)

                if len(rri_filt) > 5 and (np.min(rri_filt) >= MIN_RRI
                                          and np.max(rri_filt) <= MAX_RRI):
                    time_intp, rri_intp = interp_cubic_spline(
                        rri_filt, FS_INTP)
                    qrs_time_intp, qrs_intp = interp_cubic_spline_qrs(
                        qrs_ann, qrs_amp, FS_INTP)
                    rri_intp = rri_intp[(time_intp >= MARGIN)
                                        & (time_intp < (60 + MARGIN))]
                    qrs_intp = qrs_intp[(qrs_time_intp >= MARGIN)
                                        & (qrs_time_intp < (60 + MARGIN))]
                    #time_intp = time_intp[(time_intp >= MARGIN) & (time_intp < (60+MARGIN))]

                    if len(rri_intp) != (FS_INTP * 60):
                        skip = 1
                    else:
                        skip = 0

                    if skip == 0:
                        rri_intp = rri_intp - np.mean(rri_intp)
                        qrs_intp = qrs_intp - np.mean(qrs_intp)
                        if apn_ann[0] == 'N':  # Normal
                            label = 0.0
                        elif apn_ann[0] == 'A':  # Apnea
                            label = 1.0
                        else:
                            label = 2.0

                        train_input_array.append([
                            rri_intp, qrs_intp, age[data_index],
                            sex[data_index]
                        ])
                        train_label_array.append(label)
            except:
                hrv_module_error = 1
    print(train_input_array[0])
    print(train_label_array[0])
    np.save('train_input.npy', train_input_array)
    np.save('train_label.npy', train_label_array)

    test_input_array = []
    test_label_array = []
    for data_index in range(len(test_data_name)):
        print(test_data_name[data_index])
        win_num = len(
            wfdb.rdann(os.path.join(data_path, test_data_name[data_index]),
                       'apn').symbol)
        signals, fields = wfdb.rdsamp(
            os.path.join(data_path, test_data_name[data_index]))
        for index in tqdm(range(1, win_num)):
            samp_from = index * 60 * FS  # 60 seconds
            samp_to = samp_from + 60 * FS  # 60 seconds

            qrs_ann = wfdb.rdann(data_path + test_data_name[data_index],
                                 'qrs',
                                 sampfrom=samp_from - (MARGIN * 100),
                                 sampto=samp_to + (MARGIN * 100)).sample
            apn_ann = wfdb.rdann(data_path + test_data_name[data_index],
                                 'apn',
                                 sampfrom=samp_from,
                                 sampto=samp_to - 1).symbol

            qrs_amp = get_qrs_amp(signals, qrs_ann)

            rri = np.diff(qrs_ann)
            rri_ms = rri.astype('float') / FS * 1000.0
            try:
                rri_filt = moving_median(rri_ms)

                if len(rri_filt) > 5 and (np.min(rri_filt) >= MIN_RRI
                                          and np.max(rri_filt) <= MAX_RRI):
                    time_intp, rri_intp = interp_cubic_spline(
                        rri_filt, FS_INTP)
                    qrs_time_intp, qrs_intp = interp_cubic_spline_qrs(
                        qrs_ann, qrs_amp, FS_INTP)
                    rri_intp = rri_intp[(time_intp >= MARGIN)
                                        & (time_intp < (60 + MARGIN))]
                    qrs_intp = qrs_intp[(qrs_time_intp >= MARGIN)
                                        & (qrs_time_intp < (60 + MARGIN))]
                    #time_intp = time_intp[(time_intp >= MARGIN) & (time_intp < (60+MARGIN))]

                    if len(rri_intp) != (FS_INTP * 60):
                        skip = 1
                    else:
                        skip = 0

                    if skip == 0:
                        rri_intp = rri_intp - np.mean(rri_intp)
                        qrs_intp = qrs_intp - np.mean(qrs_intp)
                        if apn_ann[0] == 'N':  # Normal
                            label = 0.0
                        elif apn_ann[0] == 'A':  # Apnea
                            label = 1.0
                        else:
                            label = 2.0

                        test_input_array.append([
                            rri_intp, qrs_intp, age[data_index],
                            sex[data_index]
                        ])
                        test_label_array.append(label)
            except:
                hrv_module_error = 1
    np.save('test_input.npy', test_input_array)
    np.save('test_label.npy', test_label_array)