pingmapper 5.5.6__tar.gz → 5.5.7__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 (62) hide show
  1. {pingmapper-5.5.6 → pingmapper-5.5.7}/PKG-INFO +1 -1
  2. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/funcs_common.py +83 -23
  3. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/main_readFiles.py +1 -1
  4. pingmapper-5.5.7/pingmapper/version.py +1 -0
  5. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper.egg-info/PKG-INFO +1 -1
  6. pingmapper-5.5.6/pingmapper/version.py +0 -1
  7. {pingmapper-5.5.6 → pingmapper-5.5.7}/LICENSE +0 -0
  8. {pingmapper-5.5.6 → pingmapper-5.5.7}/README.md +0 -0
  9. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/__init__.py +0 -0
  10. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/__main__.py +0 -0
  11. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/class_mapSubstrateObj.py +0 -0
  12. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/class_portstarObj.py +0 -0
  13. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/class_rectObj.py +0 -0
  14. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/class_sonObj.py +0 -0
  15. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/class_sonObj_nadirgaptest.py +0 -0
  16. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/default_params.json +0 -0
  17. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/doWork.py +0 -0
  18. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/funcs_model.py +0 -0
  19. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/funcs_rectify.py +0 -0
  20. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/gui_main.py +0 -0
  21. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/main_mapSubstrate.py +0 -0
  22. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/main_rectify.py +0 -0
  23. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/nonGUI_batch_main.py +0 -0
  24. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/nonGui_main.py +0 -0
  25. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0926.py +0 -0
  26. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0929.py +0 -0
  27. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/scratch/funcs_pyhum_correct.py +0 -0
  28. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/scratch/main.py +0 -0
  29. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/scratch/main_batchDirectory.py +0 -0
  30. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/self_check.py +0 -0
  31. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/test_PINGMapper.py +0 -0
  32. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/test_cli_self_check.py +0 -0
  33. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/test_dq_filter.py +0 -0
  34. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/test_time.py +0 -0
  35. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/DRAFT_Workflows/avg_predictions_Mussel_WBL.py +0 -0
  36. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/DRAFT_Workflows/gen_centerline.py +0 -0
  37. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/DRAFT_Workflows/gen_centerline_from_bankline.py +0 -0
  38. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/DRAFT_Workflows/gen_centerline_trkpnts_fitspline_DRAFT.py +0 -0
  39. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/DRAFT_Workflows/testEXAMPLE_mosaic_logit.py +0 -0
  40. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/RawEGN_avg_predictions.py +0 -0
  41. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/00_substrate_logits_mosaic_transects.py +0 -0
  42. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/00_substrate_shps_mosaic_transects.py +0 -0
  43. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/01_gen_centerline_from_coverage.py +0 -0
  44. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/02_gen_summary_stamp_shps.py +0 -0
  45. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/03_gen_summary_shp.py +0 -0
  46. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/04_combine_summary_shp_csv.py +0 -0
  47. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/05_gen_summary_shp_plots.py +0 -0
  48. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/06_compare_raw-egn_volume.py +0 -0
  49. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/08_raw-egn_hardReacheFreq_hist.py +0 -0
  50. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/09_raw-egn_PatchSize_density.py +0 -0
  51. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/Substrate_Summaries/summarize_project_substrate.py +0 -0
  52. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/export_coverage.py +0 -0
  53. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/kml2mosaic.py +0 -0
  54. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/main_mosaic_transects.py +0 -0
  55. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper/utils/tile2mosaic.py +0 -0
  56. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper.egg-info/SOURCES.txt +0 -0
  57. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper.egg-info/dependency_links.txt +0 -0
  58. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper.egg-info/requires.txt +0 -0
  59. {pingmapper-5.5.6 → pingmapper-5.5.7}/pingmapper.egg-info/top_level.txt +0 -0
  60. {pingmapper-5.5.6 → pingmapper-5.5.7}/pyproject.toml +0 -0
  61. {pingmapper-5.5.6 → pingmapper-5.5.7}/setup.cfg +0 -0
  62. {pingmapper-5.5.6 → pingmapper-5.5.7}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pingmapper
3
- Version: 5.5.6
3
+ Version: 5.5.7
4
4
  Summary: Open-source interface for processing recreation-grade side scan sonar datasets and reproducibly mapping benthic habitat
5
5
  Author: Cameron Bodine, Daniel Buscombe, Iury T Simoes-Sousa
6
6
  Author-email: bodine.cs@gmail.email
@@ -326,42 +326,102 @@ class Logger(object):
326
326
  pass
327
327
 
328
328
  # =========================================================
329
- def downloadSegmentationModelsv1_0(modelDir):
329
+ def segmentationModelsExist(modelDir):
330
+ """True only if the model folder was fully extracted (not just created)."""
331
+ return os.path.isdir(modelDir) and any(
332
+ f.endswith('.json')
333
+ for _, _, files in os.walk(modelDir) for f in files
334
+ )
330
335
 
331
- # Create directories
332
- if not os.path.exists(modelDir):
333
- os.makedirs(modelDir)
334
336
 
335
- # Download
336
- url = 'https://zenodo.org/records/10093642/files/PINGMapperv2.0_SegmentationModelsv1.0.zip?download=1'
337
- print('\n\nDownloading segmentation models (v1.0):\nhttps://zenodo.org/records/10092289/files/PINGMapperv2.0_SegmentationModelsv1.0.zip?download=1')
337
+ def downloadSegmentationModelsv1_0(modelDir, retries=4):
338
338
 
