Ejemplo n.º 1
0
    def getSRS(self,srsname,typename):
        """Returns None or Crs object for given name

        @param typename:  feature name 
        @type typename: String
        """
        if type(srsname) == type(""):
            srs = Crs(srsname)
        else:
            srs = srsname

        srss = [crs.getcodeurn() for crs in self.contents[typename].crsOptions]

        for s in srss:
            s = Crs(s)
            if srs.authority == s.authority and\
                    srs.code == s.code:
                if s.version and srs.version:
                    if s.version  == srs.version:
                        idx = srss.index(s.getcodeurn())
                        return self.contents[typename].crsOptions[idx]
                else:
                    idx = srss.index(s.getcodeurn())
                    return self.contents[typename].crsOptions[idx]
        return None
Ejemplo n.º 2
0
    def getSRS(self, srsname, typename):
        """Returns None or Crs object for given name

        @param typename:  feature name 
        @type typename: String
        """
        if not isinstance(srsname, Crs):
            srs = Crs(srsname)
        else:
            srs = srsname

        try:
            index = self.contents[typename].crsOptions.index(srs)
            # Return the Crs string that was pulled directly from the
            # GetCaps document (the 'id' attribute in the Crs object).
            return self.contents[typename].crsOptions[index]
        except ValueError:
            options = ", ".join(map(lambda x: x.id, self.contents[typename].crsOptions))
            log.warning("Requested srsName '%s' not available for requested typename '%s'. \
                         Options are: %s. " % (srs.getcode(), typename, options))
            return None
Ejemplo n.º 3
0
    def getSRS(self, srsname, typename):
        """Returns None or Crs object for given name
        """
        if type(srsname) == type(""):
            srs = Crs(srsname)
        else:
            srs = srsname

        srss = map(lambda crs: crs.getcodeurn(), self.contents[typename].crsOptions)

        for s in srss:
            s = Crs(s)
            if srs.authority == s.authority and srs.code == s.code:
                if s.version and srs.version:
                    if s.version == srs.version:
                        idx = srss.index(s.getcodeurn())
                        return self.contents[typename].crsOptions[idx]
                else:
                    idx = srss.index(s.getcodeurn())
                    return self.contents[typename].crsOptions[idx]
        return None
Ejemplo n.º 4
0
    def getBBOXKVP (self,bbox,typename):
        """Formate bounding box for KVP request type (HTTP GET)

        @param bbox: (minx,miny,maxx,maxy[,srs])
        @type bbox: List
        @param typename:  feature name 
        @type typename: String
        @returns: String properly formated according to version and
            coordinate reference system
        """
        srs = None

        # srs of the bbox is specified in the bbox as fifth paramter
        if len(bbox) == 5:
            srs = Crs(bbox[4])
        # take default srs
        else:
            srs = self.contents[typename[0]].crsOptions[0]

        # 1.1.0 and 2.0.0 have same encoding
        if self.version in ["1.1.0","2.0.0"]:

            # format bbox parameter
            if srs.encoding == "urn" :
                    if srs.axisorder == "yx":
                        return "%s,%s,%s,%s,%s" % \
                            (bbox[1],bbox[0],bbox[3],bbox[2],srs.getcodeurn())
                    else:
                        return "%s,%s,%s,%s,%s" % \
                        (bbox[0],bbox[1],bbox[2],bbox[3],srs.getcodeurn())
            else:
                return "%s,%s,%s,%s,%s" % \
                        (bbox[0],bbox[1],bbox[2],bbox[3],srs.getcode())
        # 1.0.0
        else:
            return "%s,%s,%s,%s,%s" % \
                    (bbox[0],bbox[1],bbox[2],bbox[3],srs.getcode())
Ejemplo n.º 5
0
    def __init__(self,
                 elem,
                 parse_remote_metadata=False,
                 timeout=30,
                 auth=None):
        """."""
        super(ContentMetadata, self).__init__(auth)
        self.id = testXMLValue(elem.find(nspath_eval("wfs:Name", namespaces)))
        self.title = testXMLValue(
            elem.find(nspath_eval("wfs:Title", namespaces)))
        self.abstract = testXMLValue(
            elem.find(nspath_eval("wfs:Abstract", namespaces)))
        self.keywords = [
            f.text for f in elem.findall(
                nspath_eval("ows:Keywords/ows:Keyword", namespaces))
        ]

        # bbox
        self.boundingBoxWGS84 = None
        b = BoundingBox(
            elem.find(nspath_eval("ows:WGS84BoundingBox", namespaces)),
            namespaces["ows"],
        )
        if b is not None:
            try:
                self.boundingBoxWGS84 = (
                    float(b.minx),
                    float(b.miny),
                    float(b.maxx),
                    float(b.maxy),
                )
            except TypeError:
                self.boundingBoxWGS84 = None
        # crs options
        self.crsOptions = [
            Crs(srs.text)
            for srs in elem.findall(nspath_eval("wfs:OtherSRS", namespaces))
        ]
        dsrs = testXMLValue(
            elem.find(nspath_eval("wfs:DefaultSRS", namespaces)))
        if dsrs is not None:  # first element is default srs
            self.crsOptions.insert(0, Crs(dsrs))

        # verbs
        self.verbOptions = [
            op.text for op in elem.findall(
                nspath_eval("wfs:Operations/wfs:Operation", namespaces))
        ]

        # output formats
        self.outputFormats = [
            op.text for op in elem.findall(
                nspath_eval("wfs:OutputFormats/wfs:Format", namespaces))
        ]

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall(nspath_eval("wfs:MetadataURL", namespaces)):
            metadataUrl = {
                "type": testXMLValue(m.attrib["type"], attrib=True),
                "format": testXMLValue(m.attrib["format"], attrib=True),
                "url": testXMLValue(m),
            }
            self.metadataUrls.append(metadataUrl)

        if parse_remote_metadata:
            self.parse_remote_metadata(timeout)

        # others not used but needed for iContentMetadata harmonisation
        self.styles = None
        self.timepositions = None
        self.defaulttimeposition = None
Ejemplo n.º 6
0
def get_srid(value):
    try:
        crs = Crs(value)
        return crs.code
    except Exception:
        return None
Ejemplo n.º 7
0
    def __init__(self, elem, parent, parse_remote_metadata=False, timeout=30):
        """."""
        self.id = elem.find(nspath('Name',ns=WFS_NAMESPACE)).text
        self.title = elem.find(nspath('Title',ns=WFS_NAMESPACE)).text
        abstract = elem.find(nspath('Abstract',ns=WFS_NAMESPACE))
        if abstract is not None:
            self.abstract = abstract.text
        else:
            self.abstract = None
        self.keywords = [f.text for f in elem.findall(nspath('Keywords',ns=WFS_NAMESPACE))]

        # bboxes
        self.boundingBoxWGS84 = None
        b = elem.find(nspath('WGS84BoundingBox',ns=OWS_NAMESPACE))
        if b is not None:
            lc = b.find(nspath("LowerCorner",ns=OWS_NAMESPACE))
            uc = b.find(nspath("UpperCorner",ns=OWS_NAMESPACE))
            ll = [float(s) for s in lc.text.split()]
            ur = [float(s) for s in uc.text.split()]
            self.boundingBoxWGS84 = (ll[0],ll[1],ur[0],ur[1])

        # there is no such think as bounding box
        # make copy of the WGS84BoundingBox
        self.boundingBox = (self.boundingBoxWGS84[0],
                            self.boundingBoxWGS84[1],
                            self.boundingBoxWGS84[2],
                            self.boundingBoxWGS84[3],
                            Crs("epsg:4326"))
        # crs options
        self.crsOptions = [Crs(srs.text) for srs in elem.findall(nspath('OtherCRS',ns=WFS_NAMESPACE))]
        defaultCrs =  elem.findall(nspath('DefaultCRS',ns=WFS_NAMESPACE))
        if len(defaultCrs) > 0:
            self.crsOptions.insert(0,Crs(defaultCrs[0].text))


        # verbs
        self.verbOptions = [op.tag for op \
            in parent.findall(nspath('Operations/*',ns=WFS_NAMESPACE))]
        self.verbOptions + [op.tag for op \
            in elem.findall(nspath('Operations/*',ns=WFS_NAMESPACE)) \
            if op.tag not in self.verbOptions]

        #others not used but needed for iContentMetadata harmonisation
        self.styles=None
        self.timepositions=None
        self.defaulttimeposition=None

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall('MetadataURL'):
            metadataUrl = {
                'type': testXMLValue(m.attrib['type'], attrib=True),
                'format': m.find('Format').text.strip(),
                'url': testXMLValue(m.find('OnlineResource').attrib['{http://www.w3.org/1999/xlink}href'], attrib=True)
            }

            if metadataUrl['url'] is not None and parse_remote_metadata:  # download URL
                try:
                    content = openURL(metadataUrl['url'], timeout=timeout)
                    doc = etree.parse(content)
                    try:  # FGDC
                        metadataUrl['metadata'] = Metadata(doc)
                    except:  # ISO
                        metadataUrl['metadata'] = MD_Metadata(doc)
                except Exception:
                    metadataUrl['metadata'] = None

            self.metadataUrls.append(metadataUrl)
