Skip to content

Commit

Permalink
fix: Refactor SOS service
Browse files Browse the repository at this point in the history
Refactor SOS service to support the updated EDAM.

Fix #46
  • Loading branch information
argysamo committed Aug 16, 2022
1 parent 12dfe4a commit 746e3ec
Show file tree
Hide file tree
Showing 17 changed files with 248 additions and 200 deletions.
17 changes: 6 additions & 11 deletions edam/reader/models/measurement.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
class Measurement(object):
def __init__(self, value, timestamp=None, observable=None,
uom=None, station=None, junction=None):
self.value = value
self.timestamp = timestamp
self.observable = observable
self.uom = uom
self.station = station
self.junction = junction
from dataclasses import dataclass

def __repr__(self):
return f"{self.value}"

@dataclass
class Measurement:
timestamp: str
value: str
3 changes: 2 additions & 1 deletion edam/reader/models/station.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ def data(self) -> pd.DataFrame:
if dataframes:
dataframe = pd.concat(dataframes, join='inner', axis=1).fillna(
"empty") # type: pd.DataFrame
dataframe.set_index(keys=["timestamp"], drop=False, inplace=True)
dataframe['my_index'] = pd.to_datetime(dataframe['timestamp'])
dataframe.set_index('my_index', drop=True, inplace=True)
return dataframe
logger.warning(f"{self.name} does not have any data associated")
return None
Expand Down
16 changes: 8 additions & 8 deletions edam/resources/flask_related/templates/SOS_Examples.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
procedure = URN of sensor (see getCapabilities output for sensor's URN)
</li>
<li>Example: <a
href="{{ request.url_root }}SOS/?request=DescribeSensor&amp;procedure=2:13:TX">{{
request.url_root }}SOS/?request=DescribeSensor&amp;procedure=2:13:TX</a>
href="{{ request.url_root }}SOS/{{ example_describe }}">{{
request.url_root }}SOS/{{ example_describe }}</a>
</li>
</ul>

Expand All @@ -49,19 +49,19 @@
time frame
</li>
<li>Parameters: request = GetObservation <br/></li>
<li><code>offering</code> = URN of sensor (see getCapabilities output for
sensor's URN) <br/></li>
<li><code>observedProperty</code> = (One of : <em>Temperature, Pressure,
Nitrogen_Dioxide, Carbon_Monoxide</em>)
<li><code>offering</code> = Station name (see getCapabilities output for
available stations) <br/></li>
<li><code>observedProperty</code> = (see getCapabilities output for
available stations))
<br/></li>
<li><code>eventTime</code> = (YYYY-MM-DD HH:MM:SS/YYYY-MM-DD HH:MM:SS). When
eventTime = Datetime/
<em>EDAM</em> returns<br/>
<em>measurements</em> from <strong>Datetime</strong> until now.
</li>
<li>Example: <a
href="{{ request.url_root }}SOS/?request=GetObservation&procedure=2:13:TX">{{
request.url_root }}SOS/?request=GetObservation&procedure=2:13:TX</a>
href="{{ request.url_root }}SOS/{{ example_observation }}">{{
request.url_root }}SOS/{{ example_observation }}</a>
</li>
</ul>

Expand Down
1 change: 1 addition & 0 deletions edam/resources/flask_related/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
{% set navigation_bar = [
('/maps/', 'maps', 'Maps'),
('/about/', 'about', 'API'),
('/SensorObservationService/', 'sos', 'OGC SOS'),
('/home/', 'home', 'Home'),
('/graphs', 'graphs', 'Graphs')
] -%}
Expand Down
12 changes: 5 additions & 7 deletions edam/resources/flask_related/templates/sos/DescribeSensor.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,24 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/sensorML/1.0.1 http://schemas.opengis.net/sensorML/1.0.1/sensorML.xsd"
version="1.0.1">
{% set helper = sensor %}
<sml:identification>
<sml:IdentifierList>
<sml:identifier name="longName">
<sml:Term>
<sml:value>{{ helper.sensor.name }} observes {{
helper.observable.name }}. It is manufactured
by {{ helper.sensor.manufacturer }}
<sml:value>{{ junction.sensor.name }} observes {{
junction.observable.name }}. It is manufactured
by {{ junction.sensor.manufacturer }}
</sml:value>
</sml:Term>
</sml:identifier>
<sml:identifier name="shortName">
<sml:Term>
<sml:value>{{ helper.sensor.name }}</sml:value>
<sml:value>{{ junction.sensor.name }}</sml:value>
</sml:Term>
</sml:identifier>
<sml:identifier name="SensorId">
<sml:Term>
<sml:value>{{ helper.station_id }}:{{ helper.sensor_id}}:{{
helper.template_id }}
<sml:value>{{ station.name }}:{{ junction.sensor.name}}
</sml:value>
</sml:Term>
</sml:identifier>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
version="1.0.0"
xml:lang="en">
<Exception exceptionCode="InvalidParameterValue" locator="procedure">
<ExceptionText>{{ procedure }}</ExceptionText>
<ExceptionText>{{ exception_text }}</ExceptionText>
</Exception>
</ExceptionReport>
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,11 @@
<gml:endPosition></gml:endPosition>
</gml:TimePeriod>
</time>
{% for helper in helpers %}{% if helper.station_id == station.id
%}
{% for junction in station.junctions %}
<sos:procedure
xlink:href="{{ helper.station_id }}:{{ helper.sensor_id }}:{{ helper.template_id }}"/>
xlink:href="{{ station.name }}:{{ junction.sensor.name }}"/>
<sos:observedProperty
xlink:href="{{ helper.observable.name }}"/>{% endif %}{%
endfor %}
xlink:href="{{ junction.observable.observable_id }}"/>{% endfor %}
<sos:featureOfInterest
xlink:href="urn:edam:feature:{{ station.name }}"/>
<sos:responseFormat>text/xml;subtype="om/1.0.0"
Expand Down
30 changes: 15 additions & 15 deletions edam/resources/flask_related/templates/sos/GetObservation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,36 @@
xmlns:om="http://www.opengis.net/om/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/om/1.0 http://schemas.opengis.net/om/1.0.0/om.xsd">
<gml:description>{{ results[0].observable.name}} measurements
from {{ results[0].station.name}} station
<gml:description>**{{ junction.observable.name}}** measurements observed with
**{{ junction.sensor.name }}** from **{{ station.name}}** station
</gml:description>
<gml:name>{{ results[0].station.id}}:{{ results[0].helper.sensor.id }}
<gml:name>{{ station.name}}:{{ junction.observable.name }}
</gml:name>
<om:member>
<om:samplingTime>
<gml:TimePeriod gml:id="ST">
<gml:beginPosition>{{ results[0].timestamp }}
<gml:beginPosition>{{ measurements[0].timestamp }}
</gml:beginPosition>
<gml:endPosition>{{ results[-1].timestamp }}</gml:endPosition>
<gml:endPosition>{{ measurements[-1].timestamp }}
</gml:endPosition>
</gml:TimePeriod>
</om:samplingTime>
{% for measurement in results %}
{% for measurement in measurements %}
<sos:observationData>
{#+ hash(helper.observable.name)#}
<om:Observation gml:id="{{ results[0].observable.name }}">
<om:Observation gml:id="{{ junction.observable.name }}">
<om:phenomenonTime>
{# {{ hash(d2s(measurement.timestamp)) }}#}
<gml:TimeInstant gml:id="#">
<gml:TimeInstant
gml:id="#{{ hash(measurement.timestamp) }}">
<gml:timePosition>{{ measurement.timestamp }}
</gml:timePosition>
</gml:TimeInstant>
</om:phenomenonTime>
{# {{ hash(d2s(measurement.timestamp)) }}#}
<om:resultTime xlink:href="#"/>
<om:procedure>{{ results[0].helper.sensor.name}}</om:procedure>
<om:resultTime xlink:href="#{{ hash(measurement.timestamp) }}"/>
<om:procedure>{{ station.name }}:{{ junction.sensor.name }}
</om:procedure>
<om:observedProperty
xlink:href="{{ results[0].observable.ontology }}"/>
<om:result uom="{{ results[0].uom.name }}">{{ measurement.value
xlink:href="{{ junction.observable.ontology }}"/>
<om:result uom="{{ junction.unit.name }}">{{ measurement.value
}}
</om:result>
</om:Observation>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
xml:lang="en">
<Exception exceptionCode=""
locator="">
<ExceptionText></ExceptionText>
<ExceptionText>{{ exception_text }}</ExceptionText>
</Exception>
</ExceptionReport>
Empty file added edam/services/__init__.py
Empty file.
Empty file added edam/services/sos/__init__.py
Empty file.
150 changes: 150 additions & 0 deletions edam/services/sos/sos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import datetime

from flask import render_template

from edam.reader.models.measurement import Measurement
from edam import OGC_SOS_CONFIGURATION


class OgcSos:
def __init__(self, stations=None):

self.stations = stations
self.info = OGC_SOS_CONFIGURATION
self.keywords = [f"{station.name}:{junction.observable.name}" for
station in stations for junction in station.junctions]

def resolve_request(self, request=None, **kwargs):
"""
Determines the type or request and sets the appropriate template
"""
if request is None:
return
if request == "GetCapabilities":
return self.get_capabilities(**kwargs)
elif request == "DescribeSensor":
return self.describe_sensor(**kwargs)
elif request == "GetObservation":
return self.get_observation(**kwargs)

def get_capabilities(self, **kwargs):
template = "sos/GetCapabilities.xml"
template_related = {
"template_name_or_list": template,
"info": self.info,
"keywords": self.keywords,
"stations": self.stations
}
return template_related

def describe_sensor(self, **kwargs):

procedure = kwargs['procedure']
station_name, sensor_name = procedure.split(':')
station = filter(lambda st: st.name == station_name, self.stations)
try:
station = next(station)
except StopIteration:
template_related = {
"template_name_or_list": "sos/DescribeSensorException.xml",
"exception_text": f"*{procedure}* does not exist. "
f"*{station_name}* is not a station.",
}
return template_related
junction = filter(lambda sen: sen.sensor.name == sensor_name,
station.junctions)
try:
junction = next(junction)
except StopIteration:
template_related = {
"template_name_or_list": "sos/DescribeSensorException.xml",
"exception_text": f"*{procedure}* does not exist. "
f"*{sensor_name}* is not a sensor name.",
}
return template_related

template_related = {
"template_name_or_list": "sos/DescribeSensor.xml",
"station": station,
"junction": junction,
}
return template_related

def get_observation(self, **kwargs):
offering = kwargs['offering']
station_name = offering
station = filter(lambda st: st.name == station_name, self.stations)
try:
station = next(station)
except StopIteration:
template_related = {
"template_name_or_list": "sos/GetObservationException.xml",
"exception_text": f"*{station_name}* station does not exist."
}
return template_related
observed_property = kwargs['observed_property']
if observed_property is None:
template_related = {
"template_name_or_list": "sos/GetObservationException.xml",
"exception_text": f"observedProperty does not exist. "
}
return template_related
else:
junction = filter(
lambda sen: sen.observable.observable_id == observed_property,
station.junctions)
try:
junction = next(junction)
except StopIteration:
template_related = {
"template_name_or_list": "sos/GetObservationException.xml",
"exception_text": f"*{observed_property}* observed property"
f" does not exist."
}
return template_related

# observed_property exists
event_time = kwargs['event_time']
if event_time:

start, end = event_time.split('/')
try:
start_date = datetime.datetime.strptime(start,
"%Y-%m-%d %H:%M:%S")
except ValueError:
start_exists = False
else:
start_exists = True
try:
end_date = datetime.datetime.strptime(end,
"%Y-%m-%d %H:%M:%S")
except ValueError:
end_exists = False
else:
end_exists = True

if start_exists and end_exists:
raw = station.data.loc[lambda df: df.index >= start_date and df.index <= end_date,:]
elif start_exists and not end_exists:
raw = station.data.loc[lambda df: df.index >= start_date, :]
elif not start_exists and end_exists:
raw = station.data.loc[lambda df: df.index <= end_date, :]

raw = raw[observed_property]
raw = raw.to_dict()
else:
raw = station.data[observed_property].to_dict()

measurements = list()

for timestamp, value in raw.items():
measurements.append(
Measurement(timestamp=timestamp, value=value))

template_related = {
"template_name_or_list": "sos/GetObservation.xml",
"junction": junction,
"station": station,
"measurements": measurements
}
return template_related
Loading

0 comments on commit 746e3ec

Please sign in to comment.