canvodpy 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- canvodpy-0.2.0/PKG-INFO +151 -0
- canvodpy-0.2.0/README.md +110 -0
- canvodpy-0.2.0/pyproject.toml +77 -0
- canvodpy-0.2.0/src/canvodpy/.DS_Store +0 -0
- canvodpy-0.2.0/src/canvodpy/__init__.py +276 -0
- canvodpy-0.2.0/src/canvodpy/api.py +707 -0
- canvodpy-0.2.0/src/canvodpy/cli/__init__.py +0 -0
- canvodpy-0.2.0/src/canvodpy/cli/run.py +366 -0
- canvodpy-0.2.0/src/canvodpy/diagnostics/.DS_Store +0 -0
- canvodpy-0.2.0/src/canvodpy/diagnostics/__init__.py +9 -0
- canvodpy-0.2.0/src/canvodpy/diagnostics/sbf_timing_diagnostics_new_api.py +239 -0
- canvodpy-0.2.0/src/canvodpy/diagnostics/timing_diagnostics_new_api.py +242 -0
- canvodpy-0.2.0/src/canvodpy/diagnostics/timing_diagnostics_script.py +246 -0
- canvodpy-0.2.0/src/canvodpy/factories.py +376 -0
- canvodpy-0.2.0/src/canvodpy/fluent.py +477 -0
- canvodpy-0.2.0/src/canvodpy/functional.py +585 -0
- canvodpy-0.2.0/src/canvodpy/globals.py +50 -0
- canvodpy-0.2.0/src/canvodpy/logging/.DS_Store +0 -0
- canvodpy-0.2.0/src/canvodpy/logging/__init__.py +50 -0
- canvodpy-0.2.0/src/canvodpy/logging/context.py +37 -0
- canvodpy-0.2.0/src/canvodpy/logging/logging_config.py +437 -0
- canvodpy-0.2.0/src/canvodpy/orchestrator/.DS_Store +0 -0
- canvodpy-0.2.0/src/canvodpy/orchestrator/__init__.py +46 -0
- canvodpy-0.2.0/src/canvodpy/orchestrator/interpolator.py +369 -0
- canvodpy-0.2.0/src/canvodpy/orchestrator/matcher.py +158 -0
- canvodpy-0.2.0/src/canvodpy/orchestrator/pipeline.py +1344 -0
- canvodpy-0.2.0/src/canvodpy/orchestrator/processor.py +3404 -0
- canvodpy-0.2.0/src/canvodpy/orchestrator/resources.py +302 -0
- canvodpy-0.2.0/src/canvodpy/utils/.DS_Store +0 -0
- canvodpy-0.2.0/src/canvodpy/utils/__init__.py +37 -0
- canvodpy-0.2.0/src/canvodpy/utils/perf.py +41 -0
- canvodpy-0.2.0/src/canvodpy/utils/telemetry.py +367 -0
- canvodpy-0.2.0/src/canvodpy/vod_computer.py +349 -0
- canvodpy-0.2.0/src/canvodpy/workflow.py +471 -0
- canvodpy-0.2.0/src/canvodpy/workflows/__init__.py +27 -0
- canvodpy-0.2.0/src/canvodpy/workflows/tasks.py +1394 -0
canvodpy-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: canvodpy
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Umbrella package for canVOD ecosystem
|
|
5
|
+
Keywords: GNSS,VOD,vegetation,remote sensing,geodesy
|
|
6
|
+
Author: Nicolas François Bader
|
|
7
|
+
Author-email: Nicolas François Bader <nicolas.bader@tuwien.ac.at>
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
14
|
+
Requires-Dist: canvod-readers
|
|
15
|
+
Requires-Dist: canvod-auxiliary
|
|
16
|
+
Requires-Dist: canvod-grids
|
|
17
|
+
Requires-Dist: canvod-store
|
|
18
|
+
Requires-Dist: canvod-store-metadata
|
|
19
|
+
Requires-Dist: canvod-utils
|
|
20
|
+
Requires-Dist: canvod-viz
|
|
21
|
+
Requires-Dist: canvod-vod
|
|
22
|
+
Requires-Dist: marimo>=0.9.0
|
|
23
|
+
Requires-Dist: matplotlib>=3.8.0
|
|
24
|
+
Requires-Dist: pint>=0.20
|
|
25
|
+
Requires-Dist: structlog>=23.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0
|
|
27
|
+
Requires-Dist: tqdm>=4.65
|
|
28
|
+
Requires-Dist: tomli>=2.0.0
|
|
29
|
+
Requires-Dist: natsort>=8.0.0
|
|
30
|
+
Requires-Dist: dask[distributed]>=2026.1.1
|
|
31
|
+
Requires-Dist: mystmd>=1.8.0
|
|
32
|
+
Requires-Dist: docker>=7.1.0
|
|
33
|
+
Requires-Dist: howfairis>=0.13.0
|
|
34
|
+
Requires-Dist: pyarrow>=23.0.1
|
|
35
|
+
Requires-Dist: palettable>=3.3.3
|
|
36
|
+
Requires-Dist: altair>=6.0.0
|
|
37
|
+
Requires-Dist: tabulate>=0.10.0
|
|
38
|
+
Requires-Dist: sqlglot>=29.0.1
|
|
39
|
+
Requires-Python: >=3.14
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# canvodpy
|
|
43
|
+
|
|
44
|
+
Umbrella package for unified GNSS VOD analysis.
|
|
45
|
+
|
|
46
|
+
## Overview
|
|
47
|
+
|
|
48
|
+
`canvodpy` is the unified entry point for the canVOD ecosystem. It provides
|
|
49
|
+
three levels of API:
|
|
50
|
+
|
|
51
|
+
- **Level 1:** One-line convenience functions (fastest path to results)
|
|
52
|
+
- **Level 2:** Object-oriented classes (structured workflows)
|
|
53
|
+
- **Level 3:** Low-level components (full control)
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Installs canvodpy + all 7 sub-packages
|
|
59
|
+
uv pip install canvodpy
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
### Level 1: Simple (One-Liners)
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from canvodpy import process_date, calculate_vod
|
|
68
|
+
|
|
69
|
+
# Process one day of data
|
|
70
|
+
data = process_date("Rosalia", "2025001")
|
|
71
|
+
|
|
72
|
+
# Calculate VOD
|
|
73
|
+
vod = calculate_vod("Rosalia", "canopy_01", "reference_01", "2025001")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Level 2: Object-Oriented (More Control)
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from canvodpy import Site, Pipeline
|
|
80
|
+
|
|
81
|
+
# Create site and pipeline
|
|
82
|
+
site = Site("Rosalia")
|
|
83
|
+
pipeline = site.pipeline(aux_agency="ESA", n_workers=8)
|
|
84
|
+
|
|
85
|
+
# Process data
|
|
86
|
+
data = pipeline.process_date("2025001")
|
|
87
|
+
|
|
88
|
+
# Or process multiple days
|
|
89
|
+
for date, datasets in pipeline.process_range("2025001", "2025007"):
|
|
90
|
+
print(f"Processed {date}")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Level 3: Low-Level (Full Control)
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from canvod.readers import Rnxv3Obs
|
|
97
|
+
from canvod.auxiliary import Sp3File, ClkFile
|
|
98
|
+
from canvod.store import GnssResearchSite
|
|
99
|
+
from canvodpy.orchestrator import PipelineOrchestrator
|
|
100
|
+
|
|
101
|
+
# Direct access to all internals
|
|
102
|
+
site = GnssResearchSite("Rosalia")
|
|
103
|
+
orchestrator = PipelineOrchestrator(site, n_max_workers=12)
|
|
104
|
+
# ... custom processing ...
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Included Packages
|
|
108
|
+
|
|
109
|
+
Installing canvodpy provides access to all 7 packages:
|
|
110
|
+
|
|
111
|
+
- **canvod.readers** -- RINEX file parsing (v3.04)
|
|
112
|
+
- **canvod.auxiliary** -- Auxiliary data (SP3, CLK) handling
|
|
113
|
+
- **canvod.grids** -- Hemisphere grid structures
|
|
114
|
+
- **canvod.store** -- Icechunk data storage
|
|
115
|
+
- **canvod.vod** -- VOD calculation algorithms
|
|
116
|
+
- **canvod.viz** -- 2D/3D visualization
|
|
117
|
+
- **canvod.utils** -- Shared utilities
|
|
118
|
+
|
|
119
|
+
## Platform Support
|
|
120
|
+
|
|
121
|
+
| Platform | Status | Notes |
|
|
122
|
+
|----------|--------|-------|
|
|
123
|
+
| Linux | Full support | Recommended |
|
|
124
|
+
| macOS | Full support | Fully tested |
|
|
125
|
+
| Windows | WSL only | Native not supported (reserved `aux` name) |
|
|
126
|
+
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
Create a `.env` file in repository root (optional for NASA products):
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# NASA CDDIS credentials (optional)
|
|
133
|
+
CDDIS_MAIL=your.email@example.com
|
|
134
|
+
|
|
135
|
+
# Data root directory (required)
|
|
136
|
+
GNSS_ROOT_DIR=/path/to/your/data
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Without `.env`, canvodpy operates in ESA-only mode (COD, GFZ, ESA products).
|
|
140
|
+
|
|
141
|
+
## Documentation
|
|
142
|
+
|
|
143
|
+
[Centralized documentation](../docs/index.md)
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
See the [main repository README](../README.md) for workspace development setup.
|
|
148
|
+
|
|
149
|
+
## License
|
|
150
|
+
|
|
151
|
+
Apache License 2.0
|
canvodpy-0.2.0/README.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# canvodpy
|
|
2
|
+
|
|
3
|
+
Umbrella package for unified GNSS VOD analysis.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`canvodpy` is the unified entry point for the canVOD ecosystem. It provides
|
|
8
|
+
three levels of API:
|
|
9
|
+
|
|
10
|
+
- **Level 1:** One-line convenience functions (fastest path to results)
|
|
11
|
+
- **Level 2:** Object-oriented classes (structured workflows)
|
|
12
|
+
- **Level 3:** Low-level components (full control)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Installs canvodpy + all 7 sub-packages
|
|
18
|
+
uv pip install canvodpy
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Level 1: Simple (One-Liners)
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from canvodpy import process_date, calculate_vod
|
|
27
|
+
|
|
28
|
+
# Process one day of data
|
|
29
|
+
data = process_date("Rosalia", "2025001")
|
|
30
|
+
|
|
31
|
+
# Calculate VOD
|
|
32
|
+
vod = calculate_vod("Rosalia", "canopy_01", "reference_01", "2025001")
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Level 2: Object-Oriented (More Control)
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from canvodpy import Site, Pipeline
|
|
39
|
+
|
|
40
|
+
# Create site and pipeline
|
|
41
|
+
site = Site("Rosalia")
|
|
42
|
+
pipeline = site.pipeline(aux_agency="ESA", n_workers=8)
|
|
43
|
+
|
|
44
|
+
# Process data
|
|
45
|
+
data = pipeline.process_date("2025001")
|
|
46
|
+
|
|
47
|
+
# Or process multiple days
|
|
48
|
+
for date, datasets in pipeline.process_range("2025001", "2025007"):
|
|
49
|
+
print(f"Processed {date}")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Level 3: Low-Level (Full Control)
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from canvod.readers import Rnxv3Obs
|
|
56
|
+
from canvod.auxiliary import Sp3File, ClkFile
|
|
57
|
+
from canvod.store import GnssResearchSite
|
|
58
|
+
from canvodpy.orchestrator import PipelineOrchestrator
|
|
59
|
+
|
|
60
|
+
# Direct access to all internals
|
|
61
|
+
site = GnssResearchSite("Rosalia")
|
|
62
|
+
orchestrator = PipelineOrchestrator(site, n_max_workers=12)
|
|
63
|
+
# ... custom processing ...
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Included Packages
|
|
67
|
+
|
|
68
|
+
Installing canvodpy provides access to all 7 packages:
|
|
69
|
+
|
|
70
|
+
- **canvod.readers** -- RINEX file parsing (v3.04)
|
|
71
|
+
- **canvod.auxiliary** -- Auxiliary data (SP3, CLK) handling
|
|
72
|
+
- **canvod.grids** -- Hemisphere grid structures
|
|
73
|
+
- **canvod.store** -- Icechunk data storage
|
|
74
|
+
- **canvod.vod** -- VOD calculation algorithms
|
|
75
|
+
- **canvod.viz** -- 2D/3D visualization
|
|
76
|
+
- **canvod.utils** -- Shared utilities
|
|
77
|
+
|
|
78
|
+
## Platform Support
|
|
79
|
+
|
|
80
|
+
| Platform | Status | Notes |
|
|
81
|
+
|----------|--------|-------|
|
|
82
|
+
| Linux | Full support | Recommended |
|
|
83
|
+
| macOS | Full support | Fully tested |
|
|
84
|
+
| Windows | WSL only | Native not supported (reserved `aux` name) |
|
|
85
|
+
|
|
86
|
+
## Configuration
|
|
87
|
+
|
|
88
|
+
Create a `.env` file in repository root (optional for NASA products):
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# NASA CDDIS credentials (optional)
|
|
92
|
+
CDDIS_MAIL=your.email@example.com
|
|
93
|
+
|
|
94
|
+
# Data root directory (required)
|
|
95
|
+
GNSS_ROOT_DIR=/path/to/your/data
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Without `.env`, canvodpy operates in ESA-only mode (COD, GFZ, ESA products).
|
|
99
|
+
|
|
100
|
+
## Documentation
|
|
101
|
+
|
|
102
|
+
[Centralized documentation](../docs/index.md)
|
|
103
|
+
|
|
104
|
+
## Development
|
|
105
|
+
|
|
106
|
+
See the [main repository README](../README.md) for workspace development setup.
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
Apache License 2.0
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "canvodpy"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Umbrella package for canVOD ecosystem"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.14"
|
|
7
|
+
authors = [
|
|
8
|
+
{ name = "Nicolas François Bader", email = "nicolas.bader@tuwien.ac.at" },
|
|
9
|
+
]
|
|
10
|
+
keywords = ["GNSS", "VOD", "vegetation", "remote sensing", "geodesy"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Intended Audience :: Science/Research",
|
|
14
|
+
"License :: OSI Approved :: Apache Software License",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.14",
|
|
17
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
# Core dependencies - sub-packages from workspace
|
|
21
|
+
dependencies = [
|
|
22
|
+
"canvod-readers",
|
|
23
|
+
"canvod-auxiliary",
|
|
24
|
+
"canvod-grids",
|
|
25
|
+
"canvod-store",
|
|
26
|
+
"canvod-store-metadata",
|
|
27
|
+
"canvod-utils",
|
|
28
|
+
"canvod-viz",
|
|
29
|
+
"canvod-vod",
|
|
30
|
+
"marimo>=0.9.0",
|
|
31
|
+
"matplotlib>=3.8.0",
|
|
32
|
+
"pint>=0.20",
|
|
33
|
+
"structlog>=23.0",
|
|
34
|
+
"pydantic>=2.0",
|
|
35
|
+
"tqdm>=4.65",
|
|
36
|
+
"tomli>=2.0.0",
|
|
37
|
+
"natsort>=8.0.0",
|
|
38
|
+
"dask[distributed]>=2026.1.1",
|
|
39
|
+
"mystmd>=1.8.0",
|
|
40
|
+
"docker>=7.1.0",
|
|
41
|
+
"howfairis>=0.13.0",
|
|
42
|
+
"pyarrow>=23.0.1",
|
|
43
|
+
"palettable>=3.3.3",
|
|
44
|
+
"altair>=6.0.0",
|
|
45
|
+
"tabulate>=0.10.0",
|
|
46
|
+
"sqlglot>=29.0.1",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[dependency-groups]
|
|
50
|
+
dev = [
|
|
51
|
+
"pytest>=8.0",
|
|
52
|
+
"pytest-cov>=5.0",
|
|
53
|
+
"ruff>=0.14",
|
|
54
|
+
"ty>=0.0.9",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[build-system]
|
|
58
|
+
requires = ["uv_build>=0.9.17,<0.10.0"]
|
|
59
|
+
build-backend = "uv_build"
|
|
60
|
+
|
|
61
|
+
# Workspace package sources
|
|
62
|
+
# This tells uv where to find the local packages
|
|
63
|
+
[tool.uv.sources]
|
|
64
|
+
canvod-readers = { workspace = true }
|
|
65
|
+
canvod-auxiliary = { workspace = true }
|
|
66
|
+
canvod-grids = { workspace = true }
|
|
67
|
+
canvod-store = { workspace = true }
|
|
68
|
+
canvod-store-metadata = { workspace = true }
|
|
69
|
+
canvod-utils = { workspace = true }
|
|
70
|
+
canvod-viz = { workspace = true }
|
|
71
|
+
canvod-vod = { workspace = true }
|
|
72
|
+
|
|
73
|
+
[tool.ty]
|
|
74
|
+
extend-exclude = [
|
|
75
|
+
"**/docs/*.ipynb",
|
|
76
|
+
"**/docs/notebooks/*.py",
|
|
77
|
+
]
|
|
Binary file
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"""canvodpy: GNSS Vegetation Optical Depth Analysis.
|
|
2
|
+
|
|
3
|
+
A modern Python package for processing GNSS data and calculating
|
|
4
|
+
vegetation optical depth (VOD) using the tau-omega model.
|
|
5
|
+
|
|
6
|
+
Quick Start
|
|
7
|
+
-----------
|
|
8
|
+
Three levels of API to match your needs:
|
|
9
|
+
|
|
10
|
+
**Level 1: Simple (one-liners)**
|
|
11
|
+
>>> from canvodpy import process_date, calculate_vod
|
|
12
|
+
>>> data = process_date("Rosalia", "2025001")
|
|
13
|
+
>>> vod = calculate_vod("Rosalia", "canopy_01", "reference_01", "2025001")
|
|
14
|
+
|
|
15
|
+
**Level 2: Object-oriented (more control)**
|
|
16
|
+
>>> from canvodpy import Site, Pipeline
|
|
17
|
+
>>> site = Site("Rosalia")
|
|
18
|
+
>>> pipeline = site.pipeline()
|
|
19
|
+
>>> data = pipeline.process_date("2025001")
|
|
20
|
+
>>> vod = pipeline.calculate_vod("canopy_01", "reference_01", "2025001")
|
|
21
|
+
|
|
22
|
+
**Level 3: Low-level (full control)**
|
|
23
|
+
>>> from canvod.store import GnssResearchSite
|
|
24
|
+
>>> from canvod.vod import VODCalculator
|
|
25
|
+
>>> # Direct access to all internals
|
|
26
|
+
|
|
27
|
+
Community Extensions
|
|
28
|
+
--------------------
|
|
29
|
+
Extend canvodpy with custom components using factories:
|
|
30
|
+
|
|
31
|
+
>>> from canvodpy import VODFactory
|
|
32
|
+
>>> from my_package import CustomCalculator
|
|
33
|
+
>>> VODFactory.register("custom", CustomCalculator)
|
|
34
|
+
>>> calc = VODFactory.create("custom", **params)
|
|
35
|
+
|
|
36
|
+
Package Structure
|
|
37
|
+
-----------------
|
|
38
|
+
- canvod.readers - RINEX file parsing
|
|
39
|
+
- canvod.auxiliary - Auxiliary data (ephemeris, clocks)
|
|
40
|
+
- canvod.grids - Hemisphere grid structures
|
|
41
|
+
- canvod.vod - VOD calculation algorithms
|
|
42
|
+
- canvod.viz - 2D/3D visualization
|
|
43
|
+
- canvod.store - Icechunk data storage
|
|
44
|
+
|
|
45
|
+
Configuration
|
|
46
|
+
-------------
|
|
47
|
+
Site configurations are stored in ``config/sites.yaml``.
|
|
48
|
+
Default variables and settings are in `globals.py`.
|
|
49
|
+
|
|
50
|
+
Examples
|
|
51
|
+
--------
|
|
52
|
+
Process one day of data:
|
|
53
|
+
>>> from canvodpy import process_date
|
|
54
|
+
>>> data = process_date("Rosalia", "2025001")
|
|
55
|
+
|
|
56
|
+
Process a week:
|
|
57
|
+
>>> from canvodpy import Pipeline
|
|
58
|
+
>>> pipeline = Pipeline("Rosalia")
|
|
59
|
+
>>> for date, datasets in pipeline.process_range("2025001", "2025007"):
|
|
60
|
+
... print(f"Processed {date}")
|
|
61
|
+
|
|
62
|
+
Calculate and visualize VOD:
|
|
63
|
+
>>> from canvodpy import calculate_vod
|
|
64
|
+
>>> from canvod.viz import HemisphereVisualizer
|
|
65
|
+
>>> vod = calculate_vod("Rosalia", "canopy_01", "reference_01", "2025001")
|
|
66
|
+
>>> viz = HemisphereVisualizer()
|
|
67
|
+
>>> fig = viz.plot_2d(vod)
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
from canvodpy.api import (
|
|
72
|
+
Pipeline,
|
|
73
|
+
Site,
|
|
74
|
+
calculate_vod,
|
|
75
|
+
preview_processing,
|
|
76
|
+
process_date,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Factories (for community extensions)
|
|
80
|
+
from canvodpy.factories import (
|
|
81
|
+
AugmentationFactory,
|
|
82
|
+
GridFactory,
|
|
83
|
+
ReaderFactory,
|
|
84
|
+
VODFactory,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Fluent workflow API (deferred execution)
|
|
88
|
+
from canvodpy.fluent import FluentWorkflow
|
|
89
|
+
|
|
90
|
+
# Functional API (Airflow-compatible)
|
|
91
|
+
from canvodpy.functional import (
|
|
92
|
+
assign_grid_cells,
|
|
93
|
+
assign_grid_cells_to_file,
|
|
94
|
+
augment_with_ephemeris,
|
|
95
|
+
calculate_vod_to_file,
|
|
96
|
+
create_grid,
|
|
97
|
+
create_grid_to_file,
|
|
98
|
+
read_rinex,
|
|
99
|
+
read_rinex_to_file,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Logging (for all users)
|
|
103
|
+
from canvodpy.logging import get_logger, setup_logging
|
|
104
|
+
|
|
105
|
+
# VOD computation helper
|
|
106
|
+
from canvodpy.vod_computer import VodComputer
|
|
107
|
+
|
|
108
|
+
# New workflow API
|
|
109
|
+
from canvodpy.workflow import VODWorkflow
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def workflow(site: str, **kwargs) -> FluentWorkflow:
|
|
113
|
+
"""Create a fluent workflow with deferred execution.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
site : str
|
|
118
|
+
Site name (e.g. ``"Rosalia"``).
|
|
119
|
+
**kwargs
|
|
120
|
+
Forwarded to :class:`FluentWorkflow`.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
FluentWorkflow
|
|
125
|
+
|
|
126
|
+
Examples
|
|
127
|
+
--------
|
|
128
|
+
>>> import canvodpy
|
|
129
|
+
>>> result = (canvodpy.workflow("Rosalia")
|
|
130
|
+
... .read("2025001")
|
|
131
|
+
... .preprocess()
|
|
132
|
+
... .grid()
|
|
133
|
+
... .vod("canopy_01", "reference_01")
|
|
134
|
+
... .result())
|
|
135
|
+
"""
|
|
136
|
+
return FluentWorkflow(site, **kwargs)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# ============================================================================
|
|
140
|
+
# Level 3 API: Re-export subpackages for advanced users
|
|
141
|
+
# ============================================================================
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Lazy import subpackages on access to avoid circular dependencies
|
|
145
|
+
def __getattr__(name: str):
|
|
146
|
+
"""Lazy import subpackages when accessed."""
|
|
147
|
+
_subpackages = {
|
|
148
|
+
"auxiliary": "canvod.auxiliary",
|
|
149
|
+
"grids": "canvod.grids",
|
|
150
|
+
"readers": "canvod.readers",
|
|
151
|
+
"store": "canvod.store",
|
|
152
|
+
"viz": "canvod.viz",
|
|
153
|
+
"vod": "canvod.vod",
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if name in _subpackages:
|
|
157
|
+
import importlib
|
|
158
|
+
import sys
|
|
159
|
+
|
|
160
|
+
module = importlib.import_module(_subpackages[name])
|
|
161
|
+
# Cache the imported module (can't use globals() as it's shadowed by canvodpy.globals)
|
|
162
|
+
setattr(sys.modules[__name__], name, module)
|
|
163
|
+
return module
|
|
164
|
+
|
|
165
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# ============================================================================
|
|
169
|
+
# Version
|
|
170
|
+
# ============================================================================
|
|
171
|
+
|
|
172
|
+
__version__ = "0.1.0"
|
|
173
|
+
|
|
174
|
+
# ============================================================================
|
|
175
|
+
# Public API
|
|
176
|
+
# ============================================================================
|
|
177
|
+
|
|
178
|
+
__all__ = [ # noqa: RUF022
|
|
179
|
+
# Version
|
|
180
|
+
"__version__",
|
|
181
|
+
# High-level API (most users)
|
|
182
|
+
"Site",
|
|
183
|
+
"Pipeline",
|
|
184
|
+
"process_date",
|
|
185
|
+
"calculate_vod",
|
|
186
|
+
"preview_processing",
|
|
187
|
+
# New workflow API
|
|
188
|
+
"VODWorkflow",
|
|
189
|
+
# Fluent workflow API
|
|
190
|
+
"FluentWorkflow",
|
|
191
|
+
"workflow",
|
|
192
|
+
# Functional API (notebooks & Airflow)
|
|
193
|
+
"read_rinex",
|
|
194
|
+
"read_rinex_to_file",
|
|
195
|
+
"create_grid",
|
|
196
|
+
"create_grid_to_file",
|
|
197
|
+
"assign_grid_cells",
|
|
198
|
+
"assign_grid_cells_to_file",
|
|
199
|
+
"calculate_vod_to_file",
|
|
200
|
+
# Logging
|
|
201
|
+
"setup_logging",
|
|
202
|
+
"get_logger",
|
|
203
|
+
# Factories (community extensions)
|
|
204
|
+
"ReaderFactory",
|
|
205
|
+
"GridFactory",
|
|
206
|
+
"VODFactory",
|
|
207
|
+
"AugmentationFactory",
|
|
208
|
+
# Subpackages (advanced users)
|
|
209
|
+
"readers",
|
|
210
|
+
"aux",
|
|
211
|
+
"grids",
|
|
212
|
+
"vod",
|
|
213
|
+
"viz",
|
|
214
|
+
"store",
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# ============================================================================
|
|
219
|
+
# Auto-register built-in components
|
|
220
|
+
# ============================================================================
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _register_builtin_components() -> None:
|
|
224
|
+
"""
|
|
225
|
+
Register built-in component implementations.
|
|
226
|
+
|
|
227
|
+
Called automatically on package import. Registers:
|
|
228
|
+
- Rnxv3Obs reader (rinex3)
|
|
229
|
+
- EqualAreaGridBuilder (equal_area)
|
|
230
|
+
- TauOmegaZerothOrder calculator (tau_omega)
|
|
231
|
+
|
|
232
|
+
Notes
|
|
233
|
+
-----
|
|
234
|
+
Uses lazy imports to avoid loading heavy dependencies unless needed.
|
|
235
|
+
"""
|
|
236
|
+
log = get_logger(__name__)
|
|
237
|
+
|
|
238
|
+
# Set ABC classes for validation
|
|
239
|
+
ReaderFactory._set_abc_class()
|
|
240
|
+
GridFactory._set_abc_class()
|
|
241
|
+
VODFactory._set_abc_class()
|
|
242
|
+
AugmentationFactory._set_abc_class()
|
|
243
|
+
|
|
244
|
+
try:
|
|
245
|
+
from canvod.readers import Rnxv3Obs
|
|
246
|
+
|
|
247
|
+
ReaderFactory.register("rinex3", Rnxv3Obs)
|
|
248
|
+
except ImportError:
|
|
249
|
+
log.debug("canvod-readers not available, skipping reader registration")
|
|
250
|
+
|
|
251
|
+
try:
|
|
252
|
+
from canvod.readers.sbf import SbfReader
|
|
253
|
+
|
|
254
|
+
ReaderFactory.register("sbf", SbfReader)
|
|
255
|
+
except ImportError:
|
|
256
|
+
log.debug("SbfReader not available, skipping sbf reader registration")
|
|
257
|
+
|
|
258
|
+
try:
|
|
259
|
+
from canvod.grids import EqualAreaBuilder
|
|
260
|
+
|
|
261
|
+
GridFactory.register("equal_area", EqualAreaBuilder)
|
|
262
|
+
except ImportError:
|
|
263
|
+
log.debug("canvod-grids not available, skipping grid registration")
|
|
264
|
+
|
|
265
|
+
try:
|
|
266
|
+
from canvod.vod.calculator import TauOmegaZerothOrder
|
|
267
|
+
|
|
268
|
+
VODFactory.register("tau_omega", TauOmegaZerothOrder)
|
|
269
|
+
except ImportError:
|
|
270
|
+
log.debug("canvod-vod not available, skipping VOD registration")
|
|
271
|
+
|
|
272
|
+
log.info("builtin_components_registered")
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
# Auto-register on import
|
|
276
|
+
_register_builtin_components()
|