pingmapper 5.3.5__tar.gz → 5.3.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.
- {pingmapper-5.3.5 → pingmapper-5.3.7}/PKG-INFO +1 -1
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/class_portstarObj.py +74 -29
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/doWork.py +4 -2
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/funcs_common.py +22 -1
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/main_readFiles.py +105 -60
- pingmapper-5.3.7/pingmapper/version.py +1 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper.egg-info/PKG-INFO +1 -1
- pingmapper-5.3.5/pingmapper/version.py +0 -1
- {pingmapper-5.3.5 → pingmapper-5.3.7}/LICENSE +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/README.md +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/__init__.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/__main__.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/class_mapSubstrateObj.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/class_rectObj.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/class_sonObj.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/class_sonObj_nadirgaptest.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/default_params.json +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/funcs_model.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/funcs_rectify.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/gui_main.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/main_mapSubstrate.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/main_rectify.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0926.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0929.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/scratch/funcs_pyhum_correct.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/scratch/main.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/scratch/main_batchDirectory.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/test_PINGMapper.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/test_time.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/DRAFT_Workflows/avg_predictions_Mussel_WBL.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/DRAFT_Workflows/gen_centerline.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/DRAFT_Workflows/gen_centerline_from_bankline.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/DRAFT_Workflows/gen_centerline_trkpnts_fitspline_DRAFT.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/DRAFT_Workflows/testEXAMPLE_mosaic_logit.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/RawEGN_avg_predictions.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/00_substrate_logits_mosaic_transects.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/00_substrate_shps_mosaic_transects.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/01_gen_centerline_from_coverage.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/02_gen_summary_stamp_shps.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/03_gen_summary_shp.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/04_combine_summary_shp_csv.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/05_gen_summary_shp_plots.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/06_compare_raw-egn_volume.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/08_raw-egn_hardReacheFreq_hist.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/09_raw-egn_PatchSize_density.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/summarize_project_substrate.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/export_coverage.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/main_mosaic_transects.py +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper.egg-info/SOURCES.txt +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper.egg-info/dependency_links.txt +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper.egg-info/requires.txt +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper.egg-info/top_level.txt +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/pyproject.toml +0 -0
- {pingmapper-5.3.5 → pingmapper-5.3.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pingmapper
|
|
3
|
-
Version: 5.3.
|
|
3
|
+
Version: 5.3.7
|
|
4
4
|
Summary: Open-source interface for processing recreation-grade side scan sonar datasets and reproducibly mapping benthic habitat
|
|
5
5
|
Author: Daniel Buscombe
|
|
6
6
|
Author-email: Cameron Bodine <bodine.cs@gmail.email>
|
|
@@ -979,20 +979,20 @@ class portstarObj(object):
|
|
|
979
979
|
self._depthZheng() or self._depthThreshold()
|
|
980
980
|
'''
|
|
981
981
|
|
|
982
|
-
# Check if depth detection dependencies are available
|
|
983
|
-
if not DEPTH_DETECTION_AVAILABLE:
|
|
984
|
-
raise ImportError(
|
|
985
|
-
"TensorFlow, Transformers, and/or Doodleverse Utils are not installed. "
|
|
986
|
-
"These packages are required for automatic depth detection. "
|
|
987
|
-
"Please install them using: pip install tensorflow transformers doodleverse-utils"
|
|
988
|
-
)
|
|
989
|
-
|
|
990
|
-
# Open model configuration file
|
|
991
|
-
with open(self.configfile) as f:
|
|
992
|
-
config = json.load(f)
|
|
993
|
-
globals().update(config)
|
|
994
|
-
|
|
995
982
|
if method == 1:
|
|
983
|
+
# Check if depth detection dependencies are available
|
|
984
|
+
if not DEPTH_DETECTION_AVAILABLE:
|
|
985
|
+
raise ImportError(
|
|
986
|
+
"TensorFlow, Transformers, and/or Doodleverse Utils are not installed. "
|
|
987
|
+
"These packages are required for ML depth detection. "
|
|
988
|
+
"Use method=2 for binary-threshold depth picking instead."
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
# Open model configuration file
|
|
992
|
+
with open(self.configfile) as f:
|
|
993
|
+
config = json.load(f)
|
|
994
|
+
globals().update(config)
|
|
995
|
+
|
|
996
996
|
if not hasattr(self, 'bedpickModel'):
|
|
997
997
|
# model = self._initModel(USE_GPU)
|
|
998
998
|
model = initModel(self.weights, self.configfile, USE_GPU)
|
|
@@ -1003,7 +1003,7 @@ class portstarObj(object):
|
|
|
1003
1003
|
elif method == 2:
|
|
1004
1004
|
self.port._loadSonMeta()
|
|
1005
1005
|
self.star._loadSonMeta()
|
|
1006
|
-
portDepPixCrop, starDepPixCrop, i = self._depthThreshold(i
|
|
1006
|
+
portDepPixCrop, starDepPixCrop, i = self._depthThreshold(i)
|
|
1007
1007
|
|
|
1008
1008
|
gc.collect()
|
|
1009
1009
|
return portDepPixCrop, starDepPixCrop, i
|
|
@@ -1391,25 +1391,31 @@ class portstarObj(object):
|
|
|
1391
1391
|
for son in portstar:
|
|
1392
1392
|
# Load sonar intensity, standardize & rescale
|
|
1393
1393
|
son._getScanChunkSingle(chunk)
|
|
1394
|
-
img = son.sonDat
|
|
1395
|
-
|
|
1394
|
+
img = standardize(np.asarray(son.sonDat)).squeeze()
|
|
1395
|
+
if img.ndim == 3:
|
|
1396
|
+
img = img[:, :, -1]
|
|
1396
1397
|
W, H = img.shape[1], img.shape[0]
|
|
1397
1398
|
|
|
1398
1399
|
# Get chunks sonar metadata and instrument depth
|
|
1399
|
-
isChunk = son.sonMetaDF['chunk_id']==
|
|
1400
|
+
isChunk = son.sonMetaDF['chunk_id'] == chunk
|
|
1400
1401
|
sonMeta = son.sonMetaDF[isChunk].reset_index()
|
|
1401
|
-
|
|
1402
|
-
acousticBed = round(
|
|
1402
|
+
acoustic_depth = pd.to_numeric(sonMeta['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1403
|
+
acousticBed = np.round(acoustic_depth / sonMeta['pixM'].to_numpy(dtype=float, copy=True), 0)
|
|
1404
|
+
acousticBed = acousticBed[np.isfinite(acousticBed) & (acousticBed > 0)]
|
|
1403
1405
|
|
|
1404
1406
|
##################################
|
|
1405
1407
|
# Step 1 : Acoustic Bedpick Filter
|
|
1406
1408
|
# Use acoustic bed pick to crop image
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
+
if acousticBed.size > 0:
|
|
1410
|
+
bedMin = max(int(np.nanmin(acousticBed)) - 50, 0)
|
|
1411
|
+
bedMax = int(np.nanmax(acousticBed)) + pix_buf
|
|
1412
|
+
else:
|
|
1413
|
+
bedMin = 0
|
|
1414
|
+
bedMax = H
|
|
1409
1415
|
|
|
1410
1416
|
cropMask = np.ones((H, W)).astype(int)
|
|
1411
1417
|
cropMask[:bedMin,:] = 0
|
|
1412
|
-
cropMask[bedMax:,:] = 0
|
|
1418
|
+
cropMask[min(bedMax, H):,:] = 0
|
|
1413
1419
|
|
|
1414
1420
|
# Mask the image with bed_mask
|
|
1415
1421
|
imgMasked = img*cropMask
|
|
@@ -1464,7 +1470,7 @@ class portstarObj(object):
|
|
|
1464
1470
|
imgBinaryMask[imgBinaryMask>0] = 1 # Now set all val's greater than 0 to 1 to create the mask
|
|
1465
1471
|
|
|
1466
1472
|
# Now fill in above last row filled to make sure no gaps in bed pixels
|
|
1467
|
-
lastRow = bedMax
|
|
1473
|
+
lastRow = min(bedMax, H - 1)
|
|
1468
1474
|
imgBinaryMask[lastRow] = True
|
|
1469
1475
|
for i in range(W):
|
|
1470
1476
|
if imgBinaryMask[lastRow-1,i] == 0:
|
|
@@ -1509,10 +1515,10 @@ class portstarObj(object):
|
|
|
1509
1515
|
bed[nans] = np.interp(x(nans), x(~nans), bed[~nans])
|
|
1510
1516
|
bed = bed.astype(int)
|
|
1511
1517
|
|
|
1512
|
-
if son.beamName
|
|
1518
|
+
if str(son.beamName).startswith('ss_port'):
|
|
1513
1519
|
# self.portDepDetect[chunk] = bed
|
|
1514
1520
|
portDepPixCrop = bed
|
|
1515
|
-
elif son.beamName
|
|
1521
|
+
elif str(son.beamName).startswith('ss_star'):
|
|
1516
1522
|
# self.starDepDetect[chunk] = bed
|
|
1517
1523
|
starDepPixCrop = bed
|
|
1518
1524
|
|
|
@@ -1557,6 +1563,43 @@ class portstarObj(object):
|
|
|
1557
1563
|
Integer < 0 = decrease depth estimate by x pixels.
|
|
1558
1564
|
0 = use depth estimate with no adjustment.
|
|
1559
1565
|
'''
|
|
1566
|
+
def _format_depth_adjustment(pix_m_series):
|
|
1567
|
+
pix_m = pd.to_numeric(pix_m_series, errors='coerce')
|
|
1568
|
+
valid_pix = pix_m[np.isfinite(pix_m) & (pix_m > 0)]
|
|
1569
|
+
if len(valid_pix) == 0:
|
|
1570
|
+
return '0 pixels'
|
|
1571
|
+
return str(float(adjDep) / float(valid_pix.iloc[0])) + ' pixels'
|
|
1572
|
+
|
|
1573
|
+
def _sync_trackline_depth(beam_obj, beam_df):
|
|
1574
|
+
trk_file = os.path.join(beam_obj.metaDir, 'Trackline_Smth_' + beam_obj.beamName + '.csv')
|
|
1575
|
+
if not os.path.exists(trk_file):
|
|
1576
|
+
return
|
|
1577
|
+
|
|
1578
|
+
trk_df = pd.read_csv(trk_file)
|
|
1579
|
+
if 'record_num' not in trk_df.columns or 'record_num' not in beam_df.columns:
|
|
1580
|
+
return
|
|
1581
|
+
|
|
1582
|
+
depth_cols = ['record_num', 'dep_m']
|
|
1583
|
+
if 'dep_m_Method' in beam_df.columns:
|
|
1584
|
+
depth_cols.append('dep_m_Method')
|
|
1585
|
+
if 'dep_m_smth' in beam_df.columns:
|
|
1586
|
+
depth_cols.append('dep_m_smth')
|
|
1587
|
+
if 'dep_m_adjBy' in beam_df.columns:
|
|
1588
|
+
depth_cols.append('dep_m_adjBy')
|
|
1589
|
+
|
|
1590
|
+
depth_df = beam_df[depth_cols].drop_duplicates(subset=['record_num'], keep='last').set_index('record_num')
|
|
1591
|
+
trk_df = trk_df.set_index('record_num')
|
|
1592
|
+
|
|
1593
|
+
trk_df['dep_m'] = depth_df['dep_m']
|
|
1594
|
+
if 'dep_m_Method' in depth_df.columns:
|
|
1595
|
+
trk_df['dep_m_Method'] = depth_df['dep_m_Method']
|
|
1596
|
+
if 'dep_m_smth' in depth_df.columns:
|
|
1597
|
+
trk_df['dep_m_smth'] = depth_df['dep_m_smth']
|
|
1598
|
+
if 'dep_m_adjBy' in depth_df.columns:
|
|
1599
|
+
trk_df['dep_m_adjBy'] = depth_df['dep_m_adjBy']
|
|
1600
|
+
|
|
1601
|
+
trk_df.reset_index().to_csv(trk_file, index=False, float_format='%.14f')
|
|
1602
|
+
|
|
1560
1603
|
# Load sonar metadata file
|
|
1561
1604
|
self.port._loadSonMeta()
|
|
1562
1605
|
portDF = self.port.sonMetaDF
|
|
@@ -1617,8 +1660,8 @@ class portstarObj(object):
|
|
|
1617
1660
|
portDF['dep_m_smth'] = smthDep
|
|
1618
1661
|
starDF['dep_m_smth'] = smthDep
|
|
1619
1662
|
|
|
1620
|
-
portDF['dep_m_adjBy'] =
|
|
1621
|
-
starDF['dep_m_adjBy'] =
|
|
1663
|
+
portDF['dep_m_adjBy'] = _format_depth_adjustment(portDF['pixM'])
|
|
1664
|
+
starDF['dep_m_adjBy'] = _format_depth_adjustment(starDF['pixM'])
|
|
1622
1665
|
|
|
1623
1666
|
elif detectDep > 0:
|
|
1624
1667
|
# Prepare depth detection dictionaries
|
|
@@ -1703,8 +1746,8 @@ class portstarObj(object):
|
|
|
1703
1746
|
portDF['dep_m_smth'] = smthDep
|
|
1704
1747
|
starDF['dep_m_smth'] = smthDep
|
|
1705
1748
|
|
|
1706
|
-
portDF['dep_m_adjBy'] =
|
|
1707
|
-
starDF['dep_m_adjBy'] =
|
|
1749
|
+
portDF['dep_m_adjBy'] = _format_depth_adjustment(portDF['pixM'])
|
|
1750
|
+
starDF['dep_m_adjBy'] = _format_depth_adjustment(starDF['pixM'])
|
|
1708
1751
|
|
|
1709
1752
|
# Interpolate over nan's (and set zeros to nan)
|
|
1710
1753
|
portDep = portDF['dep_m'].to_numpy(copy=True)
|
|
@@ -1730,6 +1773,8 @@ class portstarObj(object):
|
|
|
1730
1773
|
# Export to csv
|
|
1731
1774
|
portDF.to_csv(self.port.sonMetaFile, index=False, float_format='%.14f')
|
|
1732
1775
|
starDF.to_csv(self.star.sonMetaFile, index=False, float_format='%.14f')
|
|
1776
|
+
_sync_trackline_depth(self.port, portDF)
|
|
1777
|
+
_sync_trackline_depth(self.star, starDF)
|
|
1733
1778
|
|
|
1734
1779
|
try:
|
|
1735
1780
|
# Take average of both estimates to store with downlooking sonar csv
|
|
@@ -293,6 +293,7 @@ def doWork(
|
|
|
293
293
|
if ss_chan_avail:
|
|
294
294
|
rect_wcp = run_params.get('rect_wcp', False)
|
|
295
295
|
rect_wcr = run_params.get('rect_wcr', False)
|
|
296
|
+
force_rectify = run_params.get('force_rectify', False)
|
|
296
297
|
banklines = run_params.get('banklines', False)
|
|
297
298
|
coverage = run_params.get('coverage', False)
|
|
298
299
|
pred_sub = run_params.get('pred_sub', False)
|
|
@@ -301,11 +302,12 @@ def doWork(
|
|
|
301
302
|
plt_subclass = run_params.get('pltSubClass', False)
|
|
302
303
|
|
|
303
304
|
if not nav_available:
|
|
304
|
-
if rect_wcp or rect_wcr or banklines or coverage or pred_sub or map_sub or export_poly or plt_subclass:
|
|
305
|
+
if rect_wcp or rect_wcr or force_rectify or banklines or coverage or pred_sub or map_sub or export_poly or plt_subclass:
|
|
305
306
|
print('\nWARNING: Navigation info is unavailable for this recording.')
|
|
306
307
|
print('Skipping rectification and substrate mapping workflows (non-georeferenced sonogram-only processing).')
|
|
307
308
|
rect_wcp = False
|
|
308
309
|
rect_wcr = False
|
|
310
|
+
force_rectify = False
|
|
309
311
|
banklines = False
|
|
310
312
|
coverage = False
|
|
311
313
|
pred_sub = False
|
|
@@ -313,7 +315,7 @@ def doWork(
|
|
|
313
315
|
export_poly = False
|
|
314
316
|
plt_subclass = False
|
|
315
317
|
|
|
316
|
-
if rect_wcp or rect_wcr or banklines or coverage or pred_sub or map_sub or export_poly:
|
|
318
|
+
if rect_wcp or rect_wcr or force_rectify or banklines or coverage or pred_sub or map_sub or export_poly:
|
|
317
319
|
print('\n===========================================')
|
|
318
320
|
print('===========================================')
|
|
319
321
|
print('***** RECTIFYING *****')
|
|
@@ -31,6 +31,12 @@
|
|
|
31
31
|
|
|
32
32
|
import os, sys, struct, gc, io, contextlib
|
|
33
33
|
|
|
34
|
+
# Configure TensorFlow runtime defaults as early as possible so informational
|
|
35
|
+
# startup messages do not leak to stderr before logging is initialized.
|
|
36
|
+
os.environ.setdefault('TF_CPP_MIN_LOG_LEVEL', '3')
|
|
37
|
+
os.environ.setdefault('TF_ENABLE_ONEDNN_OPTS', '0')
|
|
38
|
+
os.environ.setdefault('AUTOGRAPH_VERBOSITY', '0')
|
|
39
|
+
|
|
34
40
|
# Add 'pingmapper' to the path, may not need after pypi package...
|
|
35
41
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
36
42
|
PACKAGE_DIR = os.path.dirname(SCRIPT_DIR)
|
|
@@ -97,13 +103,27 @@ import json
|
|
|
97
103
|
|
|
98
104
|
import logging
|
|
99
105
|
|
|
100
|
-
from tqdm import tqdm
|
|
106
|
+
from tqdm import tqdm as _tqdm
|
|
101
107
|
|
|
102
108
|
import subprocess
|
|
103
109
|
|
|
104
110
|
# from funcs_pyhum_correct import doPyhumCorrections
|
|
105
111
|
|
|
106
112
|
|
|
113
|
+
# =========================================================
|
|
114
|
+
def tqdm(*args, **kwargs):
|
|
115
|
+
'''
|
|
116
|
+
Shared tqdm wrapper so CLI progress bars stay readable in the GUI console.
|
|
117
|
+
Use PINGMAPPER_TQDM_NCOLS to override the default width when needed.
|
|
118
|
+
'''
|
|
119
|
+
if 'ncols' not in kwargs:
|
|
120
|
+
try:
|
|
121
|
+
kwargs['ncols'] = int(os.environ.get('PINGMAPPER_TQDM_NCOLS', '80'))
|
|
122
|
+
except (TypeError, ValueError):
|
|
123
|
+
kwargs['ncols'] = 80
|
|
124
|
+
return _tqdm(*args, **kwargs)
|
|
125
|
+
|
|
126
|
+
|
|
107
127
|
# =========================================================
|
|
108
128
|
def safe_n_jobs(task_count, thread_count=0):
|
|
109
129
|
'''
|
|
@@ -139,6 +159,7 @@ def quiet_tensorflow_warnings():
|
|
|
139
159
|
Safe to call even if TensorFlow is not installed.
|
|
140
160
|
'''
|
|
141
161
|
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
|
|
162
|
+
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
|
|
142
163
|
os.environ['AUTOGRAPH_VERBOSITY'] = '0'
|
|
143
164
|
|
|
144
165
|
logging.getLogger('tensorflow').setLevel(logging.ERROR)
|
|
@@ -94,6 +94,17 @@ def _is_sidescan_beam(beam_name):
|
|
|
94
94
|
return beam_name.startswith('ss_port') or beam_name.startswith('ss_star')
|
|
95
95
|
|
|
96
96
|
|
|
97
|
+
def _sidescan_group_key(beam_name):
|
|
98
|
+
beam_name = str(beam_name)
|
|
99
|
+
if beam_name.startswith('ss_port_'):
|
|
100
|
+
return beam_name[len('ss_port_'):]
|
|
101
|
+
if beam_name.startswith('ss_star_'):
|
|
102
|
+
return beam_name[len('ss_star_'):]
|
|
103
|
+
if beam_name in {'ss_port', 'ss_star'}:
|
|
104
|
+
return 'default'
|
|
105
|
+
return beam_name
|
|
106
|
+
|
|
107
|
+
|
|
97
108
|
#===========================================
|
|
98
109
|
def read_master_func(logfilename='',
|
|
99
110
|
project_mode=0,
|
|
@@ -158,6 +169,7 @@ def read_master_func(logfilename='',
|
|
|
158
169
|
mosaic=False,
|
|
159
170
|
map_mosaic=0,
|
|
160
171
|
banklines=False,
|
|
172
|
+
side_scan_only=False,
|
|
161
173
|
return_context=False,
|
|
162
174
|
**kwargs):
|
|
163
175
|
|
|
@@ -354,7 +366,7 @@ def read_master_func(logfilename='',
|
|
|
354
366
|
# Prepare Cerulean file for PINGMapper
|
|
355
367
|
elif file_type == '.svlog':
|
|
356
368
|
sonar_obj = cerul2pingmapper(inFile, projDir, nchunk, tempC, exportUnknown)
|
|
357
|
-
detectDep = 1
|
|
369
|
+
detectDep = 1 if DEPTH_DETECTION_AVAILABLE else 2
|
|
358
370
|
instDepAvail = False
|
|
359
371
|
|
|
360
372
|
# Prepare JSF file for PINGMapper
|
|
@@ -375,6 +387,7 @@ def read_master_func(logfilename='',
|
|
|
375
387
|
sys.exit()
|
|
376
388
|
|
|
377
389
|
nav_available = bool(getattr(sonar_obj, 'has_position', True))
|
|
390
|
+
side_scan_only = bool(side_scan_only)
|
|
378
391
|
|
|
379
392
|
# Sonar-only fallback for sources without navigation fields (e.g., some Cerulean logs).
|
|
380
393
|
# Disable filters that rely on geospatial motion/position so processing can continue.
|
|
@@ -547,6 +560,19 @@ def read_master_func(logfilename='',
|
|
|
547
560
|
else:
|
|
548
561
|
pass
|
|
549
562
|
|
|
563
|
+
if side_scan_only:
|
|
564
|
+
if len(ss_chan_avail) == 0:
|
|
565
|
+
print('\n\nSide-scan only mode enabled, but no side-scan channels were recognized. Skipping processing.')
|
|
566
|
+
if return_context:
|
|
567
|
+
return {
|
|
568
|
+
'has_sidescan': False,
|
|
569
|
+
'has_nav': nav_available,
|
|
570
|
+
}
|
|
571
|
+
return False
|
|
572
|
+
|
|
573
|
+
print('\n\nSide-scan only mode enabled. Skipping non-side-scan channels.')
|
|
574
|
+
sonObjs = [son for son in sonObjs if _is_sidescan_beam(getattr(son, 'beamName', ''))]
|
|
575
|
+
|
|
550
576
|
print(sonObjs)
|
|
551
577
|
####
|
|
552
578
|
# OLD
|
|
@@ -949,10 +975,15 @@ def read_master_func(logfilename='',
|
|
|
949
975
|
valid=True
|
|
950
976
|
elif (attMax != 0) or ("unknown" in att) or (att =="beam"):
|
|
951
977
|
valid=True
|
|
952
|
-
elif
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
978
|
+
elif att == "inst_dep_m":
|
|
979
|
+
depth_values = pd.to_numeric(df[att], errors='coerce').to_numpy(dtype=float, copy=False)
|
|
980
|
+
has_valid_instrument_depth = np.isfinite(depth_values).any() and np.nanmax(depth_values) > 0
|
|
981
|
+
if not has_valid_instrument_depth: # Automatically detect depth if instrument depth is missing/empty
|
|
982
|
+
valid=False
|
|
983
|
+
invalid[son.beam+"."+att] = False
|
|
984
|
+
detectDep = 1 if DEPTH_DETECTION_AVAILABLE else 2
|
|
985
|
+
else:
|
|
986
|
+
valid=True
|
|
956
987
|
else:
|
|
957
988
|
valid=False
|
|
958
989
|
invalid[son.beam+"."+att] = False
|
|
@@ -1097,17 +1128,23 @@ def read_master_func(logfilename='',
|
|
|
1097
1128
|
|
|
1098
1129
|
start_time = time.time()
|
|
1099
1130
|
|
|
1100
|
-
# Determine which sonObj
|
|
1101
|
-
|
|
1131
|
+
# Determine which sonObj pairs should be depth processed together.
|
|
1132
|
+
sidescan_groups = {}
|
|
1102
1133
|
for son in sonObjs:
|
|
1103
|
-
beam = son.beamName
|
|
1104
|
-
if _is_sidescan_beam(beam):
|
|
1105
|
-
|
|
1134
|
+
beam = str(son.beamName)
|
|
1135
|
+
if not _is_sidescan_beam(beam):
|
|
1136
|
+
continue
|
|
1137
|
+
|
|
1138
|
+
group_key = _sidescan_group_key(beam)
|
|
1139
|
+
group = sidescan_groups.setdefault(group_key, {})
|
|
1140
|
+
if beam.startswith('ss_port'):
|
|
1141
|
+
group['port'] = son
|
|
1142
|
+
elif beam.startswith('ss_star'):
|
|
1143
|
+
group['star'] = son
|
|
1106
1144
|
|
|
1107
|
-
|
|
1108
|
-
chunks = np.array([], dtype=int)
|
|
1145
|
+
ps_depth_jobs = []
|
|
1109
1146
|
|
|
1110
|
-
if len(
|
|
1147
|
+
if len(sidescan_groups) == 0:
|
|
1111
1148
|
print(
|
|
1112
1149
|
'\n\nNo recognized side-scan channels available for depth processing. '\
|
|
1113
1150
|
'Continuing with down-looking beams only.'
|
|
@@ -1117,20 +1154,28 @@ def read_master_func(logfilename='',
|
|
|
1117
1154
|
pltBedPick = False
|
|
1118
1155
|
remShadow = 0
|
|
1119
1156
|
else:
|
|
1120
|
-
|
|
1121
|
-
|
|
1157
|
+
for group_key, group in sorted(sidescan_groups.items()):
|
|
1158
|
+
if 'port' not in group or 'star' not in group:
|
|
1159
|
+
print(
|
|
1160
|
+
'\nSkipping side-scan depth group {} because a matching port/star pair was not found.'.format(group_key)
|
|
1161
|
+
)
|
|
1162
|
+
continue
|
|
1163
|
+
|
|
1164
|
+
psObj = portstarObj([group['port'], group['star']])
|
|
1122
1165
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1166
|
+
chunks = []
|
|
1167
|
+
for son in [group['port'], group['star']]:
|
|
1168
|
+
c = son._getChunkID()
|
|
1169
|
+
chunks.extend(c)
|
|
1170
|
+
del c
|
|
1127
1171
|
|
|
1128
|
-
chunks.
|
|
1129
|
-
|
|
1172
|
+
chunks = np.unique(chunks).astype(int)
|
|
1173
|
+
if len(chunks) == 0:
|
|
1174
|
+
continue
|
|
1130
1175
|
|
|
1131
|
-
|
|
1176
|
+
ps_depth_jobs.append((group_key, psObj, chunks))
|
|
1132
1177
|
|
|
1133
|
-
if len(
|
|
1178
|
+
if len(ps_depth_jobs) == 0:
|
|
1134
1179
|
print(
|
|
1135
1180
|
'\n\nNo valid side-scan chunks available for depth processing. '\
|
|
1136
1181
|
'Continuing with down-looking beams only.'
|
|
@@ -1143,7 +1188,12 @@ def read_master_func(logfilename='',
|
|
|
1143
1188
|
# # Automatically estimate depth
|
|
1144
1189
|
if detectDep > 0:
|
|
1145
1190
|
# Check if depth detection dependencies are available
|
|
1146
|
-
if not DEPTH_DETECTION_AVAILABLE:
|
|
1191
|
+
if detectDep == 1 and not DEPTH_DETECTION_AVAILABLE:
|
|
1192
|
+
print('\n\nML depth detection dependencies are unavailable.')
|
|
1193
|
+
print('Falling back to binary-threshold depth detection...\n')
|
|
1194
|
+
detectDep = 2
|
|
1195
|
+
|
|
1196
|
+
if detectDep == 1 and not DEPTH_DETECTION_AVAILABLE:
|
|
1147
1197
|
print('\n\nCannot estimate depth automatically:')
|
|
1148
1198
|
print('TensorFlow, Transformers, and/or Doodleverse Utils are not installed.')
|
|
1149
1199
|
print('These packages are required for automatic depth detection.')
|
|
@@ -1153,37 +1203,28 @@ def read_master_func(logfilename='',
|
|
|
1153
1203
|
autoBed = False
|
|
1154
1204
|
saveDepth = True
|
|
1155
1205
|
else:
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
psObj
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
# Parallel estimate depth for each chunk using appropriate method
|
|
1179
|
-
r = Parallel(n_jobs=safe_n_jobs(len(chunks), threadCnt))(delayed(psObj._detectDepth)(detectDep, int(chunk), USE_GPU, tileFile) for chunk in tqdm(chunks))
|
|
1180
|
-
|
|
1181
|
-
# store the depth predictions in the class
|
|
1182
|
-
for ret in r:
|
|
1183
|
-
psObj.portDepDetect[ret[2]] = ret[0]
|
|
1184
|
-
psObj.starDepDetect[ret[2]] = ret[1]
|
|
1185
|
-
del ret
|
|
1186
|
-
del r
|
|
1206
|
+
total_chunks = sum(len(chunks) for _, _, chunks in ps_depth_jobs)
|
|
1207
|
+
print('\n\nAutomatically estimating depth for', total_chunks, 'chunks across', len(ps_depth_jobs), 'side-scan group(s):')
|
|
1208
|
+
|
|
1209
|
+
for group_key, psObj, chunks in ps_depth_jobs:
|
|
1210
|
+
psObj.portDepDetect = {}
|
|
1211
|
+
psObj.starDepDetect = {}
|
|
1212
|
+
|
|
1213
|
+
if detectDep == 1:
|
|
1214
|
+
depthModelVer = 'Bedpick_Zheng2021_Segmentation_unet_v1.0'
|
|
1215
|
+
psObj.configfile = os.path.join(modelDir, depthModelVer, 'config', depthModelVer+'.json')
|
|
1216
|
+
psObj.weights = os.path.join(modelDir, depthModelVer, 'weights', depthModelVer+'_fullmodel.h5')
|
|
1217
|
+
print('\n\tGroup {}: Using Zheng et al. 2021 method. Loading model: {}'.format(group_key, os.path.basename(psObj.weights)))
|
|
1218
|
+
elif detectDep == 2:
|
|
1219
|
+
print('\n\tGroup {}: Using binary thresholding...'.format(group_key))
|
|
1220
|
+
|
|
1221
|
+
r = Parallel(n_jobs=safe_n_jobs(len(chunks), threadCnt))(delayed(psObj._detectDepth)(detectDep, int(chunk), USE_GPU, tileFile) for chunk in tqdm(chunks))
|
|
1222
|
+
|
|
1223
|
+
for ret in r:
|
|
1224
|
+
psObj.portDepDetect[ret[2]] = ret[0]
|
|
1225
|
+
psObj.starDepDetect[ret[2]] = ret[1]
|
|
1226
|
+
del ret
|
|
1227
|
+
del r
|
|
1187
1228
|
|
|
1188
1229
|
# Flag indicating depth autmatically estimated
|
|
1189
1230
|
autoBed = True
|
|
@@ -1201,9 +1242,10 @@ def read_master_func(logfilename='',
|
|
|
1201
1242
|
|
|
1202
1243
|
if saveDepth:
|
|
1203
1244
|
|
|
1204
|
-
if ss_chan_avail and
|
|
1205
|
-
|
|
1206
|
-
|
|
1245
|
+
if ss_chan_avail and len(ps_depth_jobs) > 0:
|
|
1246
|
+
depDF = []
|
|
1247
|
+
for _, psObj, chunks in ps_depth_jobs:
|
|
1248
|
+
depDF.append(psObj._saveDepth(chunks, detectDep, smthDep, adjDep, instDepAvail))
|
|
1207
1249
|
else:
|
|
1208
1250
|
depDF = []
|
|
1209
1251
|
|
|
@@ -1260,7 +1302,7 @@ def read_master_func(logfilename='',
|
|
|
1260
1302
|
del depDF
|
|
1261
1303
|
|
|
1262
1304
|
# Cleanup
|
|
1263
|
-
|
|
1305
|
+
for _, psObj, _ in ps_depth_jobs:
|
|
1264
1306
|
psObj._cleanup()
|
|
1265
1307
|
|
|
1266
1308
|
print("\nDone!")
|
|
@@ -1281,7 +1323,10 @@ def read_master_func(logfilename='',
|
|
|
1281
1323
|
# Cleanup
|
|
1282
1324
|
if psObj is not None:
|
|
1283
1325
|
psObj._cleanup()
|
|
1284
|
-
|
|
1326
|
+
if 'psObj' in locals():
|
|
1327
|
+
del psObj
|
|
1328
|
+
if 'portstar' in locals():
|
|
1329
|
+
del portstar
|
|
1285
1330
|
|
|
1286
1331
|
for son in sonObjs:
|
|
1287
1332
|
son._cleanup()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '5.3.7'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pingmapper
|
|
3
|
-
Version: 5.3.
|
|
3
|
+
Version: 5.3.7
|
|
4
4
|
Summary: Open-source interface for processing recreation-grade side scan sonar datasets and reproducibly mapping benthic habitat
|
|
5
5
|
Author: Daniel Buscombe
|
|
6
6
|
Author-email: Cameron Bodine <bodine.cs@gmail.email>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '5.3.5'
|
|
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
|
{pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/DRAFT_Workflows/avg_predictions_Mussel_WBL.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/DRAFT_Workflows/testEXAMPLE_mosaic_logit.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingmapper-5.3.5 → pingmapper-5.3.7}/pingmapper/utils/Substrate_Summaries/03_gen_summary_shp.py
RENAMED
|
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
|