Respiration tutorial

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

import physio

Respiration cycle detection: the quick way  ——————————————

The fastest way is to use compute_respiration() using a predefined parameter preset. Here is a simple example.

# read data
raw_resp = np.load('resp1.npy')
srate = 1000.
times = np.arange(raw_resp.size) / srate

# the easiest way is to use predefined parameters
resp, resp_cycles = physio.compute_respiration(raw_resp, srate, parameter_preset='human_airflow')

# resp_cycles is a dataframe containing all cycles and related fetaures (duration, amplitude, volume, timing)
print(resp_cycles)

inspi_index = resp_cycles['inspi_index'].values
expi_index = resp_cycles['expi_index'].values

fig, ax = plt.subplots()
ax.plot(times, raw_resp)
ax.plot(times, resp)
ax.scatter(times[inspi_index], resp[inspi_index], marker='o', color='green')
ax.scatter(times[expi_index], resp[expi_index], marker='o', color='red')
ax.set_ylabel('resp')

ax.set_xlim(110, 170)
example 02 respiration
    inspi_index  expi_index  ...  expi_amplitude  total_volume
0           963        3849  ...      102.789023    290.900295
1          8755       12470  ...       92.424274    248.221182
2         16629       20085  ...      114.051992    224.880845
3         25589       28826  ...       79.971850    179.640929
4         35467       39250  ...       80.847071    218.096948
5         45631       48992  ...       88.355380    184.421903
6         55914       59772  ...       80.166094    221.551973
7         67325       70801  ...       78.223802    172.416317
8         78023       81420  ...      121.968793    240.612522
9         86030       89213  ...      109.013617    161.906780
10        94623       97972  ...      176.532582   1083.501652
11       104423      108683  ...      112.247642    236.964441
12       114252      117877  ...      134.114274    215.359089
13       124700      127879  ...      121.508199    226.502400
14       134461      138178  ...       73.704242    196.257905
15       145780      149124  ...       77.729124    143.132747
16       156359      159809  ...       64.689117    172.424788
17       165930      169247  ...       68.542888    179.678477
18       175415      178225  ...       65.214481    129.565439
19       184867      188712  ...       90.656664    172.640214
20       195179      199483  ...       56.376923    186.983757
21       205152      209074  ...       63.106055    218.620572
22       214162      217778  ...       76.314458    206.421199
23       223497      227737  ...       66.216154    222.527032
24       233353      237747  ...       95.536105    254.269911
25       242949      247667  ...       92.769307    318.495735
26       253240      257182  ...       76.873371    258.033292
27       263116      266749  ...       81.421824    204.482721
28       273102      277759  ...       77.226645    243.681649
29       284946      288731  ...       76.494002    189.285082

[30 rows x 17 columns]

(110.0, 170.0)

Cycle detection: Default parameters  ———————————–

 Here are the default parametersthose aiming to process a human airflow signal.

It is possible to get default parameters dictionnary by calling it with the get_respiration_parameters() function.

# this is a nested dict of parameters of every processing step
parameters = physio.get_respiration_parameters('human_airflow')
pprint(parameters)
{'baseline': {'baseline_mode': 'median'},
 'cycle_clean': {'low_limit_log_ratio': 4.0},
 'cycle_detection': {'inspiration_adjust_on_derivative': False,
                     'method': 'crossing_baseline'},
 'features': {'compute_amplitude': True, 'compute_volume': True},
 'preprocess': {'band': 7.0,
                'btype': 'lowpass',
                'ftype': 'bessel',
                'normalize': False,
                'order': 5},
 'smooth': {'sigma_ms': 60.0, 'win_shape': 'gaussian'}}

Cycle detection: Parameters tuning  ———————————–

 If necessary, it is possible to change the predefined parameters.  For example, we change here the length of the smoothing parameter.

# let's change on parameter in the structure ...
parameters['smooth']['sigma_ms'] = 100.
pprint(parameters)

# ... and use them by providing it to "parameters"
resp, resp_cycles = physio.compute_respiration(raw_resp, srate, parameters=parameters)
{'baseline': {'baseline_mode': 'median'},
 'cycle_clean': {'low_limit_log_ratio': 4.0},
 'cycle_detection': {'inspiration_adjust_on_derivative': False,
                     'method': 'crossing_baseline'},
 'features': {'compute_amplitude': True, 'compute_volume': True},
 'preprocess': {'band': 7.0,
                'btype': 'lowpass',
                'ftype': 'bessel',
                'normalize': False,
                'order': 5},
 'smooth': {'sigma_ms': 100.0, 'win_shape': 'gaussian'}}

Respiration : step by step  ————————–

 Here are details of all low-level functions used internally in the compute_respiration()

resp = physio.preprocess(resp, srate, band=25., btype='lowpass', ftype='bessel', order=5, normalize=False)
resp = physio.smooth_signal(resp, srate, win_shape='gaussian', sigma_ms=90.0)

baseline = physio.get_respiration_baseline(resp, srate, baseline_mode='median')
print('baseline', baseline)

# this will give a numpy.array with shape (num_cycle, 3)
cycles = physio.detect_respiration_cycles(resp, srate, baseline_mode='manual', baseline=baseline)
print(cycles[:10])

# this will return a dataframe with all cycles and fetaure before cleaning
resp_cycles = physio.compute_respiration_cycle_features(resp, srate, cycles, baseline=baseline)

# this will remove outliers cycles based on log ratio distribution
resp_cycles = physio.clean_respiration_cycles(resp, srate, resp_cycles, baseline, low_limit_log_ratio=3)
print(resp_cycles.head(10))


inspi_index = resp_cycles['inspi_index'].values
expi_index = resp_cycles['expi_index'].values

fig, ax = plt.subplots()
ax.plot(times, resp)
ax.scatter(times[inspi_index], resp[inspi_index], marker='o', color='green')
ax.scatter(times[expi_index], resp[expi_index], marker='o', color='red')
ax.set_ylabel('resp')
ax.axhline(baseline, color='Coral')

ax.set_xlim(110, 170)


plt.show()
example 02 respiration
baseline -1635.6362015145448
[[  921  3899  8696]
 [ 8696 12407 16564]
 [16564 20049 25536]
 [25536 28891 35436]
 [35436 39351 45588]
 [45588 49038 55848]
 [55848 59841 67282]
 [67282 70835 77973]
 [77973 81641 85983]
 [85983 89221 94557]]
   inspi_index  expi_index  ...  expi_amplitude  total_volume
0          921        3899  ...      100.699565    290.636011
1         8696       12407  ...       90.468119    248.115513
2        16564       20049  ...      109.301593    224.811918
3        25536       28891  ...       77.782396    179.517104
4        35436       39351  ...       79.514765    217.967633
5        45588       49038  ...       87.158593    184.333682
6        55848       59841  ...       77.257209    221.402827
7        67282       70835  ...       77.327921    172.267005
8        77973       81641  ...      117.712828    240.550042
9        85983       89221  ...      104.090516    161.702428

[10 rows x 17 columns]

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

Gallery generated by Sphinx-Gallery