API

respiration

physio.respiration.compute_respiration(raw_resp, srate, parameter_preset=None, parameters=None)
Function for respiration that:
  • preprocess the signal

  • detect cycles

  • clean cycles

  • compute metrics cycle by cycle

This function works with 3 types of possible sensors : airflow, belt and co2. Depending on these parameters, 3 differents algo will be internatlly used. So the parameters dict must contain sensor_type Note that the `resp_cycles`dataframe will contains cycles boundaries and features. Features will depend on sensor type.

See Handling parameters for parameters details.

Parameters:
raw_resp: np.array

Raw respiratory signal

srate: float

Sampling rate of the raw respiratory signal

parameter_preset: str or None

Possible presets are : ‘human_airflow’ | ‘human_belt’ | ‘human_co2’ | ‘rat_plethysmo’ | ‘rat_etisens_belt’ This string specifies the type of respiratory data, which determines the set of parameters used for processing. This set equivalent of the one you get using physio.get_respiration_parameters(preset) with preset being the same one.

parametersdict or None

When not None this updates the parameter set.

Returns:
resp: np.array

A preprocess respiratory trace

resp_cycles: pd.Dataframe

resp_cycles is a dataframe containing one row per respiratory cycle and one column per feature (timings, durations, amplitudes, volumnes …).

physio.respiration.detect_respiration_cycles(resp, srate, method='crossing_baseline', **method_kwargs)
Detect respiration with several possible methods:
  • “crossing_baseline”: method used when the respiratory signal is airflow internally uses detect_respiration_cycles_crossing_baseline()

  • “min_max” : method used when the respiratory signal is volume internally uses detect_respiration_cycles_min_max()

  • “co2” : method used when the respiratory signal is from co2 sensor internally uses detect_respiration_cycles_co2()

Parameters:
resp: np.array

Preprocessed respiratory signal.

srate: float

Sampling rate

method: ‘crossing_baseline’ | ‘co2’ | ‘min_max’

Which method is used for respiratory cycle detection respiration.

**method_kwargs:

All other options are routed to the sub-function.

Returns:
cycles: np.array

Indices of inspiration and expiration. shape=(num_cycle, 3) with [index_inspi, index_expi, index_next_inspi]

physio.respiration.clean_respiration_cycles(resp, srate, resp_cycles, baseline=None, variable_names=None, low_limit_log_ratio=3.0, sensor_type=None)

Remove outlier cycles.

This is done
  • on cycle duration

  • on resp/insp amplitudes

This can be done with:
  • hard threshold

  • median + K * mad

Parameters:
resp: np.array

Preprocess traces of respiratory signal.

srate: float

Sampling rate

resp_cycles: pd.Dataframe

Features of all cycles given by compute_respiration_cycle_features before clean.

baseline:

The baseline used to recompute resp_cycles, this is needed when sensor_type=”airflow”

variable_names: list of str

Which columns used to search for small deviant

low_limit_log_ratio: float

Used to compute low limit with “limit = med - mad * low_limit_log_ratio”

sensor_type: ‘airflow’ | ‘belt’ | ‘co2’

sensor type

Returns:
cleaned_cycles:

Clean version of cycles.

physio.respiration.compute_respiration_cycle_features(resp, srate, cycles, baseline=None, sensor_type='airflow')

Compute respiration features cycle by cycle

Parameters:
resp: np.array

Preprocess traces of respiratory signal.

srate: float

Sampling rate

cycles: np.array

Indices of inspiration and expiration. shape=(num_cycle + 1, 2)

baseline: float or None

If not None then the baseline is subtracted to resp to compute amplitudes and volumes.

sensor_type: str

The sensor type. Can be one of : ‘airflow’ | ‘belt’ | ‘co2’

Returns:
resp_cycles: pd.Dataframe

Features of all cycles.

ECG

physio.ecg.compute_ecg(raw_ecg, srate, parameter_preset='human_ecg', parameters=None)
Function for ECG that:
  • preprocess the ECG

  • detect R peaks

  • apply some cleaning to remove too small ECG interval

See Handling parameters for parameters details.

Parameters:
raw_ecg: np.array

Raw ECG signal

srate: float

Sampling rate

parameter_preset: str or None

Can be : ‘human_ecg’ | ‘rat_ecg’ This recruites parameters automatically through the use of physio.get_ecg_parameters(preset) where preset stands for what you chose.

parametersdict or None

When not None this overwrites the parameter set.

Returns:
clean_ecg: np.array

preprocess and normalized ecg traces

