forked from pickus91/HRV
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpoincare.py
207 lines (152 loc) · 7.33 KB
/
poincare.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# -*- coding: utf-8 -*-
"""
Created on Sat Mar 18 19:19:25 2017
@author: Sarah Pickus
Poincare plots are an important visualization technique for quantifying the non-linear
characteristics of the RR interval time series. They are generated via plotting
each RR interval (RR[n]) against the subsequent RR interval (RR[n+1]). There are
a number of geometrical descriptors that can be extracted from the poincare
plot that have been shown to provide insights into short and long term HRV
trends. This package allows the user to calculate a number of these poincare
features, which are detailed below:
elipseFittingMethod : The ellipse fitting technique is one of the most popular
methods for characterizing the geometry of the poincare
plot and providing insights into the level of short- and
long-term variability. The short-term variability is
represented by SD1, which is the standard deviation of points
perpendicular to the axis line-of-identy, while the
long-term variability is represented by SD2, which is the
tandard deviation of points along the line-of-identy.
This method is described in detail in:
Brennan, Michael, Marimuthu Palaniswami, and Peter Kamen.
"Do existing measures of Poincare plot geometry reflect
nonlinear features of heart rate variability?." IEEE
transactions on biomedical engineering 48.11 (2001):
1342-1347.
hraMethod : C_UP and C_DOWN are derived from the standard descriptor
SD1^2, the variance of which corresponds to short-term HRV.
These more refined descriptors quantify the Poincare plot
assymetry about the line-of-identity and in doing so
characterize accelerations (C_DOWN) and decelerations (C_UP)
of heart rate. More details on this method can be found here:
Piskorski, J., and P. Guzik. "Geometry of the Poincaré plot
of RR intervals and its asymmetry in healthy adults."
Physiological measurement 28.3 (2007): 287.
correlationCoefficient: The interbeat autocorrelation coefficient of the RR
interval time series (Pearson's correlation coefficient)
has been shown to characterize poincare plot geometry,
as shown in:
Otzenberger, Hélène, et al. "Dynamic heart rate variability:
a tool for exploring sympathovagal balance continuously
during sleep in men." American Journal of Physiology
275 (1998): H946-H950.
Additionally, this package allows you to generate a poincare plot and generate histogram
distributions from mulitple projections. Statistical properties of these projections
can then be calculated as additional descriptors.
"""
import numpy as np
from matplotlib import style
import matplotlib.pyplot as plt
style.use('ggplot')
def plotPoincare(RRints):
"""
Input :
- RRints: [list] of RR intervals
Output :
- Poincare plot
"""
ax1 = RRints[:-1]
ax2 = RRints[1:]
plt.scatter(ax1, ax2, c = 'r', s = 12)
plt.xlabel('RR_n (s)')
plt.ylabel('RR_n+1 (s)')
plt.show()
def eclipseFittingMethod(RRints):
"""
Input :
- RRints : [list] of RR intervals
Output :
- SD1, SD2 : {dict} with keys 'SD1' (numpy.float64), representing short-term
variation, and 'SD2' (numpy.float64), representing long-term
variation.
"""
SDSD = np.std(np.diff(RRints))
SDRR = np.std(RRints)
SD1 = (1 / np.sqrt(2)) * SDSD #measures the width of poincare cloud
SD2 = np.sqrt((2 * SDRR ** 2) - (0.5 * SDSD ** 2)) #measures the length of the poincare cloud
return {'SD1': SD1, 'SD2': SD2}
def hraMethod(RRints):
"""
Perform analysis to quantify heart rate assymmetry (HRA).
Input :
- RRints : [list] of RR intervals
Output :
- C_DOWN, C_UP : {dict} with keys 'C_DOWN' (numpy.float64) and
'C_UP' (numpy.float64)
"""
ax1 = RRints[:-1]
ax2 = RRints[1:]
SD1I = np.sqrt((1 / len(ax1)) * (np.sum((ax1 - ax2) ** 2) / 2))
ax1ax2 = (ax1 - ax2) / np.sqrt(2)
indices_up = np.where(ax1ax2 > 0)
indices_down = np.where(ax1ax2 < 0)
SD1_UP = np.sqrt(np.sum(ax1ax2[indices_up] ** 2) / len(ax1))
SD1_DOWN = np.sqrt(np.sum(ax1ax2[indices_down] ** 2) / len(ax1))
C_UP = SD1_UP ** 2 / SD1I ** 2 #for decelerations
C_DOWN = SD1_DOWN ** 2 / SD1I ** 2 #for accelerations
return {'C_UP': C_UP, 'C_DOWN': C_DOWN}
def correlationCoef(RRints):
"""
Computes interbeat autocorrelation coefficient
Input :
- RRints: [list] of RR intervals
Output :
- r_rr : [numpy.float64] interbeat autocorrelation coefficient
"""
ax1 = RRints[:-1]
ax2 = RRints[1:]
mu_rr = np.mean(RRints)
r_rr = np.mean((ax1 - mu_rr) * (ax2 - mu_rr)) / (np.sqrt(np.mean((ax1 - mu_rr) ** 2) * np.mean((ax2 - mu_rr) ** 2)))
return r_rr
def plotRRintHist(RRints):
"""
Histogram distribution of poincare points projected onto the x-axis
Input :
- RRints: [list] of RR intervals
Output :
- RR interval histogram plot
"""
plt.hist(RRints, bins = 'auto')
plt.xlabel('RR Interval')
plt.ylabel('Number of RR Intervals')
plt.title('RR Interval Histogram')
plt.show()
def plotWidthHist(RRints):
"""
Histogram distribution of poincare points projected along the direction of
line-of-identity, or along the line perpendicular to the line-of-identity.
Input :
- RRints: [list] of RR intervals
Output :
- 'Width', or delta-RR interval, histogram plot
"""
ax1 = RRints[:-1]
ax2 = RRints[1:]
x1 = (np.cos(np.pi / 4) * ax1) - (np.sin(np.pi / 4) * ax2)
plt.hist(x1, bins = 'auto')
plt.title('Width (Delta-RR Interval) Histogram')
plt.show()
def plotLengthHist(RRints):
"""
Histogram distribution of poincare points projected along the line-of-identty.
Input :
- RRints: [list] of RR intervals
Output :
- 'Length' histogram plot
"""
ax1 = RRints[:-1]
ax2 = RRints[1:]
x2 = (np.sin(np.pi / 4) * ax1) + (np.cos(np.pi / 4) * ax2)
plt.hist(x2, bins = 'auto')
plt.title('Length Histogram')
plt.show()