PyGeoFetch 1.8.0__tar.gz → 1.9.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 (116) hide show
  1. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/CHANGELOG.md +2 -2
  2. {pygeofetch-1.8.0/pygeofetch.egg-info → pygeofetch-1.9.1}/PKG-INFO +72 -3
  3. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/README.md +69 -0
  4. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/__init__.py +1 -1
  5. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/engine.py +32 -8
  6. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/meta.yaml +1 -1
  7. {pygeofetch-1.8.0 → pygeofetch-1.9.1/pygeofetch.egg-info}/PKG-INFO +72 -3
  8. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/requires.txt +2 -2
  9. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pyproject.toml +4 -4
  10. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/LICENSE +0 -0
  11. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/MANIFEST.in +0 -0
  12. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/__init__.py +0 -0
  13. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/auth_commands.py +0 -0
  14. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/config_commands.py +0 -0
  15. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/download_commands.py +0 -0
  16. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/index_commands.py +0 -0
  17. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/main.py +0 -0
  18. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/pipeline_process_commands.py +0 -0
  19. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/postprocess_commands.py +0 -0
  20. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/preprocess_commands.py +0 -0
  21. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/sar_commands.py +0 -0
  22. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/search_commands.py +0 -0
  23. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/config/__init__.py +0 -0
  24. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/config/defaults.yaml +0 -0
  25. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/config/settings.py +0 -0
  26. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/__init__.py +0 -0
  27. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/authenticator.py +0 -0
  28. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/cache_manager.py +0 -0
  29. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/downloader.py +0 -0
  30. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/logging.py +0 -0
  31. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/orbits.py +0 -0
  32. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/scheduler.py +0 -0
  33. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/searcher.py +0 -0
  34. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/__init__.py +0 -0
  35. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/annotation.py +0 -0
  36. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/atmosphere.py +0 -0
  37. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/coregister.py +0 -0
  38. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/extraction.py +0 -0
  39. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/geolocation.py +0 -0
  40. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/gpu.py +0 -0
  41. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/interferogram.py +0 -0
  42. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/timeseries.py +0 -0
  43. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/unwrap.py +0 -0
  44. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/validate.py +0 -0
  45. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/visualize.py +0 -0
  46. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/__init__.py +0 -0
  47. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/download_task.py +0 -0
  48. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/satellite_data.py +0 -0
  49. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/search_query.py +0 -0
  50. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/user_auth.py +0 -0
  51. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/__init__.py +0 -0
  52. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/base.py +0 -0
  53. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/batch.py +0 -0
  54. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/indices.py +0 -0
  55. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/pipeline.py +0 -0
  56. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/postprocessor.py +0 -0
  57. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/preprocessor.py +0 -0
  58. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/sar.py +0 -0
  59. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/__init__.py +0 -0
  60. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/indices.py +0 -0
  61. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/landsat.py +0 -0
  62. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/loader.py +0 -0
  63. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/stacker.py +0 -0
  64. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/timeseries.py +0 -0
  65. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/__init__.py +0 -0
  66. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/airbus_oneatlas.py +0 -0
  67. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/alaska_satellite_facility.py +0 -0
  68. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/aws_earth.py +0 -0
  69. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/base.py +0 -0
  70. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/copernicus.py +0 -0
  71. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/digitalglobe.py +0 -0
  72. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/earth_explorer_additional.py +0 -0
  73. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/element84.py +0 -0
  74. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/eodag_provider.py +0 -0
  75. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/esa_scihub.py +0 -0
  76. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/geoserver_generic.py +0 -0
  77. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/google_earth_engine.py +0 -0
  78. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/inpe_cbers.py +0 -0
  79. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/isro_bhuvan.py +0 -0
  80. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/jaxa_earth.py +0 -0
  81. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/maxar_gbdx.py +0 -0
  82. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/nasa_earthdata.py +0 -0
  83. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/nasa_earthdata_cloud.py +0 -0
  84. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/noaa_big_data.py +0 -0
  85. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/opentopography.py +0 -0
  86. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/planet.py +0 -0
  87. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/planetary_computer.py +0 -0
  88. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/sentinel_hub.py +0 -0
  89. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/terrabotics.py +0 -0
  90. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/usgs.py +0 -0
  91. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/__init__.py +0 -0
  92. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/_native.py +0 -0
  93. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/_ost.py +0 -0
  94. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/_sarxarray.py +0 -0
  95. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/extraction.py +0 -0
  96. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/processor.py +0 -0
  97. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/__init__.py +0 -0
  98. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/file_utils.py +0 -0
  99. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/gcp_recovery.py +0 -0
  100. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/geo_utils.py +0 -0
  101. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/logging_setup.py +0 -0
  102. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/retry_handler.py +0 -0
  103. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/validators.py +0 -0
  104. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/viz/__init__.py +0 -0
  105. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/viz/map.py +0 -0
  106. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/viz/plot.py +0 -0
  107. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/SOURCES.txt +0 -0
  108. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/dependency_links.txt +0 -0
  109. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/entry_points.txt +0 -0
  110. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/not-zip-safe +0 -0
  111. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/top_level.txt +0 -0
  112. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/setup.cfg +0 -0
  113. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/tests/test_extraction.py +0 -0
  114. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/tests/test_insar.py +0 -0
  115. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/tests/test_pgv_integration_contract.py +0 -0
  116. {pygeofetch-1.8.0 → pygeofetch-1.9.1}/tests/test_viz_plot.py +0 -0
