pingmapper 5.5.3__tar.gz → 5.5.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. {pingmapper-5.5.3 → pingmapper-5.5.5}/PKG-INFO +1 -1
  2. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/class_rectObj.py +58 -6
  3. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/class_sonObj.py +10 -0
  4. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/funcs_rectify.py +34 -0
  5. pingmapper-5.5.5/pingmapper/version.py +1 -0
  6. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper.egg-info/PKG-INFO +1 -1
  7. pingmapper-5.5.3/pingmapper/version.py +0 -1
  8. {pingmapper-5.5.3 → pingmapper-5.5.5}/LICENSE +0 -0
  9. {pingmapper-5.5.3 → pingmapper-5.5.5}/README.md +0 -0
  10. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/__init__.py +0 -0
  11. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/__main__.py +0 -0
  12. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/class_mapSubstrateObj.py +0 -0
  13. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/class_portstarObj.py +0 -0
  14. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/class_sonObj_nadirgaptest.py +0 -0
  15. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/default_params.json +0 -0
  16. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/doWork.py +0 -0
  17. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/funcs_common.py +0 -0
  18. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/funcs_model.py +0 -0
  19. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/gui_main.py +0 -0
  20. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/main_mapSubstrate.py +0 -0
  21. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/main_readFiles.py +0 -0
  22. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/main_rectify.py +0 -0
  23. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/nonGUI_batch_main.py +0 -0
  24. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/nonGui_main.py +0 -0
  25. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0926.py +0 -0
  26. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0929.py +0 -0
  27. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/scratch/funcs_pyhum_correct.py +0 -0
  28. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/scratch/main.py +0 -0
  29. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/scratch/main_batchDirectory.py +0 -0
  30. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/self_check.py +0 -0
  31. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/test_PINGMapper.py +0 -0
  32. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/test_cli_self_check.py +0 -0
  33. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/test_dq_filter.py +0 -0
  34. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/test_time.py +0 -0
  35. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/DRAFT_Workflows/avg_predictions_Mussel_WBL.py +0 -0
  36. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/DRAFT_Workflows/gen_centerline.py +0 -0
  37. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/DRAFT_Workflows/gen_centerline_from_bankline.py +0 -0
  38. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/DRAFT_Workflows/gen_centerline_trkpnts_fitspline_DRAFT.py +0 -0
  39. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/DRAFT_Workflows/testEXAMPLE_mosaic_logit.py +0 -0
  40. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/RawEGN_avg_predictions.py +0 -0
  41. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/00_substrate_logits_mosaic_transects.py +0 -0
  42. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/00_substrate_shps_mosaic_transects.py +0 -0
  43. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/01_gen_centerline_from_coverage.py +0 -0
  44. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/02_gen_summary_stamp_shps.py +0 -0
  45. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/03_gen_summary_shp.py +0 -0
  46. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/04_combine_summary_shp_csv.py +0 -0
  47. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/05_gen_summary_shp_plots.py +0 -0
  48. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/06_compare_raw-egn_volume.py +0 -0
  49. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/08_raw-egn_hardReacheFreq_hist.py +0 -0
  50. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/09_raw-egn_PatchSize_density.py +0 -0
  51. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/Substrate_Summaries/summarize_project_substrate.py +0 -0
  52. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/export_coverage.py +0 -0
  53. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper/utils/main_mosaic_transects.py +0 -0
  54. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper.egg-info/SOURCES.txt +0 -0
  55. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper.egg-info/dependency_links.txt +0 -0
  56. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper.egg-info/requires.txt +0 -0
  57. {pingmapper-5.5.3 → pingmapper-5.5.5}/pingmapper.egg-info/top_level.txt +0 -0
  58. {pingmapper-5.5.3 → pingmapper-5.5.5}/pyproject.toml +0 -0
  59. {pingmapper-5.5.3 → pingmapper-5.5.5}/setup.cfg +0 -0
  60. {pingmapper-5.5.3 → pingmapper-5.5.5}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pingmapper
3
- Version: 5.5.3
3
+ Version: 5.5.5
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
@@ -554,18 +554,22 @@ class rectObj(sonObj):
554
554
  fb[lats] = fb[ylat]
555
555
 
556
556
  if es not in fb.columns:
557
- if xutm in fb.columns:
558
- fb[es] = fb[xutm]
559
- elif lons in fb.columns and lats in fb.columns:
557
+ if lons in fb.columns and lats in fb.columns:
558
+ # Prefer projecting lon/lat through self.trans (the correct
559
+ # target EPSG) rather than reusing a raw xutm column, which
560
+ # may hold a different (e.g. Humminbird-internal Web Mercator)
561
+ # coordinate system and silently corrupt downstream geometry.
560
562
  e_fb, _ = self.trans(fb[lons].to_numpy(), fb[lats].to_numpy())