Ejemplo n.º 8
0
    def __init__(self, elem, parse_remote_metadata=False):
        """."""
        self.id = testXMLValue(elem.find(nspath_eval('wfs:Name', namespaces)))
        self.title = testXMLValue(
            elem.find(nspath_eval('wfs:Title', namespaces)))
        self.abstract = testXMLValue(
            elem.find(nspath_eval('wfs:Abstract', namespaces)))
        self.keywords = [
            f.text for f in elem.findall(
                nspath_eval('ows:Keywords/ows:Keyword', namespaces))
        ]

        # bbox
        self.boundingBoxWGS84 = None
        b = BoundingBox(
            elem.find(nspath_eval('ows:WGS84BoundingBox', namespaces)),
            namespaces['ows'])
        if b is not None:
            self.boundingBoxWGS84 = (
                float(b.minx),
                float(b.miny),
                float(b.maxx),
                float(b.maxy),
            )
        # crs options
        self.crsOptions = [
            Crs(srs.text)
            for srs in elem.findall(nspath_eval('wfs:OtherSRS', namespaces))
        ]
        dsrs = testXMLValue(
            elem.find(nspath_eval('wfs:DefaultSRS', namespaces)))
        if dsrs is not None:  # first element is default srs
            self.crsOptions.insert(0, Crs(dsrs))

        # verbs
        self.verbOptions = [
            op.text for op in elem.findall(
                nspath_eval('wfs:Operations/wfs:Operation', namespaces))
        ]

        # output formats
        self.verbOptions = [
            op.text for op in elem.findall(
                nspath_eval('wfs:OutputFormats/wfs:Format', namespaces))
        ]

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall(nspath_eval('wfs:MetadataURL', namespaces)):
            metadataUrl = {
                'type': testXMLValue(m.attrib['type'], attrib=True),
                'format': testXMLValue(m.find('Format')),
                'url': testXMLValue(m)
            }

            if metadataUrl[
                    'url'] is not None and parse_remote_metadata:  # download URL
                try:
                    content = urlopen(metadataUrl['url'])
                    doc = etree.parse(content)
                    if metadataUrl['type'] is not None:
                        if metadataUrl['type'] == 'FGDC':
                            metadataUrl['metadata'] = Metadata(doc)
                        if metadataUrl['type'] in ['TC211', '19115', '19139']:
                            metadataUrl['metadata'] = MD_Metadata(doc)
                except Exception, err:
                    metadataUrl['metadata'] = None

            self.metadataUrls.append(metadataUrl)
Ejemplo n.º 9
0
    def __init__(self, elem, parent=None, children=None, index=0, parse_remote_metadata=False, timeout=30):
        if xmltag_split(elem.tag) != 'Layer':
            raise ValueError('%s should be a Layer' % (elem,))

        self.parent = parent
        if parent:
            self.index = "%s.%d" % (parent.index, index)
        else:
            self.index = str(index)

        self._children = children

        self.id = self.name = testXMLValue(elem.find(nspath('Name', WMS_NAMESPACE)))

        # layer attributes
        self.queryable = int(elem.attrib.get('queryable', 0))
        self.cascaded = int(elem.attrib.get('cascaded', 0))
        self.opaque = int(elem.attrib.get('opaque', 0))
        self.noSubsets = int(elem.attrib.get('noSubsets', 0))
        self.fixedWidth = int(elem.attrib.get('fixedWidth', 0))
        self.fixedHeight = int(elem.attrib.get('fixedHeight', 0))

        # title is mandatory property
        self.title = None
        title = testXMLValue(elem.find(nspath('Title', WMS_NAMESPACE)))
        if title is not None:
            self.title = title.strip()

        self.abstract = testXMLValue(elem.find(nspath('Abstract', WMS_NAMESPACE)))

        # TODO: what is the preferred response to esri's handling of custom projections
        #       in the spatial ref definitions? see http://resources.arcgis.com/en/help/main/10.1/index.html#//00sq000000m1000000
        #       and an example (20150812) http://maps.ngdc.noaa.gov/arcgis/services/firedetects/MapServer/WMSServer?request=GetCapabilities&service=WMS

        # bboxes
        b = elem.find(nspath('EX_GeographicBoundingBox', WMS_NAMESPACE))
        self.boundingBoxWGS84 = None
        if b is not None:
            minx = b.find(nspath('westBoundLongitude', WMS_NAMESPACE))
            miny = b.find(nspath('southBoundLatitude', WMS_NAMESPACE))
            maxx = b.find(nspath('eastBoundLongitude', WMS_NAMESPACE))
            maxy = b.find(nspath('northBoundLatitude', WMS_NAMESPACE))
            box = tuple(map(float, [minx.text if minx is not None else None,
                            miny.text if miny is not None else None,
                            maxx.text if maxx is not None else None,
                            maxy.text if maxy is not None else None]))

            self.boundingBoxWGS84 = tuple(box)
        elif self.parent:
            if hasattr(self.parent, 'boundingBoxWGS84'):
                self.boundingBoxWGS84 = self.parent.boundingBoxWGS84

        # make a bbox list (of tuples)
        crs_list = []
        for bb in elem.findall(nspath('BoundingBox', WMS_NAMESPACE)):
            srs_str = bb.attrib.get('CRS', None)
            srs = Crs(srs_str)

            box = tuple(map(float, [bb.attrib['minx'],
                        bb.attrib['miny'],
                        bb.attrib['maxx'],
                        bb.attrib['maxy']]
            ))
            minx, miny, maxx, maxy = box[0], box[1], box[2], box[3]

            # handle the ordering so that it always
            # returns (minx, miny, maxx, maxy)
            if srs and srs.axisorder == 'yx':
                # reverse things
                minx, miny, maxx, maxy = box[1], box[0], box[3], box[2]

            crs_list.append((
                minx, miny, maxx, maxy,
                srs_str,
            ))
        self.crs_list = crs_list
        # and maintain the original boundingBox attribute (first in list)
        # or the wgs84 bbox (to handle cases of incomplete parentage)
        self.boundingBox = crs_list[0] if crs_list else self.boundingBoxWGS84

        # ScaleHint
        sh = elem.find(nspath('ScaleHint', WMS_NAMESPACE))
        self.scaleHint = None
        if sh is not None:
            if 'min' in sh.attrib and 'max' in sh.attrib:
                self.scaleHint = {'min': sh.attrib['min'], 'max': sh.attrib['max']}

        attribution = elem.find(nspath('Attribution', WMS_NAMESPACE))
        if attribution is not None:
            self.attribution = dict()
            title = attribution.find(nspath('Title', WMS_NAMESPACE))
            url = attribution.find(nspath('OnlineResource', WMS_NAMESPACE))
            logo = attribution.find(nspath('LogoURL', WMS_NAMESPACE))
            if title is not None:
                self.attribution['title'] = title.text
            if url is not None:
                self.attribution['url'] = url.attrib['{http://www.w3.org/1999/xlink}href']
            if logo is not None:
                self.attribution['logo_size'] = (int(logo.attrib['width']), int(logo.attrib['height']))
                self.attribution['logo_url'] = logo.find(nspath('OnlineResource', WMS_NAMESPACE)).attrib['{http://www.w3.org/1999/xlink}href']

        # TODO: get this from the bbox attributes instead (deal with parents)
        # SRS options
        self.crsOptions = []

        # Copy any parent SRS options (they are inheritable properties)
        if self.parent:
            self.crsOptions = list(self.parent.crsOptions)

        # Look for SRS option attached to this layer
        if elem.find(nspath('CRS', WMS_NAMESPACE)) is not None:
            # some servers found in the wild use a single SRS
            # tag containing a whitespace separated list of SRIDs
            # instead of several SRS tags. hence the inner loop
            for srslist in map(lambda x: x.text, elem.findall(nspath('CRS', WMS_NAMESPACE))):
                if srslist:
                    for srs in srslist.split():
                        self.crsOptions.append(srs)

        # Get rid of duplicate entries
        self.crsOptions = list(set(self.crsOptions))

        # Set self.crsOptions to None if the layer (and parents) had no SRS options
        if len(self.crsOptions) == 0:
            # raise ValueError('%s no SRS available!?' % (elem,))
            # Comment by D Lowe.
            # Do not raise ValueError as it is possible that a layer is purely a parent layer and does not have SRS specified. Instead set crsOptions to None
            # Comment by Jachym:
            # Do not set it to None, but to [], which will make the code
            # work further. Fixed by anthonybaxter
            self.crsOptions = []

        # Styles
        self.styles = {}

        # Copy any parent styles (they are inheritable properties)
        if self.parent:
            self.styles = self.parent.styles.copy()

        # Get the styles for this layer (items with the same name are replaced)
        for s in elem.findall(nspath('Style', WMS_NAMESPACE)):
            name = s.find(nspath('Name', WMS_NAMESPACE))
            title = s.find(nspath('Title', WMS_NAMESPACE))
            if name is None or title is None:
                raise ValueError('%s missing name or title' % (s,))
            style = {'title': title.text}
            # legend url
            legend = s.find(nspath('LegendURL/OnlineResource', WMS_NAMESPACE))
            if legend is not None:
                style['legend'] = legend.attrib['{http://www.w3.org/1999/xlink}href']

            lgd = s.find(nspath('LegendURL', WMS_NAMESPACE))
            if lgd is not None:
                if 'width' in lgd.attrib.keys():
                    style['legend_width'] = lgd.attrib.get('width')
                if 'height' in lgd.attrib.keys():
                    style['legend_height'] = lgd.attrib.get('height')

                lgd_format = lgd.find(nspath('Format', WMS_NAMESPACE))
                if lgd_format is not None:
                    style['legend_format'] = lgd_format.text.strip()
            self.styles[name.text] = style

        # keywords
        self.keywords = [f.text for f in elem.findall(nspath('KeywordList/Keyword', WMS_NAMESPACE))]

        # extents replaced by dimensions of name
        # comment by Soren Scott
        # <Dimension name="elevation" units="meters" default="500" multipleValues="1"
        #    nearestValue="0" current="true" unitSymbol="m">500, 490, 480</Dimension>
        # it can be repeated with the same name so ? this assumes a single one to match 1.1.1

        self.timepositions = None
        self.defaulttimeposition = None
        time_dimension = None

        for dim in elem.findall(nspath('Dimension', WMS_NAMESPACE)):
            dim_name = dim.attrib.get('name')
            if dim_name is not None and dim_name.lower() == 'time':
                time_dimension = dim
        if time_dimension is not None:
            self.timepositions = time_dimension.text.split(',') if time_dimension.text else None
            self.defaulttimeposition = time_dimension.attrib.get('default', None)

        # Elevations - available vertical levels
        self.elevations = None
        elev_dimension = None
        for dim in elem.findall(nspath('Dimension', WMS_NAMESPACE)):
            if dim.attrib.get('name') == 'elevation':
                elev_dimension = dim
        if elev_dimension is not None:
            self.elevations = [e.strip() for e in elev_dimension.text.split(',')] if elev_dimension.text else None

        # and now capture the dimensions as more generic things (and custom things)
        self.dimensions = {}
        for dim in elem.findall(nspath('Dimension', WMS_NAMESPACE)):
            dim_name = dim.attrib.get('name')
            dim_data = {}
            for k, v in six.iteritems(dim.attrib):
                if k != 'name':
                    dim_data[k] = v
            # single values and ranges are not differentiated here
            dim_data['values'] = dim.text.strip().split(',') if dim.text.strip() else None
            self.dimensions[dim_name] = dim_data

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall(nspath('MetadataURL', WMS_NAMESPACE)):
            metadataUrl = {
                'type': testXMLValue(m.attrib['type'], attrib=True),
                'format': testXMLValue(m.find(nspath('Format', WMS_NAMESPACE))),
                'url': testXMLValue(m.find(nspath('OnlineResource', WMS_NAMESPACE)).attrib['{http://www.w3.org/1999/xlink}href'], attrib=True)
            }
            self.metadataUrls.append(metadataUrl)

        if parse_remote_metadata:
            self.parse_remote_metadata(timeout)

        # DataURLs
        self.dataUrls = []
        for m in elem.findall(nspath('DataURL', WMS_NAMESPACE)):
            dataUrl = {
                'format': m.find(nspath('Format', WMS_NAMESPACE)).text.strip(),
                'url': m.find(nspath('OnlineResource', WMS_NAMESPACE)).attrib['{http://www.w3.org/1999/xlink}href']
            }
            self.dataUrls.append(dataUrl)

        # FeatureListURLs
        self.featureListUrls = []
        for m in elem.findall(nspath('FeatureListURL', WMS_NAMESPACE)):
            featureUrl = {
                'format': m.find(nspath('Format', WMS_NAMESPACE)).text.strip(),
                'url': m.find(nspath('OnlineResource', WMS_NAMESPACE)).attrib['{http://www.w3.org/1999/xlink}href']
            }
            self.featureListUrls.append(featureUrl)

        self.layers = []
        for child in elem.findall(nspath('Layer', WMS_NAMESPACE)):
            self.layers.append(ContentMetadata(child, self))