ecg_peaks: pd.DataFrame

dataframe with indices and timings of detected R peaks.

physio.ecg.clean_ecg_peak(ecg, srate, raw_peak_inds, min_interval_ms=400.0, max_clean_loop=4)

Clean peaks with simple idea: remove short interval.

Parameters:
ecg: np.array

preprocess traces of ECG signal

srate: float

Sampling rate

raw_peak_inds: np.array

Array of peaks indices to be cleaned

min_interval_ms: float (default 400ms)

Minimum interval for cleaning

max_clean_loop: int

Cleaning is iterated by looping in the range() of this value.

Returns:
peak_inds: np.array

Cleaned array of peaks indices

physio.ecg.compute_ecg_metrics(ecg_peaks, min_interval_ms=500.0, max_interval_ms=2000.0, verbose=False)

Compute metrics from ecg peaks:

  • HRV_Mean : Mean of RR intervals (Warning: this is not a measure of variability but a measure of central tendency …)

  • HRV_SD : Standard-Deviation of RR intervals

  • HRV_Median : Median of RR intervals (Warning: this is not a measure of variability but a measure of central tendency …)

  • HRV_Mad : Median Absolute Deviation (MAD) of RR intevals. MAD is more robust to outliers than a classic standard-deviation.

  • HRV_CV : HRV_SD / HRV_Mean = Coefficient of Variation = Normalized SD

  • HRV_MCV : HRV_Mad / HRV_Median = MAD Coefficient of Variation = Robust version of Coefficient of Variation

  • HRV_Asymmetry = HRV_Median - HRV_Mean = Difference between Median and Mean that diverges from 0 in case of outliers / non normal distribution of RR intervals.

  • HRV_RMSSD = Root-Mean Square of Successive Differences ~ like a 2nd derivative of RR intervals. Sensitive to fine variations of RR intervals but also very sensitive to outliers.

These metrics are a bit more robust than others toolboxes because are computed after a cleaning of RR intervals based on min and max intervals as set.

Parameters:
ecg_peaks: pd.DataFrame

DataFrame containing ecg R peaks.

min_interval_ms: float (default 500ms)

Minimum interval inter R peak

max_interval_ms: float (default 2000ms)

Maximum interval inter R peak

verbose: bool (default False)

Control verbosity

Returns:
metrics: pd.Series

A table containing HRV metrics

physio.ecg.compute_instantaneous_rate(ecg_peaks, new_times, limits=None, units='bpm', interpolation_kind='linear')
Parameters:
ecg_peaks: pd.DataFrame

DataFrame containing ecg R peaks.

new_timesnp.array

Time vector for interpolating the instantaneous rate.

limitslist or None

Limits for removing outliers.

unitsstr

Can be : ‘bpm’ / ‘Hz’ / ‘ms’ / ‘s’. Set the units of the output. Can be interval (ms or s) or rate (Hz or bpm).

interpolation_kindstr

‘linear’ or ‘cubic’

Returns:
instantaneous_ratenp.array

Instaneous rate of the shape of new_times because reinterpolated according ti this time basis

physio.ecg.compute_hrv_psd(ecg_peaks, sample_rate=100.0, limits=None, units='bpm', frequency_bands={'hf': (0.15, 0.4), 'lf': (0.04, 0.15)}, window_s=250.0, interpolation_kind='cubic')
Compute hrv power spectrum density and extract some metrics:
  • lf power

  • hf power

Please note:
  1. The duration of the signal and the window are important parameters to estimate low frequencies in a spectrum. Some warnings or errors should popup if they are too short.

  2. Given that the hrv is mainly driven by the respiration the frequency boudaries are often innacurate! For instance a slow respiration at 0.1Hz is moving out from the ‘hf’ band wheras this band should capture the respiratory part of the hrv.

  3. The instataneous rate is computed by interpolating eccg peak interval, the interpolation method ‘linear’ or ‘cubic’ are a real impact of the dynamic and signal smoothness and so the spectrum should differ because of the wieight of the harmonics

  4. The units of the instantaneous hrv (bpm, interval in second, interval in ms) have a high impact on the magnitude of metrics. Many toolboxes (neurokit2, ) differ a lot on this important detail.

  5. Here we choose the classical welch method for spectrum density estimation. Some parameters have also small impact on the results : dentend, windowing, overlap.

Parameters:
ecg_peaks: pd.DataFrame

DataFrame containing ecg R peaks.

sample_rate: float

Sampling rate of the interpolated instantanous heart rate

limits: None or List

