Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SOS2.0 and WaterML2.0 #241

Merged
merged 12 commits into from Jun 20, 2016
22 changes: 17 additions & 5 deletions docs/en/index.rst
Expand Up @@ -64,7 +64,7 @@ Standards Support
+-------------------+---------------------+
| `WMTS`_ | 1.0.0 |
+-------------------+---------------------+
| `WaterML`_ | 1.0, 1.1 |
| `WaterML`_ | 1.0, 1.1, 2.0 |
+-------------------+---------------------+

Installation
Expand Down Expand Up @@ -319,8 +319,8 @@ Search for bird data:
>>> csw.results
{'matches': 101, 'nextrecord': 21, 'returned': 20}
>>> for rec in csw.records:
... print csw.records[rec].title
...
... print(csw.records[rec].title)
...
ALLSPECIES
NatureServe Canada References
Bird Studies Canada - BirdMap WMS
Expand Down Expand Up @@ -601,8 +601,8 @@ You can also submit a pre-made request encoded as WPS XML:
Output URL=http://cida.usgs.gov/climate/gdp/process/RetrieveResultServlet?id=5103866488472745994OUTPUT.f80e2a78-96a9-4343-9777-be60fac5b256


SOS
---
SOS 1.0
-------

GetCapabilities

Expand All @@ -612,6 +612,16 @@ GetObservation

.. include:: ../../tests/doctests/sos_10_ndbc_getobservation.txt

SOS 2.0
-------
Examples of service metadata and GetObservation

.. include:: ../../tests/doctests/sos_20_52n_geoviqua.txt

Using the GetObservation response decoder for O&M and WaterML2.0 results

.. include:: ../../tests/doctests/sos_20_timeseries_decoder_ioos.txt

SensorML
--------
.. include:: ../../tests/doctests/sml_ndbc_station.txt
Expand Down Expand Up @@ -782,6 +792,8 @@ Credits
.. _`OGC WMC`: http://www.opengeospatial.org/standards/wmc
.. _`OGC WPS`: http://www.opengeospatial.org/standards/wps
.. _`OGC SOS`: http://www.opengeospatial.org/standards/sos
.. _`OGC O&M`: http://www.opengeospatial.org/standards/om
.. _`OGC WaterML2.0`: http://www.opengeospatial.org/standards/waterml
.. _`OGC SensorML`: http://www.opengeospatial.org/standards/sensorml
.. _`OGC CSW`: http://www.opengeospatial.org/standards/cat
.. _`OGC WMTS`: http://www.opengeospatial.org/standards/wmts
Expand Down
1 change: 1 addition & 0 deletions owslib/namespaces.py
Expand Up @@ -49,6 +49,7 @@ class Namespaces(object):
'swe20' : 'http://www.opengis.net/swe/2.0',
'swes' : 'http://www.opengis.net/swes/2.0',
'tml' : 'ttp://www.opengis.net/tml',
'wml2' : 'http://www.opengis.net/waterml/2.0',
'wfs' : 'http://www.opengis.net/wfs',
'wfs20' : 'http://www.opengis.net/wfs/2.0',
'wcs' : 'http://www.opengis.net/wcs',
Expand Down
109 changes: 109 additions & 0 deletions owslib/swe/observation/om.py
@@ -0,0 +1,109 @@
# -*- coding: ISO-8859-15 -*-
# =============================================================================
# Copyright (c) 2014 Pete Taylor
#
# Authors : Pete Taylor <peterataylor@gmail.com>
#
# Contact email: peterataylor@gmail.com
# =============================================================================

from owslib.util import nspath_eval, extract_time
from owslib.namespaces import Namespaces
from owslib.util import testXMLAttribute, testXMLValue

def get_namespaces():
ns = Namespaces()
return ns.get_namespaces(["swe20", "xlink", "sos20", "om20", "gml32",
"xsi"])
namespaces = get_namespaces()

def nspv(path):
return nspath_eval(path, namespaces)

class TimePeriod(object):
''' Basic class for gml TimePeriod '''
def __init__(self, start, end):
self.start = start
self.end = end
def __str__(self):
return ("start: " + str(self.start) + " " +
"end: " + str(self.end))

class OM_Observation(object):
''' The base OM_Observation type, of which there may be many
specialisations, e.g. MesaurementObservation, SWE Observation, WML2 etc.
Currently assumes that many properties are xlink only (not inline).
'''
def __init__(self, element):
self.type = testXMLAttribute(element.find(nspv(
"om20:type")), nspv("xlink:href"))

self.featureOfInterest = testXMLAttribute(element.find(nspv(
"om20:featureOfInterest")), nspv("xlink:href"))

self.observedProperty = testXMLAttribute(element.find(nspv(
"om20:observedProperty")), nspv("xlink:href"))

self.procedure = testXMLAttribute(element.find(nspv(
"om20:procedure")), nspv("xlink:href"))

''' Determine if phenom time is instant or a period. This
depend on the type of observation -- this could be split out '''
instant_element = element.find(nspv(
"om20:phenomenonTime/gml32:TimeInstant"))

if instant_element is not None:
self.phenomenonTime = extract_time(instant_element)
else:
start = extract_time(element.find(nspv(
"om20:phenomenonTime/gml32:TimePeriod/gml32:beginPosition")))
end = extract_time(element.find(nspv(
"om20:phenomenonTime/gml32:TimePeriod/gml32:endPosition")))
self.phenomenonTime = TimePeriod(start, end)

self.resultTime = extract_time(element.find(nspv(
"om20:resultTime/gml32:TimeInstant/gml32:timePosition")))

self.result = element.find(nspv("om20:result"))

def get_result(self):
''' This will handle different result types using specialised
observation types '''
return self.result

class MeasurementObservation(OM_Observation):
''' Specialised observation type that has a measurement (value + uom)
as result type
'''
def __init__(self, element):
super(MeasurementObservation, self).__init__(element)
self._parse_result()

def _parse_result(self):
''' Parse the result property, extracting the value
and unit of measure '''
if self.result is not None:
uom = testXMLAttribute(self.result, "uom")
value_str = testXMLValue(self.result)
try:
value = float(value_str)
except:
raise ValueError("Error parsing measurement value")
self.result = Measurement(value, uom)

def get_result(self):
return self.result

class Result(object):
''' Base class for different OM_Observation result types '''
def __init__(self, element):
pass

class Measurement(Result):
''' A single measurement (value + uom) '''
def __init__(self, value, uom):
super(Measurement, self).__init__(None)
self.value = value
self.uom = uom
def __str__(self):
return str(self.value) + "(" + self.uom + ")"