analysis

Functions that handle computation of heart rate (HR) and heart rate variability (HRV) measures.

heartpy.analysis.calc_rr(peaklist, sample_rate, working_data={})[source]

calculates peak-peak intervals

Function that calculates the peak-peak data required for further analysis. Stores results in the working_data{} dict.

Parameters:
  • peaklist (1d list or array) – list or array containing detected peak positions
  • sample_rate (int or float) – the sample rate with which the heart rate signal is collected
  • working_data (dict) – dictionary object that contains all heartpy’s working data (temp) objects. will be created if not passed to function
Returns:

working_data – working_data dictionary object containing all of heartpy’s temp objects

Return type:

dict

Examples

Let’s assume we detected peaks at these positions in the signal:

>>> peaklist = [200, 280, 405, 501, 615]

It is then easy to call calc_rr to compute what we need:

>>> wd = calc_rr(peaklist, sample_rate = 100.0)
>>> wd['RR_list']
array([ 800., 1250.,  960., 1140.])
>>> wd['RR_diff']
array([450., 290., 180.])
>>> wd['RR_sqdiff']
array([202500.,  84100.,  32400.])

Note that the list of peak-peak intervals is of length len(peaks) - 1 the length of the differences is of length len(peaks) - 2

heartpy.analysis.update_rr(working_data={})[source]

updates differences between adjacent peak-peak distances

Function that updates RR differences and RR squared differences based on corrected RR list

Parameters:working_data (dict) – dictionary object that contains all heartpy’s working data (temp) objects will be created if not passed to function
Returns:out – working_data dictionary object containing all of heartpy’s temp objects
Return type:dict

Examples

Let’s assume we detected peaks at these positions in the signal:

>>> peaklist = [200, 280, 405, 410, 501, 615]

And we subsequently ran further analysis:

>>> wd = calc_rr(peaklist, sample_rate = 100.0)

The peak at position 410 is likely an incorrect detection and will be marked as such by other heartpy functions. This is indicated by an array ‘binary_peaklist’ in working_data. Binary peaklist is of the same length as peaklist, and is formatted as a mask:

For now let’s set it manually, normally this is done by the check_peaks() function from HeartPy’s peakdetection module.

>>> wd['binary_peaklist'] = [1, 1, 1, 0, 1, 1]

Rejected peaks are marked with a zero and accepted with a 1.

By now running update_rr(), heartpy will update all associated measures and will only compute peak-peak intervals between two accepted peaks.

>>> wd = update_rr(wd)

This will have generated a corrected RR_list object in the dictionary:

>>> wd['RR_list_cor']
array([ 800., 1250., 1140.])

As well as updated the lists RR_diff (differences between adjacent peak-peak intervals) and RR_sqdiff (squared differences between adjacent peak-peak intervals).

heartpy.analysis.calc_rr_segment(rr_source, b_peaklist)[source]

calculates peak-peak differences for segmentwise processing

Function that calculates rr-measures when analysing segmentwise in the ‘fast’ mode.

Parameters:
  • rr_source (1d list or array) – list or array containing peak-peak intervals.
  • b_peaklist (1d list or array) – list or array containing mask for peaklist.
Returns:

  • rr_list (array) – array containing peak-peak intervals.
  • rr_diff (array) – array containing differences between adjacent peak-peak intervals
  • rr_sqdiff (array) – array containing squared differences between adjacent peak-peak intervals

Examples

The function works in the same way as update_rr, except it returns three separate objects. It’s used by process_segmentwise. Revert to doc on update_rr for more information.

>>> rr, rrd, rrsd = calc_rr_segment(rr_source = [ 800., 1250.,   50.,  910., 1140., 1002., 1142.],
... b_peaklist = [1, 1, 1, 0, 1, 1, 1, 1])
>>> print(rr)
[800.0, 1250.0, 1140.0, 1002.0, 1142.0]
>>> print(rrd)
[450.0 138.0 140.0]
>>> print(rrsd)
[202500.  19044.  19600.]
heartpy.analysis.clean_rr_intervals(working_data, method='quotient-filter')[source]

detects and rejects outliers in peak-peak intervals