If list, ex [30, 200], RR intervals correspond out of this range (here bpm) are removed before interpolation.

unitsstr

Can be : ‘bpm’ / ‘Hz’ / ‘ms’ / ‘s’. Set the units of the interpolated instantaneous heart rate.

frequency_bandsdict

Defines the frequency band of interest

window_sfloat

Size of the Welch’s window for PSD computation. Should be long enough to contain at least 5 iterations of the slowest frequency of intereset.

interpolation_kindstr

‘linear’ or ‘cubic’

Returns:
psd_freqsnp.array

Frequency vector of the PSD

psdnp.array

Power Spectral Density vector

metricspd.Series

Power of the set frequency bands, obtained using trapezoïdal rule.

Cylic tools

physio.cyclic_deformation.deform_traces_to_cycle_template(data, times, cycle_times, points_per_cycle=40, segment_ratios=None, output_mode='stacked', progress_bar=False)

Deform a signal a 1D signal (or also ND) to a ‘cycle template’. Every cycle chunk in the signal will be interpolated to have the same length. In short it is a times to cycles transformation.

Parameters:
data: nd.array

Axis of the time must always be 0, meaning of shape (n_times,…).

times: np.array

Time vector of the data. Shape = (n_times,)

cycle_times: np.array

Array with shape(num_cycle, num_segment + 1). Typically for respiration n cycles array with 3 columns (inspi time + expi time + next inspi time) will make deformation with 2 segments. If the cycle_times is 1D then it is converted to shape (size-1, 2). The end of every cycles must match the start of the next cycle.

points_per_cycle: int (default 40)

number of respi phase per cycle

segment_ratios: None or float or list of float

If multi segment deformation then a list of segmetn ratio must provived.

output_mode: str

‘stacked’ / ‘unstacked’ / ‘unstacked_full’ Format of the outputs. Stacked -> 2D matrix : cycles / points per cycle. Unstacked -> 1D matrix : flattened version of the stacked. Unstacked_full returns extra-outputs.

progress_barbool

To display or not a progress bar

Returns:
If mode == ‘stacked’
deformed_data_stacked:

A 2d array of stacked cycles. Shape = (num_cycles, points_per_cycle)

If mode == ‘unstacked’
deformed_data:

A 1d array of deformed cycles. Shape = (num_cycles * points_per_cycle)

cycle_points:

The cycle vector

If mode == ‘unstacked’:
clipped_times:

The clipped time vector

times_to_cycles:

The vector times to cycle

RespHRV

physio.resphrv.compute_resphrv(resp_cycles, ecg_peaks, srate=100.0, units='bpm', limits=None, two_segment=True, points_per_cycle=50, return_cyclic_cardiac_rate=True)

RSA = Respiratory Sinus Arrhythmia (or Respiratory Heart Rate Variability / RespHRV)

Compute the RSA cycle-by-cycle
  • compute instantaneous heart rate

  • on resp cycle basis compute peak-to-trough

Also compute the cyclic deformation of the instantaneous heart rate

Parameters:
resp_cyclespd.DataFrame

DataFrame of detected respiratory cycles

ecg_peakspd.DataFrame

DataFrame of detected ecg R peaks

srateint or float

Sampling rate used for interpolation to get an instantaneous heart rate vector, to compute cyclic_cardiac_rate. 100 is safe for both animal and human. For human 10 also works.

unitsstr

bpm / Hz

limitslist or None

Limits for removing outliers. To set according to the units parameter. Ex : [30, 200] to remove heart rates (in bpm) out of this range.

two_segmentbool

True or False (default = True). Deform instantaneous heart rate by respiratory phase using one segment (inspi_time to next_inspi_time) or two segments (inspi_time to expi_time and expi_time to next_inspi_time), to compute cyclic_cardiac_rate.

points_per_cycleint

Number of respiratory phase points per cycle, used in deform_traces_to_cycle_template() to build cyclic_cardiac_rate matrix

return_cyclic_cardiac_ratebool

If True, returns both outputs (resphrv_cycles and cyclic_cardiac_rate), else computes and returns only resphrv_cycles and not cyclic_cardiac_rate

Returns:
resphrv_cyclespd.DataFrame

Cycle-by-cycle features of Heart Rate dynamics. Ex : decay_amplitude gives the by-cycle peak-to-trough amplitude.

cyclic_cardiac_ratend.array

2D Matrix (respiratory cycle * respiratory phase) with instantaneous heart rate at each resp cycle and phase point.

reader

