Respiratory mechanics, work of breathing and diaphragm EMG entropy analysis
Project description
RespMech — respiratory mechanics, work of breathing and diaphragm EMG
(c) Copyright 2019–2026 Emil Ingerslev Walsted (emilwalsted@gmail.com), ORCID 0000-0002-6640-7175
RespMech analyses a time series of respiratory physiological recordings (e.g. exported from LabChart) breath by breath, and calculates:
- respiratory mechanics
- inspiratory and expiratory work of breathing (Campbell diagram)
- diaphragm EMG — RMS envelope, ECG-artefact removal, spectral noise reduction
- Sample Entropy1,2 (e.g. of diaphragm EMG)
Version 2 is a desktop application with a guided setup, a live preview/QC screen and a batch runner. The physiology is a faithful port of the original v1 code and is locked by golden/characterisation tests — see Correctness.
Install
Recommended — the desktop app. Download the installer for your platform from the
latest release: a .dmg (macOS) or .msi
(Windows). It bundles its own Python — nothing else to install.
Python package (CLI + core; the GUI is an extra):
pip install respmech # command-line tool + analysis engine
pip install "respmech[gui]" # + the PySide6 desktop app (respmech-gui)
From source (developers, or to use the CLI):
git clone https://github.com/emilwalsted/respmech.git
cd respmech
pip install -e ".[dev,gui]" # gui = PySide6 desktop app; dev adds the test stack
respmech-gui # launch the desktop app
Extras: gui (desktop app), emg (librosa — spectral noise reduction), plots (matplotlib
diagnostic figures), dev (tests). See docs/INSTALL.md for details.
Using the app
respmech-gui
First time in? Choose Explore with sample data on the start screen to load a ready-made synthetic recording — the one shown in the figures below, complete with a heartbeat artefact on the EMG and a little volume drift, so every step has something to demonstrate.
Three screens, in the order you work:
| Screen | What you do |
|---|---|
| Setup | Point at your recordings, map the data columns to channels, choose what to save. Assign channels visually from the data if you prefer. Settings validate as you type — the status bar flags anything inconsistent. |
| Preview & QC | See the analysis on one file before running the batch: breath segmentation, the Campbell loop and the per-breath table, and dedicated tabs to tune EMG – ECG reduction and EMG – noise reduction against the live signal. Click a breath to exclude it. |
| Run & results | Run the batch, watch progress per file, review the per-file status and averaged metrics, and open the output folder. |
Settings are stored as a declarative TOML analysis file (no longer an executable .py).
Open, save and switch between analyses — including your recently opened files — from the
Analysis menu in the header, which is available on every screen; RespMech marks unsaved
edits in the title bar and asks before discarding them.
Command line
respmech run settings.toml # process a batch (--dry-run computes without writing)
respmech validate settings.toml # check the settings and the input files
respmech migrate old_settings.py -o settings.toml # convert a v1 settings file (runs no v1 code)
migrate prints a report of every field moved, renamed or dropped.
Data recording requirements
Input data do not need to be a specific length, but because some outputs are per-time (e.g. minute ventilation) you must specify the sampling frequency of the recording.
The code analyses data breath by breath, and it is imperative that the recording starts with the last part of an expiration and ends with the first part of an inspiration. The recording is trimmed automatically to start at exactly the first inspiration and end at exactly the last expiration.
Breaths are segmented by joining an inspiration with the following expiration, using the flow signal to find the transition. A breath-separation buffer absorbs "wobbly" flow around zero (common in quiet breathing); its length depends on your sampling and breathing frequency. In Preview & QC you can click any breath — e.g. an IC manoeuvre or a cough — to drop it from the analysis:
Flow and volume conventions. The analysis assumes flow is negative on inspiration and positive on expiration — invert it in Setup if your recording is the other way around. Volume must be inspired volume; it can be inverted, or integrated from the flow signal if your recording has no volume channel. Volume drift (common when integrating from flow) is corrected automatically, with an optional trend adjustment on top — each breath's end-expiratory volume should return to the same baseline, and when it creeps the correction pulls it back:
Supported input formats: MATLAB, Excel, CSV/text. (MATLAB files exported from the Windows and macOS versions of LabChart differ — pick the variant in Setup ▸ Advanced.)
Work of breathing
Two options: calculate WOB from each breath's Campbell diagram and average the results, or first build an averaged pressure/volume loop and calculate WOB from that. The two give similar results, but with irregular breaths the averaged loop is more robust. The number of resampling points used when averaging the loop is configurable (a good default is the sampling frequency ÷ 8–10; it must be lower than the shortest inspiration or expiration in the file).
The enclosed area of the oesophageal-pressure–volume loop is the inspiratory work of breathing: the faint loops are the individual breaths, the bold one their average, the diagonal the passive elastic-recoil line, and the shaded triangle the elastic component.
Diaphragm EMG
When EMG channels are present, each is conditioned in steps before its RMS envelope and (optionally) sample entropy are measured. The heartbeat (ECG) R-wave is typically several times the EMG amplitude, so if left in it dominates the signal and badly inflates the RMS — it is detected on the clearest channel and subtracted first. Then spectral noise reduction — trained on a diaphragm-quiet reference — cleans the residual noise floor while preserving the inspiratory burst. Both steps are tuned against the live signal on the Preview screen's EMG tabs, and every stage is written to the diagnostic figures. The bold envelope below is the RMS the analysis actually measures: the raw one is dominated by the heartbeat (the R-waves run off the shared scale), and removing the ECG then reducing the noise drops the between-breath floor while keeping the bursts — the signal-to-noise of the inspiratory pattern roughly doubles from step 2 to step 3:
Entropy
Sample Entropy is calculated per breath for the selected channels and averaged like the other measurements. The embedding (m) and tolerance (r, multiplied by the SD of the data) parameters are configurable in Setup ▸ Advanced.
1) Lozano-García M, Leonardo, Moxham J, Rafferty F., Torres A, Jolley CJ, Jané R. Assessment of Inspiratory Muscle Activation using Surface Diaphragm Mechanomyography and Crural Diaphragm Electromyography. doi:10.1109/EMBC.2018.8513046.
2) Aboy M, David, Austin D, Pau. Characterization of Sample Entropy in the Context of Biomedical Signal Analysis. 2007. doi:10.1109/IEMBS.2007.4353701.
Output
Everything lands in the output folder you choose:
data/— Excel workbooks: the across-file averages, and (optionally) breath-by-breath values per file, plus a cohort summary. Each workbook carries its own Units and Provenance sheets.diagnostics/— vector PDF figures per file: Campbell/PV loops (averaged and per breath), the analysed and raw signals, the staged volume correction, and per-channel EMG overviews at each conditioning stage (raw → ECG-removed → noise-reduced). Optionally the EMG channels as WAV.analysis-used.tomlandrun-report.txt— the exact settings and a log of what was read, kept, excluded and written, so a folder of results carries its own recipe.
Use the diagnostic figures (or the Preview screen) to spot breaths to exclude — e.g. IC manoeuvres or coughs — then exclude them by clicking them in Preview.
Correctness
The v2 engine is a port of the original v1 monolith. Golden/characterisation tests pin the
output byte-for-byte against references baked from the original implementation, which is kept
frozen in legacy/ for exactly that purpose.
- How the calculations work (formulas and units): docs/REVERSE_ENGINEERING.md
- Design and rationale: docs/PLAN.md
- The tests: tests/golden/
License and usage
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
Sample entropy is vendored from pyEntropy — see LICENSE pyentrp.
Note to respiratory scientists
I created this code for my own work and shared it hoping that other researchers working with respiratory physiology might find it useful. If you have questions or suggestions that would make it more useful, please drop me an email.
How do I cite this code in scientific papers – and should I?
It is up to you, really. Personally I am a fan of transparency and Open Source / Open Science and I would appreciate a mention. This will also make readers of your papers aware that this code exists – if you found it useful, perhaps they will too.
Every released version has its own DOI. Reference the latest via
,
or cite a specific version using that version's DOI (click the badge for the list).
An example citation:
[...] were calculated using the Python package RespMech (E Walsted, RespMech v2.2, 2026, https://github.com/emilwalsted/respmech/, DOI: 10.5281/zenodo.3270826) [...]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file respmech-2.3.0.tar.gz.
File metadata
- Download URL: respmech-2.3.0.tar.gz
- Upload date:
- Size: 235.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
253833158f9e14a18ef4e4403af5954d3238e95065d924e365abb87ff6eb78c5
|
|
| MD5 |
a066960d33ad7f86086098a0c60aa383
|
|
| BLAKE2b-256 |
429f0b971e579193b423d03e854a2fba442ba59d24b1060f245a8795dc09219c
|
Provenance
The following attestation bundles were made for respmech-2.3.0.tar.gz:
Publisher:
publish-pypi.yml on emilwalsted/respmech
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
respmech-2.3.0.tar.gz -
Subject digest:
253833158f9e14a18ef4e4403af5954d3238e95065d924e365abb87ff6eb78c5 - Sigstore transparency entry: 2216513115
- Sigstore integration time:
-
Permalink:
emilwalsted/respmech@85cde5e9fd04c5e0c8f064d0516aaec4affd2cfb -
Branch / Tag:
refs/tags/v2.3.0 - Owner: https://github.com/emilwalsted
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@85cde5e9fd04c5e0c8f064d0516aaec4affd2cfb -
Trigger Event:
push
-
Statement type:
File details
Details for the file respmech-2.3.0-py3-none-any.whl.
File metadata
- Download URL: respmech-2.3.0-py3-none-any.whl
- Upload date:
- Size: 260.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5796bc9180cab83582382ac341a8d1dde99580c7e2f033df5dd7dc19dac207d
|
|
| MD5 |
3b7aece676545abaa02b0d992998b8d7
|
|
| BLAKE2b-256 |
cea488ebfbe9ae9aefcb2f0ec4fa52494e04483e860bc40d80651fd725eeb37e
|
Provenance
The following attestation bundles were made for respmech-2.3.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on emilwalsted/respmech
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
respmech-2.3.0-py3-none-any.whl -
Subject digest:
e5796bc9180cab83582382ac341a8d1dde99580c7e2f033df5dd7dc19dac207d - Sigstore transparency entry: 2216513159
- Sigstore integration time:
-
Permalink:
emilwalsted/respmech@85cde5e9fd04c5e0c8f064d0516aaec4affd2cfb -
Branch / Tag:
refs/tags/v2.3.0 - Owner: https://github.com/emilwalsted
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@85cde5e9fd04c5e0c8f064d0516aaec4affd2cfb -
Trigger Event:
push
-
Statement type: