easy-eo 0.1.0__tar.gz → 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.
Files changed (77) hide show
  1. easy_eo-0.2.0/.gitignore +42 -0
  2. easy_eo-0.2.0/PKG-INFO +176 -0
  3. easy_eo-0.2.0/README.md +117 -0
  4. easy_eo-0.2.0/eeo/__init__.py +41 -0
  5. easy_eo-0.2.0/eeo/_optional.py +65 -0
  6. easy_eo-0.2.0/eeo/_show_versions.py +101 -0
  7. easy_eo-0.2.0/eeo/analysis/__init__.py +33 -0
  8. easy_eo-0.2.0/eeo/analysis/indices.py +766 -0
  9. easy_eo-0.2.0/eeo/analysis/stats.py +327 -0
  10. easy_eo-0.2.0/eeo/common.py +240 -0
  11. easy_eo-0.2.0/eeo/core/__init__.py +27 -0
  12. {easy_eo-0.1.0 → easy_eo-0.2.0}/eeo/core/adapters/__init__.py +3 -2
  13. easy_eo-0.2.0/eeo/core/adapters/base.py +126 -0
  14. {easy_eo-0.1.0 → easy_eo-0.2.0}/eeo/core/adapters/numpy.py +22 -9
  15. {easy_eo-0.1.0 → easy_eo-0.2.0}/eeo/core/adapters/rasterio.py +39 -24
  16. easy_eo-0.2.0/eeo/core/core.py +877 -0
  17. easy_eo-0.2.0/eeo/core/core.pyi +311 -0
  18. easy_eo-0.2.0/eeo/core/decorators.py +116 -0
  19. easy_eo-0.2.0/eeo/core/exceptions.py +63 -0
  20. easy_eo-0.2.0/eeo/core/loader.py +150 -0
  21. easy_eo-0.2.0/eeo/core/plugins.py +23 -0
  22. {easy_eo-0.1.0 → easy_eo-0.2.0}/eeo/core/types.py +2 -0
  23. easy_eo-0.2.0/eeo/datasets/__init__.py +30 -0
  24. easy_eo-0.2.0/eeo/datasets/_cache.py +123 -0
  25. easy_eo-0.2.0/eeo/datasets/_registry.py +174 -0
  26. easy_eo-0.2.0/eeo/datasets/_samples.py +222 -0
  27. easy_eo-0.2.0/eeo/io/__init__.py +18 -0
  28. easy_eo-0.2.0/eeo/io/stac.py +1080 -0
  29. easy_eo-0.2.0/eeo/io/xarray.py +434 -0
  30. easy_eo-0.2.0/eeo/ops/__init__.py +17 -0
  31. easy_eo-0.2.0/eeo/ops/algebra.py +485 -0
  32. easy_eo-0.2.0/eeo/ops/merge.py +256 -0
  33. {easy_eo-0.1.0 → easy_eo-0.2.0}/eeo/preprocessing/__init__.py +4 -2
  34. easy_eo-0.2.0/eeo/preprocessing/clip.py +237 -0
  35. easy_eo-0.2.0/eeo/preprocessing/normalize.py +161 -0
  36. easy_eo-0.2.0/eeo/preprocessing/reproject.py +118 -0
  37. easy_eo-0.2.0/eeo/preprocessing/resample.py +154 -0
  38. easy_eo-0.2.0/eeo/py.typed +0 -0
  39. easy_eo-0.2.0/eeo/viz/__init__.py +17 -0
  40. easy_eo-0.2.0/eeo/viz/plot.py +640 -0
  41. easy_eo-0.2.0/pyproject.toml +261 -0
  42. easy_eo-0.1.0/.gitignore +0 -28
  43. easy_eo-0.1.0/PKG-INFO +0 -114
  44. easy_eo-0.1.0/README.md +0 -67
  45. easy_eo-0.1.0/eeo/__init__.py +0 -20
  46. easy_eo-0.1.0/eeo/analysis/__init__.py +0 -13
  47. easy_eo-0.1.0/eeo/analysis/indices.py +0 -62
  48. easy_eo-0.1.0/eeo/analysis/indices.pyi +0 -35
  49. easy_eo-0.1.0/eeo/analysis/stats.py +0 -127
  50. easy_eo-0.1.0/eeo/analysis/stats.pyi +0 -99
  51. easy_eo-0.1.0/eeo/common.py +0 -35
  52. easy_eo-0.1.0/eeo/core/__init__.py +0 -11
  53. easy_eo-0.1.0/eeo/core/adapters/base.py +0 -94
  54. easy_eo-0.1.0/eeo/core/core.py +0 -198
  55. easy_eo-0.1.0/eeo/core/core.pyi +0 -955
  56. easy_eo-0.1.0/eeo/core/decorators.py +0 -52
  57. easy_eo-0.1.0/eeo/core/loader.py +0 -42
  58. easy_eo-0.1.0/eeo/core/loader.pyi +0 -41
  59. easy_eo-0.1.0/eeo/core/plugins.py +0 -15
  60. easy_eo-0.1.0/eeo/ops/__init__.py +0 -15
  61. easy_eo-0.1.0/eeo/ops/algebra.py +0 -170
  62. easy_eo-0.1.0/eeo/ops/algebra.pyi +0 -175
  63. easy_eo-0.1.0/eeo/ops/merge.py +0 -133
  64. easy_eo-0.1.0/eeo/ops/merge.pyi +0 -46
  65. easy_eo-0.1.0/eeo/preprocessing/clip.py +0 -136
  66. easy_eo-0.1.0/eeo/preprocessing/clip.pyi +0 -83
  67. easy_eo-0.1.0/eeo/preprocessing/normalize.py +0 -50
  68. easy_eo-0.1.0/eeo/preprocessing/normalize.pyi +0 -67
  69. easy_eo-0.1.0/eeo/preprocessing/reproject.py +0 -73
  70. easy_eo-0.1.0/eeo/preprocessing/reproject.pyi +0 -36
  71. easy_eo-0.1.0/eeo/preprocessing/resample.py +0 -81
  72. easy_eo-0.1.0/eeo/preprocessing/resample.pyi +0 -44
  73. easy_eo-0.1.0/eeo/viz/__init__.py +0 -9
  74. easy_eo-0.1.0/eeo/viz/plot.py +0 -284
  75. easy_eo-0.1.0/eeo/viz/plot.pyi +0 -163
  76. easy_eo-0.1.0/pyproject.toml +0 -62
  77. {easy_eo-0.1.0 → easy_eo-0.2.0}/LICENSE +0 -0
