openeolib 0.1.3__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.
- openeolib-0.1.3/LICENSE +15 -0
- openeolib-0.1.3/PKG-INFO +299 -0
- openeolib-0.1.3/README.md +263 -0
- openeolib-0.1.3/openeolib/__init__.py +250 -0
- openeolib-0.1.3/openeolib/_plot_utils.py +268 -0
- openeolib-0.1.3/openeolib/analyzer.py +273 -0
- openeolib-0.1.3/openeolib/animation.py +512 -0
- openeolib-0.1.3/openeolib/engines.py +202 -0
- openeolib-0.1.3/openeolib/eo_cache.py +381 -0
- openeolib-0.1.3/openeolib/eo_types.py +313 -0
- openeolib-0.1.3/openeolib/eo_utils.py +128 -0
- openeolib-0.1.3/openeolib/panels.py +940 -0
- openeolib-0.1.3/openeolib/providers/__init__.py +1 -0
- openeolib-0.1.3/openeolib/providers/_s2_utils.py +280 -0
- openeolib-0.1.3/openeolib/providers/base.py +12 -0
- openeolib-0.1.3/openeolib/providers/era5.py +2133 -0
- openeolib-0.1.3/openeolib/providers/msm.py +836 -0
- openeolib-0.1.3/openeolib/providers/openeo_client.py +147 -0
- openeolib-0.1.3/openeolib/providers/provider.py +507 -0
- openeolib-0.1.3/openeolib/providers/radar_gpv_client.py +412 -0
- openeolib-0.1.3/openeolib/providers/rain.py +551 -0
- openeolib-0.1.3/openeolib/providers/sentinel2.py +231 -0
- openeolib-0.1.3/openeolib/providers/sentinel5p.py +147 -0
- openeolib-0.1.3/openeolib/report.py +184 -0
- openeolib-0.1.3/openeolib/roc.py +400 -0
- openeolib-0.1.3/openeolib/simulator.py +535 -0
- openeolib-0.1.3/openeolib/theme.py +23 -0
- openeolib-0.1.3/openeolib.egg-info/PKG-INFO +299 -0
- openeolib-0.1.3/openeolib.egg-info/SOURCES.txt +32 -0
- openeolib-0.1.3/openeolib.egg-info/dependency_links.txt +1 -0
- openeolib-0.1.3/openeolib.egg-info/requires.txt +29 -0
- openeolib-0.1.3/openeolib.egg-info/top_level.txt +1 -0
- openeolib-0.1.3/pyproject.toml +68 -0
- openeolib-0.1.3/setup.cfg +4 -0
openeolib-0.1.3/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ApacheLicense2.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 tkxu
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
openeolib-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openeolib
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Satellite-based methane emission detection and quantification using openEO
|
|
5
|
+
Author: tkxu
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: numpy>=1.24
|
|
11
|
+
Requires-Dist: scipy>=1.10
|
|
12
|
+
Requires-Dist: matplotlib>=3.7
|
|
13
|
+
Provides-Extra: provider
|
|
14
|
+
Requires-Dist: openeo>=0.26; extra == "provider"
|
|
15
|
+
Requires-Dist: rasterio>=1.3; extra == "provider"
|
|
16
|
+
Requires-Dist: xarray>=2023.1; extra == "provider"
|
|
17
|
+
Requires-Dist: netCDF4>=1.6; extra == "provider"
|
|
18
|
+
Provides-Extra: era5
|
|
19
|
+
Requires-Dist: cdsapi>=0.6; extra == "era5"
|
|
20
|
+
Requires-Dist: xarray>=2023.1; extra == "era5"
|
|
21
|
+
Requires-Dist: netCDF4>=1.6; extra == "era5"
|
|
22
|
+
Provides-Extra: jma
|
|
23
|
+
Requires-Dist: xarray>=2023.1; extra == "jma"
|
|
24
|
+
Requires-Dist: cfgrib>=0.9.10; extra == "jma"
|
|
25
|
+
Requires-Dist: dask>=2023.1; extra == "jma"
|
|
26
|
+
Requires-Dist: requests>=2.28; extra == "jma"
|
|
27
|
+
Requires-Dist: beautifulsoup4>=4.12; extra == "jma"
|
|
28
|
+
Requires-Dist: pyyaml>=6.0; extra == "jma"
|
|
29
|
+
Requires-Dist: JMA-grib2>=0.0.4a3; extra == "jma"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=4.1; extra == "dev"
|
|
33
|
+
Requires-Dist: flake8>=6.1; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy>=1.5; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# OpenEO-LIB
|
|
38
|
+
|
|
39
|
+
OpenEO-LIB is a Python library for satellite-based Earth observation workflows, including data providers, geospatial analysis, plume simulation, and reusable visualization components.
|
|
40
|
+
|
|
41
|
+
The package is designed so that reusable library functionality is kept separate from application-specific validation and research code.
|
|
42
|
+
|
|
43
|
+
## Current architecture
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
openeolib/
|
|
47
|
+
├── __init__.py
|
|
48
|
+
├── analyzer.py Analysis pipeline orchestration
|
|
49
|
+
├── animation.py Generic scalar-field animation (GridAnimationEngine)
|
|
50
|
+
├── engines.py Inference-engine interfaces and built-ins
|
|
51
|
+
├── eo_cache.py Persistent scientific-data cache (ScienceCacheStore)
|
|
52
|
+
├── eo_types.py Shared data structures and type definitions
|
|
53
|
+
├── eo_utils.py Geospatial and wind utilities
|
|
54
|
+
├── panels.py Generic Matplotlib visualization panels
|
|
55
|
+
├── report.py Generic figure/report composition
|
|
56
|
+
├── roc.py ROC construction
|
|
57
|
+
├── simulator.py Synthetic plume generation
|
|
58
|
+
├── theme.py Theme definition only (Theme, DEFAULT_THEME)
|
|
59
|
+
└── providers/
|
|
60
|
+
├── base.py BaseProvider ABC (raw Dataset retrieval)
|
|
61
|
+
├── provider.py Provider / EOProvider (S2+ERA5+S5P integration)
|
|
62
|
+
├── openeo_client.py openEO connection client
|
|
63
|
+
├── sentinel2.py Sentinel-2 L2A band retrieval
|
|
64
|
+
├── sentinel5p.py Sentinel-5P L2 CH4 column retrieval
|
|
65
|
+
├── era5.py ERA5 wind/pressure/temperature retrieval
|
|
66
|
+
├── msm.py JMA MSM (mesoscale model) wind retrieval
|
|
67
|
+
├── radar_gpv_client.py JMA nationwide composite radar GPV download
|
|
68
|
+
├── rain.py JMA rainfall / XRAIN providers + animate_rain()
|
|
69
|
+
└── _s2_utils.py Sentinel-2 coordinate/time conversion utilities
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Provider responsibilities are deliberately separated. `BaseProvider` and `Provider`
|
|
75
|
+
are independent interfaces with different responsibilities; `Provider` does not
|
|
76
|
+
extend `BaseProvider`. `BaseProvider` is the minimal file/data-opening interface
|
|
77
|
+
for providers that return an `xarray.Dataset` without application-level analysis.
|
|
78
|
+
`Provider` is the higher-level interface used by `EOAnalyzer` and returns an
|
|
79
|
+
`ObservationBundle` for a site and observation time. `EOProvider` implements
|
|
80
|
+
`Provider` for the openEO/Sentinel-2/Sentinel-5P workflow and contains the
|
|
81
|
+
workflow-specific quality and time-alignment logic.
|
|
82
|
+
|
|
83
|
+
The visualization layer (`panels.py`, `theme.py`, `report.py`, `animation.py`)
|
|
84
|
+
is kept domain-agnostic. Domain providers may know the schema and units of
|
|
85
|
+
their own source data, but they do not depend on application-specific
|
|
86
|
+
research pipelines.
|
|
87
|
+
|
|
88
|
+
Likewise, `theme.py` contains only the `Theme` data structure and `DEFAULT_THEME`.
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
pip install openeolib
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Development dependencies are optional and are intended for the private test suite:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install -e ".[dev]"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Optional provider dependencies are grouped by feature:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pip install -e ".[provider]"
|
|
106
|
+
pip install -e ".[era5]"
|
|
107
|
+
pip install -e ".[jma]"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The core package supports Python 3.9 or later. Provider-specific optional dependencies may have their own Python-version requirements.
|
|
111
|
+
|
|
112
|
+
The JMA extra (`openeolib[jma]`) is required for `MSMProvider`. The module
|
|
113
|
+
`openeolib.providers.msm` remains importable without the optional dependencies,
|
|
114
|
+
but constructing `MSMProvider` raises a clear `ImportError` listing the missing
|
|
115
|
+
dependencies and the installation command. This keeps optional JMA support from
|
|
116
|
+
breaking the core package import.
|
|
117
|
+
|
|
118
|
+
## Public visualization API
|
|
119
|
+
|
|
120
|
+
The reusable visualization API consists of five panels:
|
|
121
|
+
|
|
122
|
+
- `VectorFieldPanel` — arbitrary geospatial vector fields with optional scalar contours.
|
|
123
|
+
- `BasemapPanel` — an already prepared RGB image with an optional marker.
|
|
124
|
+
- `RawBandsPanel` — arbitrary grids of 2D images with a shared scale.
|
|
125
|
+
- `ScalarMapPanel` — arbitrary 2D scalar fields.
|
|
126
|
+
- `DetectionMaskPanel` — boolean, probability, or coverage masks.
|
|
127
|
+
|
|
128
|
+
Example:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import matplotlib.pyplot as plt
|
|
132
|
+
import numpy as np
|
|
133
|
+
from openeolib import ScalarMapPanel
|
|
134
|
+
|
|
135
|
+
field = np.random.default_rng(0).normal(size=(100, 100))
|
|
136
|
+
|
|
137
|
+
fig = plt.figure(figsize=(6, 5))
|
|
138
|
+
gs = fig.add_gridspec(1, 1)[0]
|
|
139
|
+
ScalarMapPanel().draw(
|
|
140
|
+
fig,
|
|
141
|
+
gs,
|
|
142
|
+
field,
|
|
143
|
+
title="Scalar field",
|
|
144
|
+
axis_mode="none",
|
|
145
|
+
)
|
|
146
|
+
fig.savefig("scalar_field.png", dpi=150, bbox_inches="tight")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Vector fields
|
|
150
|
+
|
|
151
|
+
`VectorFieldPanel` is intentionally not ERA5-specific. It accepts latitude/longitude grids and arbitrary vector components. A caller may supply any bounding box through `extent=(west, east, south, north)`.
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from openeolib import VectorFieldPanel
|
|
155
|
+
|
|
156
|
+
panel = VectorFieldPanel(quiver_stride=3)
|
|
157
|
+
panel.draw(
|
|
158
|
+
fig,
|
|
159
|
+
gs,
|
|
160
|
+
lats=lats,
|
|
161
|
+
lons=lons,
|
|
162
|
+
u=u,
|
|
163
|
+
v=v,
|
|
164
|
+
extent=(120, 150, 20, 50),
|
|
165
|
+
title="Wind field",
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
There is no Japan-specific bounding-box constant in the library.
|
|
170
|
+
|
|
171
|
+
### Theme
|
|
172
|
+
|
|
173
|
+
Use `Theme` when a caller needs to customize the visual appearance:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from openeolib import Theme
|
|
177
|
+
|
|
178
|
+
light = Theme(
|
|
179
|
+
bg="#ffffff",
|
|
180
|
+
panel_bg="#ffffff",
|
|
181
|
+
grid_color="#cccccc",
|
|
182
|
+
text_primary="#222222",
|
|
183
|
+
)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`Theme` does not contain plotting operations or application-specific labels, flags, or data extraction rules.
|
|
187
|
+
|
|
188
|
+
## Generic reports
|
|
189
|
+
|
|
190
|
+
`SiteReportBuilder` composes caller-supplied panels into a single-site report Figure. It does not know about methane, ROC curves, quality flags, or a particular inference engine -- it only handles grid layout, the report title, and file saving.
|
|
191
|
+
|
|
192
|
+
Each entry in `panels` is `(label, factory, height_ratio)`. `factory` is called once with the report's `Theme` and must return a `(fig, gs) -> None` draw function; any panel-specific data (the field to plot, its title, ...) is bound into that closure by the caller, not inspected by `SiteReportBuilder` itself.
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
import numpy as np
|
|
196
|
+
from openeolib import SiteReportBuilder, ScalarMapPanel
|
|
197
|
+
|
|
198
|
+
field = np.random.default_rng(0).normal(size=(100, 100))
|
|
199
|
+
|
|
200
|
+
report = SiteReportBuilder(
|
|
201
|
+
panels=[
|
|
202
|
+
(
|
|
203
|
+
"Scalar field",
|
|
204
|
+
lambda theme: lambda fig, gs: ScalarMapPanel(theme=theme).draw(
|
|
205
|
+
fig, gs, field, title="Scalar field", axis_mode="none",
|
|
206
|
+
),
|
|
207
|
+
1.0,
|
|
208
|
+
),
|
|
209
|
+
],
|
|
210
|
+
report_title="Example report",
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
report.build_site({"site": {"id": "SITE-01"}}, save_path="report.png")
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Application-specific validation reports can be built with the components under `examples/validation_panels.py` and `examples/validation_report.py` without adding those domain concepts to the reusable package.
|
|
217
|
+
|
|
218
|
+
## Analysis and simulation
|
|
219
|
+
|
|
220
|
+
The main public analysis components include:
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
from openeolib import EOAnalyzer, PlumeSimulator, InferenceEngine
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`EOAnalyzer` coordinates provider data and an inference engine. `PlumeSimulator` provides synthetic plume data for testing and demonstrations. `InferenceEngine` defines the interface for custom detection/quantification algorithms.
|
|
227
|
+
|
|
228
|
+
## Providers
|
|
229
|
+
|
|
230
|
+
The package contains provider implementations for openEO, Sentinel-2, Sentinel-5P, ERA5, MSM, and JMA radar rainfall products. Provider-specific dependencies are optional where practical.
|
|
231
|
+
|
|
232
|
+
`XrainProvider` accepts NetCDF and CSV input. If a CSV has no time column, it
|
|
233
|
+
creates a single `time` coordinate containing `NaT` rather than inventing an
|
|
234
|
+
observation timestamp. Callers that require a real observation time must provide
|
|
235
|
+
a time column or pass `time_name=`. This distinction is intentional and prevents
|
|
236
|
+
silent fabrication of temporal metadata.
|
|
237
|
+
|
|
238
|
+
`RadarGpvClient` is a public retrieval utility, not a `BaseProvider` or `Provider`.
|
|
239
|
+
It resolves JMA nationwide composite radar GPV archive URLs, downloads the archive,
|
|
240
|
+
and extracts the target GRIB2 file. `JmaRainProvider` is the dataset-opening provider
|
|
241
|
+
that parses those extracted files into an `xarray.Dataset`. This separation keeps
|
|
242
|
+
network/archive handling distinct from dataset parsing.
|
|
243
|
+
|
|
244
|
+
`ERA5Provider` supports surface fields and pressure-level wind processing, including height-aware interpolation for wind products. Provider modules return data; visualization remains a separate concern.
|
|
245
|
+
|
|
246
|
+
`MSMProvider` retrieves JMA MSM GPV wind data and requires the `jma` extra. The
|
|
247
|
+
public facade exposes `MSMProvider`, `MSM_AVAILABLE`, and
|
|
248
|
+
`MSM_MISSING_DEPENDENCIES` so applications can detect optional support without
|
|
249
|
+
catching an import failure from the core package.
|
|
250
|
+
|
|
251
|
+
For ERA5, CDS credentials and the current CDS API/client configuration are required for live retrieval. Unit tests mock retrieval where network access is unnecessary.
|
|
252
|
+
|
|
253
|
+
## Animation
|
|
254
|
+
|
|
255
|
+
`GridAnimationEngine` in `openeolib.animation` is the generic animation component. Domain-specific wrappers, such as `animate_rain()` in `providers.rain`, configure rainfall-specific variables and color scales before delegating rendering to the generic engine.
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
from openeolib.animation import GridAnimationEngine
|
|
259
|
+
|
|
260
|
+
engine = GridAnimationEngine()
|
|
261
|
+
engine.animate_scalar_field(
|
|
262
|
+
grids=grids,
|
|
263
|
+
lats=lats,
|
|
264
|
+
lons=lons,
|
|
265
|
+
timestamps=timestamps,
|
|
266
|
+
output_path="animation.gif",
|
|
267
|
+
)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Validation examples
|
|
271
|
+
|
|
272
|
+
Validation-only components are kept outside the package:
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from examples.validation_panels import (
|
|
276
|
+
SpectralPanel,
|
|
277
|
+
StatisticalPanel,
|
|
278
|
+
FlagsPanel,
|
|
279
|
+
)
|
|
280
|
+
from examples.validation_report import ValidationReportBuilder
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
These modules are useful for project-specific evaluation but are not exported from `openeolib` and should not be treated as stable library APIs.
|
|
284
|
+
|
|
285
|
+
## Testing
|
|
286
|
+
|
|
287
|
+
Run the test suite with:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
pytest
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The suite is designed to avoid network access for ordinary unit tests. Tests that require optional provider dependencies are skipped when those dependencies are unavailable.
|
|
294
|
+
|
|
295
|
+
The current test suite covers analysis, engines, caching, utilities, ERA5 behavior, MSM behavior, radar GPV handling, rainfall providers, ROC construction, simulation, animation, and reusable visualization panels.
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
OpenEO-LIB is distributed under the Apache License 2.0. See `LICENSE` for the full license text.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# OpenEO-LIB
|
|
2
|
+
|
|
3
|
+
OpenEO-LIB is a Python library for satellite-based Earth observation workflows, including data providers, geospatial analysis, plume simulation, and reusable visualization components.
|
|
4
|
+
|
|
5
|
+
The package is designed so that reusable library functionality is kept separate from application-specific validation and research code.
|
|
6
|
+
|
|
7
|
+
## Current architecture
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
openeolib/
|
|
11
|
+
├── __init__.py
|
|
12
|
+
├── analyzer.py Analysis pipeline orchestration
|
|
13
|
+
├── animation.py Generic scalar-field animation (GridAnimationEngine)
|
|
14
|
+
├── engines.py Inference-engine interfaces and built-ins
|
|
15
|
+
├── eo_cache.py Persistent scientific-data cache (ScienceCacheStore)
|
|
16
|
+
├── eo_types.py Shared data structures and type definitions
|
|
17
|
+
├── eo_utils.py Geospatial and wind utilities
|
|
18
|
+
├── panels.py Generic Matplotlib visualization panels
|
|
19
|
+
├── report.py Generic figure/report composition
|
|
20
|
+
├── roc.py ROC construction
|
|
21
|
+
├── simulator.py Synthetic plume generation
|
|
22
|
+
├── theme.py Theme definition only (Theme, DEFAULT_THEME)
|
|
23
|
+
└── providers/
|
|
24
|
+
├── base.py BaseProvider ABC (raw Dataset retrieval)
|
|
25
|
+
├── provider.py Provider / EOProvider (S2+ERA5+S5P integration)
|
|
26
|
+
├── openeo_client.py openEO connection client
|
|
27
|
+
├── sentinel2.py Sentinel-2 L2A band retrieval
|
|
28
|
+
├── sentinel5p.py Sentinel-5P L2 CH4 column retrieval
|
|
29
|
+
├── era5.py ERA5 wind/pressure/temperature retrieval
|
|
30
|
+
├── msm.py JMA MSM (mesoscale model) wind retrieval
|
|
31
|
+
├── radar_gpv_client.py JMA nationwide composite radar GPV download
|
|
32
|
+
├── rain.py JMA rainfall / XRAIN providers + animate_rain()
|
|
33
|
+
└── _s2_utils.py Sentinel-2 coordinate/time conversion utilities
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Provider responsibilities are deliberately separated. `BaseProvider` and `Provider`
|
|
39
|
+
are independent interfaces with different responsibilities; `Provider` does not
|
|
40
|
+
extend `BaseProvider`. `BaseProvider` is the minimal file/data-opening interface
|
|
41
|
+
for providers that return an `xarray.Dataset` without application-level analysis.
|
|
42
|
+
`Provider` is the higher-level interface used by `EOAnalyzer` and returns an
|
|
43
|
+
`ObservationBundle` for a site and observation time. `EOProvider` implements
|
|
44
|
+
`Provider` for the openEO/Sentinel-2/Sentinel-5P workflow and contains the
|
|
45
|
+
workflow-specific quality and time-alignment logic.
|
|
46
|
+
|
|
47
|
+
The visualization layer (`panels.py`, `theme.py`, `report.py`, `animation.py`)
|
|
48
|
+
is kept domain-agnostic. Domain providers may know the schema and units of
|
|
49
|
+
their own source data, but they do not depend on application-specific
|
|
50
|
+
research pipelines.
|
|
51
|
+
|
|
52
|
+
Likewise, `theme.py` contains only the `Theme` data structure and `DEFAULT_THEME`.
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install openeolib
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Development dependencies are optional and are intended for the private test suite:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install -e ".[dev]"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Optional provider dependencies are grouped by feature:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install -e ".[provider]"
|
|
70
|
+
pip install -e ".[era5]"
|
|
71
|
+
pip install -e ".[jma]"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The core package supports Python 3.9 or later. Provider-specific optional dependencies may have their own Python-version requirements.
|
|
75
|
+
|
|
76
|
+
The JMA extra (`openeolib[jma]`) is required for `MSMProvider`. The module
|
|
77
|
+
`openeolib.providers.msm` remains importable without the optional dependencies,
|
|
78
|
+
but constructing `MSMProvider` raises a clear `ImportError` listing the missing
|
|
79
|
+
dependencies and the installation command. This keeps optional JMA support from
|
|
80
|
+
breaking the core package import.
|
|
81
|
+
|
|
82
|
+
## Public visualization API
|
|
83
|
+
|
|
84
|
+
The reusable visualization API consists of five panels:
|
|
85
|
+
|
|
86
|
+
- `VectorFieldPanel` — arbitrary geospatial vector fields with optional scalar contours.
|
|
87
|
+
- `BasemapPanel` — an already prepared RGB image with an optional marker.
|
|
88
|
+
- `RawBandsPanel` — arbitrary grids of 2D images with a shared scale.
|
|
89
|
+
- `ScalarMapPanel` — arbitrary 2D scalar fields.
|
|
90
|
+
- `DetectionMaskPanel` — boolean, probability, or coverage masks.
|
|
91
|
+
|
|
92
|
+
Example:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import matplotlib.pyplot as plt
|
|
96
|
+
import numpy as np
|
|
97
|
+
from openeolib import ScalarMapPanel
|
|
98
|
+
|
|
99
|
+
field = np.random.default_rng(0).normal(size=(100, 100))
|
|
100
|
+
|
|
101
|
+
fig = plt.figure(figsize=(6, 5))
|
|
102
|
+
gs = fig.add_gridspec(1, 1)[0]
|
|
103
|
+
ScalarMapPanel().draw(
|
|
104
|
+
fig,
|
|
105
|
+
gs,
|
|
106
|
+
field,
|
|
107
|
+
title="Scalar field",
|
|
108
|
+
axis_mode="none",
|
|
109
|
+
)
|
|
110
|
+
fig.savefig("scalar_field.png", dpi=150, bbox_inches="tight")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Vector fields
|
|
114
|
+
|
|
115
|
+
`VectorFieldPanel` is intentionally not ERA5-specific. It accepts latitude/longitude grids and arbitrary vector components. A caller may supply any bounding box through `extent=(west, east, south, north)`.
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from openeolib import VectorFieldPanel
|
|
119
|
+
|
|
120
|
+
panel = VectorFieldPanel(quiver_stride=3)
|
|
121
|
+
panel.draw(
|
|
122
|
+
fig,
|
|
123
|
+
gs,
|
|
124
|
+
lats=lats,
|
|
125
|
+
lons=lons,
|
|
126
|
+
u=u,
|
|
127
|
+
v=v,
|
|
128
|
+
extent=(120, 150, 20, 50),
|
|
129
|
+
title="Wind field",
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
There is no Japan-specific bounding-box constant in the library.
|
|
134
|
+
|
|
135
|
+
### Theme
|
|
136
|
+
|
|
137
|
+
Use `Theme` when a caller needs to customize the visual appearance:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from openeolib import Theme
|
|
141
|
+
|
|
142
|
+
light = Theme(
|
|
143
|
+
bg="#ffffff",
|
|
144
|
+
panel_bg="#ffffff",
|
|
145
|
+
grid_color="#cccccc",
|
|
146
|
+
text_primary="#222222",
|
|
147
|
+
)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
`Theme` does not contain plotting operations or application-specific labels, flags, or data extraction rules.
|
|
151
|
+
|
|
152
|
+
## Generic reports
|
|
153
|
+
|
|
154
|
+
`SiteReportBuilder` composes caller-supplied panels into a single-site report Figure. It does not know about methane, ROC curves, quality flags, or a particular inference engine -- it only handles grid layout, the report title, and file saving.
|
|
155
|
+
|
|
156
|
+
Each entry in `panels` is `(label, factory, height_ratio)`. `factory` is called once with the report's `Theme` and must return a `(fig, gs) -> None` draw function; any panel-specific data (the field to plot, its title, ...) is bound into that closure by the caller, not inspected by `SiteReportBuilder` itself.
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
import numpy as np
|
|
160
|
+
from openeolib import SiteReportBuilder, ScalarMapPanel
|
|
161
|
+
|
|
162
|
+
field = np.random.default_rng(0).normal(size=(100, 100))
|
|
163
|
+
|
|
164
|
+
report = SiteReportBuilder(
|
|
165
|
+
panels=[
|
|
166
|
+
(
|
|
167
|
+
"Scalar field",
|
|
168
|
+
lambda theme: lambda fig, gs: ScalarMapPanel(theme=theme).draw(
|
|
169
|
+
fig, gs, field, title="Scalar field", axis_mode="none",
|
|
170
|
+
),
|
|
171
|
+
1.0,
|
|
172
|
+
),
|
|
173
|
+
],
|
|
174
|
+
report_title="Example report",
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
report.build_site({"site": {"id": "SITE-01"}}, save_path="report.png")
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Application-specific validation reports can be built with the components under `examples/validation_panels.py` and `examples/validation_report.py` without adding those domain concepts to the reusable package.
|
|
181
|
+
|
|
182
|
+
## Analysis and simulation
|
|
183
|
+
|
|
184
|
+
The main public analysis components include:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from openeolib import EOAnalyzer, PlumeSimulator, InferenceEngine
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`EOAnalyzer` coordinates provider data and an inference engine. `PlumeSimulator` provides synthetic plume data for testing and demonstrations. `InferenceEngine` defines the interface for custom detection/quantification algorithms.
|
|
191
|
+
|
|
192
|
+
## Providers
|
|
193
|
+
|
|
194
|
+
The package contains provider implementations for openEO, Sentinel-2, Sentinel-5P, ERA5, MSM, and JMA radar rainfall products. Provider-specific dependencies are optional where practical.
|
|
195
|
+
|
|
196
|
+
`XrainProvider` accepts NetCDF and CSV input. If a CSV has no time column, it
|
|
197
|
+
creates a single `time` coordinate containing `NaT` rather than inventing an
|
|
198
|
+
observation timestamp. Callers that require a real observation time must provide
|
|
199
|
+
a time column or pass `time_name=`. This distinction is intentional and prevents
|
|
200
|
+
silent fabrication of temporal metadata.
|
|
201
|
+
|
|
202
|
+
`RadarGpvClient` is a public retrieval utility, not a `BaseProvider` or `Provider`.
|
|
203
|
+
It resolves JMA nationwide composite radar GPV archive URLs, downloads the archive,
|
|
204
|
+
and extracts the target GRIB2 file. `JmaRainProvider` is the dataset-opening provider
|
|
205
|
+
that parses those extracted files into an `xarray.Dataset`. This separation keeps
|
|
206
|
+
network/archive handling distinct from dataset parsing.
|
|
207
|
+
|
|
208
|
+
`ERA5Provider` supports surface fields and pressure-level wind processing, including height-aware interpolation for wind products. Provider modules return data; visualization remains a separate concern.
|
|
209
|
+
|
|
210
|
+
`MSMProvider` retrieves JMA MSM GPV wind data and requires the `jma` extra. The
|
|
211
|
+
public facade exposes `MSMProvider`, `MSM_AVAILABLE`, and
|
|
212
|
+
`MSM_MISSING_DEPENDENCIES` so applications can detect optional support without
|
|
213
|
+
catching an import failure from the core package.
|
|
214
|
+
|
|
215
|
+
For ERA5, CDS credentials and the current CDS API/client configuration are required for live retrieval. Unit tests mock retrieval where network access is unnecessary.
|
|
216
|
+
|
|
217
|
+
## Animation
|
|
218
|
+
|
|
219
|
+
`GridAnimationEngine` in `openeolib.animation` is the generic animation component. Domain-specific wrappers, such as `animate_rain()` in `providers.rain`, configure rainfall-specific variables and color scales before delegating rendering to the generic engine.
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from openeolib.animation import GridAnimationEngine
|
|
223
|
+
|
|
224
|
+
engine = GridAnimationEngine()
|
|
225
|
+
engine.animate_scalar_field(
|
|
226
|
+
grids=grids,
|
|
227
|
+
lats=lats,
|
|
228
|
+
lons=lons,
|
|
229
|
+
timestamps=timestamps,
|
|
230
|
+
output_path="animation.gif",
|
|
231
|
+
)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Validation examples
|
|
235
|
+
|
|
236
|
+
Validation-only components are kept outside the package:
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
from examples.validation_panels import (
|
|
240
|
+
SpectralPanel,
|
|
241
|
+
StatisticalPanel,
|
|
242
|
+
FlagsPanel,
|
|
243
|
+
)
|
|
244
|
+
from examples.validation_report import ValidationReportBuilder
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
These modules are useful for project-specific evaluation but are not exported from `openeolib` and should not be treated as stable library APIs.
|
|
248
|
+
|
|
249
|
+
## Testing
|
|
250
|
+
|
|
251
|
+
Run the test suite with:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
pytest
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The suite is designed to avoid network access for ordinary unit tests. Tests that require optional provider dependencies are skipped when those dependencies are unavailable.
|
|
258
|
+
|
|
259
|
+
The current test suite covers analysis, engines, caching, utilities, ERA5 behavior, MSM behavior, radar GPV handling, rainfall providers, ROC construction, simulation, animation, and reusable visualization panels.
|
|
260
|
+
|
|
261
|
+
## License
|
|
262
|
+
|
|
263
|
+
OpenEO-LIB is distributed under the Apache License 2.0. See `LICENSE` for the full license text.
|