RSA tutorial

Respiratory sinus arrhythmia (RSA) can be analysed with the physio toolbox with an innovative method to extract parameters of the heart rate dynamic on a respiratory cycle-to-cycle basis.

The method consists of:
  • detect respiratory cycle

  • detect ECG peaks

  • compute instanteneous heart rate in BPM

  • extract parameters in this heart timeseries for each respiratory cycle

  • use cyclic deformation of this heart rate signal and stack all cycles.

This method has 2 important advantages:
  • the dynamic of th RSA can be finely analysed

  • features of RSA can be analysed using respiratory cycle-by-cycle

import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path
from pprint import pprint

import physio

Read data

raw_resp = np.load('resp1.npy')
raw_ecg = np.load('ecg1.npy')
srate = 1000.
times = np.arange(raw_resp.size) / srate

Get respiratory cycle and ECG peaks

resp, resp_cycles = physio.compute_respiration(raw_resp, srate, parameter_preset='human_airflow')
ecg, ecg_peaks = physio.compute_ecg(raw_ecg, srate, parameter_preset='human_ecg')

Compute RSA

This is done with one unique function that returns:

  • One dataframe with all RSA features

  • The cyclically deformed cardiac rate

points_per_cycle = 50

rsa_cycles, cyclic_cardiac_rate = physio.compute_rsa(
    resp_cycles,
     ecg_peaks,
     srate=10.,
     two_segment=True,
     points_per_cycle=points_per_cycle,
)

some_features = ['rising_amplitude', 'decay_amplitude', 'rising_duration', 'decay_duration', 'rising_slope', 'decay_slope']
print(rsa_cycles[some_features].head(9))
   rising_amplitude  decay_amplitude  ...  rising_slope  decay_slope
0               NaN        50.193323  ...           NaN    16.731108
1         43.168103        38.499518  ...      6.860792    15.399807
2         35.376571        22.633509  ...      6.346712     8.705196
3         23.867865        47.549776  ...      4.216937    22.642750
4         45.491712        45.570177  ...      5.631556    21.700084
5         47.775766        46.566829  ...      5.998966    22.174681
6         49.811333        42.775593  ...      6.568816    12.962301
7         39.605566        38.517421  ...      5.136243    14.814393
8         40.432051        46.146617  ...      4.757831    24.287693

[9 rows x 6 columns]

Plot RSA cycle dynamic

Here we also plot the average ratio of inspiration duration to cycle duration

# this is the average ratio
inspi_expi_ratio = np.mean(resp_cycles['inspi_duration'] / resp_cycles['cycle_duration'])

one_cycle = np.arange(points_per_cycle) / points_per_cycle
fig, ax = plt.subplots()
ax.plot(one_cycle, cyclic_cardiac_rate.T, color='k', alpha=.3)
ax.plot(one_cycle, np.mean(cyclic_cardiac_rate, axis=0), color='darkorange', lw=3)
ax.axvspan(0, inspi_expi_ratio, color='g', alpha=0.3)
ax.axvspan(inspi_expi_ratio, 1, color='r', alpha=0.3)
ax.set_xlabel('One respiratory cycle')
ax.set_ylabel('Heart rate [bpm]')
ax.set_xlim(0, 1)
ax.text(0.2, 60, 'inhalation', ha='center', color='g')
ax.text(0.85, 60, 'exhalation', ha='center', color='r')
ax.set_title('All RSA cycle streched to resp cycles')


plt.show()
All RSA cycle streched to resp cycles

Total running time of the script: (0 minutes 0.257 seconds)

Gallery generated by Sphinx-Gallery