weatherdb 1.1.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- docker/Dockerfile +30 -0
- docker/docker-compose.yaml +58 -0
- docker/docker-compose_test.yaml +24 -0
- docker/start-docker-test.sh +6 -0
- docs/requirements.txt +10 -0
- docs/source/Changelog.md +2 -0
- docs/source/License.rst +7 -0
- docs/source/Methode.md +161 -0
- docs/source/_static/custom.css +8 -0
- docs/source/_static/favicon.ico +0 -0
- docs/source/_static/logo.png +0 -0
- docs/source/api/api.rst +15 -0
- docs/source/api/cli.rst +8 -0
- docs/source/api/weatherDB.broker.rst +10 -0
- docs/source/api/weatherDB.config.rst +7 -0
- docs/source/api/weatherDB.db.rst +23 -0
- docs/source/api/weatherDB.rst +22 -0
- docs/source/api/weatherDB.station.rst +56 -0
- docs/source/api/weatherDB.stations.rst +46 -0
- docs/source/api/weatherDB.utils.rst +22 -0
- docs/source/conf.py +137 -0
- docs/source/index.rst +33 -0
- docs/source/setup/Configuration.md +127 -0
- docs/source/setup/Hosting.md +9 -0
- docs/source/setup/Install.md +49 -0
- docs/source/setup/Quickstart.md +183 -0
- docs/source/setup/setup.rst +12 -0
- weatherdb/__init__.py +24 -0
- weatherdb/_version.py +1 -0
- weatherdb/alembic/README.md +8 -0
- weatherdb/alembic/alembic.ini +80 -0
- weatherdb/alembic/config.py +9 -0
- weatherdb/alembic/env.py +100 -0
- weatherdb/alembic/script.py.mako +26 -0
- weatherdb/alembic/versions/V1.0.0_initial_database_creation.py +898 -0
- weatherdb/alembic/versions/V1.0.2_more_charachters_for_settings+term_station_ma_raster.py +88 -0
- weatherdb/alembic/versions/V1.0.5_fix-ma-raster-values.py +152 -0
- weatherdb/alembic/versions/V1.0.6_update-views.py +22 -0
- weatherdb/broker.py +667 -0
- weatherdb/cli.py +214 -0
- weatherdb/config/ConfigParser.py +663 -0
- weatherdb/config/__init__.py +5 -0
- weatherdb/config/config_default.ini +162 -0
- weatherdb/db/__init__.py +3 -0
- weatherdb/db/connections.py +374 -0
- weatherdb/db/fixtures/RichterParameters.json +34 -0
- weatherdb/db/models.py +402 -0
- weatherdb/db/queries/get_quotient.py +155 -0
- weatherdb/db/views.py +165 -0
- weatherdb/station/GroupStation.py +710 -0
- weatherdb/station/StationBases.py +3108 -0
- weatherdb/station/StationET.py +111 -0
- weatherdb/station/StationP.py +807 -0
- weatherdb/station/StationPD.py +98 -0
- weatherdb/station/StationT.py +164 -0
- weatherdb/station/__init__.py +13 -0
- weatherdb/station/constants.py +21 -0
- weatherdb/stations/GroupStations.py +519 -0
- weatherdb/stations/StationsBase.py +1021 -0
- weatherdb/stations/StationsBaseTET.py +30 -0
- weatherdb/stations/StationsET.py +17 -0
- weatherdb/stations/StationsP.py +128 -0
- weatherdb/stations/StationsPD.py +24 -0
- weatherdb/stations/StationsT.py +21 -0
- weatherdb/stations/__init__.py +11 -0
- weatherdb/utils/TimestampPeriod.py +369 -0
- weatherdb/utils/__init__.py +3 -0
- weatherdb/utils/dwd.py +350 -0
- weatherdb/utils/geometry.py +69 -0
- weatherdb/utils/get_data.py +285 -0
- weatherdb/utils/logging.py +126 -0
- weatherdb-1.1.0.dist-info/LICENSE +674 -0
- weatherdb-1.1.0.dist-info/METADATA +765 -0
- weatherdb-1.1.0.dist-info/RECORD +77 -0
- weatherdb-1.1.0.dist-info/WHEEL +5 -0
- weatherdb-1.1.0.dist-info/entry_points.txt +2 -0
- weatherdb-1.1.0.dist-info/top_level.txt +3 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
# libraries
|
2
|
+
import logging
|
3
|
+
import sqlalchemy as sa
|
4
|
+
from sqlalchemy import text as sqltxt
|
5
|
+
from functools import cached_property
|
6
|
+
|
7
|
+
from ..db.connections import db_engine
|
8
|
+
from ..db.models import MetaET
|
9
|
+
from .StationBases import StationTETBase
|
10
|
+
|
11
|
+
# set settings
|
12
|
+
# ############
|
13
|
+
__all__ = ["StationET"]
|
14
|
+
log = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
# class definition
|
17
|
+
##################
|
18
|
+
class StationET(StationTETBase):
|
19
|
+
"""A class to work with and download potential Evapotranspiration (VPGB) data for one station."""
|
20
|
+
|
21
|
+
# common settings
|
22
|
+
_MetaModel = MetaET
|
23
|
+
_para = "et"
|
24
|
+
_para_base = _para
|
25
|
+
_para_long = "potential Evapotranspiration"
|
26
|
+
_unit = "mm/Tag"
|
27
|
+
_decimals = 10
|
28
|
+
|
29
|
+
# cdc dwd parameters
|
30
|
+
_ftp_folder_base = ["climate_environment/CDC/derived_germany/soil/daily/"]
|
31
|
+
_ftp_zip_regex_prefix = r".*_v2_"
|
32
|
+
_cdc_date_col = "Datum"
|
33
|
+
_cdc_col_names_imp = ["VPGFAO"]
|
34
|
+
|
35
|
+
# for regionalistaion
|
36
|
+
_ma_terms = ["year"]
|
37
|
+
|
38
|
+
# for the fillup
|
39
|
+
_fillup_max_dist = 100000
|
40
|
+
|
41
|
+
def __init__(self, id, **kwargs):
|
42
|
+
super().__init__(id, **kwargs)
|
43
|
+
self.id_str = str(id)
|
44
|
+
|
45
|
+
@cached_property
|
46
|
+
def _table(self):
|
47
|
+
return sa.table(
|
48
|
+
f"{self.id}_{self._para}",
|
49
|
+
sa.column("timestamp", sa.Date),
|
50
|
+
sa.column("raw", sa.Integer),
|
51
|
+
sa.column("qc", sa.Integer),
|
52
|
+
sa.column("filled", sa.Integer),
|
53
|
+
sa.column("filled_by", sa.SmallInteger),
|
54
|
+
schema="timeseries")
|
55
|
+
|
56
|
+
def _create_timeseries_table(self):
|
57
|
+
"""Create the timeseries table in the DB if it is not yet existing."""
|
58
|
+
sql_add_table = '''
|
59
|
+
CREATE TABLE IF NOT EXISTS timeseries."{stid}_{para}" (
|
60
|
+
timestamp date PRIMARY KEY,
|
61
|
+
raw integer NULL DEFAULT NULL,
|
62
|
+
qc integer NULL DEFAULT NULL,
|
63
|
+
filled integer NULL DEFAULT NULL,
|
64
|
+
filled_by smallint NULL DEFAULT NULL
|
65
|
+
);
|
66
|
+
'''.format(stid=self.id, para=self._para)
|
67
|
+
with db_engine.connect() as con:
|
68
|
+
con.execute(sqltxt(sql_add_table))
|
69
|
+
con.commit()
|
70
|
+
|
71
|
+
def _get_sql_new_qc(self, period):
|
72
|
+
# inversion possible?
|
73
|
+
do_invers = self.get_meta(infos=["stationshoehe"])>800
|
74
|
+
|
75
|
+
sql_nears = self._get_sql_near_median(
|
76
|
+
period=period, only_real=False, add_is_winter=do_invers,
|
77
|
+
extra_cols="raw-nbs_median AS diff")
|
78
|
+
|
79
|
+
sql_null_case = f"""(nears.raw > (nears.nbs_median * 2) AND nears.raw > {3*self._decimals})
|
80
|
+
OR ((nears.raw * 4) < nears.nbs_median AND nears.raw > {2*self._decimals})"""
|
81
|
+
if do_invers:
|
82
|
+
# without inversion
|
83
|
+
sql_null_case = "CASE WHEN (winter) THEN "+\
|
84
|
+
f"((nears.raw * 4) < nears.nbs_median AND nears.raw > {2*self._decimals}) ELSE "+\
|
85
|
+
f"{sql_null_case} END"
|
86
|
+
|
87
|
+
# create sql for new qc
|
88
|
+
sql_new_qc = f"""
|
89
|
+
WITH nears AS ({sql_nears})
|
90
|
+
SELECT
|
91
|
+
timestamp,
|
92
|
+
(CASE WHEN ({sql_null_case}
|
93
|
+
OR (nears.raw < 0)
|
94
|
+
OR (nears.raw > {20*self._decimals}))
|
95
|
+
THEN NULL
|
96
|
+
ELSE nears."raw" END) as qc
|
97
|
+
FROM nears
|
98
|
+
"""
|
99
|
+
|
100
|
+
return sql_new_qc
|
101
|
+
|
102
|
+
def get_adj(self, **kwargs):
|
103
|
+
main_df, adj_df, ma, main_df_tr = super().get_adj(**kwargs)
|
104
|
+
|
105
|
+
# calculate the yearly
|
106
|
+
main_df_y = main_df.groupby(main_df_tr.index.year)\
|
107
|
+
.sum(min_count=345).mean()
|
108
|
+
|
109
|
+
adj_df["adj"] = (main_df * (ma[0] / main_df_y)).round(1)
|
110
|
+
|
111
|
+
return adj_df
|