Function that detects and rejects outliers in the peak-peak intervals. It updates the RR_list_cor in the working data dict

Parameters:
  • working_data (dict) – dictionary object that contains all heartpy’s working data (temp) objects. Needs to contain RR_list_cor, meaning one analysis cycle has already completed.
  • method (str) – which method to use for outlier rejection, included are: - ‘quotient-filter’, based on the work in “Piskorki, J., Guzik, P. (2005), Filtering Poincare plots”, - ‘iqr’, which uses the inter-quartile range, - ‘z-score’, which uses the modified z-score method. default : quotient-filter
Returns:

working_data – dictionary object that contains all heartpy’s working data (temp) objects. will be created if not passed to function

Return type:

dict

Examples

Let’s load some data

>>> import heartpy as hp
>>> data, timer = hp.load_exampledata(1)
>>> sample_rate = hp.get_samplerate_mstimer(timer)

Run at least one analysis cycle first so that the dicts are populated

>>> wd, m = hp.process(data, sample_rate)
>>> wd = clean_rr_intervals(working_data = wd)
>>> ['%.3f' %x for x in wd['RR_list_cor'][0:5]]
['897.470', '811.997', '829.091', '777.807', '803.449']

You can also specify the outlier rejection method to be used, for example using the z-score method:

>>> wd = clean_rr_intervals(working_data = wd, method = 'z-score')
>>> ['%.3f' %x for x in wd['RR_list_cor'][0:5]]
['897.470', '811.997', '829.091', '777.807', '803.449']

Or the inter-quartile range (iqr) based method:

>>> wd = clean_rr_intervals(working_data = wd, method = 'iqr')
>>> ['%.3f' %x for x in wd['RR_list_cor'][0:5]]
['897.470', '811.997', '829.091', '965.849', '803.449']
heartpy.analysis.calc_ts_measures(rr_list, rr_diff, rr_sqdiff, measures={}, working_data={})[source]

calculates standard time-series measurements.

Function that calculates the time-series measurements for HeartPy.

Parameters:
  • rr_list (1d list or array) – list or array containing peak-peak intervals
  • rr_diff (1d list or array) – list or array containing differences between adjacent peak-peak intervals
  • rr_sqdiff (1d list or array) – squared rr_diff
  • measures (dict) – dictionary object used by heartpy to store computed measures. Will be created if not passed to function.
  • working_data (dict) – dictionary object that contains all heartpy’s working data (temp) objects. will be created if not passed to function
Returns:

  • working_data (dict) – dictionary object that contains all heartpy’s working data (temp) objects.
  • measures (dict) – dictionary object used by heartpy to store computed measures.

Examples

Normally this function is called during the process pipeline of HeartPy. It can of course also be used separately.

Assuming we have the following peak-peak distances:

>>> import numpy as np
>>> rr_list = [1020.0, 990.0, 960.0, 1000.0, 1050.0, 1090.0, 990.0, 900.0, 900.0, 950.0, 1080.0]

we can then compute the other two required lists by hand for now:

>>> rr_diff = np.diff(rr_list)
>>> rr_sqdiff = np.power(rr_diff, 2)
>>> wd, m = calc_ts_measures(rr_list, rr_diff, rr_sqdiff)

All output measures are then accessible from the measures object through their respective keys:

>>> print('%.3f' %m['bpm'])
60.384
>>> print('%.3f' %m['rmssd'])
67.082
heartpy.analysis.calc_fd_measures(method='welch', welch_wsize=240, square_spectrum=False, measures={}, working_data={}, degree_smoothing_spline=3)[source]

calculates the frequency-domain measurements.

Function that calculates the frequency-domain measurements for HeartPy.

method : str
method used to compute the spectrogram of the heart rate. available methods: fft, periodogram, and welch default : welch
welch_wsize : float

Size of window (in sec) when welch method used to compute the spectrogram. This choice is based on a trade-off btw temporal res and freq res of the resulting spectrum 60 sec may seem reasonable, but this would greatly limit frequency resolution!

1/60 s = 0.017 Hz, so you would only have 2 points in the VLF band

Therefore, the default is 4 min (9 points in the VLF band) default : 240

