pingmapper 5.5.0__tar.gz → 5.5.2__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.5.0 → pingmapper-5.5.2}/PKG-INFO +1 -1
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/class_mapSubstrateObj.py +1 -1
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/class_portstarObj.py +9 -3
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/class_rectObj.py +5 -5
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/class_sonObj.py +185 -17
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/class_sonObj_nadirgaptest.py +27 -3
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/default_params.json +3 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/gui_main.py +36 -2
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/main_readFiles.py +12 -0
- pingmapper-5.5.2/pingmapper/version.py +1 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper.egg-info/PKG-INFO +1 -1
- pingmapper-5.5.0/pingmapper/version.py +0 -1
- {pingmapper-5.5.0 → pingmapper-5.5.2}/LICENSE +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/README.md +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/__init__.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/__main__.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/doWork.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/funcs_common.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/funcs_model.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/funcs_rectify.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/main_mapSubstrate.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/main_rectify.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/nonGUI_batch_main.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/nonGui_main.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0926.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0929.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/scratch/funcs_pyhum_correct.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/scratch/main.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/scratch/main_batchDirectory.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/self_check.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/test_PINGMapper.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/test_cli_self_check.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/test_dq_filter.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/test_time.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/DRAFT_Workflows/avg_predictions_Mussel_WBL.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/DRAFT_Workflows/gen_centerline.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/DRAFT_Workflows/gen_centerline_from_bankline.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/DRAFT_Workflows/gen_centerline_trkpnts_fitspline_DRAFT.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/DRAFT_Workflows/testEXAMPLE_mosaic_logit.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/RawEGN_avg_predictions.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/00_substrate_logits_mosaic_transects.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/00_substrate_shps_mosaic_transects.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/01_gen_centerline_from_coverage.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/02_gen_summary_stamp_shps.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/03_gen_summary_shp.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/04_combine_summary_shp_csv.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/05_gen_summary_shp_plots.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/06_compare_raw-egn_volume.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/08_raw-egn_hardReacheFreq_hist.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/09_raw-egn_PatchSize_density.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/Substrate_Summaries/summarize_project_substrate.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/export_coverage.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/main_mosaic_transects.py +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper.egg-info/SOURCES.txt +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper.egg-info/dependency_links.txt +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper.egg-info/requires.txt +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper.egg-info/top_level.txt +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/pyproject.toml +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/setup.cfg +0 -0
- {pingmapper-5.5.0 → pingmapper-5.5.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pingmapper
|
|
3
|
-
Version: 5.5.
|
|
3
|
+
Version: 5.5.2
|
|
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
|
|
@@ -880,7 +880,7 @@ class mapSubObj(rectObj):
|
|
|
880
880
|
ax.imshow(son, cmap='gray')
|
|
881
881
|
|
|
882
882
|
# Prepare color map
|
|
883
|
-
color_map = plt.
|
|
883
|
+
color_map = plt.get_cmap('viridis')
|
|
884
884
|
|
|
885
885
|
im = ax.imshow(c, cmap=color_map, alpha=0.5, vmin=minSoft, vmax=maxSoft)
|
|
886
886
|
ax.axis('off')
|
|
@@ -3185,7 +3185,11 @@ class portstarObj(object):
|
|
|
3185
3185
|
|
|
3186
3186
|
for feature in dst_layer:
|
|
3187
3187
|
subID = str(int(feature.GetField('Substrate')))
|
|
3188
|
-
subName = MY_CLASS_NAMES
|
|
3188
|
+
subName = MY_CLASS_NAMES.get(subID)
|
|
3189
|
+
if subName is None:
|
|
3190
|
+
print("\n\tWARNING: Unexpected substrate value '{}' found in raster. "
|
|
3191
|
+
"This value is not in the model config and will be removed from output.".format(subID))
|
|
3192
|
+
subName = 'Unknown'
|
|
3189
3193
|
feature.SetField('Name', subName)
|
|
3190
3194
|
dst_layer.SetFeature(feature)
|
|
3191
3195
|
|
|
@@ -3204,10 +3208,12 @@ class portstarObj(object):
|
|
|
3204
3208
|
feature.SetField("Area_m", area)
|
|
3205
3209
|
dst_layer.SetFeature(feature)
|
|
3206
3210
|
|
|
3207
|
-
# Delete NoData
|
|
3211
|
+
# Delete NoData and any unexpected-value polygons
|
|
3208
3212
|
# https://gis.stackexchange.com/questions/254444/deleting-selected-features-from-vector-ogr-in-gdal-python
|
|
3213
|
+
valid_sub_ids = [int(k) for k in MY_CLASS_NAMES.keys() if int(k) != 0]
|
|
3214
|
+
invalid_filter = "Substrate NOT IN ({})".format(','.join(str(v) for v in valid_sub_ids))
|
|
3209
3215
|
layer = dst_ds.GetLayer()
|
|
3210
|
-
layer.SetAttributeFilter(
|
|
3216
|
+
layer.SetAttributeFilter(invalid_filter)
|
|
3211
3217
|
|
|
3212
3218
|
for feat in layer:
|
|
3213
3219
|
layer.DeleteFeature(feat.GetFID())
|
|
@@ -1968,7 +1968,7 @@ class rectObj(sonObj):
|
|
|
1968
1968
|
use_uint8_rgb = self._export_colormap_as_uint8()
|
|
1969
1969
|
if source_scale_bounds is not None:
|
|
1970
1970
|
norm_data = self._normalize_with_bounds(sonRect_raw16, source_scale_bounds[0], source_scale_bounds[1])
|
|
1971
|
-
cmap = plt.
|
|
1971
|
+
cmap = plt.get_cmap(self.son_colorMap_name)(norm_data)
|
|
1972
1972
|
if use_uint8_rgb:
|
|
1973
1973
|
sonRect_out = np.clip(cmap[:, :, :3] * 255.0, 0, 255).astype(np.uint8)
|
|
1974
1974
|
else:
|
|
@@ -2769,9 +2769,9 @@ class rectObj(sonObj):
|
|
|
2769
2769
|
if source_scale_bounds is not None:
|
|
2770
2770
|
norm_data = self._normalize_with_bounds(out16_raw, source_scale_bounds[0], source_scale_bounds[1])
|
|
2771
2771
|
if use_uint8_rgb:
|
|
2772
|
-
out16 = np.clip(plt.
|
|
2772
|
+
out16 = np.clip(plt.get_cmap(self.son_colorMap_name)(norm_data)[:, :, :3] * 255.0, 0, 255).astype(np.uint8)
|
|
2773
2773
|
else:
|
|
2774
|
-
out16 = np.clip(plt.
|
|
2774
|
+
out16 = np.clip(plt.get_cmap(self.son_colorMap_name)(norm_data)[:, :, :3] * 65535.0, 0, 65535).astype(np.uint16)
|
|
2775
2775
|
valid_mask = out16_raw > 0
|
|
2776
2776
|
out16[valid_mask] = np.maximum(out16[valid_mask], 1)
|
|
2777
2777
|
else:
|
|
@@ -2914,9 +2914,9 @@ class rectObj(sonObj):
|
|
|
2914
2914
|
if source_scale_bounds is not None:
|
|
2915
2915
|
norm_data = self._normalize_with_bounds(out16_raw, source_scale_bounds[0], source_scale_bounds[1])
|
|
2916
2916
|
if use_uint8_rgb:
|
|
2917
|
-
out16 = np.clip(plt.
|
|
2917
|
+
out16 = np.clip(plt.get_cmap(self.son_colorMap_name)(norm_data)[:, :, :3] * 255.0, 0, 255).astype(np.uint8)
|
|
2918
2918
|
else:
|
|
2919
|
-
out16 = np.clip(plt.
|
|
2919
|
+
out16 = np.clip(plt.get_cmap(self.son_colorMap_name)(norm_data)[:, :, :3] * 65535.0, 0, 65535).astype(np.uint16)
|
|
2920
2920
|
valid_mask = out16_raw > 0
|
|
2921
2921
|
out16[valid_mask] = np.maximum(out16[valid_mask], 1)
|
|
2922
2922
|
else:
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
# SOFTWARE.
|
|
31
31
|
|
|
32
32
|
import os, sys
|
|
33
|
+
from skimage import exposure
|
|
33
34
|
|
|
34
35
|
# Add 'pingmapper' to the path, may not need after pypi package...
|
|
35
36
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
@@ -708,10 +709,34 @@ class sonObj(object):
|
|
|
708
709
|
else:
|
|
709
710
|
time_table = pd.read_csv(time_table)
|
|
710
711
|
|
|
712
|
+
if 'start_seconds' not in time_table.columns or 'end_seconds' not in time_table.columns:
|
|
713
|
+
raise ValueError("time_table must contain 'start_seconds' and 'end_seconds' columns.")
|
|
714
|
+
|
|
715
|
+
# Normalize to numeric and drop unusable rows.
|
|
716
|
+
time_table['start_seconds'] = pd.to_numeric(time_table['start_seconds'], errors='coerce')
|
|
717
|
+
time_table['end_seconds'] = pd.to_numeric(time_table['end_seconds'], errors='coerce')
|
|
718
|
+
time_table = time_table.dropna(subset=['start_seconds', 'end_seconds'])
|
|
719
|
+
|
|
720
|
+
if time_table.empty:
|
|
721
|
+
return sonDF
|
|
722
|
+
|
|
723
|
+
son_time = pd.to_numeric(sonDF[time_col], errors='coerce')
|
|
724
|
+
son_min = son_time.min()
|
|
725
|
+
|
|
726
|
+
# Auto-detect relative clip ranges when sonar time is epoch-like and
|
|
727
|
+
# clip-table values are small. This allows 0..N seconds-from-start.
|
|
728
|
+
tt_max = np.nanmax(np.abs(time_table[['start_seconds', 'end_seconds']].to_numpy(dtype=float)))
|
|
729
|
+
use_relative_seconds = np.isfinite(son_min) and son_min > 1e8 and np.isfinite(tt_max) and tt_max < 1e7
|
|
730
|
+
|
|
731
|
+
offset = float(son_min) if use_relative_seconds else 0.0
|
|
732
|
+
|
|
711
733
|
for i, row in time_table.iterrows():
|
|
712
734
|
|
|
713
|
-
start = row['start_seconds']
|
|
714
|
-
end = row['end_seconds']
|
|
735
|
+
start = float(row['start_seconds']) + offset
|
|
736
|
+
end = float(row['end_seconds']) + offset
|
|
737
|
+
|
|
738
|
+
if end < start:
|
|
739
|
+
start, end = end, start
|
|
715
740
|
|
|
716
741
|
# dfFilt = sonDF[(sonDF['time_s'] >= start) & (sonDF['time_s'] <= end)]
|
|
717
742
|
sonDF.loc[(sonDF[time_col] >= start) & (sonDF[time_col] <= end) & (sonDF[filtCol] == True), filtTimeCol] = True
|
|
@@ -1238,6 +1263,19 @@ class sonObj(object):
|
|
|
1238
1263
|
if np.isfinite(wf) and wf > 0:
|
|
1239
1264
|
dat = dat * (2.0 ** (-float(wf)))
|
|
1240
1265
|
|
|
1266
|
+
if bool(getattr(self, '_use_cerulean_power_scale', False)):
|
|
1267
|
+
dat = dat.astype(np.float32, copy=False)
|
|
1268
|
+
if hasattr(self, 'minPwrDb') and hasattr(self, 'maxPwrDb') and i < len(self.minPwrDb) and i < len(self.maxPwrDb):
|
|
1269
|
+
min_db = self.minPwrDb[i]
|
|
1270
|
+
max_db = self.maxPwrDb[i]
|
|
1271
|
+
if np.isfinite(min_db) and np.isfinite(max_db) and (max_db > min_db):
|
|
1272
|
+
# Issue #206: Cerulean pwr_results[] are normalized
|
|
1273
|
+
# uint16 values that must be rescaled with min/max dB.
|
|
1274
|
+
dat_db = float(min_db) + (dat / 65535.0) * (float(max_db) - float(min_db))
|
|
1275
|
+
# Keep values non-negative for downstream intensity
|
|
1276
|
+
# processing while preserving the per-ping dB span.
|
|
1277
|
+
dat = dat_db - float(min_db)
|
|
1278
|
+
|
|
1241
1279
|
n_samples = min(len(dat), sonDat.shape[0])
|
|
1242
1280
|
if n_samples <= 0:
|
|
1243
1281
|
skipped_reads += 1
|
|
@@ -1268,6 +1306,82 @@ class sonObj(object):
|
|
|
1268
1306
|
self.sonDat = self._convert_son_dat_to_uint8(sonDat)
|
|
1269
1307
|
return
|
|
1270
1308
|
|
|
1309
|
+
def _apply_display_enhancements(self, sonDat):
|
|
1310
|
+
"""Optional display-stage intensity transforms before uint8 mapping.
|
|
1311
|
+
|
|
1312
|
+
These transforms are intended to improve perceptual contrast of exported
|
|
1313
|
+
sonograms while keeping the processing pipeline opt-in and backward-
|
|
1314
|
+
compatible by default.
|
|
1315
|
+
"""
|
|
1316
|
+
use_db = bool(getattr(self, 'sonar_db_transform', False))
|
|
1317
|
+
use_clahe = bool(getattr(self, 'sonar_clahe', False))
|
|
1318
|
+
|
|
1319
|
+
if not use_db and not use_clahe:
|
|
1320
|
+
return sonDat
|
|
1321
|
+
|
|
1322
|
+
arr = np.asarray(sonDat, dtype=np.float32)
|
|
1323
|
+
if arr.size == 0:
|
|
1324
|
+
return arr
|
|
1325
|
+
|
|
1326
|
+
arr[~np.isfinite(arr)] = 0.0
|
|
1327
|
+
arr[arr < 0] = 0.0
|
|
1328
|
+
|
|
1329
|
+
valid = arr > 0
|
|
1330
|
+
if not np.any(valid):
|
|
1331
|
+
return arr
|
|
1332
|
+
|
|
1333
|
+
if use_db:
|
|
1334
|
+
# Use the smallest positive intensity as the log floor to avoid
|
|
1335
|
+
# collapsing zeros to -inf and to preserve relative low amplitudes.
|
|
1336
|
+
floor = float(np.nanmin(arr[valid]))
|
|
1337
|
+
if (not np.isfinite(floor)) or floor <= 0:
|
|
1338
|
+
floor = 1.0
|
|
1339
|
+
arr = np.maximum(arr, floor)
|
|
1340
|
+
arr = 20.0 * np.log10(arr)
|
|
1341
|
+
arr = arr - np.nanmin(arr)
|
|
1342
|
+
|
|
1343
|
+
if use_clahe:
|
|
1344
|
+
max_val = float(np.nanmax(arr))
|
|
1345
|
+
if np.isfinite(max_val) and max_val > 0:
|
|
1346
|
+
arr01 = np.clip(arr / max_val, 0.0, 1.0)
|
|
1347
|
+
clip_limit = float(getattr(self, 'sonar_clahe_clip_limit', 0.01))
|
|
1348
|
+
if (not np.isfinite(clip_limit)) or clip_limit <= 0:
|
|
1349
|
+
clip_limit = 0.01
|
|
1350
|
+
try:
|
|
1351
|
+
arr01 = exposure.equalize_adapthist(arr01, clip_limit=clip_limit)
|
|
1352
|
+
arr = np.asarray(arr01, dtype=np.float32)
|
|
1353
|
+
except MemoryError:
|
|
1354
|
+
arr = self._apply_clahe_chunked(arr01, clip_limit)
|
|
1355
|
+
except np.core._exceptions._ArrayMemoryError:
|
|
1356
|
+
arr = self._apply_clahe_chunked(arr01, clip_limit)
|
|
1357
|
+
|
|
1358
|
+
# Preserve no-data convention for empty samples.
|
|
1359
|
+
arr[~valid] = 0.0
|
|
1360
|
+
return arr
|
|
1361
|
+
|
|
1362
|
+
def _apply_clahe_chunked(self, arr01, clip_limit):
|
|
1363
|
+
"""Apply CLAHE in row-wise stripes to reduce peak memory usage."""
|
|
1364
|
+
src = np.asarray(arr01, dtype=np.float32)
|
|
1365
|
+
h, w = src.shape
|
|
1366
|
+
if h == 0 or w == 0:
|
|
1367
|
+
return src
|
|
1368
|
+
|
|
1369
|
+
# Keep per-stripe working set bounded. equalize_adapthist promotes to
|
|
1370
|
+
# float64 internally, so we target moderate stripe sizes.
|
|
1371
|
+
stripe_rows = int(getattr(self, 'sonar_clahe_rows_per_chunk', 512))
|
|
1372
|
+
if stripe_rows <= 0:
|
|
1373
|
+
stripe_rows = 512
|
|
1374
|
+
stripe_rows = min(stripe_rows, h)
|
|
1375
|
+
|
|
1376
|
+
out = np.empty_like(src, dtype=np.float32)
|
|
1377
|
+
for start in range(0, h, stripe_rows):
|
|
1378
|
+
end = min(start + stripe_rows, h)
|
|
1379
|
+
stripe = src[start:end, :]
|
|
1380
|
+
stripe_eq = exposure.equalize_adapthist(stripe, clip_limit=clip_limit)
|
|
1381
|
+
out[start:end, :] = np.asarray(stripe_eq, dtype=np.float32)
|
|
1382
|
+
|
|
1383
|
+
return out
|
|
1384
|
+
|
|
1271
1385
|
def _apply_tvg(self, sonDat):
|
|
1272
1386
|
sonDat = np.asarray(sonDat, dtype=np.float32)
|
|
1273
1387
|
|
|
@@ -1872,7 +1986,7 @@ class sonObj(object):
|
|
|
1872
1986
|
return out
|
|
1873
1987
|
|
|
1874
1988
|
def _colorize_array_batched(self, norm_data, valid_mask, cmap_name, scale_max, out_dtype):
|
|
1875
|
-
cmap = plt.
|
|
1989
|
+
cmap = plt.get_cmap(cmap_name)
|
|
1876
1990
|
height, width = norm_data.shape
|
|
1877
1991
|
out = np.zeros((height, width, 3), dtype=out_dtype)
|
|
1878
1992
|
|
|
@@ -1979,7 +2093,8 @@ class sonObj(object):
|
|
|
1979
2093
|
k,
|
|
1980
2094
|
imgOutPrefix,
|
|
1981
2095
|
tileFile='.jpg',
|
|
1982
|
-
colormap=False
|
|
2096
|
+
colormap=False,
|
|
2097
|
+
apply_display_enhancement=True):
|
|
1983
2098
|
'''
|
|
1984
2099
|
Using currently saved ping ping returns stored in self.sonDAT,
|
|
1985
2100
|
saves an unrectified image of the sonar echogram.
|
|
@@ -2016,7 +2131,15 @@ class sonObj(object):
|
|
|
2016
2131
|
data = self._prepare_export_uint16(self.sonDat)
|
|
2017
2132
|
data = self._reserve_zero_for_nodata(data)
|
|
2018
2133
|
else:
|
|
2019
|
-
|
|
2134
|
+
arr = self.sonDat
|
|
2135
|
+
if apply_display_enhancement and (bool(getattr(self, 'sonar_db_transform', False)) or bool(getattr(self, 'sonar_clahe', False))):
|
|
2136
|
+
arr = self._apply_display_enhancements(arr)
|
|
2137
|
+
|
|
2138
|
+
if np.issubdtype(np.asarray(arr).dtype, np.floating):
|
|
2139
|
+
data = self._convert_son_dat_to_uint8(arr)
|
|
2140
|
+
else:
|
|
2141
|
+
data = np.clip(arr, 0, 255).astype(np.uint8)
|
|
2142
|
+
|
|
2020
2143
|
data = self._reserve_zero_for_nodata(data)
|
|
2021
2144
|
|
|
2022
2145
|
# File name zero padding
|
|
@@ -2039,7 +2162,8 @@ class sonObj(object):
|
|
|
2039
2162
|
k,
|
|
2040
2163
|
imgOutPrefix,
|
|
2041
2164
|
tileFile='.jpg',
|
|
2042
|
-
colormap=False
|
|
2165
|
+
colormap=False,
|
|
2166
|
+
apply_display_enhancement=True):
|
|
2043
2167
|
'''
|
|
2044
2168
|
Using currently saved ping ping returns stored in self.sonDAT,
|
|
2045
2169
|
saves an unrectified image of the sonar echogram.
|
|
@@ -2077,7 +2201,15 @@ class sonObj(object):
|
|
|
2077
2201
|
data = self._prepare_export_uint16(self.sonDat)
|
|
2078
2202
|
data = self._reserve_zero_for_nodata(data)
|
|
2079
2203
|
else:
|
|
2080
|
-
|
|
2204
|
+
arr = self.sonDat
|
|
2205
|
+
if apply_display_enhancement and (bool(getattr(self, 'sonar_db_transform', False)) or bool(getattr(self, 'sonar_clahe', False))):
|
|
2206
|
+
arr = self._apply_display_enhancements(arr)
|
|
2207
|
+
|
|
2208
|
+
if np.issubdtype(np.asarray(arr).dtype, np.floating):
|
|
2209
|
+
data = self._convert_son_dat_to_uint8(arr)
|
|
2210
|
+
else:
|
|
2211
|
+
data = np.clip(arr, 0, 255).astype(np.uint8)
|
|
2212
|
+
|
|
2081
2213
|
data = self._reserve_zero_for_nodata(data)
|
|
2082
2214
|
|
|
2083
2215
|
# File name zero padding
|
|
@@ -2147,40 +2279,44 @@ class sonObj(object):
|
|
|
2147
2279
|
if self.wcp:
|
|
2148
2280
|
# Do speed correction
|
|
2149
2281
|
export_16bit = bool(getattr(self, 'export_16bit', False)) and not bool(getattr(self, 'son8bit', False))
|
|
2150
|
-
|
|
2282
|
+
pre_spd_enhance = (not export_16bit) and (bool(getattr(self, 'sonar_db_transform', False)) or bool(getattr(self, 'sonar_clahe', False)))
|
|
2283
|
+
self._doSpdCor(chunk, spdCor=spdCor, mask_shdw=mask_shdw, maxCrop=maxCrop, do_egn=self.egn, stretch_wcp=True, integer=not export_16bit, pre_spd_enhance=pre_spd_enhance)
|
|
2151
2284
|
|
|
2152
2285
|
if self.sonDat is not np.nan:
|
|
2153
|
-
self._writeTilesPlot(chunk, imgOutPrefix='wcp', tileFile=tileFile, colormap=True)
|
|
2286
|
+
self._writeTilesPlot(chunk, imgOutPrefix='wcp', tileFile=tileFile, colormap=True, apply_display_enhancement=not pre_spd_enhance)
|
|
2154
2287
|
else:
|
|
2155
2288
|
pass
|
|
2156
2289
|
|
|
2157
2290
|
if self.wcm:
|
|
2158
2291
|
# Do speed correction
|
|
2159
2292
|
export_16bit = bool(getattr(self, 'export_16bit', False)) and not bool(getattr(self, 'son8bit', False))
|
|
2160
|
-
|
|
2293
|
+
pre_spd_enhance = (not export_16bit) and (bool(getattr(self, 'sonar_db_transform', False)) or bool(getattr(self, 'sonar_clahe', False)))
|
|
2294
|
+
self._doSpdCor(chunk, spdCor=spdCor, mask_shdw=mask_shdw, mask_wc=True, maxCrop=maxCrop, do_egn=self.egn, stretch_wcp=True, integer=not export_16bit, pre_spd_enhance=pre_spd_enhance)
|
|
2161
2295
|
|
|
2162
2296
|
if self.sonDat is not np.nan:
|
|
2163
|
-
self._writeTilesPlot(chunk, imgOutPrefix='wcm', tileFile=tileFile, colormap=True)
|
|
2297
|
+
self._writeTilesPlot(chunk, imgOutPrefix='wcm', tileFile=tileFile, colormap=True, apply_display_enhancement=not pre_spd_enhance)
|
|
2164
2298
|
else:
|
|
2165
2299
|
pass
|
|
2166
2300
|
|
|
2167
2301
|
if self.wcr_src:
|
|
2168
2302
|
# Do speed correction
|
|
2169
2303
|
export_16bit = bool(getattr(self, 'export_16bit', False)) and not bool(getattr(self, 'son8bit', False))
|
|
2170
|
-
|
|
2304
|
+
pre_spd_enhance = (not export_16bit) and (bool(getattr(self, 'sonar_db_transform', False)) or bool(getattr(self, 'sonar_clahe', False)))
|
|
2305
|
+
self._doSpdCor(chunk, spdCor=spdCor, mask_shdw=mask_shdw, src=True, maxCrop=maxCrop, do_egn=self.egn, stretch_wcp=True, integer=not export_16bit, pre_spd_enhance=pre_spd_enhance)
|
|
2171
2306
|
|
|
2172
2307
|
if self.sonDat is not np.nan:
|
|
2173
|
-
self._writeTilesPlot(chunk, imgOutPrefix='src', tileFile=tileFile, colormap=True)
|
|
2308
|
+
self._writeTilesPlot(chunk, imgOutPrefix='src', tileFile=tileFile, colormap=True, apply_display_enhancement=not pre_spd_enhance)
|
|
2174
2309
|
else:
|
|
2175
2310
|
pass
|
|
2176
2311
|
|
|
2177
2312
|
if self.wco:
|
|
2178
2313
|
# Do speed correction
|
|
2179
2314
|
export_16bit = bool(getattr(self, 'export_16bit', False)) and not bool(getattr(self, 'son8bit', False))
|
|
2180
|
-
|
|
2315
|
+
pre_spd_enhance = (not export_16bit) and (bool(getattr(self, 'sonar_db_transform', False)) or bool(getattr(self, 'sonar_clahe', False)))
|
|
2316
|
+
self._doSpdCor(chunk, spdCor=spdCor, mask_bed=True, maxCrop=maxCrop, do_egn=self.egn, stretch_wcp=True, integer=not export_16bit, pre_spd_enhance=pre_spd_enhance)
|
|
2181
2317
|
|
|
2182
2318
|
if self.sonDat is not np.nan:
|
|
2183
|
-
self._writeTilesPlot(chunk, imgOutPrefix='wco', tileFile=tileFile, colormap=True)
|
|
2319
|
+
self._writeTilesPlot(chunk, imgOutPrefix='wco', tileFile=tileFile, colormap=True, apply_display_enhancement=not pre_spd_enhance)
|
|
2184
2320
|
else:
|
|
2185
2321
|
pass
|
|
2186
2322
|
|
|
@@ -2200,7 +2336,8 @@ class sonObj(object):
|
|
|
2200
2336
|
son=True,
|
|
2201
2337
|
integer=True,
|
|
2202
2338
|
do_egn=False,
|
|
2203
|
-
stretch_wcp=False
|
|
2339
|
+
stretch_wcp=False,
|
|
2340
|
+
pre_spd_enhance=False):
|
|
2204
2341
|
|
|
2205
2342
|
if not hasattr(self, 'sonMetaDF'):
|
|
2206
2343
|
self._loadSonMeta()
|
|
@@ -2248,6 +2385,10 @@ class sonObj(object):
|
|
|
2248
2385
|
|
|
2249
2386
|
sonDat = self.sonDat
|
|
2250
2387
|
|
|
2388
|
+
if pre_spd_enhance and not export_16bit:
|
|
2389
|
+
sonDat = self._apply_display_enhancements(sonDat)
|
|
2390
|
+
self.sonDat = sonDat
|
|
2391
|
+
|
|
2251
2392
|
if spdCor == 0:
|
|
2252
2393
|
# Don't do speed correction
|
|
2253
2394
|
pass
|
|
@@ -2310,7 +2451,12 @@ class sonObj(object):
|
|
|
2310
2451
|
clip=False, preserve_range=True)#.astype('uint8')
|
|
2311
2452
|
|
|
2312
2453
|
if integer:
|
|
2313
|
-
|
|
2454
|
+
if pre_spd_enhance and np.issubdtype(np.asarray(sonDat).dtype, np.floating):
|
|
2455
|
+
# CLAHE outputs 0..1 floats; convert with robust scaling so
|
|
2456
|
+
# display-enhanced data does not collapse to near-black.
|
|
2457
|
+
self.sonDat = self._convert_son_dat_to_uint8(sonDat)
|
|
2458
|
+
else:
|
|
2459
|
+
self.sonDat = sonDat.astype('uint8')
|
|
2314
2460
|
else:
|
|
2315
2461
|
self.sonDat = sonDat
|
|
2316
2462
|
|
|
@@ -2413,6 +2559,12 @@ class sonObj(object):
|
|
|
2413
2559
|
self._use_jsf_weighting = True
|
|
2414
2560
|
self._ensure_jsf_global_scale_max(sonMetaAll)
|
|
2415
2561
|
|
|
2562
|
+
self._use_cerulean_power_scale = False
|
|
2563
|
+
if 'min_pwr_db' in sonMeta.columns and 'max_pwr_db' in sonMeta.columns:
|
|
2564
|
+
self.minPwrDb = pd.to_numeric(sonMeta['min_pwr_db'], errors='coerce').to_numpy(dtype=float)
|
|
2565
|
+
self.maxPwrDb = pd.to_numeric(sonMeta['max_pwr_db'], errors='coerce').to_numpy(dtype=float)
|
|
2566
|
+
self._use_cerulean_power_scale = True
|
|
2567
|
+
|
|
2416
2568
|
# Load chunk's sonar data into memory
|
|
2417
2569
|
self._loadSonChunk()
|
|
2418
2570
|
# Do PPDRC filter
|
|
@@ -2427,7 +2579,12 @@ class sonObj(object):
|
|
|
2427
2579
|
del self.bytesPerSample
|
|
2428
2580
|
if hasattr(self, 'weightingFactor'):
|
|
2429
2581
|
del self.weightingFactor
|
|
2582
|
+
if hasattr(self, 'minPwrDb'):
|
|
2583
|
+
del self.minPwrDb
|
|
2584
|
+
if hasattr(self, 'maxPwrDb'):
|
|
2585
|
+
del self.maxPwrDb
|
|
2430
2586
|
self._use_jsf_weighting = False
|
|
2587
|
+
self._use_cerulean_power_scale = False
|
|
2431
2588
|
|
|
2432
2589
|
return
|
|
2433
2590
|
|
|
@@ -2477,6 +2634,12 @@ class sonObj(object):
|
|
|
2477
2634
|
self._use_jsf_weighting = True
|
|
2478
2635
|
self._ensure_jsf_global_scale_max(sonMetaAll_full)
|
|
2479
2636
|
|
|
2637
|
+
self._use_cerulean_power_scale = False
|
|
2638
|
+
if 'min_pwr_db' in sonMeta.columns and 'max_pwr_db' in sonMeta.columns:
|
|
2639
|
+
self.minPwrDb = pd.to_numeric(sonMeta['min_pwr_db'], errors='coerce').to_numpy(dtype=float)
|
|
2640
|
+
self.maxPwrDb = pd.to_numeric(sonMeta['max_pwr_db'], errors='coerce').to_numpy(dtype=float)
|
|
2641
|
+
self._use_cerulean_power_scale = True
|
|
2642
|
+
|
|
2480
2643
|
# Load chunk's sonar data into memory
|
|
2481
2644
|
self._loadSonChunk()
|
|
2482
2645
|
|
|
@@ -2489,7 +2652,12 @@ class sonObj(object):
|
|
|
2489
2652
|
del self.bytesPerSample
|
|
2490
2653
|
if hasattr(self, 'weightingFactor'):
|
|
2491
2654
|
del self.weightingFactor
|
|
2655
|
+
if hasattr(self, 'minPwrDb'):
|
|
2656
|
+
del self.minPwrDb
|
|
2657
|
+
if hasattr(self, 'maxPwrDb'):
|
|
2658
|
+
del self.maxPwrDb
|
|
2492
2659
|
self._use_jsf_weighting = False
|
|
2660
|
+
self._use_cerulean_power_scale = False
|
|
2493
2661
|
|
|
2494
2662
|
return
|
|
2495
2663
|
|
|
@@ -686,10 +686,34 @@ class sonObj(object):
|
|
|
686
686
|
else:
|
|
687
687
|
time_table = pd.read_csv(time_table)
|
|
688
688
|
|
|
689
|
+
if 'start_seconds' not in time_table.columns or 'end_seconds' not in time_table.columns:
|
|
690
|
+
raise ValueError("time_table must contain 'start_seconds' and 'end_seconds' columns.")
|
|
691
|
+
|
|
692
|
+
# Normalize to numeric and drop unusable rows.
|
|
693
|
+
time_table['start_seconds'] = pd.to_numeric(time_table['start_seconds'], errors='coerce')
|
|
694
|
+
time_table['end_seconds'] = pd.to_numeric(time_table['end_seconds'], errors='coerce')
|
|
695
|
+
time_table = time_table.dropna(subset=['start_seconds', 'end_seconds'])
|
|
696
|
+
|
|
697
|
+
if time_table.empty:
|
|
698
|
+
return sonDF
|
|
699
|
+
|
|
700
|
+
son_time = pd.to_numeric(sonDF[time_col], errors='coerce')
|
|
701
|
+
son_min = son_time.min()
|
|
702
|
+
|
|
703
|
+
# Auto-detect relative clip ranges when sonar time is epoch-like and
|
|
704
|
+
# clip-table values are small. This allows 0..N seconds-from-start.
|
|
705
|
+
tt_max = np.nanmax(np.abs(time_table[['start_seconds', 'end_seconds']].to_numpy(dtype=float)))
|
|
706
|
+
use_relative_seconds = np.isfinite(son_min) and son_min > 1e8 and np.isfinite(tt_max) and tt_max < 1e7
|
|
707
|
+
|
|
708
|
+
offset = float(son_min) if use_relative_seconds else 0.0
|
|
709
|
+
|
|
689
710
|
for i, row in time_table.iterrows():
|
|
690
711
|
|
|
691
|
-
start = row['start_seconds']
|
|
692
|
-
end = row['end_seconds']
|
|
712
|
+
start = float(row['start_seconds']) + offset
|
|
713
|
+
end = float(row['end_seconds']) + offset
|
|
714
|
+
|
|
715
|
+
if end < start:
|
|
716
|
+
start, end = end, start
|
|
693
717
|
|
|
694
718
|
# dfFilt = sonDF[(sonDF['time_s'] >= start) & (sonDF['time_s'] <= end)]
|
|
695
719
|
sonDF.loc[(sonDF[time_col] >= start) & (sonDF[time_col] <= end) & (sonDF[filtCol] == True), filtTimeCol] = True
|
|
@@ -1500,7 +1524,7 @@ class sonObj(object):
|
|
|
1500
1524
|
# plt.savefig(outfile)
|
|
1501
1525
|
|
|
1502
1526
|
norm_data = data / 255.0
|
|
1503
|
-
colored_data = plt.
|
|
1527
|
+
colored_data = plt.get_cmap(self.sonogram_colorMap)(norm_data)
|
|
1504
1528
|
colored_data = (colored_data[:, :, :3] * 255).astype('uint8')
|
|
1505
1529
|
data = colored_data
|
|
1506
1530
|
|
|
@@ -207,7 +207,7 @@ def gui(batch: bool):
|
|
|
207
207
|
tip_speed_min = ml_tip('Minimum vessel speed filter in m/s. 0=no minimum speed filter.')
|
|
208
208
|
tip_speed_max = ml_tip('Maximum vessel speed filter in m/s. 0=no maximum speed filter.')
|
|
209
209
|
tip_aoi = ml_tip('Optional polygon shapefile (.shp) to spatially filter sonar records to area of interest.')
|
|
210
|
-
tip_time_filter = ml_tip('
|
|
210
|
+
tip_time_filter = ml_tip('Filter by start/end time ranges. Use either relative seconds from recording start (e.g., 0-2000) or absolute Unix seconds.')
|
|
211
211
|
# Cropping
|
|
212
212
|
text_crop = sg.Text('Crop Range [m]', size=(22,1))
|
|
213
213
|
in_crop = sg.Input(key='cropRange', default_text=default_params['cropRange'], size=(10,1), tooltip=tip_crop)
|
|
@@ -280,6 +280,9 @@ def gui(batch: bool):
|
|
|
280
280
|
tip_egn_factor = ml_tip('Percent clip amount used by EGN Stretch Factor when Percent Clip is selected.')
|
|
281
281
|
tip_gamma = ml_tip('Tone curve control. <1 brightens mid-tones, >1 darkens mid-tones.')
|
|
282
282
|
tip_gain = ml_tip('Linear brightness multiplier. >1 brightens overall intensity, <1 darkens.')
|
|
283
|
+
tip_db = ml_tip('Apply 20*log10 transform before final 8-bit mapping. Helps reveal low-amplitude detail.')
|
|
284
|
+
tip_clahe = ml_tip('Apply adaptive histogram equalization (CLAHE) after dB transform for local contrast boost.')
|
|
285
|
+
tip_clahe_clip = ml_tip('CLAHE clip limit. Lower values are gentler; higher values increase local contrast.')
|
|
283
286
|
# EGN
|
|
284
287
|
check_egn = sg.Checkbox('Empiracal Gain Normalization (EGN)', key='egn', default=default_params['egn'], tooltip=tip_egn)
|
|
285
288
|
|
|
@@ -306,8 +309,36 @@ def gui(batch: bool):
|
|
|
306
309
|
default_value=float(default_params['tone_gain']),
|
|
307
310
|
tooltip=tip_gain,
|
|
308
311
|
)
|
|
312
|
+
check_sonar_db = sg.Checkbox(
|
|
313
|
+
'Display dB Transform',
|
|
314
|
+
key='sonar_db_transform',
|
|
315
|
+
default=default_params.get('sonar_db_transform', False),
|
|
316
|
+
tooltip=tip_db,
|
|
317
|
+
)
|
|
318
|
+
check_sonar_clahe = sg.Checkbox(
|
|
319
|
+
'Display CLAHE',
|
|
320
|
+
key='sonar_clahe',
|
|
321
|
+
default=default_params.get('sonar_clahe', False),
|
|
322
|
+
tooltip=tip_clahe,
|
|
323
|
+
)
|
|
324
|
+
text_clahe_clip = sg.Text('CLAHE Clip Limit', size=(20,1))
|
|
325
|
+
in_clahe_clip = sg.Input(
|
|
326
|
+
key='sonar_clahe_clip_limit',
|
|
327
|
+
default_text=default_params.get('sonar_clahe_clip_limit', 0.01),
|
|
328
|
+
size=(10,1),
|
|
329
|
+
tooltip=tip_clahe_clip,
|
|
330
|
+
)
|
|
309
331
|
|
|
310
|
-
col_egn_1 = sg.Column(
|
|
332
|
+
col_egn_1 = sg.Column(
|
|
333
|
+
[
|
|
334
|
+
[text_egn_gamma, slide_egn_gamma],
|
|
335
|
+
[text_egn_gain, slide_egn_gain],
|
|
336
|
+
[check_sonar_db],
|
|
337
|
+
[check_sonar_clahe],
|
|
338
|
+
[text_clahe_clip, in_clahe_clip],
|
|
339
|
+
],
|
|
340
|
+
pad=0,
|
|
341
|
+
)
|
|
311
342
|
col_egn_2 = sg.Column([[check_egn], [text_egn_stretch, combo_egn_stretch], [text_egn_factor, in_egn_factor]], pad=0)
|
|
312
343
|
# Add to layout
|
|
313
344
|
layout.append([sg.HorizontalSeparator()])
|
|
@@ -804,6 +835,9 @@ def gui(batch: bool):
|
|
|
804
835
|
'egn_stretch_factor':float(values['egn_stretch_factor']),
|
|
805
836
|
'tone_gamma':float(values['tone_gamma']),
|
|
806
837
|
'tone_gain':float(values['tone_gain']),
|
|
838
|
+
'sonar_db_transform':values['sonar_db_transform'],
|
|
839
|
+
'sonar_clahe':values['sonar_clahe'],
|
|
840
|
+
'sonar_clahe_clip_limit':float(values['sonar_clahe_clip_limit']),
|
|
807
841
|
'wcp':values['wcp'],
|
|
808
842
|
'wcm':values['wcm'],
|
|
809
843
|
'wcr':values['wcr'],
|
|
@@ -718,6 +718,9 @@ def read_master_func(logfilename='',
|
|
|
718
718
|
egn_stretch_factor=1,
|
|
719
719
|
tone_gamma=1.0,
|
|
720
720
|
tone_gain=1.0,
|
|
721
|
+
sonar_db_transform=False,
|
|
722
|
+
sonar_clahe=False,
|
|
723
|
+
sonar_clahe_clip_limit=0.01,
|
|
721
724
|
wcp=False,
|
|
722
725
|
wcm=False,
|
|
723
726
|
wcr=False,
|
|
@@ -1038,6 +1041,9 @@ def read_master_func(logfilename='',
|
|
|
1038
1041
|
son.son8bit = sonar_obj.son8bit
|
|
1039
1042
|
if hasattr(sonar_obj, 'sample_dtype'):
|
|
1040
1043
|
son.sample_dtype = sonar_obj.sample_dtype
|
|
1044
|
+
elif file_type == '.svlog':
|
|
1045
|
+
# Cerulean pwr_results are uint16 values in little-endian order.
|
|
1046
|
+
son.sample_dtype = '<u2'
|
|
1041
1047
|
if hasattr(sonar_obj, 'export_raw_16bit'):
|
|
1042
1048
|
son.export_raw_16bit = sonar_obj.export_raw_16bit
|
|
1043
1049
|
if hasattr(son, 'sample_dtype'):
|
|
@@ -1201,6 +1207,9 @@ def read_master_func(logfilename='',
|
|
|
1201
1207
|
son.cropRange = cropRange
|
|
1202
1208
|
son.tone_gamma = tone_gamma
|
|
1203
1209
|
son.tone_gain = tone_gain
|
|
1210
|
+
son.sonar_db_transform = bool(sonar_db_transform)
|
|
1211
|
+
son.sonar_clahe = bool(sonar_clahe)
|
|
1212
|
+
son.sonar_clahe_clip_limit = float(sonar_clahe_clip_limit)
|
|
1204
1213
|
# Do range crop, if necessary
|
|
1205
1214
|
if cropRange > 0.0:
|
|
1206
1215
|
if file_type == '.xtf' and _is_sidescan_beam(getattr(son, 'beamName', '')):
|
|
@@ -1394,6 +1403,9 @@ def read_master_func(logfilename='',
|
|
|
1394
1403
|
son.wcp = wcp
|
|
1395
1404
|
son.tone_gamma = tone_gamma
|
|
1396
1405
|
son.tone_gain = tone_gain
|
|
1406
|
+
son.sonar_db_transform = bool(sonar_db_transform)
|
|
1407
|
+
son.sonar_clahe = bool(sonar_clahe)
|
|
1408
|
+
son.sonar_clahe_clip_limit = float(sonar_clahe_clip_limit)
|
|
1397
1409
|
|
|
1398
1410
|
beam = son.beamName
|
|
1399
1411
|
if wcr:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '5.5.2'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pingmapper
|
|
3
|
-
Version: 5.5.
|
|
3
|
+
Version: 5.5.2
|
|
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.0'
|
|
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
|
|
File without changes
|
{pingmapper-5.5.0 → pingmapper-5.5.2}/pingmapper/utils/DRAFT_Workflows/avg_predictions_Mussel_WBL.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingmapper-5.5.0 → pingmapper-5.5.2}/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.5.0 → pingmapper-5.5.2}/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
|
|
File without changes
|