Skip to content
Snippets Groups Projects
Commit 6bb671b5 authored by Stefan Hendricks's avatar Stefan Hendricks
Browse files

update the dashboard download class

parent 13724225
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,8 @@
__author__ = "Stefan Hendricks"
import requests
from datetime import datetime
from dateutil.parser import parse as dtparse
from datetime import datetime, timedelta
from pathlib import Path
from loguru import logger
import numpy as np
......@@ -16,26 +17,28 @@ from icedrift import GeoReferenceStation
class PolarsternAWIDashboardPos(object):
def __init__(self, begin_date=None, end_date=None, output="csv"):
def __init__(self, begin_date, end_date, time_pad_minutes=10):
"""
Get Polarstern position and heading from the Polarstern HYDRINS1 sensor
NOTE: The URL etc can be checked using the web interface at
https://dashboard.awi.de/data-xxl/index.html
:param begin_date: (datetime.datetime) Start of the requested temporal coverage
:param end_date: (datetime.datetime)Start of the requested temporal coverage
:param time_pad_minutes: (integer) The number of minutes the period will be extended
on both side to ensure the data coverage of Polarstern position and heading
data always fully comprised the requested data period
:param begin_date:
:param end_date:
:param output:
"""
# Save input arguments
self.begin_date = begin_date
self.end_date = end_date
self.output = output
# Save input arguments and automatically extend data period
# using a short time window to ensure that there is always
# Polarstern data before the requested data period.
self.begin_date = begin_date - timedelta(minutes=time_pad_minutes)
self.end_date = end_date + timedelta(minutes=time_pad_minutes)
# --- Properties ---
# The format of the REST output.
# NOTE: The (default) value is specified in the `output` keyword to this method
self.format_dict = {"csv": "text/csv",
"json": "application/json",
"tab": "text/tab-separated-values"}
self.requested_format = "text/csv",
# Output format for the time stamp
# NOTE: Most sensors do not report faster than 1 second, therefore there is no need
......@@ -45,36 +48,70 @@ class PolarsternAWIDashboardPos(object):
# The main URL to the dashboard REST interface
self.base_url = "https://dashboard.awi.de/data-xxl/rest/data"
# A list of sensors
# Parameter to be pulled from the Polarstern Inertial Navigation Unit
# 1. Latitude
# 2. Longitude
# 3. True Heading
self.sensors = ["vessel:polarstern:hydrins_1:latitude$NRT",
"sensors=vessel:polarstern:hydrins_1:longitude$NRT",
"sensors=vessel:polarstern:hydrins_1:heading$NRT"]
# Temporal resolution:
# Temporal resolution (full)
self.aggregate_value = "second"
def save(self, filename=None):
"""
# Load the data
self.response = None
self.download()
:param filename:
self._variables = {}
self.decode_response()
def download(self):
"""
Pulls the data for the requested period from dashboard.awi.de
:return:
"""
# Construct the URL
url = self._construct_url()
logger.debug("url=%s" % url)
logger.info("data request url: {}".format(url))
# Download the websites response
# TODO: Error management
r = requests.get(url)
# Post-process the content
ascii_content = "\n".join(r.text.splitlines())
if self.output == "csv":
ascii_content = ascii_content.replace(";", ",")
self.response = "\n".join(r.text.splitlines())
self.response = self.response.replace(";", ",")
# Write output file
open(filename, 'w').write(ascii_content)
def decode_response(self):
"""
Parses the response from the data service into arrays of time, longitude, latitude
and true heading.
:return:
"""
# Init the variables
# NOTE: the first line is the header line and has to be ignored.
lines = self.response.split("\n")[1:]
n_lines = len(lines)
self._variables["time"] = np.full(n_lines, object)
for parameter_name in ["longitude", "latitude", "heading"]:
self._variables[parameter_name] = np.full(n_lines, np.nan)
for i, line in enumerate(lines):
string_array = line.split(",")
self._variables["time"][i] = dtparse(string_array[0])
self._variables["latitude"][i] = np.float(string_array[1])
self._variables["longitude"][i] = np.float(string_array[2])
self._variables["heading"][i] = np.float(string_array[3])
def save(self, filename):
"""
:param filename:
:return:
"""
raise NotImplementedError()
def _construct_url(self):
"""
......@@ -89,18 +126,18 @@ class PolarsternAWIDashboardPos(object):
url += self.sensor_def
# add output format
url += "&format=%s" % self.format_dict[self.output]
url += "&format=%s" % self.requested_format
# add temporal resolution
url += "&aggregate={}".format(self.aggregate_value)
# add begin date (optional)
if self.begin_date is not None:
url += "&beginDate=%s" % self.begin_date.strftime(self.datetime_format)
url += "&beginDate={}".format(self.begin_date.strftime(self.datetime_format))
# add end date (optional)
if self.end_date is not None:
url += "&endDate=%s" % self.end_date.strftime(self.datetime_format)
url += "&endDate={}".format(self.end_date.strftime(self.datetime_format))
return url
......@@ -113,6 +150,26 @@ class PolarsternAWIDashboardPos(object):
sensor_def = "sensors="+"&".join(self.sensors)
return sensor_def
@property
def reference_station(self):
"""
Return a icedrift.GeoReferenceStation instance
:return:
"""
refstat = GeoReferenceStation(self.time, self.longitude, self.latitude, self.heading)
return refstat
def __getattr__(self, attr):
"""
Modify the attribute getter to provide a shortcut to the data content
:param attr:
:return:
"""
if attr in list(self._variables.keys()):
return self._variables[attr]
else:
raise AttributeError()
class PolarsternPOSDashboardData(object):
"""
......@@ -180,5 +237,3 @@ class PolarsternPOSDashboardData(object):
data = GeoReferenceStation(content["time"], content["longitude"], content["latitude"], content["heading"])
return data
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment