.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/example_02_respiration.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_example_02_respiration.py: Respiration tutorial ==================== .. GENERATED FROM PYTHON SOURCE LINES 7-17 .. code-block:: Python import numpy as np import matplotlib.pyplot as plt from pathlib import Path from pprint import pprint import physio .. GENERATED FROM PYTHON SOURCE LINES 18-39 Respiration cycle detection. The faster way: using `parameter_preset`. ---------------------------------------------------------------------- The fastest way to process respiration with :py:mod:`physio` is to use :py:func:`~physio.compute_respiration` which is a high-level wrapper function that simplifies respiratory signal analysis. To use this function, you must provide: * `raw_resp` : the raw respiratory signal as a NumPy array. * `srate` : the sampling rate of the respiratory signal * `parameter_preset` : a string specifying the type of respiratory data, which determines the set of parameters used for processing. Can be one of: `human_airflow`, `human_co2`, `human_belt`, `rat_plethysmo`, or `rat_etisens_belt`. When called, :py:func:`~physio.compute_respiration` performs the following: * Preprocesses the respiratory signal (returns a NumPy array: `resp`) * Computes cycle-by-cycle features (returns a pd.DataFrame: `resp_cycles`) **Warning:** The orientation of the `raw_resp` trace is important (multiply it by -1 for reversing it if necessary). Inspiration must point downward for `human_airflow` or `human_co2`, because downward deflections are interpreted by :py:func:`~physio.compute_respiration` as inspiration. For `rat_plethysmo` or `rat_etisens_belt`, the inspiration–expiration transition must point upward. For this tutorial, we will use an internal file already stored in NumPy format for demonstration purposes. .. GENERATED FROM PYTHON SOURCE LINES 40-69 .. code-block:: Python raw_resp = np.load('resp1_airflow.npy') # load respi srate = 1000. # our example signals have been recorded at 1000 Hz times = np.arange(raw_resp.size) / srate # build time vector # the easiest way is to use predefined parameters resp, resp_cycles = physio.compute_respiration(raw_resp, srate, parameter_preset='human_airflow') # set 'human_airflow' as preset because example resp is an airflow from humans # resp_cycles is a dataframe containing all cycles and related features (duration, amplitude, volume, timing, etc...). print(resp_cycles) inspi_ind = resp_cycles['inspi_index'].values # get index of inspiration start points expi_ind = resp_cycles['expi_index'].values # get index of expiration start points fig, ax = plt.subplots() ax.plot(times, raw_resp) ax.plot(times, resp) ax.scatter(times[inspi_ind], resp[inspi_ind], color='green', label = 'inspiration start') ax.scatter(times[expi_ind], resp[expi_ind], color='red', label = 'expiration start') ax.set_xlabel('Time (s)') ax.set_ylabel('Amplitude (AU)') ax.set_ylim(-1750, -1450) ax.set_title('Respiratory cycle detection') ax.legend(loc = 'upper right') ax.set_xlim(110, 170) .. image-sg:: /examples/images/sphx_glr_example_02_respiration_001.png :alt: Respiratory cycle detection :srcset: /examples/images/sphx_glr_example_02_respiration_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none inspi_index expi_index ... expi_peak_time total_volume 0 963 3849 ... 4.969 291.424431 1 8755 12470 ... 13.479 248.679461 2 16629 20085 ... 20.995 225.343872 3 25589 28826 ... 30.576 180.226656 4 35467 39250 ... 41.144 218.772816 5 45631 48992 ... 50.698 185.303221 6 55914 59772 ... 61.809 222.938344 7 67325 70801 ... 72.750 173.728543 8 78023 81420 ... 82.834 241.129370 9 86030 89213 ... 90.996 162.205566 10 94623 97972 ... 100.891 1083.803965 11 104423 108683 ... 110.518 237.217117 12 114252 117877 ... 119.319 216.113417 13 124700 127879 ... 129.999 227.066006 14 134461 138178 ... 140.396 196.708830 15 145780 149124 ... 151.674 145.025697 16 156359 159809 ... 161.764 173.603192 17 165930 169247 ... 171.542 179.954129 18 175415 178225 ... 180.364 129.920402 19 184867 188712 ... 190.757 172.982517 20 195179 199483 ... 201.509 187.120995 21 205152 209074 ... 210.793 218.716716 22 214162 217778 ... 220.553 206.830544 23 223497 227737 ... 229.680 222.818645 24 233353 237747 ... 239.786 254.319332 25 242949 247667 ... 249.696 318.826908 26 253240 257182 ... 259.468 258.070059 27 263116 266749 ... 269.279 204.821141 28 273102 277759 ... 279.953 244.363774 29 284946 288731 ... 291.162 189.545873 [30 rows x 21 columns] (110.0, 170.0) .. GENERATED FROM PYTHON SOURCE LINES 70-80 What is `parameter_preset` ? ---------------------------- Using `parameter_preset` tells :py:func:`~physio.compute_respiration` to process respiration according to a predefined set of parameters already optimized by :py:mod:`physio`. To get an idea of the default parameters used in `parameter_preset`, you can call :py:func:`~physio.get_respiration_parameters`. Here is an example showing the set of parameters applied in the case of a human airflow signal. .. GENERATED FROM PYTHON SOURCE LINES 81-86 .. code-block:: Python parameters = physio.get_respiration_parameters('human_airflow') # parameters is a nested dictionary of parameters used at each processing step. pprint(parameters) # pprint to "pretty print" .. rst-class:: sphx-glr-script-out .. code-block:: none {'baseline': {'baseline_mode': 'median'}, 'cycle_clean': {'low_limit_log_ratio': 4.5, 'variable_names': ['inspi_volume', 'expi_volume']}, 'cycle_detection': {'epsilon_factor1': 10.0, 'epsilon_factor2': 5.0, 'inspiration_adjust_on_derivative': False, 'method': 'crossing_baseline'}, 'preprocess': {'band': 7.0, 'btype': 'lowpass', 'ftype': 'bessel', 'order': 5}, 'sensor_type': 'airflow', 'smooth': {'sigma_ms': 60.0, 'win_shape': 'gaussian'}} .. GENERATED FROM PYTHON SOURCE LINES 87-101 Tuning parameters if unsatisfied -------------------------------- Variability during data acquisition (subject, acquisition system) can affect the recorded respiratory signal. Such variability may make some predefined parameters of :py:mod:`physio` inappropriate. In this situation, you can tune certain parameters by re-assigning values to the keys of the `parameters` dictionary. You may also tune multiple parameters at once if necessary. **To fine-tune parameters properly, a good understanding of each parameter's role is required. For this reason, we have dedicated a whole section to this topic — see the "Parameters" section.** For example, here we modify the length of the smoothing parameter, which corresponds to the duration in milliseconds of the Gaussian smoothing kernel (the width of the bell-shaped curve), usually referred to as sigma. .. GENERATED FROM PYTHON SOURCE LINES 102-114 .. code-block:: Python # let's change one parameter in the nested structure ... parameters['smooth']['sigma_ms'] = 100. # at the key "smooth" and the sub-key "sigma_ms", the default values is 60. Here we replace it by 100 milliseconds to induce more smoothing pprint(parameters) # pprint to "pretty print" # ... and use them by providing it to "parameters" resp, resp_cycles = physio.compute_respiration(raw_resp, srate, parameters=parameters) # preset_parameters = None in this case, because parameters is now explicitly defined .. rst-class:: sphx-glr-script-out .. code-block:: none {'baseline': {'baseline_mode': 'median'}, 'cycle_clean': {'low_limit_log_ratio': 4.5, 'variable_names': ['inspi_volume', 'expi_volume']}, 'cycle_detection': {'epsilon_factor1': 10.0, 'epsilon_factor2': 5.0, 'inspiration_adjust_on_derivative': False, 'method': 'crossing_baseline'}, 'preprocess': {'band': 7.0, 'btype': 'lowpass', 'ftype': 'bessel', 'order': 5}, 'sensor_type': 'airflow', 'smooth': {'sigma_ms': 100.0, 'win_shape': 'gaussian'}} .. GENERATED FROM PYTHON SOURCE LINES 115-121 Using low-level functions to control each step of the pipeline -------------------------------------------------------------- :py:func:`~physio.compute_respiration` is a high-level wrapper function that simplifies respiratory signal analysis. However, you may want more control over the entire process and therefore use the low-level functions of :py:mod:`physio`. Here are the details of all low-level functions used internally by :py:func:`~physio.compute_respiration`. .. GENERATED FROM PYTHON SOURCE LINES 122-161 .. code-block:: Python resp = physio.preprocess(raw_resp, srate, band=25., btype='lowpass', ftype='bessel', order=5, normalize=False) # filter resp = physio.smooth_signal(resp, srate, win_shape='gaussian', sigma_ms=90.0) # smooth baseline = physio.get_respiration_baseline(resp, srate, baseline_mode='median') # compute baseline level 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) # detect inspi-expi / expi-inspi / next inspi-expi indices print(cycles[:10]) # this will return a dataframe with all cycles and features before cleaning resp_cycles = physio.compute_respiration_cycle_features(resp, srate, cycles, baseline=baseline, sensor_type = 'airflow') # compute cycle-by-cycle resp features on airflow sensor type # 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=4.5, sensor_type = 'airflow') # clean features print(resp_cycles.head(10)) inspi_ind = resp_cycles['inspi_index'].values # get index of inspiration start points expi_ind = resp_cycles['expi_index'].values # get index of expiration start points fig, ax = plt.subplots() ax.plot(times, resp, label = 'preprocessed resp signal') ax.scatter(times[inspi_ind], resp[inspi_ind], marker='o', color='green', label = 'inspiration start') ax.scatter(times[expi_ind], resp[expi_ind], marker='o', color='red', label = 'expiration start') ax.axhline(baseline, color='Coral', label = 'baseline', ls = '--', alpha = 0.9) ax.set_ylabel('Amplitude (AU)') ax.set_xlabel('Time (s)') ax.set_title('Respiratory cycle detection (using low-level functions)') ax.set_ylim(-1750, -1450) ax.set_xlim(110, 170) ax.legend(loc = 'upper right') plt.show() .. image-sg:: /examples/images/sphx_glr_example_02_respiration_002.png :alt: Respiratory cycle detection (using low-level functions) :srcset: /examples/images/sphx_glr_example_02_respiration_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none baseline : -1635.636336457686 [[ 959 3856 8749] [ 8749 12461 16623] [16623 20084 25584] [25584 28837 35465] [35465 39256 45628] [45628 48997 55907] [55907 59779 67319] [67319 70804 78017] [78017 81433 86026] [86026 89212 94617]] /home/docs/checkouts/readthedocs.org/user_builds/physio/envs/stable/lib/python3.11/site-packages/physio/respiration.py:701: UserWarning: clean_respiration_cycles() need variable_names to be set, variable_name=['inspi_volume', 'expi_volume'] is set to for backward compatibility warnings.warn("clean_respiration_cycles() need variable_names to be set, variable_name=['inspi_volume', 'expi_volume'] is set to for backward compatibility") inspi_index expi_index ... expi_peak_time total_volume 0 959 3856 ... 4.968 291.387502 1 8749 12461 ... 13.477 248.663272 2 16623 20084 ... 20.993 225.308920 3 25584 28837 ... 30.575 180.185173 4 35465 39256 ... 41.138 218.718159 5 45628 48997 ... 50.699 185.262616 6 55907 59779 ... 61.812 222.891807 7 67319 70804 ... 72.757 173.670636 8 78017 81433 ... 82.837 241.081997 9 86026 89212 ... 90.998 162.158526 [10 rows x 21 columns] .. GENERATED FROM PYTHON SOURCE LINES 162-223 Respiration features / metrics ------------------------------ `resp_cycles` is a dataframe containing one row per respiratory cycle and one column per feature. Depending on the sensor type, **each cycle is described by multiple features.** Some features are related to the position (index) or time of particular points within the cycle: * `inspi_index`: Index of the start of inspiration (green point in the figure below). The index refers to the sequential position of the sample in the entire respiratory time series. * `expi_index`: Index of the start of expiration (red point in the figure below). * `next_inspi_index`: Index of the start of the next inspiration (equal to the `inspi_index` of cycle n+1). * `inspi_time`: (units = `s`) Time of the start of inspiration (green point in the figure below). * `expi_time`: (units = `s`) Time of the start of expiration (red point in the figure below). * `next_inspi_time`: (units = `s`) Time of the start of the next inspiration. * `inspi_peak_index`: Index of the inspiratory peak = position of the minimum sample of the cycle in the respiratory time series (computed only if `sensor_type` = `airflow`). * `expi_peak_index`: Index of the expiratory peak = position of the maximum sample of the cycle in the respiratory time series (computed only if `sensor_type` = `airflow`). * `inspi_peak_time`: (units = `s`) Time of the inspiratory peak = timestamp of the minimum sample of the cycle (computed only if `sensor_type` = `airflow`). * `expi_peak_time`: (units = `s`) Time of the expiratory peak = timestamp of the maximum sample of the cycle (computed only if `sensor_type` = `airflow`). From these points, many derived features of interest (e.g., for statistics) are computed: * `cycle_duration`: (units = `s`) Duration of the cycle in seconds = `next_inspi_time` - `inspi_time` * `inspi_duration`: (units = `s`) Duration of inspiration in seconds = `expi_time` - `inspi_time` * `expi_duration`: (units = `s`) Duration of expiration in seconds = `next_inspi_time` - `expi_time` * `cycle_freq`: (units = `Hz`) Breathing frequency in Hertz = 1 / `cycle_duration` * `cycle_ratio`: (units = AU because proportion) Ratio of inspiration duration to total cycle duration = `inspi_duration` / `cycle_duration`. Equivalent to the relative position of the transition from inspiration to expiration. * `inspi_amplitude`: (units = AU, the units of the recorded respiratory signal) Amplitude difference of the respiratory signal from baseline at `inspi_peak_index` (computed only if `sensor_type` = `airflow` or `belt`). Equivalent to peak inspiratory flow (black descending arrow in the figure below). * `expi_amplitude`: (units = AU, the units of the recorded respiratory signal) Amplitude difference of the respiratory signal from baseline at `expi_peak_index` (computed only if `sensor_type` = `airflow`' or `belt`). Equivalent to peak expiratory flow (black ascending arrow in the figure below). * `total_amplitude`: (units = AU, the units of the recorded respiratory signal) Sum of `inspi_amplitude` + `expi_amplitude` (computed only if `sensor_type` = `airflow` or `belt`). * `inspi_volume`: (units = AU * `s`, depending on units the recorded respiratory signal) Integral of the respiratory signal below baseline during inspiration (computed only if `sensor_type` = `airflow`). Equivalent to the green area in the figure below. * `expi_volume`: (units = AU * `s`, depending on units the recorded respiratory signal) Integral of the respiratory signal above baseline during expiration (computed only if `sensor_type` = `airflow`). Equivalent to the red area in the figure below. * `total_volume`: (units = AU * `s`, depending on units the recorded respiratory signal) Sum of `inspi_volume` + `expi_volume` (computed only if `sensor_type` = `airflow`). Equivalent to the sum of the green + red areas in the figure below. .. image:: ../img/resp_features_doc_physio.png :alt: Respiration Parameters :align: center :scale: 70% .. GENERATED FROM PYTHON SOURCE LINES 224-230 .. code-block:: Python pprint(f'{resp_cycles.shape[0]} detected cycles') pprint(f'{resp_cycles.shape[1]} computed features, which are the following :') pprint(resp_cycles.columns.to_list()) .. rst-class:: sphx-glr-script-out .. code-block:: none '30 detected cycles' '21 computed features, which are the following :' ['inspi_index', 'expi_index', 'next_inspi_index', 'inspi_time', 'expi_time', 'next_inspi_time', 'cycle_duration', 'inspi_duration', 'expi_duration', 'cycle_freq', 'cycle_ratio', 'inspi_volume', 'expi_volume', 'total_amplitude', 'inspi_amplitude', 'expi_amplitude', 'inspi_peak_index', 'expi_peak_index', 'inspi_peak_time', 'expi_peak_time', 'total_volume'] .. GENERATED FROM PYTHON SOURCE LINES 231-254 Quick example with respiration recorded using a belt ---------------------------------------------------- For this tutorial, we will use an internal file already stored in NumPy format for demonstration purposes. This file corresponds to 5 minutes of signal recorded with a belt on a human subject. The belt is a sensor of trunk circumference: the signal rises when the trunk dilates and decreases when the trunk retracts. Therefore, the detection method does not rely on a "baseline-crossing" approach, but rather on a "min-max" approach. This `min_max` method is activated via the `parameter_preset` dedicated to this situation. Note that respiratory signals recorded with belts are often of poor quality. In addition, some participants may present paradoxical respiration, with the trunk retracting during inspiration and dilating during expiration. In such cases, the metrics returned in `resp_cycles_belt` will not be meaningful. Further note that in case of a `belt`, volumes can't be computed and amplitudes are no the same ones than in `airflow`. In this case this a `max` - `min` measure related to a circumference, while in case of an `airflow` this is a vertical distance to the baseline... meaning an instantaneous flow. Let's run a short example. .. GENERATED FROM PYTHON SOURCE LINES 255-289 .. code-block:: Python raw_resp_belt = np.load('resp3_belt.npy') # load respi belt srate = 1000. # our example signals have been recorded at 1000 Hz times = np.arange(raw_resp_belt.size) / srate # build time vector # the easiest way is to use predefined parameters resp_belt, resp_cycles_belt = physio.compute_respiration(raw_resp_belt, srate, parameter_preset='human_belt') # set 'human_belt' as preset because example resp is an airflow from humans # print human_belt params pprint(physio.get_respiration_parameters('human_belt')) # resp_cycles_belt is a dataframe containing all cycles and related features (duration, amplitude, timing, etc...). In the case of belt, volumes are not computed. print(resp_cycles_belt) inspi_ind = resp_cycles_belt['inspi_index'].values # get index of inspiration start points expi_ind = resp_cycles_belt['expi_index'].values # get index of expiration start points fig, ax = plt.subplots() ax.plot(times, raw_resp_belt) ax.plot(times, resp_belt) ax.scatter(times[inspi_ind], resp_belt[inspi_ind], color='green', label = 'inspiration start') ax.scatter(times[expi_ind], resp_belt[expi_ind], color='red', label = 'expiration start') ax.set_xlim(195, 215) ax.set_xlabel('Time (s)') ax.set_ylabel('Amplitude (AU)') ax.set_title('Respiratory cycle detection on a belt signal (min-max signal)') ax.legend(loc = 'upper right') .. image-sg:: /examples/images/sphx_glr_example_02_respiration_003.png :alt: Respiratory cycle detection on a belt signal (min-max signal) :srcset: /examples/images/sphx_glr_example_02_respiration_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none {'baseline': None, 'cycle_clean': {'low_limit_log_ratio': 8.0, 'variable_names': ['inspi_amplitude', 'expi_amplitude']}, 'cycle_detection': {'exclude_sweep_ms': 200.0, 'method': 'min_max'}, 'preprocess': {'band': 5.0, 'btype': 'lowpass', 'ftype': 'bessel', 'order': 5}, 'sensor_type': 'belt', 'smooth': {'sigma_ms': 40.0, 'win_shape': 'gaussian'}} inspi_index expi_index ... inspi_amplitude expi_amplitude 0 3875 6168 ... 497.761465 747.099189 1 9499 11176 ... 453.815590 316.429352 2 13317 15405 ... 390.832924 432.101417 3 18137 19825 ... 389.225680 436.079255 4 22469 24252 ... 479.711632 414.107313 .. ... ... ... ... ... 82 283479 284539 ... 256.353191 236.941509 83 286221 287424 ... 250.333176 273.552655 84 289046 290081 ... 287.955141 288.775000 85 291656 292918 ... 284.711136 271.157089 86 294552 295610 ... 271.450497 285.710228 [87 rows x 13 columns] .. GENERATED FROM PYTHON SOURCE LINES 290-308 Quick example with respiration recorded using a CO2 sensor ---------------------------------------------------------- For this tutorial, we will use an internal file already stored in NumPy format for demonstration purposes. This file corresponds to 5 minutes of signal recorded with a CO2 sensor at 60 Hz from a human subject. In the upper airways, CO2 concentration decreases during inspiration and increases during exhalation, and so does the recorded signal. Therefore, the detection method does not rely on a "baseline-crossing" approach, but rather on a dedicated "co2" method. This method is activated via the `parameter_preset` specific to this situation. Note that for `co2`, amplitude and volumes are not computed. Let's run a short example. .. GENERATED FROM PYTHON SOURCE LINES 309-343 .. code-block:: Python raw_resp_co2 = np.load('resp4_CO2.npy') # load respi co2 srate = 60. # our example signals have been recorded at 60 Hz times = np.arange(raw_resp_co2.size) / srate # build time vector # the easiest way is to use predefined parameters resp_co2, resp_cycles_co2 = physio.compute_respiration(raw_resp_co2, srate, parameter_preset='human_co2') # set 'human_co2' as preset because example resp is an airflow from humans # print human_co2 params pprint(physio.get_respiration_parameters('human_co2')) # resp_cycles_co2 is a dataframe containing all cycles and related features (duration, timing, etc...). In the case of belt, volumes and amplitudes are not computed. print(resp_cycles_co2) inspi_ind = resp_cycles_co2['inspi_index'].values # get index of inspiration start points expi_ind = resp_cycles_co2['expi_index'].values # get index of expiration start points fig, ax = plt.subplots() ax.plot(times, raw_resp_co2) ax.plot(times, resp_co2) ax.scatter(times[inspi_ind], resp_co2[inspi_ind], color='green', label = 'inspiration start') ax.scatter(times[expi_ind], resp_co2[expi_ind], color='red', label = 'expiration start') ax.set_xlim(95, 110) ax.set_ylim(-1, 40) ax.set_xlabel('Time (s)') ax.set_ylabel('Amplitude (mmHg)') ax.set_title('Respiratory cycle detection on a CO2 signal') ax.legend(loc = 'upper right') .. image-sg:: /examples/images/sphx_glr_example_02_respiration_004.png :alt: Respiratory cycle detection on a CO2 signal :srcset: /examples/images/sphx_glr_example_02_respiration_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none {'baseline': None, 'cycle_clean': None, 'cycle_detection': {'clean_by_mid_value': True, 'method': 'co2', 'thresh_expi_factor': 0.05, 'thresh_inspi_factor': 0.08}, 'preprocess': {'band': 10.0, 'btype': 'lowpass', 'ftype': 'bessel', 'order': 5}, 'sensor_type': 'co2', 'smooth': {'sigma_ms': 40.0, 'win_shape': 'gaussian'}} inspi_index expi_index ... cycle_freq cycle_ratio 0 131 198 ... 0.255319 0.285106 1 366 396 ... 0.256410 0.128205 2 600 667 ... 0.256410 0.286325 3 834 865 ... 0.255319 0.131915 4 1069 1136 ... 0.255319 0.285106 .. ... ... ... ... ... 76 17755 17821 ... 0.256410 0.282051 77 17989 18055 ... 0.300000 0.330000 78 18189 18258 ... 0.256410 0.294872 79 18423 18491 ... 0.254237 0.288136 80 18659 18688 ... 0.740741 0.358025 [81 rows x 11 columns] .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.677 seconds) .. _sphx_glr_download_examples_example_02_respiration.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: example_02_respiration.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: example_02_respiration.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: example_02_respiration.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_