Skip to content

Commit e47150c

Browse files
committed
added method to identify grid cells with high uncertainty
1 parent 248f075 commit e47150c

6 files changed

+186
-4
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,6 @@ docs/_build/*
6262
# notebooks checkpoint
6363
*.ipynb_checkpoints
6464

65+
data/temp/
66+
data/download/
67+
data/output/

data/.gitkeep

Whitespace-only changes.
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import os
2+
import logging
3+
4+
from hyo2.abc2.lib.logging import set_logging
5+
from hyo2.abc2.lib.testing import Testing
6+
from hyo2.bag.bag import BAGFile
7+
from hyo2.bag.meta import Meta
8+
from hyo2.qc4.lib.common.writers.s57_writer import S57Writer
9+
10+
set_logging(ns_list=['hyo2.bag'])
11+
logger = logging.getLogger(__name__)
12+
13+
# file_bag_0 = os.path.join(Helper.samples_folder(), "bdb_01.bag")
14+
file_bag_0 = r"D:\google_drive\_ccom\QC Tools\data\survey\BAG Checks\H13275_MB_VR_MLLW.bag"
15+
th = 2.0
16+
17+
root_folder = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
18+
testing = Testing(root_folder=root_folder)
19+
20+
if os.path.exists(file_bag_0):
21+
logger.debug("- file_bag_0: %s" % file_bag_0)
22+
23+
bag_0 = BAGFile(file_bag_0, mode="r")
24+
logger.debug(bag_0)
25+
26+
meta = Meta(bag_0.metadata())
27+
28+
ret = bag_0.uncertainty_greater_than(th=th)
29+
logger.debug(ret)
30+
31+
s57_bn_path = os.path.join(testing.output_data_folder(), "%s.blue_notes.000" % os.path.basename(file_bag_0))
32+
s57_ss_path = os.path.join(testing.output_data_folder(), "%s.soundings.000" % os.path.basename(file_bag_0))
33+
34+
flags_for_blue_notes = list()
35+
for entry in ret:
36+
flags_for_blue_notes.append([entry[0], entry[1], "%.2f" % entry[2]])
37+
S57Writer.write_bluenotes(feature_list=flags_for_blue_notes, path=s57_bn_path, list_of_list=False)
38+
S57Writer.write_soundings(feature_list=ret, path=s57_ss_path, list_of_list=False)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import os
2+
import logging
3+
4+
from hyo2.abc2.lib.logging import set_logging
5+
from hyo2.abc2.lib.testing import Testing
6+
from hyo2.bag.bag import BAGFile
7+
from hyo2.bag.meta import Meta
8+
from hyo2.qc4.lib.common.writers.s57_writer import S57Writer
9+
10+
set_logging(ns_list=['hyo2.bag'])
11+
logger = logging.getLogger(__name__)
12+
13+
# file_bag_0 = os.path.join(Helper.samples_folder(), "bdb_01.bag")
14+
file_bag_0 = r"D:\google_drive\_ccom\QC Tools\data\survey\BAG Checks\H13275_MB_VR_MLLW.bag"
15+
th = 2.0
16+
17+
root_folder = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
18+
testing = Testing(root_folder=root_folder)
19+
20+
if os.path.exists(file_bag_0):
21+
logger.debug("- file_bag_0: %s" % file_bag_0)
22+
23+
bag_0 = BAGFile(file_bag_0, mode="r")
24+
logger.debug(bag_0)
25+
26+
meta = Meta(bag_0.metadata())
27+
28+
ret = bag_0.vr_uncertainty_greater_than(th=th)
29+
logger.debug(ret)
30+
31+
s57_bn_path = os.path.join(testing.output_data_folder(), "%s.blue_notes.000" % os.path.basename(file_bag_0))
32+
s57_ss_path = os.path.join(testing.output_data_folder(), "%s.soundings.000" % os.path.basename(file_bag_0))
33+
34+
flags_for_blue_notes = list()
35+
for entry in ret:
36+
flags_for_blue_notes.append([entry[0], entry[1], "%.2f" % entry[2]])
37+
S57Writer.write_bluenotes(feature_list=flags_for_blue_notes, path=s57_bn_path, list_of_list=False)
38+
S57Writer.write_soundings(feature_list=ret, path=s57_ss_path, list_of_list=False)

hyo2/bag/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55

66
name = 'BAG'
7-
__version__ = '1.2.5'
7+
__version__ = '1.2.6'
88
__author__ = '[email protected]'
99
__license__ = 'LGPLv3 license'
1010
__copyright__ = 'Copyright (c) 2024, University of New Hampshire, Center for Coastal and Ocean Mapping'

hyo2/bag/bag.py

+106-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
from typing import Tuple
44

5+
from osgeo import osr
56
import numpy as np
67
from lxml import etree, isoschematron
78

@@ -86,7 +87,7 @@ def create_template(cls, name):
8687
elevation.attrs.create(cls._bag_elevation_min_ev, 0.0, shape=(), dtype=np.float32)
8788
elevation.attrs.create(cls._bag_elevation_max_ev, 0.0, shape=(), dtype=np.float32)
8889

89-
new_bag.create_dataset(cls._bag_metadata, shape=(1, ), dtype="S1")
90+
new_bag.create_dataset(cls._bag_metadata, shape=(1,), dtype="S1")
9091

9192
tracking_list = new_bag.create_dataset(cls._bag_tracking_list, shape=(), dtype=cls._bag_tracking_list_type)
9293
tracking_list.attrs.create(cls._bag_tracking_list_len, 0, shape=(), dtype=np.uint32)
@@ -281,6 +282,51 @@ def uncertainty_min_max(self) -> Tuple[float, float]:
281282

282283
return unc_min, unc_max
283284

285+
def uncertainty_greater_than(self, th: float) -> list[list[int | float]]:
286+
rows, cols = self.uncertainty_shape()
287+
# logger.debug('shape: %s, %s' % (rows, cols))
288+
289+
self.populate_metadata()
290+
291+
x_min = self.meta.sw[0]
292+
y_min = self.meta.sw[1]
293+
x_res = self.meta.res_x
294+
y_res = self.meta.res_y
295+
logger.debug("info: %f %f %f %f" % (x_min, y_min, x_res, y_res))
296+
297+
in_srs = osr.SpatialReference()
298+
in_srs.ImportFromWkt(self.meta.wkt_srs)
299+
out_srs = osr.SpatialReference()
300+
out_srs.ImportFromEPSG(4326)
301+
ctr = osr.CoordinateTransformation(in_srs, out_srs)
302+
303+
mem_row = cols * 32 / 1024 / 1024
304+
# mem = mem_row * rows
305+
# logger.debug('estimated memory: %.1f MB' % mem)
306+
chunk_size = 8096
307+
chunk_rows = int(chunk_size / mem_row) + 1
308+
# logger.debug('nr of rows per chunk: %s' % chunk_rows)
309+
310+
xyz = list()
311+
for start in range(0, rows, chunk_rows):
312+
stop = start + chunk_rows
313+
if stop > rows:
314+
stop = rows
315+
316+
unc = self.uncertainty(row_range=slice(start, stop))
317+
ijs = np.argwhere(unc > th)
318+
for ij in ijs:
319+
i = ij[0]
320+
j = ij[1]
321+
e = x_min + j * x_res
322+
n = y_min + i * y_res
323+
lon, lat, _ = ctr.TransformPoint(e, n)
324+
u = float(unc[i, j])
325+
xyz.append([float(lat), float(lon), u])
326+
# logger.info("%s" % (xyz[-1]))
327+
328+
return xyz
329+
284330
def vr_uncertainty_min_max(self) -> Tuple[float, float]:
285331
# rows, cols = self.vr_refinements_shape()
286332
# logger.debug('shape: %s, %s' % (rows, cols))
@@ -293,7 +339,64 @@ def vr_uncertainty_min_max(self) -> Tuple[float, float]:
293339

294340
return np.nanmin(vr_unc), np.nanmax(vr_unc)
295341

342+
def vr_uncertainty_greater_than(self, th: float) -> list[list[int | float]]:
343+
# rows, cols = self.vr_refinements_shape()
344+
# logger.debug('shape: %s, %s' % (rows, cols))
345+
346+
self.populate_metadata()
347+
348+
x_min = self.meta.sw[0]
349+
y_min = self.meta.sw[1]
350+
x_res = self.meta.res_x
351+
y_res = self.meta.res_y
352+
logger.debug("info: %f %f %f %f" % (x_min, y_min, x_res, y_res))
353+
354+
in_srs = osr.SpatialReference()
355+
in_srs.ImportFromWkt(self.meta.wkt_srs)
356+
out_srs = osr.SpatialReference()
357+
out_srs.ImportFromEPSG(4326)
358+
ctr = osr.CoordinateTransformation(in_srs, out_srs)
359+
360+
vr_unc = self[BAGFile._bag_varres_refinements][0]['depth_uncrt']
361+
mask = vr_unc == BAGFile.BAG_NAN
362+
vr_unc[mask] = np.nan
363+
364+
xyz_dict = dict()
365+
for idx, unc in enumerate(vr_unc):
366+
if unc > th:
367+
xyz_dict[idx] = unc
368+
369+
logger.info("Located %d outliers" % len(xyz_dict))
370+
371+
xyz = list()
372+
vr_ixs = self[BAGFile._bag_varres_metadata][:]
373+
rows, cols = vr_ixs.shape
374+
i = 0
375+
for sg_r in range(rows):
376+
for sg_c in range(cols):
377+
if vr_ixs[sg_r, sg_c][1] == 0:
378+
continue
379+
ir = vr_ixs[sg_r, sg_c][1] * vr_ixs[sg_r, sg_c][2]
380+
for ir_idx in range(ir):
381+
j = i + ir_idx
382+
if j not in xyz_dict:
383+
continue
384+
unc = float(xyz_dict[j])
385+
logger.debug("Located outliers: %d %f in %d,%d: %s" % (j, unc, sg_r, sg_c, vr_ixs[sg_r, sg_c]))
386+
# vr_ixs[r, c]
387+
rfn_r = ir_idx // vr_ixs[sg_r, sg_c][1]
388+
rfn_c = ir_idx % vr_ixs[sg_r, sg_c][1]
389+
logger.debug("%d > %d,%d" % (ir_idx, rfn_r, rfn_c))
390+
e = x_min + (sg_c - 0.5) * x_res + vr_ixs[sg_r, sg_c][5] + rfn_c * vr_ixs[sg_r, sg_c][3]
391+
n = y_min + (sg_r - 0.5) * y_res + vr_ixs[sg_r, sg_c][6] + rfn_r * vr_ixs[sg_r, sg_c][4]
392+
lon, lat, _ = ctr.TransformPoint(e, n)
393+
xyz.append([float(lat), float(lon), unc])
394+
i += ir
395+
396+
return xyz
397+
296398
def has_density(self):
399+
# noinspection PyBroadException
297400
try:
298401
self[BAGFile._bag_elevation_solution]['num_soundings']
299402
except Exception:
@@ -437,7 +540,7 @@ def substitute_metadata(self, path):
437540

438541
del self[BAGFile._bag_metadata]
439542
xml_sz = len(xml_string)
440-
ds = self.create_dataset(self._bag_metadata, (xml_sz, ), dtype="S1")
543+
ds = self.create_dataset(self._bag_metadata, (xml_sz,), dtype="S1")
441544
for i, bt in enumerate(xml_string):
442545
ds[i] = bytes([bt])
443546

@@ -566,7 +669,7 @@ def modify_wkt_prj(self, wkt_hor, wkt_ver=None):
566669

567670
new_xml = etree.tostring(xml_tree, pretty_print=True)
568671
del self[BAGFile._bag_metadata]
569-
ds = self.create_dataset(BAGFile._bag_metadata, shape=(len(new_xml), ), dtype="S1")
672+
ds = self.create_dataset(BAGFile._bag_metadata, shape=(len(new_xml),), dtype="S1")
570673
for i, x in enumerate(new_xml):
571674
ds[i] = bytes([x])
572675

0 commit comments

Comments
 (0)