/usr/lib/python3/dist-packages/hydroffice/bag/meta.py is in python3-hydroffice.bag 0.2.15-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | 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
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
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)
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
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
|