Skip to content

Commit f60d6b9

Browse files
authored
Merge pull request #44 from smoia/feat/hrv
Fix naming of metrics, clarify PULSE RATE vs HEART RATE
2 parents 6783c28 + 1785434 commit f60d6b9

File tree

2 files changed

+83
-5
lines changed

2 files changed

+83
-5
lines changed

phys2denoise/metrics/cardiac.py

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ def _cardiac_metrics(card, peaks, samplerate, metric, window=6, central_measure=
1515
Computes the average heart beats interval (HBI)
1616
or the average heart rate variability (HRV) in a sliding window.
1717
18+
We refer to HEART RATE (variability), however note that if using a PPG
19+
recorded signal, it is more accurate to talk about PULSE RATE (variability).
20+
See [3]_ for the differences and similarities between the two measures.
21+
1822
Parameters
1923
----------
2024
card : list or 1D numpy.ndarray
@@ -23,14 +27,15 @@ def _cardiac_metrics(card, peaks, samplerate, metric, window=6, central_measure=
2327
array of peak indexes for card.
2428
samplerate : float
2529
Sampling rate for card, in Hertz.
26-
metrics : "hbi", "hrv", string
30+
metrics : "hbi", "hr", "hrv", string
2731
Cardiac metric(s) to calculate.
2832
window : float, optional
2933
Size of the sliding window, in seconds.
3034
Default is 6.
31-
central_measure : "mean","average", "avg", "median", "mdn", string, optional
35+
central_measure : "mean","average", "avg", "median", "mdn", "stdev", "std", string, optional
3236
Measure of the center used (mean or median).
3337
Default is "mean".
38+
3439
Returns
3540
-------
3641
card_met : 2D numpy.ndarray
@@ -62,6 +67,9 @@ def _cardiac_metrics(card, peaks, samplerate, metric, window=6, central_measure=
6267
vol. 213, pp. 116707, 2020.
6368
.. [2] C. Chang, J. P. Cunningham, & G. H. Glover, "Influence of heart rate on the
6469
BOLD signal: The cardiac response function", NeuroImage, vol. 44, 2009
70+
.. [3] N. Pinheiro et al., "Can PPG be used for HRV analysis?," 2016 38th
71+
Annual International Conference of the IEEE Engineering in Medicine and
72+
Biology Society (EMBC), doi: 10.1109/EMBC.2016.7591347.
6573
"""
6674
# Convert window to samples, but halves it.
6775
halfwindow_samples = int(round(window * samplerate / 2))
@@ -70,6 +78,8 @@ def _cardiac_metrics(card, peaks, samplerate, metric, window=6, central_measure=
7078
central_measure_operator = np.mean
7179
elif central_measure in ["median", "mdn"]:
7280
central_measure_operator = np.median
81+
elif central_measure in ["stdev", "std"]:
82+
central_measure_operator = np.std
7383
else:
7484
raise NotImplementedError(
7585
f" {central_measure} is not a supported metric of centrality."
@@ -86,7 +96,10 @@ def _cardiac_metrics(card, peaks, samplerate, metric, window=6, central_measure=
8696
)
8797
if metric == "hbi":
8898
card_met[n] = central_measure_operator(diff) if diff.size > 0 else 0
99+
elif metric == "hr":
100+
card_met[n] = central_measure_operator(1 / diff) if diff.size > 0 else 0
89101
elif metric == "hrv":
102+
central_measure_operator = np.std
90103
card_met[n] = central_measure_operator(1 / diff) if diff.size > 0 else 0
91104
else:
92105
raise NotImplementedError(
@@ -102,9 +115,13 @@ def _cardiac_metrics(card, peaks, samplerate, metric, window=6, central_measure=
102115

103116

104117
@due.dcite(references.CHANG_CUNNINGHAM_GLOVER_2009)
105-
def heart_rate_variability(card, peaks, samplerate, window=6, central_measure="mean"):
118+
def heart_rate(card, peaks, samplerate, window=6, central_measure="mean"):
106119
"""
107-
Compute average heart rate variability (HRV) in a sliding window.
120+
Compute average heart rate (HR) in a sliding window.
121+
122+
We call this function HEART RATE, however note that if using a PPG
123+
recorded signal, it is more accurate to talk about PULSE RATE.
124+
See [2]_ for the differences and similarities between the two measures.
108125
109126
Parameters
110127
----------
@@ -130,7 +147,7 @@ def heart_rate_variability(card, peaks, samplerate, window=6, central_measure="m
130147
131148
Notes
132149
-----
133-
Heart rate variability (HRV) is taken from [1]_, and computed as the amounts of
150+
Heart rate (HR) is taken from [1]_, and computed as the amounts of
134151
beats per minute.
135152
However, operationally, it is the average of the inverse of the time interval
136153
between two heart beats.
@@ -146,12 +163,71 @@ def heart_rate_variability(card, peaks, samplerate, window=6, central_measure="m
146163
----------
147164
.. [1] C. Chang, J. P. Cunningham, & G. H. Glover, "Influence of heart rate on the
148165
BOLD signal: The cardiac response function", NeuroImage, vol. 44, 2009
166+
.. [2] N. Pinheiro et al., "Can PPG be used for HRV analysis?," 2016 38th
167+
Annual International Conference of the IEEE Engineering in Medicine and
168+
Biology Society (EMBC), doi: 10.1109/EMBC.2016.7591347.
149169
"""
150170
return _cardiac_metrics(
151171
card, peaks, samplerate, metric="hrv", window=6, central_measure="mean"
152172
)
153173

154174

175+
@due.dcite(references.PINHERO_ET_AL_2016)
176+
def heart_rate_variability(card, peaks, samplerate, window=6, central_measure="mean"):
177+
"""
178+
Compute average heart rate variability (HRV) in a sliding window.
179+
180+
We call this function HEART RATE variability, however note that if using a PPG
181+
recorded signal, it is more accurate to talk about PULSE RATE variability.
182+
See [1]_ for the differences and similarities between the two measures.
183+
184+
Parameters
185+
----------
186+
card : list or 1D numpy.ndarray
187+
Timeseries of recorded cardiac signal
188+
peaks : list or 1D numpy.ndarray
189+
array of peak indexes for card.
190+
samplerate : float
191+
Sampling rate for card, in Hertz.
192+
window : float, optional
193+
Size of the sliding window, in seconds.
194+
Default is 6.
195+
central_measure : "mean","average", "avg", "median", "mdn", string, optional
196+
Measure of the center used (mean or median).
197+
Default is "mean".
198+
Returns
199+
-------
200+
card_met : 2D numpy.ndarray
201+
Heart Beats Interval or Heart Rate Variability timeseries.
202+
The first column is the raw metric, in Hertz.
203+
The second column is the metric convolved with the CRF, cut to the length
204+
of the raw metric.
205+
206+
Notes
207+
-----
208+
Heart rate variability (HRV) is taken from [1]_, and computed as the amounts of
209+
beats per minute.
210+
However, operationally, it is the average of the inverse of the time interval
211+
between two heart beats.
212+
This metric should be convolved with the cardiac response function
213+
before being included in a GLM.
214+
215+
IMPORTANT : The unit of measure has a meaning, since they it's based on Hertz.
216+
Hence, zscoring might remove important quantifiable information.
217+
218+
See `_cardiac_metrics` for full implementation.
219+
220+
References
221+
----------
222+
.. [1] N. Pinheiro et al., "Can PPG be used for HRV analysis?," 2016 38th
223+
Annual International Conference of the IEEE Engineering in Medicine and
224+
Biology Society (EMBC), doi: 10.1109/EMBC.2016.7591347.
225+
"""
226+
return _cardiac_metrics(
227+
card, peaks, samplerate, metric="hrv", window=6, central_measure="std"
228+
)
229+
230+
155231
@due.dcite(references.CHEN_2020)
156232
def heart_beat_interval(card, peaks, samplerate, window=6, central_measure="mean"):
157233
"""

phys2denoise/references.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
GLOVER_2000 = Doi("10.1002/1522-2594(200007)44:1<162::AID-MRM23>3.0.CO;2-E")
1313

14+
PINHERO_ET_AL_2016 = Doi("10.1109/EMBC.2016.7591347")
15+
1416
POWER_2018 = Doi("10.1073/pnas.1720985115")
1517

1618
POWER_2020 = Doi("10.1016/j.neuroimage.2019.116234")

0 commit comments

Comments
 (0)