PyGeoFetch 2.3.0__py3-none-any.whl → 2.4.0__py3-none-any.whl

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/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- PyGeoFetch v2.3.0 — Universal Satellite Data Pipeline.
2
+ PyGeoFetch v2.4.0 — 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.3.0"
33
+ __version__ = "2.4.0"
34
34
  __author__ = "PyGeoFetch Contributors"
35
35
  __license__ = "MIT"
36
36
 
pygeofetch/cli/main.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- PyGeoFetch CLI v2.3.0 main entry point.
2
+ PyGeoFetch CLI v2.4.0 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.3.0 — Universal Satellite Data Pipeline
74
+ PyGeoFetch v2.4.0 — Universal Satellite Data Pipeline
75
75
  ===========================================================
76
76
  Unified access to 22+ satellite data providers.
77
77
 
@@ -356,6 +356,7 @@ class PhaseUnwrapper:
356
356
 
357
357
  def _unwrap_cli(self, igram, corr, nlooks, min_conncomp_frac, min_region_size):
358
358
  import numpy as np
359
+ import os
359
360
  cli_path = _ensure_snaphu_cli()
360
361
  height, width = igram.shape
361
362
  bin_dir = Path(cli_path).parent
@@ -371,10 +372,6 @@ class PhaseUnwrapper:
371
372
  corr.tofile(str(corr_path))
372
373
  nlooks_int = max(1, int(nlooks))
373
374
 
