canVODpy¶
An Open Python Ecosystem for GNSS-Transmissometry Canopy VOD Retrievals
canVODpy aims to be the central community-driven software suite for deriving and analyzing canopy Vegetation Optical Depth (VOD) from GNSS signal-to-noise ratio observations.
What makes canVODpy different¶
-
Single unified dataset format
Every reader produces an identical
(epoch × sid)xarray Dataset that passes structural validation. Downstream code is reader-agnostic. -
Versioned, cloud-native storage
Icechunk gives every append a git-like commit snapshot. Reproducible reads, safe parallel writes, S3-ready.
-
Hemispheric grid system
Equal-area, geodesic, HTM and four more grid types. KDTree cell assignment in O(n log m).
-
Four API levels
One-liner convenience functions · Fluent workflow ·
VODWorkflowclass · Fully stateless functional API for Airflow / Prefect. -
Parallel processing pipeline
Dask Distributed parallel pipeline with per-file commit, hash deduplication, and cooperative distributed writing.
Supported receiver formats¶
RINEX v3.04
Text-based standard format from all manufacturers. Satellite geometry computed from SP3 + CLK precise ephemerides.
Reader: Rnxv3Obs — all GNSS constellations, all bands
Septentrio Binary Format (SBF)
Binary format from Septentrio receivers. Includes broadcast ephemerides (SatVisibility blocks) for standalone satellite geometry — no SP3/CLK download required.
Reader: SbfReader — all GNSS constellations, PVT + DOP metadata
Quick Start¶
pip install canvodpy
Two lines, everything automatic:
from canvodpy import process_date, calculate_vod
data = process_date("Rosalia", "2025001")
vod = calculate_vod("Rosalia", "canopy_01", "reference_01", "2025001")
Deferred execution, chainable steps:
import canvodpy
result = (
canvodpy.workflow("Rosalia")
.read("2025001")
.preprocess()
.grid("equal_area", angular_resolution=5.0)
.vod("canopy_01", "reference_01")
.result()
)
Eager execution with structured logging:
from canvodpy import VODWorkflow
wf = VODWorkflow(site="Rosalia", grid="equal_area")
vod = wf.calculate_vod("canopy_01", "reference_01", "2025001")
Processing Pipeline¶
flowchart TD
RINEX["RINEX 3.04"] --> PARSE["Parse + SP3/CLK interpolation"]
SBF["Septentrio SBF"] --> PARSE2["Parse (geometry embedded)"]
SP3["SP3 / CLK"] --> PARSE
PARSE --> STORE["Icechunk store"]
PARSE2 --> STORE
STORE --> VOD["Tau-Omega VOD retrieval"]
VOD --> GRID["Hemispheric grid assignment"]
GRID --> VIZ["Visualisation"]
Packages¶
-
canvod-readers
RINEX v3.04 parsing with signal ID mapping. Unified
(epoch × sid)output with full validation. -
canvod-auxiliary
SP3 ephemeris and CLK clock retrieval. Hermite spline interpolation, FTP fallback chain.
-
canvod-grids
7 hemispheric grid types — equal-area, geodesic, HTM and more. KDTree-backed O(n log m) cell assignment.
-
canvod-vod
VOD estimation via zeroth-order tau-omega model. Extensible
VODCalculatorABC. -
canvod-store
Icechunk versioned storage with per-file hash deduplication. S3-compatible backends, ACID commits.
-
canvod-viz
2D polar hemisphere plots and 3D interactive Plotly surfaces.
-
canvod-utils
Pydantic configuration, YYYYDOY date utilities, shared tooling.
-
canvod-virtualiconvname
Maps arbitrary filenames to canonical canVOD names. NamingRecipe system, pre-flight validation, DuckDB catalog.
-
canvod-ops
Configurable preprocessing pipeline: temporal aggregation, grid assignment, extensible Op chain.
-
canvod-store-metadata
Store-level provenance (DataCite, ACDD, STAC), compliance validation, inventory builder, STAC catalog export.
-
canvodpy
Umbrella package — four API levels, factory system, unified entry point.
Technology¶
Scientific stack
xarray · NumPy · SciPy · Polars
Storage
Icechunk · Zarr · S3-compatible
Code quality
ruff · ty · pytest · uv
Documentation
Zensical · beautiful-mermaid · marimo notebooks
AI-assisted development
Claude Code · 15+ domain skills · persistent memory · CLAUDE.md
Affiliation¶
Climate and Environmental Remote Sensing Research Unit (CLIMERS) Department of Geodesy and Geoinformation, TU Wien