What the app is
Osmograph Desktop connects to a metal-oxide (MOX) e-nose — over serial, WiFi, or BLE — streams readings in real time, records phase-labelled sessions, measures a phenotype strip, lets you compare and train classifiers, manages a fleet of devices, tracks burn-in, and runs a local data-commons contribution pipeline with optional Hugging Face sync. It is software, not a device: it drives the hardware you already have.
| Facts | Value |
|---|---|
| Version / id | v0.1.0 · com.opensmell.osmograph-desktop |
| Stack | Tauri 2 (Rust backend) + TypeScript/Vite frontend; Chart.js for charts |
| Window | Default 1360×740, resizable 960×640 → 1920×1080 |
| Connections | Serial (OSM protocol, 115200 baud), WiFi (HTTP polling), BLE (async streaming) |
| Max channels | 6 (presets for 3 / 4 / 6) — channel count is auto-detected and never hardcoded |
Tabs
Six top-level tabs: Dashboard, Library, Compare, Train, Fleet, and System (which carries the connection, sensor, hardware, calibration, OLED, buzzer, firmware, burn-in, data-hub, Hugging Face, and plugins panels).
Dashboard
The live view. It shows a real-time trace canvas (play/pause/clear/record), the phenotype strip, a time-position scrubber over the buffered readings, the phase-recording HUD, and live classification probability bars when a classifier is loaded. Sensor presets switch between 3/4/6-channel configurations, and channels can be renamed or toggled on/off.
The phenotype strip
The strip projects live (or replayed) sensor readings onto the A1/A3 fingerprint axis and reports amplitudes plus the A1 direction (reducing vs oxidizing). It wraps the two-cluster centroid model (Vergara et al. 2012) embedded in the app.
The phenotype strip is measured and estimated, never "identified". It is not molecule identification and it is not validated classification — those would be overclaims. The app explicitly reports when a sample is outside the model's valid region (boundaries_cannot). The strong/weak amplitude split and the oxidizing/mixture categories are not validated and are not presented as such.
Phase recording protocol
Recordings follow a disciplined three-phase protocol that the analysis stack expects: baseline (default 30s) → exposure (default 120s) → recovery (default 120s). Phases are colour-coded (blue baseline, red exposure, green recovery), with per-phase operator instructions, a countdown timer, and a state machine ( start_phase_recording → set_phase → stop_phase_recording / cancel_phase_recording). Sessions export as .osmell bundles (manifest + data.csv + events) with the protocol, phase timeline, and dead channels recorded. Dead channels are detected automatically via a CV threshold.
The base ROX normalization uses a clean-air baseline; a recording is only physically comparable when the capture protocol was followed — the app records the protocol so downstream analysis can check.
Library
The Library is a persistent index of sessions (a JSON index plus per-session CSV files). For each session it shows label, date, duration, sensor count, and quality score. Actions: rename, delete, analyze (runs the quality scorer → badge and breakdown), export (copy the raw CSV or convert to an .osmell bundle), edit the substance label and notes. Import via drag-and-drop of CSV files on the panel or the import button; bulk operations (multi-select analyze/delete) are supported.
Compare
Select two or more library sessions and overlay their traces for visual comparison. Series are loaded from disk and aligned for the overlay — useful for sanity-checking protocol compliance and seeing response differences directly.
Train
Training builds a logistic-regression classifier on labelled sessions, evaluated by leave-one-recording-out (LORO). Trained models persist to disk with a model card (name, classes, feature mode, hardware gate, evaluation, quality gates). The Train tab lists, deletes, and inspects classifiers; a trained model can be loaded for live prediction on the Dashboard, where it renders probability bars.
- Only well-formed, protocol-compliant, quality-gated recordings are used (min-quality gate).
- A model trained on N channels is never silently run with fewer (hardware gate).
- Live classification uses a rolling window with a lock/unknown state machine so it refuses to overclaim.
Fleet
The Fleet tab shows a grid of known devices (serial + network). fleet_scan auto-discovers devices via serial-port enumeration and mDNS network scanning; probe_osm_info HTTP-probes OSM-capable devices on the LAN. Devices can be added or removed manually. Per-device state includes connection status, sensor configuration, and health.
System panels
Connection
- Serial — list ports, connect/disconnect, set baud (default 115200). The OSM protocol parses
OSM-prefixed lines and filters bootloader noise. - WiFi — host/port, HTTP polling connection with status and last-reading tracking.
- BLE — scan for devices, connect, and stream asynchronously with chunked reads.
Sensors
View and edit channel names and preset mappings; set the channel count (3/4/6). Channel names you set are persisted and honoured when exporting.
Hardware
Auto-detects the board via USB VID/PID (e.g. ESP32, Arduino Uno, Raspberry Pi Pico) and shows a human-readable board label.
Calibration
Zero-point baseline calibration (calibrate_baseline from an array of baseline samples), reference-point / power-law fitting from datasheet values or a measured-fit path, concentration inversion, and import/export of calibration profiles.
OLED & Buzzer
Read and write OLED display and buzzer configuration on the connected board (oled_get/set_config, buzzer_get/set_config).
Firmware
Flash firmware to detected boards (ESP toolchain; channel count maps to sensor pins), verify esptool availability, erase flash, and read the MAC address.
Burn-in
A 24-hour (configurable) burn-in tracker. Elapsed time is tracked against the wall clock and persisted to JSON, so it survives restarts. Shows elapsed time, percentage, and burning-in/ready status; supports start and reset (with custom hours).
Data hub
A local contribution pipeline mirroring the commons protocol: Pending → Approved → Published. List local contributions, approve, reject (with reason), publish vetted contributions, import CSVs, submit a CSV plus metadata, or export-and-submit a recording in one step.
Hugging Face sync
Split by trust, deliberately. Downloading reads public HF datasets with no token; uploading vetted (Published) contributions requires a write token that is held in memory only and never persisted to disk — it is used for the upload request and then dropped. Operations: list files, download, upload with commit message, and set/clear/check the token.
Plugins
The app scans ~/.config/Osmograph/plugins for Python scripts (with # name:, # description:, # version: headers) and model files (.pkl, .json) and lists them with their parsed metadata.
Hardware & data expectations
The app is tolerant on input: the CSV parser never rejects on structure, auto-detects delimiting, recognizes six time-column aliases (and clock-style and epoch-seconds formats), synthesizes 10 Hz timing when absent, sorts out-of-order rows, detects context columns (temperature, humidity, etc.) to keep out of scoring, and surfaces every interpretation as a warning. This mirrors the Python SDK's parser semantics so desktop and SDK agree.
Scope of claims
The app reports a measured phenotype, not an identified smell, and presents model quality as LORO-evaluated rather than proof of generalization to unseen devices. Quality flags are always shown, never hidden.
