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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pneumonitor-0.1.1.tar.gz (2.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pneumonitor-0.1.1-py3-none-any.whl (9.4 kB view details)

Uploaded Python 3

File details

Details for the file pneumonitor-0.1.1.tar.gz.

File metadata

  • Download URL: pneumonitor-0.1.1.tar.gz
  • Upload date:
  • Size: 2.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.4.28

File hashes

Hashes for pneumonitor-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d02fc9be6d4d50e73c9ece73124287a5de1cc0b82bf2f09345583c6123423ade
MD5 0e0f930af6151f94243e89e14b0543a8
BLAKE2b-256 86cda4b78cfc894f1bb142caf0e9f0fc98e111336c0c17132d7aa433ee6f89e0

See more details on using hashes here.

File details

Details for the file pneumonitor-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for pneumonitor-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c260d716514ded2a022f9e5311cb2665a25fcf1ca2d5a135639dc32f1a71606b
MD5 bdab92e286bbf4baa4bb85c23a8b3993
BLAKE2b-256 37acaecee1606e7f6755b646ad250d4cbd6f9f7017f0f6fa9231a69d66a498a2

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

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