561
563
  fb[es] = e_fb
564
+ elif xutm in fb.columns:
565
+ fb[es] = fb[xutm]
562
566
 
563
567
  if ns not in fb.columns:
564
- if yutm in fb.columns:
565
- fb[ns] = fb[yutm]
566
- elif lons in fb.columns and lats in fb.columns:
568
+ if lons in fb.columns and lats in fb.columns:
567
569
  _, n_fb = self.trans(fb[lons].to_numpy(), fb[lats].to_numpy())
568
570
  fb[ns] = n_fb
571
+ elif yutm in fb.columns:
572
+ fb[ns] = fb[yutm]
569
573
 
570
574
  if 'cog' not in fb.columns:
571
575
  if 'instr_heading' in fb.columns:
@@ -1099,6 +1103,26 @@ class rectObj(sonObj):
1099
1103
  else:
1100
1104
  continue
1101
1105
 
1106
+ # Guard against spline overshoot: the linear spline fit to range
1107
+ # extent coordinates can extrapolate far beyond the sonar's actual
1108
+ # range near gaps left by upstream filtering (time/speed/coord
1109
+ # outlier filters). Fall back to the geometrically-derived
1110
+ # (un-smoothed) range extent point for any ping whose smoothed
1111
+ # point lands unreasonably far from its trackline origin.
1112
+ if {'record_num', 'range_lon', 'range_lat', 'utm_es', 'utm_ns', 'range'}.issubset(schunkDF.columns):
1113
+ e_smth_chk, n_smth_chk = self.trans(smthChunk['range_lons'].to_numpy(), smthChunk['range_lats'].to_numpy())
1114
+ chk = schunkDF[['record_num', 'utm_es', 'utm_ns', 'range', 'range_lon', 'range_lat']].set_index('record_num')
1115
+ chk = chk.reindex(smthChunk['record_num'].to_numpy())
1116
+
1117
+ dist = np.hypot(e_smth_chk - chk['utm_es'].to_numpy(), n_smth_chk - chk['utm_ns'].to_numpy())
1118
+ max_expected = np.maximum(chk['range'].to_numpy(), 1.0) * 3.0 + 50.0
1119
+ bad = np.isfinite(dist) & (dist > max_expected)
1120
+ n_bad = int(np.sum(bad))
1121
+ if n_bad > 0:
1122
+ print(f"\n _interpRangeCoords: corrected {n_bad} spline-overshoot range extent point(s) in chunk {chunk}.")
1123
+ smthChunk.loc[bad, 'range_lons'] = chk['range_lon'].to_numpy()[bad]
1124
+ smthChunk.loc[bad, 'range_lats'] = chk['range_lat'].to_numpy()[bad]
1125
+
1102
1126
  rs_chunks.append(smthChunk.copy())
1103
1127
 
1104
1128
  ##################################################
@@ -3000,6 +3024,34 @@ class rectObj(sonObj):
3000
3024
  # Set output name
3001
3025
  f_out = f.replace('temp.tif', '.tif')
3002
3026
 
3027
+ # Sanity check the georeferenced extent before warping. A corrupt/outlier
3028
+ # coordinate upstream can produce a geotransform spanning thousands of km,
3029
+ # which causes gdal.Warp to attempt allocating a raster with an absurd
3030
+ # pixel count (surfacing as a misleading "free disk space" GDAL error).
3031
+ src = gdal.Open(f)
3032
+ if src is not None:
3033
+ gt = src.GetGeoTransform()
3034
+ width_m = abs(gt[1]) * src.RasterXSize
3035
+ height_m = abs(gt[5]) * src.RasterYSize
3036
+ src = None
3037
+
3038
+ est_cols = width_m / pix_res
3039
+ est_rows = height_m / pix_res
3040
+
3041
+ _MAX_PIXELS = 5e8 # ~500 million pixels safety cap
3042
+ if est_cols * est_rows > _MAX_PIXELS:
3043
+ print(
3044
+ f"\nWARNING: Skipping pixel resolution resize for {os.path.basename(f)}. "
3045
+ f"Georeferenced extent ({width_m:.1f} x {height_m:.1f} m) at {pix_res} m resolution "
3046
+ f"would require ~{est_cols*est_rows:,.0f} pixels. This indicates a corrupt or outlier "
3047
+ f"ping coordinate in this chunk. Keeping the un-resized GeoTiff instead."
3048
+ )
3049
+ try:
3050
+ os.rename(f, f_out)
3051
+ except OSError:
3052
+ pass
3053
+ return
3054
+
3003
3055
  # Reopen f and warp to pix_res
3004
3056
  t = gdal.Warp(f_out, f, xRes = pix_res, yRes = pix_res, targetAlignedPixels=True)
