weatherdb 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. docker/Dockerfile +30 -0
  2. docker/docker-compose.yaml +58 -0
  3. docker/docker-compose_test.yaml +24 -0
  4. docker/start-docker-test.sh +6 -0
  5. docs/requirements.txt +10 -0
  6. docs/source/Changelog.md +2 -0
  7. docs/source/License.rst +7 -0
  8. docs/source/Methode.md +161 -0
  9. docs/source/_static/custom.css +8 -0
  10. docs/source/_static/favicon.ico +0 -0
  11. docs/source/_static/logo.png +0 -0
  12. docs/source/api/api.rst +15 -0
  13. docs/source/api/cli.rst +8 -0
  14. docs/source/api/weatherDB.broker.rst +10 -0
  15. docs/source/api/weatherDB.config.rst +7 -0
  16. docs/source/api/weatherDB.db.rst +23 -0
  17. docs/source/api/weatherDB.rst +22 -0
  18. docs/source/api/weatherDB.station.rst +56 -0
  19. docs/source/api/weatherDB.stations.rst +46 -0
  20. docs/source/api/weatherDB.utils.rst +22 -0
  21. docs/source/conf.py +137 -0
  22. docs/source/index.rst +33 -0
  23. docs/source/setup/Configuration.md +127 -0
  24. docs/source/setup/Hosting.md +9 -0
  25. docs/source/setup/Install.md +49 -0
  26. docs/source/setup/Quickstart.md +183 -0
  27. docs/source/setup/setup.rst +12 -0
  28. weatherdb/__init__.py +24 -0
  29. weatherdb/_version.py +1 -0
  30. weatherdb/alembic/README.md +8 -0
  31. weatherdb/alembic/alembic.ini +80 -0
  32. weatherdb/alembic/config.py +9 -0
  33. weatherdb/alembic/env.py +100 -0
  34. weatherdb/alembic/script.py.mako +26 -0
  35. weatherdb/alembic/versions/V1.0.0_initial_database_creation.py +898 -0
  36. weatherdb/alembic/versions/V1.0.2_more_charachters_for_settings+term_station_ma_raster.py +88 -0
  37. weatherdb/alembic/versions/V1.0.5_fix-ma-raster-values.py +152 -0
  38. weatherdb/alembic/versions/V1.0.6_update-views.py +22 -0
  39. weatherdb/broker.py +667 -0
  40. weatherdb/cli.py +214 -0
  41. weatherdb/config/ConfigParser.py +663 -0
  42. weatherdb/config/__init__.py +5 -0
  43. weatherdb/config/config_default.ini +162 -0
  44. weatherdb/db/__init__.py +3 -0
  45. weatherdb/db/connections.py +374 -0
  46. weatherdb/db/fixtures/RichterParameters.json +34 -0
  47. weatherdb/db/models.py +402 -0
  48. weatherdb/db/queries/get_quotient.py +155 -0
  49. weatherdb/db/views.py +165 -0
  50. weatherdb/station/GroupStation.py +710 -0
  51. weatherdb/station/StationBases.py +3108 -0
  52. weatherdb/station/StationET.py +111 -0
  53. weatherdb/station/StationP.py +807 -0
  54. weatherdb/station/StationPD.py +98 -0
  55. weatherdb/station/StationT.py +164 -0
  56. weatherdb/station/__init__.py +13 -0
  57. weatherdb/station/constants.py +21 -0
  58. weatherdb/stations/GroupStations.py +519 -0
  59. weatherdb/stations/StationsBase.py +1021 -0
  60. weatherdb/stations/StationsBaseTET.py +30 -0
  61. weatherdb/stations/StationsET.py +17 -0
  62. weatherdb/stations/StationsP.py +128 -0
  63. weatherdb/stations/StationsPD.py +24 -0
  64. weatherdb/stations/StationsT.py +21 -0
  65. weatherdb/stations/__init__.py +11 -0
  66. weatherdb/utils/TimestampPeriod.py +369 -0
  67. weatherdb/utils/__init__.py +3 -0
  68. weatherdb/utils/dwd.py +350 -0
  69. weatherdb/utils/geometry.py +69 -0
  70. weatherdb/utils/get_data.py +285 -0
  71. weatherdb/utils/logging.py +126 -0
  72. weatherdb-1.1.0.dist-info/LICENSE +674 -0
  73. weatherdb-1.1.0.dist-info/METADATA +765 -0
  74. weatherdb-1.1.0.dist-info/RECORD +77 -0
  75. weatherdb-1.1.0.dist-info/WHEEL +5 -0
  76. weatherdb-1.1.0.dist-info/entry_points.txt +2 -0
  77. 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
+ )