Ejemplo n.º 10
0
    def __init__(self,
                 elem,
                 parent,
                 parse_remote_metadata=False,
                 timeout=30,
                 headers=None,
                 auth=None):
        """."""
        super(ContentMetadata, self).__init__(headers=headers, auth=auth)
        self.id = elem.find(nspath("Name", ns=WFS_NAMESPACE)).text
        self.title = elem.find(nspath("Title", ns=WFS_NAMESPACE)).text
        abstract = elem.find(nspath("Abstract", ns=WFS_NAMESPACE))
        if abstract is not None:
            self.abstract = abstract.text
        else:
            self.abstract = None
        self.keywords = [
            f.text for f in elem.findall(nspath("Keywords", ns=WFS_NAMESPACE))
        ]

        # bboxes
        self.boundingBoxWGS84 = None
        b = elem.find(nspath("WGS84BoundingBox", ns=OWS_NAMESPACE))
        if b is not None:
            try:
                lc = b.find(nspath("LowerCorner", ns=OWS_NAMESPACE))
                uc = b.find(nspath("UpperCorner", ns=OWS_NAMESPACE))
                ll = [float(s) for s in lc.text.split()]
                ur = [float(s) for s in uc.text.split()]
                self.boundingBoxWGS84 = (ll[0], ll[1], ur[0], ur[1])

                # there is no such think as bounding box
                # make copy of the WGS84BoundingBox
                self.boundingBox = (
                    self.boundingBoxWGS84[0],
                    self.boundingBoxWGS84[1],
                    self.boundingBoxWGS84[2],
                    self.boundingBoxWGS84[3],
                    Crs("epsg:4326"),
                )
            except AttributeError:
                self.boundingBoxWGS84 = None
        # crs options
        self.crsOptions = [
            Crs(srs.text)
            for srs in elem.findall(nspath("OtherCRS", ns=WFS_NAMESPACE))
        ]
        defaultCrs = elem.findall(nspath("DefaultCRS", ns=WFS_NAMESPACE))
        if len(defaultCrs) > 0:
            self.crsOptions.insert(0, Crs(defaultCrs[0].text))

        # verbs
        self.verbOptions = [
            op.tag
            for op in parent.findall(nspath("Operations/*", ns=WFS_NAMESPACE))
        ]
        self.verbOptions + [
            op.tag
            for op in elem.findall(nspath("Operations/*", ns=WFS_NAMESPACE))
            if op.tag not in self.verbOptions
        ]

        # others not used but needed for iContentMetadata harmonisation
        self.styles = None
        self.timepositions = None
        self.defaulttimeposition = None

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall(nspath("MetadataURL", ns=WFS_NAMESPACE)):
            metadataUrl = {
                "url":
                testXMLValue(m.attrib["{http://www.w3.org/1999/xlink}href"],
                             attrib=True)
            }
            self.metadataUrls.append(metadataUrl)

        if parse_remote_metadata:
            self.parse_remote_metadata(timeout)
