PyGeoFetch 1.9.3__tar.gz → 1.9.4__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 (138) hide show
  1. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/CHANGELOG.md +4 -4
  2. {pygeofetch-1.9.3/pygeofetch.egg-info → pygeofetch-1.9.4}/PKG-INFO +179 -77
  3. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/README.md +176 -74
  4. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/__init__.py +1 -1
  5. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/meta.yaml +1 -1
  6. {pygeofetch-1.9.3 → pygeofetch-1.9.4/pygeofetch.egg-info}/PKG-INFO +179 -77
  7. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch.egg-info/requires.txt +2 -2
  8. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pyproject.toml +3 -3
  9. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/LICENSE +0 -0
  10. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/MANIFEST.in +0 -0
  11. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/__init__.py +0 -0
  12. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/auth_commands.py +0 -0
  13. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/config_commands.py +0 -0
  14. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/download_commands.py +0 -0
  15. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/index_commands.py +0 -0
  16. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/main.py +0 -0
  17. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/pipeline_process_commands.py +0 -0
  18. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/postprocess_commands.py +0 -0
  19. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/preprocess_commands.py +0 -0
  20. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/sar_commands.py +0 -0
  21. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/cli/search_commands.py +0 -0
  22. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/config/__init__.py +0 -0
  23. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/config/defaults.yaml +0 -0
  24. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/config/settings.py +0 -0
  25. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/__init__.py +0 -0
  26. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/authenticator.py +0 -0
  27. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/cache_manager.py +0 -0
  28. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/downloader.py +0 -0
  29. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/engine.py +0 -0
  30. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/logging.py +0 -0
  31. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/orbits.py +0 -0
  32. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/scheduler.py +0 -0
  33. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/core/searcher.py +0 -0
  34. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/__init__.py +0 -0
  35. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/annotation.py +0 -0
  36. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/atmosphere.py +0 -0
  37. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/coregister.py +0 -0
  38. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/deburst.py +0 -0
  39. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/esd.py +0 -0
  40. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/extraction.py +0 -0
  41. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/flatearth.py +0 -0
  42. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/geolocation.py +0 -0
  43. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/gpu.py +0 -0
  44. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/interferogram.py +0 -0
  45. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/ionosphere.py +0 -0
  46. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/splitspectrum_diagnostic.py +0 -0
  47. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/synthetic.py +0 -0
  48. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/timeseries.py +0 -0
  49. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/unwrap.py +0 -0
  50. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/validate.py +0 -0
  51. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/visualize.py +0 -0
  52. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/insar/workflow.py +0 -0
  53. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/models/__init__.py +0 -0
  54. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/models/download_task.py +0 -0
  55. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/models/satellite_data.py +0 -0
  56. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/models/search_query.py +0 -0
  57. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/models/user_auth.py +0 -0
  58. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processing/__init__.py +0 -0
  59. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processing/base.py +0 -0
  60. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processing/batch.py +0 -0
  61. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processing/indices.py +0 -0
  62. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processing/pipeline.py +0 -0
  63. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processing/postprocessor.py +0 -0
  64. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processing/preprocessor.py +0 -0
  65. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processing/sar.py +0 -0
  66. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processor/__init__.py +0 -0
  67. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processor/indices.py +0 -0
  68. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processor/landsat.py +0 -0
  69. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processor/loader.py +0 -0
  70. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processor/stacker.py +0 -0
  71. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/processor/timeseries.py +0 -0
  72. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/__init__.py +0 -0
  73. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/airbus_oneatlas.py +0 -0
  74. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/alaska_satellite_facility.py +0 -0
  75. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/aws_earth.py +0 -0
  76. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/base.py +0 -0
  77. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/copernicus.py +0 -0
  78. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/digitalglobe.py +0 -0
  79. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/earth_explorer_additional.py +0 -0
  80. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/element84.py +0 -0
  81. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/eodag_provider.py +0 -0
  82. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/esa_scihub.py +0 -0
  83. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/geoserver_generic.py +0 -0
  84. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/google_earth_engine.py +0 -0
  85. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/inpe_cbers.py +0 -0
  86. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/isro_bhuvan.py +0 -0
  87. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/jaxa_earth.py +0 -0
  88. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/maxar_gbdx.py +0 -0
  89. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/nasa_earthdata.py +0 -0
  90. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/nasa_earthdata_cloud.py +0 -0
  91. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/noaa_big_data.py +0 -0
  92. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/opentopography.py +0 -0
  93. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/planet.py +0 -0
  94. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/planetary_computer.py +0 -0
  95. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/sentinel_hub.py +0 -0
  96. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/terrabotics.py +0 -0
  97. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/providers/usgs.py +0 -0
  98. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/sar/__init__.py +0 -0
  99. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/sar/_native.py +0 -0
  100. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/sar/_ost.py +0 -0
  101. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/sar/_sarxarray.py +0 -0
  102. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/sar/extraction.py +0 -0
  103. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/sar/processor.py +0 -0
  104. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/utils/__init__.py +0 -0
  105. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/utils/file_utils.py +0 -0
  106. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/utils/gcp_recovery.py +0 -0
  107. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/utils/geo_utils.py +0 -0
  108. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/utils/logging_setup.py +0 -0
  109. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/utils/retry_handler.py +0 -0
  110. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/utils/validators.py +0 -0
  111. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/viz/__init__.py +0 -0
  112. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/viz/map.py +0 -0
  113. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch/viz/plot.py +0 -0
  114. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch.egg-info/SOURCES.txt +0 -0
  115. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch.egg-info/dependency_links.txt +0 -0
  116. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch.egg-info/entry_points.txt +0 -0
  117. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch.egg-info/not-zip-safe +0 -0
  118. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/pygeofetch.egg-info/top_level.txt +0 -0
  119. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/setup.cfg +0 -0
  120. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_atmospheric_circular_regression.py +0 -0
  121. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_burst_metadata.py +0 -0
  122. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_burst_processing_integration.py +0 -0
  123. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_era5_atmospheric_correction.py +0 -0
  124. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_extraction.py +0 -0
  125. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_flat_earth_phase.py +0 -0
  126. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_gcp_reprojection.py +0 -0
  127. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_insar.py +0 -0
  128. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_ionosphere.py +0 -0
  129. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_models.py +0 -0
  130. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_pgv_integration_contract.py +0 -0
  131. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_provider_geometry_audit (1).py +0 -0
  132. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_provider_geometry_audit.py +0 -0
  133. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_provider_scene_disambiguation.py +0 -0
  134. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_providers.py +0 -0
  135. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_search_download.py +0 -0
  136. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_splitspectrum_diagnostic.py +0 -0
  137. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_utils.py +0 -0
  138. {pygeofetch-1.9.3 → pygeofetch-1.9.4}/tests/test_viz_plot.py +0 -0
@@ -1,7 +1,7 @@
1
1
  # Changelog
2
2
 
3
3
  All notable changes to PyGeoFetch are documented here.
4
- Format follows [Keep a Changelog](https://keepachangelog.com/en/1.9.3/).
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.9.4/).
5
5
 
6
6
  ## [1.9.4] — 2026-07-29
7
7
 
@@ -51,7 +51,7 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.9.3/).
51
51
 
52
52
  ### Migration Guide
53
53
  ```python
54
- # Before (v1.9.3)
54
+ # Before (v1.9.4)
55
55
  unwrapper = PhaseUnwrapper(cost_mode="defo", init_method="mcf")
56
56
  unwrapped = unwrapper.unwrap(phase, coherence, nlooks=2.0)
57
57
 
@@ -72,7 +72,7 @@ unwrapped = unwrapper.unwrap(
72
72
 
73
73
  ---
74
74
 
75
- ## [1.9.3] — 2026-07-12
75
+ ## [1.9.4] — 2026-07-12
76
76
 
77
77
  ### Added
78
78
  - Federated search across 22+ satellite data providers
@@ -189,7 +189,7 @@ unwrapped = unwrapper.unwrap(
189
189
  | Version | Date | Key Changes |
190
190
  |---------|------------|-------------|
191
191
  | **1.9.4** | 2026-07-29 | SNAPHU unwrapping fixes, 87.1% reliable pixels |
192
- | **1.9.3** | 2026-07-12 | 22 providers, 17 indices, Sentinel-1C/D |
192
+ | **1.9.4** | 2026-07-12 | 22 providers, 17 indices, Sentinel-1C/D |
193
193
  | **1.9.2** | 2026-06-15 | Batch processing, parallel downloads |
194
194
  | **1.9.1** | 2026-05-20 | 3D terrain, SNAPHU integration, time series |
195
195
  | **1.9.0** | 2026-04-25 | Initial public release |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygeofetch
3
- Version: 1.9.3
3
+ Version: 1.9.4
4
4
  Summary: Universal satellite data pipeline + geospatial processing platform
5
5
  Author-email: Samuel Appiah Kubi <appiahkubis14@gmail.com>
6
6
  License: MIT License
@@ -96,8 +96,8 @@ Requires-Dist: plotly>=5.14.0; extra == "viz"
96
96
  Requires-Dist: whitebox>=2.3.0; extra == "viz"
97
97
  Requires-Dist: whiteboxgui>=2.3.0; extra == "viz"
98
98
  Requires-Dist: geemap>=0.28.0; extra == "viz"
99
- Requires-Dist: osmnx>=1.9.3; extra == "viz"
100
- Requires-Dist: contextily>=1.9.3; extra == "viz"
99
+ Requires-Dist: osmnx>=1.9.4; extra == "viz"
100
+ Requires-Dist: contextily>=1.9.4; extra == "viz"
101
101
  Requires-Dist: xyzservices>=2023.10.0; extra == "viz"
102
102
  Requires-Dist: mapclassify>=2.5.0; extra == "viz"
103
103
  Requires-Dist: geoplot>=0.5.0; extra == "viz"
@@ -147,7 +147,7 @@ Dynamic: license-file
147
147
  [![Tests](https://github.com/appiahkubis14/pygeofetch/actions/workflows/tests.yml/badge.svg)](https://github.com/appiahkubis14/pygeofetch/actions)
148
148
  [![Coverage](https://codecov.io/gh/appiahkubis14/pygeofetch/branch/main/graph/badge.svg)](https://codecov.io/gh/appiahkubis14/pygeofetch)
149
149
 
150
- **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.**
150
+ **Universal satellite data pipeline + geospatial processing platform — unified access to 24 satellite repositories, 17 spectral indices, a full verified InSAR chain, and chainable YAML pipelines. One CLI, one Python API.**
151
151
 
152
152
  </div>
153
153
 
@@ -155,31 +155,55 @@ Dynamic: license-file
155
155
 
156
156
  ## 📖 Introduction
157
157
 
158
- 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.
158
+ pygeofetch is a **production-ready satellite data acquisition and processing framework** that provides unified, authenticated access to 24 Earth observation repositories — including Sentinel, Landsat, Planet, Maxar, Airbus, Copernicus, USGS, NASA, JAXA, and more — through a single consistent CLI and Python API.
159
159
 
160
- 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:
160
+ 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, including a real, independently-verified InSAR pipeline built and validated against real Sentinel-1 data, not just synthetic test cases. pygeofetch provides seven core capabilities:
161
161
 
162
- 1. **Authenticated access** to 22+ providers, with secure credential storage via system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service).
163
- 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.
162
+ 1. **Authenticated access** to 24 providers, with secure credential storage via system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service).
163
+ 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 — with real, verified footprint geometry (not just bounding boxes) for providers whose APIs actually supply it.
164
164
  3. **Resilient parallel downloads** with band selection, checksum verification, resume support, exponential backoff, and atomic writes.
165
165
  4. **Preprocessing engine** — atmospheric correction, cloud masking, reprojection, resampling, pan-sharpening, mosaicking, and compositing.
166
166
  5. **17 spectral indices** — NDVI, EVI, SAVI, NDWI, MNDWI, NDBI, TCT, PCA, LST, Albedo, dNBR, GLCM texture, and more.
167
- 6. **YAML pipeline orchestration** with cron scheduling, batch processing, and full execution history — enabling repeatable, automated geospatial workflows.
167
+ 6. **A full, verified InSAR chain** — burst-aware coregistration, real flat-earth and topographic phase removal, real ERA5 tropospheric and ionospheric correction, phase unwrapping, and SBAS time series inversion, each stage independently verified against synthetic ground truth or real, published deformation studies.
168
+ 7. **YAML pipeline orchestration** with cron scheduling, batch processing, and full execution history — enabling repeatable, automated geospatial workflows.
168
169
 
169
170
  ---
170
171
 
172
+
173
+
174
+ <p align="center">
175
+ <img src="docs/images/trend_map.png" width="48%" />
176
+ <img src="docs/images/trend_classification.png" width="48%" />
177
+ </p>
178
+ <p align="center"><em>NDVI trend (2018–2024) and severity classification for the Obuasi Municipal District, computed end-to-end with PyGeoFetch — real USGS Landsat data, boundary-clipped before processing.</em></p>
179
+
180
+ 32.0% of the Obuasi Municipal District shows measurable vegetation decline over 2018–2024 (9.2% strong decline + 22.8% moderate decline), against 57.5% stable and 10.5% showing an increasing trend.
181
+
182
+ That headline number matters less than where it's concentrated. The decline isn't scattered randomly across the district — it forms a clear, spatially coherent cluster in the western portion of the AOI (roughly west of -1.70° longitude), visible as a dense, contiguous red-and-orange zone in both the trend map and the classification map. Real land degradation signals tend to look like this — clustered along mining concessions, roads, or river corridors — whereas sensor noise or processing artifacts tend to scatter more randomly across the whole scene. The fact that this pattern holds together spatially is a reasonable indicator that it reflects something real on the ground, not just pixel-level noise.
183
+
184
+ That said, an NDVI trend map on its own can't distinguish why vegetation declined — illegal small-scale mining (galamsey), selective logging, agricultural land clearing, and urban expansion can all produce a similar signature. Given Obuasi's well-documented galamsey activity specifically concentrated in this district, the spatial pattern here is consistent with mining-driven clearance — but confirming that specific cause would need either higher-resolution imagery, ground verification, or cross-referencing against known concession boundaries, not this analysis alone.
185
+
186
+ Two things worth flagging honestly rather than glossing over:
187
+
188
+ The scattered dark-blue linear and blob features running through the map (most visibly the river-like feature crossing the upper-central area) are very likely water bodies, not vegetation gain. NDVI trend over open water isn't a meaningful signal — surface reflectance there is driven by turbidity and water level, not plant health — so those features should be excluded from the "increasing" interpretation, not read as reforestation.
189
+ The small white gaps scattered through the trend map (several distinct circular patches) are nodata — pixels that didn't have enough valid, cloud-free observations across all six dates to fit a reliable trend. Worth being upfront that the 32%/57.5%/10.5% breakdown is computed over the valid pixels only, not the full district area including these gaps.
190
+
191
+ The eastern two-thirds of the district, by contrast, is overwhelmingly stable (dominant green in the classification map), which is itself a useful negative result — it suggests the decline is genuinely localized to a specific area rather than reflecting a district-wide drought or seasonal artifact that would show up everywhere.
192
+
193
+
171
194
  ## 📝 Statement of Need
172
195
 
173
196
  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.
174
197
 
175
- 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.
198
+ 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; ISCE2/MintPy provide a genuine InSAR chain but no unified data access layer. No single tool covers the full breadth of providers, processing, InSAR, and automation needed for operational geospatial workflows.
176
199
 
177
200
  | Feature | pygeofetch | EODAG | pystac-client | satpy | sentinelsat |
178
201
  |---|---|---|---|---|---|
179
- | **Providers** | **22+** | 10+ | STAC only | Limited | Sentinel only |
202
+ | **Providers** | **24** | 10+ | STAC only | Limited | Sentinel only |
180
203
  | **Processing Engine** | ✅ Full | ❌ | ❌ | Partial | ❌ |
181
204
  | **Spectral Indices** | ✅ 17+ | ❌ | ❌ | ❌ | ❌ |
182
- | **SAR Processing** | ✅ | ❌ | ❌ | ✅ | ❌ |
205
+ | **Full InSAR Chain** | ✅ Verified | ❌ | ❌ | ❌ | ❌ |
206
+ | **Real Footprint Display** | ✅ | ❌ | ✅ (STAC only) | ❌ | ❌ |
183
207
  | **YAML Pipelines** | ✅ | ❌ | ❌ | ❌ | ❌ |
184
208
  | **Auth Management** | ✅ Keyring | Partial | ❌ | ❌ | ✅ |
185
209
  | **STAC 1.0 Output** | ✅ Native | ❌ | ✅ | ❌ | ❌ |
@@ -190,15 +214,15 @@ Existing tools address parts of this problem: EODAG supports several providers b
190
214
 
191
215
  ## 🚀 Key Features
192
216
 
193
- ### 🛰️ 22+ Satellite Providers
217
+ ### 🛰️ 24 Satellite Providers
194
218
 
195
- **Open access — no login required (10):**
219
+ **Open access — no login required (11):**
196
220
 
197
221
  | Provider ID | Satellites | Capabilities |
198
222
  |---|---|---|
199
- | `planetary_computer` | Sentinel-1/2, Landsat 8/9, MODIS, NAIP, ALOS DEM | STAC, SAR |
200
- | `aws_earth` | Sentinel-2 COG, Landsat C2, NAIP | STAC |
201
- | `element84` | Sentinel-2 L2A, Landsat C2, Sentinel-1 RTC, COP-DEM | STAC, SAR |
223
+ | `planetary_computer` | Sentinel-1/2, Landsat 8/9, MODIS, NAIP, ALOS DEM | STAC, SAR, real footprint geometry |
224
+ | `aws_earth` | Sentinel-2 COG, Landsat C2, NAIP | STAC, real footprint geometry |
225
+ | `element84` | Sentinel-2 L2A, Landsat C2, Sentinel-1 RTC, COP-DEM | STAC, SAR, real footprint geometry |
202
226
  | `noaa_big_data` | GOES-16/17/18, NEXRAD radar | Weather |
203
227
  | `esa_scihub` | Sentinel-1/2/3/5P (public mirrors) | SAR |
204
228
  | `jaxa_earth` | ALOS 30m DSM, PALSAR-2 | SAR |
@@ -206,14 +230,36 @@ Existing tools address parts of this problem: EODAG supports several providers b
206
230
  | `inpe_cbers` | CBERS-4, CBERS-4A | — |
207
231
  | `digitalglobe` | WorldView open disaster response | <1m VHR |
208
232
  | `geoserver_generic` | Any OGC WMS/WFS/WCS endpoint | Generic |
233
+ | `eodag` | Sentinel-1/2, Landsat (via EODAG's own providers) | SAR, real footprint geometry (Shapely-derived) |
234
+
235
+ **Authenticated providers (13):** USGS (real footprint geometry, confirmed) · Copernicus CDSE (real footprint geometry, confirmed against a live search) · NASA Earthdata (real footprint geometry, confirmed) · NASA Earthdata Cloud · Alaska SAR Facility · OpenTopography · Planet Labs (real footprint geometry, confirmed) · Sentinel Hub (real footprint geometry via STAC) · Maxar GBDX · Airbus OneAtlas · Google Earth Engine · TerraBotics · Earth Explorer
209
236
 
210
- **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
237
+ Every provider above has been individually, directly verified to populate at minimum a correct bounding box. For providers marked "confirmed," real, precise footprint geometry has been independently verified against the provider's own live API response or documented spec. For the remaining providers, geometry parsing is real and correctly wired — it will surface real, precise footprint shape the moment the provider's live API returns one — but that specific live return hasn't been independently confirmed for each of them; a bounding-box rectangle is what you'll see today. See [Real Footprint Display](#-real-footprint-display) below.
211
238
 
212
239
  ### 🔍 Unified Search
213
240
  - Federated query across multiple providers simultaneously with deduplicated results
214
241
  - Filter by bbox, geometry file, date range, cloud cover, resolution, processing level, and CQL2 expressions
215
242
  - 7 output formats: `table` · `json` · `stac` · `geojson` · `geoparquet` · `csv` · `ids`
216
243
 
244
+ ### 🗺️ Real Footprint Display
245
+
246
+ Every real search result can be shown directly on an interactive map, with real, useful hover info (scene ID, date, satellite, provider, cloud cover) — not just printed to a table.
247
+
248
+ ```python
249
+ from pygeofetch.viz.map import MapViewer
250
+
251
+ mv = MapViewer(center=(19.36, -99.09), zoom=9)
252
+ mv.add_basemap("SATELLITE")
253
+ mv.add_search_results(search_results) # real footprints, real hover info
254
+ mv.show()
255
+ ```
256
+
257
+ <p align="center">
258
+ <img src="docs/images/search.png" width="100%" />
259
+ </p>
260
+
261
+ `add_search_results()` uses each result's real, provider-supplied geometry when available, and falls back automatically to a bounding-box rectangle when it isn't — every provider is safe to call this against, none will silently show nothing or crash on an empty result set.
262
+
217
263
  ### 📥 Resilient Downloads
218
264
  - Adaptive parallel downloads with configurable concurrency and real-time progress
219
265
  - Band selection (e.g. `B02,B03,B04` → download 150 MB instead of 600 MB full scene)
@@ -296,6 +342,12 @@ pip install "pygeofetch[cloud]"
296
342
  # + Cron scheduling
297
343
  pip install "pygeofetch[schedule]"
298
344
 
345
+ # + Full InSAR chain (SBAS inversion, phase unwrapping)
346
+ pip install "pygeofetch[insar]"
347
+
348
+ # + Advanced InSAR corrections (MintPy passthrough)
349
+ pip install "pygeofetch[insar-full]"
350
+
299
351
  # Everything
300
352
  pip install "pygeofetch[all]"
301
353
  ```
