PyGeoFetch 1.0.0__tar.gz → 1.0.1__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 (81) hide show
  1. pygeofetch-1.0.1/PKG-INFO +588 -0
  2. pygeofetch-1.0.1/PyGeoFetch.egg-info/PKG-INFO +588 -0
  3. pygeofetch-1.0.1/README.md +503 -0
  4. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/__init__.py +2 -2
  5. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/main.py +2 -2
  6. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/models/satellite_data.py +1 -1
  7. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/sentinel_hub.py +1 -1
  8. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pyproject.toml +1 -1
  9. pygeofetch-1.0.0/PKG-INFO +0 -1022
  10. pygeofetch-1.0.0/PyGeoFetch.egg-info/PKG-INFO +0 -1022
  11. pygeofetch-1.0.0/README.md +0 -937
  12. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/LICENSE +0 -0
  13. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/PyGeoFetch.egg-info/SOURCES.txt +0 -0
  14. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/PyGeoFetch.egg-info/dependency_links.txt +0 -0
  15. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/PyGeoFetch.egg-info/entry_points.txt +0 -0
  16. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/PyGeoFetch.egg-info/not-zip-safe +0 -0
  17. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/PyGeoFetch.egg-info/requires.txt +0 -0
  18. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/PyGeoFetch.egg-info/top_level.txt +0 -0
  19. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/__init__.py +0 -0
  20. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/auth_commands.py +0 -0
  21. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/config_commands.py +0 -0
  22. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/download_commands.py +0 -0
  23. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/index_commands.py +0 -0
  24. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/pipeline_process_commands.py +0 -0
  25. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/postprocess_commands.py +0 -0
  26. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/preprocess_commands.py +0 -0
  27. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/sar_commands.py +0 -0
  28. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/cli/search_commands.py +0 -0
  29. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/config/__init__.py +0 -0
  30. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/config/defaults.yaml +0 -0
  31. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/config/settings.py +0 -0
  32. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/core/__init__.py +0 -0
  33. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/core/authenticator.py +0 -0
  34. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/core/cache_manager.py +0 -0
  35. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/core/downloader.py +0 -0
  36. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/core/engine.py +0 -0
  37. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/core/scheduler.py +0 -0
  38. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/core/searcher.py +0 -0
  39. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/models/__init__.py +0 -0
  40. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/models/download_task.py +0 -0
  41. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/models/search_query.py +0 -0
  42. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/models/user_auth.py +0 -0
  43. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/processing/__init__.py +0 -0
  44. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/processing/base.py +0 -0
  45. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/processing/batch.py +0 -0
  46. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/processing/indices.py +0 -0
  47. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/processing/pipeline.py +0 -0
  48. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/processing/postprocessor.py +0 -0
  49. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/processing/preprocessor.py +0 -0
  50. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/processing/sar.py +0 -0
  51. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/__init__.py +0 -0
  52. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/airbus_oneatlas.py +0 -0
  53. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/alaska_satellite_facility.py +0 -0
  54. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/aws_earth.py +0 -0
  55. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/base.py +0 -0
  56. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/copernicus.py +0 -0
  57. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/digitalglobe.py +0 -0
  58. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/earth_explorer_additional.py +0 -0
  59. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/element84.py +0 -0
  60. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/esa_scihub.py +0 -0
  61. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/geoserver_generic.py +0 -0
  62. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/google_earth_engine.py +0 -0
  63. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/inpe_cbers.py +0 -0
  64. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/isro_bhuvan.py +0 -0
  65. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/jaxa_earth.py +0 -0
  66. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/maxar_gbdx.py +0 -0
  67. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/nasa_earthdata.py +0 -0
  68. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/nasa_earthdata_cloud.py +0 -0
  69. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/noaa_big_data.py +0 -0
  70. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/opentopography.py +0 -0
  71. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/planet.py +0 -0
  72. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/planetary_computer.py +0 -0
  73. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/terrabotics.py +0 -0
  74. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/providers/usgs.py +0 -0
  75. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/utils/__init__.py +0 -0
  76. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/utils/file_utils.py +0 -0
  77. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/utils/geo_utils.py +0 -0
  78. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/utils/logging_setup.py +0 -0
  79. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/utils/retry_handler.py +0 -0
  80. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/pygeofetch/utils/validators.py +0 -0
  81. {pygeofetch-1.0.0 → pygeofetch-1.0.1}/setup.cfg +0 -0