Ejemplo n.º 11
0
    def __init__(self,
                 elem,
                 parent=None,
                 children=None,
                 index=0,
                 parse_remote_metadata=False,
                 timeout=30):
        if xmltag_split(elem.tag) != 'Layer':
            raise ValueError('%s should be a Layer' % (elem, ))

        self.parent = parent
        if parent:
            self.index = "%s.%d" % (parent.index, index)
        else:
            self.index = str(index)

        self._children = children

        self.id = self.name = testXMLValue(
            elem.find(subcommon.nspath('Name', ns=WMS_NAMESPACE)))

        # layer attributes
        self.queryable = int(elem.attrib.get('queryable', 0))
        self.cascaded = int(elem.attrib.get('cascaded', 0))
        self.opaque = int(elem.attrib.get('opaque', 0))
        self.noSubsets = int(elem.attrib.get('noSubsets', 0))
        self.fixedWidth = int(elem.attrib.get('fixedWidth', 0))
        self.fixedHeight = int(elem.attrib.get('fixedHeight', 0))

        # title is mandatory property
        self.title = None
        title = testXMLValue(
            elem.find(subcommon.nspath('Title', ns=WMS_NAMESPACE)))
        if title is not None:
            self.title = title.strip()

        self.abstract = testXMLValue(
            elem.find(subcommon.nspath('Abstract', ns=WMS_NAMESPACE)))
        # keywords
        self.keywords = [
            f.text for f in elem.findall(
                subcommon.nspath('KeywordList/Keyword', ns=WMS_NAMESPACE))
        ]

        # ScaleHint
        sh = elem.find(subcommon.nspath('ScaleHint', ns=WMS_NAMESPACE))
        self.scaleHint = None
        if sh is not None:
            if 'min' in sh.attrib and 'max' in sh.attrib:
                self.scaleHint = {
                    'min': sh.attrib['min'],
                    'max': sh.attrib['max']
                }

        attribution = elem.find(
            subcommon.nspath('Attribution', ns=WMS_NAMESPACE))
        if attribution is not None:
            self.attribution = dict()
            title = attribution.find(
                subcommon.nspath('Title', ns=WMS_NAMESPACE))
            url = attribution.find(
                subcommon.nspath('OnlineResource', ns=WMS_NAMESPACE))
            logo = attribution.find(
                subcommon.nspath('LogoURL', ns=WMS_NAMESPACE))
            if title is not None:
                self.attribution['title'] = title.text
            if url is not None:
                self.attribution['url'] = url.attrib[
                    '{http://www.w3.org/1999/xlink}href']
            if logo is not None:
                self.attribution['logo_size'] = (int(logo.attrib['width']),
                                                 int(logo.attrib['height']))
                self.attribution['logo_url'] = logo.find(
                    subcommon.nspath('OnlineResource', ns=WMS_NAMESPACE)
                ).attrib['{http://www.w3.org/1999/xlink}href']

        b = elem.find(subcommon.nspath('LatLonBoundingBox', ns=WMS_NAMESPACE))
        if b is not None:
            self.boundingBoxWGS84 = (
                float(b.attrib['minx']),
                float(b.attrib['miny']),
                float(b.attrib['maxx']),
                float(b.attrib['maxy']),
            )
        elif self.parent:
            self.boundingBoxWGS84 = self.parent.boundingBoxWGS84
        else:
            self.boundingBoxWGS84 = None

        # bboxes
        bbs = elem.findall(subcommon.nspath('BoundingBox', WMS_NAMESPACE))
        if not bbs:
            crs_list = []
            for bb in bbs:
                srs_str = bb.attrib.get('SRS', None)
                srs = Crs(srs_str)
                box = tuple(
                    map(float, [
                        bb.attrib['minx'], bb.attrib['miny'],
                        bb.attrib['maxx'], bb.attrib['maxy']
                    ]))
                minx, miny, maxx, maxy = box[0], box[1], box[2], box[3]
                # handle the ordering so that it always
                # returns (minx, miny, maxx, maxy)
                if srs and srs.axisorder == 'yx':
                    # reverse things
                    minx, miny, maxx, maxy = box[1], box[0], box[3], box[2]
                crs_list.append((minx, miny, maxx, maxy, srs_str))
            self.crs_list = crs_list

        elif self.parent:
            self.crs_list = self.parent.crs_list
        else:
            self.crs_list = None

        # and maintain the original boundingBox attribute (first in list)
        # or the wgs84 bbox (to handle cases of incomplete parentage)
        self.boundingBox = self.crs_list[
            0] if self.crs_list else self.boundingBoxWGS84

        # SRS options
        self.crsOptions = []
        # Copy any parent SRS options (they are inheritable properties)
        if self.parent:
            self.crsOptions = list(self.parent.crsOptions)
        # Look for SRS option attached to this layer
        if elem.find(subcommon.nspath('SRS', ns=WMS_NAMESPACE)) is not None:
            ## some servers found in the wild use a single SRS
            ## tag containing a whitespace separated list of SRIDs
            ## instead of several SRS tags. hence the inner loop
            for srslist in [
                    x.text for x in elem.findall(
                        subcommon.nspath('SRS', ns=WMS_NAMESPACE))
            ]:
                if srslist:
                    for srs in srslist.split():
                        self.crsOptions.append(srs)
        #Get rid of duplicate entries
        self.crsOptions = list(set(self.crsOptions))
        #Set self.crsOptions to None if the layer (and parents) had no SRS options
        if len(self.crsOptions) == 0:
            #raise ValueError('%s no SRS available!?' % (elem,))
            #Comment by D Lowe.
            #Do not raise ValueError as it is possible that a layer is purely a parent layer and does not have SRS specified. Instead set crsOptions to None
            # Comment by Jachym:
            # Do not set it to None, but to [], which will make the code
            # work further. Fixed by anthonybaxter
            self.crsOptions = None

        #Styles
        self.styles = {}
        #Copy any parent styles (they are inheritable properties)
        if self.parent:
            self.styles = self.parent.styles.copy()
        #Get the styles for this layer (items with the same name are replaced)
        for s in elem.findall(subcommon.nspath('Style', ns=WMS_NAMESPACE)):
            name = s.find(subcommon.nspath('Name', ns=WMS_NAMESPACE))
            title = s.find(subcommon.nspath('Title', ns=WMS_NAMESPACE))
            if not name:
                continue
            if title is None:
                style = {'title': None}
            else:
                style = {'title': title.text}


#             if name is None or title is None:
#                 raise ValueError('%s missing name or title' % (s,))
#             style = { 'title' : title.text }
# legend url
            legend = s.find(
                subcommon.nspath('LegendURL/OnlineResource', ns=WMS_NAMESPACE))
            if legend is not None:
                style['legend'] = legend.attrib[
                    '{http://www.w3.org/1999/xlink}href']

            lgd = s.find(subcommon.nspath('LegendURL', WMS_NAMESPACE))
            if lgd is not None:
                if 'width' in lgd.attrib.keys():
                    style['legend_width'] = lgd.attrib.get('width')
                if 'height' in lgd.attrib.keys():
                    style['legend_height'] = lgd.attrib.get('height')

                lgd_format = lgd.find(subcommon.nspath('Format',
                                                       WMS_NAMESPACE))
                if lgd_format is not None:
                    style['legend_format'] = lgd_format.text.strip()

            self.styles[name.text] = style

        # timepositions - times for which data is available.
        self.timepositions = None
        self.defaulttimeposition = None
        for extent in elem.findall(subcommon.nspath('Extent',
                                                    ns=WMS_NAMESPACE)):
            if extent.attrib.get("name").lower() == 'time':
                if extent.text:
                    self.timepositions = extent.text.split(',')
                    self.defaulttimeposition = extent.attrib.get("default")
                    break

        # Elevations - available vertical levels
        self.elevations = None
        for extent in elem.findall(subcommon.nspath('Extent',
                                                    ns=WMS_NAMESPACE)):
            if extent.attrib.get("name").lower() == 'elevation':
                if extent.text:
                    self.elevations = extent.text.split(',')
                    break

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall(subcommon.nspath('MetadataURL',
                                               ns=WMS_NAMESPACE)):
            metadataUrl = {
                #                 'type': testXMLValue(m.attrib['type'], attrib=True),
                #                 'format': testXMLValue(m.find(subcommon.nspath('Format',ns=WMS_NAMESPACE))),
                #                 'url': testXMLValue(m.find(subcommon.nspath('OnlineResource',ns=WMS_NAMESPACE)).attrib['{http://www.w3.org/1999/xlink}href'], attrib=True)
                'type':
                testXMLValue(subcommon.attrib_extraction(m, 'type', None),
                             attrib=True),
                'format':
                testXMLValue(
                    m.find(subcommon.nspath('Format', ns=WMS_NAMESPACE))),
                'url':
                testXMLValue(subcommon.attrib_extraction(
                    m.find(subcommon.nspath('OnlineResource',
                                            ns=WMS_NAMESPACE)), 'href',
                    'xlink}'),
                             attrib=True)
            }

            if metadataUrl[
                    'url'] is not None and parse_remote_metadata:  # download URL
                try:
                    content = openURL(metadataUrl['url'], timeout=timeout)
                    doc = etree.parse(content)
                    if metadataUrl['type'] is not None:
                        if metadataUrl['type'] == 'FGDC':
                            metadataUrl['metadata'] = Metadata(doc)
                        if metadataUrl['type'] == 'TC211':
                            metadataUrl['metadata'] = MD_Metadata(doc)
                except Exception:
                    metadataUrl['metadata'] = None

            self.metadataUrls.append(metadataUrl)

        def str_strip(str_text):
            if str_text:
                return str_text.strip()
            else:
                return str_text

        # FeatureListURLs
        self.featureListUrls = []
        for m in elem.findall(
                subcommon.nspath('FeatureListURL', ns=WMS_NAMESPACE)):
            featureListUrl = {
                'format':
                str_strip(
                    m.find(subcommon.nspath('Format', ns=WMS_NAMESPACE)).text),
                'url':
                subcommon.attrib_extraction(
                    m.find(subcommon.nspath('OnlineResource',
                                            ns=WMS_NAMESPACE)), 'href',
                    'xlink')
            }
            self.featureListUrls.append(featureListUrl)

        # DataURLs
        self.dataUrls = []
        for m in elem.findall(subcommon.nspath('DataURL', ns=WMS_NAMESPACE)):
            dataUrl = {
                'format':
                str_strip(
                    m.find(subcommon.nspath('Format', ns=WMS_NAMESPACE)).text),
                'url':
                subcommon.attrib_extraction(
                    m.find(subcommon.nspath('OnlineResource',
                                            ns=WMS_NAMESPACE)), 'href',
                    'xlink')
            }
            self.dataUrls.append(dataUrl)

        self.layers = []
        for child in elem.findall(subcommon.nspath('Layer', ns=WMS_NAMESPACE)):
            self.layers.append(SubContentMetadata(child, self))