@@ -353,11 +405,11 @@ pygeofetch download run \
353
405
 
354
406
  ```python
355
407
  from pathlib import Path
356
- from pygeofetch import pygeofetch
408
+ from pygeofetch import PyGeoFetch
357
409
  from pygeofetch.models.search_query import SearchQuery, BoundingBox
358
410
  from pygeofetch.models.download_task import DownloadOptions
359
411
 
360
- client = pygeofetch()
412
+ client = PyGeoFetch()
361
413
 
362
414
  # Credentials
363
415
  client.add_credentials("usgs", username="user", password="pass")
@@ -377,6 +429,13 @@ results = client.search(
377
429
  providers=["usgs", "copernicus", "planetary_computer", "aws_earth"],
378
430
  )
379
431
 
432
+ # See what you found, on a real map, before downloading anything
433
+ from pygeofetch.viz.map import MapViewer
434
+ mv = MapViewer(center=(40.7, -74.0), zoom=9)
435
+ mv.add_basemap("SATELLITE")
436
+ mv.add_search_results(results)
437
+ mv.show()
438
+
380
439
  # Download
381
440
  downloads = client.download(
382
441
  results[:5],
@@ -468,23 +527,27 @@ pygeofetch proc-pipeline template change_detection
468
527
 
469
528
  ---
470
529
 
530
+ ## 🌐 InSAR Processing (`pygeofetch.insar`)
471
531
 
472
- ### 🌐 InSAR Processing (`pygeofetch.insar`)
473
-
474
- A full Interferometric SAR chain for Sentinel-1 — search through SBAS time series inversion, pure Python, no external InSAR software required beyond `snaphu-py`'s bundled unwrapper.
532
+ A full, independently-verified Interferometric SAR chain for Sentinel-1 — search through SBAS time series inversion, pure Python, no external InSAR software required beyond `snaphu-py`'s bundled unwrapper. Every stage below has been verified against either synthetic ground truth (closed-loop, known-answer tests) or real, published deformation studies — not assumed correct from theory alone.
475
533
 
476
534
  ```bash
