eo-processor 0.2.0__cp312-cp312-manylinux_2_34_x86_64.whl

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.

Potentially problematic release.


This version of eo-processor might be problematic. Click here for more details.

@@ -0,0 +1,93 @@
1
+ """
2
+ High-performance Earth Observation processing library.
3
+
4
+ This library provides Rust-accelerated functions for common EO/geospatial
5
+ computations that can be used within XArray/Dask workflows to bypass Python's GIL.
6
+ """
7
+
8
+ from ._core import (
9
+ normalized_difference as _normalized_difference,
10
+ ndvi as _ndvi,
11
+ ndwi as _ndwi,
12
+ enhanced_vegetation_index as _enhanced_vegetation_index,
13
+ median as _median,
14
+ )
15
+
16
+ __version__ = "0.1.0"
17
+
18
+ __all__ = [
19
+ "normalized_difference",
20
+ "ndvi",
21
+ "ndwi",
22
+ "enhanced_vegetation_index",
23
+ "evi",
24
+ "median",
25
+ "composite",
26
+ ]
27
+
28
+
29
+ def normalized_difference(a, b):
30
+ """
31
+ Compute normalized difference (a - b) / (a + b) using the Rust core.
32
+ Supports 1D or 2D numpy float arrays; dimensional dispatch occurs in Rust.
33
+ """
34
+ return _normalized_difference(a, b)
35
+
36
+
37
+ def ndvi(nir, red):
38
+ """
39
+ Compute NDVI = (NIR - Red) / (NIR + Red) via Rust core (1D or 2D).
40
+ """
41
+ return _ndvi(nir, red)
42
+
43
+
44
+ def ndwi(green, nir):
45
+ """
46
+ Compute NDWI = (Green - NIR) / (Green + NIR) via Rust core (1D or 2D).
47
+ """
48
+ return _ndwi(green, nir)
49
+
50
+
51
+ def enhanced_vegetation_index(nir, red, blue):
52
+ """
53
+ Compute EVI = 2.5 * (NIR - Red) / (NIR + 6*Red - 7.5*Blue + 1) via Rust core (1D or 2D).
54
+ """
55
+ return _enhanced_vegetation_index(nir, red, blue)
56
+
57
+
58
+ # Alias
59
+ evi = enhanced_vegetation_index
60
+
61
+
62
+ def median(arr, skip_na=True):
63
+ """
64
+ Compute median over the time axis of a 1D, 2D, 3D, or 4D array.
65
+
66
+ Parameters
67
+ ----------
68
+ arr : numpy.ndarray
69
+ Input array.
70
+ skip_na : bool, optional
71
+ Whether to skip NaN values, by default True. If False, the median
72
+ of any pixel containing a NaN will be NaN.
73
+ """
74
+ return _median(arr, skip_na=skip_na)
75
+
76
+
77
+ def composite(arr, method="median", **kwargs):
78
+ """
79
+ Compute a composite over the time axis of a 1D, 2D, 3D, or 4D array.
80
+
81
+ Parameters
82
+ ----------
83
+ arr : numpy.ndarray
84
+ Input array.
85
+ method : str, optional
86
+ The compositing method to use, by default "median".
87
+ **kwargs
88
+ Additional keyword arguments to pass to the compositing function.
89
+ """
90
+ if method == "median":
91
+ return median(arr, **kwargs)
92
+ else:
93
+ raise ValueError(f"Unknown composite method: {method}")
@@ -0,0 +1,19 @@
1
+ """Type stubs for eo_processor"""
2
+
3
+ import numpy as np
4
+ from numpy.typing import NDArray
5
+
6
+ __version__: str
7
+
8
+ def normalized_difference(
9
+ a: NDArray[np.float64], b: NDArray[np.float64]
10
+ ) -> NDArray[np.float64]: ...
11
+ def ndvi(nir: NDArray[np.float64], red: NDArray[np.float64]) -> NDArray[np.float64]: ...
12
+ def ndwi(
13
+ green: NDArray[np.float64], nir: NDArray[np.float64]
14
+ ) -> NDArray[np.float64]: ...
15
+ def enhanced_vegetation_index(
16
+ nir: NDArray[np.float64], red: NDArray[np.float64], blue: NDArray[np.float64]
17
+ ) -> NDArray[np.float64]: ...
18
+
19
+ evi = enhanced_vegetation_index
@@ -0,0 +1,288 @@
1
+ Metadata-Version: 2.4
2
+ Name: eo-processor
3
+ Version: 0.2.0
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: 3.8
7
+ Classifier: Programming Language :: Python :: 3.9
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Topic :: Scientific/Engineering :: GIS
13
+ Requires-Dist: maturin>=1.9.6
14
+ Requires-Dist: numpy>=1.20.0
15
+ Requires-Dist: tox>=4.25.0
16
+ Requires-Dist: pytest>=7.0 ; extra == 'dev'
17
+ Requires-Dist: maturin>=1.0,<2.0 ; extra == 'dev'
18
+ Requires-Dist: dask[array]>=2023.0.0 ; extra == 'dask'
19
+ Requires-Dist: xarray>=2023.0.0 ; extra == 'dask'
20
+ Provides-Extra: dev
21
+ Provides-Extra: dask
22
+ License-File: LICENSE
23
+ Summary: High-performance Rust UDFs for Earth Observation processing
24
+ Keywords: earth-observation,gis,remote-sensing,ndvi,dask,xarray,rust,pyo3,numpy
25
+ Author: Ben Smith
26
+ Requires-Python: >=3.8
27
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
28
+
29
+ # eo-processor
30
+
31
+ [![Coverage](./coverage-badge.svg)](#test-coverage)
32
+
33
+ High-performance Rust UDFs for Earth Observation (EO) processing with Python bindings.
34
+
35
+ ## Overview
36
+
37
+ `eo-processor` is a framework that provides Rust-based User Defined Functions (UDFs) for common Earth Observation and geospatial computations. These functions can be used within local and remote (Dask/Kubernetes) workflows, leveraging PyO3 to create highly efficient and optimized operations.
38
+
39
+ The Rust implementation bypasses Python's Global Interpreter Lock (GIL), making it ideal for:
40
+ - Long-running computations on large satellite imagery
41
+ - Parallel processing with Dask
42
+ - XArray `apply_ufunc` and `map_blocks` workflows
43
+ - CPU-intensive geospatial operations
44
+
45
+ ## Features
46
+
47
+ - **High Performance**: Rust-accelerated computations that bypass Python's GIL
48
+ - **Easy Integration**: Works seamlessly with NumPy, XArray, and Dask
49
+ - **Common EO Indices**: Pre-implemented functions for NDVI, NDWI, and generic normalized differences
50
+ - **Type Safe**: Full type hints for Python IDE support
51
+ - **Flexible**: Supports both 1D and 2D arrays with automatic dimension detection
52
+
53
+ ## Installation
54
+
55
+ ### From Source
56
+
57
+ Requirements:
58
+ - Python 3.8+
59
+ - Rust toolchain (install from [rustup.rs](https://rustup.rs/))
60
+
61
+ ```bash
62
+ # Install maturin for building
63
+ pip install maturin
64
+
65
+ # Build and install the package
66
+ maturin develop --release
67
+
68
+ # Or build wheel for distribution
69
+ maturin build --release
70
+ pip install target/wheels/*.whl
71
+ ```
72
+
73
+ ## Usage
74
+
75
+ ### Basic Usage
76
+
77
+ ```python
78
+ import numpy as np
79
+ from eo_processor import ndvi, ndwi, normalized_difference
80
+
81
+ # Compute NDVI from NIR and Red bands
82
+ nir = np.array([0.8, 0.7, 0.6])
83
+ red = np.array([0.2, 0.1, 0.3])
84
+ ndvi_result = ndvi(nir, red)
85
+ print(ndvi_result) # [0.6, 0.75, 0.33333333]
86
+
87
+ # Note: the functions in `eo_processor` now return NumPy arrays directly.
88
+ # They no longer return a (array, dims) tuple or any dims metadata.
89
+
90
+ # Works with 2D arrays (images)
91
+ nir_image = np.random.rand(1000, 1000)
92
+ red_image = np.random.rand(1000, 1000)
93
+ ndvi_image = ndvi(nir_image, red_image)
94
+
95
+ # Compute NDWI (water index)
96
+ green = np.array([0.3, 0.4, 0.5])
97
+ ndwi_result = ndwi(green, nir)
98
+
99
+ # Generic normalized difference: (a - b) / (a + b)
100
+ custom_index = normalized_difference(band_a, band_b)
101
+ ```
102
+
103
+ ### XArray Integration
104
+
105
+ ```python
106
+ import xarray as xr
107
+ from eo_processor import ndvi
108
+
109
+ # Create XArray DataArrays
110
+ nir = xr.DataArray(nir_data, dims=["y", "x"])
111
+ red = xr.DataArray(red_data, dims=["y", "x"])
112
+
113
+ # Apply using xr.apply_ufunc
114
+ ndvi_result = xr.apply_ufunc(
115
+ ndvi,
116
+ nir,
117
+ red,
118
+ dask="parallelized",
119
+ output_dtypes=[float],
120
+ )
121
+ ```
122
+
123
+ ### Dask Integration (Parallel Processing)
124
+
125
+ ```python
126
+ import dask.array as da
127
+ import xarray as xr
128
+ from eo_processor import ndvi
129
+
130
+ # Create large Dask arrays (chunked for parallel processing)
131
+ nir_dask = da.random.random((10000, 10000), chunks=(1000, 1000))
132
+ red_dask = da.random.random((10000, 10000), chunks=(1000, 1000))
133
+
134
+ # Wrap in XArray
135
+ nir_xr = xr.DataArray(nir_dask, dims=["y", "x"])
136
+ red_xr = xr.DataArray(red_dask, dims=["y", "x"])
137
+
138
+ # Compute NDVI (bypasses GIL, enables true parallelism)
139
+ ndvi_result = xr.apply_ufunc(
140
+ ndvi,
141
+ nir_xr,
142
+ red_xr,
143
+ dask="parallelized",
144
+ output_dtypes=[float],
145
+ )
146
+
147
+ # Compute result
148
+ ndvi_computed = ndvi_result.compute()
149
+ ```
150
+
151
+ ### Using map_blocks with Dask
152
+
153
+ ```python
154
+ import dask.array as da
155
+ from eo_processor import ndvi
156
+
157
+ nir_dask = da.random.random((5000, 5000), chunks=(500, 500))
158
+ red_dask = da.random.random((5000, 5000), chunks=(500, 500))
159
+
160
+ # Apply to blocks (each block processed independently)
161
+ ndvi_result = da.map_blocks(
162
+ ndvi,
163
+ nir_dask,
164
+ red_dask,
165
+ dtype=np.float64,
166
+ )
167
+
168
+ result = ndvi_result.compute()
169
+ ```
170
+
171
+ ## Available Functions
172
+
173
+ ### Normalized Difference Functions
174
+
175
+ - `normalized_difference(a, b)`: Generic normalized difference `(a - b) / (a + b)`
176
+ - `normalized_difference_1d(a, b)`: 1D version
177
+ - `normalized_difference_2d(a, b)`: 2D version
178
+
179
+ ### Vegetation Indices
180
+
181
+ - `ndvi(nir, red)`: Normalized Difference Vegetation Index
182
+ - `ndvi_1d(nir, red)`: 1D version
183
+ - `ndvi_2d(nir, red)`: 2D version
184
+
185
+ ### Water Indices
186
+
187
+ - `ndwi(green, nir)`: Normalized Difference Water Index
188
+ - `ndwi_1d(green, nir)`: 1D version
189
+ - `ndwi_2d(green, nir)`: 2D version
190
+
191
+ ## Performance
192
+
193
+ The Rust implementation provides significant performance improvements over pure Python/NumPy, especially for large arrays:
194
+
195
+ ```python
196
+ import numpy as np
197
+ import time
198
+ from eo_processor import ndvi
199
+
200
+ # Large array
201
+ nir = np.random.rand(5000, 5000)
202
+ red = np.random.rand(5000, 5000)
203
+
204
+ # Rust implementation
205
+ start = time.time()
206
+ result_rust = ndvi(nir, red)
207
+ time_rust = time.time() - start
208
+
209
+ # NumPy implementation
210
+ start = time.time()
211
+ result_numpy = (nir - red) / (nir + red)
212
+ time_numpy = time.time() - start
213
+
214
+ print(f"Rust: {time_rust:.4f}s")
215
+ print(f"NumPy: {time_numpy:.4f}s")
216
+ print(f"Speedup: {time_numpy/time_rust:.2f}x")
217
+ ```
218
+
219
+ ## Development
220
+
221
+ ### Building
222
+
223
+ ```bash
224
+ # Development build
225
+ maturin develop
226
+
227
+ # Release build
228
+ maturin develop --release
229
+ ```
230
+
231
+ ### Testing
232
+
233
+ ```bash
234
+ # Run Rust tests
235
+ cargo test
236
+
237
+ # Run Python tests (if pytest is installed)
238
+ pytest
239
+ ```
240
+
241
+ ### Running Examples
242
+
243
+ ```bash
244
+ # Basic usage examples
245
+ python examples/basic_usage.py
246
+
247
+ # XArray/Dask examples (requires: pip install eo-processor[dask])
248
+ python examples/xarray_dask_usage.py
249
+ ```
250
+
251
+ ## Why Rust + PyO3?
252
+
253
+ 1. **Performance**: Rust provides C-level performance with memory safety
254
+ 2. **GIL-Free**: Rust code releases the Python GIL, enabling true parallelism
255
+ 3. **Type Safety**: Compile-time guarantees reduce runtime errors
256
+ 4. **Easy Integration**: PyO3 makes it seamless to call Rust from Python
257
+ 5. **Modern Tooling**: Cargo and maturin provide excellent development experience
258
+
259
+ ## Use Cases
260
+
261
+ - Processing large satellite imagery datasets (Sentinel, Landsat, etc.)
262
+ - Real-time vegetation monitoring using NDVI
263
+ - Water body detection using NDWI
264
+ - Custom spectral indices computation
265
+ - Distributed processing on Dask/Kubernetes clusters
266
+ - Time-series analysis of Earth Observation data
267
+
268
+ ## License
269
+
270
+ MIT License - see LICENSE file for details
271
+
272
+ ## Contributing
273
+
274
+ Contributions are welcome! Please feel free to submit issues or pull requests.
275
+
276
+ ## Citation
277
+
278
+ If you use this library in your research, please cite:
279
+
280
+ ```bibtex
281
+ @software{eo_processor,
282
+ title = {eo-processor: High-performance Rust UDFs for Earth Observation},
283
+ author = {Ben},
284
+ year = {2025},
285
+ url = {https://github.com/BnJam/eo-processor}
286
+ }
287
+ ```
288
+
@@ -0,0 +1,7 @@
1
+ eo_processor-0.2.0.dist-info/METADATA,sha256=x2HtqNfyza5k3j8ZUNvhkXgTAxZONc2QFjGn54lEf1s,7544
2
+ eo_processor-0.2.0.dist-info/WHEEL,sha256=6SMSE7o6zBbAY_fbEHyYtLCyWUTWMuzw9qWPgdJzl40,109
3
+ eo_processor-0.2.0.dist-info/licenses/LICENSE,sha256=noiI0CshqVqEhzZuL0pDreo0XgmzA3P69UjdcQAXGuc,1060
4
+ eo_processor/__init__.py,sha256=LK59qvugof6T_veNozmgvMWY-ajxn04zCXvEzsaBxrw,2277
5
+ eo_processor/__init__.pyi,sha256=ayia_pbvDt3d30CBPMhQl-PtjkEGjUPcBfFgN1ulU4k,576
6
+ eo_processor/_core.cpython-312-x86_64-linux-gnu.so,sha256=_fvMoKte9rgmRLz8gA9YqEfshGHkzQzsB1Et5hoo-c4,591656
7
+ eo_processor-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.10.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp312-cp312-manylinux_2_34_x86_64
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ben
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.