@@ -1,9 +1,9 @@
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.8.0/).
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.9.1/).
5
5
 
6
- ## [1.8.0] — 2026-07-12
6
+ ## [1.9.1] — 2026-07-12
7
7
 
8
8
  ### Added
9
9
  - Federated search across 22+ satellite data providers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygeofetch
3
- Version: 1.8.0
3
+ Version: 1.9.1
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
@@ -94,8 +94,8 @@ Requires-Dist: plotly>=5.14.0; extra == "viz"
94
94
  Requires-Dist: whitebox>=2.3.0; extra == "viz"
95
95
  Requires-Dist: whiteboxgui>=2.3.0; extra == "viz"
96
96
  Requires-Dist: geemap>=0.28.0; extra == "viz"
97
- Requires-Dist: osmnx>=1.8.0; extra == "viz"
98
- Requires-Dist: contextily>=1.8.0; extra == "viz"
97
+ Requires-Dist: osmnx>=1.9.1; extra == "viz"
98
+ Requires-Dist: contextily>=1.9.1; extra == "viz"
99
99
  Requires-Dist: xyzservices>=2023.10.0; extra == "viz"
100
100
  Requires-Dist: mapclassify>=2.5.0; extra == "viz"
101
101
  Requires-Dist: geoplot>=0.5.0; extra == "viz"
@@ -467,6 +467,70 @@ pygeofetch proc-pipeline template change_detection
467
467
 
468
468
  ---
469
469
 