477
535
  pip install "pygeofetch[insar]" # native SBAS inversion
478
536
  pip install "pygeofetch[insar-full]" # + MintPy passthrough for advanced corrections
479
537
  ```
480
538
 
539
+ ### Core components
540
+
481
541
  | Component | Description |
482
542
  |---|---|
483
- | `InterferogramGenerator` | Coregistration (real orbit-based, or shape-based fallback) + Enhanced Spectral Diversity (ESD) refinement for TOPS burst continuity + topographic phase removal |
543
+ | `SLCExtractor` | Sub-swath matching and AOI-cropped extraction from raw SAFE archives; `.show_on_map()` for real amplitude display |
544
+ | `InterferogramGenerator` | Real orbit-based coregistration (falls back cleanly to shape-based when orbit files aren't supplied) + real per-burst-overlap Enhanced Spectral Diversity (ESD, verified against Prats-Iraola 2012) + real TOPS deburst (verified against ESA's own algorithm) + real flat-earth phase removal (orbit-geometry-derived, verified to 0.01% against independent computation) + topographic phase removal + Goldstein filtering |
545
+ | `AtmosphericCorrector` | Two real, independently-verified methods: elevation-correlated circular regression, and real ERA5 tropospheric delay correction via `pyaps3` and CDS, with automatic per-date differencing (not a naive single-date subtraction) |
546
+ | `IonosphericCorrector` | Real ionospheric pierce-point (IPP) geometry (ICD-GPS-200/Klobuchar model) and real CDDIS/IONEX TEC data, with both a scalar and a full per-pixel correction mode — closed-loop verified to recover a known, spatially-varying synthetic dispersive signal exactly |
484
547
  | `PhaseUnwrapper` | SNAPHU (Chen & Zebker 2001) via the official `snaphu-py` bindings — the same algorithm used by ASF, ISCE2/3, GAMMA, and SNAP |
485
- | `AtmosphericCorrector` | Elevation-correlated regression or ERA5 reanalysis-based tropospheric delay correction |
486
548
  | `SBASTimeSeries` | Small BAseline Subset displacement/velocity inversion (Berardino et al. 2002) |
487
549
  | `DataValidator` | SLC, coherence, and SBAS-network sanity checks, wired in at every real pipeline entry point |
550
+ | `InSARProject` | A high-level workflow wrapper — real search, download, extraction, and interferogram formation in a handful of calls, each with automatic map display, built on top of the fully-verified lower-level pieces above |
488
551
 
489
552
  Real orbit-based coregistration computes genuine per-pixel offsets from actual satellite orbit state vectors and acquisition timing (not a shape-matching guess) — supply a DEM, both SAFE archives, and both `.EOF` orbit files, and it's used automatically; otherwise falls back cleanly to shape-based resampling.
490
553
 
@@ -492,10 +555,16 @@ Every stage supports automatic visualization (`auto_visualize=True`) and optiona
492
555
 
493
556
  See [`pygeofetch/insar/README.md`](pygeofetch/insar/README.md) for the full processing chain, verification methodology, and current limitations.
494
557
 
558
+ ### Full pipeline, real orbit-based coregistration
559
+
495
560
  ```python
