Skip to content

Commit 16947d2

Browse files
Merge pull request #15 from nsidc/ardwa-6
ARDWA-6
2 parents 117e44d + ad73a2c commit 16947d2

File tree

4 files changed

+86
-11
lines changed

4 files changed

+86
-11
lines changed

pyproject.toml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,29 +39,30 @@ aross-stations-db = "aross_stations_db.cli:cli"
3939

4040
[project.optional-dependencies]
4141
test = [
42+
"mypy >=1.10",
43+
"pandas-stubs",
4244
"pytest >=6",
4345
"pytest-cov >=3",
44-
"mypy >=1.10",
4546
"types-tqdm",
4647
]
4748
dev = [
48-
"pytest >=6",
49-
"pytest-cov >=3",
5049
"nox",
5150
"pre-commit",
51+
"pytest >=6",
52+
"pytest-cov >=3",
5253
]
5354
docs = [
54-
"sphinx>=7.0",
55+
"furo>=2023.08.17",
5556
"myst_parser>=0.13",
56-
"sphinx_copybutton",
57+
"sphinx>=7.0",
5758
"sphinx_autodoc_typehints",
58-
"furo>=2023.08.17",
59+
"sphinx_copybutton",
5960
]
6061
ui = [
6162
"jupyterlab",
6263
"leafmap",
63-
"pandas",
6464
"matplotlib",
65+
"pandas",
6566
]
6667

6768
[project.urls]

src/aross_stations_db/api/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
allow_credentials=True,
1818
allow_methods=["*"],
1919
allow_headers=["*"],
20+
expose_headers=["content-disposition"]
2021
)
2122

2223

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
11
import datetime as dt
2+
import io
23
from typing import Annotated
34

4-
from fastapi import APIRouter, Depends, Query
5+
from fastapi import APIRouter, Depends, Query, Form
6+
from fastapi.responses import StreamingResponse
57
from geoalchemy2 import WKTElement
8+
import pandas as pd
69
from sqlalchemy.orm import Session
710

811
from aross_stations_db.api.dependencies import get_db_session
912
from aross_stations_db.api.v1.output import (
1013
StationsGeoJson,
1114
stations_query_results_to_geojson,
1215
)
13-
from aross_stations_db.db.query import stations_query
16+
from aross_stations_db.db.query import (
17+
stations_query,
18+
station_data_query
19+
)
1420

1521
router = APIRouter()
1622

17-
1823
@router.get("/")
19-
def get(
24+
async def get(
2025
db: Annotated[Session, Depends(get_db_session)],
2126
*,
2227
start: Annotated[dt.datetime, Query(description="ISO-format timestamp")],
@@ -27,3 +32,44 @@ def get(
2732
query = stations_query(db=db, start=start, end=end, polygon=polygon)
2833

2934
return stations_query_results_to_geojson(query.all())
35+
36+
37+
def station_data(
38+
db: Session,
39+
start: dt.datetime | None,
40+
end: dt.datetime | None,
41+
stations: list[str]
42+
) -> StreamingResponse:
43+
now = dt.datetime.now().strftime("%Y%m%d%H%M%S")
44+
fileRoot = 'stationdata'
45+
46+
query = station_data_query(db=db, start=start, end=end, stations=stations)
47+
df = pd.read_sql(query.statement, query.session.connection())
48+
49+
stream = io.StringIO()
50+
df.to_csv(stream, index=False)
51+
response = StreamingResponse(iter([stream.getvalue()]), media_type='text/csv')
52+
response.headers['Content-Disposition'] = f"attachment; filename={fileRoot}_{now}.csv"
53+
return response
54+
55+
56+
@router.get("/data")
57+
async def station_data_get(
58+
db: Annotated[Session, Depends(get_db_session)],
59+
*,
60+
start: Annotated[dt.datetime, Query(description="ISO-format timestamp")] | None = None,
61+
end: Annotated[dt.datetime, Query(description="ISO-format timestamp")] | None = None,
62+
stations: Annotated[list[str], Query(description="Station ID(s)")]
63+
) -> StreamingResponse:
64+
return station_data(db, start, end, stations)
65+
66+
67+
@router.post("/data")
68+
async def station_data_post(
69+
db: Annotated[Session, Depends(get_db_session)],
70+
*,
71+
start: Annotated[dt.datetime, Form(description="ISO-format timestamp")] | None = None,
72+
end: Annotated[dt.datetime, Form(description="ISO-format timestamp")] | None = None,
73+
stations: Annotated[list[str], Form(description="Station ID(s)")]
74+
) -> StreamingResponse:
75+
return station_data(db, start, end, stations)

src/aross_stations_db/db/query.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,33 @@ def stations_query(
3939
return query.group_by(Station.id)
4040

4141

42+
def station_data_query(
43+
db: Session,
44+
*,
45+
start: dt.datetime | None,
46+
end: dt.datetime | None,
47+
stations: list[str] = [],
48+
) -> RowReturningQuery[tuple[str, dt.datetime, dt.datetime, bool | None, int, int, int, int]]:
49+
print(type(stations))
50+
query = db.query(
51+
Event.station_id,
52+
Event.time_start,
53+
Event.time_end,
54+
Event.snow_on_ground,
55+
Event.rain_hours,
56+
Event.freezing_rain_hours,
57+
Event.solid_precipitation_hours,
58+
Event.unknown_precipitation_hours
59+
).filter(Event.station_id.in_(stations))
60+
61+
if start is not None:
62+
query = query.filter(Event.time_start >= start)
63+
if end is not None:
64+
query = query.filter(Event.time_end < end)
65+
66+
return query.order_by(Event.station_id)
67+
68+
4269
def timeseries_query(
4370
db: Session,
4471
*,

0 commit comments

Comments
 (0)