374
- # FIX: Removed 'CONNCOMPOUTFORMAT UINT_DATA'. It is not a valid
375
- # SNAPHU parameter. SNAPHU always writes connected components as
376
- # 32-bit unsigned integers by default. The strict Windows port
377
- # we use rejects the config file if it sees unknown keys.
378
375
  conf_text = f"""INFILE igram.cpx
379
376
  INFILEFORMAT COMPLEX_DATA
380
377
  CORRFILE corr.cor
@@ -396,7 +393,6 @@ NLOOKSAZ {nlooks_int}
396
393
  with tempfile.TemporaryDirectory() as tmp_dir:
397
394
  result, unw_path, cc_path = _run_snaphu(tmp_dir)
398
395
 
399
- # AUTO-REPAIR: Catch Windows STATUS_DLL_NOT_FOUND (0xC0000135)
400
396
  if result.returncode in (3221225781, -1073741515):
401
397
  logger.warning("SNAPHU crashed with STATUS_DLL_NOT_FOUND (0xC0000135). Auto-bundling runtime DLLs...")
402
398
  self._ensure_runtime_dlls(bin_dir)
@@ -406,8 +402,44 @@ NLOOKSAZ {nlooks_int}
406
402
  if result.returncode != 0:
407
403
  raise RuntimeError(f"SNAPHU CLI failed with code {result.returncode}: {result.stderr}")
408
404
 
409
- unw = np.fromfile(str(unw_path), dtype=np.float32).reshape((height, width))
410
- conncomp = np.fromfile(str(cc_path), dtype=np.uint32).reshape((height, width))
405
+ # ═══════════════════════════════════════════════════════════════
406
+ # SMART FILE READER (Handles Windows Port Quirks)
407
+ # ═══════════════════════════════════════════════════════════════
408
+ expected_pixels = height * width
409
+
410
+ # 1. Read Unwrapped Phase (Usually FLOAT_DATA = 4 bytes)
411
+ unw_size = os.path.getsize(str(unw_path))
412
+ unw_dtype = np.float32 if unw_size <= expected_pixels * 4 else np.float64
413
+ unw = np.fromfile(str(unw_path), dtype=unw_dtype)
414
+
415
+ # 2. Read Connected Components (Adapts to 1-byte, 2-byte, or 4-byte formats)
416
+ cc_size = os.path.getsize(str(cc_path))
417
+ if cc_size >= expected_pixels * 4:
418
+ cc_dtype = np.uint32
419
+ elif cc_size >= expected_pixels * 2:
420
+ cc_dtype = np.uint16
421
+ else:
422
+ cc_dtype = np.uint8 # The Windows port default
423
+
424
+ conncomp = np.fromfile(str(cc_path), dtype=cc_dtype)
425
+
426
+ # 3. Auto-heal the Windows "off-by-one" truncation bug
427
+ if conncomp.size < expected_pixels:
428
+ logger.warning(
429
+ "SNAPHU conncomp file is %d elements, expected %d. Padding missing bytes with 0 "
430
+ "(known Windows port truncation quirk).", conncomp.size, expected_pixels
431
+ )
432
+ conncomp = np.pad(conncomp, (0, expected_pixels - conncomp.size), mode='constant', constant_values=0)
433
+ elif conncomp.size > expected_pixels:
434
+ conncomp = conncomp[:expected_pixels]
435
+
436
+ if unw.size < expected_pixels:
437
+ unw = np.pad(unw, (0, expected_pixels - unw.size), mode='constant', constant_values=0)
438
+ elif unw.size > expected_pixels:
439
+ unw = unw[:expected_pixels]
440
+
441
+ unw = unw.reshape((height, width))
442
+ conncomp = conncomp.reshape((height, width))
411
443
 
412
444
  total_pixels = height * width
413
445
  labels, counts = np.unique(conncomp, return_counts=True)
@@ -591,4 +623,59 @@ NLOOKSAZ {nlooks_int}
591
623
 
592
624
  def _np(self):
593
625
  import numpy as np
594
- return np
626
+ return np
627
+
628
+
629
+ import shutil
630
+ import subprocess
631
+ import logging
632
+ import sys
633
+
634
+ logger = logging.getLogger(__name__)
635
+
636
+ def verify_snaphu_ready():
637
+ """
638
+ Proactively checks for snaphu availability to assure the user
639
+ that no manual installation is required.
640
+ """
641
+ # 1. Check for the standard SNAPHU binary in the system PATH
642
+ snaphu_bin = shutil.which("snaphu")
643
+ if snaphu_bin:
644
+ # Optional: Verify the binary actually executes and isn't just a broken alias
645
+ try:
646
+ subprocess.run(
647
+ ["snaphu"],
648
+ stdout=subprocess.DEVNULL,
649
+ stderr=subprocess.DEVNULL,
650
+ timeout=3
651
+ )
652
+ except Exception:
653
+ pass # Snaphu without args prints usage to stderr and exits; this is expected.
654
+
655
+ msg = f"✅ Success: snaphu binary detected at '{snaphu_bin}'. No manual installation needed."
656
+ print(msg)
657
+ logger.info(msg)
658
+ return True
659
+
660
+ # 2. Fallback: Check if it's available as a Python package/module
661
+ try:
662
+ import snaphu # or pysnaphu, depending on your wrapper
663
+ msg = "✅ Success: snaphu Python module detected. No manual installation needed."
664
+ print(msg)
665
+ logger.info(msg)
666
+ return True
667
+ except ImportError:
668
+ pass
669
+
670
+ # 3. If neither is found, handle the failure gracefully
671
+ msg = "❌ snaphu not found in PATH or Python environment. Phase unwrapping will fail."
672
+ print(msg)
673
+ logger.warning(msg)
674
+ return False
675
+
676
+ # --- Embed this early in your notebook or pipeline ---
677
+ snaphu_is_ready = verify_snaphu_ready()
678
+
679
+ if not snaphu_is_ready:
680
+ # Decide how to handle the missing dependency (see questions below)
681
+ pass
pygeofetch/meta.yaml CHANGED
@@ -1,4 +1,4 @@
1
- {% set version = "2.3.0" %}
1
+ {% set version = "2.4.0" %}
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.3.0
3
+ Version: 2.4.0
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
@@ -91,8 +91,8 @@ Requires-Dist: sidecar>=0.6.0; extra == "viz"
91
91
  Requires-Dist: bokeh>=3.0.0; extra == "viz"
92
92
  Requires-Dist: seaborn>=0.12.0; extra == "viz"
93
93
  Requires-Dist: plotly>=5.14.0; extra == "viz"
94
- Requires-Dist: whitebox>=2.3.0; extra == "viz"
95
- Requires-Dist: whiteboxgui>=2.3.0; extra == "viz"
94
+ Requires-Dist: whitebox>=2.4.0; extra == "viz"
95
+ Requires-Dist: whiteboxgui>=2.4.0; extra == "viz"
96
96
  Requires-Dist: geemap>=0.28.0; extra == "viz"
97
97
  Requires-Dist: osmnx>=1.9.4; extra == "viz"
98
98
  Requires-Dist: contextily>=1.9.4; extra == "viz"
@@ -1,11 +1,11 @@
1
- pygeofetch/__init__.py,sha256=fUNpnnugxPve0K3zsKxMYwR2zzlhdbdJWMARGZpMKNk,1990
2
- pygeofetch/meta.yaml,sha256=QFa2engAVMeSZRG1fzE6qD82AO-9rXoKR-wcpJvX7jg,1280
1
+ pygeofetch/__init__.py,sha256=_bHgoiQ6l5aQR6GOuqKKte2bqg51iJPILBNzLROiZUg,1990
2
+ pygeofetch/meta.yaml,sha256=_3LO3mdYsaEWdrrwTP6ITyr57YTTJmweff4ja5aqKmk,1280
3
3
  pygeofetch/cli/__init__.py,sha256=QZMIIHEgmjGFieucqq9fZ5uephxP9-jdu1s8Q4qqw8o,30
4
4
  pygeofetch/cli/auth_commands.py,sha256=YqbrN_BYcAYCaUIYLpSJ_VIw35tKFUiD9Kc55SWbDWg,7742
5
5
  pygeofetch/cli/config_commands.py,sha256=1Pps0HLCLPODMlM6SFV8ru3IKCDpexSTz8uKIXvIIF8,3918
6
6
  pygeofetch/cli/download_commands.py,sha256=reQ9vmA50mj1zqechjLHAOe_cjBfa1miqfWa8UiIlxU,11741
7
7
  pygeofetch/cli/index_commands.py,sha256=IoLGrsSU-lTcBitFFsg8EtucqSKZtNL-0ODj_I8Twew,10020
8
- pygeofetch/cli/main.py,sha256=XQGjVeZLlPzWf1khMWy0fdnjGekglnrXcPoKKHJZG0s,30335
8
+ pygeofetch/cli/main.py,sha256=ABJstgL_Z0wE7f-eSl8m6a3KEpaue54P5XG_M2W0Gac,30335
9
9
  pygeofetch/cli/pipeline_process_commands.py,sha256=OvuouT35zZlrC-7hWAJRfaY_aUNk4ScK0Fia9WVB_Gw,6904
10
10
  pygeofetch/cli/postprocess_commands.py,sha256=kof_f-kjjvYl5eqPqrcNHSOUM_qVkGdSh6-N4vcx2y4,5825
11
11
  pygeofetch/cli/preprocess_commands.py,sha256=cFp1VR03Q1pmCwiBWYmS5lXF3NOnzVAq3XgrZh3rBdU,8696
@@ -42,7 +42,7 @@ pygeofetch/insar/splitspectrum_diagnostic.py,sha256=_IlfBs__BW7Yz2RwdmWxfrOspe67
42
42
  pygeofetch/insar/stack_selection.py,sha256=FaRBXDNnLwwiXPGeALSW1AaUdpLFOEepVTgEGVfNC4o,37555
43
43
  pygeofetch/insar/synthetic.py,sha256=FazdaG_u3GR1qk8022T92W2uxDJPg7OJaUSGY0wR0pw,16248
44
44
  pygeofetch/insar/timeseries.py,sha256=jXAYCFV5-m1Zv6kErlg4CWntpOSCKE8BR5qJru6GH7Q,60155
45
- pygeofetch/insar/unwrap.py,sha256=kG6hzD-jADRnRAgCdljSBWGkVK8cT5Tf_uLjHh1YJbc,30029
45
+ pygeofetch/insar/unwrap.py,sha256=zXw2WJwMQJS1gSR1L5L7DUfG1XD-Al9YZ2LnDJqJQEU,33444
46
46
  pygeofetch/insar/validate.py,sha256=BZaVvaPNllfDzoPwat0vDA4do6H5xh5Ju_g4r5YNogE,10110
47
47
  pygeofetch/insar/visualize.py,sha256=OxaQCUyRPKdikk5eQToGaXEtnN5RHEFEUMTD4O0-1iQ,8320
48
48
  pygeofetch/insar/workflow.py,sha256=8IxGgabdz9fDLoGAVrJRCdw16GP3sSDSoFPXyv1RXcg,11713
@@ -108,9 +108,9 @@ pygeofetch/utils/validators.py,sha256=f-k3mGFP4byjimyDymhPEdsz5I16jZacx1HSnwrARj
108
108
  pygeofetch/viz/__init__.py,sha256=xf2C9IL4n3bv3oxk8RYkogq7nkuNyt18V-urAoXWRQY,449
109
109
  pygeofetch/viz/map.py,sha256=vYO99NvTumCAVXVtXcEzMx_cpmH-FvSVNWl8X0PNSgE,15494
110
110
  pygeofetch/viz/plot.py,sha256=I16rdOWb80gcjYDsDvTMzuyek7QHgUNOQxY2RejBAPs,53675
111
- pygeofetch-2.3.0.dist-info/licenses/LICENSE,sha256=zavMyhODD6NvZTmmKFEtATrngwY4CU_NEtY7lhjxGnI,1075
112
- pygeofetch-2.3.0.dist-info/METADATA,sha256=rzAus9D-4CmV_laOgjX32304Urseo9600_UmjupWHa8,43254
113
- pygeofetch-2.3.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
114
- pygeofetch-2.3.0.dist-info/entry_points.txt,sha256=dHiUXLF5xNJ8vgtXZoUQNleEMQUeDPZiKQOE1tW8SDY,55
115
- pygeofetch-2.3.0.dist-info/top_level.txt,sha256=rOmnZargIfNk99fwVOqt6OJyJvpSTBBAYO5HU37yhHk,11
116
- pygeofetch-2.3.0.dist-info/RECORD,,
111
+ pygeofetch-2.4.0.dist-info/licenses/LICENSE,sha256=zavMyhODD6NvZTmmKFEtATrngwY4CU_NEtY7lhjxGnI,1075
112
+ pygeofetch-2.4.0.dist-info/METADATA,sha256=pDlu8XZmm0G3xTLHpf3tf5F9K2uAn1kiojbZ9651Qmk,43254
113
+ pygeofetch-2.4.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
114
+ pygeofetch-2.4.0.dist-info/entry_points.txt,sha256=dHiUXLF5xNJ8vgtXZoUQNleEMQUeDPZiKQOE1tW8SDY,55
115
+ pygeofetch-2.4.0.dist-info/top_level.txt,sha256=rOmnZargIfNk99fwVOqt6OJyJvpSTBBAYO5HU37yhHk,11
116
+ pygeofetch-2.4.0.dist-info/RECORD,,