From 4d929d36634c6f8edb168c0b8b9778521cd48ef5 Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Mon, 14 Sep 2020 12:55:53 +0200 Subject: [PATCH] Update documentation all over the place (#150) --- .gitignore | 3 +- CHANGELOG.rst | 8 +- README.rst | 133 +++++++++++++--------- docs/index.rst | 17 ++- docs/pages/api.rst | 208 +++++++++++++++++++---------------- docs/pages/changelog.rst | 1 + docs/pages/cli.rst | 88 +++++++++++++++ docs/pages/data_coverage.rst | 11 +- docs/pages/development.rst | 13 ++- docs/pages/installation.rst | 14 +-- 10 files changed, 319 insertions(+), 177 deletions(-) create mode 120000 docs/pages/changelog.rst create mode 100644 docs/pages/cli.rst diff --git a/.gitignore b/.gitignore index 64f2be3dc..6a4832e27 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ coverage.xml .coverage htmlcov .nox/ -.pytest_cache/ \ No newline at end of file +.pytest_cache/ +docs/_build/ diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1341b580e..c8815a502 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,11 +2,11 @@ Changelog ********* Development -======= +=========== -- add test for Jupyter notebook -- add function to discover available climate observations (time resolution, parameter, -period type) +- Add test for Jupyter notebook +- Add function to discover available climate observations + (time resolution, parameter, period type) 0.6.0 (07.09.2020) ================== diff --git a/README.rst b/README.rst index ae9cd25ce..7878ee282 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,6 @@ -Introduction to wetterdienst -############################ +################################################################# +Wetterdienst - Python library to ease access to open weather data +################################################################# .. image:: https://github.com/earthobservations/wetterdienst/workflows/Tests/badge.svg :target: https://github.com/earthobservations/wetterdienst/actions?workflow=Tests @@ -26,91 +27,105 @@ Introduction to wetterdienst :target: https://zenodo.org/badge/latestdoi/160953150 -Welcome to wetterdienst, your friendly weather service library for Python from the -neighbourhood! We are a group of people, who try to make access to weather data in +Welcome to Wetterdienst, your friendly weather service library for Python from the +neighbourhood! We are a group of people who try to make access to weather data in Python feel like a warm summer breeze, similar to other projects like `rdwd `_ -for the R language ,which originally drew our interest in this project. As we long-term -goal is to provide you with data from multiple weather services, we are still stuck with -the German Weather Service (DWD). +for the R language, which originally drew our interest in this project. -We currently cover +While our long-term goal is to provide you with data from multiple weather services, +we are still stuck with the German Weather Service (DWD). -- historical weather data from ground stations -- RADOLAN fitted radar data for areal precipitation +Features +******** -and soon +Coverage +======== +The library currently covers +- historical weather data from ground stations +- RADOLAN fitted radar data for areal precipitation - MOSMIX statistical optimized scalar forecasts extracted from weather models - To get better insight on which data we have currently made available, with this library -take a look at -`Data Coverage `_ -. - -**CAUTION** -Although the data is specified as being open, the DWD asks you to reference them as -Copyright owner. To check out further, take a look at the -`Open Data Strategy at the DWD `_ -and the -`Official Copyright `_ +take a look at `data coverage`_. -To keep you updated about added features etc. we provide a -`Changelog `_ -. +.. _data coverage: https://wetterdienst.readthedocs.io/en/latest/pages/data_coverage.html -We strongly recommend reading the full documentation, which will be updated continuously -as we make progress with this library: -https://wetterdienst.readthedocs.io/en/latest/ +Details +======= +- Get metadata for a set of Parameter, PeriodType and TimeResolution. +- Get station(s) nearby a selected location for a given set. +- Store/recover collected data. +- Docker image to run the library dockerized. +- Client to run the library from command line. -Getting started -*************** -Run the following to make wetterdienst available in your current environment: +Setup +***** +Run the following to make ``wetterdienst`` available in your current environment: -.. code-block:: Python +.. code-block:: bash pip install wetterdienst -To get some historical observed station data call +Synopsis +******** +Get historical data for specific stations, using Python: -.. code-block:: Python +.. code-block:: python - from wetterdienst import collect_dwd_data - from wetterdienst import Parameter, PeriodType, TimeResolution + from wetterdienst import DWDStationRequest, Parameter, PeriodType, TimeResolution - station_data = collect_dwd_data( - station_ids=[1048], - parameter=Parameter.CLIMATE_SUMMARY, + request = DWDStationRequest( + station_ids=[1048,4411], + parameter=[Parameter.CLIMATE_SUMMARY, Parameter.SOLAR], time_resolution=TimeResolution.DAILY, - period_type=PeriodType.HISTORICAL + start_date="1990-01-01", + end_date="2020-01-01", + tidy_data=True, + humanize_column_names=True, + write_file=True, + prefer_local=True ) -Furthermore we currently offer: + for df in request.collect_data(): + # analyse the station here + +Get data for specific stations from the command line: -- RADOLAN radar based precipitation for Germany -- getting metadata for a set of Parameter, PeriodType and TimeResolution -- getting station(s) nearby a selected location for a given set... +.. code-block:: bash -and also + # Get list of all stations for daily climate summary data in JSON format + wetterdienst stations --parameter=kl --resolution=daily --period=recent -- storing/recovering collected data -- a prepared Docker image to run the library dockerized -- a client to run the library from command line + # Get daily climate summary data for specific stations + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=daily --period=recent + + +Documentation +************* +We strongly recommend reading the full documentation, which will be updated continuously +as we make progress with this library: + + - https://wetterdienst.readthedocs.io/ + +For the whole functionality, check out the `Wetterdienst API`_ section of our +documentation, which will be constantly updated. To stay up to date with the +development, take a look at the changelog_. Also, don't miss out our examples_. + + +.. _Wetterdienst API: https://wetterdienst.readthedocs.io/en/latest/pages/api.html +.. _changelog: https://wetterdienst.readthedocs.io/en/latest/pages/api.html +.. _examples: https://github.com/earthobservations/wetterdienst/tree/master/example -For the whole functionality, check out the -`API `_ -section of our documentation, which will be constantly updated. Also don't miss out our -`examples `_. Contribution ************ - Check out our contribution section in the documentation! For a successful PR passing all tests, you have to run -.. code-block:: Python +.. code-block:: bash nox -s tests nox -s black @@ -118,3 +133,13 @@ all tests, you have to run before committing. This will inform you in case of problems with tests and your code format. + + +Data license +************ +**CAUTION** +Although the data is specified as being open, the DWD asks you to reference them as +Copyright owner. To check out further, take a look at the +`Open Data Strategy at the DWD `_ +and the +`Official Copyright `_. diff --git a/docs/index.rst b/docs/index.rst index e0ef76be5..88a399e7b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,20 +3,25 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -**************************************** -Welcome to wetterdienst's documentation! -**************************************** +################################################################# +Wetterdienst - Python library to ease access to open weather data +################################################################# .. toctree:: - :maxdepth: 2 - :caption: Contents: + :maxdepth: 1 - pages/welcome + README pages/installation pages/data_coverage pages/api + pages/cli + +.. toctree:: + :maxdepth: 1 + pages/behind_the_scenes pages/development + pages/changelog pages/license_and_citation Indices and tables diff --git a/docs/pages/api.rst b/docs/pages/api.rst index 2c74cd104..e68e72082 100644 --- a/docs/pages/api.rst +++ b/docs/pages/api.rst @@ -1,57 +1,97 @@ +### API ### +The API is divided amongst the data products as written in the :ref:`data-coverage` chapter. -The API is divided amongst the data products as written in the Data coverage chapter. +*********************** +Historical Weather Data +*********************** +The API for the historical weather data mainly consists of the following functions: -API For Historical Weather Data -******************************* +``discover_climate_observations`` +================================= +- Print out available time resolution, parameter, period type combinations and + subsets of it depending on the entered arguments. -The API for the historical weather data mainly consists of the following functions: +``metadata_for_climate_observations`` +===================================== +- Discover what data for a set of parameters (parameter, time_resolution, + period_type) is available, especially which stations can be found. +- With **create_new_file_index**, the function can be forced to retrieve a new list + of files from the server, which is usually avoided as it rarely changes. + +Let's get station information for a given parameter, time resolution and period type: + +.. code-block:: python + + import wetterdienst + from wetterdienst import Parameter, PeriodType, TimeResolution + + metadata = wetterdienst.metadata_for_climate_observations( + parameter=Parameter.PRECIPITATION_MORE, + time_resolution=TimeResolution.DAILY, + period_type=PeriodType.HISTORICAL + ) + +The function returns a pandas DataFrame with information about the available stations, +including the column **HAS_FILE**, that indicates if the station has a file with data on +the server (which may not always be the case!). -- **discover_climate_observations:** - - prints out available time resolution, parameter, period type combinations and - subsets of it depending on the entered arguments -- **metadata_for_dwd_data:** - - discover what data for a set of parameters (parameter, time_resolution, - period_type) is available, especially which stations can be found. - - with **create_new_file_index**, the function can be forced to retrieve a new list - of files from the server, which is usually avoided as it rarely changes. +``DWDStationRequest`` +===================== -- **get_nearby_stations:** - - calculates the close weather stations based on the coordinates for the requested - data - - either selected by rank (n stations) or by distance in km - - it returns a DataFrame with meta data, distances [in km] and station ids that can be used to download the - data plus the +Synopsis +-------- +.. code-block:: python -- **DWDStationRequest:** - - a class that can combine multiple periods/date ranges for any number of stations - and parameters of one time resolution - - wraps collect_dwd_data: + from wetterdienst import DWDStationRequest, Parameter, PeriodType, TimeResolution + + request = DWDStationRequest( + station_ids=[3, 1048], + parameter=[Parameter.CLIMATE_SUMMARY, Parameter.SOLAR], + time_resolution=TimeResolution.DAILY, + start_date="1990-01-01", + end_date="2020-01-01", + tidy_data=True, + humanize_column_names=True, + write_file=True, + prefer_local=True + ) + + for df in request.collect_data(): + # analyse the station here + +This gives us the most options to work with the data, getting multiple parameters at +once, parsed nicely into column structure with improved parameter names and stored +automatically on the drive if wanted. - - **collect_dwd_data:** - - combines create_file_list_for_dwd_server, download_dwd_data and - parse_dwd_data for multiple stations - - wraps the following three functions: +Details +------- +- A class that can combine multiple periods/date ranges for any number of stations + and parameters of one time resolution. +- Wraps ``collect_climate_observations_data``: - - **create_file_list_for_dwd_server:** - - is used with the help of the metadata to retrieve file paths to - files for a set of parameters + station id - - here also **create_new_file_index** can be used + - Combines create_file_list_for_dwd_server, download_dwd_data and + parse_dwd_data for multiple stations + - Wraps the following three functions: - - **download_dwd_data_parallel:** - - is used with the created file paths to download and store the data - (second os optionally, in a hdf) + - ``create_file_list_for_climate_observations`` + - is used with the help of the metadata to retrieve file paths to + files for a set of parameters + station id + - here also **create_new_file_index** can be used - - **parse_dwd_data:** - - is used to get the data into the Python environment in - shape of a pandas DataFrame. - - the data will be ready to be analyzed by you! + - ``download_climate_observations_data_parallel`` + - is used with the created file paths to download and store the data + (second os optionally, in a hdf) + - ``parse_climate_observations_data`` + - is used to get the data into the Python environment in + shape of a pandas DataFrame. + - the data will be ready to be analyzed by you! -Additionally the following functions allow you to reset the cache of the file/meta index: +Additionally, the following functions allow you to reset the cache of the file/meta index: - **reset_file_index_cache:** - reset the cached file index to get latest list of files (only required for @@ -64,49 +104,39 @@ Additionally the following functions allow you to reset the cache of the file/me Parameter, time resolution and period type can be entered in three ways: - by using the exact enumeration e.g. - .. code-block:: Python + .. code-block:: python Parameter.CLIMATE_SUMMARY - by using the enumeration string e.g. - .. code-block:: Python + .. code-block:: python "climate_summary" or "CLIMATE_SUMMARY" - by using the originally defined parameter string e.g. - .. code-block:: Python + .. code-block:: python "kl" -How can you use the functions above? Let's take a look! - -We want to get the metadata for a given parameter, time resolution and period type -.. code-block:: Python +****************** +Geospatial support +****************** - import wetterdienst - from wetterdienst import Parameter, PeriodType, TimeResolution +``get_nearby_stations`` +======================= +- Calculate the close weather stations based on the coordinates for the requested data. +- Either selected by rank (n stations) or by distance in km. +- It returns a DataFrame with meta data, distances [in km] and station ids + that can be used to download the data. - metadata = wetterdienst.metadata_for_dwd_data( - parameter=Parameter.PRECIPITATION_MORE, - time_resolution=TimeResolution.DAILY, - period_type=PeriodType.HISTORICAL - ) - -The function returns a pandas DataFrame with information about the available stations, -including the column **HAS_FILE**, that indicates if the station has a file with data on -the server (which may not always be the case!). - -Now, we know an approximate location, where we cant to get data for the temperature. - -.. code-block:: Python +.. code-block:: python from datetime import datetime - from wetterdienst import Parameter, PeriodType, TimeResolution - from wetterdienst import get_nearby_stations + from wetterdienst import get_nearby_stations, DWDStationRequest, Parameter, PeriodType, TimeResolution - get_nearby_stations( - 50., 8.9, + stations = get_nearby_stations( + 50.0, 8.9, datetime(2020, 1, 1), datetime(2020, 1, 20), Parameter.TEMPERATURE_AIR, @@ -115,34 +145,21 @@ Now, we know an approximate location, where we cant to get data for the temperat num_stations_nearby=1 ) -The function returns a meta data DataFrame, where we can find weather station ids and distances to get our -observation data. +The function returns a meta data DataFrame, where we can find +weather station ids and distances to get the observation data: -.. code-block:: Python +.. code-block:: python - from wetterdienst import collect_dwd_data - from wetterdienst import Parameter, PeriodType, TimeResolution + station_ids = stations.STATION_ID.unique() - station_data = collect_dwd_data( - station_ids=[1048], - parameter=Parameter.CLIMATE_SUMMARY, - time_resolution=TimeResolution.DAILY, - period_type=PeriodType.HISTORICAL - ) - -Et voila: We just got the data we wanted for our location and are ready to analyse the -temperature on historical developments. To go even further we may use the following -code. - -.. code-block:: Python +Use these station ids to retrieve weather information: - from wetterdienst import DWDStationRequest - from wetterdienst import Parameter, PeriodType, TimeResolution +.. code-block:: python request = DWDStationRequest( - station_ids=[3, 1048], - parameter=[Parameter.CLIMATE_SUMMARY, Parameter.SOLAR], - time_resolution=TimeResolution.DAILY, + station_ids=station_ids, + parameter=[Parameter.TEMPERATURE_AIR, Parameter.SOLAR], + time_resolution=TimeResolution.HOURLY, start_date="1990-01-01", end_date="2020-01-01", tidy_data=True, @@ -151,24 +168,25 @@ code. prefer_local=True ) - for station_data in request.collect_data(): + for df in request.collect_data(): # analyse the station here -This gives us the most options to work with the data, getting multiple parameters at -once, parsed nicely into column structure with improved parameter names and stored -automatically on the drive if wanted. +Et voila: We just got the data we wanted for our location and are ready to analyse the +temperature on historical developments. Check out the more advanced examples in the `example `_ folder on Github. -API For MOSMIX -************** +****** +MOSMIX +****** Yet to be implemented... -API For RADOLAN -*************** +******* +RADOLAN +******* A request for RADOLAN data can be made either with DWDRadolanRequest or can be directly collected with collect_radolan_data. @@ -178,5 +196,3 @@ and date_times (list of datetimes or strings) or a start date and end date. Date are rounded to HH:50min as the data is packaged for this minute step. Additionally you can provide a folder and if to use local RADOLAN (to read in stored data) and if to write the file to a folder. - - diff --git a/docs/pages/changelog.rst b/docs/pages/changelog.rst new file mode 120000 index 000000000..bfa394db2 --- /dev/null +++ b/docs/pages/changelog.rst @@ -0,0 +1 @@ +../../CHANGELOG.rst \ No newline at end of file diff --git a/docs/pages/cli.rst b/docs/pages/cli.rst new file mode 100644 index 000000000..f9f6d8806 --- /dev/null +++ b/docs/pages/cli.rst @@ -0,0 +1,88 @@ +###################### +Command line interface +###################### +:: + + $ wetterdienst --help + + Usage: + wetterdienst stations --parameter= --resolution= --period= [--station=] [--latitude=] [--longitude=] [--number=] [--distance=] [--persist] [--format=] + wetterdienst readings --parameter= --resolution= --period= --station= [--persist] [--date=] [--format=] + wetterdienst readings --parameter= --resolution= --period= --latitude= --longitude= [--number=] [--distance=] [--persist] [--date=] [--format=] + wetterdienst about [parameters] [resolutions] [periods] + wetterdienst --version + wetterdienst (-h | --help) + + Options: + --parameter= Parameter/variable, e.g. "kl", "air_temperature", "precipitation", etc. + --resolution= Dataset resolution: "annual", "monthly", "daily", "hourly", "minute_10", "minute_1" + --period= Dataset period: "historical", "recent", "now" + --station= Comma-separated list of station identifiers + --latitude= Latitude for filtering by geoposition. + --longitude= Longitude for filtering by geoposition. + --number= Number of nearby stations when filtering by geoposition. + --distance= Maximum distance in km when filtering by geoposition. + --persist Save and restore data to filesystem w/o going to the network + --date= Date for filtering data. Can be either a single date(time) or + an ISO-8601 time interval, see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals. + --format= Output format. [Default: json] + --version Show version information + --debug Enable debug messages + -h --help Show this screen + + + Examples requesting stations: + + # Get list of all stations for daily climate summary data in JSON format + wetterdienst stations --parameter=kl --resolution=daily --period=recent + + # Get list of all stations in CSV format + wetterdienst stations --parameter=kl --resolution=daily --period=recent --format=csv + + # Get list of specific stations + wetterdienst stations --resolution=daily --parameter=kl --period=recent --station=1,1048,4411 + + # Get list of specific stations in GeoJSON format + wetterdienst stations --resolution=daily --parameter=kl --period=recent --station=1,1048,4411 --format=geojson + + Examples requesting readings: + + # Get daily climate summary data for specific stations + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=daily --period=recent + + # Optionally save/restore to/from disk in order to avoid asking upstream servers each time + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=daily --period=recent --persist + + # Limit output to specific date + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=daily --period=recent --date=2020-05-01 + + # Limit output to specified date range in ISO-8601 time interval format + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=daily --period=recent --date=2020-05-01/2020-05-05 + + # The real power horse: Acquire data across historical+recent data sets + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=daily --period=historical,recent --date=1969-01-01/2020-06-11 + + # Acquire monthly data for 2020-05 + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=monthly --period=recent,historical --date=2020-05 + + # Acquire monthly data from 2017-01 to 2019-12 + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=monthly --period=recent,historical --date=2017-01/2019-12 + + # Acquire annual data for 2019 + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=annual --period=recent,historical --date=2019 + + # Acquire annual data from 2010 to 2020 + wetterdienst readings --station=1048,4411 --parameter=kl --resolution=annual --period=recent,historical --date=2010/2020 + + # Acquire hourly data + wetterdienst readings --station=1048,4411 --parameter=air_temperature --resolution=hourly --period=recent --date=2020-06-15T12 + + Examples using geospatial features: + + # Acquire stations and readings by geoposition, request specific number of nearby stations. + wetterdienst stations --resolution=daily --parameter=kl --period=recent --lat=49.9195 --lon=8.9671 --num=5 + wetterdienst readings --resolution=daily --parameter=kl --period=recent --lat=49.9195 --lon=8.9671 --num=5 --date=2020-06-30 + + # Acquire stations and readings by geoposition, request stations within specific radius. + wetterdienst stations --resolution=daily --parameter=kl --period=recent --lat=49.9195 --lon=8.9671 --distance=25 + wetterdienst readings --resolution=daily --parameter=kl --period=recent --lat=49.9195 --lon=8.9671 --distance=25 --date=2020-06-30 diff --git a/docs/pages/data_coverage.rst b/docs/pages/data_coverage.rst index 2f97b034d..b39257622 100644 --- a/docs/pages/data_coverage.rst +++ b/docs/pages/data_coverage.rst @@ -1,3 +1,6 @@ +.. _data-coverage: + +############# Data Coverage ############# @@ -11,8 +14,8 @@ For a quick overview of the work of the DWD check the current `report `_ (only in german). -Wetterdienst currently only supports historical weather data, but sets its target to -include MOSMIX and radolan as well in future iterations. +Wetterdienst currently supports historical weather data +as well as MOSMIX and RADOLAN data. Historical Weather Data *********************** @@ -100,8 +103,8 @@ how the DWD calls the parameter e.g. "precipitation". .. |check| unicode:: + .. check .. |cross| unicode:: - .. cross -This table and subsets of it can be printed with a function call of "discover_climate_ -observations" as described in the API section. +This table and subsets of it can be printed with a function call of +``discover_climate_observations`` as described in the API section. MOSMIX ****** diff --git a/docs/pages/development.rst b/docs/pages/development.rst index 4d563954b..b8f55c2f8 100644 --- a/docs/pages/development.rst +++ b/docs/pages/development.rst @@ -1,3 +1,4 @@ +########### Development ########### @@ -8,6 +9,7 @@ as flawless as we can. We are always looking for others to join and bring in the ideas so please consider writing us! Below you can find more about contribution and the most recent changelog of the library. +************ Contribution ************ @@ -19,15 +21,18 @@ out how to solve it with a suitable programming solution). For development clone the repository and install developer dependencies via -.. code-block:: Python +.. code-block:: bash git clone https://github.com/earthobservations/wetterdienst cd wetterdienst - pip install . or poetry install + + pip install . + # or + poetry install Before committing, run black code formatter and lint to test for format. -.. code-block:: Python +.. code-block:: bash nox -s tests nox -s black @@ -38,5 +43,3 @@ In order to run the tests more **quickly**:: poetry install --extras=excel poetry shell pytest -vvvv -m "not (remote or slow) - -.. include:: ../../CHANGELOG.rst diff --git a/docs/pages/installation.rst b/docs/pages/installation.rst index e5f8fc554..dcbe9ef3f 100644 --- a/docs/pages/installation.rst +++ b/docs/pages/installation.rst @@ -7,13 +7,13 @@ version will always include most recent changes that may not have been released PyPi -.. code-block:: Python +.. code-block:: bash pip install wetterdienst Github -.. code-block:: Python +.. code-block:: bash pip install git+https://github.com/earthobservations/wetterdienst @@ -27,19 +27,19 @@ Docker We have a Docker image available that let's you run the library dockerized. To use Wetterdienst in a Docker container, you just have to build the image from this project -.. code-block:: Python +.. code-block:: bash docker build -t "wetterdienst" . To run the tests in the given environment, just call -.. code-block:: Python +.. code-block:: bash docker run -ti -v $(pwd):/app wetterdienst:latest poetry run pytest tests from the main directory. To work in an iPython shell call -.. code-block:: Python +.. code-block:: bash docker run -ti -v $(pwd):/app wetterdienst:latest poetry run ipython @@ -49,7 +49,7 @@ Command line script You can download data as csv files after building docker container. Currently, only the `collect_dwd_data` is supported by this service. -.. code-block:: Python +.. code-block:: bash docker run \ -ti -v $(pwd):/app wetterdienst:latest poetry run python wetterdienst/run.py \ @@ -58,6 +58,6 @@ Currently, only the `collect_dwd_data` is supported by this service. The `wetterdienst` command is also available through Docker: -.. code-block:: Python +.. code-block:: bash docker run -ti -v $(pwd):/app wetterdienst:latest poetry run wetterdienst