From bf82cc1a0ef33d07fe5cf1e6477dc1a05a99c5bb Mon Sep 17 00:00:00 2001 From: giumas Date: Sun, 28 Jul 2024 22:06:28 +0200 Subject: [PATCH] added support for EPSG SRS --- examples/bag_metadata_crs.py | 22 +++++++++ hyo2/bag/__init__.py | 2 +- hyo2/bag/bag.py | 2 +- hyo2/bag/meta.py | 88 ++++++++++++++++++++++++------------ 4 files changed, 82 insertions(+), 32 deletions(-) create mode 100644 examples/bag_metadata_crs.py diff --git a/examples/bag_metadata_crs.py b/examples/bag_metadata_crs.py new file mode 100644 index 0000000..b962461 --- /dev/null +++ b/examples/bag_metadata_crs.py @@ -0,0 +1,22 @@ +import os +import logging + +from hyo2.abc2.lib.logging import set_logging +from hyo2.bag.bag import BAGFile +from hyo2.bag.helper import Helper +from hyo2.bag.meta import Meta + +set_logging(ns_list=['hyo2.bag']) +logger = logging.getLogger(__name__) + +# file_bag_0 = os.path.join(Helper.samples_folder(), "bdb_01.bag") +file_bag_0 = r"D:\google_drive\_ccom\QC Tools\data\survey\BAG Checks\QC3_error\F00834_MB_VR_MLLW_2of2.bag" +if os.path.exists(file_bag_0): + logger.debug("- file_bag_0: %s" % file_bag_0) + +bag_0 = BAGFile(file_bag_0, mode='r') +logger.debug(bag_0) + +meta = Meta(bag_0.metadata()) + +logger.debug("crs: %s (%s)" % (meta.wkt_srs, type(meta.wkt_srs))) diff --git a/hyo2/bag/__init__.py b/hyo2/bag/__init__.py index eba1062..e815338 100644 --- a/hyo2/bag/__init__.py +++ b/hyo2/bag/__init__.py @@ -4,7 +4,7 @@ """ name = 'BAG' -__version__ = '1.2.7' +__version__ = '1.2.8' __author__ = 'gmasetti@ccom.unh.edu' __license__ = 'LGPLv3 license' __copyright__ = 'Copyright (c) 2024, University of New Hampshire, Center for Coastal and Ocean Mapping' diff --git a/hyo2/bag/bag.py b/hyo2/bag/bag.py index f1c5b38..aa79a70 100644 --- a/hyo2/bag/bag.py +++ b/hyo2/bag/bag.py @@ -707,7 +707,7 @@ def has_valid_col_in_tracking_list(self): return True - def metadata(self, as_string=True, as_pretty_xml=True): + def metadata(self, as_string: bool = True, as_pretty_xml: bool = True) -> bytes | str: """ Return the metadata as_string diff --git a/hyo2/bag/meta.py b/hyo2/bag/meta.py index 4b9b13d..843278e 100644 --- a/hyo2/bag/meta.py +++ b/hyo2/bag/meta.py @@ -1,5 +1,8 @@ import logging +import dateutil.parser from lxml import etree +from osgeo import osr +from hyo2.abc2.lib.gdal_aux import GdalAux from hyo2.bag.helper import Helper logger = logging.getLogger(__name__) @@ -23,39 +26,41 @@ class Meta: 'smXML': 'http://metadata.dgiwg.org/smXML', } - def __init__(self, meta_xml): + def __init__(self, meta_xml: bytes | str) -> None: + GdalAux.push_gdal_error_handler() + self.xml_tree = etree.fromstring(meta_xml) # rows and cols - self.rows = None - self.cols = None + self.rows: int | None = None + self.cols: int | None = None self._read_rows_and_cols() # resolution along x and y axes - self.res_x = None - self.res_y = None + self.res_x: float | None = None + self.res_y: float | None = None self._read_res_x_and_y() # corner SW and NE - self.sw = None - self.ne = None + self.sw: float | None = None + self.ne: float | None = None self._read_corners_sw_and_ne() # wkt projection - self.wkt_srs = None - self.xml_srs = None + self.wkt_srs: str | None = None + self.xml_srs: str | None = None self._read_wkt_prj() # wkt vertical datum - self.wkt_vertical_datum = None - self.xml_vertical_datum = None + self.wkt_vertical_datum: str | None = None + self.xml_vertical_datum: str | None = None self._read_wkt_vertical_datum() # bbox - self.lon_min = None - self.lon_max = None - self.lat_min = None - self.lat_max = None + self.lon_min: float | None = None + self.lon_max: float | None = None + self.lat_min: float | None = None + self.lat_max: float | None = None self._read_bbox() # abstract @@ -78,7 +83,7 @@ def __init__(self, meta_xml): # uncertainty type self.sec_constr = None - self._read_security_contraints() + self._read_security_constraints() def __str__(self): output = "" @@ -125,8 +130,8 @@ def geo_extent(self): def wkt_bbox(self): return "LINESTRING Z(%.6f %.6f 0, %.6f %.6f 0, %.6f %.6f 0, %.6f %.6f 0, %.6f %.6f 0)" \ - % (self.lon_min, self.lat_min, self.lon_min, self.lat_max, self.lon_max, self.lat_max, self.lon_max, self.lat_min, - self.lon_min, self.lat_min) + % (self.lon_min, self.lat_min, self.lon_min, self.lat_max, self.lon_max, self.lat_max, self.lon_max, + self.lat_min, self.lon_min, self.lat_min) def _read_rows_and_cols(self): """ attempts to read rows and cols info """ @@ -237,7 +242,18 @@ def _read_wkt_prj(self): return try: - self.wkt_srs = ret[0].text + space = self.xml_tree.xpath( + '//*/gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/' + 'gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:codeSpace/gco:CharacterString', + namespaces=self.ns) + # logger.info("codeSpace: %s" % space[0].text) + + if space[0].text == "EPSG": + sr = osr.SpatialReference() + sr.ImportFromEPSG(int(ret[0].text)) + self.wkt_srs = sr.ExportToWkt() + else: + self.wkt_srs = ret[0].text except (ValueError, IndexError) as e: logger.warning("unable to read the WKT projection string: %s" % e) @@ -269,7 +285,18 @@ def _read_wkt_vertical_datum(self): return try: - self.wkt_vertical_datum = ret[1].text + space = self.xml_tree.xpath( + '//*/gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/' + 'gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:codeSpace/gco:CharacterString', + namespaces=self.ns) + # logger.info("codeSpace: %s" % space[0].text) + + if space[1].text == "EPSG": + sr = osr.SpatialReference() + sr.ImportFromEPSG(int(ret[1].text)) + self.wkt_vertical_datum = sr.ExportToWkt() + else: + self.wkt_vertical_datum = ret[1].text except (ValueError, IndexError) as e: logger.warning("unable to read the WKT vertical datum string: %s" % e) @@ -381,12 +408,12 @@ def _read_date(self): return tm_date = None + # noinspection PyBroadException try: - import dateutil.parser parsed_date = dateutil.parser.parse(text_date) tm_date = parsed_date.strftime('%Y-%m-%dT%H:%M:%SZ') - except Exception: - logger.warning("unable to handle the date string: %s" % text_date) + except Exception as e: + logger.warning("unable to handle the date string: %s (%s)" % (text_date, e), exc_info=True) if tm_date is None: self.date = text_date @@ -423,12 +450,13 @@ def _read_survey_start_date(self): return tm_begin_date = None + # noinspection PyBroadException try: - import dateutil.parser parsed_date = dateutil.parser.parse(text_begin_date) tm_begin_date = parsed_date.strftime('%Y-%m-%dT%H:%M:%SZ') - except Exception: - logger.warning("unable to handle the survey begin date string: %s" % text_begin_date) + except Exception as e: + logger.warning("unable to handle the survey begin date string: %s (%s)" % (text_begin_date, e), + exc_info=True) if tm_begin_date is None: self.survey_start_date = text_begin_date @@ -466,12 +494,12 @@ def _read_survey_end_date(self): return tm_end_date = None + # noinspection PyBroadException try: - import dateutil.parser parsed_date = dateutil.parser.parse(text_end_date) tm_end_date = parsed_date.strftime('%Y-%m-%dT%H:%M:%SZ') - except Exception: - logger.warning("unable to handle the survey end date string: %s" % text_end_date) + except Exception as e: + logger.warning("unable to handle the survey end date string: %s (%s)" % (text_end_date, e), exc_info=True) if tm_end_date is None: self.survey_end_date = text_end_date @@ -510,7 +538,7 @@ def _read_uncertainty_type(self): logger.warning("unable to read the uncertainty type attribute: %s" % e) return - def _read_security_contraints(self): + def _read_security_constraints(self): """ attempts to read the uncertainty type """ old_format = False