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.
Files changed (144) hide show
  1. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/CHANGELOG.md +6 -6
  2. {pygeofetch-2.0.6/pygeofetch.egg-info → pygeofetch-2.0.8}/PKG-INFO +1 -1
  3. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/__init__.py +2 -2
  4. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/main.py +2 -2
  5. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/unwrap.py +91 -27
  6. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/meta.yaml +1 -1
  7. {pygeofetch-2.0.6 → pygeofetch-2.0.8/pygeofetch.egg-info}/PKG-INFO +1 -1
  8. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pyproject.toml +1 -1
  9. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/LICENSE +0 -0
  10. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/MANIFEST.in +0 -0
  11. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/README.md +0 -0
  12. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/__init__.py +0 -0
  13. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/auth_commands.py +0 -0
  14. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/config_commands.py +0 -0
  15. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/download_commands.py +0 -0
  16. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/index_commands.py +0 -0
  17. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/pipeline_process_commands.py +0 -0
  18. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/postprocess_commands.py +0 -0
  19. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/preprocess_commands.py +0 -0
  20. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/sar_commands.py +0 -0
  21. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/cli/search_commands.py +0 -0
  22. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/config/__init__.py +0 -0
  23. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/config/defaults.yaml +0 -0
  24. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/config/settings.py +0 -0
  25. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/__init__.py +0 -0
  26. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/authenticator.py +0 -0
  27. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/cache_manager.py +0 -0
  28. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/downloader.py +0 -0
  29. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/engine.py +0 -0
  30. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/logging.py +0 -0
  31. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/orbits.py +0 -0
  32. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/scheduler.py +0 -0
  33. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/core/searcher.py +0 -0
  34. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/__init__.py +0 -0
  35. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/annotation.py +0 -0
  36. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/atmosphere.py +0 -0
  37. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/coregister.py +0 -0
  38. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/deburst.py +0 -0
  39. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/esd.py +0 -0
  40. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/extraction.py +0 -0
  41. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/flatearth.py +0 -0
  42. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/geolocation.py +0 -0
  43. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/gpu.py +0 -0
  44. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/interferogram.py +0 -0
  45. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/ionosphere.py +0 -0
  46. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/splitspectrum_diagnostic.py +0 -0
  47. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/stack_selection.py +0 -0
  48. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/synthetic.py +0 -0
  49. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/timeseries.py +0 -0
  50. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/validate.py +0 -0
  51. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/visualize.py +0 -0
  52. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/insar/workflow.py +0 -0
  53. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/__init__.py +0 -0
  54. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/download_task.py +0 -0
  55. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/satellite_data.py +0 -0
  56. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/search_query.py +0 -0
  57. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/models/user_auth.py +0 -0
  58. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/__init__.py +0 -0
  59. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/base.py +0 -0
  60. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/batch.py +0 -0
  61. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/indices.py +0 -0
  62. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/pipeline.py +0 -0
  63. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/postprocessor.py +0 -0
  64. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/preprocessor.py +0 -0
  65. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processing/sar.py +0 -0
  66. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/__init__.py +0 -0
  67. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/indices.py +0 -0
  68. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/landsat.py +0 -0
  69. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/loader.py +0 -0
  70. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/stacker.py +0 -0
  71. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/processor/timeseries.py +0 -0
  72. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/__init__.py +0 -0
  73. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/airbus_oneatlas.py +0 -0
  74. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/alaska_satellite_facility.py +0 -0
  75. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/aws_earth.py +0 -0
  76. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/base.py +0 -0
  77. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/copernicus.py +0 -0
  78. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/digitalglobe.py +0 -0
  79. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/earth_explorer_additional.py +0 -0
  80. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/element84.py +0 -0
  81. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/eodag_provider.py +0 -0
  82. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/esa_scihub.py +0 -0
  83. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/geoserver_generic.py +0 -0
  84. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/google_earth_engine.py +0 -0
  85. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/inpe_cbers.py +0 -0
  86. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/isro_bhuvan.py +0 -0
  87. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/jaxa_earth.py +0 -0
  88. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/maxar_gbdx.py +0 -0
  89. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/nasa_earthdata.py +0 -0
  90. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/nasa_earthdata_cloud.py +0 -0
  91. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/noaa_big_data.py +0 -0
  92. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/opentopography.py +0 -0
  93. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/planet.py +0 -0
  94. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/planetary_computer.py +0 -0
  95. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/sentinel_hub.py +0 -0
  96. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/terrabotics.py +0 -0
  97. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/providers/usgs.py +0 -0
  98. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/__init__.py +0 -0
  99. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/_native.py +0 -0
  100. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/_ost.py +0 -0
  101. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/_sarxarray.py +0 -0
  102. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/extraction.py +0 -0
  103. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/sar/processor.py +0 -0
  104. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/__init__.py +0 -0
  105. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/file_utils.py +0 -0
  106. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/gcp_recovery.py +0 -0
  107. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/geo_utils.py +0 -0
  108. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/logging_setup.py +0 -0
  109. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/retry_handler.py +0 -0
  110. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/utils/validators.py +0 -0
  111. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/viz/__init__.py +0 -0
  112. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/viz/map.py +0 -0
  113. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch/viz/plot.py +0 -0
  114. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/SOURCES.txt +0 -0
  115. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/dependency_links.txt +0 -0
  116. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/entry_points.txt +0 -0
  117. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/not-zip-safe +0 -0
  118. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/requires.txt +0 -0
  119. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/pygeofetch.egg-info/top_level.txt +0 -0
  120. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/setup.cfg +0 -0
  121. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_atmospheric_circular_regression (1).py +0 -0
  122. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_atmospheric_circular_regression.py +0 -0
  123. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_build_sbas_network.py +0 -0
  124. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_burst_metadata.py +0 -0
  125. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_burst_processing_integration.py +0 -0
  126. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_coregister_integration.py +0 -0
  127. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_coregister_upgrades.py +0 -0
  128. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_era5_atmospheric_correction.py +0 -0
  129. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_extraction.py +0 -0
  130. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_flat_earth_phase.py +0 -0
  131. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_gcp_reprojection.py +0 -0
  132. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_insar.py +0 -0
  133. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_ionosphere.py +0 -0
  134. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_models.py +0 -0
  135. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_pgv_integration_contract.py +0 -0
  136. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_provider_geometry_audit (1).py +0 -0
  137. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_provider_geometry_audit.py +0 -0
  138. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_provider_scene_disambiguation.py +0 -0
  139. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_providers.py +0 -0
  140. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_raster_collocation_integration.py +0 -0
  141. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_search_download.py +0 -0
  142. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_splitspectrum_diagnostic.py +0 -0
  143. {pygeofetch-2.0.6 → pygeofetch-2.0.8}/tests/test_utils.py +0 -0
  144. {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.6/).
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/2.0.8/).
5
5
 
