Generation of Poincaré Plot from ECG Analysis
Difficulty Level:
 Tags pre-process☁ecg☁poincare

The Poincaré Plot defines a geometrical and non-linear approach for studying heart rate variability and in a more generic perspective is also a methodology to quantify the level of chaos in periodic processes.

This structure consists in a bidimensional plot, where each of its points has as coordinates the duration of two consecutive RR intervals ( $RR[i]$, $RR[i + 1]$ ), i.e. from tachogram each pair of samples i and i + 1 define a point in the Poincaré Plot.

There are two reference lines mathematically defined by the following equations:

 $$RR[i + 1] = RR[i]$$ $$RR[i + 1] = -RR[i] + 2 avg(RR)$$

If the dispersion of Poincaré points in relation to these lines is high, than it can be concluded that heart rate variability is high.

1 - Importing needed packages

In [1]:
# biosignalsnotebooks own package for loading and plotting the acquired data
import biosignalsnotebooks as bsnb

# Scientific packages
import numpy
import math


2 - Load of acquired ECG data

In [2]:
# Load of data (using a relative path of the project)


3 - Identification of mac address of the device and the channel used during acquisition

In [3]:
channel = list(data.keys())[0]

In [4]:
print ("Mac Address: " + str(header["device name"]) + " Channel: " + str(channel))

Mac Address: b'00:07:80:58:9B:3F' Channel: CH1


4 - Storage of sampling frequency and acquired data inside variables

In [5]:
# Sampling frequency and acquired data
fs = header["sampling rate"]

# Signal Samples
signal = data[channel]
time = numpy.linspace(0, len(signal) / fs, len(signal))


5 - Generation of tachogram

In [6]:
tachogram_data, tachogram_time = bsnb.tachogram(signal, fs, signal=True, out_seconds=True)


6 - Axes of Poincaré plot

In [7]:
rr_i = tachogram_data[:-1]
rr_i_plus_1 = tachogram_data[1:]


7 - Generation of Poincaré Plot

In [8]:
bsnb.dispersion(rr_i, rr_i_plus_1, 'RR\u1D62 (s)', 'RR\u1D62\u208A\u2081 (s)')

Out[8]:
[Figure(id='1001', ...)]

8 - Determination of SD1 and SD2 parameters

These parameters quantify the dispersion level of the Poincaré samples regarding to each reference line, being proportional to the short and long-term heart rate variability, respectively.

 $$SD1 = \sqrt{\frac{SDSD^2}{2}}$$ $$SD2 = \sqrt{2 \times SDNN^2 - SD1^2}$$
where:
 $$SDSD = \sqrt{\frac{\sum_{i=2}^N ((RR[i] - RR[i - 1]) - \overline{RR_i - RR_{i - 1}})^2}{N - 1}}$$ $$SDNN = \sqrt{\frac{\sum_{i=1}^N (RR[i] - \overline{RR})^2}{N - 1}}$$
and:
 $\overline{RR_i - RR_{i - 1}}$ is the average value of the first derivative of tachogram, while $\overline{RR}$ is the average value of the tachogram samples
In [9]:
tachogram_diff = numpy.diff(tachogram_data)
SDSD = numpy.std(tachogram_diff)
SDNN = numpy.std(tachogram_data)

SD1 = numpy.sqrt(0.5 * numpy.power(SDSD, 2))
SD2 = numpy.sqrt(2 * numpy.power(SDNN, 2) - numpy.power(SD1, 2))

avg_rr = numpy.average(tachogram_data)


9 - Representation of Poincaré Plot with associated parameters

In [10]:
list_figures = bsnb.plot_poincare(tachogram_data)


This procedure can be automatically done by poincare function in process module of biosignalsnotebooks package

In [11]:
x_axis, y_axis, SD1, SD2 = bsnb.poincare(signal, fs, signal=True, in_seconds=False)


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 !

 ☌ Project Presentation ☌ GitHub Repository ☌ How to install biosignalsnotebooks Python package ? ☌ Signal Library ☌ Notebook Categories ☌ Notebooks by Difficulty ☌ Notebooks by Signal Type ☌ Notebooks by Tag
In [12]:
bsnb.css_style_apply()

.................... CSS Style Applied to Jupyter Notebook .........................

Out[12]: