Skip to content

Commit

Permalink
Add streamlit app for DWD climate stations
Browse files Browse the repository at this point in the history
  • Loading branch information
gutzbenj committed Sep 24, 2023
1 parent a00f295 commit d8e6098
Show file tree
Hide file tree
Showing 7 changed files with 693 additions and 339 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Development
***********

- Make parameters TEMPERATURE_AIR_MAX_200 and TEMPERATURE_AIR_MIN_200 summarizable/interpolatable
- Add streamlit app for DWD climate stations

0.60.0 (16.09.2023)
*******************
Expand Down
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,14 @@ Features
- Define general settings in Settings context
- Command line interface
- Web-API via FastAPI
- Rich UI features like wetterdienst explorer and `streamlit_app`_
- Run SQL queries on the results
- Export results to databases and other data sinks
- Public Docker image
- Interpolation and Summary of station values

.. _streamlit_app: https://wetterdienst.streamlit.app

Setup
*****

Expand Down
933 changes: 595 additions & 338 deletions poetry.lock

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ classifiers = [
"Releases" = "https://github.com/earthobservations/wetterdienst/releases"

[tool.poetry.dependencies]
python = "^3.9,<3.12"
python = "^3.9,!=3.9.7,<3.12"

aenum = "^3.0"
aiohttp = "^3.8.1"
Expand Down Expand Up @@ -155,6 +155,7 @@ psycopg2-binary = { version = "^2.8", optional = true } # Expor
scipy = { version = "^1.9", optional = true } # Interpolation feature.
shapely = { version = "^2.0", optional = true } # Interpolation feature.
sqlalchemy = { version = "^2.0", optional = true } # Export feature.
streamlit = { version = "^1.27.0", optional = true } # Streamlit app
utm = { version = "^0.7", optional = true } # Interpolation feature.
uvicorn = { version = "^0.14", optional = true } # HTTP REST API feature.
wradlib = { version = "^1.19", optional = true } # Radar feature.
Expand Down Expand Up @@ -228,6 +229,7 @@ radar = ["h5py"]
radarplus = ["pybufrkit", "wradlib", "xradar"]
restapi = ["fastapi", "httpx", "uvicorn"]
sql = ["duckdb"]
streamlit = ["streamlit"]

[tool.poetry.scripts]
wetterdienst = 'wetterdienst.ui.cli:cli'
Expand Down Expand Up @@ -310,6 +312,8 @@ coverage-parallel = "pytest --cov=wetterdienst --numprocesses=auto -m 'not (expl
update = "poetry update"
citation = "python -m tools.citation"

stlit = "streamlit run ./wetterdienst/ui/stlit.py"

[tool.pytest.ini_options]
addopts = "-rsfEX -p pytester --strict-markers --verbosity=3 --webdriver=Firefox --headless"
#log_cli = true
Expand Down
Empty file.
87 changes: 87 additions & 0 deletions wetterdienst/ui/streamlit/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2018-2023, earthobservations developers.
# Distributed under the MIT License. See LICENSE for more info.
import plotly.express as px
import polars as pl
import streamlit
import streamlit as st

from wetterdienst.provider.dwd.observation import DwdObservationRequest

request = DwdObservationRequest("climate_summary", "daily")


@streamlit.cache_data
def get_dwd_observation_stations():
return request.all().df


@streamlit.cache_data
def get_dwd_observation_station(station_id):
return request.filter_by_station_id(station_id)


@streamlit.cache_data
def get_dwd_observation_station_values(station_id):
return get_dwd_observation_station(station_id).values.all()


def main():
"""Small streamlit app for accessing German climate stations by DWD"""
st.title("Wetterdienst - Data Tool")

st.subheader("Introduction")
st.markdown(
"""
This is a streamlit app based on the [wetterdienst](https://github.com/earthobservations/wetterdienst)
library that allows analysis of German climate stations (internally phrased "climate summary") by
the [German Weather Service (DWD)](https://www.dwd.de/). There are over 1_500 climate stations in Germany and
all of the data can be accessed freely thanks to the open data initiative. The app enables you to select any
of the stations (by station id or name), download its data (as CSV) and get visualizations of it.
"""
)
st.markdown("Here's a map of all stations:")
st.map(get_dwd_observation_stations(), latitude="latitude", longitude="longitude")

st.subheader("Select")
station = st.selectbox(
"Select climate station",
options=get_dwd_observation_stations().sort("name").rows(named=True),
format_func=lambda s: f"{s['name']} [{s['station_id']}]",
)
if station:
st.map(get_dwd_observation_station(station["station_id"]).df)

st.subheader("DataFrame")
df = pl.DataFrame()
if station:
df = get_dwd_observation_station_values(station["station_id"]).df
st.dataframe(df, hide_index=True, use_container_width=True)
st.download_button("Download CSV", df.write_csv(), "data.csv", "text/csv")

st.subheader("Plot")
parameters = st.multiselect("Select parameters", options=df.get_column("parameter").unique().sort().to_list())
if parameters:
fig = px.scatter(
df.filter(pl.col("parameter").is_in(parameters)),
x="date",
y="value",
color="parameter",
facet_row="parameter",
)
fig.update_layout(
showlegend=False, # Hide the legend
height=400 * len(parameters), # plot height times parameters
)
fig.update_yaxes(matches=None)
# Update y-axis titles to use facet labels and remove subplot titles
for i, annotation in enumerate(fig.layout.annotations):
axis_name = f"yaxis{i + 1}"
if axis_name in fig.layout:
fig.layout[axis_name].title.text = annotation.text
annotation.text = ""
st.plotly_chart(fig)


if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions wetterdienst/ui/streamlit/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
wetterdienst
plotly

0 comments on commit d8e6098

Please sign in to comment.