Ejemplo n.º 12
0
    def __init__(self, element):
        record = DataRecord(element)

        stations_field = record.get_by_name("stations")

        stations = {}
        sensors = {}

        for station in stations_field.content.field:
            s = StationProfile()
            s.name = station.name
            s.uid = station.content.get_by_name("stationID").content.value

            # Location
            vector = station.content.get_by_name("platformLocation").content
            srss = vector.referenceFrame.split("&amp;")
            hsrs = None
            try:
                hsrs = Crs(srss[0])
            except ValueError:
                pass

            vsrs = None
            try:
                vsrs = Crs(srss[-1].replace("2=http:", "http:"))
            except ValueError:
                pass

            s.set_property("horizontal_srs", hsrs)
            s.set_property("vertical_srs", vsrs)
            s.set_property("localFrame", vector.localFrame)

            lat = vector.get_by_name("latitude").content.value
            lon = vector.get_by_name("longitude").content.value
            z = vector.get_by_name("height").content.value

            loc = [lon, lat]
            if z:
                loc.append(z)

            s.location = sPoint(*loc)

            # sensors
            for sensor in station.content.get_by_name("sensors").content.field:
                name = sensor.name
                uri = sensor.content.get_by_name("sensorID").content.value

                sensors[name] = {'station': s.uid, 'name': name, 'uri': uri}
                # orientation
                ori_el = sensor.content.get_by_name("sensorOrientation")
                if ori_el:
                    orientation = self._parse_sensor_orientation(ori_el)
                    sensors[name]['sensor_orientation'] = orientation

                # location
                loc_el = sensor.content.get_by_name("sensorLocation")
                if loc_el:
                    location = self._parse_location(loc_el, s.location)
                    sensors[name]['location'] = location

                # profile bins
                profbins_el = sensor.content.get_by_name("profileBins")
                if profbins_el:
                    profile_bins = self._parse_profile_bins(profbins_el)
                    sensors[name]['profile_bins'] = profile_bins

                # OR profile heights
                profheights_el = sensor.content.get_by_name('profileHeights')
                if profheights_el:
                    profile_heights = self._parse_profile_heights(
                        profheights_el)
                    sensors[name]['profile_heights'] = profile_heights

            s.sensors = sensors

            stations[s.uid] = s

        sensor_data = self._parse_sensor_data(
            record.get_by_name('observationData'), sensors)

        # sensor data is dict of station id -> profile collection
        for station_id, sensor_profile_data in sensor_data.items():
            stations[station_id].elements.extend(sensor_profile_data._elements)

        if len(stations) > 1:
            self.feature = StationCollection(elements=stations)
        elif len(stations) == 1:
            self.feature = next(iter(stations.values()))
        else:
            print("No stations found!")
            self.feature = None
Ejemplo n.º 13
0
    def __init__(self, element):
        self._root = element

        self.description = testXMLValue(
            self._root.find(nspv("gml311:description")))

        self.begin_position = extract_time(
            self._root.find(
                nspv('om10:samplingTime/gml311:TimePeriod/gml311:beginPosition'
                     )))

        self.end_position = extract_time(
            self._root.find(
                nspv(
                    'om10:samplingTime/gml311:TimePeriod/gml311:endPosition')))

        self.procedures = [
            testXMLAttribute(e, nspv("xlink:href"))
            for e in self._root.findall(
                nspv("om10:procedure/om10:Process/gml311:member"))
        ]

        self.observedProperties = [
            testXMLAttribute(e, nspv("xlink:href"))
            for e in self._root.findall(
                nspv(
                    "om10:observedProperty/swe101:CompositePhenomenon/swe101:component"
                ))
        ]

        # Can't use a full Xpath expression, so iterate over all metaDataProperties to find the IOOS FeatureType
        self.feature_type = None
        ft = self._root.findall(
            nspv(
                "om10:featureOfInterest/gml311:FeatureCollection/gml311:metaDataProperty/gml311:GenericMetaData/gml311:name"
            ))
        ft.extend(
            self._root.findall(
                nspv(
                    "om10:featureOfInterest/gml311:FeatureCollection/gml311:metaDataProperty/gml311:name"
                )))
        ft_def = "http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.6/cf-conventions.html#discrete-sampling-geometries"
        for f in ft:
            if testXMLAttribute(f, "codeSpace") == ft_def:
                self.feature_type = testXMLValue(f)

        # BBOX
        envelope = self._root.find(
            nspv(
                "om10:featureOfInterest/gml311:FeatureCollection/gml311:boundedBy/gml311:Envelope"
            ))
        self.bbox_srs = Crs(testXMLAttribute(envelope, 'srsName'))
        lower_left_corner = testXMLValue(
            envelope.find(nspv('gml311:lowerCorner'))).split(" ")
        upper_right_corner = testXMLValue(
            envelope.find(nspv('gml311:upperCorner'))).split(" ")
        if self.bbox_srs.axisorder == "yx":
            self.bbox = box(float(lower_left_corner[1]),
                            float(lower_left_corner[0]),
                            float(upper_right_corner[1]),
                            float(upper_right_corner[0]))
        else:
            self.bbox = box(float(lower_left_corner[0]),
                            float(lower_left_corner[1]),
                            float(upper_right_corner[0]),
                            float(upper_right_corner[1]))

        # LOCATION
        location = self._root.find(
            nspv(
                "om10:featureOfInterest/gml311:FeatureCollection/gml311:location"
            ))
        # Should only have one child
        geo = list(location)[-1]
        self.location = {}

        def get_point(element, srs):
            name = testXMLValue(element.find(nspv("gml311:name")))
            point = testXMLValue(element.find(nspv("gml311:pos"))).split(" ")
            if srs.axisorder == "yx":
                point = Point(float(point[1]), float(point[0]))
            else:
                point = Point(float(point[0]), float(point[1]))
            return name, point

        self.location_srs = Crs(testXMLAttribute(geo, "srsName"))
        if geo.tag == nspv("gml311:Point"):
            n, p = get_point(geo, self.location_srs)
            self.location[n] = p
        elif geo.tag == nspv("gml311:MultiPoint"):
            for point in geo.findall(nspv("gml311:pointMembers/gml311:Point")):
                n, p = get_point(point, self.location_srs)
                self.location[n] = p

        # Now the fields change depending on the FeatureType
        self.results = self._root.find(nspv("om10:result"))

        # TODO: This should be implemented as a Factory
        self.feature = None
        data = self.results.find(nspv("swe20:DataRecord"))
        if data is not None:
            if self.feature_type == 'timeSeries':
                self.feature = TimeSeries(data).feature
            elif self.feature_type == 'timeSeriesProfile':
                self.feature = TimeSeriesProfile(data).feature
            else:
                print "No feature type found"
Ejemplo n.º 14
0
    def __init__(self, element):

        record = DataRecord(element)

        # Top level org structure
        stations_field = record.get_by_name("stations")
        stations = {}
        sensors = {}
        for station in stations_field.content.field:
            s = Station()
            s.name = station.name
            s.uid = station.content.get_by_name("stationID").content.value

            # Location
            vector = station.content.get_by_name("platformLocation").content
            srss = vector.referenceFrame.split("&amp;")
            hsrs = None
            try:
                hsrs = Crs(srss[0])
            except ValueError:
                pass

            vsrs = None
            try:
                vsrs = Crs(srss[-1].replace("2=http:", "http:"))
            except ValueError:
                pass

            s.set_property("horizontal_srs", hsrs)
            s.set_property("vertical_srs", vsrs)
            s.set_property("localFrame", vector.localFrame)

            lat = vector.get_by_name("latitude").content.value
            lon = vector.get_by_name("longitude").content.value
            z = vector.get_by_name("height").content.value

            loc = [lon, lat]
            if z:
                loc.append(z)

            s.location = sPoint(*loc)

            # Sensors
            for sensor in station.content.get_by_name("sensors").content.field:
                name = sensor.name
                uri = sensor.content.get_by_name("sensorID").content.value
                height = None
                location_quantity = sensor.content.get_by_name(
                    "height").content
                if location_quantity.referenceFrame == "#%s_frame" % s.name:
                    # Uses the station as reference frame
                    if location_quantity.value and z:
                        height = z + location_quantity.value
                    horizontal_srs = s.get_property("horizontal_srs")
                    vertical_srs = s.get_property("vertical_srs")
                else:
                    # Uses its own height
                    if location_quantity.value:
                        height = location_quantity.value
                    horizontal_srs = None
                    vertical_srs = None
                    if hasattr(sensor, 'referenceFrame'):
                        srss = sensor.referenceFrame.split("&amp;")
                        try:
                            horizontal_srs = Crs(srss[0])
                        except ValueError:
                            pass
                        try:
                            vertical_srs = Crs(srss[-1].replace(
                                "2=http:", "http:"))
                        except ValueError:
                            pass

                loc = [s.location.x, s.location.y]
                if height:
                    loc.append(height)

                location = sPoint(*loc)

                sensors[name] = {
                    'station': s.uid,
                    'name': name,
                    'uri': uri,
                    'horizontal_srs': horizontal_srs,
                    'vertical_srs': vertical_srs,
                    'location': location,
                    'columns': [],  # Array of Members representing the columns
                    'values': []  # Array of Points (the actual data)
                }

            stations[s.uid] = s

        # Start building the column structure
        data_array = record.get_by_name("observationData").content
        data_record = data_array.elementType.content

        columns = []
        # Data outside of the <field name="sensors"> DataChoice element
        for f in data_record.field:
            columns.append(f)

        # Data inside of DataChoice
        sensor_data = data_record.get_by_name("sensor")
        for sendata in sensor_data.content.item:
            if sendata.content is not None:
                sensors[sendata.name]['columns'] = []
                sensors[sendata.name]['values'] = []
                for f in sendata.content.field:
                    # Create a model Member for each column that will be copied and filled with data from each row
                    sensors[sendata.name]['columns'].append(f)

        decimalSeparator = data_array.encoding.decimalSeparator
        tokenSeparator = data_array.encoding.tokenSeparator
        blockSeparator = data_array.encoding.blockSeparator
        collapseWhiteSpaces = data_array.encoding.collapseWhiteSpaces

        data_values = data_array.values
        self.raw_data = copy(data_values)

        for row in filter(lambda x: x != "",
                          data_values.split(blockSeparator)):

            pt = None
            members = []
            values = row.split(tokenSeparator)
            sensor_key = None
            i = 0

            for x in columns:

                if isinstance(
                        x.content, Time
                ) and x.content.definition == "http://www.opengis.net/def/property/OGC/0/SamplingTime":
                    pt = Point()
                    pt.time = parser.parse(values[i])

                elif isinstance(x.content, DataChoice):
                    sensor_key = values[i]
                    dc_cols = sensors[sensor_key]['columns']

                    for j, c in enumerate(dc_cols):
                        if isinstance(c.content, AbstractSimpleComponent):
                            m = Member(units=c.content.uom,
                                       name=c.name,
                                       standard=c.content.definition,
                                       value=float(values[i + 1]))
                            members.append(m)

                        elif isinstance(
                                c.content, Time
                        ) and c.content.definition == "http://www.opengis.net/def/property/OGC/0/SamplingTime":
                            pt = Point()
                            pt.time = parser.parse(values[i])

                        # For each data column
                        i += 1

                elif isinstance(x.content, AbstractSimpleComponent):
                    m = Member(units=x.content.uom,
                               name=x.name,
                               standard=x.content.definition,
                               value=float(values[i]))
                    members.append(m)

                else:
                    print "WHAT AM I"

                i += 1

            pt.members = members
            pt.location = stations[sensors[sensor_key]['station']].location
            sensors[sensor_key]['values'].append(pt)

        for k, v in stations.iteritems():
            for sk, sv in sensors.iteritems():
                # Match on station uid
                if sv['station'] == k:
                    v.elements = self._merge_points(v.elements or [],
                                                    sv['values'])

        if len(stations) > 1:
            self.feature = StationCollection(elements=stations)
        elif len(stations) == 1:
            self.feature = next(stations.itervalues())
        else:
            print "No stations found!"