@@ -0,0 +1,588 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyGeoFetch
3
+ Version: 1.0.1
4
+ Summary: Universal satellite data pipeline — unified access to 22+ providers
5
+ Author: PyGeoFetch Contributors
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 SatelliteBridge Contributors
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/pygeofetch/PyGeoFetch
29
+ Project-URL: Documentation, https://pygeofetch.readthedocs.io
30
+ Project-URL: Repository, https://github.com/pygeofetch/PyGeoFetch
31
+ Project-URL: Bug Tracker, https://github.com/pygeofetch/PyGeoFetch/issues
32
+ Keywords: satellite,remote-sensing,GIS,earth-observation,geospatial
33
+ Classifier: Development Status :: 5 - Production/Stable
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.9
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Topic :: Scientific/Engineering :: GIS
42
+ Requires-Python: >=3.9
43
+ Description-Content-Type: text/markdown
44
+ License-File: LICENSE
45
+ Requires-Dist: httpx>=0.27
46
+ Requires-Dist: click>=8.1
47
+ Requires-Dist: pydantic>=2.5
48
+ Requires-Dist: pydantic-settings>=2.1
49
+ Requires-Dist: rich>=13.7
50
+ Requires-Dist: PyYAML>=6.0
51
+ Requires-Dist: cryptography>=42.0
52
+ Requires-Dist: keyring>=24.3
53
+ Requires-Dist: aiofiles>=23.2
54
+ Requires-Dist: tenacity>=8.2
55
+ Requires-Dist: python-dateutil>=2.9
56
+ Requires-Dist: tqdm>=4.66
57
+ Requires-Dist: requests>=2.31
58
+ Requires-Dist: anyio>=4.2
59
+ Requires-Dist: boto3>=1.34
60
+ Requires-Dist: click-completion>=0.5
61
+ Provides-Extra: geo
62
+ Requires-Dist: rasterio>=1.3; extra == "geo"
63
+ Requires-Dist: geopandas>=0.14; extra == "geo"
64
+ Requires-Dist: pyarrow>=15.0; extra == "geo"
65
+ Requires-Dist: shapely>=2.0; extra == "geo"
66
+ Requires-Dist: pyproj>=3.6; extra == "geo"
67
+ Provides-Extra: cloud
68
+ Requires-Dist: boto3>=1.34; extra == "cloud"
69
+ Requires-Dist: pystac>=1.9; extra == "cloud"
70
+ Provides-Extra: schedule
71
+ Requires-Dist: croniter>=2.0; extra == "schedule"
72
+ Provides-Extra: dev
73
+ Requires-Dist: pytest>=8.0; extra == "dev"
74
+ Requires-Dist: pytest-cov>=4.1; extra == "dev"
75
+ Requires-Dist: pytest-mock>=3.12; extra == "dev"
76
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
77
+ Requires-Dist: vcrpy>=6.0; extra == "dev"
78
+ Requires-Dist: black>=24.0; extra == "dev"
79
+ Requires-Dist: ruff>=0.3; extra == "dev"
80
+ Requires-Dist: mypy>=1.8; extra == "dev"
81
+ Requires-Dist: bump2version>=1.0; extra == "dev"
82
+ Provides-Extra: all
83
+ Requires-Dist: PyGeoFetch[cloud,dev,geo,schedule]; extra == "all"
84
+ Dynamic: license-file
85
+
86
+
87
+ <div align="center">
88
+
89
+ <!-- <img src="https://appiahkubis14.github.io/portfolio/logo/samuel_logo_dark.svg" alt="PyGeoFetch Logo" width="200"/> -->
90
+
91
+ # PyGeoFetch 🛰️
92
+
93
+ [![PyPI version](https://badge.fury.io/py/pygeofetch.svg)](https://pypi.org/project/pygeofetch/)
94
+ [![Python Versions](https://img.shields.io/pypi/pyversions/pygeofetch.svg)](https://pypi.org/project/pygeofetch/)
95
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
96
+ [![Tests](https://github.com/appiahkubis14/pygeofetch/actions/workflows/tests.yml/badge.svg)](https://github.com/appiahkubis14/pygeofetch/actions)
97
+ [![Coverage](https://codecov.io/gh/appiahkubis14/pygeofetch/branch/main/graph/badge.svg)](https://codecov.io/gh/appiahkubis14/pygeofetch)
98
+
99
+ **Universal satellite data pipeline + geospatial processing platform — unified access to 22+ satellite repositories, 17 spectral indices, full SAR processing, and chainable YAML pipelines. One CLI, one Python API.**
100
+
101
+ </div>
102
+
103
+ ---
104
+
105
+ ## 📖 Introduction
106
+
107
+ PyGeoFetch is a **production-ready satellite data acquisition and processing framework** that provides unified, authenticated access to 22+ Earth observation repositories — including Sentinel, Landsat, Planet, Maxar, Airbus, Copernicus, USGS, NASA, JAXA, and more — through a single consistent CLI and Python API.
108
+
109
+ The package abstracts away the authentication complexity, API fragmentation, and format inconsistencies of individual satellite providers, and adds a complete geospatial processing engine on top. PyGeoFetch provides six core capabilities:
110
+
111
+ 1. **Authenticated access** to 22+ providers, with secure credential storage via system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service).
112
+ 2. **Unified federated search** across all providers, returning standardized STAC 1.0 GeoJSON, GeoParquet, or CSV results sortable by cloud cover, date, or relevance score.
113
+ 3. **Resilient parallel downloads** with band selection, checksum verification, resume support, exponential backoff, and atomic writes.
114
+ 4. **Preprocessing engine** — atmospheric correction, cloud masking, reprojection, resampling, pan-sharpening, mosaicking, and compositing.
115
+ 5. **17 spectral indices** — NDVI, EVI, SAVI, NDWI, MNDWI, NDBI, TCT, PCA, LST, Albedo, dNBR, GLCM texture, and more.
116
+ 6. **YAML pipeline orchestration** with cron scheduling, batch processing, and full execution history — enabling repeatable, automated geospatial workflows.
117
+
118
+ ---
119
+
120
+ ## 📝 Statement of Need
121
+
122
+ Accessing satellite data at scale is surprisingly fragmented. Each provider — USGS, Copernicus, Planet, Maxar, NASA — exposes a different authentication scheme, a different query API, a different download protocol, and a different file format. Researchers and engineers working across multiple providers must maintain a patchwork of custom scripts, scattered credentials, and ad hoc download logic, making workflows difficult to reproduce and brittle to maintain.
123
+
124
+ Existing tools address parts of this problem: EODAG supports several providers but lacks pipeline orchestration and commercial coverage; `pystac-client` handles STAC-compliant endpoints only; `sentinelsat` is Sentinel-specific. No single tool covers the full breadth of providers, processing, and automation needed for operational geospatial workflows.
125
+
126
+ | Feature | PyGeoFetch | EODAG | pystac-client | satpy | sentinelsat |
127
+ |---|---|---|---|---|---|
128
+ | **Providers** | **22+** | 10+ | STAC only | Limited | Sentinel only |
129
+ | **Processing Engine** | ✅ Full | ❌ | ❌ | Partial | ❌ |
130
+ | **Spectral Indices** | ✅ 17+ | ❌ | ❌ | ❌ | ❌ |
131
+ | **SAR Processing** | ✅ | ❌ | ❌ | ✅ | ❌ |
132
+ | **YAML Pipelines** | ✅ | ❌ | ❌ | ❌ | ❌ |
133
+ | **Auth Management** | ✅ Keyring | Partial | ❌ | ❌ | ✅ |
134
+ | **STAC 1.0 Output** | ✅ Native | ❌ | ✅ | ❌ | ❌ |
135
+ | **Cron Scheduling** | ✅ | ❌ | ❌ | ❌ | ❌ |
136
+ | **Commercial Providers** | ✅ Planet/Maxar | ❌ | ❌ | ❌ | ❌ |
137
+
138
+ ---
139
+
140
+ ## 🚀 Key Features
141
+
142
+ ### 🛰️ 22+ Satellite Providers
143
+
144
+ **Open access — no login required (10):**
145
+
146
+ | Provider ID | Satellites | Capabilities |
147
+ |---|---|---|
148
+ | `planetary_computer` | Sentinel-1/2, Landsat 8/9, MODIS, NAIP, ALOS DEM | STAC, SAR |
149
+ | `aws_earth` | Sentinel-2 COG, Landsat C2, NAIP | STAC |
150
+ | `element84` | Sentinel-2 L2A, Landsat C2, Sentinel-1 RTC, COP-DEM | STAC, SAR |
151
+ | `noaa_big_data` | GOES-16/17/18, NEXRAD radar | Weather |
152
+ | `esa_scihub` | Sentinel-1/2/3/5P (public mirrors) | SAR |
153
+ | `jaxa_earth` | ALOS 30m DSM, PALSAR-2 | SAR |
154
+ | `isro_bhuvan` | ResourceSat-2/2A (5.8m), Cartosat-1 (2.5m) | — |
155
+ | `inpe_cbers` | CBERS-4, CBERS-4A | — |
156
+ | `digitalglobe` | WorldView open disaster response | <1m VHR |
157
+ | `geoserver_generic` | Any OGC WMS/WFS/WCS endpoint | Generic |
158
+
159
+ **Authenticated providers (12):** USGS · Copernicus CDSE · NASA Earthdata · NASA Earthdata Cloud · Alaska SAR Facility · OpenTopography · Planet Labs · Sentinel Hub · Maxar GBDX · Airbus OneAtlas · Google Earth Engine · TerraBotics
160
+
161
+ ### 🔍 Unified Search
162
+ - Federated query across multiple providers simultaneously with deduplicated results
163
+ - Filter by bbox, geometry file, date range, cloud cover, resolution, processing level, and CQL2 expressions
164
+ - 7 output formats: `table` · `json` · `stac` · `geojson` · `geoparquet` · `csv` · `ids`
165
+
166
+ ### 📥 Resilient Downloads
167
+ - Adaptive parallel downloads with configurable concurrency and real-time progress
168
+ - Band selection (e.g. `B02,B03,B04` → download 150 MB instead of 600 MB full scene)
169
+ - SHA256 checksum verification, resume support, exponential-backoff retries
170
+ - Atomic writes — no partial files ever written to disk
171
+
172
+ ### ⚙️ Preprocessing Engine (`client.preprocess`)
173
+
174
+ | Method | Description |
175
+ |---|---|
176
+ | `atmos()` | Atmospheric correction: DOS1, DOS2, Sen2Cor, FLAASH, 6S, iCOR |
177
+ | `cloud_mask()` | Cloud masking: SCL, FMask, threshold, NDSI |
178
+ | `cloud_fill()` | Fill cloud gaps from time-series |
179
+ | `topo_correct()` | Topographic correction: cosine, Minnaert, C-correction |
180
+ | `clip()` | Clip to bounding box or GeoJSON polygon |
181
+ | `reproject()` | Reproject to any CRS (EPSG:4326, UTM, etc.) |
182
+ | `resample()` | Change resolution: nearest, bilinear, cubic, lanczos |
183
+ | `pansharpen()` | Pan-sharpening: Brovey, IHS, Gram-Schmidt |
184
+ | `tile()` | Split into overlapping tiles for AI inference |
185
+ | `mosaic()` | Merge scenes: first, last, min, max |
186
+ | `composite()` | Multi-temporal: median, mean, max, best-pixel |
187
+
188
+ ### 📊 Spectral Indices (`client.indices`)
189
+
190
+ | Index | Formula | Use Case |
191
+ |---|---|---|
192
+ | `ndvi` | (NIR−Red)/(NIR+Red) | Vegetation health |
193
+ | `evi` | G·(NIR−Red)/(NIR+C1·Red−C2·Blue+L) | Dense canopy |
194
+ | `savi` | (NIR−Red)/(NIR+Red+L)·(1+L) | Sparse vegetation |
195
+ | `ndwi` | (Green−NIR)/(Green+NIR) | Water bodies |
196
+ | `mndwi` | (Green−SWIR1)/(Green+SWIR1) | Urban water |
197
+ | `ndbi` | (SWIR1−NIR)/(SWIR1+NIR) | Built-up areas |
198
+ | `ndsi` | (Green−SWIR1)/(Green+SWIR1) | Snow / ice |
199
+ | `ndmi` | (NIR−SWIR1)/(NIR+SWIR1) | Canopy moisture |
200
+ | `nbr` / `dnbr` | (NIR−SWIR2)/(NIR+SWIR2) | Burn severity |
201
+ | `tct` | Matrix coefficients | Brightness, Greenness, Wetness |
202
+ | `pca` | Eigen decomposition | Dimensionality reduction |
203
+ | `texture` | GLCM | Contrast, homogeneity, energy |
204
+ | `lst` | Thermal → Kelvin / Celsius | Land surface temperature |
205
+ | `albedo` | Narrowband→broadband (Liang 2001) | Surface reflectance |
206
+ | `band_math` | Arbitrary expression on B[i] | Custom indices |
207
+
208
+ ### 🔧 Post-Processing (`client.post`)
209
+
210
+ `vectorize` → `smooth` → `regularize` → `zonal_stats` → `buffer` → `centroids` → `compress` → `cog`
211
+
212
+ ### 📡 SAR Processing (`client.sar`)
213
+
214
+ | Method | Description |
215
+ |---|---|
216
+ | `despeckle()` | Lee, Enhanced Lee, Frost, Gamma MAP, Boxcar |
217
+ | `calibrate()` | DN → sigma0 / gamma0 / beta0 (dB or linear) |
218
+ | `flood_map()` | Threshold or change-based flood detection |
219
+ | `coherence()` | Interferometric coherence (stable surface / change) |
220
+
221
+ ### 📋 YAML Pipeline Orchestration
222
+ - Define search → filter → download → process → export workflows in YAML
223
+ - Chain any preprocessing, index, or post-processing step
224
+ - Schedule with cron expressions, run history, and retry
225
+ - 6 built-in templates: `ndvi` · `change_detection` · `flood_map` · `urban_mapping` · `sar_analysis` · `land_cover`
226
+
227
+ ### 🔐 Security by Default
228
+ - Credentials stored in system keyring — never logged or written to disk in plaintext
229
+ - TLS 1.2+ enforced, SSL verification always on, no telemetry, no analytics
230
+
231
+ ---
232
+
233
+ ## 📦 Installation
234
+
235
+ ```bash
236
+ # Core — free providers work immediately, no extras needed
237
+ pip install PyGeoFetch
238
+
239
+ # + Raster/vector processing (rasterio, geopandas, shapely)
240
+ pip install "PyGeoFetch[geo]"
241
+
242
+ # + Cloud provider S3 access
243
+ pip install "PyGeoFetch[cloud]"
244
+
245
+ # + Cron scheduling
246
+ pip install "PyGeoFetch[schedule]"
247
+
248
+ # Everything
249
+ pip install "PyGeoFetch[all]"
250
+ ```
251
+
252
+ **Requirements:** Python 3.9+
253
+
254
+ Verify your installation:
255
+ ```bash
256
+ PyGeoFetch doctor
257
+ # ✓ Python 3.11 ✓ httpx ✓ pydantic ✓ rich
258
+ # ✓ AWS Earth Search: HTTP 200
259
+ # ✓ Planetary Computer: HTTP 200
260
+ # ✓ Element 84: HTTP 200
261
+ ```
262
+
263
+ ---
264
+
265
+ ## ⚡ Quick Start
266
+
267
+ ### CLI
268
+
269
+ ```bash
270
+ # Add credentials (free providers need no credentials at all)
271
+ PyGeoFetch auth add usgs --username USER --password PASS
272
+ PyGeoFetch auth add copernicus --username email@example.com --password PASS
273
+ PyGeoFetch auth add planet --api-key YOUR_KEY
274
+
275
+ # Search (free — no login)
276
+ PyGeoFetch search run \
277
+ --bbox "-74.1,40.6,-73.7,40.9" \
278
+ --start-date 2024-01-01 \
279
+ --cloud-cover 0-15 \
280
+ --providers planetary_computer,aws_earth \
281
+ --format table \
282
+ --output results.geojson
283
+
284
+ # Download with band selection
285
+ PyGeoFetch download run \
286
+ --from-search results.geojson \
287
+ --output ./data/ \
288
+ --parallel 4 \
289
+ --bands "B02,B03,B04" \
290
+ --max-items 3
291
+
292
+ # Download with full post-processing chain
293
+ PyGeoFetch download run \
294
+ --from-search results.geojson \
295
+ --output ./data/ \
296
+ --parallel 4 \
297
+ --verify-checksum \
298
+ --post-process "unzip,reproject:EPSG:4326,compress:lzw,cog"
299
+ ```
300
+
301
+ ### Python API
302
+
303
+ ```python
304
+ from pathlib import Path
305
+ from pygeofetch import PyGeoFetch
306
+ from pygeofetch.models.search_query import SearchQuery, BoundingBox
307
+ from pygeofetch.models.download_task import DownloadOptions
308
+
309
+ client = PyGeoFetch()
310
+
311
+ # Credentials
312
+ client.add_credentials("usgs", username="user", password="pass")
313
+ client.add_credentials("copernicus", username="email@example.com", password="pass")
314
+ client.add_credentials("planet", api_key="PL_KEY")
315
+
316
+ # Search
317
+ results = client.search(
318
+ SearchQuery(
319
+ bbox=BoundingBox.from_string("-74.1,40.6,-73.7,40.9"),
320
+ start_date="2024-01-01",
321
+ end_date="2024-06-01",
322
+ cloud_cover_max=20,
323
+ sort_by="cloud_cover",
324
+ sort_ascending=True,
325
+ ),
326
+ providers=["usgs", "copernicus", "planetary_computer", "aws_earth"],
327
+ )
328
+
329
+ # Download
330
+ downloads = client.download(
331
+ results[:5],
332
+ destination=Path("./data/"),
333
+ options=DownloadOptions(
334
+ parallel=4,
335
+ verify_checksum=True,
336
+ resume=True,
337
+ bands=["B02", "B03", "B04"],
338
+ ),
339
+ )
340
+
341
+ for dr in downloads:
342
+ if dr.success:
343
+ print(f"✓ {dr.data_id} ({dr.bytes_downloaded // 1024 // 1024:.1f} MB)")
344
+ else:
345
+ print(f"✗ {dr.data_id}: {dr.error}")
346
+
347
+ # Process
348
+ ndvi = client.indices.ndvi(red="B04.tif", nir="B08.tif")
349
+ clipped = client.preprocess.clip("scene.tif", bbox=(-74.1, 40.6, -73.7, 40.9))
350
+ cog = client.post.cog("ndvi.tif", compress="deflate")
351
+
352
+ # End-to-end pipeline
353
+ result = (
354
+ client.pipeline("sentinel2-ndvi")
355
+ .atmos(method="dos1")
356
+ .cloud_mask(method="scl", scl_band="SCL.tif")
357
+ .clip(bbox=(-74.1, 40.6, -73.7, 40.9))
358
+ .ndvi(red="B04.tif", nir="B08.tif")
359
+ .vectorize(threshold=0.3)
360
+ .cog(compress="deflate")
361
+ .run(input="scene.tif", output_dir="./processed/")
362
+ )
363
+ print(f"Pipeline: {result.success} in {result.duration_seconds:.1f}s")
364
+ ```
365
+
366
+ ### YAML Pipeline
367
+
368
+ ```yaml
369
+ name: weekly-sentinel2-ndvi
370
+ schedule: "0 6 * * 1" # Every Monday 06:00 UTC
371
+ description: Weekly NDVI monitoring — search, download, process, export
372
+
373
+ steps:
374
+ - search:
375
+ providers: [copernicus, aws_earth, planetary_computer]
376
+ bbox: "-74.1,40.6,-73.7,40.9"
377
+ date_range: last_7_days
378
+ cloud_cover: "0-10"
379
+ max_results: 20
380
+
381
+ - filter:
382
+ expression: "data.cloud_cover < 5"
383
+
384
+ - download:
385
+ parallel: 4
386
+ output: ./raw/
387
+ verify_checksum: true
388
+ bands: [B04, B08]
389
+
390
+ - ndvi:
391
+ red: B04.tif
392
+ nir: B08.tif
393
+
394
+ - vectorize:
395
+ threshold: 0.3
396
+ format: geojson
397
+
398
+ - cog:
399
+ compress: deflate
400
+ ```
401
+
402
+ ```bash
403
+ # Validate without running
404
+ PyGeoFetch proc-pipeline validate weekly-sentinel2.yaml
405
+
406
+ # Run once
407
+ PyGeoFetch proc-pipeline run weekly-sentinel2.yaml --input scene.tif
408
+
409
+ # Schedule (recurring)
410
+ PyGeoFetch pipeline schedule weekly-sentinel2.yaml --name "ndvi-weekly"
411
+
412
+ # Generate a starter template
413
+ PyGeoFetch proc-pipeline template ndvi
414
+ PyGeoFetch proc-pipeline template flood_map
415
+ PyGeoFetch proc-pipeline template change_detection
416
+ ```
417
+
418
+ ---
419
+
420
+ ## 🖥️ Complete CLI Reference
421
+
422
+ ```
423
+ SYSTEM
424
+ PyGeoFetch doctor diagnose installation + connectivity
425
+ PyGeoFetch status [--json] provider and cache overview
426
+ PyGeoFetch version
427
+
428
+ AUTH
429
+ PyGeoFetch auth add PROVIDER [--username U] [--password P] [--api-key K]
430
+ PyGeoFetch auth login PROVIDER interactive prompt
431
+ PyGeoFetch auth list [--json]
432
+ PyGeoFetch auth test PROVIDER
433
+ PyGeoFetch auth remove PROVIDER [--yes]
434
+ PyGeoFetch auth export [--output FILE]
435
+
436
+ PROVIDERS
437
+ PyGeoFetch providers list [--auth|--no-auth] [--capabilities sar] [--json]
438
+ PyGeoFetch providers info PROVIDER
439
+ PyGeoFetch providers search "TERM"
440
+
441
+ SEARCH
442
+ PyGeoFetch search run \
443
+ --bbox "minlon,minlat,maxlon,maxlat" or --geometry-file area.geojson
444
+ --start-date YYYY-MM-DD --end-date YYYY-MM-DD
445
+ --cloud-cover 0-20
446
+ --providers aws_earth,copernicus
447
+ --satellites Sentinel-2
448
+ --sort-by cloud_cover --sort-order asc
449
+ --max-results 50
450
+ --cql2 "eo:cloud_cover < 5"
451
+ --format table|json|stac|geojson|geoparquet|csv|ids
452
+ --output results.geojson
453
+ --no-cache --timeout 60
454
+
455
+ DOWNLOAD
456
+ PyGeoFetch download run \
457
+ --from-search results.geojson
458
+ --output ./data/
459
+ --parallel 4 --retry 5
460
+ --bands "B02,B03,B04"
461
+ --verify-checksum --resume
462
+ --bandwidth-limit 10MB
463
+ --post-process "reproject:EPSG:4326,compress:lzw,cog"
464
+ --on-failure skip
465
+ --max-items 10
466
+ --notify webhook:https://hooks.slack.com/YOUR/WEBHOOK
467
+ --json
468
+
469
+ PREPROCESSING
470
+ PyGeoFetch preprocess atmos scene.tif --method dos1|sen2cor|flaash|6s
471
+ PyGeoFetch preprocess cloud-mask scene.tif --method scl|fmask|threshold
472
+ PyGeoFetch preprocess cloud-fill cloudy.tif t1.tif t2.tif
473
+ PyGeoFetch preprocess topo-correct scene.tif dem.tif --method cosine
474
+ PyGeoFetch preprocess clip scene.tif --bbox "..." | --geometry file.geojson
475
+ PyGeoFetch preprocess reproject scene.tif --crs EPSG:4326
476
+ PyGeoFetch preprocess resample scene.tif --resolution 30
477
+ PyGeoFetch preprocess pansharpen pan.tif ms.tif --method brovey
478
+ PyGeoFetch preprocess mosaic s1.tif s2.tif --method first|last|min|max
479
+ PyGeoFetch preprocess composite *.tif --method median|mean|max|best_pixel
480
+ PyGeoFetch preprocess tile scene.tif --tile-size 512 --overlap 64
481
+
482
+ SPECTRAL INDICES
483
+ PyGeoFetch index ndvi --red B04.tif --nir B08.tif
484
+ PyGeoFetch index evi --blue B02.tif --red B04.tif --nir B08.tif
485
+ PyGeoFetch index savi --red B04.tif --nir B08.tif --soil-l 0.5
486
+ PyGeoFetch index ndwi --green B03.tif --nir B08.tif
487
+ PyGeoFetch index mndwi --green B03.tif --swir1 B11.tif
488
+ PyGeoFetch index ndbi --nir B08.tif --swir1 B11.tif
489
+ PyGeoFetch index ndsi --green B03.tif --swir1 B11.tif
490
+ PyGeoFetch index ndmi --nir B08.tif --swir1 B11.tif
491
+ PyGeoFetch index nbr --nir B08.tif --swir2 B12.tif
492
+ PyGeoFetch index dnbr --pre-nir B08.tif --pre-swir2 B12.tif \
493
+ --post-nir B08_post.tif --post-swir2 B12_post.tif
494
+ PyGeoFetch index tct --blue B02.tif --green B03.tif --red B04.tif \
495
+ --nir B08.tif --swir1 B11.tif --swir2 B12.tif
496
+ PyGeoFetch index pca B02.tif B03.tif B04.tif B08.tif --components 3
497
+ PyGeoFetch index texture B08.tif --window 7 --features contrast,homogeneity
498
+ PyGeoFetch index lst B10.tif --emissivity 0.97 --sensor landsat8
499
+ PyGeoFetch index albedo B02.tif B03.tif B04.tif B08.tif B11.tif B12.tif
500
+ PyGeoFetch index band-math B04.tif B08.tif --expr "(B[1]-B[0])/(B[1]+B[0]+1e-6)"
501
+ PyGeoFetch index stack B02.tif B03.tif B04.tif
502
+
503
+ POST-PROCESSING
504
+ PyGeoFetch post vectorize ndvi.tif --threshold 0.3 --format geojson
505
+ PyGeoFetch post smooth polygons.geojson --tolerance 0.5
506
+ PyGeoFetch post regularize buildings.geojson
507
+ PyGeoFetch post zonal-stats ndvi.tif parcels.geojson --output stats.csv
508
+ PyGeoFetch post buffer roads.geojson --distance 15
509
+ PyGeoFetch post centroids polygons.geojson
510
+ PyGeoFetch post geometry-metrics polygons.geojson
511
+ PyGeoFetch post compress scene.tif --method lzw|deflate|zstd
512
+ PyGeoFetch post cog scene.tif --compress deflate --blocksize 512
513
+
514
+ SAR PROCESSING
515
+ PyGeoFetch sar despeckle sar.tif --filter lee|enhanced_lee|frost|gamma --window 7
516
+ PyGeoFetch sar calibrate sar.tif --output-type sigma0|gamma0|beta0 --db
517
+ PyGeoFetch sar flood-map post.tif --threshold -15 [--reference pre.tif]
518
+ PyGeoFetch sar coherence slc1.tif slc2.tif --window 7
519
+
520
+ PROCESSING PIPELINES
521
+ PyGeoFetch proc-pipeline template ndvi|change_detection|flood_map|urban_mapping|...
522
+ PyGeoFetch proc-pipeline validate FILE
523
+ PyGeoFetch proc-pipeline run FILE [--input scene.tif] [--output-dir ./out/]
524
+
525
+ DATA PIPELINES (search + download)
526
+ PyGeoFetch pipeline run|validate|schedule|list-scheduled|unschedule|history
527
+
528
+ CACHE
529
+ PyGeoFetch cache stats|clear|ttl [show|set N]|location|prune --max-size 1GB
530
+
531
+ CONFIG
532
+ PyGeoFetch config show|get KEY|set KEY VALUE|path|reset
533
+
534
+ COMPLETION
535
+ PyGeoFetch --install-completion bash|zsh|fish
536
+ ```
537
+
538
+ ---
539
+
540
+ ## 📚 Notebooks
541
+
542
+ | Notebook | Topics |
543
+ |---|---|
544
+ | `01_getting_started.ipynb` | Install, doctor, first search, first download |
545
+ | `02_authentication_and_providers.ipynb` | All 22 providers, credentials, capability filters |
546
+ | `03_advanced_search.ipynb` | Federated search, CQL2 filters, 7 output formats, caching |
547
+ | `04_download_and_postprocessing.ipynb` | Band selection, parallel downloads, post-processing |
548
+ | `05_pipelines_and_scheduling.ipynb` | YAML pipelines, scheduling, Python builder API |
549
+ | `06_real_world_workflows.ipynb` | NDVI time series, change detection, multi-sensor fusion |
550
+ | `07_copernicus_and_authenticated_providers.ipynb` | Copernicus, USGS, NASA, Planet, ASF, OpenTopography |
551
+ | `08_cli_complete_reference.ipynb` | Every CLI command with runnable examples |
552
+ | `09_processing_complete.ipynb` | Full processing engine: preprocessing, indices, SAR, pipelines |
553
+
554
+ ```bash
555
+ cd notebooks/
556
+ jupyter lab
557
+ ```
558
+
559
+ ---
560
+
561
+ ## 📋 Documentation
562
+
563
+ Full documentation: **https://appiahkubis14.github.io/pygeofetch-docs/**
564
+
565
+ Covers: CLI reference · provider auth guides · pipeline configuration · post-processing catalogue · contributing guide.
566
+
567
+ ---
568
+
569
+ ## 🤝 Contributing
570
+
571
+ Contributions of all kinds are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines.
572
+
573
+ Good first issues include implementing stub providers to full API integrations, improving test coverage, and adding new post-processing actions.
574
+
575
+ ```bash
576
+ git clone https://github.com/appiahkubis14/PyGeoFetch
577
+ cd PyGeoFetch
578
+ pip install -e ".[dev,all]"
579
+ pytest tests/unit/ -v
580
+ ```
581
+
582
+ ---
583
+
584
+ ## 📄 License
585
+
586
+ PyGeoFetch is free and open source software, licensed under the [MIT License](LICENSE).
587
+
588
+ © 2026 PyGeoFetch Contributors. Part of the **PyGeoVision** platform — [PyGeoFetch](https://github.com/appiahkubis14/PyGeoFetch) (data + processing) + [GeoAI](https://opengeoai.org) (AI) = complete Earth observation pipeline.