@@ -0,0 +1,42 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.pyd
6
+ *.egg-info/
7
+ .env
8
+ .venv
9
+
10
+ # Builds
11
+ build/
12
+ dist/
13
+
14
+ # Data
15
+ data/
16
+ others/
17
+ # ...but the recorded API responses under tests/data are fixtures the suite
18
+ # needs, not scratch data: without them the STAC replay tests fail in CI.
19
+ !tests/data/
20
+
21
+ # Docs
22
+ docs/build/
23
+
24
+ # Tests
25
+ .pytest_cache/
26
+ .ruff_cache/
27
+ .mypy_cache/
28
+ .coverage
29
+ .coverage.*
30
+ coverage.xml
31
+ htmlcov/
32
+
33
+ # IDE
34
+ .vscode/
35
+ .idea/
36
+
37
+ # OS
38
+ .DS_Store
39
+
40
+ # Sample data (downloaded, not tracked)
41
+ sample-data/
42
+ scripts/build_sample_data.py
easy_eo-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,176 @@
1
+ Metadata-Version: 2.4
2
+ Name: easy-eo
3
+ Version: 0.2.0
4
+ Summary: A lightweight Earth Observation utilities library for chainable raster operations
5
+ Project-URL: Homepage, https://github.com/tommy-burns/easy-eo
6
+ Project-URL: Repository, https://github.com/tommy-burns/easy-eo
7
+ Project-URL: Documentation, https://easy-eo.readthedocs.io
8
+ Project-URL: Issues, https://github.com/tommy-burns/easy-eo/issues
9
+ Author: Thomas Burns Botchwey
10
+ License: MIT License
11
+
12
+ Copyright (c) 2025 Thomas Burns Botchwey
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: earth observation,gis,raster,remote sensing
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Science/Research
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.10
38
+ Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Topic :: Scientific/Engineering :: GIS
41
+ Requires-Python: >=3.10
42
+ Requires-Dist: geopandas<2,>=1.1
43
+ Requires-Dist: matplotlib>=3.8
44
+ Requires-Dist: numpy<3,>=1.26
45
+ Requires-Dist: rasterio<2,>=1.4
46
+ Provides-Extra: dev
47
+ Requires-Dist: mypy>=1.10; extra == 'dev'
48
+ Requires-Dist: pre-commit>=3.7; extra == 'dev'
49
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
50
+ Requires-Dist: pytest>=8.0; extra == 'dev'
51
+ Requires-Dist: ruff>=0.6; extra == 'dev'
52
+ Provides-Extra: stac
53
+ Requires-Dist: planetary-computer<2,>=1.0; extra == 'stac'
54
+ Requires-Dist: pystac-client<1,>=0.8; extra == 'stac'
55
+ Provides-Extra: xarray
56
+ Requires-Dist: rioxarray<1,>=0.17; extra == 'xarray'
57
+ Requires-Dist: xarray>=2024.7; extra == 'xarray'
58
+ Description-Content-Type: text/markdown
59
+
60
+ # Easy-EO
61
+
62
+ <p align="center">
63
+ <img src=".github/assets/eeo_logo.png" alt="Easy-EO logo" width="200">
64
+ </p>
65
+
66
+ [![CI](https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml/badge.svg)](https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml)
67
+ [![codecov](https://codecov.io/gh/Tommy-Burns/easy-eo/branch/main/graph/badge.svg)](https://codecov.io/gh/Tommy-Burns/easy-eo)
68
+ [![PyPI](https://img.shields.io/pypi/v/easy-eo.svg)](https://pypi.org/project/easy-eo/)
69
+ [![Python versions](https://img.shields.io/pypi/pyversions/easy-eo.svg)](https://pypi.org/project/easy-eo/)
70
+ [![Documentation Status](https://readthedocs.org/projects/easy-eo/badge/?version=latest)](https://easy-eo.readthedocs.io/en/latest/?badge=latest)
71
+ [![License: MIT](https://img.shields.io/github/license/Tommy-Burns/easy-eo)](https://github.com/Tommy-Burns/easy-eo/blob/main/LICENSE)
72
+
73
+ Easy-EO is a lightweight, extensible Python library for raster-based Earth Observation (EO) analysis which allows for chainable raster processing, algebra, and visualization.
74
+ It provides high-level abstractions over libraries such as Rasterio, NumPy, and Matplotlib, enabling users to perform common earth-observation analyses and visualization tasks efficiently, without dealing with the underlying complexity.
75
+
76
+ ---
77
+
78
+ ## Features
79
+
80
+ - Raster operations with spatial awareness
81
+ - Algebraic operations (`add`, `subtract`, `multiply`, `divide`)
82
+ - Spectral index library (`ndvi`, `ndwi`, `ndmi`, `ndbi`, `evi`, `savi`)
83
+ - Resampling, reprojection, and alignment
84
+ - Clip rasters using vectors or bounding boxes
85
+ - Normalization (min-max, percentile, z-score)
86
+ - Named bands - address bands by name anywhere an index is accepted
87
+ - STAC data access - search and load Sentinel-2/Landsat scenes, reading only the area of interest
88
+ - xarray interoperability (`to_xarray()` / `from_xarray()`)
89
+ - Hosted sample dataset, one call away (`eeo.datasets.load_sample_dataset()`)
90
+ - Visualization helpers (bands, composites, histograms)
91
+ - Backend-aware design (currently NumPy and Rasterio)
92
+
93
+ ---
94
+
95
+ ## Installation
96
+
97
+ ```bash
98
+ conda create -n env_name python=3.10
99
+ conda activate env_name
100
+ pip install easy-eo
101
+ ```
102
+
103
+ ## Quick Example
104
+ ```python
105
+ from eeo import load_raster
106
+
107
+ ds_nir = load_raster("path/to/nir.tif")
108
+ ds_red = load_raster("path/to/red.tif")
109
+
110
+ # Chainable example: clip -> resample -> compute NDVI -> multiply
111
+ result = (
112
+ ds_nir.clip_raster_with_bbox((0, 0, 1000, 1000))
113
+ .resample(scale_factor=2)
114
+ .normalized_difference(ds_red)
115
+ .multiply(100)
116
+ )
117
+ ```
118
+
119
+ ***Or try with a hosted sample data***
120
+ ```python
121
+ from eeo.datasets import load_sample_dataset
122
+ from eeo import load_raster
123
+
124
+ sd = load_sample_dataset()
125
+
126
+ scene = load_raster(sd.sentinel2_cog_stacked) # red, green, blue, nir bands
127
+
128
+ ndvi = scene.ndvi(red="red", nir="nir")
129
+ ndvi.plot_raster()
130
+ ```
131
+
132
+ ## Tutorials
133
+
134
+ Sixteen runnable notebooks live in [`examples/`](examples/README.md), from first
135
+ install through to complete analyses (flood mapping, drought stress, land cover,
136
+ terrain). Each one opens in Colab with no local setup — the first cell installs
137
+ Easy-EO when it detects Colab:
138
+
139
+ | | |
140
+ | --- | --- |
141
+ | [Quickstart: NDVI](examples/00_getting_started/02_quickstart_ndvi.ipynb) — open a scene, compute an index, plot it | [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Tommy-Burns/easy-eo/blob/main/examples/00_getting_started/02_quickstart_ndvi.ipynb) |
142
+ | [Search and load from STAC](examples/02_data_access/02_stac_search_and_load.ipynb) — find real scenes, read them over HTTP | [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Tommy-Burns/easy-eo/blob/main/examples/02_data_access/02_stac_search_and_load.ipynb) |
143
+ | [Flood mapping with NDWI](examples/03_real_world/01_flood_mapping_ndwi.ipynb) — Pakistan 2022, before/after, area affected | [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Tommy-Burns/easy-eo/blob/main/examples/03_real_world/01_flood_mapping_ndwi.ipynb) |
144
+
145
+ The full index, including what each notebook covers, is in
146
+ [`examples/README.md`](examples/README.md) and in the
147
+ [tutorials page](https://easy-eo.readthedocs.io/en/latest/tutorials.html) of the
148
+ documentation.
149
+
150
+ ## Supported Backends
151
+ | Backend | Description |
152
+ |----------|------------------------------------------------------|
153
+ | NumPy | Fast, in-memory arrays without I/O |
154
+ | Rasterio | Full geospatial support (CRS, transform, resampling) |
155
+
156
+
157
+ ## Documentation
158
+
159
+ 📚 Full documentation is available at:
160
+
161
+ 👉 [Easy-EO Documentation](https://easy-eo.readthedocs.io/en/latest/index.html)
162
+
163
+ ## Project Status
164
+ 🚧 Active development
165
+ The API is stabilizing but may change before v1.0.
166
+
167
+ ## Contributing
168
+ Contributions are welcome!
169
+ - Bug reports
170
+ - Feature requests
171
+ - Documentation improvements
172
+
173
+ Please open an issue or pull request on GitHub.
174
+
175
+ ## License
176
+ MIT License © 2025 Thomas Burns Botchwey
@@ -0,0 +1,117 @@
1
+ # Easy-EO
2
+
3
+ <p align="center">
4
+ <img src=".github/assets/eeo_logo.png" alt="Easy-EO logo" width="200">
5
+ </p>
6
+
7
+ [![CI](https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml/badge.svg)](https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml)
8
+ [![codecov](https://codecov.io/gh/Tommy-Burns/easy-eo/branch/main/graph/badge.svg)](https://codecov.io/gh/Tommy-Burns/easy-eo)
9
+ [![PyPI](https://img.shields.io/pypi/v/easy-eo.svg)](https://pypi.org/project/easy-eo/)
10
+ [![Python versions](https://img.shields.io/pypi/pyversions/easy-eo.svg)](https://pypi.org/project/easy-eo/)
11
+ [![Documentation Status](https://readthedocs.org/projects/easy-eo/badge/?version=latest)](https://easy-eo.readthedocs.io/en/latest/?badge=latest)
12
+ [![License: MIT](https://img.shields.io/github/license/Tommy-Burns/easy-eo)](https://github.com/Tommy-Burns/easy-eo/blob/main/LICENSE)
13
+
14
+ Easy-EO is a lightweight, extensible Python library for raster-based Earth Observation (EO) analysis which allows for chainable raster processing, algebra, and visualization.
15
+ It provides high-level abstractions over libraries such as Rasterio, NumPy, and Matplotlib, enabling users to perform common earth-observation analyses and visualization tasks efficiently, without dealing with the underlying complexity.
16
+
17
+ ---
18
+
19
+ ## Features
20
+
21
+ - Raster operations with spatial awareness
22
+ - Algebraic operations (`add`, `subtract`, `multiply`, `divide`)
23
+ - Spectral index library (`ndvi`, `ndwi`, `ndmi`, `ndbi`, `evi`, `savi`)
24
+ - Resampling, reprojection, and alignment
25
+ - Clip rasters using vectors or bounding boxes
26
+ - Normalization (min-max, percentile, z-score)
27
+ - Named bands - address bands by name anywhere an index is accepted
28
+ - STAC data access - search and load Sentinel-2/Landsat scenes, reading only the area of interest
29
+ - xarray interoperability (`to_xarray()` / `from_xarray()`)
30
+ - Hosted sample dataset, one call away (`eeo.datasets.load_sample_dataset()`)
31
+ - Visualization helpers (bands, composites, histograms)
32
+ - Backend-aware design (currently NumPy and Rasterio)
33
+
34
+ ---
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ conda create -n env_name python=3.10
40
+ conda activate env_name
41
+ pip install easy-eo
42
+ ```
43
+
44
+ ## Quick Example
45
+ ```python
46
+ from eeo import load_raster
47
+
48
+ ds_nir = load_raster("path/to/nir.tif")
49
+ ds_red = load_raster("path/to/red.tif")
50
+
51
+ # Chainable example: clip -> resample -> compute NDVI -> multiply
52
+ result = (
53
+ ds_nir.clip_raster_with_bbox((0, 0, 1000, 1000))
54
+ .resample(scale_factor=2)
55
+ .normalized_difference(ds_red)
56
+ .multiply(100)
57
+ )
58
+ ```
59
+
60
+ ***Or try with a hosted sample data***
61
+ ```python
62
+ from eeo.datasets import load_sample_dataset
63
+ from eeo import load_raster
64
+
65
+ sd = load_sample_dataset()
66
+
67
+ scene = load_raster(sd.sentinel2_cog_stacked) # red, green, blue, nir bands
68
+
69
+ ndvi = scene.ndvi(red="red", nir="nir")
70
+ ndvi.plot_raster()
71
+ ```
72
+
73
+ ## Tutorials
74
+
75
+ Sixteen runnable notebooks live in [`examples/`](examples/README.md), from first
76
+ install through to complete analyses (flood mapping, drought stress, land cover,
77
+ terrain). Each one opens in Colab with no local setup — the first cell installs
78
+ Easy-EO when it detects Colab:
79
+
80
+ | | |
81
+ | --- | --- |
82
+ | [Quickstart: NDVI](examples/00_getting_started/02_quickstart_ndvi.ipynb) — open a scene, compute an index, plot it | [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Tommy-Burns/easy-eo/blob/main/examples/00_getting_started/02_quickstart_ndvi.ipynb) |
83
+ | [Search and load from STAC](examples/02_data_access/02_stac_search_and_load.ipynb) — find real scenes, read them over HTTP | [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Tommy-Burns/easy-eo/blob/main/examples/02_data_access/02_stac_search_and_load.ipynb) |
84
+ | [Flood mapping with NDWI](examples/03_real_world/01_flood_mapping_ndwi.ipynb) — Pakistan 2022, before/after, area affected | [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Tommy-Burns/easy-eo/blob/main/examples/03_real_world/01_flood_mapping_ndwi.ipynb) |
85
+
86
+ The full index, including what each notebook covers, is in
87
+ [`examples/README.md`](examples/README.md) and in the
88
+ [tutorials page](https://easy-eo.readthedocs.io/en/latest/tutorials.html) of the
89
+ documentation.
90
+
91
+ ## Supported Backends
92
+ | Backend | Description |
93
+ |----------|------------------------------------------------------|
94
+ | NumPy | Fast, in-memory arrays without I/O |
95
+ | Rasterio | Full geospatial support (CRS, transform, resampling) |
96
+
97
+
98
+ ## Documentation
99
+
100
+ 📚 Full documentation is available at:
101
+
102
+ 👉 [Easy-EO Documentation](https://easy-eo.readthedocs.io/en/latest/index.html)
103
+
104
+ ## Project Status
105
+ 🚧 Active development
106
+ The API is stabilizing but may change before v1.0.
107
+
108
+ ## Contributing
109
+ Contributions are welcome!
110
+ - Bug reports
111
+ - Feature requests
112
+ - Documentation improvements
113
+
114
+ Please open an issue or pull request on GitHub.
115
+
116
+ ## License
117
+ MIT License © 2025 Thomas Burns Botchwey
@@ -0,0 +1,41 @@
1
+ """Easy-EO: chainable raster processing for Earth Observation.
2
+
3
+ A lightweight library of chainable raster operations, algebra, and
4
+ visualization built on rasterio, NumPy, GeoPandas, and matplotlib.
5
+ """
6
+
7
+ from . import datasets
8
+ from ._show_versions import show_versions
9
+ from .analysis import *
10
+ from .core import (
11
+ AlignmentError,
12
+ BackendError,
13
+ CRSMismatchError,
14
+ EEOError,
15
+ MissingDependencyError,
16
+ ValidationError,
17
+ load_array,
18
+ load_raster,
19
+ )
20
+ from .core.adapters import *
21
+ from .io import from_xarray, stac_search
22
+ from .ops import *
23
+ from .preprocessing import *
24
+ from .viz import *
25
+
26
+ __all__ = [
27
+ "datasets",
28
+ "load_raster",
29
+ "load_array",
30
+ "stac_search",
31
+ "from_xarray",
32
+ "show_versions",
33
+ "EEOError",
34
+ "ValidationError",
35
+ "CRSMismatchError",
36
+ "AlignmentError",
37
+ "BackendError",
38
+ "MissingDependencyError",
39
+ ]
40
+
41
+ __version__ = "0.2.0"
@@ -0,0 +1,65 @@
1
+ """Import helper for the packages behind Easy-EO's optional extras.
2
+
3
+ Heavier capabilities — STAC data access, xarray interop, the lazy backend —
4
+ live behind optional extras so that a plain ``pip install easy-eo`` stays
5
+ small. The modules implementing them import their third-party packages through
6
+ :func:`import_optional`, which turns a missing package into a
7
+ :class:`~eeo.MissingDependencyError` naming the exact install command instead
8
+ of a bare ``ModuleNotFoundError``.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import importlib
14
+ from types import ModuleType
15
+
16
+ from .core.exceptions import MissingDependencyError
17
+
18
+
19
+ def import_optional(module: str, *, extra: str, purpose: str) -> ModuleType:
20
+ """Import a module provided by an optional extra.
21
+
22
+ Parameters
23
+ ----------
24
+ module : str
25
+ Importable module name (e.g. ``"pystac_client"``), not the
26
+ distribution name.
27
+ extra : str
28
+ Name of the Easy-EO extra that provides the module (e.g. ``"stac"``),
29
+ used to build the ``pip install`` hint.
30
+ purpose : str
31
+ Short description of the feature needing the module (e.g. ``"STAC
32
+ search"``), used to open the error message.
33
+
34
+ Returns
35
+ -------
36
+ ModuleType
37
+ The imported module.
38
+
39
+ Raises
40
+ ------
41
+ MissingDependencyError
42
+ If the module is not installed. The message names the feature, the
43
+ missing package, and the ``pip install 'easy-eo[<extra>]'`` command
44
+ that provides it.
45
+
46
+ Examples
47
+ --------
48
+ >>> from eeo._optional import import_optional
49
+ >>> np = import_optional("numpy", extra="stac", purpose="STAC search")
50
+ >>> np.__name__
51
+ 'numpy'
52
+ """
53
+ try:
54
+ return importlib.import_module(module)
55
+ except ModuleNotFoundError as err:
56
+ # A ModuleNotFoundError raised *inside* the optional package (one of
57
+ # its own dependencies missing) is a different problem; report it as-is
58
+ # rather than blaming the package the user did install.
59
+ if err.name is not None and err.name.split(".")[0] != module.split(".")[0]:
60
+ raise
61
+ raise MissingDependencyError(
62
+ f"{purpose} requires the optional '{module}' package, which is not "
63
+ f"installed. Install the '{extra}' extra with: "
64
+ f"pip install 'easy-eo[{extra}]'"
65
+ ) from err
@@ -0,0 +1,101 @@
1
+ """Environment reporting for bug reports and support requests."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import platform
6
+ from importlib.metadata import PackageNotFoundError, version
7
+
8
+ # Optional dependencies that back the planned optional extras. Reported so a
9
+ # bug report shows which extras are active. Maps the display label to the
10
+ # installed distribution name.
11
+ _OPTIONAL_DISTRIBUTIONS = {
12
+ "xarray": "xarray",
13
+ "rioxarray": "rioxarray",
14
+ "dask": "dask",
15
+ "pystac-client": "pystac-client",
16
+ "planetary-computer": "planetary-computer",
17
+ }
18
+
19
+
20
+ def _distribution_version(name: str) -> str:
21
+ """Return an installed distribution's version, or ``"not installed"``.
22
+
23
+ Parameters
24
+ ----------
25
+ name : str
26
+ Distribution (PyPI) name to look up.
27
+
28
+ Returns
29
+ -------
30
+ str
31
+ The installed version string, or ``"not installed"`` if the
32
+ distribution is not present.
33
+ """
34
+ try:
35
+ return version(name)
36
+ except PackageNotFoundError:
37
+ return "not installed"
38
+
39
+
40
+ def _get_versions() -> dict[str, str]:
41
+ """Collect version information for Easy-EO and its dependencies.
42
+
43
+ Returns
44
+ -------
45
+ dict of str to str
46
+ Ordered mapping of component name to version string. Covers easy-eo,
47
+ the Python runtime and platform, the core geospatial stack (rasterio,
48
+ GDAL, numpy, geopandas, matplotlib), and each optional-extra
49
+ dependency (reported as ``"not installed"`` when absent).
50
+ """
51
+ # Imported lazily to keep `import eeo` light; all are hard dependencies.
52
+ import geopandas
53
+ import matplotlib
54
+ import numpy
55
+ import rasterio
56
+
57
+ gdal_version = getattr(rasterio, "__gdal_version__", None) or rasterio.gdal_version()
58
+
59
+ info = {
60
+ "easy-eo": _distribution_version("easy-eo"),
61
+ "python": platform.python_version(),
62
+ "OS": f"{platform.system()} {platform.release()}",
63
+ "rasterio": rasterio.__version__,
64
+ "GDAL": str(gdal_version),
65
+ "numpy": numpy.__version__,
66
+ "geopandas": geopandas.__version__,
67
+ "matplotlib": matplotlib.__version__,
68
+ }
69
+ for label, dist in _OPTIONAL_DISTRIBUTIONS.items():
70
+ info[label] = _distribution_version(dist)
71
+ return info
72
+
73
+
74
+ def show_versions() -> None:
75
+ """Print Easy-EO, Python, and dependency version information.
76
+
77
+ Writes a human-readable report to standard output covering easy-eo, the
78
+ Python runtime and operating system, the core geospatial stack (rasterio,
79
+ GDAL, numpy, geopandas, matplotlib), and the optional-extra dependencies
80
+ (each shown as its version or ``not installed``). Intended for pasting
81
+ into bug reports.
82
+
83
+ Returns
84
+ -------
85
+ None
86
+ The report is printed; nothing is returned.
87
+
88
+ Examples
89
+ --------
90
+ >>> import eeo
91
+ >>> eeo.show_versions() # doctest: +SKIP
92
+ Easy-EO version information
93
+ ...
94
+ """
95
+ info = _get_versions()
96
+ width = max(len(name) for name in info)
97
+
98
+ lines = ["Easy-EO version information", "=========================="]
99
+ for name, value in info.items():
100
+ lines.append(f"{name:<{width}} : {value}")
101
+ print("\n".join(lines))
@@ -0,0 +1,33 @@
1
+ """Analysis operations: spectral indices and pixel statistics."""
2
+
3
+ from .indices import (
4
+ evi,
5
+ ndbi,
6
+ ndmi,
7
+ ndvi,
8
+ ndwi,
9
+ normalized_difference,
10
+ savi,
11
+ )
12
+ from .stats import (
13
+ extract_value_at_coordinate,
14
+ get_maximum_pixel,
15
+ get_mean_pixel,
16
+ get_minimum_pixel,
17
+ get_percentile_pixel,
18
+ )
19
+
20
+ __all__ = [
21
+ "extract_value_at_coordinate",
22
+ "normalized_difference",
23
+ "ndvi",
24
+ "ndwi",
25
+ "ndmi",
26
+ "ndbi",
27
+ "evi",
28
+ "savi",
29
+ "get_minimum_pixel",
30
+ "get_percentile_pixel",
31
+ "get_mean_pixel",
32
+ "get_maximum_pixel",
33
+ ]