470
+
471
+ ### 🌐 InSAR Processing (`pygeofetch.insar`)
472
+
473
+ 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.
474
+
475
+ ```bash
476
+ pip install "pygeofetch[insar]" # native SBAS inversion
477
+ pip install "pygeofetch[insar-full]" # + MintPy passthrough for advanced corrections
478
+ ```
479
+
480
+ | Component | Description |
481
+ |---|---|
482
+ | `InterferogramGenerator` | Coregistration (real orbit-based, or shape-based fallback) + Enhanced Spectral Diversity (ESD) refinement for TOPS burst continuity + topographic phase removal |
483
+ | `PhaseUnwrapper` | SNAPHU (Chen & Zebker 2001) via the official `snaphu-py` bindings — the same algorithm used by ASF, ISCE2/3, GAMMA, and SNAP |
484
+ | `AtmosphericCorrector` | Elevation-correlated regression or ERA5 reanalysis-based tropospheric delay correction |
485
+ | `SBASTimeSeries` | Small BAseline Subset displacement/velocity inversion (Berardino et al. 2002) |
486
+ | `DataValidator` | SLC, coherence, and SBAS-network sanity checks, wired in at every real pipeline entry point |
487
+
488
+ 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.
489
+
490
+ Every stage supports automatic visualization (`auto_visualize=True`) and optional GPU acceleration (`use_gpu=True`, CuPy) for coherence estimation and SBAS inversion on large scenes.
491
+
492
+ See [`pygeofetch/insar/README.md`](pygeofetch/insar/README.md) for the full processing chain, verification methodology, and current limitations.
493
+
494
+
495
+ ```python
496
+ # InSAR — search to SBAS time series
497
+ from pygeofetch.insar import (
498
+ InterferogramGenerator, PhaseUnwrapper, AtmosphericCorrector,
499
+ SBASTimeSeries, DataValidator,
500
+ )
501
+ from pygeofetch.insar.timeseries import InterferogramPair
502
+ from pygeofetch.core.orbits import fetch_orbit_file
503
+
504
+ # Coregistration + interferogram formation (real orbit-based when a DEM,
505
+ # both SAFE archives, and both orbit files are supplied; falls back to
506
+ # shape-based resampling otherwise)
507
+ gen = InterferogramGenerator(coherence_window=5, esd_enabled=True, use_gpu=False)
508
+ result = gen.process_pair(
509
+ reference="slc_ref.tif", secondary="slc_sec.tif", dem="dem.tif",
510
+ reference_safe_zip="ref.SAFE.zip", secondary_safe_zip="sec.SAFE.zip",
511
+ reference_orbit_file=fetch_orbit_file("S1A_..._ref"),
512
+ secondary_orbit_file=fetch_orbit_file("S1A_..._sec"),
513
+ )
514
+ result.save("./output", auto_visualize=True)
515
+
516
+ # Atmospheric correction + phase unwrapping
517
+ atm = AtmosphericCorrector(method="elevation")
518
+ corrected_phase = atm.correct(result.interferogram, dem="dem.tif")
519
+
520
+ unwrapper = PhaseUnwrapper(cost_mode="defo", init_method="mcf")
521
+ unwrapped, conncomp = unwrapper.unwrap(corrected_phase, result.coherence)
522
+
523
+ # SBAS time series inversion across a network of interferograms
524
+ pairs = [
525
+ InterferogramPair("2026-01-01", "2026-01-13", unwrapped, result.coherence),
526
+ # ... additional pairs forming a connected network
527
+ ]
528
+ sbas = SBASTimeSeries(wavelength_m=0.05546576, reference_date="2026-01-01")
529
+ ts_result = sbas.invert(pairs, reference_pixel=(10, 15)) # known-stable pixel
530
+ ts_result.save("./timeseries", auto_visualize=True)
531
+ print(f"Mean velocity: {ts_result.velocity.mean()*1000:.1f} mm/year")
532
+ ```
533
+
470
534
  ## 🖥️ Complete CLI Reference
471
535
 
