canvodpy API reference¶
Umbrella package of canVODpy: one supported surface, and the command-line tool on top of it. See API levels.
Site and pipeline (recommended)¶
Stateful orchestrator with factory integration and structured logging. What the command-line tool builds internally.
User-friendly wrapper around GnssResearchSite.
Provides a clean, modern API for site management while using the proven GnssResearchSite implementation internally.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Site name from configuration (e.g., "ExampleSite") |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Site name |
receivers |
dict
|
All configured receivers |
active_receivers |
dict
|
Only active receivers |
vod_analyses |
dict
|
Configured VOD analysis pairs |
gnss_store |
MyIcechunkStore
|
Access to RINEX data store |
vod_store |
MyIcechunkStore
|
Access to VOD results store |
Examples:
>>> site = Site("ExampleSite")
>>> print(site.receivers)
{'canopy_01': {...}, 'reference_01': {...}}
>>> # Create pipeline
>>> pipeline = site.pipeline()
>>> # Access stores
>>> site.gnss_store.list_groups()
receivers
property
¶
Get all configured receivers.
active_receivers
property
¶
Get only active receivers.
vod_analyses
property
¶
Get configured VOD analysis pairs.
vod
property
¶
Lazy VOD computation helper.
gnss_store
property
¶
Access RINEX data store.
vod_store
property
¶
Access VOD results store.
gnss_store_path
property
¶
Where the site's GNSS store is, from the settings; read-only.
A local directory, or the s3:// URL of a store on S3.
vod_store_path
property
¶
Where the site's VOD store is, from the settings; read-only.
A local directory, or the s3:// URL of a store on S3.
pipeline(keep_vars=None, aux_agency=None, n_workers=None, dry_run=False, max_memory_gb=None, cpu_affinity=None, nice_priority=None, threads_per_worker=None, on_group_written=None, label=None, on_discovery_start=None, on_discovery_end=None, on_incomplete_day=None, on_days_without_vod=None)
¶
Create a processing pipeline for this site.
All parameters default to None, which means "read from config".
Explicit values override the config.
Reader format is configured per-receiver via reader_format in
the sites: section of config/canvod-settings.yaml (default:
"auto").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keep_vars
|
list[str]
|
RINEX variables to keep. Default: from config. |
None
|
aux_agency
|
str
|
Analysis center for auxiliary data (COD, ESA, GFZ, JPL). Default: from config. |
None
|
n_workers
|
int
|
Number of parallel workers. Default: from config. |
None
|
dry_run
|
bool
|
If True, simulate processing without execution. |
False
|
max_memory_gb
|
float
|
Memory budget of the run in GB: the workers and the days per unit are sized to fit it. Default: from config; without a value there, the memory available when the run starts. |
None
|
threads_per_worker
|
int
|
Threads per worker process. Default: from config. |
None
|
on_group_written
|
Callable[[str], None]
|
Called with the receiver-group name each time a group's data for one day finishes writing to Icechunk. Lets a caller drive its own progress display (e.g. the CLI's per-site/receiver rows) without this class owning any display itself. |
None
|
label
|
str
|
Free-text label of the run, stored in the run history (for example to group the repetitions of a benchmark). |
None
|
on_discovery_start
|
Callable[[str, Path], None]
|
Called with the receiver name and its data folder when the run starts finding that receiver's files. |
None
|
on_discovery_end
|
Callable[[str, int, int, float], None]
|
Called with the receiver name, the number of files found, the number of days and the elapsed seconds when the run has found them. |
None
|
on_incomplete_day
|
Callable[[str, str, int, int], None]
|
Called with |
None
|
on_days_without_vod
|
Callable[[str, list[str]], None]
|
Called with a receiver and the days in the range on which it has no files while its pair has: those days are not processed and get no VOD. |
None
|
Returns:
| Type | Description |
|---|---|
Pipeline
|
Configured pipeline for this site |
Examples:
>>> site = Site("ExampleSite")
>>> pipeline = site.pipeline(n_workers=8)
>>> data = pipeline.process_date("2025001")
User-friendly wrapper around PipelineOrchestrator.
Provides a clean API for processing workflows while using proven orchestrator logic internally.
All parameters default to None, which means "read from the
processing: section of config/canvod-settings.yaml". Explicit
values override the config.
Reader format is configured per-receiver via reader_format in the
sites: section (default: "auto").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
site
|
Site or str
|
Site object or site name |
required |
keep_vars
|
list[str]
|
RINEX variables to keep. Default: from config. |
None
|
aux_agency
|
str
|
Analysis center for auxiliary data. Default: from config. |
None
|
n_workers
|
int
|
Number of parallel loky worker processes. Default: from config
( |
None
|
dry_run
|
bool
|
If True, simulate without execution. |
False
|
max_memory_gb
|
float
|
Memory budget of the run in GB: the workers and the days per unit are sized to fit it (ADR 0021). Default: from config; without a value there, the memory available when the run starts. |
None
|
threads_per_worker
|
int
|
Threads per loky worker process. Default: from config. |
None
|
on_group_written
|
Callable[[str], None]
|
Called with the receiver-group name each time a group's data for one day finishes writing to Icechunk. Lets a caller drive its own progress display without this class owning any display itself. |
None
|
label
|
str
|
Free-text label of the run, stored in the run history. |
None
|
on_discovery_start
|
Callable[[str, Path], None]
|
Called with the receiver name and its data folder when the run starts finding that receiver's files. |
None
|
on_discovery_end
|
Callable[[str, int, int, float], None]
|
Called with the receiver name, the number of files found, the number of days and the elapsed seconds when the run has found them. |
None
|
on_incomplete_day
|
Callable[[str, str, int, int], None]
|
Called with |
None
|
on_days_without_vod
|
Callable[[str, list[str]], None]
|
Called with a receiver and the days in the range on which it has no files while its pair has: those days are not processed and get no VOD. |
None
|
A
|
|
required | |
history
|
|
required | |
with
|
|
required |
Examples:
>>> # From site object
>>> site = Site("ExampleSite")
>>> pipeline = Pipeline(site)
>>> # Or directly from name
>>> pipeline = Pipeline("ExampleSite")
>>> # Process single date
>>> data = pipeline.process_date("2025001")
>>> # Process range
>>> for date, datasets in pipeline.process_range("2025001", "2025007"):
... print(f"Processed {date}")
failed_receiver_days
property
¶
Receiver-days of this run that failed.
(receiver, YYYYDOY) pairs, empty while every receiver-day is
written or skipped. canvodpy run exits with code 3 when a run
has any; the log says why each one failed.
close()
¶
End the run and release orchestrator resources.
loky's reusable executor is shared and left running.
process_date(date)
¶
Process RINEX data for one date.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
date
|
str
|
Date in YYYYDOY format (e.g., "2025001" for Jan 1, 2025) |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Dataset]
|
Processed datasets for each receiver |
Examples:
>>> pipeline = Pipeline("ExampleSite")
>>> data = pipeline.process_date("2025001")
>>> print(data.keys())
dict_keys(['canopy_01', 'canopy_02', 'reference_01'])
>>> # Access individual receiver
>>> canopy_data = data['canopy_01']
>>> print(canopy_data.dims)
Dimensions: (epoch: 2880, sv: 32, ...)
process_range(start, end)
¶
Process RINEX data for a date range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
str
|
Start date (YYYYDOY) |
required |
end
|
str
|
End date (YYYYDOY) |
required |
Yields:
| Type | Description |
|---|---|
tuple[str, dict[str, Dataset]]
|
(date_key, datasets) for each processed date |
Examples:
>>> pipeline = Pipeline("ExampleSite")
>>> for date, datasets in pipeline.process_range("2025001", "2025007"):
... print(f"Processed {date}: {len(datasets)} receivers")
Processed 2025001: 3 receivers
Processed 2025002: 3 receivers
...
run(start=None, end=None, *, update_to_latest=False, vod_analyses=None, calculator='tau_omega')
¶
Store the days from start to end, then compute their VOD.
The run of canvodpy run (ADR 0021). The GNSS phase stores the
days in units of days and reads nothing back; after each unit, the
VOD phase computes the VOD of its days in the same worker pool,
from the GNSS store, and commits once (VodComputer.compute_days).
Meanwhile, the GNSS phase works on the next unit. A day that failed
gets no VOD and stays open for the next run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
str
|
First and last day (YYYYDOY). |
None
|
end
|
str
|
First and last day (YYYYDOY). |
None
|
update_to_latest
|
bool
|
Process the days from the last stored day on instead of
|
False
|
vod_analyses
|
sequence of str
|
The VOD analyses to compute; all the site's by default. An empty sequence computes no VOD. |
None
|
calculator
|
str
|
The registered VOD calculator. |
"tau_omega"
|
Yields:
| Type | Description |
|---|---|
RunUnit
|
Per unit, once its VOD is committed: the days stored and what
the VOD phase did. A failing VOD phase is logged and reported
in |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither |
NothingStoredError
|
With |
Examples:
>>> with Site("ExampleSite").pipeline() as pipeline:
... for unit in pipeline.run("2025001", "2025007"):
... print(sorted(unit.days), unit.vod.written)
preview(start=None, end=None, *, update_to_latest=False)
¶
Preview processing plan without execution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
str
|
YYYYDOY string to start from (inclusive). |
None
|
end
|
str
|
YYYYDOY string to end at (inclusive). |
None
|
update_to_latest
|
bool
|
Preview the days a run with |
False
|
Returns:
| Type | Description |
|---|---|
dict
|
Summary of dates, receivers, and files |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
NothingStoredError
|
With |
Examples:
>>> pipeline = Pipeline("ExampleSite")
>>> plan = pipeline.preview(start="2025001", end="2025003")
>>> print(f"Total files: {plan['total_files']}")
update_range()
¶
The days a run with update_to_latest processes.
It starts on the earliest last stored day in the site's GNSS store, counting only the receivers with new files: after their own last stored day, or on it but not in the store's log book. A day stored while its files were still arriving thus gets the rest, and a retired receiver doesn't hold the start back. It ends on the latest day with files.
Returns:
| Type | Description |
|---|---|
tuple[str, str] | None
|
The first and last day (YYYYDOY); None if no receiver has new files. |
Raises:
| Type | Description |
|---|---|
NothingStoredError
|
If nothing is stored for the site yet. |
Examples:
>>> with Site("ExampleSite").pipeline(dry_run=True) as pipeline:
... pipeline.update_range()
('2026293', '2026298')
Factories¶
Bases: ComponentFactory
Factory for GNSS data readers.
All registered readers must inherit from GNSSDataReader ABC.
Supports two creation modes:
- By name:
ReaderFactory.create("rinex3", fpath=path) - By file:
ReaderFactory.create_from_file(path)— detects RINEX v2, RINEX v3 and NMEA from the file's content (not SBF).
Examples:
>>> from canvodpy import ReaderFactory
>>> reader = ReaderFactory.create("rinex3", fpath="station.25o")
>>> reader = ReaderFactory.create_from_file("station.25o")
create_from_file(fpath, **kwargs)
classmethod
¶
Auto-detect the file format and create the appropriate reader.
Detects NMEA (a .nmea extension or a first line starting with
$), and otherwise RINEX v2 or v3 from the version in the first
header line; a RINEX v3 file with signal-strength observables only
gets the stripped RINEX v3 reader. SBF files are not detected: create
their reader by name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fpath
|
str or Path
|
Path to the GNSS data file. |
required |
**kwargs
|
Any
|
Additional parameters forwarded to the reader constructor. |
{}
|
Returns:
| Type | Description |
|---|---|
GNSSDataReader
|
Instantiated reader for the detected format. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If fpath does not exist. |
ValueError
|
If the format cannot be determined or no reader is registered for the detected format. |
detect_reader(fpath)
classmethod
¶
Name of the registered reader for the file at fpath.
Decided as in :meth:create_from_file: NMEA by its .nmea
extension or its sentences, RINEX by the version in the first
header line.
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If fpath does not exist. |
ValueError
|
If the format cannot be determined or no reader is registered for the detected format. |
Bases: ComponentFactory
Factory for grid builders.
All registered builders must inherit from BaseGridBuilder ABC.
Examples:
>>> from canvod.grids import EqualAreaBuilder
>>> GridFactory.register("equal_area", EqualAreaBuilder)
>>> grid = GridFactory.create(
... "equal_area",
... angular_resolution=5.0,
... cutoff_theta=75.0,
... )
Bases: ComponentFactory
Factory for VOD calculators.
All registered calculators must inherit from VODCalculator ABC.
Examples:
>>> from canvod.vod import TauOmegaZerothOrder
>>> VODFactory.register("tau_omega", TauOmegaZerothOrder)
>>> calc = VODFactory.create(
... "tau_omega",
... canopy_ds=canopy,
... sky_ds=sky,
... )
>>> vod = calc.calculate_vod()