PyGeoFetch 2.0.6__tar.gz → 2.0.8__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-2.0.6 → pygeofetch-2.0.8}/CHANGELOG.md +6 -6
- {pygeofetch-2.0.6/pygeofetch.egg-info → pygeofetch-2.0.8}/PKG-INFO +1 -1
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/__init__.py +2 -2
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/main.py +2 -2
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/unwrap.py +91 -27
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/meta.yaml +1 -1
- {pygeofetch-2.0.6 → pygeofetch-2.0.8/pygeofetch.egg-info}/PKG-INFO +1 -1
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pyproject.toml +1 -1
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/LICENSE +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/MANIFEST.in +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/README.md +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/auth_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/config_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/download_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/index_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/pipeline_process_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/postprocess_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/preprocess_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/sar_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/search_commands.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/config/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/config/defaults.yaml +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/config/settings.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/authenticator.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/cache_manager.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/downloader.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/engine.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/logging.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/orbits.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/scheduler.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/searcher.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/annotation.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/atmosphere.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/coregister.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/deburst.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/esd.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/extraction.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/flatearth.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/geolocation.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/gpu.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/interferogram.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/ionosphere.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/splitspectrum_diagnostic.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/stack_selection.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/synthetic.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/timeseries.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/validate.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/visualize.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/workflow.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/download_task.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/satellite_data.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/search_query.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/user_auth.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/base.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/batch.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/indices.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/pipeline.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/postprocessor.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/preprocessor.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/sar.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/indices.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/landsat.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/loader.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/stacker.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/timeseries.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/airbus_oneatlas.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/alaska_satellite_facility.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/aws_earth.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/base.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/copernicus.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/digitalglobe.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/earth_explorer_additional.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/element84.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/eodag_provider.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/esa_scihub.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/geoserver_generic.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/google_earth_engine.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/inpe_cbers.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/isro_bhuvan.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/jaxa_earth.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/maxar_gbdx.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/nasa_earthdata.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/nasa_earthdata_cloud.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/noaa_big_data.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/opentopography.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/planet.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/planetary_computer.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/sentinel_hub.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/terrabotics.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/usgs.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/_native.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/_ost.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/_sarxarray.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/extraction.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/processor.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/file_utils.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/gcp_recovery.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/geo_utils.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/logging_setup.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/retry_handler.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/validators.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/viz/__init__.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/viz/map.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/viz/plot.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/SOURCES.txt +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/dependency_links.txt +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/entry_points.txt +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/not-zip-safe +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/requires.txt +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/top_level.txt +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/setup.cfg +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_atmospheric_circular_regression (1).py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_atmospheric_circular_regression.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_build_sbas_network.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_burst_metadata.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_burst_processing_integration.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_coregister_integration.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_coregister_upgrades.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_era5_atmospheric_correction.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_extraction.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_flat_earth_phase.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_gcp_reprojection.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_insar.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_ionosphere.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_models.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_pgv_integration_contract.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_provider_geometry_audit (1).py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_provider_geometry_audit.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_provider_scene_disambiguation.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_providers.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_raster_collocation_integration.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_search_download.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_splitspectrum_diagnostic.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_utils.py +0 -0
- {pygeofetch-2.0.6 → pygeofetch-2.0.8}/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/2.0.
|
|
4
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/2.0.8/).
|
|
5
5
|
|
|
6
|
-
## [2.0.
|
|
6
|
+
## [2.0.8] — 2026-07-29
|
|
7
7
|
|
|
8
8
|
### Added
|
|
9
9
|
- Major SNAPHU unwrapping improvements for urban InSAR applications
|
|
@@ -51,7 +51,7 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/2.0.6/).
|
|
|
51
51
|
|
|
52
52
|
### Migration Guide
|
|
53
53
|
```python
|
|
54
|
-
# Before (v2.0.
|
|
54
|
+
# Before (v2.0.8)
|
|
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
|
-
## [2.0.
|
|
75
|
+
## [2.0.8] — 2026-07-12
|
|
76
76
|
|
|
77
77
|
### Added
|
|
78
78
|
- Federated search across 22+ satellite data providers
|
|
@@ -188,8 +188,8 @@ unwrapped = unwrapper.unwrap(
|
|
|
188
188
|
|
|
189
189
|
| Version | Date | Key Changes |
|
|
190
190
|
|---------|------------|-------------|
|
|
191
|
-
| **2.0.
|
|
192
|
-
| **2.0.
|
|
191
|
+
| **2.0.8** | 2026-07-29 | SNAPHU unwrapping fixes, 87.1% reliable pixels |
|
|
192
|
+
| **2.0.8** | 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,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
PyGeoFetch v2.0.
|
|
2
|
+
PyGeoFetch v2.0.8 — Universal Satellite Data Pipeline.
|
|
3
3
|
|
|
4
4
|
Unified access to 22+ satellite data providers with a consistent
|
|
5
5
|
Python API and CLI. Supports authentication management, federated search,
|
|
@@ -30,7 +30,7 @@ CLI::
|
|
|
30
30
|
pygeofetch doctor
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
__version__ = "2.0.
|
|
33
|
+
__version__ = "2.0.8"
|
|
34
34
|
__author__ = "PyGeoFetch Contributors"
|
|
35
35
|
__license__ = "MIT"
|
|
36
36
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
PyGeoFetch CLI v2.0.
|
|
2
|
+
PyGeoFetch CLI v2.0.8 main entry point.
|
|
3
3
|
|
|
4
4
|
Full command reference:
|
|
5
5
|
pygeofetch auth — credential management
|
|
@@ -71,7 +71,7 @@ def cli(
|
|
|
71
71
|
) -> None:
|
|
72
72
|
"""
|
|
73
73
|
\b
|
|
74
|
-
PyGeoFetch v2.0.
|
|
74
|
+
PyGeoFetch v2.0.8 — Universal Satellite Data Pipeline
|
|
75
75
|
===========================================================
|
|
76
76
|
Unified access to 22+ satellite data providers.
|
|
77
77
|
|
|
@@ -451,14 +451,15 @@ class PhaseUnwrapper:
|
|
|
451
451
|
def _unwrap_cli(self, igram, corr, nlooks, min_conncomp_frac, min_region_size):
|
|
452
452
|
"""
|
|
453
453
|
Fallback unwrapping using the SNAPHU CLI executable.
|
|
454
|
-
|
|
454
|
+
Includes auto-repair for the infamous 0xC0000135 (STATUS_DLL_NOT_FOUND) error.
|
|
455
455
|
"""
|
|
456
456
|
import numpy as np
|
|
457
457
|
|
|
458
458
|
cli_path = _ensure_snaphu_cli()
|
|
459
459
|
height, width = igram.shape
|
|
460
|
+
bin_dir = Path(cli_path).parent
|
|
460
461
|
|
|
461
|
-
|
|
462
|
+
def _run_snaphu(tmp_dir):
|
|
462
463
|
tmp = Path(tmp_dir)
|
|
463
464
|
igram_path = tmp / "igram.cpx"
|
|
464
465
|
corr_path = tmp / "corr.cor"
|
|
@@ -466,42 +467,50 @@ class PhaseUnwrapper:
|
|
|
466
467
|
cc_path = tmp / "conncomp.cc"
|
|
467
468
|
conf_path = tmp / "snaphu.conf"
|
|
468
469
|
|
|
469
|
-
# Write binary files
|
|
470
470
|
igram.tofile(str(igram_path))
|
|
471
471
|
corr.tofile(str(corr_path))
|
|
472
472
|
|
|
473
|
-
# Write config file using relative paths to avoid Windows space issues
|
|
474
473
|
nlooks_int = max(1, int(nlooks))
|
|
475
474
|
conf_text = f"""INFILE igram.cpx
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
475
|
+
INFILEFORMAT COMPLEX_DATA
|
|
476
|
+
CORRFILE corr.cor
|
|
477
|
+
CORRFILEFORMAT FLOAT_DATA
|
|
478
|
+
OUTFILE unw.unw
|
|
479
|
+
OUTFILEFORMAT FLOAT_DATA
|
|
480
|
+
CONNCOMPFILE conncomp.cc
|
|
481
|
+
CONNCOMPOUTFORMAT UINT_DATA
|
|
482
|
+
LINELENGTH {width}
|
|
483
|
+
STATCOSTMODE {self._cost_mode.upper()}
|
|
484
|
+
INITMETHOD {self._init_method.upper()}
|
|
485
|
+
NLOOKSRANGE {nlooks_int}
|
|
486
|
+
NLOOKSAZ {nlooks_int}
|
|
487
|
+
"""
|
|
489
488
|
conf_path.write_text(conf_text)
|
|
490
489
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
490
|
+
cmd = [cli_path, "-f", "snaphu.conf"]
|
|
491
|
+
result = subprocess.run(cmd, capture_output=True, text=True, cwd=str(tmp), timeout=3600)
|
|
492
|
+
return result, unw_path, cc_path
|
|
493
|
+
|
|
494
|
+
with tempfile.TemporaryDirectory() as tmp_dir:
|
|
495
|
+
result, unw_path, cc_path = _run_snaphu(tmp_dir)
|
|
496
|
+
|
|
497
|
+
# AUTO-REPAIR: Catch Windows STATUS_DLL_NOT_FOUND (0xC0000135)
|
|
498
|
+
if result.returncode in (3221225781, -1073741515):
|
|
499
|
+
logger.warning(
|
|
500
|
+
"SNAPHU crashed with STATUS_DLL_NOT_FOUND (0xC0000135). "
|
|
501
|
+
"Auto-bundling MSVC runtime DLLs..."
|
|
502
|
+
)
|
|
503
|
+
self._ensure_msvc_runtime(bin_dir)
|
|
504
|
+
|
|
505
|
+
logger.info("Retrying SNAPHU with bundled DLLs...")
|
|
506
|
+
result, unw_path, cc_path = _run_snaphu(tmp_dir)
|
|
507
|
+
|
|
508
|
+
if result.returncode != 0:
|
|
509
|
+
raise RuntimeError(f"SNAPHU CLI failed with code {result.returncode}: {result.stderr}")
|
|
499
510
|
|
|
500
|
-
# Read outputs
|
|
501
511
|
unw = np.fromfile(str(unw_path), dtype=np.float32).reshape((height, width))
|
|
502
512
|
conncomp = np.fromfile(str(cc_path), dtype=np.uint32).reshape((height, width))
|
|
503
513
|
|
|
504
|
-
# Apply reliability filtering to match Python API behavior
|
|
505
514
|
total_pixels = height * width
|
|
506
515
|
labels, counts = np.unique(conncomp, return_counts=True)
|
|
507
516
|
for lbl, count in zip(labels, counts):
|
|
@@ -512,6 +521,61 @@ class PhaseUnwrapper:
|
|
|
512
521
|
|
|
513
522
|
return unw, conncomp.astype(np.int32)
|
|
514
523
|
|
|
524
|
+
def _ensure_msvc_runtime(self, bin_dir: Path):
|
|
525
|
+
"""
|
|
526
|
+
Fixes the 0xC0000135 error by finding the required MSVC DLLs
|
|
527
|
+
already present in the user's Python environment (e.g., from
|
|
528
|
+
numpy/scipy wheels) and copying them next to snaphu.exe.
|
|
529
|
+
"""
|
|
530
|
+
import sys
|
|
531
|
+
import shutil
|
|
532
|
+
|
|
533
|
+
required_dlls = ["vcruntime140.dll", "msvcp140.dll"]
|
|
534
|
+
missing = [dll for dll in required_dlls if not (bin_dir / dll).exists()]
|
|
535
|
+
|
|
536
|
+
if not missing:
|
|
537
|
+
return
|
|
538
|
+
|
|
539
|
+
logger.info(f"SNAPHU requires {missing}. Searching local Python environment...")
|
|
540
|
+
|
|
541
|
+
found = {}
|
|
542
|
+
for path in sys.path:
|
|
543
|
+
if not path or not Path(path).exists():
|
|
544
|
+
continue
|
|
545
|
+
try:
|
|
546
|
+
p = Path(path)
|
|
547
|
+
for dll in missing:
|
|
548
|
+
if dll in found:
|
|
549
|
+
continue
|
|
550
|
+
# Check .libs folders first (where numpy/scipy put them)
|
|
551
|
+
for libs_dir in p.glob("*.libs"):
|
|
552
|
+
target = libs_dir / dll
|
|
553
|
+
if target.exists():
|
|
554
|
+
found[dll] = target
|
|
555
|
+
break
|
|
556
|
+
if dll in found:
|
|
557
|
+
continue
|
|
558
|
+
# Fallback to full rglob if not in .libs
|
|
559
|
+
for target in p.rglob(dll):
|
|
560
|
+
found[dll] = target
|
|
561
|
+
break
|
|
562
|
+
except Exception:
|
|
563
|
+
continue
|
|
564
|
+
|
|
565
|
+
if len(found) == len(missing):
|
|
566
|
+
logger.info("Found MSVC DLLs in local Python environment. Copying to SNAPHU bin...")
|
|
567
|
+
for dll, src in found.items():
|
|
568
|
+
shutil.copy2(src, bin_dir / dll)
|
|
569
|
+
return
|
|
570
|
+
|
|
571
|
+
raise RuntimeError(
|
|
572
|
+
f"SNAPHU requires the Microsoft Visual C++ Redistributable DLLs ({missing}), "
|
|
573
|
+
"but they could not be found in your Python environment.\n"
|
|
574
|
+
"Please install the Microsoft Visual C++ Redistributable manually from:\n"
|
|
575
|
+
"https://aka.ms/vs/17/release/vc_redist.x64.exe\n"
|
|
576
|
+
"Then restart your Jupyter kernel and try again."
|
|
577
|
+
)
|
|
578
|
+
|
|
515
579
|
def unwrap(
|
|
516
580
|
self,
|
|
517
581
|
interferogram: Any,
|
|
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
|
|
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
|