472
536
  ```
@@ -653,3 +717,8 @@ pytest tests/unit/ -v
653
717
  pygeofetch is free and open source software, licensed under the [MIT License](LICENSE).
654
718
 
655
719
  © 2026 Samuel Appiah Kubi. Part of the **PyGeoVision** platform — [pygeofetch](https://github.com/appiahkubis14/pygeofetch) (data + processing) complete Earth observation pipeline.
720
+
721
+
722
+
723
+
724
+
@@ -331,6 +331,70 @@ pygeofetch proc-pipeline template change_detection
331
331
 
332
332
  ---
333
333
 
334
+
335
+ ### 🌐 InSAR Processing (`pygeofetch.insar`)
336
+
337
+ 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.
338
+
339
+ ```bash
340
+ pip install "pygeofetch[insar]" # native SBAS inversion
341
+ pip install "pygeofetch[insar-full]" # + MintPy passthrough for advanced corrections
342
+ ```
343
+
344
+ | Component | Description |
345
+ |---|---|
346
+ | `InterferogramGenerator` | Coregistration (real orbit-based, or shape-based fallback) + Enhanced Spectral Diversity (ESD) refinement for TOPS burst continuity + topographic phase removal |
347
+ | `PhaseUnwrapper` | SNAPHU (Chen & Zebker 2001) via the official `snaphu-py` bindings — the same algorithm used by ASF, ISCE2/3, GAMMA, and SNAP |
348
+ | `AtmosphericCorrector` | Elevation-correlated regression or ERA5 reanalysis-based tropospheric delay correction |
349
+ | `SBASTimeSeries` | Small BAseline Subset displacement/velocity inversion (Berardino et al. 2002) |
350
+ | `DataValidator` | SLC, coherence, and SBAS-network sanity checks, wired in at every real pipeline entry point |
351
+
352
+ 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.
353
+
354
+ Every stage supports automatic visualization (`auto_visualize=True`) and optional GPU acceleration (`use_gpu=True`, CuPy) for coherence estimation and SBAS inversion on large scenes.
355
+
356
+ See [`pygeofetch/insar/README.md`](pygeofetch/insar/README.md) for the full processing chain, verification methodology, and current limitations.
357
+
358
+
359
+ ```python
360
+ # InSAR — search to SBAS time series
361
+ from pygeofetch.insar import (
362
+ InterferogramGenerator, PhaseUnwrapper, AtmosphericCorrector,
363
+ SBASTimeSeries, DataValidator,
364
+ )
365
+ from pygeofetch.insar.timeseries import InterferogramPair
366
+ from pygeofetch.core.orbits import fetch_orbit_file
367
+
368
+ # Coregistration + interferogram formation (real orbit-based when a DEM,
369
+ # both SAFE archives, and both orbit files are supplied; falls back to
370
+ # shape-based resampling otherwise)
371
+ gen = InterferogramGenerator(coherence_window=5, esd_enabled=True, use_gpu=False)
372
+ result = gen.process_pair(
373
+ reference="slc_ref.tif", secondary="slc_sec.tif", dem="dem.tif",
374
+ reference_safe_zip="ref.SAFE.zip", secondary_safe_zip="sec.SAFE.zip",
375
+ reference_orbit_file=fetch_orbit_file("S1A_..._ref"),
376
+ secondary_orbit_file=fetch_orbit_file("S1A_..._sec"),
377
+ )
378
+ result.save("./output", auto_visualize=True)
379
+
380
+ # Atmospheric correction + phase unwrapping
381
+ atm = AtmosphericCorrector(method="elevation")
382
+ corrected_phase = atm.correct(result.interferogram, dem="dem.tif")
383
+
384
+ unwrapper = PhaseUnwrapper(cost_mode="defo", init_method="mcf")
385
+ unwrapped, conncomp = unwrapper.unwrap(corrected_phase, result.coherence)
386
+
387
+ # SBAS time series inversion across a network of interferograms
388
+ pairs = [
389
+ InterferogramPair("2026-01-01", "2026-01-13", unwrapped, result.coherence),
390
+ # ... additional pairs forming a connected network
391
+ ]
392
+ sbas = SBASTimeSeries(wavelength_m=0.05546576, reference_date="2026-01-01")
393
+ ts_result = sbas.invert(pairs, reference_pixel=(10, 15)) # known-stable pixel
394
+ ts_result.save("./timeseries", auto_visualize=True)
395
+ print(f"Mean velocity: {ts_result.velocity.mean()*1000:.1f} mm/year")
396
+ ```
397
+
334
398
  ## 🖥️ Complete CLI Reference
335
399
 
336
400
  ```