339
- filename = modelDir+'.zip'
340
- r = requests.get(url, allow_redirects=True)
341
- # open(filename, 'wb').write(r.content)
342
- with open(filename, 'wb') as f:
343
- f.write(r.content)
339
+ url = 'https://zenodo.org/records/10093642/files/PINGMapperv2.0_SegmentationModelsv1.0.zip?download=1'
340
+ print('\n\nDownloading segmentation models (v1.0):\n{}'.format(url))
344
341
 
345
- with zipfile.ZipFile(filename, 'r') as z_fp:
346
- z_fp.extractall(modelDir)
347
- os.remove(filename)
342
+ # Start clean in case a previous attempt left a partial folder
343
+ if os.path.exists(modelDir):
344
+ shutil.rmtree(_long_path(modelDir), ignore_errors=True)
345
+ os.makedirs(modelDir, exist_ok=True)
348
346
 
349
- print('Model download success!')
350
-
351
- return
347
+ filename = modelDir+'.zip'
348
+ last_err = None
349
+ for attempt in range(1, retries + 1):
350
+ try:
351
+ with requests.get(url, allow_redirects=True, stream=True, timeout=(30, 120)) as r:
352
+ r.raise_for_status()
353
+ with open(filename, 'wb') as f:
354
+ for chunk in r.iter_content(chunk_size=1024*1024):
355
+ f.write(chunk)
356
+
357
+ # Guard against error pages (e.g. 504) saved as the zip
358
+ if not zipfile.is_zipfile(filename):
359
+ raise RuntimeError('Downloaded file is not a valid zip archive.')
360
+
361
+ # \\?\ prefix lets extraction exceed MAX_PATH on Windows without admin rights
362
+ with zipfile.ZipFile(filename, 'r') as z_fp:
363
+ z_fp.extractall(_long_path(modelDir))
364
+
365
+ if not segmentationModelsExist(modelDir):
366
+ raise RuntimeError('Models were not extracted correctly.')
367
+
368
+ os.remove(filename)
369
+ print('Model download success!')
370
+ return
371
+ except Exception as e:
372
+ last_err = e
373
+ print('Model download attempt {} of {} failed: {}'.format(attempt, retries, e))
374
+ if os.path.exists(filename):
375
+ os.remove(filename)
376
+ if attempt < retries:
377
+ time.sleep(5 * attempt)
378
+
379
+ shutil.rmtree(_long_path(modelDir), ignore_errors=True)
380
+ raise RuntimeError(
381
+ 'Unable to download segmentation models after {} attempts: {}\n'
382
+ 'Download manually from {} and extract to {}'.format(retries, last_err, url, modelDir)
383
+ )
352
384
 
353
385
 
354
386
  # =========================================================
355
387
  def get_segmentation_model_dir():
356
388
  """
357
389
  Return the default local directory for segmentation models.
358
- Models are stored in the user's home folder to avoid deep environment paths
359
- that can break zip extraction on Windows.
390
+ Models are stored in a short path outside the environment to avoid deep
391
+ paths that can break zip extraction on Windows. Set PINGMAPPER_MODEL_DIR to
392
+ override. If the home folder is synced by OneDrive (which can lock files
393
+ mid-extraction), a folder at the drive root is used instead.
360
394
  """
395
+ override = os.environ.get('PINGMAPPER_MODEL_DIR')
396
+ if override:
397
+ return os.path.normpath(override)
398
+
399
+ model_name = 'PINGMapperv2.0_SegmentationModelsv1.0'
361
400
  home_dir = os.path.expanduser('~')
362
- return os.path.normpath(
363
- os.path.join(home_dir, '.pingmapper', 'models', 'PINGMapperv2.0_SegmentationModelsv1.0')
364
- )
401
+
402
+ if os.name == 'nt' and 'onedrive' in home_dir.lower():
403
+ drive = os.path.splitdrive(home_dir)[0] or 'C:'
404
+ alt = os.path.join(drive + os.sep, '.pingmapper', 'models')
405
+ try:
406
+ os.makedirs(alt, exist_ok=True)
407
+ print('Home folder is in OneDrive; storing models in {} instead.'.format(alt))
408
+ return os.path.normpath(os.path.join(alt, model_name))
409
+ except OSError:
410
+ print('Warning: models will be stored in OneDrive and sync may interfere.')
411
+
412
+ return os.path.normpath(os.path.join(home_dir, '.pingmapper', 'models', model_name))
413
+
414
+
415
+ def _long_path(path):
416
+ """Return a \\\\?\\ prefixed absolute path on Windows; unchanged elsewhere."""
417
+ if os.name != 'nt':
418
+ return path
419
+ path = os.path.abspath(path)
420
+ if path.startswith('\\\\?\\'):
421
+ return path
422
+ if path.startswith('\\\\'):
423
+ return '\\\\?\\UNC\\' + path[2:]
424
+ return '\\\\?\\' + path
365
425
 
366
426
 
367
427
  # # =========================================================
@@ -907,7 +907,7 @@ def read_master_func(logfilename='',
907
907
  #####################################
908
908
  # Download models if they don't exist
909
909
  modelDir = get_segmentation_model_dir()
910
- if not os.path.exists(modelDir):
910
+ if not segmentationModelsExist(modelDir):
911
911
  downloadSegmentationModelsv1_0(modelDir)
912
912
 
913
913
 
@@ -0,0 +1 @@
1
+ __version__ = '5.5.7'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pingmapper
3
- Version: 5.5.6
3
+ Version: 5.5.7
4
4
  Summary: Open-source interface for processing recreation-grade side scan sonar datasets and reproducibly mapping benthic habitat
5
5
  Author: Cameron Bodine, Daniel Buscombe, Iury T Simoes-Sousa
6
6
  Author-email: bodine.cs@gmail.email
@@ -1 +0,0 @@
1
- __version__ = '5.5.6'
File without changes
File without changes
File without changes
File without changes
File without changes