|
ECG Analysis - Heart Rate Variability Parameters |
Tags | extract☁ecg☁hrv |
Using an analogy with the programming paradigms, electrophysiological signals can be viewed as objects containing lots of information inside. However obtatining knowledge from an object is only possible by accessing its attributes (characteristics).
In signal processing there is an identical logic, so, for extracting knowledge from signals (our objects), we need to identify their intrinsic characteristics (parameters).
The following description explains how to extract some parameters from ECG, commonly used for heart rate variability analysis (HRV).
List of HRV analysis parameters:
☌
Minimum, Maximum and Average RR Interval;
☌
Minimum, Maximum and Average Heart Rate (BPM);
☌
SDNN;
☌
rmsSD;
☌
NN20, pNN20;
☌
NN50, pNN50;
☌
Power inside ULF, VLF, LF and HF Frequency Bands;
☌
SD1, SD2, SD1 / SD2;
1 - Importation of the needed packages
# biosignalsnotebooks own package for loading and plotting the acquired data
import biosignalsnotebooks as bsnb
# Scientific packages
from numpy import linspace, max, min, average, std, array, diff, fabs, sqrt, power, round
from scipy.integrate import simps
2 - Load of acquired ECG data
# Load of data
data, header = bsnb.load_signal("ecg_5_min", get_header=True)
3 - Identification of the channel used during acquisition
channel = list(data.keys())[0]
4 - Storage of sampling frequency and acquired data inside variables
# Sampling frequency and acquired data
fs = header["sampling rate"]
# Signal Samples
signal = data[channel]
time = linspace(0, len(signal) / fs, len(signal))
5 - Generation of tachogram
Tachogram defines the fundamental structure from where all parameters will be extracted.tachogram_data, tachogram_time = bsnb.tachogram(signal, fs, signal=True, out_seconds=True)
6 - Removal of ectopic beats
A commonly accepted definition for ectopic beats establishes that a cardiac cycle that differs in at least 20 % of the duration of the previous one, can be considered an ectopic beat that should be removed.tachogram_data_NN, tachogram_time_NN = bsnb.remove_ectopy(tachogram_data, tachogram_time)
bpm_data = (1 / array(tachogram_data_NN)) * 60
7 - Comparison between the tachograms obtained before and after ectopic beat removal
We can conclude that there are not ectopic beats in the present acquisition
8 - Extraction of Parameters
8.1 - Time Parameters
# Maximum, Minimum and Average RR Interval
max_rr = max(tachogram_data_NN)
min_rr = min(tachogram_data_NN)
avg_rr = average(tachogram_data_NN)
# Maximum, Minimum and Average Heart Rate
max_hr = 1 / min_rr # Cycles per second
max_bpm = max_hr * 60 # BPM
min_hr = 1 / max_rr # Cycles per second
min_bpm = min_hr * 60 # BPM
avg_hr = 1 / avg_rr # Cyles per second
avg_bpm = avg_hr * 60 # BPM
# SDNN
sdnn = std(tachogram_data_NN)
time_param_dict = {"Maximum RR": max_rr, "Minimum RR": min_rr, "Average RR": avg_rr, "Maximum BPM": max_bpm, "Minimum BPM": min_bpm, "Average BPM": avg_bpm, "SDNN": sdnn}
8.2 - Poincaré Parameters
# Auxiliary Structures
tachogram_diff = diff(tachogram_data)
tachogram_diff_abs = fabs(tachogram_diff)
sdsd = std(tachogram_diff)
rr_i = tachogram_data[:-1]
rr_i_plus_1 = tachogram_data[1:]
# Poincaré Parameters
sd1 = sqrt(0.5 * power(sdsd, 2))
sd2 = sqrt(2 * power(sdnn, 2) - power(sd1, 2))
sd1_sd2 = sd1 / sd2
8.3 - Frequency Parameters
# Auxiliary Structures
freqs, power_spect = bsnb.psd(tachogram_time, tachogram_data) # Power spectrum.
# Frequemcy Parameters
freq_bands = {"ulf_band": [0.00, 0.003], "vlf_band": [0.003, 0.04], "lf_band": [0.04, 0.15], "hf_band": [0.15, 0.40]}
power_values = {}
total_power = 0
band_keys = freq_bands.keys()
for band in band_keys:
freq_band = freq_bands[band]
freq_samples_inside_band = [freq for freq in freqs if freq >= freq_band[0] and freq <= freq_band[1]]
power_samples_inside_band = [p for p, freq in zip(power_spect, freqs) if freq >= freq_band[0] and freq <= freq_band[1]]
power = round(simps(power_samples_inside_band, freq_samples_inside_band), 5)
# Storage of power inside each band
power_values[band] = power
# Total power update
total_power = total_power + power
Additional Temporal Parameters
# Number of RR intervals that have a difference in duration, from the previous one, of at least 20 ms
nn20 = sum(1 for i in tachogram_diff_abs if i > 0.02)
pnn20 = int(float(nn20) / len(tachogram_diff_abs) * 100) # Percentage value.
# Number of RR intervals that have a difference in duration, from the previous one, of at least 50 ms
nn50 = sum(1 for i in tachogram_diff_abs if i > 0.05)
pnn50 = int(float(nn50) / len(tachogram_diff_abs) * 100) # Percentage value.
This procedure can be automatically done by hrv_parameters function in extract module of biosignalsnotebooks package
dictParameters = bsnb.hrv_parameters(signal, fs, signal=True)
print (dictParameters)
This set of parameters reveals interesting information about ECG signal, however you can extract much more features during your signal processing journey !
We hope that you have enjoyed this guide. biosignalsnotebooks is an environment in continuous expansion, so don"t stop your journey and learn more with the remaining Notebooks !