Skip to main content

Pneumonitor

Python toolkit for analysing cardiorespiratory data recorded with the Pneumonitor 4 wearable device. The device simultaneously acquires ECG and impedance pneumography signals, enabling synchronised analysis of cardiac and respiratory activity.

Project structure

Pneumonitor/
├── pneumonitor/
│   ├── load.py         # Data loading and timestamp normalisation
│   ├── preprocess.py   # Signal processing (ECG, respiration, IMU)
│   ├── filters.py      # Digital filter building blocks
│   └── plots.py        # Interactive Plotly visualisations
├── <recording_id>/     # One folder per recording (e.g. 00001/)
│   ├── bio.txt         # ECG + bioimpedance (I/Q) at 500 Hz
│   ├── imu.txt         # 3-axis accelerometer at 50 Hz
│   ├── mark.txt        # User-triggered event markers
│   ├── stat.txt        # Battery and device status
│   ├── imp.txt         # Empty in the current version
│   └── info.txt        # Recording metadata and error log
└── experiments.py      # Example analysis notebook (%-cell format)

Recording format

Each recording folder contains semicolon-delimited text files:

File Columns Description
bio.txt timestamp[us], ECG[uV], BiozI[uV], BiozQ[uV] ECG and bioimpedance in-phase / quadrature components
imu.txt timestamp[us], X[mq], Y[mg], Z[mg] 3-axis accelerometer in mg
mark.txt timestamp[us] Timestamps of manual markers
stat.txt timestamp[us], BatLevel[%], BatVoltage[mV], BatCurrent[mA], Status[NONE] Device telemetry
info.txt Key-value pairs Hardware/firmware version, sample counts, error list

Timestamps are in microseconds from device boot. load_data() normalises them to seconds relative to the first biosignal sample.

Usage

1. Load a recording

from pneumonitor.load import load_data

df_bio, df_acc, df_markers, df_stats, errors = load_data('00001')

df_bio already contains the derived Amplitude (√(I²+Q²)) and Phase (arctan2(Q,I)) columns computed from the bioimpedance I/Q pair.

2. Process IMU data

from pneumonitor.preprocess import process_imu

df_acc = process_imu(df_acc, rms_window_sec=1, sampling_rate=50)

Adds Acc_Magnitude[g] (gravity-removed vector magnitude) and Acc_RMS[g] (rolling RMS over the specified window).

3. Preprocess cardiorespiratory signals

from pneumonitor.preprocess import preprocess_cardio_resp

df_bio = preprocess_cardio_resp(df_bio, sampling_rate=500)

Uses NeuroKit2 internally and appends the following columns to df_bio:

Column Description
ECG_clean[uV] Cleaned ECG signal
ECG_R_Peaks Binary mask of R-peak locations
ECG_Rate Instantaneous heart rate (bpm)
Amplitude_clean Cleaned respiratory amplitude
RSP_Rate Instantaneous respiratory rate (bpm)
RSP_Peaks Binary mask of respiration peaks
RSP_Phase Respiratory phase (0 = exhalation, 1 = inhalation)

4. Visualise

from pneumonitor.plots import plot_cardio_resp_data, plot_accelerometer_data

# Cardiorespiratory overview — add extra derived signals as extra subplots
plot_cardio_resp_data(df_bio, df_markers, include_raw=True,
                      additional_signals=['ECG_Rate', 'RSP_Rate'])

# Accelerometer overview
plot_accelerometer_data(df_acc, df_markers)

Both functions return a Plotly Figure and call .show(). The cardiorespiratory plot shades the respiratory amplitude subplot green (inhalation) / red (exhalation) based on RSP_Phase, and overlays R-peak markers on the ECG subplot.

5. Filters (optional low-level use)

from pneumonitor.filters import bandpass_filter, notch_filter, resp_filter

ecg_filtered = notch_filter(df_bio['ECG[uV]'].values)          # remove 50 Hz mains
ecg_filtered = bandpass_filter(ecg_filtered, lowcut=0.5, highcut=25)
resp_filtered = resp_filter(df_bio['Amplitude'].values)        # 3–180 bpm bandpass

Installation

Once published to PyPI, install it into any project with:

pip install pneumonitor
# or
uv add pneumonitor

Development

This project uses uv for dependency management.

Installing dependencies

Install all dependencies specified in pyproject.toml:

uv sync

Adding new dependencies

To add a new package to the project:

uv add <package-name>

This will update both pyproject.toml and the virtual environment automatically.

Metadata

Release files for pneumonitor 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pneumonitor 0.1.1
File Size Uploaded Provenance Actions
pneumonitor-0.1.1.tar.gz 2.5 MB Without provenance Details for pneumonitor-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pneumonitor 0.1.1
File Interpreter ABI Platform Actions
pneumonitor-0.1.1-py3-none-any.whl Python 3 none any Details for pneumonitor-0.1.1-py3-none-any.whl

Total release size: 2.5 MB

Release files / pneumonitor-0.1.1.tar.gz

Download URL pneumonitor-0.1.1.tar.gz
Size 2.5 MB
Tags Source
SHA-256 checksum
How to use checksums
d02fc9be6d4d50e73c9ece73124287a5de1cc0b82bf2f09345583c6123423ade
BLAKE2b-256 checksum
How to use checksums
86cda4b78cfc894f1bb142caf0e9f0fc98e111336c0c17132d7aa433ee6f89e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.4.28

Release files / pneumonitor-0.1.1-py3-none-any.whl

Download URL pneumonitor-0.1.1-py3-none-any.whl
Size 9.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c260d716514ded2a022f9e5311cb2665a25fcf1ca2d5a135639dc32f1a71606b
BLAKE2b-256 checksum
How to use checksums
37acaecee1606e7f6755b646ad250d4cbd6f9f7017f0f6fa9231a69d66a498a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.4.28

Security for pneumonitor 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page