pingmapper 5.1.0__tar.gz → 5.2.0__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.1.0 → pingmapper-5.2.0}/PKG-INFO +1 -1
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/__main__.py +5 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/class_portstarObj.py +171 -57
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/class_rectObj.py +565 -93
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/class_sonObj.py +691 -44
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/class_sonObj_nadirgaptest.py +116 -18
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/default_params.json +4 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/doWork.py +17 -5
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/funcs_common.py +91 -10
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/funcs_model.py +6 -5
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/funcs_rectify.py +66 -52
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/gui_main.py +205 -59
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/main_mapSubstrate.py +12 -5
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/main_readFiles.py +182 -53
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/main_rectify.py +108 -13
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/test_PINGMapper.py +4 -0
- pingmapper-5.2.0/pingmapper/version.py +1 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper.egg-info/PKG-INFO +1 -1
- pingmapper-5.1.0/pingmapper/version.py +0 -1
- {pingmapper-5.1.0 → pingmapper-5.2.0}/LICENSE +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/README.md +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/__init__.py +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/class_mapSubstrateObj.py +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper/test_time.py +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper.egg-info/SOURCES.txt +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper.egg-info/dependency_links.txt +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper.egg-info/requires.txt +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/pingmapper.egg-info/top_level.txt +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/setup.cfg +0 -0
- {pingmapper-5.1.0 → pingmapper-5.2.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pingmapper
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.2.0
|
|
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
|
|
6
6
|
Author-email: bodine.cs@gmail.email
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import os, sys
|
|
3
3
|
|
|
4
|
+
# Configure TensorFlow runtime logging/CPU backend before any TF import occurs.
|
|
5
|
+
# Use setdefault so user-provided environment values still take precedence.
|
|
6
|
+
os.environ.setdefault('TF_CPP_MIN_LOG_LEVEL', '2')
|
|
7
|
+
os.environ.setdefault('TF_ENABLE_ONEDNN_OPTS', '0')
|
|
8
|
+
|
|
4
9
|
# Add 'pingmapper' to the path, may not need after pypi package...
|
|
5
10
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
6
11
|
PACKAGE_DIR = os.path.dirname(SCRIPT_DIR)
|
|
@@ -59,10 +59,13 @@ import matplotlib.pyplot as plt
|
|
|
59
59
|
|
|
60
60
|
import inspect
|
|
61
61
|
|
|
62
|
+
quiet_tensorflow_warnings()
|
|
63
|
+
|
|
62
64
|
try:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
with suppress_stdout_stderr():
|
|
66
|
+
from doodleverse_utils.imports import *
|
|
67
|
+
from doodleverse_utils.model_imports import *
|
|
68
|
+
from doodleverse_utils.prediction_imports import *
|
|
66
69
|
except ImportError as e:
|
|
67
70
|
import traceback
|
|
68
71
|
print('\n' + '='*80)
|
|
@@ -146,19 +149,38 @@ class portstarObj(object):
|
|
|
146
149
|
-------
|
|
147
150
|
portstarObj instance.
|
|
148
151
|
'''
|
|
152
|
+
beam_names = []
|
|
149
153
|
for obj in objs:
|
|
150
|
-
|
|
154
|
+
beam_name = str(obj.beamName)
|
|
155
|
+
beam_names.append(beam_name)
|
|
156
|
+
|
|
157
|
+
if beam_name.startswith('ss_port'):
|
|
151
158
|
self.port = obj
|
|
152
|
-
elif
|
|
159
|
+
elif beam_name.startswith('ss_star'):
|
|
153
160
|
self.star = obj
|
|
154
161
|
else:
|
|
155
162
|
print("Object is unknown...")
|
|
163
|
+
|
|
164
|
+
if not hasattr(self, 'port') or not hasattr(self, 'star'):
|
|
165
|
+
raise ValueError(
|
|
166
|
+
"portstarObj requires both side-scan channels (port and star). "
|
|
167
|
+
f"Received beam names: {beam_names}"
|
|
168
|
+
)
|
|
156
169
|
return
|
|
157
170
|
|
|
158
171
|
############################################################################
|
|
159
172
|
# Get Port/Star Sonar Intensity and Merge #
|
|
160
173
|
############################################################################
|
|
161
174
|
|
|
175
|
+
#=======================================================================
|
|
176
|
+
def _get_sonar_mosaic_name_token(self):
|
|
177
|
+
beam_name = str(self.port.beamName)
|
|
178
|
+
if beam_name.startswith('ss_port_'):
|
|
179
|
+
return beam_name.replace('ss_port_', 'ss_', 1)
|
|
180
|
+
if beam_name.startswith('ss_port'):
|
|
181
|
+
return ''
|
|
182
|
+
return beam_name
|
|
183
|
+
|
|
162
184
|
#=======================================================================
|
|
163
185
|
def _getPortStarScanChunk(self,
|
|
164
186
|
i):
|
|
@@ -348,35 +370,35 @@ class portstarObj(object):
|
|
|
348
370
|
if mosaic == 1:
|
|
349
371
|
if son:
|
|
350
372
|
if self.port.rect_wcp:
|
|
351
|
-
_ = Parallel(n_jobs=
|
|
373
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(wcpToMosaic), threadCnt), verbose=10)(delayed(self._mosaicGtiff)([wcp], overview, i, son=son) for i, wcp in enumerate(wcpToMosaic))
|
|
352
374
|
if self.port.rect_wcr:
|
|
353
|
-
_ = Parallel(n_jobs=
|
|
375
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(srcToMosaic), threadCnt), verbose=10)(delayed(self._mosaicGtiff)([src], overview, i, son=son) for i, src in enumerate(srcToMosaic))
|
|
354
376
|
else:
|
|
355
377
|
if self.port.map_sub:
|
|
356
|
-
_ = Parallel(n_jobs=
|
|
378
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(subToMosaic), threadCnt), verbose=10)(delayed(self._mosaicGtiff)([sub], overview=overview, i=i, son=son) for i, sub in enumerate(subToMosaic))
|
|
357
379
|
|
|
358
380
|
if self.port.map_predict:
|
|
359
381
|
# Determine number of bands, i.e. substrate classes
|
|
360
382
|
bands = self._getBandCount(predictToMosaic[0][0])
|
|
361
383
|
for i, pred in enumerate(predictToMosaic):
|
|
362
|
-
_ = Parallel(n_jobs=
|
|
384
|
+
_ = Parallel(n_jobs=safe_n_jobs(bands, threadCnt), verbose=10)(delayed(self._mosaicGtiff)([pred], overview, i, bands=[c], son=True) for c in range(1,bands+1))
|
|
363
385
|
|
|
364
386
|
# Create vrt
|
|
365
387
|
elif mosaic == 2:
|
|
366
388
|
if son:
|
|
367
389
|
if self.port.rect_wcp:
|
|
368
|
-
_ = Parallel(n_jobs=
|
|
390
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(wcpToMosaic), threadCnt), verbose=10)(delayed(self._mosaicVRT)([wcp], overview, i, son=son) for i, wcp in enumerate(wcpToMosaic))
|
|
369
391
|
if self.port.rect_wcr:
|
|
370
|
-
_ = Parallel(n_jobs=
|
|
392
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(srcToMosaic), threadCnt), verbose=10)(delayed(self._mosaicVRT)([src], overview, i, son=son) for i, src in enumerate(srcToMosaic))
|
|
371
393
|
else:
|
|
372
394
|
if self.port.map_sub:
|
|
373
|
-
_ = Parallel(n_jobs=
|
|
395
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(subToMosaic), threadCnt), verbose=10)(delayed(self._mosaicVRT)([sub], overview, i, son=son) for i, sub in enumerate(subToMosaic))
|
|
374
396
|
|
|
375
397
|
if self.port.map_predict:
|
|
376
398
|
# Determine number of bands, i.e. substrate classes
|
|
377
399
|
bands = self._getBandCount(predictToMosaic[0][0])
|
|
378
400
|
for i, pred in enumerate(predictToMosaic):
|
|
379
|
-
_ = Parallel(n_jobs=
|
|
401
|
+
_ = Parallel(n_jobs=safe_n_jobs(bands, threadCnt), verbose=10)(delayed(self._mosaicVRT)([pred], overview, i, bands=[c], son=True) for c in range(1,bands+1))
|
|
380
402
|
|
|
381
403
|
return
|
|
382
404
|
|
|
@@ -425,6 +447,13 @@ class portstarObj(object):
|
|
|
425
447
|
|
|
426
448
|
chunkField = 'chunk_id'
|
|
427
449
|
|
|
450
|
+
def _iter_groups(df):
|
|
451
|
+
if 'transect' in df.columns:
|
|
452
|
+
groups = list(df.groupby('transect', dropna=False))
|
|
453
|
+
if len(groups) > 0:
|
|
454
|
+
return groups
|
|
455
|
+
return [(0, df)]
|
|
456
|
+
|
|
428
457
|
if son:
|
|
429
458
|
if self.port.rect_wcp: # Moscaic wcp sonograms if previousl exported
|
|
430
459
|
self.port._loadSonMeta()
|
|
@@ -433,15 +462,18 @@ class portstarObj(object):
|
|
|
433
462
|
portPath = os.path.join(self.port.outDir, 'rect_wcp')
|
|
434
463
|
|
|
435
464
|
port = []
|
|
436
|
-
for name, group in df
|
|
465
|
+
for name, group in _iter_groups(df):
|
|
437
466
|
chunks = pd.unique(group[chunkField])
|
|
438
467
|
port_transect = []
|
|
439
468
|
for chunk in chunks:
|
|
440
469
|
zero = self.port._addZero(chunk)
|
|
441
470
|
img_path = os.path.join(portPath, '*_{}{}.tif'.format(zero, chunk))
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
471
|
+
imgs = glob(img_path)
|
|
472
|
+
if len(imgs) == 0:
|
|
473
|
+
continue
|
|
474
|
+
port_transect.append(imgs[0])
|
|
475
|
+
if len(port_transect) > 0:
|
|
476
|
+
port.append(port_transect)
|
|
445
477
|
|
|
446
478
|
self.star._loadSonMeta()
|
|
447
479
|
df = self.star.sonMetaDF
|
|
@@ -449,15 +481,18 @@ class portstarObj(object):
|
|
|
449
481
|
starPath = os.path.join(self.star.outDir, 'rect_wcp')
|
|
450
482
|
|
|
451
483
|
star = []
|
|
452
|
-
for name, group in df
|
|
484
|
+
for name, group in _iter_groups(df):
|
|
453
485
|
chunks = pd.unique(group[chunkField])
|
|
454
486
|
star_transect = []
|
|
455
487
|
for chunk in chunks:
|
|
456
488
|
zero = self.port._addZero(chunk)
|
|
457
489
|
img_path = os.path.join(starPath, '*_{}{}.tif'.format(zero, chunk))
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
490
|
+
imgs = glob(img_path)
|
|
491
|
+
if len(imgs) == 0:
|
|
492
|
+
continue
|
|
493
|
+
star_transect.append(imgs[0])
|
|
494
|
+
if len(star_transect) > 0:
|
|
495
|
+
star.append(star_transect)
|
|
461
496
|
|
|
462
497
|
wcpToMosaic = [list(itertools.chain(*i)) for i in zip(port, star)]
|
|
463
498
|
|
|
@@ -469,18 +504,21 @@ class portstarObj(object):
|
|
|
469
504
|
portPath = os.path.join(self.port.outDir, 'rect_wcr')
|
|
470
505
|
|
|
471
506
|
port = []
|
|
472
|
-
for name, group in df
|
|
507
|
+
for name, group in _iter_groups(df):
|
|
473
508
|
chunks = pd.unique(group[chunkField])
|
|
474
509
|
port_transect = []
|
|
475
510
|
for chunk in chunks:
|
|
476
511
|
# try:
|
|
477
512
|
zero = self.port._addZero(chunk)
|
|
478
513
|
img_path = os.path.join(portPath, '*_{}{}.tif'.format(zero, chunk))
|
|
479
|
-
|
|
480
|
-
|
|
514
|
+
imgs = glob(img_path)
|
|
515
|
+
if len(imgs) == 0:
|
|
516
|
+
continue
|
|
517
|
+
port_transect.append(imgs[0])
|
|
481
518
|
# except:
|
|
482
519
|
# pass
|
|
483
|
-
|
|
520
|
+
if len(port_transect) > 0:
|
|
521
|
+
port.append(port_transect)
|
|
484
522
|
|
|
485
523
|
self.star._loadSonMeta()
|
|
486
524
|
df = self.star.sonMetaDF
|
|
@@ -488,18 +526,21 @@ class portstarObj(object):
|
|
|
488
526
|
starPath = os.path.join(self.star.outDir, 'rect_wcr')
|
|
489
527
|
|
|
490
528
|
star = []
|
|
491
|
-
for name, group in df
|
|
529
|
+
for name, group in _iter_groups(df):
|
|
492
530
|
chunks = pd.unique(group[chunkField])
|
|
493
531
|
star_transect = []
|
|
494
532
|
for chunk in chunks:
|
|
495
533
|
# try:
|
|
496
534
|
zero = self.star._addZero(chunk)
|
|
497
535
|
img_path = os.path.join(starPath, '*_{}{}.tif'.format(zero, chunk))
|
|
498
|
-
|
|
499
|
-
|
|
536
|
+
imgs = glob(img_path)
|
|
537
|
+
if len(imgs) == 0:
|
|
538
|
+
continue
|
|
539
|
+
star_transect.append(imgs[0])
|
|
500
540
|
# except:
|
|
501
541
|
# pass
|
|
502
|
-
|
|
542
|
+
if len(star_transect) > 0:
|
|
543
|
+
star.append(star_transect)
|
|
503
544
|
|
|
504
545
|
srcToMosaic = [list(itertools.chain(*i)) for i in zip(port, star)]
|
|
505
546
|
|
|
@@ -521,15 +562,18 @@ class portstarObj(object):
|
|
|
521
562
|
portPath = os.path.join(self.port.substrateDir, 'map_substrate_raster')
|
|
522
563
|
|
|
523
564
|
subToMosaic = []
|
|
524
|
-
for name, group in df
|
|
565
|
+
for name, group in _iter_groups(df):
|
|
525
566
|
chunks = pd.unique(group[chunkField])
|
|
526
567
|
port_transect = []
|
|
527
568
|
for chunk in chunks:
|
|
528
569
|
zero = self.port._addZero(chunk)
|
|
529
570
|
img_path = os.path.join(portPath, '*_{}{}.tif'.format(zero, chunk))
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
571
|
+
imgs = glob(img_path)
|
|
572
|
+
if len(imgs) == 0:
|
|
573
|
+
continue
|
|
574
|
+
port_transect.append(imgs[0])
|
|
575
|
+
if len(port_transect) > 0:
|
|
576
|
+
subToMosaic.append(port_transect)
|
|
533
577
|
|
|
534
578
|
if self.port.map_predict:
|
|
535
579
|
# Locate map files
|
|
@@ -549,35 +593,37 @@ class portstarObj(object):
|
|
|
549
593
|
if mosaic == 1:
|
|
550
594
|
if son:
|
|
551
595
|
if self.port.rect_wcp:
|
|
552
|
-
|
|
596
|
+
if len(wcpToMosaic) > 0:
|
|
597
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(wcpToMosaic), threadCnt), verbose=10)(delayed(self._mosaicGtiff)([wcp], overview, i, son=son) for i, wcp in enumerate(wcpToMosaic))
|
|
553
598
|
if self.port.rect_wcr:
|
|
554
|
-
|
|
599
|
+
if len(srcToMosaic) > 0:
|
|
600
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(srcToMosaic), threadCnt), verbose=10)(delayed(self._mosaicGtiff)([src], overview, i, son=son) for i, src in enumerate(srcToMosaic))
|
|
555
601
|
else:
|
|
556
602
|
if self.port.map_sub:
|
|
557
|
-
_ = Parallel(n_jobs=
|
|
603
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(subToMosaic), threadCnt), verbose=10)(delayed(self._mosaicGtiff)([sub], overview=overview, i=i, son=son) for i, sub in enumerate(subToMosaic))
|
|
558
604
|
|
|
559
605
|
if self.port.map_predict:
|
|
560
606
|
# Determine number of bands, i.e. substrate classes
|
|
561
607
|
bands = self._getBandCount(predictToMosaic[0][0])
|
|
562
608
|
for i, pred in enumerate(predictToMosaic):
|
|
563
|
-
_ = Parallel(n_jobs=
|
|
609
|
+
_ = Parallel(n_jobs=safe_n_jobs(bands, threadCnt), verbose=10)(delayed(self._mosaicGtiff)([pred], overview, i, bands=[c], son=True) for c in range(1,bands+1))
|
|
564
610
|
|
|
565
611
|
# Create vrt
|
|
566
612
|
elif mosaic == 2:
|
|
567
613
|
if son:
|
|
568
614
|
if self.port.rect_wcp:
|
|
569
|
-
_ = Parallel(n_jobs=
|
|
615
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(wcpToMosaic), threadCnt), verbose=10)(delayed(self._mosaicVRT)([wcp], overview, i, son=son) for i, wcp in enumerate(wcpToMosaic))
|
|
570
616
|
if self.port.rect_wcr:
|
|
571
|
-
_ = Parallel(n_jobs=
|
|
617
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(srcToMosaic), threadCnt), verbose=10)(delayed(self._mosaicVRT)([src], overview, i, son=son) for i, src in enumerate(srcToMosaic))
|
|
572
618
|
else:
|
|
573
619
|
if self.port.map_sub:
|
|
574
|
-
_ = Parallel(n_jobs=
|
|
620
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(subToMosaic), threadCnt), verbose=10)(delayed(self._mosaicVRT)([sub], overview, i, son=son) for i, sub in enumerate(subToMosaic))
|
|
575
621
|
|
|
576
622
|
if self.port.map_predict:
|
|
577
623
|
# Determine number of bands, i.e. substrate classes
|
|
578
624
|
bands = self._getBandCount(predictToMosaic[0][0])
|
|
579
625
|
for i, pred in enumerate(predictToMosaic):
|
|
580
|
-
_ = Parallel(n_jobs=
|
|
626
|
+
_ = Parallel(n_jobs=safe_n_jobs(bands, threadCnt), verbose=10)(delayed(self._mosaicVRT)([pred], overview, i, bands=[c], son=True) for c in range(1,bands+1))
|
|
581
627
|
|
|
582
628
|
return
|
|
583
629
|
|
|
@@ -623,10 +669,27 @@ class portstarObj(object):
|
|
|
623
669
|
# Iterate each sublist of images
|
|
624
670
|
outMosaic = []
|
|
625
671
|
for imgs in imgsToMosaic:
|
|
672
|
+
if imgs is None or len(imgs) == 0:
|
|
673
|
+
continue
|
|
674
|
+
|
|
675
|
+
# Preserve all source bands for sonar mosaics when no explicit band
|
|
676
|
+
# selection is provided. This is required for colorized 16-bit
|
|
677
|
+
# rectified outputs (RGB) so mosaics do not collapse to band 1.
|
|
678
|
+
bands_to_use = bands
|
|
679
|
+
if son and bands == [1] and len(imgs) > 0:
|
|
680
|
+
try:
|
|
681
|
+
src_ds = gdal.Open(imgs[0])
|
|
682
|
+
src_band_count = int(src_ds.RasterCount) if src_ds is not None else 1
|
|
683
|
+
src_ds = None
|
|
684
|
+
if src_band_count > 1:
|
|
685
|
+
bands_to_use = list(range(1, src_band_count + 1))
|
|
686
|
+
except Exception:
|
|
687
|
+
pass
|
|
626
688
|
|
|
627
689
|
# Set output file names
|
|
628
690
|
fileSuffix = os.path.split(os.path.dirname(imgs[0]))[-1] + '_mosaic_'+str(i)+'.vrt'
|
|
629
691
|
filePrefix = os.path.split(self.port.projDir)[-1]
|
|
692
|
+
sonar_token = self._get_sonar_mosaic_name_token()
|
|
630
693
|
if 'substrate' in fileSuffix:
|
|
631
694
|
outDir = os.path.join(self.port.substrateDir, 'map_substrate_mosaic')
|
|
632
695
|
outVRT = os.path.join(outDir, filePrefix+'_'+fileSuffix)
|
|
@@ -638,7 +701,10 @@ class portstarObj(object):
|
|
|
638
701
|
outVRT = os.path.join(outDir, filePrefix+'_'+'class_'+str(bands[0]-1)+'_'+fileSuffix)
|
|
639
702
|
else:
|
|
640
703
|
outDir = os.path.join(self.port.projDir, 'sonar_mosaic')
|
|
641
|
-
|
|
704
|
+
if sonar_token:
|
|
705
|
+
outVRT = os.path.join(outDir, filePrefix+'_'+sonar_token+'_'+fileSuffix)
|
|
706
|
+
else:
|
|
707
|
+
outVRT = os.path.join(outDir, filePrefix+'_'+fileSuffix)
|
|
642
708
|
outTIF = outVRT.replace('.vrt', '.tif')
|
|
643
709
|
|
|
644
710
|
if not os.path.isdir(outDir):
|
|
@@ -648,7 +714,7 @@ class portstarObj(object):
|
|
|
648
714
|
pass
|
|
649
715
|
|
|
650
716
|
# First built a vrt
|
|
651
|
-
vrt_options = gdal.BuildVRTOptions(resampleAlg=resampleAlg, bandList =
|
|
717
|
+
vrt_options = gdal.BuildVRTOptions(resampleAlg=resampleAlg, bandList = bands_to_use)
|
|
652
718
|
gdal.BuildVRT(outVRT, imgs, options=vrt_options)
|
|
653
719
|
|
|
654
720
|
# Create GeoTiff from vrt
|
|
@@ -679,7 +745,7 @@ class portstarObj(object):
|
|
|
679
745
|
outMosaic.append(outTIF)
|
|
680
746
|
|
|
681
747
|
gc.collect()
|
|
682
|
-
return
|
|
748
|
+
return outMosaic
|
|
683
749
|
|
|
684
750
|
#=======================================================================
|
|
685
751
|
def _mosaicVRT(self,
|
|
@@ -726,10 +792,26 @@ class portstarObj(object):
|
|
|
726
792
|
# Iterate each sublist of images
|
|
727
793
|
outMosaic = []
|
|
728
794
|
for imgs in imgsToMosaic:
|
|
795
|
+
if imgs is None or len(imgs) == 0:
|
|
796
|
+
continue
|
|
797
|
+
|
|
798
|
+
# Preserve all source bands for sonar mosaics when no explicit band
|
|
799
|
+
# selection is provided.
|
|
800
|
+
bands_to_use = bands
|
|
801
|
+
if son and bands == [1] and len(imgs) > 0:
|
|
802
|
+
try:
|
|
803
|
+
src_ds = gdal.Open(imgs[0])
|
|
804
|
+
src_band_count = int(src_ds.RasterCount) if src_ds is not None else 1
|
|
805
|
+
src_ds = None
|
|
806
|
+
if src_band_count > 1:
|
|
807
|
+
bands_to_use = list(range(1, src_band_count + 1))
|
|
808
|
+
except Exception:
|
|
809
|
+
pass
|
|
729
810
|
|
|
730
811
|
# Set output file names
|
|
731
812
|
fileSuffix = os.path.split(os.path.dirname(imgs[0]))[-1] + '_mosaic_'+str(i)+'.vrt'
|
|
732
813
|
filePrefix = os.path.split(self.port.projDir)[-1]
|
|
814
|
+
sonar_token = self._get_sonar_mosaic_name_token()
|
|
733
815
|
if 'substrate' in fileSuffix:
|
|
734
816
|
outDir = os.path.join(self.port.substrateDir, 'map_substrate_mosaic')
|
|
735
817
|
outVRT = os.path.join(outDir, filePrefix+'_'+fileSuffix)
|
|
@@ -741,7 +823,10 @@ class portstarObj(object):
|
|
|
741
823
|
outVRT = os.path.join(outDir, filePrefix+'_'+'class_'+str(bands[0]-1)+'_'+fileSuffix)
|
|
742
824
|
else:
|
|
743
825
|
outDir = os.path.join(self.port.projDir, 'sonar_mosaic')
|
|
744
|
-
|
|
826
|
+
if sonar_token:
|
|
827
|
+
outVRT = os.path.join(outDir, filePrefix+'_'+sonar_token+'_'+fileSuffix)
|
|
828
|
+
else:
|
|
829
|
+
outVRT = os.path.join(outDir, filePrefix+'_'+fileSuffix)
|
|
745
830
|
|
|
746
831
|
if not os.path.isdir(outDir):
|
|
747
832
|
try:
|
|
@@ -755,7 +840,7 @@ class portstarObj(object):
|
|
|
755
840
|
|
|
756
841
|
# Build VRT
|
|
757
842
|
# vrt_options = gdal.BuildVRTOptions(resampleAlg=resampleAlg, bandList = bands, xRes=xRes, yRes=yRes)
|
|
758
|
-
vrt_options = gdal.BuildVRTOptions(resampleAlg=resampleAlg, bandList =
|
|
843
|
+
vrt_options = gdal.BuildVRTOptions(resampleAlg=resampleAlg, bandList = bands_to_use)
|
|
759
844
|
gdal.BuildVRT(outVRT, imgs, options=vrt_options)
|
|
760
845
|
|
|
761
846
|
# Generate overviews
|
|
@@ -1210,7 +1295,7 @@ class portstarObj(object):
|
|
|
1210
1295
|
port = []
|
|
1211
1296
|
for pdi, pdc in zip(portDepPix, portDepPixFinal):
|
|
1212
1297
|
if np.isnan(pdc): # Final pick is nan
|
|
1213
|
-
if np.isnan(
|
|
1298
|
+
if np.isnan(pdi): # Initial pick is nan
|
|
1214
1299
|
port.append(0) # set to 0
|
|
1215
1300
|
else: # Initial pick not nan
|
|
1216
1301
|
port.append(pdi) # Use initial pick
|
|
@@ -1231,7 +1316,7 @@ class portstarObj(object):
|
|
|
1231
1316
|
star.append(sdi) # Use initial pick
|
|
1232
1317
|
|
|
1233
1318
|
elif sdc < 0:
|
|
1234
|
-
|
|
1319
|
+
star.append(0)
|
|
1235
1320
|
|
|
1236
1321
|
else: # Final pick ok
|
|
1237
1322
|
star.append(sdc)
|
|
@@ -1482,8 +1567,25 @@ class portstarObj(object):
|
|
|
1482
1567
|
chunks = pd.unique(portDF['chunk_id'])
|
|
1483
1568
|
|
|
1484
1569
|
if detectDep == 0:
|
|
1485
|
-
|
|
1486
|
-
|
|
1570
|
+
def _depth_series(df):
|
|
1571
|
+
# Some formats (e.g., Garmin RSD) may not include dep_m in metadata.
|
|
1572
|
+
if 'dep_m' in df.columns:
|
|
1573
|
+
return pd.to_numeric(df['dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1574
|
+
if 'inst_dep_m' in df.columns:
|
|
1575
|
+
return pd.to_numeric(df['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1576
|
+
return np.zeros(len(df), dtype=float)
|
|
1577
|
+
|
|
1578
|
+
portInstDepth = pd.to_numeric(portDF['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1579
|
+
starInstDepth = pd.to_numeric(starDF['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1580
|
+
|
|
1581
|
+
portMetaDepth = _depth_series(portDF)
|
|
1582
|
+
starMetaDepth = _depth_series(starDF)
|
|
1583
|
+
|
|
1584
|
+
portValid = np.isfinite(portInstDepth) & (portInstDepth > 0)
|
|
1585
|
+
starValid = np.isfinite(starInstDepth) & (starInstDepth > 0)
|
|
1586
|
+
|
|
1587
|
+
portInstDepth = np.where(portValid, portInstDepth, portMetaDepth)
|
|
1588
|
+
starInstDepth = np.where(starValid, starInstDepth, starMetaDepth)
|
|
1487
1589
|
|
|
1488
1590
|
if smthDep:
|
|
1489
1591
|
# print("\nSmoothing depth values...")
|
|
@@ -1509,8 +1611,8 @@ class portstarObj(object):
|
|
|
1509
1611
|
portDF['dep_m'] = portInstDepth
|
|
1510
1612
|
starDF['dep_m'] = starInstDepth
|
|
1511
1613
|
|
|
1512
|
-
portDF['dep_m_Method'] = 'Instrument Depth'
|
|
1513
|
-
starDF['dep_m_Method'] = 'Instrument Depth'
|
|
1614
|
+
portDF['dep_m_Method'] = 'Instrument/Metadata Depth'
|
|
1615
|
+
starDF['dep_m_Method'] = 'Instrument/Metadata Depth'
|
|
1514
1616
|
|
|
1515
1617
|
portDF['dep_m_smth'] = smthDep
|
|
1516
1618
|
starDF['dep_m_smth'] = smthDep
|
|
@@ -1612,11 +1714,17 @@ class portstarObj(object):
|
|
|
1612
1714
|
starDep[starDep == 0] = np.nan
|
|
1613
1715
|
|
|
1614
1716
|
nans, x = np.isnan(portDep), lambda z: z.nonzero()[0]
|
|
1615
|
-
|
|
1717
|
+
if (~nans).any():
|
|
1718
|
+
portDep[nans] = np.interp(x(nans), x(~nans), portDep[~nans])
|
|
1719
|
+
else:
|
|
1720
|
+
portDep[nans] = 0
|
|
1616
1721
|
portDF['dep_m'] = portDep
|
|
1617
1722
|
|
|
1618
1723
|
nans, x = np.isnan(starDep), lambda z: z.nonzero()[0]
|
|
1619
|
-
|
|
1724
|
+
if (~nans).any():
|
|
1725
|
+
starDep[nans] = np.interp(x(nans), x(~nans), starDep[~nans])
|
|
1726
|
+
else:
|
|
1727
|
+
starDep[nans] = 0
|
|
1620
1728
|
starDF['dep_m'] = starDep
|
|
1621
1729
|
|
|
1622
1730
|
# Export to csv
|
|
@@ -1697,10 +1805,16 @@ class portstarObj(object):
|
|
|
1697
1805
|
portDF = portDF.loc[portDF['chunk_id'] == i, ['inst_dep_m', 'dep_m', 'pixM']]
|
|
1698
1806
|
starDF = starDF.loc[starDF['chunk_id'] == i, ['inst_dep_m', 'dep_m', 'pixM']]
|
|
1699
1807
|
|
|
1700
|
-
|
|
1808
|
+
portInstDepth = pd.to_numeric(portDF['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1809
|
+
portMetaDepth = pd.to_numeric(portDF['dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1810
|
+
portInstDepth = np.where(np.isfinite(portInstDepth) & (portInstDepth > 0), portInstDepth, portMetaDepth)
|
|
1811
|
+
portInst = np.nan_to_num(portInstDepth / portDF['pixM'].to_numpy(dtype=float), nan=0.0).astype(int)
|
|
1701
1812
|
portAuto = (portDF['dep_m'] / portDF['pixM']).to_numpy(dtype=int, copy=True)
|
|
1702
1813
|
|
|
1703
|
-
|
|
1814
|
+
starInstDepth = pd.to_numeric(starDF['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1815
|
+
starMetaDepth = pd.to_numeric(starDF['dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1816
|
+
starInstDepth = np.where(np.isfinite(starInstDepth) & (starInstDepth > 0), starInstDepth, starMetaDepth)
|
|
1817
|
+
starInst = np.nan_to_num(starInstDepth / starDF['pixM'].to_numpy(dtype=float), nan=0.0).astype(int)
|
|
1704
1818
|
starAuto = (starDF['dep_m'] / starDF['pixM']).to_numpy(dtype=int, copy=True)
|
|
1705
1819
|
|
|
1706
1820
|
# Ensure port/star same length
|
|
@@ -2572,7 +2686,7 @@ class portstarObj(object):
|
|
|
2572
2686
|
os.mkdir(outDir)
|
|
2573
2687
|
|
|
2574
2688
|
print("\n\tExporting to shapefile...")
|
|
2575
|
-
_ = Parallel(n_jobs=
|
|
2689
|
+
_ = Parallel(n_jobs=safe_n_jobs(len(rasterFiles), threadCnt), verbose=10)(delayed(self._createPolygon)(f, outDir) for f in rasterFiles)
|
|
2576
2690
|
|
|
2577
2691
|
return
|
|
2578
2692
|
|