Skip to content

Commit

Permalink
Merge pull request #746 from akrherz/240423-3
Browse files Browse the repository at this point in the history
doc and use pydantic for tempwind_aloft service
  • Loading branch information
akrherz authored Apr 24, 2024
2 parents f37157e + 3ff0dc0 commit df850af
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 20 deletions.
100 changes: 81 additions & 19 deletions cgi-bin/request/tempwind_aloft.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,87 @@
Documentation for /cgi-bin/request/tempwind_aloft.py
----------------------------------------------------
To be written.
This service emits processed data from a temperature and winds aloft product.
Example Usage
~~~~~~~~~~~~~
Request all data for `KDSM` for 2023.
https://mesonet.agron.iastate.edu/cgi-bin/request/tempwind_aloft.py?station=KDSM&sts=2023-01-01T00:00Z&ets=2024-01-01T00:00Z
"""

from io import BytesIO, StringIO

import pandas as pd
from pydantic import AwareDatetime, Field
from pyiem.database import get_sqlalchemy_conn
from pyiem.exceptions import IncompleteWebRequest
from pyiem.webutil import iemapp
from pyiem.webutil import CGIModel, ListOrCSVType, iemapp
from sqlalchemy import text

EXL = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"


def get_data(station, sts, ets, tz, na, fmt):
class Schema(CGIModel):
"""See how we are called."""

ets: AwareDatetime = Field(
None,
description="The end time of the data request",
)
format: str = Field(
"csv",
description="The format of the output (csv json or excel)",
pattern="^(csv|json|excel)$",
)
na: str = Field(
"M",
description="The value to use for missing data",
pattern="^(M|None|blank)$",
)
sts: AwareDatetime = Field(
None,
description="The start time of the data request",
)
station: ListOrCSVType = Field(
...,
description="The station identifier(s) to request data for",
)
tz: str = Field(
"UTC",
description=(
"The timezone to use for timestamps in request and response, it "
"should be something recognized by the pytz library."
),
)
year1: int = Field(
None,
description="The year for the start time, if sts is not provided",
)
year2: int = Field(
None,
description="The year for the end time, if ets is not provided",
)
month1: int = Field(
None,
description="The month for the start time, if sts is not provided",
)
month2: int = Field(
None,
description="The month for the end time, if ets is not provided",
)
day1: int = Field(
None,
description="The day for the start time, if sts is not provided",
)
day2: int = Field(
None,
description="The day for the end time, if ets is not provided",
)


def get_data(stations, sts, ets, tz, na, fmt):
"""Go fetch data please"""
with get_sqlalchemy_conn("asos") as conn:
df = pd.read_sql(
Expand All @@ -30,10 +95,11 @@ def get_data(station, sts, ets, tz, na, fmt):
to_char(ftime at time zone :tz, 'YYYY/MM/DD HH24:MI')
as ftime2
from alldata_tempwind_aloft WHERE ftime >= :sts and
ftime <= :ets and station = :station ORDER by obtime, ftime"""
ftime <= :ets and station = ANY(:stations) ORDER by obtime, ftime
"""
),
conn,
params={"sts": sts, "ets": ets, "station": station, "tz": tz},
params={"sts": sts, "ets": ets, "stations": stations, "tz": tz},
)
df = df.drop(columns=["obtime", "ftime"]).rename(
columns={"obtime2": "obtime", "ftime2": "ftime"}
Expand All @@ -59,29 +125,25 @@ def get_data(station, sts, ets, tz, na, fmt):
return sio.getvalue()


@iemapp(help=__doc__)
@iemapp(help=__doc__, schema=Schema)
def application(environ, start_response):
"""See how we are called"""

fmt = environ.get("format", "csv")
tz = environ.get("tz", "UTC")
station = environ.get("station", "")[:4]
if station == "":
raise IncompleteWebRequest("GET parameter station= missing")
na = environ.get("na", "M")
if na not in ["M", "None", "blank"]:
start_response("200 OK", [("Content-type", "text/plain")])
return [b"ERROR: Invalid `na` value provided. {M, None, blank}"]
fmt = environ["format"]
tz = environ["tz"]
stations = environ["station"]
na = environ["na"]
if fmt != "excel":
start_response("200 OK", [("Content-type", "text/plain")])
return [
get_data(
station, environ["sts"], environ["ets"], tz, na, fmt
stations, environ["sts"], environ["ets"], tz, na, fmt
).encode("ascii")
]
lll = "stations" if len(stations) > 1 else stations[0]
headers = [
("Content-type", EXL),
("Content-disposition", f"attachment; Filename={station}.xlsx"),
("Content-disposition", f"attachment; Filename={lll}.xlsx"),
]
start_response("200 OK", headers)
return [get_data(station, environ["sts"], environ["ets"], tz, na, fmt)]
return [get_data(stations, environ["sts"], environ["ets"], tz, na, fmt)]
4 changes: 3 additions & 1 deletion htdocs/request/tempwind_aloft.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
near term forecasts of temperatures and wind speed aloft. More details on the
product can be found with the <a href="https://www.nws.noaa.gov/directives/sym/pd01008012curr.pdf">NWS Directive 10-812</a>.</p>
<p>The archive dates back to 23 September 2004.</p>
<p><a href="/cgi-bin/request/tempwind_aloft.py?help" class="btn btn-default">
<i class="fa fa-file"></i> Backend documentation</a> exists for those wishing to script against this
service. The archive dates back to 23 September 2004.</p>
<p><strong>Related:</strong>
<a class="btn btn-primary" href="/request/gis/cwas.phtml">CWSU Center Weather Advisories</a>
Expand Down

0 comments on commit df850af

Please sign in to comment.