Ejemplo n.º 15
0
    def __init__(self, elem, parent, parse_remote_metadata=False, timeout=30):
        """."""
        self.id = testXMLValue(elem.find(nspath('Name')))
        self.title = testXMLValue(elem.find(nspath('Title')))
        self.abstract = testXMLValue(elem.find(nspath('Abstract')))
        self.keywords = [f.text for f in elem.findall(nspath('Keywords'))]

        # bboxes
        self.boundingBox = None
        b = elem.find(nspath('LatLongBoundingBox'))
        srs = elem.find(nspath('SRS'))

        if b is not None:
            self.boundingBox = (float(b.attrib['minx']), float(
                b.attrib['miny']), float(b.attrib['maxx']),
                                float(b.attrib['maxy']), Crs(srs.text))

        # transform wgs84 bbox from given default bboxt
        self.boundingBoxWGS84 = None

        if b is not None and srs is not None:
            wgs84 = pyproj.Proj(init="epsg:4326")
            try:
                src_srs = pyproj.Proj(init=srs.text)
                mincorner = pyproj.transform(src_srs, wgs84, b.attrib['minx'],
                                             b.attrib['miny'])
                maxcorner = pyproj.transform(src_srs, wgs84, b.attrib['maxx'],
                                             b.attrib['maxy'])

                self.boundingBoxWGS84 = (mincorner[0], mincorner[1],
                                         maxcorner[0], maxcorner[1])
            except RuntimeError as e:
                pass

        # crs options
        self.crsOptions = [
            Crs(srs.text) for srs in elem.findall(nspath('SRS'))
        ]

        # verbs
        self.verbOptions = [op.tag for op \
            in parent.findall(nspath('Operations/*'))]
        self.verbOptions + [op.tag for op \
            in elem.findall(nspath('Operations/*')) \
            if op.tag not in self.verbOptions]

        #others not used but needed for iContentMetadata harmonisation
        self.styles = None
        self.timepositions = None
        self.defaulttimeposition = None

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall(nspath('MetadataURL')):
            metadataUrl = {
                'type': testXMLValue(m.attrib['type'], attrib=True),
                'format': testXMLValue(m.find('Format')),
                'url': testXMLValue(m)
            }

            if metadataUrl[
                    'url'] is not None and parse_remote_metadata:  # download URL
                try:
                    content = openURL(metadataUrl['url'], timeout=timeout)
                    doc = etree.parse(content)
                    if metadataUrl['type'] is not None:
                        if metadataUrl['type'] == 'FGDC':
                            metadataUrl['metadata'] = Metadata(doc)
                        if metadataUrl['type'] == 'TC211':
                            metadataUrl['metadata'] = MD_Metadata(doc)
                except Exception:
                    metadataUrl['metadata'] = None

            self.metadataUrls.append(metadataUrl)
Ejemplo n.º 16
0
    def __init__(self, element):
        self._root = element

        self.id = testXMLValue(
            self._root.attrib.get(nspath_eval('gml:id', namespaces)), True)
        self.description = testXMLValue(
            self._root.find(nspath_eval('gml:description', namespaces)))
        self.name = testXMLValue(
            self._root.find(nspath_eval('gml:name', namespaces)))
        val = testXMLValue(
            self._root.find(nspath_eval('gml:srsName', namespaces)))
        if val is not None:
            self.srs = Crs(val)

        # LOOK: Check on GML boundedBy to make sure we handle all of the cases
        # gml:boundedBy
        try:
            envelope = self._root.find(
                nspath_eval('gml:boundedBy/gml:Envelope', namespaces))
            lower_left_corner = testXMLValue(
                envelope.find(nspath_eval('gml:lowerCorner',
                                          namespaces))).split()
            upper_right_corner = testXMLValue(
                envelope.find(nspath_eval('gml:upperCorner',
                                          namespaces))).split()
            # (left, bottom, right, top) in self.bbox_srs units
            self.bbox = (float(lower_left_corner[1]),
                         float(lower_left_corner[0]),
                         float(upper_right_corner[1]),
                         float(upper_right_corner[0]))
            self.bbox_srs = Crs(
                testXMLValue(envelope.attrib.get('srsName'), True))
        except Exception:
            self.bbox = None
            self.bbox_srs = None

        # LOOK: Support all gml:TimeGeometricPrimitivePropertyType
        # Right now we are just supporting gml:TimePeriod
        # sos:Time
        begin_position_element = self._root.find(
            nspath_eval('sos:time/gml:TimePeriod/gml:beginPosition',
                        namespaces))
        self.begin_position = extract_time(begin_position_element)
        end_position_element = self._root.find(
            nspath_eval('sos:time/gml:TimePeriod/gml:endPosition', namespaces))
        self.end_position = extract_time(end_position_element)

        self.result_model = testXMLValue(
            self._root.find(nspath_eval('sos:resultModel', namespaces)))

        self.procedures = []
        for proc in self._root.findall(nspath_eval('sos:procedure',
                                                   namespaces)):
            self.procedures.append(
                testXMLValue(
                    proc.attrib.get(nspath_eval('xlink:href', namespaces)),
                    True))

        # LOOK: Support swe:Phenomenon here
        # this includes compound properties
        self.observed_properties = []
        for op in self._root.findall(
                nspath_eval('sos:observedProperty', namespaces)):
            self.observed_properties.append(
                testXMLValue(
                    op.attrib.get(nspath_eval('xlink:href', namespaces)),
                    True))

        self.features_of_interest = []
        for fot in self._root.findall(
                nspath_eval('sos:featureOfInterest', namespaces)):
            self.features_of_interest.append(
                testXMLValue(
                    fot.attrib.get(nspath_eval('xlink:href', namespaces)),
                    True))

        self.response_formats = []
        for rf in self._root.findall(
                nspath_eval('sos:responseFormat', namespaces)):
            self.response_formats.append(testXMLValue(rf))

        self.response_modes = []
        for rm in self._root.findall(
                nspath_eval('sos:responseMode', namespaces)):
            self.response_modes.append(testXMLValue(rm))
