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
weatherdb/db/views.py
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
import sqlalchemy as sa
|
2
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
3
|
+
from sqlalchemy.ext.compiler import compiles
|
4
|
+
from sqlalchemy.sql.expression import Executable, ClauseElement
|
5
|
+
|
6
|
+
from .models import StationMATimeserie, StationMARaster, ModelBase
|
7
|
+
|
8
|
+
__all__ = [
|
9
|
+
"StationMATimeserieRasterQuotientView",
|
10
|
+
"StationKindQuotientView"
|
11
|
+
]
|
12
|
+
|
13
|
+
# View Bases
|
14
|
+
class CreateView(Executable, ClauseElement):
|
15
|
+
inherit_cache = True
|
16
|
+
def __init__(self, name, selectable):
|
17
|
+
self.name = name
|
18
|
+
self.selectable = selectable
|
19
|
+
|
20
|
+
@compiles(CreateView)
|
21
|
+
def compile_create_view(element, compiler, **kwargs):
|
22
|
+
return "CREATE OR REPLACE VIEW %s AS %s" % (
|
23
|
+
element.name,
|
24
|
+
compiler.sql_compiler.process(element.selectable, literal_binds=True)
|
25
|
+
)
|
26
|
+
|
27
|
+
class DropView(Executable, ClauseElement):
|
28
|
+
inherit_cache = True
|
29
|
+
def __init__(self, name, cascade=False, if_exists=True):
|
30
|
+
self.name = name
|
31
|
+
self.cascade = cascade
|
32
|
+
self.if_exists = if_exists
|
33
|
+
|
34
|
+
@compiles(DropView)
|
35
|
+
def compile_drop_view(element, compiler, **kwargs):
|
36
|
+
return "DROP VIEW %s%s%s" % (
|
37
|
+
"IF EXISTS " if element.if_exists else "",
|
38
|
+
element.name,
|
39
|
+
" CASCADE" if element.cascade else ""
|
40
|
+
)
|
41
|
+
|
42
|
+
class ViewBase(ModelBase):
|
43
|
+
__view_selectable__ = None
|
44
|
+
__abstract__ = True
|
45
|
+
|
46
|
+
@classmethod
|
47
|
+
def create_view(cls, target, connection, **kwargs):
|
48
|
+
if cls.__view_selectable__ is None:
|
49
|
+
raise NotImplementedError("No selectable defined for view. Please define a class variable \"__view_selectable__\"")
|
50
|
+
view = CreateView(cls.__tablename__, cls.__view_selectable__)
|
51
|
+
connection.execute(view)
|
52
|
+
connection.commit()
|
53
|
+
|
54
|
+
@classmethod
|
55
|
+
def drop_view(cls, target, connection, **kwargs):
|
56
|
+
drop = DropView(cls.__tablename__, if_exists=True, cascade=True)
|
57
|
+
connection.execute(drop)
|
58
|
+
connection.commit()
|
59
|
+
|
60
|
+
def __init_subclass__(cls, **kwargs):
|
61
|
+
super().__init_subclass__(**kwargs)
|
62
|
+
cls.metadata._remove_table(
|
63
|
+
cls.__tablename__,
|
64
|
+
cls.__table_args__.get("schema", "public"))
|
65
|
+
sa.event.listen(cls.metadata, 'after_create', cls.create_view)
|
66
|
+
sa.event.listen(cls.metadata, 'before_drop', cls.drop_view)
|
67
|
+
|
68
|
+
# add a views section to metadata
|
69
|
+
if hasattr(cls, "__view_selectable__"):
|
70
|
+
if not hasattr(cls.metadata, "views"):
|
71
|
+
cls.metadata.views = [cls]
|
72
|
+
elif cls not in cls.metadata.views:
|
73
|
+
cls.metadata.views.append(cls)
|
74
|
+
|
75
|
+
# declare all database views
|
76
|
+
# --------------------------
|
77
|
+
class StationMATimeserieRasterQuotientView(ViewBase):
|
78
|
+
__tablename__ = 'station_ma_timeseries_raster_quotient_view'
|
79
|
+
__table_args__ = dict(
|
80
|
+
schema='public',
|
81
|
+
comment="The multi annual mean values of the stations timeseries divided by the multi annual raster values for the maximum available timespan.",
|
82
|
+
extend_existing = True)
|
83
|
+
|
84
|
+
station_id: Mapped[int] = mapped_column(
|
85
|
+
primary_key=True,
|
86
|
+
comment="The DWD-ID of the station.")
|
87
|
+
parameter: Mapped[str] = mapped_column(
|
88
|
+
primary_key=True,
|
89
|
+
comment="The parameter of the station. e.g. 'p', 'et'")
|
90
|
+
kind: Mapped[str] = mapped_column(
|
91
|
+
primary_key=True,
|
92
|
+
comment="The kind of the timeserie. e.g. 'raw', 'filled', 'corr'")
|
93
|
+
raster_key: Mapped[str] = mapped_column(
|
94
|
+
primary_key=True,
|
95
|
+
comment="The name of the raster. e.g. 'dwd' or 'hyras'")
|
96
|
+
value: Mapped[float] = mapped_column(
|
97
|
+
comment="The multi annual value of the yearly mean value of the station to the multi annual mean value of the raster.")
|
98
|
+
|
99
|
+
__view_selectable__ = sa\
|
100
|
+
.select(
|
101
|
+
StationMATimeserie.station_id,
|
102
|
+
StationMATimeserie.parameter,
|
103
|
+
StationMATimeserie.kind,
|
104
|
+
StationMARaster.raster_key,
|
105
|
+
StationMARaster.term,
|
106
|
+
sa.case(
|
107
|
+
(StationMARaster.value is not None,
|
108
|
+
StationMATimeserie.value / StationMARaster.value),
|
109
|
+
else_=None).label("value")
|
110
|
+
).select_from(
|
111
|
+
StationMATimeserie.__table__.outerjoin(
|
112
|
+
StationMARaster.__table__,
|
113
|
+
sa.and_(
|
114
|
+
StationMATimeserie.station_id == StationMARaster.station_id,
|
115
|
+
StationMATimeserie.parameter == StationMARaster.parameter,
|
116
|
+
StationMARaster.term == "year"
|
117
|
+
)
|
118
|
+
)
|
119
|
+
).where(
|
120
|
+
StationMATimeserie.parameter.in_(["p", "et"])
|
121
|
+
)
|
122
|
+
|
123
|
+
class StationKindQuotientView(ViewBase):
|
124
|
+
__tablename__ = 'station_kind_quotient_view'
|
125
|
+
__table_args__ = dict(
|
126
|
+
schema='public',
|
127
|
+
comment="The quotient between different kinds of multi annual mean timeseries values.",
|
128
|
+
extend_existing = True)
|
129
|
+
|
130
|
+
station_id: Mapped[int] = mapped_column(
|
131
|
+
primary_key=True,
|
132
|
+
comment="The DWD-ID of the station.")
|
133
|
+
parameter: Mapped[str] = mapped_column(
|
134
|
+
primary_key=True,
|
135
|
+
comment="The parameter of the station. e.g. 'p', 'p_d', 'et'")
|
136
|
+
kind_numerator: Mapped[str] = mapped_column(
|
137
|
+
primary_key=True,
|
138
|
+
comment="The kind of the timeserie for the numerator. e.g. 'raw', 'filled', 'corr'")
|
139
|
+
kind_denominator: Mapped[str] = mapped_column(
|
140
|
+
primary_key=True,
|
141
|
+
comment="The kind of the timeserie for the denominator. e.g. 'raw', 'filled', 'corr'")
|
142
|
+
value: Mapped[float] = mapped_column(
|
143
|
+
comment="The quotient between the numerator and the nominator kind of the complete timeserie.")
|
144
|
+
|
145
|
+
__view_selectable__ = sa\
|
146
|
+
.select(
|
147
|
+
(smt1:=sa.orm.aliased(StationMATimeserie, name="smt1")).station_id,
|
148
|
+
smt1.parameter,
|
149
|
+
smt1.kind.label("kind_numerator"),
|
150
|
+
(smt2:=sa.orm.aliased(StationMATimeserie, name="smt2")).kind.label("kind_denominator"),
|
151
|
+
(smt1.value/smt2.value).label("value")
|
152
|
+
).select_from(
|
153
|
+
sa.join(
|
154
|
+
smt1,
|
155
|
+
smt2,
|
156
|
+
sa.and_(
|
157
|
+
smt1.station_id == smt2.station_id,
|
158
|
+
smt1.parameter == smt2.parameter
|
159
|
+
)
|
160
|
+
)
|
161
|
+
).where(
|
162
|
+
sa.and_(smt1.parameter.in_(["p", "p_d", "et"]),
|
163
|
+
smt1.kind != smt2.kind,
|
164
|
+
)
|
165
|
+
)
|