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.
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/CHANGELOG.md +2 -2
- {pygeofetch-1.8.0/pygeofetch.egg-info → pygeofetch-1.9.1}/PKG-INFO +72 -3
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/README.md +69 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/__init__.py +1 -1
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/engine.py +32 -8
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/meta.yaml +1 -1
- {pygeofetch-1.8.0 → pygeofetch-1.9.1/pygeofetch.egg-info}/PKG-INFO +72 -3
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/requires.txt +2 -2
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pyproject.toml +4 -4
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/LICENSE +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/MANIFEST.in +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/auth_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/config_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/download_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/index_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/main.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/pipeline_process_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/postprocess_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/preprocess_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/sar_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/cli/search_commands.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/config/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/config/defaults.yaml +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/config/settings.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/authenticator.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/cache_manager.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/downloader.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/logging.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/orbits.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/scheduler.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/core/searcher.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/annotation.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/atmosphere.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/coregister.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/extraction.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/geolocation.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/gpu.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/interferogram.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/timeseries.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/unwrap.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/validate.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/insar/visualize.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/download_task.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/satellite_data.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/search_query.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/models/user_auth.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/base.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/batch.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/indices.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/pipeline.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/postprocessor.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/preprocessor.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processing/sar.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/indices.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/landsat.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/loader.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/stacker.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/processor/timeseries.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/airbus_oneatlas.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/alaska_satellite_facility.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/aws_earth.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/base.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/copernicus.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/digitalglobe.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/earth_explorer_additional.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/element84.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/eodag_provider.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/esa_scihub.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/geoserver_generic.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/google_earth_engine.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/inpe_cbers.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/isro_bhuvan.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/jaxa_earth.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/maxar_gbdx.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/nasa_earthdata.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/nasa_earthdata_cloud.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/noaa_big_data.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/opentopography.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/planet.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/planetary_computer.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/sentinel_hub.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/terrabotics.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/providers/usgs.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/_native.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/_ost.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/_sarxarray.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/extraction.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/sar/processor.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/file_utils.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/gcp_recovery.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/geo_utils.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/logging_setup.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/retry_handler.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/utils/validators.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/viz/__init__.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/viz/map.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch/viz/plot.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/SOURCES.txt +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/dependency_links.txt +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/entry_points.txt +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/not-zip-safe +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/pygeofetch.egg-info/top_level.txt +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/setup.cfg +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/tests/test_extraction.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/tests/test_insar.py +0 -0
- {pygeofetch-1.8.0 → pygeofetch-1.9.1}/tests/test_pgv_integration_contract.py +0 -0
- {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.
|
|
4
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.9.1/).
|
|
5
5
|
|
|
6
|
-
## [1.
|
|
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.
|
|
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.
|
|
98
|
-
Requires-Dist: contextily>=1.
|
|
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
|
+
|
|
@@ -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
|
|
222
|
-
|
|
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
|
-
|
|
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
|
|
232
|
-
"
|
|
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,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pygeofetch
|
|
3
|
-
Version: 1.
|
|
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.
|
|
98
|
-
Requires-Dist: contextily>=1.
|
|
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
|
+
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pygeofetch"
|
|
7
|
-
version = "1.
|
|
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.
|
|
101
|
-
"contextily>=1.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|