Ejemplo n.º 17
0
    def __init__(self, elem, parent, service, nmSpc):
        """Initialize."""
        # TODO - examine the parent for bounding box info.

        self._service = service
        self._elem = elem
        self._parent = parent
        self.id = self._checkChildAndParent(nmSpc.WCS('Identifier'))
        self.description = self._checkChildAndParent(nmSpc.WCS('Description'))
        self.title = self._checkChildAndParent(nmSpc.OWS('Title'))
        self.abstract = self._checkChildAndParent(nmSpc.OWS('Abstract'))

        # keywords.
        self.keywords = []
        for kw in elem.findall(
                nmSpc.OWS('Keywords') + '/' + nmSpc.OWS('Keyword')):
            if kw is not None:
                self.keywords.append(kw.text)

        # also inherit any keywords from parent coverage summary (if there is one)
        if parent is not None:
            for kw in parent.findall(
                    nmSpc.OWS('Keywords') + '/' + nmSpc.OWS('Keyword')):
                if kw is not None:
                    self.keywords.append(kw.text)

        self.boundingBox = None  # needed for iContentMetadata harmonisation
        self.boundingBoxWGS84 = None
        b = elem.find(nmSpc.OWS('WGS84BoundingBox'))
        if b is not None:
            lc = b.find(nmSpc.OWS('LowerCorner')).text
            uc = b.find(nmSpc.OWS('UpperCorner')).text
            self.boundingBoxWGS84 = (
                float(lc.split()[0]),
                float(lc.split()[1]),
                float(uc.split()[0]),
                float(uc.split()[1]),
            )

        # bboxes - other CRS
        self.boundingboxes = []
        for bbox in elem.findall(nmSpc.OWS('BoundingBox')):
            if bbox is not None:
                try:
                    lc = b.find(nmSpc.OWS('LowerCorner')).text
                    uc = b.find(nmSpc.OWS('UpperCorner')).text
                    boundingBox = (float(lc.split()[0]), float(lc.split()[1]),
                                   float(uc.split()[0]), float(uc.split()[1]),
                                   b.attrib['crs'])
                    self.boundingboxes.append(boundingBox)
                except Exception:
                    pass

        # others not used but needed for iContentMetadata harmonisation
        self.styles = None
        self.crsOptions = None

        # SupportedCRS
        self.supportedCRS = []
        for crs in elem.findall(nmSpc.WCS('SupportedCRS')):
            self.supportedCRS.append(Crs(crs.text))

        # SupportedFormats
        self.supportedFormats = []
        for format in elem.findall(nmSpc.WCS('SupportedFormat')):
            self.supportedFormats.append(format.text)
Ejemplo n.º 18
0
    def __init__(
        self, elem, parent, parse_remote_metadata=False, timeout=30, auth=None
    ):
        """."""
        super(ContentMetadata, self).__init__(auth)
        self.id = testXMLValue(elem.find(nspath("Name")))
        self.title = testXMLValue(elem.find(nspath("Title")))
        self.abstract = testXMLValue(elem.find(nspath("Abstract")))
        self.keywords = [f.text for f in elem.findall(nspath("Keywords"))]

        # bboxes
        self.boundingBox = None
        b = elem.find(nspath("LatLongBoundingBox"))
        srs = elem.find(nspath("SRS"))

        if b is not None:
            self.boundingBox = (
                float(b.attrib["minx"]),
                float(b.attrib["miny"]),
                float(b.attrib["maxx"]),
                float(b.attrib["maxy"]),
                Crs(srs.text),
            )

        # transform wgs84 bbox from given default bboxt
        self.boundingBoxWGS84 = None

        if b is not None and srs is not None:
            wgs84 = pyproj.Proj("epsg:4326")
            try:
                src_srs = pyproj.Proj(srs.text)
                transformer = pyproj.Transformer.from_crs(src_srs, wgs84, always_xy=True)
                mincorner = transformer.transform(b.attrib["minx"], b.attrib["miny"])
                maxcorner = transformer.transform(b.attrib["maxx"], b.attrib["maxy"])

                self.boundingBoxWGS84 = (
                    mincorner[0],
                    mincorner[1],
                    maxcorner[0],
                    maxcorner[1],
                )
            except RuntimeError:
                pass

        # crs options
        self.crsOptions = [Crs(srs.text) for srs in elem.findall(nspath("SRS"))]

        # verbs
        ops = itertools.chain(
            parent.findall(nspath("Operations/*")), elem.findall(nspath("Operations/*"))
        )
        self.verbOptions = list({op.tag for op in ops})

        # others not used but needed for iContentMetadata harmonisation
        self.styles = None
        self.timepositions = None
        self.defaulttimeposition = None

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall(nspath("MetadataURL")):
            metadataUrl = {
                "type": testXMLValue(m.attrib["type"], attrib=True),
                "format": testXMLValue(m.attrib["format"], attrib=True),
                "url": testXMLValue(m),
            }
            self.metadataUrls.append(metadataUrl)
Ejemplo n.º 19
0
    def __init__(self, elem, parent, parse_remote_metadata=False, timeout=30):
        """."""
        self.id = testXMLValue(elem.find(nspath('Name')))
        self.title = testXMLValue(elem.find(nspath('Title')))
        self.abstract = testXMLValue(elem.find(nspath('Abstract')))
        self.keywords = [f.text for f in elem.findall(nspath('Keywords'))]

        # bboxes
        self.boundingBox = None
        b = elem.find(nspath('BoundingBox'))
        if b is not None:
            self.boundingBox = (float(b.attrib['minx']), float(
                b.attrib['miny']), float(b.attrib['maxx']),
                                float(b.attrib['maxy']), b.attrib['SRS'])
        self.boundingBoxWGS84 = None
        b = elem.find(nspath('LatLongBoundingBox'))
        if b is not None:
            self.boundingBoxWGS84 = (
                float(b.attrib['minx']),
                float(b.attrib['miny']),
                float(b.attrib['maxx']),
                float(b.attrib['maxy']),
            )
        # crs options
        self.crsOptions = [
            Crs(srs.text) for srs in elem.findall(nspath('SRS'))
        ]

        # verbs
        self.verbOptions = [op.tag for op \
            in parent.findall(nspath('Operations/*'))]
        self.verbOptions + [op.tag for op \
            in elem.findall(nspath('Operations/*')) \
            if op.tag not in self.verbOptions]

        #others not used but needed for iContentMetadata harmonisation
        self.styles = None
        self.timepositions = None
        self.defaulttimeposition = None

        # MetadataURLs
        self.metadataUrls = []
        for m in elem.findall(nspath('MetadataURL')):
            metadataUrl = {
                'type': testXMLValue(m.attrib['type'], attrib=True),
                'format': testXMLValue(m.find('Format')),
                'url': testXMLValue(m)
            }

            if metadataUrl[
                    'url'] is not None and parse_remote_metadata:  # download URL
                try:
                    content = urlopen(metadataUrl['url'], timeout=timeout)
                    doc = etree.parse(content)
                    if metadataUrl['type'] is not None:
                        if metadataUrl['type'] == 'FGDC':
                            metadataUrl['metadata'] = Metadata(doc)
                        if metadataUrl['type'] == 'TC211':
                            metadataUrl['metadata'] = MD_Metadata(doc)
                except Exception, err:
                    metadataUrl['metadata'] = None

            self.metadataUrls.append(metadataUrl)
Ejemplo n.º 20
0
    def __init__(self, element):
        self._root = element

        self.id = testXMLValue(
            self._root.find(nspath_eval('swes:identifier', namespaces)))
        if self.id is None:
            self.id = testXMLValue(
                self._root.attrib.get(nspath_eval('swes:id', namespaces)),
                True)
        self.description = testXMLValue(
            self._root.find(nspath_eval('swes:description', namespaces)))
        self.name = testXMLValue(
            self._root.find(nspath_eval('swes:name', namespaces)))

        # sos:observedArea
        try:
            envelope = self._root.find(
                nspath_eval('sos:observedArea/gml32:Envelope', namespaces))
            lower_left_corner = testXMLValue(
                envelope.find(nspath_eval('gml32:lowerCorner',
                                          namespaces))).split()
            upper_right_corner = testXMLValue(
                envelope.find(nspath_eval('gml32:upperCorner',
                                          namespaces))).split()
            # (left, bottom, right, top) in self.bbox_srs units
            self.bbox = (float(lower_left_corner[1]),
                         float(lower_left_corner[0]),
                         float(upper_right_corner[1]),
                         float(upper_right_corner[0]))
            self.bbox_srs = Crs(
                testXMLValue(envelope.attrib.get('srsName'), True))
        except Exception:
            self.bbox = None
            self.bbox_srs = None

        # LOOK: Support all gml:TimeGeometricPrimitivePropertyType
        # Right now we are just supporting gml:TimePeriod
        # sos:Time
        begin_position_element = self._root.find(
            nspath_eval(
                'sos:phenomenonTime/gml32:TimePeriod/gml32:beginPosition',
                namespaces))
        self.begin_position = extract_time(begin_position_element)
        end_position_element = self._root.find(
            nspath_eval(
                'sos:phenomenonTime/gml32:TimePeriod/gml32:endPosition',
                namespaces))
        self.end_position = extract_time(end_position_element)

        self.procedures = []
        for proc in self._root.findall(
                nspath_eval('swes:procedure', namespaces)):
            self.procedures.append(testXMLValue(proc))

        self.procedure_description_formats = []
        for proc in self._root.findall(
                nspath_eval('swes:procedureDescriptionFormat', namespaces)):
            self.procedure_description_formats.append(testXMLValue(proc))

        # LOOK: Support swe:Phenomenon here
        # this includes compound properties
        self.observed_properties = []
        for op in self._root.findall(
                nspath_eval('swes:observableProperty', namespaces)):
            self.observed_properties.append(testXMLValue(op))

        self.features_of_interest = []
        for fot in self._root.findall(
                nspath_eval('sos:featureOfInterest', namespaces)):
            self.features_of_interest.append(
                testXMLValue(
                    fot.attrib.get(nspath_eval('xlink:href', namespaces)),
                    True))

        self.response_formats = []
        for rf in self._root.findall(
                nspath_eval('sos:responseFormat', namespaces)):
            self.response_formats.append(testXMLValue(rf))

        self.observation_models = []
        for om in self._root.findall(
                nspath_eval('sos:observationType', namespaces)):
            self.observation_models.append(testXMLValue(om))
