Skip to main content

Oxygen Data

Wellue O2 Ring overnight readings, parsed locally and stored in your browser. Use the import page on the dashboard to add a night.

If you also have Oura ring data, the dashboard joins your nights. Open Oura data

Overnight pulse oximetry, paired with your CPAP data

A pulse oximeter is a small device that clips to your finger or wraps around your wrist and records your blood-oxygen saturation (SpO2) and heart rate every few seconds. Used overnight, it answers a question your CPAP machine cannot: did the air your machine delivered actually keep your oxygen up while you slept? The CPAP machine knows when its flow sensor sees an event. The oximeter knows when your blood oxygen actually dipped.

CPAP Clarity reads the ViHealth CSV that the Wellue O2 Ring (and the OxySmart fingertip clip and the next-generation O2Ring S) produce, parses it client-side, and shows three numbers that matter most: min SpO2 (how low your oxygen dipped), ODI 3% (how often it dropped 3 percent or more for at least 10 seconds, motion-rejected), and time below 88% (the clinically significant hypoxemia threshold). The dashboard joins each oximeter night to the CPAP session on the same calendar date, so a night with good CPAP data but persistent low SpO2 stands out clearly.

Like every other surface on this site, parsing happens entirely in your browser. Your overnight oximetry data does not pass through any server. There is no account; nothing leaves the tab.

How to read these numbers

An overnight pulse oximeter records your blood oxygen saturation (SpO2) and pulse every few seconds while you sleep. Three numbers carry most of the signal: min SpO2, ODI 3%, and time below 88%. Together they tell you whether your CPAP is reaching your oxygen, not just whether the machine's flow sensor is happy.

SpO2 readings can be affected by motion, finger temperature, skin pigmentation, and nail polish. A consumer pulse oximeter is a tracking and screening tool, not a diagnostic device. If you see persistent low SpO2at rest, talk to a sleep physician.

Most well-controlled CPAP users see overnight SpO2minimums between 88 and 92 percent (with brief, position-related dips lower), an ODI of 1 to 3 events per hour, and zero or near-zero time below 88 percent. Persistent values outside that range, especially with a clean CPAP AHI, are the pattern to bring to your sleep clinic; the data narrows what they need to look for.

Read the full guide: pulse oximetry for CPAP users →

Frequently asked questions

How do I export the overnight CSV from my Wellue O2 Ring?

Open the ViHealth app, tap the night you want, then tap the share / export icon. Choose CSV (not PDF). On iOS, save to Files; on Android, save to Downloads. Drop the resulting file into the Dashboard import zone on cpapclarity.com. The OxySmart fingertip clip and the new O2Ring S follow the same flow with slightly different CSV column shapes; CPAP Clarity dispatches by header automatically and writes all three into the same Dexie store keyed by date.

What is ODI 3% and why is it not the same as my AHI?

ODI (oxygen desaturation index) counts how often per hour your blood-oxygen saturation drops at least 3 percent for at least 10 seconds, motion-rejected. AHI counts apnea and hypopnea events scored from CPAP airflow. They measure related but distinct things. A treated CPAP user often has AHI under 1 and a slightly elevated ODI, because some events are too brief to score on flow but still produce a measurable oxygen dip. Use both to triangulate, not to argue with each other.

How does CPAP Clarity calculate ODI, and why might it not exactly match the ViHealth app?

CPAP Clarity uses an AASM-style ODI: the baseline is the peak SpO2 in the prior 120 seconds of clean readings, an event is any drop of 3% (or 4%) sustained for at least 10 seconds, and motion-flagged samples are excluded from both the baseline and the dip. This matches the open-source OSCAR implementation and lands within about 1 to 2 events per hour of the ViHealth app on the same CSV. The remaining gap comes from two design choices: CPAP Clarity excludes motion-flagged samples; ViHealth scores them. CPAP Clarity uses a 120-second look-back; some vendor algorithms use shorter or longer windows. Neither is wrong; the AASM peak-baseline definition is the most widely cited reference. If your dashboard ODI and your ViHealth ODI disagree by 5 or more events per hour on the same night, that is a bug worth reporting; small differences are expected.

Why does my dashboard sometimes show 'n/a' for ODI instead of a number?

ODI is only defensible when the recording produced enough usable data to score. Two cases trigger 'n/a' instead of a number: a recording shorter than the algorithm's 60-second warmup minimum, and a night where motion rejection (rolling over, hand against the sheets) flagged every sample as unreliable. A short late-night spot check or a particularly restless night can hit either case. We surface 'n/a (recording too short)' or 'n/a (motion-saturated)' in those cases instead of displaying 0.0, which would imply a perfect night when the algorithm actually had no clean data to work with. The mean SpO2, minimum SpO2, and time-below-88% values are still scored on whatever clean samples exist, so those headlines remain trustworthy even when ODI cannot be computed.

Why not just clone the ViHealth (or OSCAR) algorithm exactly?

Different vendor apps disagree with each other on ODI by larger margins than CPAP Clarity disagrees with any single one of them. ViHealth, OSCAR, and clinical sleep-study software each use slightly different baseline windows, motion rules, and recovery criteria. Cloning any one would lock CPAP Clarity in to that vendor's quirks (and break when the vendor updates their algorithm). The AASM 2018 manual is the clinical reference behind every home-sleep-study report you might bring to a sleep physician, so the algorithm here is the most comparable to what your clinician would score. We document the small expected deltas vs vendor apps in this FAQ so you know what to expect, rather than pretending vendor apps and clinical scoring are interchangeable.

Why does the dashboard show motion-rejected periods?

Pulse oximeters lose contact with their reading when you move your hand against the sheets. The O2 Ring writes a motion column on every reading; CPAP Clarity uses an AASM-style motion-rejection rule that holds the SpO2 baseline frozen during a desaturation candidate so a motion artifact cannot create a false ODI event. The OxySmart fingertip clip has no motion column (the clip itself does not produce useful motion data), so motion rejection is a no-op for OxySmart nights and the dashboard renders motion percent as n/a.

Do I need to wear the oximeter every night?

No. The O2 Ring is most useful as a periodic check rather than nightly wear. A pattern that works well for established CPAP users: one night of overnight oximeter data per month, plus extra nights if your CPAP data trends out of range. New CPAP users sometimes wear it nightly for the first two weeks to establish a baseline, then taper to monthly. The night-by-night join with CPAP data lights up automatically on the dates where both data sources exist.

How does the join with CPAP data work?

CPAP sessions and oximeter nights are joined by calendar date through a shared rollup layer. A 9 PM to 7 AM oximeter session pairs with the CPAP session that started during the same calendar night by default. The dashboard, history page, and AI export all surface paired nights together; the standalone oximeter page shows oximeter-only nights. The two data stores stay independent; deleting one does not affect the other.