Skip to main content

Oxynet

pyoxynet

PyPI version Python versions Documentation

The open-source models from the Oxynet research papers, for cardiopulmonary exercise test (CPET) data. Give pyoxynet a test and it returns, second by second, the model's output for the moderate, heavy and severe exercise-intensity domains, and the two ventilatory thresholds (VT1 and VT2) where those outputs cross. It can also generate synthetic tests.

Everything runs on your machine. The models are frozen LiteRT files, so TensorFlow is not needed.

Install

pip install pyoxynet

Python 3.10 to 3.14, on Windows, Linux and macOS (Apple silicon).

Quick start

import pyoxynet

# The bundled example test, through the default model
out_df, thresholds = pyoxynet.test_pyoxynet()

print(thresholds['VT1']['time'], round(thresholds['VT1']['VO2']))  # 372 2979
print(thresholds['VT2']['time'], round(thresholds['VT2']['VO2']))  # 550 3656

Each threshold gives its time (s) and the VO2, VE and HR there. out_df holds the three domain outputs (p_md, p_hv, p_sv) over time, next to the signals.

Your own test

import pandas as pd
import pyoxynet

df = pd.read_csv('my_test.csv')    # your test, with the columns below
out_df, thresholds = pyoxynet.test_pyoxynet(input_df=df)

The columns test_pyoxynet reads:

Column Signal
time seconds from the start of the test
VO2_I oxygen uptake
VCO2_I carbon dioxide output
VE_I minute ventilation
PetO2_I end-tidal O2
PetCO2_I end-tidal CO2
HR_I heart rate, optional: it is only reported at the thresholds
  • Any sampling works, breath by breath included. test_pyoxynet averages the data into one-second bins and interpolates linearly between them.
  • Each signal is min-max scaled over the test before it reaches the model, so units do not change the domains. The VO2, VE and HR reported at each threshold are in your file's units.
  • Other columns, text included, are ignored. From a cart export, rename its columns and turn its time into seconds: the docs show how. The hosted Oxynet API reads vendor exports directly.
  • test_pyoxynet raises a ValueError that says why when it cannot place consistent thresholds: the outputs never cross, VT1 would fall after VT2 or in the first 40 s, a signal is missing or constant, or the test is shorter than 80 s.

The models

model= What it is Paper
'CNN', the default Oxynet's convolutional network, fine-tuned on ramp tests from the Murias lab Evaluated in Keir et al. (2026)
'LSTM' A recurrent network: one LSTM and one GRU layer Follows the recurrent approach of Zignoli et al. (2019); not evaluated on its own
out_df, thresholds = pyoxynet.test_pyoxynet(input_df=df, model='LSTM')
  • Both are research models, frozen as they are: they are not retrained.
  • The evaluation in Keir et al. covered incremental tests in healthy individuals.
  • The domain outputs are what the network gives, not calibrated probabilities, and pyoxynet reports no confidence score.

Where each file came from is recorded in models/README.md. The models offered before 1.0.0 (murias_lab, AIS, NSWIS, TCN, LSTMGRUModel) were removed. Asking for one raises an error that names the available ones, and the earlier releases remain on PyPI. In 0.1.12, 'CNN' loaded a different network (regressor), so 1.0 gives different thresholds than 0.1.12 on the same file.

Synthetic and example tests

generator = pyoxynet.load_generator()
df, info = pyoxynet.generate_CPET(generator)        # a synthetic ramp test
out_df, thresholds = pyoxynet.test_pyoxynet(input_df=df)

df, info = pyoxynet.draw_real_test()                # one of 138 anonymised example tests
  • info['VT1'] and info['VT2'] are the thresholds the test was generated or labelled with, in seconds.
  • generate_CPET(generator, fitness_group=0) to 3 sets the fitness level, from very low to high.

The Oxynet API

pyoxynet is the open research package. Oxynet itself is a hosted service at app.oxynet.net, with its own, separately trained models. It reads metabolic cart exports as they come off the cart (COSMED and Cortex among them), checks the signals, and returns ventilatory thresholds, substrate use and signal-quality checks as versioned JSON. API keys are free: app.oxynet.net/signup.

Questions and citing

Questions and ideas go to GitHub Discussions, bugs to issues.

If you use the CNN, cite:

Keir DA, Zignoli A, Iannetta D, Mattioni Maturana F, Murias JM. AI-Driven Analysis of Cardiopulmonary Exercise Tests to Identify Gas Exchange and Ventilatory Thresholds. Sports Medicine. 2026;56(7):1833-1843. doi:10.1007/s40279-026-02403-w

Background:

  • Zignoli A, et al. Expert-level classification of ventilatory thresholds from cardiopulmonary exercising test data with recurrent neural networks. European Journal of Sport Science. 2019;19(9):1221-1229. doi:10.1080/17461391.2019.1587523
  • Zignoli A, et al. Oxynet: A collective intelligence that detects ventilatory thresholds in cardiopulmonary exercise tests. European Journal of Sport Science. 2022;22(3):425-435. doi:10.1080/17461391.2020.1866081
  • Zignoli A. Machine Learning Models for the Automatic Detection of Exercise Thresholds in Cardiopulmonary Exercising Tests: From Regression to Generation to Explanation. Sensors. 2023;23(2):826. doi:10.3390/s23020826

License and disclaimer

MIT. Research software, not a medical device: it does not diagnose, and its results are no substitute for a clinician's judgement.

Metadata

Release files for pyoxynet 1.0.2

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

Source distribution (sdist)

Source distribution for pyoxynet 1.0.2
File Size Uploaded Provenance Actions
pyoxynet-1.0.2.tar.gz 8.2 MB With provenance Details for pyoxynet-1.0.2.tar.gz

Built distribution (wheel)

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

Total release size: 16.5 MB

Release files / pyoxynet-1.0.2.tar.gz

Download URL pyoxynet-1.0.2.tar.gz
Size 8.2 MB
Tags Source
SHA-256 checksum
How to use checksums
6b7bf935c712abf19776600a6661e594e8494e0639fe2bb2720740cfadb05357
BLAKE2b-256 checksum
How to use checksums
7ec1fdfee9f6cc4f67e3a1477832cecef8ce0fb1e4d50465fa03582fc872b108
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Release files / pyoxynet-1.0.2-py3-none-any.whl

Download URL pyoxynet-1.0.2-py3-none-any.whl
Size 8.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
3c3f2e5987fc0510d3b1c8593f43ea7e24601617ede92b0beb262873a3caffef
BLAKE2b-256 checksum
How to use checksums
65c456753dee72cda2c735132ba515dc0f7726a7ac8d211d9d068babe147ed92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Security for pyoxynet 1.0.2

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pyoxynet-1.0.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

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

1.0.2 This release

2 release files Full 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