Metadata-Version: 2.4
Name: pneumonitor
Version: 0.1.1
Summary: Code related to Pneumonitor data processing
Project-URL: Repository, https://github.com/<your-username>/Pneumonitor
Author-email: Maciej Rosoł <maciej.rosol@pw.edu.pl>
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: matplotlib>=3.10.0
Requires-Dist: neurokit2>=0.2.12
Requires-Dist: numpy>=2.4.6
Requires-Dist: pandas>=3.0.3
Requires-Dist: plotly>=6.7.0
Requires-Dist: scipy>=1.17.1
Description-Content-Type: text/markdown

# 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

```python
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

```python
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

```python
from pneumonitor.preprocess import preprocess_cardio_resp

df_bio = preprocess_cardio_resp(df_bio, sampling_rate=500)
```

Uses [NeuroKit2](https://github.com/neuropsychology/NeuroKit) 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

```python
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)

```python
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:

```bash
pip install pneumonitor
# or
uv add pneumonitor
```

## Development

This project uses [uv](https://docs.astral.sh/uv/) for dependency management.

### Installing dependencies

Install all dependencies specified in `pyproject.toml`:

```bash
uv sync
```

### Adding new dependencies

To add a new package to the project:

```bash
uv add <package-name>
```

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