PyGeoFetch 2.0.7__tar.gz → 2.0.9__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.7 → pygeofetch-2.0.9}/CHANGELOG.md +6 -6
- {pygeofetch-2.0.7/pygeofetch.egg-info → pygeofetch-2.0.9}/PKG-INFO +1 -1
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/__init__.py +2 -2
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/main.py +2 -2
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/unwrap.py +50 -50
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/meta.yaml +1 -1
- {pygeofetch-2.0.7 → pygeofetch-2.0.9/pygeofetch.egg-info}/PKG-INFO +1 -1
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pyproject.toml +1 -1
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/LICENSE +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/MANIFEST.in +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/README.md +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/auth_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/config_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/download_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/index_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/pipeline_process_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/postprocess_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/preprocess_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/sar_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/cli/search_commands.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/config/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/config/defaults.yaml +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/config/settings.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/authenticator.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/cache_manager.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/downloader.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/engine.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/logging.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/orbits.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/scheduler.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/core/searcher.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/annotation.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/atmosphere.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/coregister.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/deburst.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/esd.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/extraction.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/flatearth.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/geolocation.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/gpu.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/interferogram.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/ionosphere.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/splitspectrum_diagnostic.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/stack_selection.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/synthetic.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/timeseries.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/validate.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/visualize.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/insar/workflow.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/models/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/models/download_task.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/models/satellite_data.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/models/search_query.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/models/user_auth.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processing/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processing/base.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processing/batch.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processing/indices.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processing/pipeline.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processing/postprocessor.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processing/preprocessor.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processing/sar.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processor/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processor/indices.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processor/landsat.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processor/loader.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processor/stacker.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/processor/timeseries.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/airbus_oneatlas.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/alaska_satellite_facility.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/aws_earth.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/base.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/copernicus.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/digitalglobe.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/earth_explorer_additional.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/element84.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/eodag_provider.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/esa_scihub.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/geoserver_generic.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/google_earth_engine.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/inpe_cbers.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/isro_bhuvan.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/jaxa_earth.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/maxar_gbdx.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/nasa_earthdata.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/nasa_earthdata_cloud.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/noaa_big_data.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/opentopography.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/planet.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/planetary_computer.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/sentinel_hub.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/terrabotics.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/providers/usgs.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/sar/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/sar/_native.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/sar/_ost.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/sar/_sarxarray.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/sar/extraction.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/sar/processor.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/utils/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/utils/file_utils.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/utils/gcp_recovery.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/utils/geo_utils.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/utils/logging_setup.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/utils/retry_handler.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/utils/validators.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/viz/__init__.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/viz/map.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch/viz/plot.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch.egg-info/SOURCES.txt +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch.egg-info/dependency_links.txt +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch.egg-info/entry_points.txt +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch.egg-info/not-zip-safe +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch.egg-info/requires.txt +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/pygeofetch.egg-info/top_level.txt +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/setup.cfg +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_atmospheric_circular_regression (1).py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_atmospheric_circular_regression.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_build_sbas_network.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_burst_metadata.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_burst_processing_integration.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_coregister_integration.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_coregister_upgrades.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_era5_atmospheric_correction.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_extraction.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_flat_earth_phase.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_gcp_reprojection.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_insar.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_ionosphere.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_models.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_pgv_integration_contract.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_provider_geometry_audit (1).py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_provider_geometry_audit.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_provider_scene_disambiguation.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_providers.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_raster_collocation_integration.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_search_download.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_splitspectrum_diagnostic.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/tests/test_utils.py +0 -0
- {pygeofetch-2.0.7 → pygeofetch-2.0.9}/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.9/).
|
|
5
5
|
|
|
6
|
-
## [2.0.
|
|
6
|
+
## [2.0.9] — 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.7/).
|
|
|
51
51
|
|
|
52
52
|
### Migration Guide
|
|
53
53
|
```python
|
|
54
|
-
# Before (v2.0.
|
|
54
|
+
# Before (v2.0.9)
|
|
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.9] — 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.9** | 2026-07-29 | SNAPHU unwrapping fixes, 87.1% reliable pixels |
|
|
192
|
+
| **2.0.9** | 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.9 — 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.9"
|
|
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.9 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.9 — Universal Satellite Data Pipeline
|
|
75
75
|
===========================================================
|
|
76
76
|
Unified access to 22+ satellite data providers.
|
|
77
77
|
|
|
@@ -451,13 +451,13 @@ 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
|
-
Bypasses Python C-extension compilation issues on Windows entirely.
|
|
455
454
|
Includes auto-repair for the infamous 0xC0000135 (STATUS_DLL_NOT_FOUND) error.
|
|
456
455
|
"""
|
|
457
456
|
import numpy as np
|
|
458
457
|
|
|
459
458
|
cli_path = _ensure_snaphu_cli()
|
|
460
459
|
height, width = igram.shape
|
|
460
|
+
bin_dir = Path(cli_path).parent
|
|
461
461
|
|
|
462
462
|
def _run_snaphu(tmp_dir):
|
|
463
463
|
tmp = Path(tmp_dir)
|
|
@@ -467,11 +467,9 @@ class PhaseUnwrapper:
|
|
|
467
467
|
cc_path = tmp / "conncomp.cc"
|
|
468
468
|
conf_path = tmp / "snaphu.conf"
|
|
469
469
|
|
|
470
|
-
# Write binary files
|
|
471
470
|
igram.tofile(str(igram_path))
|
|
472
471
|
corr.tofile(str(corr_path))
|
|
473
472
|
|
|
474
|
-
# Write config file using relative paths to avoid Windows space issues
|
|
475
473
|
nlooks_int = max(1, int(nlooks))
|
|
476
474
|
conf_text = f"""INFILE igram.cpx
|
|
477
475
|
INFILEFORMAT COMPLEX_DATA
|
|
@@ -489,7 +487,6 @@ class PhaseUnwrapper:
|
|
|
489
487
|
"""
|
|
490
488
|
conf_path.write_text(conf_text)
|
|
491
489
|
|
|
492
|
-
# Run SNAPHU from within the temp directory
|
|
493
490
|
cmd = [cli_path, "-f", "snaphu.conf"]
|
|
494
491
|
result = subprocess.run(cmd, capture_output=True, text=True, cwd=str(tmp), timeout=3600)
|
|
495
492
|
return result, unw_path, cc_path
|
|
@@ -497,30 +494,23 @@ class PhaseUnwrapper:
|
|
|
497
494
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
|
498
495
|
result, unw_path, cc_path = _run_snaphu(tmp_dir)
|
|
499
496
|
|
|
500
|
-
# ═══════════════════════════════════════════════════════════════
|
|
501
497
|
# AUTO-REPAIR: Catch Windows STATUS_DLL_NOT_FOUND (0xC0000135)
|
|
502
|
-
# 3221225781 is the unsigned int representation of 0xC0000135
|
|
503
|
-
# -1073741515 is the signed int representation. We check both.
|
|
504
|
-
# ═══════════════════════════════════════════════════════════════
|
|
505
498
|
if result.returncode in (3221225781, -1073741515):
|
|
506
499
|
logger.warning(
|
|
507
500
|
"SNAPHU crashed with STATUS_DLL_NOT_FOUND (0xC0000135). "
|
|
508
|
-
"
|
|
501
|
+
"Auto-bundling MSVC runtime DLLs..."
|
|
509
502
|
)
|
|
510
|
-
self._ensure_msvc_runtime()
|
|
503
|
+
self._ensure_msvc_runtime(bin_dir)
|
|
511
504
|
|
|
512
|
-
|
|
513
|
-
logger.info("Retrying SNAPHU after MSVC runtime installation...")
|
|
505
|
+
logger.info("Retrying SNAPHU with bundled DLLs...")
|
|
514
506
|
result, unw_path, cc_path = _run_snaphu(tmp_dir)
|
|
515
507
|
|
|
516
508
|
if result.returncode != 0:
|
|
517
509
|
raise RuntimeError(f"SNAPHU CLI failed with code {result.returncode}: {result.stderr}")
|
|
518
510
|
|
|
519
|
-
# Read outputs
|
|
520
511
|
unw = np.fromfile(str(unw_path), dtype=np.float32).reshape((height, width))
|
|
521
512
|
conncomp = np.fromfile(str(cc_path), dtype=np.uint32).reshape((height, width))
|
|
522
513
|
|
|
523
|
-
# Apply reliability filtering to match Python API behavior
|
|
524
514
|
total_pixels = height * width
|
|
525
515
|
labels, counts = np.unique(conncomp, return_counts=True)
|
|
526
516
|
for lbl, count in zip(labels, counts):
|
|
@@ -531,48 +521,58 @@ class PhaseUnwrapper:
|
|
|
531
521
|
|
|
532
522
|
return unw, conncomp.astype(np.int32)
|
|
533
523
|
|
|
534
|
-
def _ensure_msvc_runtime(self):
|
|
524
|
+
def _ensure_msvc_runtime(self, bin_dir: Path):
|
|
535
525
|
"""
|
|
536
|
-
Fixes the 0xC0000135 (STATUS_DLL_NOT_FOUND) error by
|
|
537
|
-
|
|
526
|
+
Fixes the 0xC0000135 (STATUS_DLL_NOT_FOUND) error by downloading
|
|
527
|
+
the required MSVC DLLs directly from NuGet (VCRuntime.140 package).
|
|
528
|
+
This requires ZERO admin rights and ZERO manual installation.
|
|
538
529
|
"""
|
|
539
|
-
import
|
|
530
|
+
import shutil
|
|
531
|
+
import zipfile
|
|
532
|
+
import io
|
|
533
|
+
import urllib.request
|
|
540
534
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
pass
|
|
535
|
+
required_dlls = ["vcruntime140.dll", "msvcp140.dll"]
|
|
536
|
+
missing = [dll for dll in required_dlls if not (bin_dir / dll).exists()]
|
|
537
|
+
|
|
538
|
+
if not missing:
|
|
539
|
+
return
|
|
547
540
|
|
|
548
|
-
logger.info("Downloading
|
|
549
|
-
vc_url = "https://aka.ms/vs/17/release/vc_redist.x64.exe"
|
|
541
|
+
logger.info(f"SNAPHU requires {missing}. Downloading directly from NuGet (no admin required)...")
|
|
550
542
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
)
|
|
543
|
+
# NuGet packages are just zip files. We download the VCRuntime.140 package
|
|
544
|
+
# which contains the exact DLLs we need for x64 Windows.
|
|
545
|
+
nuget_url = "https://www.nuget.org/api/v2/package/VCRuntime.140"
|
|
546
|
+
|
|
547
|
+
try:
|
|
548
|
+
req = urllib.request.Request(nuget_url, headers={'User-Agent': 'PyGeoFetch'})
|
|
549
|
+
with urllib.request.urlopen(req, timeout=30) as response:
|
|
550
|
+
nupkg_data = response.read()
|
|
560
551
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
552
|
+
extracted = 0
|
|
553
|
+
with zipfile.ZipFile(io.BytesIO(nupkg_data)) as zf:
|
|
554
|
+
for name in zf.namelist():
|
|
555
|
+
# We only want the 64-bit native DLLs
|
|
556
|
+
if "win-x64/native/" in name and name.lower().endswith(".dll"):
|
|
557
|
+
dll_name = Path(name).name
|
|
558
|
+
if dll_name.lower() in [m.lower() for m in missing]:
|
|
559
|
+
with zf.open(name) as src, open(bin_dir / dll_name, "wb") as dst:
|
|
560
|
+
shutil.copyfileobj(src, dst)
|
|
561
|
+
extracted += 1
|
|
562
|
+
|
|
563
|
+
if extracted == len(missing):
|
|
564
|
+
logger.info(f"Successfully extracted {extracted} MSVC DLLs to {bin_dir}. Retrying SNAPHU...")
|
|
565
|
+
return
|
|
566
|
+
else:
|
|
567
|
+
raise RuntimeError(f"Could not find all required DLLs in the NuGet package. Found {extracted}/{len(missing)}")
|
|
568
|
+
|
|
569
|
+
except Exception as e:
|
|
570
|
+
raise RuntimeError(
|
|
571
|
+
f"Failed to download/extract MSVC runtime DLLs from NuGet: {e}\n"
|
|
572
|
+
"As a last resort, please install the Microsoft Visual C++ Redistributable manually from:\n"
|
|
573
|
+
"https://aka.ms/vs/17/release/vc_redist.x64.exe\n"
|
|
574
|
+
"Then restart your Jupyter kernel."
|
|
575
|
+
)
|
|
576
576
|
|
|
577
577
|
def unwrap(
|
|
578
578
|
self,
|
|
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
|