Ejemplo n.º 21
0
    def __init__(self, element):
        self._root = element

        OM_NS = ns.get_versioned_namespace('om', '1.0')
        GML_NS = ns.get_versioned_namespace('gml', '3.1.1')
        SWE_NS = ns.get_versioned_namespace('swe', '1.0')
        XLINK_NS = ns.get_namespace("xlink")

        self.name = testXMLValue(self._root.find(nsp("name", GML_NS)))
        self.description = testXMLValue(
            self._root.find(nsp("description", GML_NS)))
        self.observedProperties = []
        for op in self._root.findall(nsp('observedProperty', OM_NS)):
            self.observedProperties.append(
                testXMLAttribute(op, nsp('href', XLINK_NS)))

        # BBOX
        try:
            envelope = self._root.find(nsp('boundedBy/Envelope', GML_NS))
            lower_left_corner = testXMLValue(
                envelope.find(nsp('lowerCorner', GML_NS))).split(" ")
            upper_right_corner = testXMLValue(
                envelope.find(nsp('upperCorner', GML_NS))).split(" ")

            self.bbox_srs = Crs(testXMLAttribute(envelope, 'srsName'))
            # Always keep the BBOX as minx, miny, maxx, maxy
            if self.bbox_srs.axisorder == "yx":
                self.bbox = box(float(lower_left_corner[1]),
                                float(lower_left_corner[0]),
                                float(upper_right_corner[1]),
                                float(upper_right_corner[0]))
            else:
                self.bbox = box(float(lower_left_corner[0]),
                                float(lower_left_corner[1]),
                                float(upper_right_corner[0]),
                                float(upper_right_corner[1]))
        except Exception:
            self.bbox = None
            self.bbox_srs = None

        # Time range
        fp = nsp('samplingTime', OM_NS)
        mp = nsp('TimePeriod', GML_NS)

        lp = nsp('beginPosition', GML_NS)
        begin_position_element = self._root.find('%s/%s/%s' % (fp, mp, lp))
        self.begin_position = extract_time(begin_position_element)

        ep = nsp('endPosition', GML_NS)
        end_position_element = self._root.find('%s/%s/%s' % (fp, mp, ep))
        self.end_position = extract_time(end_position_element)

        feature_of_interest_element = self._root.find(
            nsp("featureOfInterest", OM_NS))
        self.feature_type = testXMLValue(
            feature_of_interest_element.find(
                nsp("FeatureCollection/metaDataProperty/name", GML_NS)))

        # Now the fields change depending on the FeatureType
        result_element = self._root.find(nsp("result", OM_NS))

        #TODO: This should be implemented as a Factory
        self.feature = None
        if self.feature_type == 'timeSeries':
            self.feature = SweTimeSeries(
                feature_of_interest=feature_of_interest_element,
                result=result_element,
                GML_NS=GML_NS,
                OM_NS=OM_NS,
                SWE_NS=SWE_NS)
        elif self.feature_type == 'trajectoryProfile':
            self.feature = SweTrajectoryProfile(
                feature_of_interest=feature_of_interest_element,
                result=result_element,
                GML_NS=GML_NS,
                OM_NS=OM_NS,
                SWE_NS=SWE_NS)
        elif self.feature_type == 'timeSeriesProfile':
            self.feature = SweTimeseriesProfile(
                feature_of_interest=feature_of_interest_element,
                result=result_element,
                GML_NS=GML_NS,
                OM_NS=OM_NS,
                SWE_NS=SWE_NS)
Ejemplo n.º 22
0
    def __build_getmap_request(self,
                               layers=None,
                               styles=None,
                               srs=None,
                               bbox=None,
                               format=None,
                               size=None,
                               time=None,
                               dimensions={},
                               elevation=None,
                               transparent=False,
                               bgcolor=None,
                               exceptions=None,
                               **kwargs):

        request = {
            'service': 'WMS',
            'version': self.version,
            'request': 'GetMap'
        }

        # check layers and styles
        assert len(layers) > 0
        request['layers'] = ','.join(layers)
        if styles:
            assert len(styles) == len(layers)
            request['styles'] = ','.join(styles)
        else:
            request['styles'] = ''

        # size
        request['width'] = str(size[0])
        request['height'] = str(size[1])

        # remap srs to crs for the actual request
        if srs.upper() == 'EPSG:0':
            # if it's esri's unknown spatial ref code, bail
            raise Exception('Undefined spatial reference (%s).' % srs)

        sref = Crs(srs)
        if sref.axisorder == 'yx':
            # remap the given bbox
            bbox = (bbox[1], bbox[0], bbox[3], bbox[2])

        # remapping the srs to crs for the request
        request['crs'] = str(srs)
        request['bbox'] = ','.join([repr(x) for x in bbox])
        request['format'] = str(format)
        request['transparent'] = str(transparent).upper()
        request['bgcolor'] = '0x' + bgcolor[1:7]
        request['exceptions'] = str(exceptions)

        if time is not None:
            request['time'] = str(time)

        if elevation is not None:
            request['elevation'] = str(elevation)

        # any other specified dimension, prefixed with "dim_"
        for k, v in six.iteritems(dimensions):
            request['dim_' + k] = str(v)

        if kwargs:
            for kw in kwargs:
                request[kw] = kwargs[kw]
        return request
Ejemplo n.º 23
0
    def process_station(self, uid):
        """ Makes a DescribeSensor request based on a 'uid' parameter being a station procedure """

        GML_NS = "http://www.opengis.net/gml"
        XLINK_NS = "http://www.w3.org/1999/xlink"

        with app.app_context():

            metadata_value = etree.fromstring(
                self.sos.describe_sensor(
                    outputFormat=
                    'text/xml;subtype="sensorML/1.0.1/profiles/ioos_sos/1.0"',
                    procedure=uid))
            station_ds = IoosDescribeSensor(metadata_value)

            unique_id = station_ds.id
            if unique_id is None:
                app.logger.warn(
                    "Could not get a 'stationID' from the SensorML identifiers.  Looking for a definition of 'http://mmisw.org/ont/ioos/definition/stationID'"
                )
                return

            dataset = db.Dataset.find_one({'uid': unicode(unique_id)})
            if dataset is None:
                dataset = db.Dataset()
                dataset.uid = unicode(unique_id)

            # Find service reference in Dataset.services and remove (to replace it)
            tmp = dataset.services[:]
            for d in tmp:
                if d['service_id'] == self.service.get('_id'):
                    dataset.services.remove(d)

            # Parsing messages
            messages = []

            # NAME
            name = unicode_or_none(station_ds.shortName)
            if name is None:
                messages.append(
                    u"Could not get a 'shortName' from the SensorML identifiers.  Looking for a definition of 'http://mmisw.org/ont/ioos/definition/shortName'"
                )

            # DESCRIPTION
            description = unicode_or_none(station_ds.longName)
            if description is None:
                messages.append(
                    u"Could not get a 'longName' from the SensorML identifiers.  Looking for a definition of 'http://mmisw.org/ont/ioos/definition/longName'"
                )

            # PLATFORM TYPE
            asset_type = unicode_or_none(station_ds.platformType)
            if asset_type is None:
                messages.append(
                    u"Could not get a 'platformType' from the SensorML identifiers.  Looking for a definition of 'http://mmisw.org/ont/ioos/definition/platformType'"
                )

            # LOCATION is in GML
            gj = None
            loc = station_ds.location
            if loc is not None and loc.tag == "{%s}Point" % GML_NS:
                pos_element = loc.find("{%s}pos" % GML_NS)
                # strip out points
                positions = map(float, testXMLValue(pos_element).split(" "))
                crs = Crs(testXMLAttribute(pos_element, "srsName"))
                if crs.axisorder == "yx":
                    gj = json.loads(
                        geojson.dumps(
                            geojson.Point([positions[1], positions[0]])))
                else:
                    gj = json.loads(
                        geojson.dumps(
                            geojson.Point([positions[0], positions[1]])))
            else:
                messages.append(
                    u"Found an unrecognized child of the sml:location element and did not attempt to process it: %s"
                    % etree.tostring(loc).strip())

            service = {
                # Reset service
                'name': name,
                'description': description,
                'service_type': self.service.get('service_type'),
                'service_id': ObjectId(self.service.get('_id')),
                'data_provider': self.service.get('data_provider'),
                'metadata_type': u'sensorml',
                'metadata_value':
                unicode(etree.tostring(metadata_value)).strip(),
                'messages': map(unicode, messages),
                'keywords': map(unicode, sorted(station_ds.keywords)),
                'variables': map(unicode, sorted(station_ds.variables)),
                'asset_type': asset_type,
                'geojson': gj,
                'updated': datetime.utcnow()
            }

            dataset.services.append(service)
            dataset.updated = datetime.utcnow()
            dataset.save()
            return "Harvested"