square_spectrum : bool
whether to square the power spectrum returned. default : False
measures : dict
dictionary object used by heartpy to store computed measures. Will be created if not passed to function.
working_data : dict
dictionary object that contains all heartpy’s working data (temp) objects. will be created if not passed to function
degree_smoothing_spline : int, optional
Degree of the smoothing spline for UnivariateSpline function in fitpack2. Must be 1 <= k <= 5. Default is k = 3, a cubic spline.
working_data : dict
dictionary object that contains all heartpy’s working data (temp) objects.
measures : dict
dictionary object used by heartpy to store computed measures.

Normally this function is called during the process pipeline of HeartPy. It can of course also be used separately.

Let’s load an example and get a list of peak-peak intervals

>>> import heartpy as hp
>>> data, timer = hp.load_exampledata(2)
>>> sample_rate = hp.get_samplerate_datetime(timer, timeformat='%Y-%m-%d %H:%M:%S.%f')
>>> wd, m = hp.process(data, sample_rate)

wd now contains a list of peak-peak intervals that has been cleaned of outliers (‘RR_list_cor’). Calling the function then is easy

>>> wd, m = calc_fd_measures(method = 'periodogram', measures = m, working_data = wd)
>>> print('%.3f' %m['lf/hf'])
5.198

Available methods are ‘fft’, ‘welch’ and ‘periodogram’. To set another method, do:

>>> wd, m = calc_fd_measures(method = 'fft', measures = m, working_data = wd)
>>> print('%.3f' %m['lf/hf'])
5.198

If there are no valid peak-peak intervals specified, returned measures are NaN: >>> wd[‘RR_list_cor’] = [] >>> wd, m = calc_fd_measures(working_data = wd) >>> np.isnan(m[‘lf/hf’]) True

If there are rr-intervals but not enough to reliably compute frequency measures, a warning is raised:

RuntimeWarning: Short signal. ———Warning:——— too few peak-peak intervals for (reliable) frequency domain measure computation, frequency output measures are still computed but treat them with caution!

HF is usually computed over a minimum of 1 minute of good signal. LF is usually computed over a minimum of 2 minutes of good signal. VLF is usually computed over a minimum of 5 minutes of good signal. The LF/HF ratio is usually computed over minimum 24 hours, although an absolute minimum of 5 min has also been suggested.

For more info see:

Shaffer, F., Ginsberg, J.P. (2017).

An Overview of Heart Rate Variability Metrics and Norms.

Task Force of Pacing and Electrophysiology (1996), Heart Rate Variability in: European Heart Journal, vol.17, issue 3, pp354-381

heartpy.analysis.calc_breathing(rrlist, method='welch', filter_breathing=True, bw_cutoff=[0.1, 0.4], measures={}, working_data={})[source]

estimates breathing rate

Function that estimates breathing rate from heart rate signal. Upsamples the list of detected rr_intervals by interpolation then tries to extract breathing peaks in the signal.

Parameters:
  • rr_list (1d list or array) – list or array containing peak-peak intervals
  • method (str) – method to use to get the spectrogram, must be ‘fft’ or ‘welch’ default : fft
  • filter_breathing (bool) – whether to filter the breathing signal derived from the peak-peak intervals default : True
  • bw_cutoff (list or tuple) – breathing frequency range expected default : [0.1, 0.4], meaning between 6 and 24 breaths per minute
  • measures (dict) – dictionary object used by heartpy to store computed measures. Will be created if not passed to function.
  • working_data (dict) – dictionary object that contains all heartpy’s working data (temp) objects. will be created if not passed to function
Returns:

measures – dictionary object used by heartpy to store computed measures.

Return type:

dict

Examples

Normally this function is called during the process pipeline of HeartPy. It can of course also be used separately.

Let’s load an example and get a list of peak-peak intervals

>>> import heartpy as hp
>>> data, _ = hp.load_exampledata(0)
>>> wd, m = hp.process(data, 100.0)

Breathing is then computed with the function

>>> m, wd = calc_breathing(wd['RR_list_cor'], measures = m, working_data = wd)
>>> round(m['breathingrate'], 3)
0.171

There we have it, .17Hz, or about one breathing cycle in 6.25 seconds.