Class: PostRunner::HRV_Analyzer
- Inherits:
-
Object
- Object
- PostRunner::HRV_Analyzer
- Defined in:
- lib/postrunner/HRV_Analyzer.rb
Overview
This class analyzes the heart rate variablity based on the R-R intervals in the given FIT file. It can compute RMSSD and a HRV score if the data quality is good enough.
Constant Summary collapse
- LN_RMSSD_MIN =
According to Nunan et. al. 2010 (www.qeeg.co.uk/HRV/NUNAN-2010-A%20Quantitative%20Systematic%20Review%20of%20Normal%20Values%20for.pdf) rMSSD (ms) are expected to be in the rage of 19 to 75 in healthy, adult humans. Typical ln(rMSSD) (ms) values for healthy, adult humans are between 2.94 and 4.32. We use a slighly broader interval. We’ll add a bit of padding for our limits here.
2.9
- LN_RMSSD_MAX =
4.4
Instance Attribute Summary collapse
-
#duration ⇒ Object
readonly
Returns the value of attribute duration.
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
-
#hrv ⇒ Object
readonly
Returns the value of attribute hrv.
-
#timestamps ⇒ Object
readonly
Returns the value of attribute timestamps.
Instance Method Summary collapse
- #data_quality ⇒ Object
-
#has_hrv_data? ⇒ Boolean
The method can be used to check if we have valid HRV data.
-
#hrv_score(start_time = 0.0, duration = nil) ⇒ Object
The ln_rmssd values are hard to interpret.
-
#initialize(arg) ⇒ HRV_Analyzer
constructor
Create a new HRV_Analyzer object.
-
#ln_rmssd(start_time = 0.0, duration = nil) ⇒ Object
The natural logarithm of rMSSD.
-
#rmssd(start_time = 0.0, duration = nil) ⇒ Object
Compute the root mean square of successive differences.
-
#total_duration ⇒ Object
Return the total duration of all measured intervals in seconds.
Constructor Details
#initialize(arg) ⇒ HRV_Analyzer
Create a new HRV_Analyzer object.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 35 def initialize(arg) if arg.is_a?(Array) rr_intervals = arg else activity = arg # Gather the RR interval list from the activity. Note that HRV data # still gets recorded after the activity has been stoped until the # activity gets saved. # Each Fit4Ruby::HRV object has an Array called 'time' that contains up # to 5 R-R interval durations. If less than 5 values are present the # remaining are filled with nil entries. rr_intervals = activity.fit_activity.hrv.map do |hrv| hrv.time.compact end.flatten end #$stderr.puts rr_intervals.inspect cleanup_rr_intervals(rr_intervals) end |
Instance Attribute Details
#duration ⇒ Object (readonly)
Returns the value of attribute duration.
22 23 24 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 22 def duration @duration end |
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
22 23 24 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 22 def errors @errors end |
#hrv ⇒ Object (readonly)
Returns the value of attribute hrv.
22 23 24 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 22 def hrv @hrv end |
#timestamps ⇒ Object (readonly)
Returns the value of attribute timestamps.
22 23 24 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 22 def @timestamps end |
Instance Method Details
#data_quality ⇒ Object
62 63 64 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 62 def data_quality (@hrv.size - @errors).to_f / @hrv.size * 100.0 end |
#has_hrv_data? ⇒ Boolean
The method can be used to check if we have valid HRV data. The FIT file must have HRV data and the measurement duration must be at least 30 seconds.
58 59 60 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 58 def has_hrv_data? @hrv && !@hrv.empty? && total_duration > 30.0 end |
#hrv_score(start_time = 0.0, duration = nil) ⇒ Object
The ln_rmssd values are hard to interpret. Since we know the expected range we’ll transform it into a value in the range 0 - 100. If the HRV is measured early in the morning while standing upright and with a regular 3s in/3s out breathing pattern the HRV Score is a performance indicator. The higher it is, the better the performance condition.
125 126 127 128 129 130 131 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 125 def hrv_score(start_time = 0.0, duration = nil) ssd = ln_rmssd(start_time, duration) ssd = LN_RMSSD_MIN if ssd < LN_RMSSD_MIN ssd = LN_RMSSD_MAX if ssd > LN_RMSSD_MAX (ssd - LN_RMSSD_MIN) * (100.0 / (LN_RMSSD_MAX - LN_RMSSD_MIN)) end |
#ln_rmssd(start_time = 0.0, duration = nil) ⇒ Object
The natural logarithm of rMSSD.
116 117 118 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 116 def ln_rmssd(start_time = 0.0, duration = nil) Math.log(rmssd(start_time, duration)) end |
#rmssd(start_time = 0.0, duration = nil) ⇒ Object
Compute the root mean square of successive differences.
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 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 77 def rmssd(start_time = 0.0, duration = nil) # Find the start index based on the requested interval start time. start_idx = 0 @timestamps.each do |ts| break if ts >= start_time start_idx += 1 end # Find the end index based on the requested interval duration. if duration end_time = start_time + duration end_idx = start_idx while end_idx < (@timestamps.length - 1) && @timestamps[end_idx] < end_time end_idx += 1 end else end_idx = -1 end sum = 0.0 cnt = 0 @hrv[start_idx..end_idx].each do |i| if i # Input values are in seconds, but rmssd is usually computed from # milisecond values. sum += (i * 1000) ** 2.0 cnt += 1 end end Math.sqrt(sum / cnt) end |
#total_duration ⇒ Object
Return the total duration of all measured intervals in seconds.
67 68 69 |
# File 'lib/postrunner/HRV_Analyzer.rb', line 67 def total_duration @timestamps[-1] end |