This document describes the HydrOffice BAG library and tools (0.2). For the source code, go here.

Source code for hydroffice.bag.meta

from __future__ import absolute_import, division, print_function  # , unicode_literals

import os
import sys
import logging
import numpy as np
import h5py
from lxml import etree

log = logging.getLogger(__name__)

from .helper import Helper


[docs]class Meta(object): """ Helper class to manage BAG xml metadata. """ ns = { 'bag': 'http://www.opennavsurf.org/schema/bag', 'gco': 'http://www.isotc211.org/2005/gco', 'gmd': 'http://www.isotc211.org/2005/gmd', 'gmi': 'http://www.isotc211.org/2005/gmi', 'gml': 'http://www.opengis.net/gml/3.2', 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', } def __init__(self, meta_xml): self.xml_tree = etree.fromstring(meta_xml) # rows and cols self.rows = None self.cols = None self._read_rows_and_cols() # resolution along x and y axes self.res_x = None self.res_y = None self._read_res_x_and_y() # corner SW and NE self.sw = None self.ne = None self._read_corners_sw_and_ne() # corner wkt projection self.wkt_srs = None self._read_wkt_prj() # bbox self.lon_min = None self.lon_max = None self.lat_min = None self.lat_max = None self._read_bbox() # abstract self.abstract = None self._read_abstract() # date self.date = None self._read_date() def __str__(self): output = "<metadata>" if (self.rows is not None) and (self.cols is not None): output += "\n <shape rows=%d, cols=%d>" % (self.rows, self.cols) if (self.res_x is not None) and (self.res_y is not None): output += "\n <resolution x=%f, y=%f>" % (self.res_x, self.res_y) if (self.sw is not None) and (self.ne is not None): output += "\n <corners SW=%s, NE=%s>" % (self.sw, self.ne) if self.wkt_srs is not None: output += "\n <projection=%s>" % Helper.elide(self.wkt_srs, max_len=60) if self.date is not None: output += "\n <date=%s>" % self.date if self.abstract is not None: output += "\n <abstract=%s>" % self.abstract output += "\n <bbox>" if (self.lon_min is not None) and (self.lon_max is not None): output += "\n <x min=%s, max=%s>" % (self.lon_min, self.lon_max) if (self.lat_min is not None) and (self.lat_max is not None): output += "\n <y min=%s, max=%s>" % (self.lat_min, self.lat_max) return output
[docs] def valid_bbox(self): return (self.lon_min is not None) and (self.lon_max is not None) and \ (self.lat_min is not None) and (self.lat_max is not None)
[docs] def geo_extent(self): """ Return the geographic extent as a tuple: (x_min, x_max, y_min, y_max) """ return self.lon_min, self.lon_max, self.lat_min, self.lat_max
[docs] 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)
def _read_rows_and_cols(self): """ attempts to read rows and cols info """ try: ret = self.xml_tree.xpath('//*/gmd:spatialRepresentationInfo/gmd:MD_Georectified/' 'gmd:axisDimensionProperties/gmd:MD_Dimension/gmd:dimensionSize/gco:Integer', namespaces=self.ns) except etree.Error as e: log.warning("unable to read rows and cols: %s" % e) return try: self.rows = int(ret[0].text) self.cols = int(ret[1].text) except (ValueError, IndexError) as e: log.warning("unable to read rows and cols: %s" % e) return def _read_res_x_and_y(self): """ attempts to read resolution along x- and y- axes """ try: ret = self.xml_tree.xpath('//*/gmd:spatialRepresentationInfo/gmd:MD_Georectified/' 'gmd:axisDimensionProperties/gmd:MD_Dimension/gmd:resolution/gco:Measure', namespaces=self.ns) except etree.Error as e: log.warning("unable to read res x and y: %s" % e) return try: self.res_x = float(ret[0].text) self.res_y = float(ret[1].text) except (ValueError, IndexError) as e: log.warning("unable to read res x and y: %s" % e) return def _read_corners_sw_and_ne(self): """ attempts to read corners SW and NE """ try: ret = self.xml_tree.xpath('//*/gmd:spatialRepresentationInfo/gmd:MD_Georectified/' 'gmd:cornerPoints/gml:Point/gml:coordinates', namespaces=self.ns)[0].text.split() except etree.Error as e: log.warning("unable to read corners SW and NE: %s" % e) return try: self.sw = [float(c) for c in ret[0].split(',')] self.ne = [float(c) for c in ret[1].split(',')] except (ValueError, IndexError) as e: log.warning("unable to read corners SW and NE: %s" % e) return def _read_wkt_prj(self): """ attempts to read the WKT projection string """ try: ret = self.xml_tree.xpath('//*/gmd:referenceSystemInfo/gmd:MD_ReferenceSystem/' 'gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:code/gco:CharacterString', namespaces=self.ns) except etree.Error as e: log.warning("unable to read the WKT projection string: %s" % e) return try: self.wkt_srs = ret[0].text except (ValueError, IndexError) as e: log.warning("unable to read the WKT projection string: %s" % e) return def _read_bbox(self): """ attempts to read the bounding box values """ try: ret_x_min = self.xml_tree.xpath('//*/gmd:EX_GeographicBoundingBox/gmd:westBoundLongitude/gco:Decimal', namespaces=self.ns) ret_x_max = self.xml_tree.xpath('//*/gmd:EX_GeographicBoundingBox/gmd:eastBoundLongitude/gco:Decimal', namespaces=self.ns) except etree.Error as e: log.warning("unable to read the bbox's longitude values: %s" % e) return try: self.lon_min = float(ret_x_min[0].text) self.lon_max = float(ret_x_max[0].text) except (ValueError, IndexError) as e: log.warning("unable to read the bbox's longitude values: %s" % e) return try: ret_y_min = self.xml_tree.xpath('//*/gmd:EX_GeographicBoundingBox/gmd:southBoundLatitude/gco:Decimal', namespaces=self.ns) ret_y_max = self.xml_tree.xpath('//*/gmd:EX_GeographicBoundingBox/gmd:northBoundLatitude/gco:Decimal', namespaces=self.ns) except etree.Error as e: log.warning("unable to read the bbox's latitude values: %s" % e) return try: self.lat_min = float(ret_y_min[0].text) self.lat_max = float(ret_y_max[0].text) except (ValueError, IndexError) as e: log.warning("unable to read the bbox's latitude values: %s" % e) return def _read_abstract(self): """ attempts to read the abstract string """ try: ret = self.xml_tree.xpath('//*/gmd:abstract/gco:CharacterString', namespaces=self.ns) except etree.Error as e: log.warning("unable to read the abstract string: %s" % e) return try: self.abstract = ret[0].text except (ValueError, IndexError) as e: log.warning("unable to read the abstract string: %s" % e) return def _read_date(self): """ attempts to read the date string """ try: ret = self.xml_tree.xpath('//*/gmd:CI_Date/gmd:date/gco:Date', namespaces=self.ns) except etree.Error as e: log.warning("unable to read the date string: %s" % e) return try: text_date = ret[0].text except (ValueError, IndexError) as e: log.warning("unable to read the date string: %s" % e) return tm_date = None try: import dateutil.parser parsed_date = dateutil.parser.parse(text_date) tm_date = parsed_date.strftime('%Y-%m-%dT%H:%M:%SZ') except Exception: log.warning("unable to handle the date string: %s" % text_date) if tm_date is None: self.date = text_date else: self.date = tm_date