@@ -517,3 +581,8 @@ pytest tests/unit/ -v
517
581
  pygeofetch is free and open source software, licensed under the [MIT License](LICENSE).
518
582
 
519
583
  © 2026 Samuel Appiah Kubi. Part of the **PyGeoVision** platform — [pygeofetch](https://github.com/appiahkubis14/pygeofetch) (data + processing) complete Earth observation pipeline.
584
+
585
+
586
+
587
+
588
+
@@ -30,7 +30,7 @@ CLI::
30
30
  pygeofetch doctor
31
31
  """
32
32
 
33
- __version__ = "1.8.0"
33
+ __version__ = "1.9.1"
34
34
  __author__ = "PyGeoFetch Contributors"
35
35
  __license__ = "MIT"
36
36
 
@@ -176,7 +176,7 @@ class PyGeoFetch:
176
176
  if _product.upper() == "SLC" and _effective:
177
177
  _effective = self._route_slc_providers(_effective)
178
178
  results = self.searcher.search(query, providers=_effective, use_cache=use_cache)
179
- self._warn_if_outdated_constellation(results)
179
+ self._warn_if_outdated_constellation(results, query)
180
180
  return results
181
181
 
182
182
  def search_and_save(
@@ -217,19 +217,43 @@ class PyGeoFetch:
217
217
  }
218
218
  _GRD_ONLY = {"planetary_computer", "aws_earth", "element84"}
219
219
 
220
- def _warn_if_outdated_constellation(self, results: list) -> None:
221
- """Log a warning if results contain only decommissioned satellites after S1A decomm."""
222
- from datetime import date
220
+ def _warn_if_outdated_constellation(self, results: list, query) -> None:
221
+ """Log a warning if results contain only decommissioned satellites
222
+ for a search whose OWN requested date range extends past S1A's
223
+ real decommissioning date — not just because today happens to be
224
+ past it. A search for genuine historical data (e.g. November
225
+ 2024, well before S1A's actual 1 July 2026 end of mission) must
226
+ never trigger this, regardless of what today's date is; S1A
227
+ results from before decommissioning are completely legitimate."""
228
+ from datetime import date, datetime
223
229
 
224
230
  S1A_DECOM = date(2026, 7, 1)
225
- if date.today() >= S1A_DECOM:
231
+
232
+ query_end = getattr(query, "end_date", None)
233
+ if query_end is None:
234
+ # No end date specified -- fall back to whether the search
235
+ # was actually run after decommissioning (the old behaviour,
236
+ # but only as a last resort when there's no query date to
237
+ # check against).
238
+ query_end_date = date.today()
239
+ elif isinstance(query_end, str):
240
+ query_end_date = datetime.fromisoformat(query_end.replace("Z", "")).date()
241
+ elif isinstance(query_end, datetime):
242
+ query_end_date = query_end.date()
243
+ elif isinstance(query_end, date):
244
+ query_end_date = query_end
245
+ else:
246
+ query_end_date = date.today()
247
+
248
+ if query_end_date >= S1A_DECOM:
226
249
  platforms = {getattr(r, "satellite", "") or "" for r in results}
227
250
  normalised = {_normalise_satellite_name(p) for p in platforms}
228
251
  if any("S1" in p for p in normalised): # only check if S1 results
229
252
  if not any(p in {"S1C", "S1D"} for p in normalised):
230
253
  logger.warning(
231
- "Search returned only S1A/S1B results after Sentinel-1A "
232
- "decommissioning date. This may indicate a provider collection "
254
+ "Search returned only S1A/S1B results for a date range "
255
+ "extending past Sentinel-1A's real decommissioning date "
256
+ "(1 July 2026). This may indicate a provider collection "
233
257
  "routing issue. Check platform filter settings."
234
258
  )
235
259
 
@@ -460,4 +484,4 @@ class PyGeoFetch:
460
484
 
461
485
  def __repr__(self) -> str:
462
486
  authed = [item["provider"] for item in self.auth.list()]
463
- return f"PyGeoFetch(authenticated={authed}, cache_entries={len(self.searcher.cache._cache)})"
487
+ return f"PyGeoFetch(authenticated={authed}, cache_entries={len(self.searcher.cache._cache)})"
@@ -1,4 +1,4 @@
1
- {% set version = "1.8.0" %}
1
+ {% set version = "1.9.1" %}
2
2
 
3
3
  package:
4
4
  name: pygeofetch
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygeofetch
3
- Version: 1.8.0
3
+ Version: 1.9.1
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
@@ -94,8 +94,8 @@ Requires-Dist: plotly>=5.14.0; extra == "viz"
94
94
  Requires-Dist: whitebox>=2.3.0; extra == "viz"
95
95
  Requires-Dist: whiteboxgui>=2.3.0; extra == "viz"
96
96
  Requires-Dist: geemap>=0.28.0; extra == "viz"
97
- Requires-Dist: osmnx>=1.8.0; extra == "viz"
98
- Requires-Dist: contextily>=1.8.0; extra == "viz"
97
+ Requires-Dist: osmnx>=1.9.1; extra == "viz"
98
+ Requires-Dist: contextily>=1.9.1; extra == "viz"
99
99
  Requires-Dist: xyzservices>=2023.10.0; extra == "viz"
100
100
  Requires-Dist: mapclassify>=2.5.0; extra == "viz"
101
101
  Requires-Dist: geoplot>=0.5.0; extra == "viz"
@@ -467,6 +467,70 @@ pygeofetch proc-pipeline template change_detection
467
467
 
468
468
  ---
469
469
 
470
+
471
+ ### 🌐 InSAR Processing (`pygeofetch.insar`)
472
+
473
+ 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.
474
+
475
+ ```bash
476
+ pip install "pygeofetch[insar]" # native SBAS inversion
477
+ pip install "pygeofetch[insar-full]" # + MintPy passthrough for advanced corrections
478
+ ```
479
+
480
+ | Component | Description |
481
+ |---|---|
482
+ | `InterferogramGenerator` | Coregistration (real orbit-based, or shape-based fallback) + Enhanced Spectral Diversity (ESD) refinement for TOPS burst continuity + topographic phase removal |
483
+ | `PhaseUnwrapper` | SNAPHU (Chen & Zebker 2001) via the official `snaphu-py` bindings — the same algorithm used by ASF, ISCE2/3, GAMMA, and SNAP |
484
+ | `AtmosphericCorrector` | Elevation-correlated regression or ERA5 reanalysis-based tropospheric delay correction |
485
+ | `SBASTimeSeries` | Small BAseline Subset displacement/velocity inversion (Berardino et al. 2002) |
486
+ | `DataValidator` | SLC, coherence, and SBAS-network sanity checks, wired in at every real pipeline entry point |
487
+
488
+ 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.
489
+
490
+ Every stage supports automatic visualization (`auto_visualize=True`) and optional GPU acceleration (`use_gpu=True`, CuPy) for coherence estimation and SBAS inversion on large scenes.
491
+
492
+ See [`pygeofetch/insar/README.md`](pygeofetch/insar/README.md) for the full processing chain, verification methodology, and current limitations.
493
+
494
+
495
+ ```python
496
+ # InSAR — search to SBAS time series
497
+ from pygeofetch.insar import (
498
+ InterferogramGenerator, PhaseUnwrapper, AtmosphericCorrector,
499
+ SBASTimeSeries, DataValidator,
500
+ )
501
+ from pygeofetch.insar.timeseries import InterferogramPair
502
+ from pygeofetch.core.orbits import fetch_orbit_file
503
+
504
+ # Coregistration + interferogram formation (real orbit-based when a DEM,
505
+ # both SAFE archives, and both orbit files are supplied; falls back to
506
+ # shape-based resampling otherwise)
507
+ gen = InterferogramGenerator(coherence_window=5, esd_enabled=True, use_gpu=False)
508
+ result = gen.process_pair(
509
+ reference="slc_ref.tif", secondary="slc_sec.tif", dem="dem.tif",
510
+ reference_safe_zip="ref.SAFE.zip", secondary_safe_zip="sec.SAFE.zip",
511
+ reference_orbit_file=fetch_orbit_file("S1A_..._ref"),
512
+ secondary_orbit_file=fetch_orbit_file("S1A_..._sec"),
513
+ )
514
+ result.save("./output", auto_visualize=True)
515
+
516
+ # Atmospheric correction + phase unwrapping
517
+ atm = AtmosphericCorrector(method="elevation")
518
+ corrected_phase = atm.correct(result.interferogram, dem="dem.tif")
519
+
520
+ unwrapper = PhaseUnwrapper(cost_mode="defo", init_method="mcf")
521
+ unwrapped, conncomp = unwrapper.unwrap(corrected_phase, result.coherence)
522
+
523
+ # SBAS time series inversion across a network of interferograms
524
+ pairs = [
525
+ InterferogramPair("2026-01-01", "2026-01-13", unwrapped, result.coherence),
526
+ # ... additional pairs forming a connected network
527
+ ]
528
+ sbas = SBASTimeSeries(wavelength_m=0.05546576, reference_date="2026-01-01")
529
+ ts_result = sbas.invert(pairs, reference_pixel=(10, 15)) # known-stable pixel
530
+ ts_result.save("./timeseries", auto_visualize=True)
531
+ print(f"Mean velocity: {ts_result.velocity.mean()*1000:.1f} mm/year")
532
+ ```
533
+
470
534
  ## 🖥️ Complete CLI Reference
471
535
 
472
536
  ```
@@ -653,3 +717,8 @@ pytest tests/unit/ -v
653
717
  pygeofetch is free and open source software, licensed under the [MIT License](LICENSE).
654
718
 
655
719
  © 2026 Samuel Appiah Kubi. Part of the **PyGeoVision** platform — [pygeofetch](https://github.com/appiahkubis14/pygeofetch) (data + processing) complete Earth observation pipeline.
720
+
721
+
722
+
723
+
724
+
@@ -90,8 +90,8 @@ plotly>=5.14.0
90
90
  whitebox>=2.3.0
91
91
  whiteboxgui>=2.3.0
92
92
  geemap>=0.28.0
93
- osmnx>=1.8.0
94
- contextily>=1.8.0
93
+ osmnx>=1.9.1
94
+ contextily>=1.9.1
95
95
  xyzservices>=2023.10.0
96
96
  mapclassify>=2.5.0
97
97
  geoplot>=0.5.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pygeofetch"
7
- version = "1.8.0"
7
+ version = "1.9.1"
8
8
  description = "Universal satellite data pipeline + geospatial processing platform"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -97,8 +97,8 @@ viz = [
97
97
  "whitebox>=2.3.0",
98
98
  "whiteboxgui>=2.3.0",
99
99
  "geemap>=0.28.0",
100
- "osmnx>=1.8.0",
101
- "contextily>=1.8.0",
100
+ "osmnx>=1.9.1",
101
+ "contextily>=1.9.1",
102
102
  "xyzservices>=2023.10.0",
103
103
  "mapclassify>=2.5.0",
104
104
  "geoplot>=0.5.0",
@@ -143,7 +143,7 @@ dev = [
143
143
  insar-full = [
144
144
  "snaphu>=0.1",
145
145
  "scipy>=1.12",
146
- "mintpy>=1.5",
146
+ "mintpy>=1.5", # <- almost certainly this one
147
147
  "pyaps3>=0.3",
148
148
  ]
149
149
 
File without changes
File without changes
File without changes