physio.reader.read_one_channel(filename, format, channel_name, scaled=True)

Simple function on top of neo that read one channel from file in supported format.

>>>  ecg, srate = physio.read_one_channel('/path/to/micromed_file.TRC', 'micromed', 'p7+', scaled=True)
Parameters:
filename: str or Path

The file

format: str

The foormat of the file ‘micromed’ or ‘brainvision’

channel_name: str

The channel names.

scaled: bool (default True)

Return traces scaled to unit or unscaled (int16)

Returns:
trace: np.array

The trace of the channel as a numpy 1d array.

srate: float

The sampling rate.

preproces

physio.preprocess.preprocess(traces, srate, band=[5.0, 45.0], btype='bandpass', ftype='bessel', order=5, normalize=False)

Apply simple filter using scipy

For ECG bessel 5-50Hz and order 5 is maybe a good choice.

Optionally also normalize the signal using median and mad.

Parameters:
traces: np.array

Input signal.

srate: float

Sampling rate

band: list of float or float

Tha band in Hz or scalar if high/low pass.

btype: ‘bandpass’, ‘highpass’, ‘lowpass’

The band pass type

ftype: str (dfault ‘bessel’)

The filter type used to generate coefficient using scipy.signal.iirfilter

order: int (default 5)

The order

normalize: bool (default False)

Apply or not normalization

Returns:
traces_clean: np.array

The preprocess traces

physio.preprocess.smooth_signal(trace, srate, win_shape='gaussian', sigma_ms=5.0)

A simple signal smoother using gaussian/rect kernel.

Parameters:
traces: np.array

Input signal.

srate: float

Sampling rate

win_shape: ‘gaussian’ / ‘rect’

The shape of the kernel

sigma_ms: float (default 5ms)

The length of the kernel. Sigma for the gaussian case.

Returns:
trace_smooth: np.array

The smoothed traces

plotting

physio.plotting.plot_cyclic_deformation(data, segment_ratios=None, two_cycles=True, ax=None)
Parameters:
data: np.array

A 2d cyclic deformed array

segment_ratios: None or list

Multi-segment deformation (then vertical line are also plotted at this ratio)

two_cycles: bool (dafult True)

Plot 2 consecutive cycles.

ax: None or matplotlib axes

Use it to plot on an external ax

Returns:
None

tools

physio.tools.compute_median_mad(data, axis=0)

Compute median and mad (median absolute deviation)

Parameters:
data: np.array

An array

axis: int (default 0)

The axis

Returns:
med:

The median

mad:

The mad

physio.tools.detect_peak(traces, srate, thresh=5, abs_threshold=None, exclude_sweep_ms=4.0, thresh_artifact=None, abs_thresh_artifact=None)

Simple positive peak detector.

Parameters:
traces: np.array

An array

srate: float

Sampling rate of the traces

thresh: float (default 5)

The threhold as mad factor abs_threshold = med + thresh * mad

abs_thresholdNone or float

This replace thresh (which is relative to mad)

exclude_sweep_ms: float

Zone to exclude multiple peak detection when noisy. If several peaks or detected in the same sweep the best is the winner.

thresh_artifact: float, default None

Ceil threshold that peaks must not exceed, this aims to remove big artifact This is relative to mad : abs_threshold = med + thresh_artifact * mad

abs_thresh_artifact: float, None

Same as thresh_artifact but absolute

Returns:
inds: np.array

Indices on the peaks

physio.tools.get_empirical_mode(traces, nbins=200)

Get the empirical mode of a distribution. This is a really lazy implementation that makes an histogram of the traces inside quantile [0.25, 0.75] and makes an histogram of 200 bins and takes the max.

Parameters:
traces: np.array

The traces

nbins: int (default 200)

Number of bins for the histogram

Returns:
mode: float

The empirical mode.

parameters

Some predefined parameters preset for computing respiration and ecg without pain.

physio.parameters.get_respiration_parameters(parameter_preset)

Get parameters nested dict for a given predefined parameter preset.

Parameters:
parameter_presetstr

Possible presets are : ‘human_airflow’ | ‘human_belt’ | ‘human_co2’ | ‘rat_etisens_belt’ | ‘rat_plethysmo’

Returns:
presetdict

Dictionary of predefined parameters

physio.parameters.get_ecg_parameters(parameter_preset)

Get parameters nested dict for a given predefined parameter preset.

Parameters:
parameter_presetstr

Possible presets are : ‘human_ecg’ | ‘rat_ecg’

Returns:
presetdict

Dictionary of predefined parameters