496
561
  from pygeofetch.insar import InterferogramGenerator
497
-
498
- gen = InterferogramGenerator(use_gpu=False)
562
+
563
+ gen = InterferogramGenerator(
564
+ use_gpu=False,
565
+ use_real_burst_processing=True, # real per-burst ESD + real deburst
566
+ remove_flat_earth_phase=True, # real, orbit-geometry-derived correction
567
+ )
499
568
  result = gen.process_pair(
500
569
  reference="slc_ref.tif",
501
570
  secondary="slc_sec.tif",
@@ -504,19 +573,72 @@ result = gen.process_pair(
504
573
  secondary_safe_zip="S1A_..._sec.SAFE.zip",
505
574
  reference_orbit_file="ref.EOF",
506
575
  secondary_orbit_file="sec.EOF",
576
+ reference_date="2024-11-08",
577
+ secondary_date="2024-11-20",
578
+ apply_goldstein_filter=True,
507
579
  )
508
580
  result.save("./output", auto_visualize=True)
581
+ result.show_on_map(band="wrapped_phase") # real, cyclic-colormap display
509
582
  ```
510
-
511
- ### Without the new orbit-based inputs (falls back safely)
512
-
583
+
584
+ ### Without the orbit-based inputs (falls back safely)
585
+
513
586
  ```python
514
587
  result = gen.process_pair(reference="slc_ref.tif", secondary="slc_sec.tif", dem="dem.tif")
515
588
  # Logs: "Using shape-based coregistration fallback ..."
516
589
  ```
517
-
590
+
591
+ ### Real ERA5 tropospheric correction
592
+
593
+ ```python
594
+ from pygeofetch.insar.atmosphere import AtmosphericCorrector
595
+
596
+ # One-time: writes the real ~/.cdsapirc CDS reads from directly
597
+ atm = AtmosphericCorrector(method="era5", cds_api_key="your-cds-key")
598
+ corrected_phase, meta = atm.correct(
599
+ wrapped_phase, dem="dem.tif",
600
+ reference_datetime="2024-11-08T12:34:39",
601
+ secondary_datetime="2024-11-20T12:34:38",
602
+ return_metadata=True,
603
+ )
604
+ ```
605
+
606
+ ### Real ionospheric correction (per-pixel)
607
+
608
+ ```python
609
+ from pygeofetch.insar.ionosphere import IonosphericCorrector
610
+
611
+ # One-time: writes the real ~/.netrc Earthdata Login reads from directly
612
+ iono = IonosphericCorrector(
613
+ ionex_dir="./ionex",
614
+ earthdata_username="your-username", earthdata_password="your-password",
615
+ )
616
+ corrected_phase = iono.correct_per_pixel(
617
+ wrapped_phase,
618
+ reference_datetime="2024-12-26T12:34:35", secondary_datetime="2025-01-07T12:34:34",
619
+ lat_grid=lat_grid, lon_grid=lon_grid,
620
+ reference_orbit_file="ref.EOF", secondary_orbit_file="sec.EOF",
621
+ )
622
+ ```
623
+
624
+ ### High-level workflow — search to interferogram in a handful of calls
625
+
626
+ ```python
627
+ from pygeofetch.insar import InSARProject
628
+ from pygeofetch.models import BoundingBox
629
+
630
+ project = InSARProject(
631
+ name="my_aoi", aoi=BoundingBox(min_lon=-99.183, max_lon=-99.003, min_lat=19.278, max_lat=19.438),
632
+ output_dir="data/my_aoi_insar",
633
+ )
634
+ project.search(start_date="2024-11-01", end_date="2025-01-15") # real search, real map
635
+ project.download_and_extract(max_scenes=6) # real download + AOI crop
636
+ project.form_all_interferograms() # full verified pipeline
637
+ project.summary()
638
+ ```
639
+
518
640
  ### Full chain, search to SBAS
519
-
641
+
520
642
  ```python
521
643
  from pathlib import Path
522
644
  import numpy as np
@@ -530,15 +652,15 @@ from pygeofetch.insar import (
530
652
  PhaseUnwrapper, SBASTimeSeries, DataValidator, multilook,
531
653
  )
532
654
  from pygeofetch.insar.timeseries import InterferogramPair
533
-
655
+
534
656
  client = PyGeoFetch()
535
657
  client.add_credentials("copernicus", username="you@example.com", password="...")
536
658
  client.add_credentials("opentopography", api_key="...")
537
-
659
+
538
660
  aoi = BoundingBox(min_lon=-1.75, max_lon=-1.63, min_lat=6.15, max_lat=6.24)
539
661
  output_dir = Path("./insar_output")
540
-
541
- # Search — real geometry/bbox filtering, not the dead geometry_geojson= field
662
+
663
+ # Search — real geometry/bbox filtering
542
664
  scenes = {}
543
665
  for start, end in [("2026-01-01", "2026-01-08"), ("2026-01-13", "2026-01-20")]:
544
666
  results = client.search(
@@ -548,14 +670,14 @@ for start, end in [("2026-01-01", "2026-01-08"), ("2026-01-13", "2026-01-20")]:
548
670
  )
549
671
  if results:
550
672
  scenes[str(results[0].datetime.date())] = results[0]
551
-
673
+
552
674
  # Download
553
675
  downloads = {
554
676
  label: client.download([scene], destination=output_dir / "raw" / label,
555
677
  options=DownloadOptions(resume=True))[0]
556
678
  for label, scene in scenes.items()
557
679
  }
558
-
680
+
559
681
  # Real orbit files — use the real product name, not the catalog ID
560
682
  orbits = {
561
683
  label: fetch_orbit_file(
@@ -564,7 +686,7 @@ orbits = {
564
686
  )
565
687
  for label, scene in scenes.items()
566
688
  }
567
-
689
+
568
690
  # Real DEM, clipped to the AOI
569
691
  dem_result = client.download(
570
692
  client.search(SearchQuery(bbox=aoi), providers=["opentopography"])[:1],
@@ -572,7 +694,7 @@ dem_result = client.download(
572
694
  )[0]
573
695
  dem_path = Preprocessor().clip(dem_result.output_path, bbox=aoi,
574
696
  output=str(output_dir / "dem" / "clipped.tif")).output_path
575
-
697
+
576
698
  # AOI-cropped extraction (not the full sub-swath)
577
699
  extractor = SLCExtractor(polarisation="VV")
578
700
  slcs = {
@@ -581,7 +703,7 @@ slcs = {
581
703
  for label, dl in downloads.items()
582
704
  }
583
705
  dates = sorted(slcs)
584
-
706
+
585
707
  # Interferogram formation — real orbit-based coregistration when all four
586
708
  # inputs are available; falls back to shape-based resampling otherwise
587
709
  gen = InterferogramGenerator(coherence_window=5, esd_enabled=True, use_gpu=False)
@@ -593,20 +715,20 @@ result = gen.process_pair(
593
715
  reference_orbit_file=orbits[d1], secondary_orbit_file=orbits[d2],
594
716
  )
595
717
  result.save(output_dir / "interferograms", auto_visualize=True)
596
-
718
+
597
719
  # Atmospheric correction — return_metadata=True to know what actually happened
598
720
  atm = AtmosphericCorrector(method="elevation")
599
721
  corrected_phase, atm_meta = atm.correct(
600
722
  np.angle(result.interferogram), dem=dem_path, return_metadata=True
601
723
  )
602
-
724
+
603
725
  # Unwrapping — multilook first; wrapped_phase must be explicit (True for
604
726
  # phase, False for coherence — never guessed from dtype)
605
727
  phase_ml = multilook(corrected_phase, 4, 1, wrapped_phase=True)
606
728
  coherence_ml = multilook(result.coherence, 4, 1, wrapped_phase=False)
607
729
  unwrapper = PhaseUnwrapper(cost_mode="defo", init_method="mcf")
608
730
  unwrapped, conncomp = unwrapper.unwrap(phase_ml, coherence_ml, nlooks=4.0)
609
-
731
+
610
732
  # SBAS inversion
611
733
  pairs = [InterferogramPair(d1, d2, unwrapped, coherence_ml)]
612
734
  network_check = DataValidator.validate_sbas_network(pairs, dates)
@@ -615,12 +737,13 @@ ts_result = sbas.invert(pairs, reference_pixel=(0, 0))
615
737
  ts_result.save(output_dir / "timeseries", auto_visualize=True)
616
738
  print(f"Mean velocity: {ts_result.velocity.mean()*1000:.1f} mm/year")
617
739
  ```
618
-
740
+
619
741
  <!-- A real, runnable two-date example — extend the search date list and repeat
620
742
  the interferogram/unwrapping steps per consecutive pair for a full SBAS
621
- network. See `23_accra_urban_deformation_sbas.ipynb` for the complete,
622
- real, multi-date worked version of this exact chain. -->
623
-
743
+ network. See the notebooks table below for complete, real, multi-date
744
+ worked examples of this exact chain, including two real, published
745
+ volcanic and seismic deformation events. -->
746
+
624
747
  ---
625
748
 
626
749
  ## 🖥️ Complete CLI Reference
@@ -746,7 +869,7 @@ COMPLETION
746
869
  | Notebook | Topics |
747
870
  |---|---|
748
871
  | `01_getting_started.ipynb` | Install, doctor, first search, first download |
749
- | `02_authentication_and_providers.ipynb` | All 22 providers, credentials, capability filters |
872
+ | `02_authentication_and_providers.ipynb` | All 24 providers, credentials, capability filters |
750
873
  | `03_advanced_search.ipynb` | Federated search, CQL2 filters, 7 output formats, caching |
751
874
  | `04_download_and_postprocessing.ipynb` | Band selection, parallel downloads, post-processing |
752
875
  | `05_pipelines_and_scheduling.ipynb` | YAML pipelines, scheduling, Python builder API |
@@ -754,6 +877,9 @@ COMPLETION
754
877
  | `07_copernicus_and_authenticated_providers.ipynb` | Copernicus, USGS, NASA, Planet, ASF, OpenTopography |
755
878
  | `08_cli_complete_reference.ipynb` | Every CLI command with runnable examples |
756
879
  | `09_processing_complete.ipynb` | Full processing engine: preprocessing, indices, SAR, pipelines |
880
+ | `piton_fournaise_full.ipynb` | Real, verified InSAR pipeline against the real April 2021 Piton de la Fournaise eruption (Réunion Island) — real pygeofetch search/download throughout, full burst-aware coregistration, real flat-earth and ERA5 correction |
881
+ | `amatrice_full.ipynb` | Real, verified InSAR pipeline against the real 2016 Amatrice, Italy earthquake, using the exact real interferometric pair dates from a published processing archive |
882
+ | `provider_search_footprint_test.ipynb` | Real search and footprint-map display validation across all 24 providers, one fully explicit, independently-runnable cell per provider |
757
883
 
758
884
  ```bash
759
885
  cd notebooks/
@@ -762,30 +888,11 @@ jupyter lab
762
888
 
763
889
  ---
764
890
 
765
- <p align="center">
766
- <img src="docs/images/trend_map.png" width="48%" />
767
- <img src="docs/images/trend_classification.png" width="48%" />
768
- </p>
769
- <p align="center"><em>NDVI trend (2018–2024) and severity classification for the Obuasi Municipal District, computed end-to-end with PyGeoFetch — real USGS Landsat data, boundary-clipped before processing.</em></p>
770
-
771
- 32.0% of the Obuasi Municipal District shows measurable vegetation decline over 2018–2024 (9.2% strong decline + 22.8% moderate decline), against 57.5% stable and 10.5% showing an increasing trend.
772
-
773
- That headline number matters less than where it's concentrated. The decline isn't scattered randomly across the district — it forms a clear, spatially coherent cluster in the western portion of the AOI (roughly west of -1.70° longitude), visible as a dense, contiguous red-and-orange zone in both the trend map and the classification map. Real land degradation signals tend to look like this — clustered along mining concessions, roads, or river corridors — whereas sensor noise or processing artifacts tend to scatter more randomly across the whole scene. The fact that this pattern holds together spatially is a reasonable indicator that it reflects something real on the ground, not just pixel-level noise.
774
-
775
- That said, an NDVI trend map on its own can't distinguish why vegetation declined — illegal small-scale mining (galamsey), selective logging, agricultural land clearing, and urban expansion can all produce a similar signature. Given Obuasi's well-documented galamsey activity specifically concentrated in this district, the spatial pattern here is consistent with mining-driven clearance — but confirming that specific cause would need either higher-resolution imagery, ground verification, or cross-referencing against known concession boundaries, not this analysis alone.
776
-
777
- Two things worth flagging honestly rather than glossing over:
778
-
779
- The scattered dark-blue linear and blob features running through the map (most visibly the river-like feature crossing the upper-central area) are very likely water bodies, not vegetation gain. NDVI trend over open water isn't a meaningful signal — surface reflectance there is driven by turbidity and water level, not plant health — so those features should be excluded from the "increasing" interpretation, not read as reforestation.
780
- The small white gaps scattered through the trend map (several distinct circular patches) are nodata — pixels that didn't have enough valid, cloud-free observations across all six dates to fit a reliable trend. Worth being upfront that the 32%/57.5%/10.5% breakdown is computed over the valid pixels only, not the full district area including these gaps.
781
-
782
- The eastern two-thirds of the district, by contrast, is overwhelmingly stable (dominant green in the classification map), which is itself a useful negative result — it suggests the decline is genuinely localized to a specific area rather than reflecting a district-wide drought or seasonal artifact that would show up everywhere.
783
-
784
891
  ## 📋 Documentation
785
892
 
786
893
  Full documentation: **https://appiahkubis14.github.io/pygeofetch-docs/**
787
894
 
788
- Covers: CLI reference · provider auth guides · pipeline configuration · post-processing catalogue · contributing guide.
895
+ Covers: CLI reference · provider auth guides · pipeline configuration · post-processing catalogue · InSAR verification methodology · contributing guide.
789
896
 
790
897
  ---
791
898
 
@@ -793,10 +900,10 @@ Covers: CLI reference · provider auth guides · pipeline configuration · post-
793
900
 
794
901
  Contributions of all kinds are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines.
795
902
 
796
- Good first issues include implementing stub providers to full API integrations, improving test coverage, and adding new post-processing actions.
903
+ Good first issues include implementing stub providers to full API integrations, extending real footprint geometry support to the remaining bbox-only providers, improving test coverage, and adding new post-processing actions.
797
904
 
798
905
  ```bash
799
- git clone https://github.com/appiahkubis14/pygeofetch
906
+ git clone git@github.com:EOCoreINT/pygeofetch.git
800
907
  cd pygeofetch
801
908
  pip install -e ".[dev,all]"
802
909
  pytest tests/unit/ -v
@@ -808,9 +915,4 @@ pytest tests/unit/ -v
808
915
 
809
916
  pygeofetch is free and open source software, licensed under the [MIT License](LICENSE).
810
917
 
811
- © 2026 Samuel Appiah Kubi. Part of the **PyGeoVision** platform — [pygeofetch](https://github.com/appiahkubis14/pygeofetch) (data + processing) complete Earth observation pipeline.
812
-
813
-
814
-
815
-
816
-
918
+ © 2026 Samuel Appiah Kubi. Part of the **PyGeoVision** platform — [pygeofetch](https://github.com/appiahkubis14/pygeofetch) (data + processing) — complete Earth observation pipeline.