Skip to main content

A python package for heart rate variability analysis

# Pythonic package for Heart Rate Variability Analysis

version number: 0.2.3 author: Rhenan Bartels

## Overview

hrv is a simple Python module that brings the most widely used techniques to work with RRi series and Heart Rate Variability (HRV) analyses without losing the Power and Flexibility of a native Python object and numpy arrays.

## Installation / Usage

To install use pip:

$pip install hrv  Or clone the repo: $ git clone https://github.com/rhenanbartels/hrv.git
\$ python setup.py install


## Create an RRi instance

Once you create an RRi object you will have the power of a native Python iterable object. This means, that you can loop through it using a for loop, get a just a part of the series using native slicing and much more. Let us try it:

from hrv.rri import RRi

rri_list = [800, 810, 815, 750, 753, 905]
rri = RRi(rri_list)

print(rri)
RRi array([800., 810., 815., 750., 753., 905.])


#### Slicing

print(rri[0])
800.0

print(type(rri[0]))
numpy.float64

print(rri[::2])
RRi array([800., 815., 753.])


#### Logical Indexing

from hrv.rri import RRi

rri = RRi([800, 810, 815, 750, 753, 905])
rri_ge = rri[rri >= 800]

rri_ge
RRi array([800., 810., 815., 905.])


#### Loop

for rri_value in rri:
print(rri_value)

800.0
810.0
815.0
750.0
753.0
905.0


#### Note:

When time information is not provided, time array will be created using the cumulative sum of successive RRi. After cumulative sum, the time array is subtracted from the value at t[0] to make it start from 0s

#### RRi object and time information

from hrv.rri import RRi

rri_list = [800, 810, 815, 750, 753, 905]
rri = RRi(rri_list)

print(rri.time)
array([0.   , 0.81 , 1.625, 2.375, 3.128, 4.033]) # Cumsum of rri values minus t[0]

rri = RRi(rri_list, time=[0, 1, 2, 3, 4, 5])
print(rri.time)
[0. 1. 2. 3. 4. 5.]


#### Note:

Some validations are made in the time list/array provided to the RRi class, for instance:

• RRi and time list/array must have the same length;
• Time list/array can not have negative values;
• Time list/array must be monotonic increasing.

### Basic math operations

With RRi objects you can make math operatins just like a numpy array:

rri
RRi array([800., 810., 815., 750., 753., 905.])

rri * 10
RRi array([8000., 8100., 8150., 7500., 7530., 9050.])

rri + 200
RRi array([1000., 1010., 1015.,  950.,  953., 1105.])


### Works with Numpy functions

import numpy as np

rri = RRi([800, 810, 815, 750, 753, 905])

sum_rri = np.sum(rri)
print(sum_rri)
4833.0

mean_rri = np.mean(rri)
print(mean_rri)
805.5

std_rri = np.std(rri)
print(std_rri)
51.44171459039833


## Read RRi files

### From text (.txt) file

Text files contains a single column with all RRi values. Example of RRi text file

800
810
815
750

from hrv.io import read_from_text

rri = read_from_text('path/to/file.txt')

print(rri)
RRi array([800., 810., 815., 750.])


### From Polar ® (.hrm) file

The .hrm files contain the RRi acquired with Polar ®

A complete guide for .hrm files can be found here.

from hrv.io import read_from_hrm

rri = read_from_hrm('path/to/file.hrm')

print(rri)
RRi array([800., 810., 815., 750.])


### From comma separated (.csv) file file

Example of csv file:

800,
810,
815,
750,

from hrv.io import read_from_csv

rri = read_from_csv('path/to/file.csv')

print(rri)
RRi array([800., 810., 815., 750.])


#### Note:

When using read_from_csv you can also provide a column containing time information. Let's check it.

800,1
810,2
815,3
750,4

rri = read_from_csv('path/to/file.csv', time_col_index=1)

print(rri)
RRi array([800., 810., 815., 750.])

print(rri.time)
array([0., 1., 2., 3., 4.])


### RRi statistics

The RRi object implements some basic statistics information about its values:

• mean
• median
• standard deviation
• variance
• minimum
• maximum
• amplitude

Some examples:

from hrv.rri import RRi

rri = RRi([800, 810, 815, 750, 753, 905])

# mean
rri.mean()
805.5

# median
rri.median()
805.0


You can also have a complete overview of its statistical charactheristic

desc = rri.describe()
desc

----------------------------------------
rri          hr
----------------------------------------
min             750.00       66.30
max             905.00       80.00
mean            805.50       74.78
var            2646.25       20.85
std              51.44        4.57
median          805.00       74.54
amplitude       155.00       13.70

print(desc['std'])
{'rri': 51.44171459039833, 'hr': 4.5662272355549725}


## RRi Basic Information

rri = RRi([800, 810, 815, 750, 753, 905])
rri.info()

N Points: 6
Duration: 4.03s
Interpolated: False
Detrended: False
Memory Usage: 0.05Kb


## RRi Visualization

The RRi class brings a very easy way to visualize your series:

### RRi Series

from hrv.io import read_from_text

rri = read_from_text('path/to/file.txt')
fig, ax = rri.plot(color='k')


### RRi histogram and Heart Rate Histogram

rri.hist()

rri.hist(hr=True)


## Time Slicing

It is also possible to slice RRi series with time range information (in seconds).

In the following example, we are taking a slice that starts at 100s  and ends at 200s.

from hrv.io import read_from_text

rri = read_from_text('path/to/file.txt')
rri_range = rri.time_range(start=100, end=200)

fig, ax = rri_range.plot(marker='.')


Time offset can be reset from the RRi series range:

rri_range.reset_time(inplace=True)


## Filters

### Moving Average

from hrv.filters import moving_average
filt_rri = moving_average(rri, order=3)

fig, ax = rri.plot()
filt_rri.plot(ax=ax)


### Moving Median

from hrv.filters import moving_median
filt_rri = moving_median(rri, order=3)

fig, ax = rri.plot()
filt_rri.plot(ax=ax)


### Quotient

Read more.

from hrv.filters import quotient
filt_rri = quotient(rri)

fig, ax = rri.plot()
filt_rri.plot(ax=ax)


## Time Domain Analysis

from hrv.classical import time_domain
from hrv.io import read_from_text

rri = read_from_text('path/to/file.txt')
results = time_domain(rri)
print(results)

{'mhr': 66.528130159638053,
'mrri': 912.50302419354841,
'nn50': 337,
'pnn50': 33.971774193548384,
'rmssd': 72.849900286450023,
'sdnn': 96.990569261440797}


## Frequency Domain Analysis

from hrv.classical import frequency_domain
from hrv.io import read_from_text

rri = read_from_text('path/to/file.txt')
results = frequency_domain(
rri=rri,
fs=4.0,
method='welch',
interp_method='cubic',
detrend='linear'
)
print(results)

{'hf': 1874.6342520920668,
'hfnu': 27.692517001462079,
'lf': 4894.8271587038234,
'lf_hf': 2.6110838171452708,
'lfnu': 72.307482998537921,
'total_power': 7396.0879278950533,
'vlf': 626.62651709916258}


## Non-linear Analysis

from hrv.classical import non_linear
from hrv.io import read_from_text

rri = read_from_text('path/to/file.txt')
results = non_linear(rri)
print(results)

{'sd1': 51.538501037146382,
'sd2': 127.11460955437322}


## Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

### Source Distribution

hrv-0.2.3.tar.gz (13.2 kB view hashes)

Uploaded source

### Built Distribution

hrv-0.2.3-py2.py3-none-any.whl (11.9 kB view hashes)

Uploaded py2 py3