6
- ## [2.0.6] — 2026-07-29
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.6)
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.6] — 2026-07-12
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.6** | 2026-07-29 | SNAPHU unwrapping fixes, 87.1% reliable pixels |
192
- | **2.0.6** | 2026-07-12 | 22 providers, 17 indices, Sentinel-1C/D |
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygeofetch
3
- Version: 2.0.6
3
+ Version: 2.0.8
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
@@ -1,5 +1,5 @@
1
1
  """
2
- PyGeoFetch v2.0.6 — Universal Satellite Data Pipeline.
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.6"
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.6 main entry point.
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.6 — Universal Satellite Data Pipeline
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
- Bypasses Python C-extension compilation issues on Windows entirely.
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
- with tempfile.TemporaryDirectory() as tmp_dir:
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
- INFILEFORMAT COMPLEX_DATA
477
- CORRFILE corr.cor
478
- CORRFILEFORMAT FLOAT_DATA
479
- OUTFILE unw.unw
480
- OUTFILEFORMAT FLOAT_DATA
481
- CONNCOMPFILE conncomp.cc
482
- CONNCOMPOUTFORMAT UINT_DATA
483
- LINELENGTH {width}
484
- STATCOSTMODE {self._cost_mode.upper()}
485
- INITMETHOD {self._init_method.upper()}
486
- NLOOKSRANGE {nlooks_int}
487
- NLOOKSAZ {nlooks_int}
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
- # Run SNAPHU from within the temp directory
492
- try:
493
- cmd = [cli_path, "-f", "snaphu.conf"]
494
- result = subprocess.run(cmd, capture_output=True, text=True, cwd=str(tmp), timeout=3600)
495
- if result.returncode != 0:
496
- raise RuntimeError(f"SNAPHU CLI failed with code {result.returncode}: {result.stderr}")
497
- except Exception as e:
498
- raise RuntimeError(f"SNAPHU CLI execution failed: {e}")
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,
@@ -1,4 +1,4 @@
1
- {% set version = "2.0.6" %}
1
+ {% set version = "2.0.8" %}
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: 2.0.6
3
+ Version: 2.0.8
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pygeofetch"
7
- version = "2.0.6"
7
+ version = "2.0.8"
8
8
  description = "Universal satellite data pipeline + geospatial processing platform"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
File without changes
File without changes
File without changes
File without changes