3005
3057
 
@@ -1356,6 +1356,16 @@ class sonObj(object):
1356
1356
  arr[~valid] = 0.0
1357
1357
  return arr
1358
1358
 
1359
+ def _normalize_with_bounds(self, data, lo, hi):
1360
+ arr = np.asarray(data, dtype=np.float32)
1361
+ arr[~np.isfinite(arr)] = 0.0
1362
+
1363
+ if (not np.isfinite(lo)) or (not np.isfinite(hi)) or hi <= lo:
1364
+ return np.clip(arr, 0.0, 1.0).astype(np.float32)
1365
+
1366
+ norm = (arr - float(lo)) / (float(hi) - float(lo))
1367
+ return np.clip(norm, 0.0, 1.0).astype(np.float32)
1368
+
1359
1369
  def _apply_display_db_transform(self, sonDat):
1360
1370
  arr = np.asarray(sonDat, dtype=np.float32)
1361
1371
  if arr.size == 0:
@@ -149,11 +149,44 @@ def smoothTrackline(projDir='', x_offset='', y_offset='', nchunk ='', cog=True,
149
149
  # filter = int(nchunk*0.1)
150
150
 
151
151
  # print('\n\n\ntransect:', name, 'filter:', filter)
152
+ # Snapshot raw coordinates before _interpTrack() may drop duplicates
153
+ # in-place, so we can validate/repair the smoothed output below.
154
+ raw_lon = group['lon'].copy()
155
+ raw_lat = group['lat'].copy()
156
+
152
157
  smoothed = son._interpTrack(df=group, dropDup=True, filt=filter, deg=3)
153
158
 
154
159
  # smooth trackline fit
155
160
  # if smoothed is not None:
156
161
  if len(smoothed.columns) > 4:
162
+ # Guard against cubic spline overshoot (Runge's phenomenon) across
163
+ # long or gappy transects (e.g. gaps left by time/speed/coord
164
+ # outlier filters). Fall back to the raw GPS fix for any ping
165
+ # whose smoothed position was displaced further than the
166
+ # transect's own spatial extent would allow.
167
+ raw_e, raw_n = son.trans(raw_lon.to_numpy(), raw_lat.to_numpy())
168
+ raw_e = pd.Series(raw_e, index=raw_lon.index).reindex(smoothed.index).to_numpy()
169
+ raw_n = pd.Series(raw_n, index=raw_lat.index).reindex(smoothed.index).to_numpy()
170
+
171
+ smth_e, smth_n = son.trans(smoothed['lons'].to_numpy(), smoothed['lats'].to_numpy())
172
+
173
+ dist = np.hypot(smth_e - raw_e, smth_n - raw_n)
174
+ span = np.hypot(np.nanmax(raw_e) - np.nanmin(raw_e), np.nanmax(raw_n) - np.nanmin(raw_n))
175
+ max_allowed = max(span, 50.0) * 2.0
176
+
177
+ bad = np.isfinite(dist) & (dist > max_allowed)
178
+ n_bad = int(np.sum(bad))
179
+ if n_bad > 0:
180
+ print(f"\n smoothTrackline: corrected {n_bad} spline-overshoot trackline point(s) in transect {name}.")
181
+ fix_lon = pd.Series(raw_lon.to_numpy(), index=raw_lon.index).reindex(smoothed.index).to_numpy()
182
+ fix_lat = pd.Series(raw_lat.to_numpy(), index=raw_lat.index).reindex(smoothed.index).to_numpy()
183
+ smoothed.loc[bad, 'lons'] = fix_lon[bad]
184
+ smoothed.loc[bad, 'lats'] = fix_lat[bad]
185
+ if 'utm_es' in smoothed.columns and 'utm_ns' in smoothed.columns:
186
+ e_fix, n_fix = son.trans(smoothed.loc[bad, 'lons'].to_numpy(), smoothed.loc[bad, 'lats'].to_numpy())
187
+ smoothed.loc[bad, 'utm_es'] = e_fix
188
+ smoothed.loc[bad, 'utm_ns'] = n_fix
189
+
157
190
  smoothed['transect'] = int(name)
158
191
  sDF = pd.concat([sDF, smoothed], ignore_index=False)
159
192
 
@@ -166,6 +199,7 @@ def smoothTrackline(projDir='', x_offset='', y_offset='', nchunk ='', cog=True,
166
199
 
167
200
  del smoothed
168
201
 
202
+
169
203
  # Save sonDF
170
204
  if len(transect_dropped) > 0:
171
205
 
@@ -0,0 +1 @@
1
+ __version__ = '5.5.5'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pingmapper
3
- Version: 5.5.3
3
+ Version: 5.5.5
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.3'
File without changes
File without changes
File without changes
File without changes
File without changes