Skip to content

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.

DOI PyPI License fair-software.eu OpenSSF Best Practices

Get started


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.

    Reader Architecture

  •   Versioned, cloud-native storage


    Icechunk gives every append a git-like commit snapshot. Reproducible reads, safe parallel writes, S3-ready.

    canvod-store

  •   Hemispheric grid system


    Equal-area, geodesic, HTM and four more grid types. KDTree cell assignment in O(n log m).

    canvod-grids

  •   Four API levels


    One-liner convenience functions · Fluent workflow · VODWorkflow class · Fully stateless functional API for Airflow / Prefect.

    Quick Start

  •   Parallel processing pipeline


    Dask Distributed parallel pipeline with per-file commit, hash deduplication, and cooperative distributed writing.

    Architecture · Dask & Resources


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 VODCalculator ABC.

  •   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

tuwien.at/en/mg/geo/climers