weatherdb 1.1.1__tar.gz → 1.1.2__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. {weatherdb-1.1.1 → weatherdb-1.1.2}/.gitlab-ci.yml +1 -0
  2. {weatherdb-1.1.1 → weatherdb-1.1.2}/CHANGES.md +8 -2
  3. {weatherdb-1.1.1 → weatherdb-1.1.2}/PKG-INFO +1 -1
  4. weatherdb-1.1.2/weatherdb/_version.py +1 -0
  5. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/cli.py +18 -3
  6. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/station/GroupStation.py +3 -1
  7. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/station/StationBases.py +5 -3
  8. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/utils/get_data.py +204 -40
  9. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb.egg-info/PKG-INFO +1 -1
  10. weatherdb-1.1.1/weatherdb/_version.py +0 -1
  11. {weatherdb-1.1.1 → weatherdb-1.1.2}/.dockerignore +0 -0
  12. {weatherdb-1.1.1 → weatherdb-1.1.2}/.github/workflows/cleanup-cache.yml +0 -0
  13. {weatherdb-1.1.1 → weatherdb-1.1.2}/.github/workflows/python-publish.yml +0 -0
  14. {weatherdb-1.1.1 → weatherdb-1.1.2}/.github/workflows/python-test.yml +0 -0
  15. {weatherdb-1.1.1 → weatherdb-1.1.2}/.gitignore +0 -0
  16. {weatherdb-1.1.1 → weatherdb-1.1.2}/.gitlab/merge_request_templates/new_version.md +0 -0
  17. {weatherdb-1.1.1 → weatherdb-1.1.2}/.readthedocs.yaml +0 -0
  18. {weatherdb-1.1.1 → weatherdb-1.1.2}/LICENSE +0 -0
  19. {weatherdb-1.1.1 → weatherdb-1.1.2}/MANIFEST.in +0 -0
  20. {weatherdb-1.1.1 → weatherdb-1.1.2}/README.md +0 -0
  21. {weatherdb-1.1.1 → weatherdb-1.1.2}/docker/Dockerfile +0 -0
  22. {weatherdb-1.1.1 → weatherdb-1.1.2}/docker/docker-compose.yaml +0 -0
  23. {weatherdb-1.1.1 → weatherdb-1.1.2}/docker/docker-compose_test.yaml +0 -0
  24. {weatherdb-1.1.1 → weatherdb-1.1.2}/docker/start-docker-test.sh +0 -0
  25. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/requirements.txt +0 -0
  26. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/Changelog.md +0 -0
  27. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/License.rst +0 -0
  28. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/Methode.md +0 -0
  29. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/_static/custom.css +0 -0
  30. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/_static/favicon.ico +0 -0
  31. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/_static/logo.png +0 -0
  32. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/api.rst +0 -0
  33. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/cli.rst +0 -0
  34. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/weatherDB.broker.rst +0 -0
  35. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/weatherdb.config.rst +0 -0
  36. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/weatherdb.db.rst +0 -0
  37. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/weatherdb.rst +0 -0
  38. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/weatherdb.station.rst +0 -0
  39. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/weatherdb.stations.rst +0 -0
  40. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/api/weatherdb.utils.rst +0 -0
  41. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/conf.py +0 -0
  42. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/index.rst +0 -0
  43. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/setup/Configuration.md +0 -0
  44. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/setup/Hosting.md +0 -0
  45. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/setup/Install.md +0 -0
  46. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/setup/Quickstart.md +0 -0
  47. {weatherdb-1.1.1 → weatherdb-1.1.2}/docs/source/setup/setup.rst +0 -0
  48. {weatherdb-1.1.1 → weatherdb-1.1.2}/pyproject.toml +0 -0
  49. {weatherdb-1.1.1 → weatherdb-1.1.2}/setup.cfg +0 -0
  50. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherDB.egg-info/PKG-INFO +0 -0
  51. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherDB.egg-info/SOURCES.txt +0 -0
  52. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherDB.egg-info/dependency_links.txt +0 -0
  53. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherDB.egg-info/entry_points.txt +0 -0
  54. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherDB.egg-info/requires.txt +0 -0
  55. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherDB.egg-info/top_level.txt +0 -0
  56. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/__init__.py +0 -0
  57. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/README.md +0 -0
  58. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/alembic.ini +0 -0
  59. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/config.py +0 -0
  60. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/env.py +0 -0
  61. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/script.py.mako +0 -0
  62. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/versions/V1.0.0_initial_database_creation.py +0 -0
  63. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/versions/V1.0.2_more_charachters_for_settings+term_station_ma_raster.py +0 -0
  64. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/versions/V1.0.5_fix-ma-raster-values.py +0 -0
  65. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/alembic/versions/V1.0.6_update-views.py +0 -0
  66. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/broker.py +0 -0
  67. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/config/ConfigParser.py +0 -0
  68. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/config/__init__.py +0 -0
  69. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/config/config_default.ini +0 -0
  70. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/db/__init__.py +0 -0
  71. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/db/connections.py +0 -0
  72. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/db/fixtures/RichterParameters.json +0 -0
  73. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/db/models.py +0 -0
  74. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/db/queries/get_quotient.py +0 -0
  75. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/db/views.py +0 -0
  76. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/station/StationET.py +0 -0
  77. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/station/StationP.py +0 -0
  78. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/station/StationPD.py +0 -0
  79. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/station/StationT.py +0 -0
  80. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/station/__init__.py +0 -0
  81. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/station/constants.py +0 -0
  82. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/stations/GroupStations.py +0 -0
  83. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/stations/StationsBase.py +0 -0
  84. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/stations/StationsBaseTET.py +0 -0
  85. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/stations/StationsET.py +0 -0
  86. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/stations/StationsP.py +0 -0
  87. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/stations/StationsPD.py +0 -0
  88. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/stations/StationsT.py +0 -0
  89. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/stations/__init__.py +0 -0
  90. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/utils/TimestampPeriod.py +0 -0
  91. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/utils/__init__.py +0 -0
  92. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/utils/dwd.py +0 -0
  93. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/utils/geometry.py +0 -0
  94. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb/utils/logging.py +0 -0
  95. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb.egg-info/SOURCES.txt +0 -0
  96. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb.egg-info/dependency_links.txt +0 -0
  97. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb.egg-info/entry_points.txt +0 -0
  98. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb.egg-info/requires.txt +0 -0
  99. {weatherdb-1.1.1 → weatherdb-1.1.2}/weatherdb.egg-info/top_level.txt +0 -0
@@ -65,6 +65,7 @@ test_single:
65
65
  WEATHERDB_TEST_ARTIFACT_DB_DUMP: ON_FAILURE
66
66
  WEATHERDB_TEST_ARTIFACT_LIST_DATA_FILES: ON_FAILURE
67
67
  WEATHERDB_TEST_ARTIFACT_COPY_USER_CONFIG: ON_FAILURE
68
+ WEATHERDB_OPENTOPO_API_KEY: $WEATHERDB_OPENTOPO_API_KEY
68
69
  DOCKER_ENV: test
69
70
  tags:
70
71
  - docker
@@ -1,8 +1,14 @@
1
1
  # Change-log
2
2
 
3
- ## Version 1.0.1
3
+ ## Version 1.1.2
4
+
5
+ - add method to download DEM data from OpenTopography-API
6
+ - update StationBase._expand_timeserie_to_period to remove entries that are older than the min_date config to remove unnessecary database entries
7
+ - fix GroupStation.create_ts: don't throw period changed warning if the change was only due to the expand_to_timestamp output
8
+
9
+ ## Version 1.1.1
4
10
 
5
- - minor fixes to fix previous version
11
+ - minor fixes to fix previous version
6
12
 
7
13
  ## Version 1.1.0
8
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: weatherdb
3
- Version: 1.1.1
3
+ Version: 1.1.2
4
4
  Summary: This is a package to work with and to create the Weather Database which handles, checks, fills and corrects DWD Weather Station data.
5
5
  Author-email: Max Schmit <max.schmit@hydrology.uni-freiburg.de>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -0,0 +1 @@
1
+ __version__ = "1.1.2"
@@ -103,10 +103,16 @@ def download_ma_rasters(which, overwrite, update_user_config):
103
103
  """
104
104
  click.echo("starting downloading multi annual raster data")
105
105
  from weatherdb.utils.get_data import download_ma_rasters
106
- download_ma_rasters(overwrite=overwrite)
106
+ download_ma_rasters(
107
+ which=which,
108
+ overwrite=overwrite,
109
+ update_user_config=update_user_config)
107
110
 
108
111
 
109
112
  @cli.command(short_help="Download the needed digital elevation model raster data from Copernicus to the data folder.")
113
+ @click.option('--out-dir', '-d',
114
+ type=click.Path(), default=None, show_default=False,
115
+ help="The directory to save the downloaded DEM data to.")
110
116
  @click.option('--overwrite/--no-overwrite', '-o/-no-o',
111
117
  type=bool, is_flag=True, default=None, show_default=False,
112
118
  help="Should the digital elevation model raster be downloaded even if it already exists?")
@@ -116,7 +122,11 @@ def download_ma_rasters(which, overwrite, update_user_config):
116
122
  @click.option("--update-user-config", "-u",
117
123
  type=bool, default=False, show_default=True, is_flag=True,
118
124
  help="Should the user configuration be updated with the path to the downloaded DEM?")
119
- def download_dem(overwrite, extent):
125
+ @click.option("--service", "-s",
126
+ type=str, default=["prism", "openTopography"], show_default=True, multiple=True,
127
+ help="The service to use to download the DEM. Options are 'prism' or 'openTopography'. " +\
128
+ "You can use this option muultiple times to test both in the given order until the file could be downloaded.")
129
+ def download_dem(out_dir, overwrite, extent, update_user_config, service="prism"):
120
130
  """Download the newest DEM data from the Copernicus Sentinel dataset.
121
131
 
122
132
  Only the GLO-30 DEM, wich has a 30m resolution, is downloaded as it is freely available.
@@ -131,7 +141,12 @@ def download_dem(overwrite, extent):
131
141
  """
132
142
  click.echo("Starting downloading digital elevation model from Copernicus")
133
143
  from weatherdb.utils.get_data import download_dem
134
- download_dem(overwrite=overwrite, extent=extent)
144
+ download_dem(
145
+ out_dir=out_dir,
146
+ overwrite=overwrite,
147
+ extent=extent,
148
+ service=service,
149
+ update_user_config=update_user_config)
135
150
 
136
151
 
137
152
  # cli statements to update the database
@@ -526,7 +526,9 @@ class GroupStation(object):
526
526
  period_new = period_filled.union(
527
527
  period,
528
528
  how="inner")
529
- if period_new != period:
529
+ if period_new != period and not (
530
+ (period.start == period_new.start) and
531
+ ((period.end - period_new.end) <= pd.Timedelta(days=1))):
530
532
  warnings.warn(
531
533
  f"The Period for Station {self.id} got changed from {str(period)} to {str(period_new)}.")
532
534
  period = period_new
@@ -504,10 +504,12 @@ class StationBase:
504
504
  '{interval}'::INTERVAL)::{tstp_dtype} AS timestamp)
505
505
  INSERT INTO timeseries."{stid}_{para}"(timestamp)
506
506
  (SELECT wts.timestamp
507
- FROM whole_ts wts
508
- LEFT JOIN timeseries."{stid}_{para}" ts
507
+ FROM whole_ts wts
508
+ LEFT JOIN timeseries."{stid}_{para}" ts
509
509
  ON ts.timestamp=wts.timestamp
510
- WHERE ts.timestamp IS NULL);
510
+ WHERE ts.timestamp IS NULL);
511
+ DELETE FROM timeseries."{stid}_{para}"
512
+ WHERE timestamp < '{min_date} 00:00'::{tstp_dtype};
511
513
  """.format(
512
514
  stid=self.id,
513
515
  para=self._para,
@@ -6,9 +6,19 @@ from pathlib import Path
6
6
  from distutils.util import strtobool
7
7
  import hashlib
8
8
  import progressbar as pb
9
+ import keyring
10
+ import os
11
+ import getpass
12
+ import logging
9
13
 
10
14
  from ..config import config
11
15
 
16
+ __all__ = ["download_ma_rasters", "download_dem"]
17
+
18
+ log = logging.getLogger(__name__)
19
+
20
+ # Multi annual rasters
21
+ # --------------------
12
22
  def download_ma_rasters(which="all", overwrite=None, update_user_config=False):
13
23
  """Get the multi annual rasters on which bases the regionalisation is done.
14
24
 
@@ -60,7 +70,7 @@ def download_ma_rasters(which="all", overwrite=None, update_user_config=False):
60
70
  if file_key in which:
61
71
  # check if file is in config
62
72
  if f"data:rasters:{file_key}" not in config:
63
- print(f"Skipping {file_key} as it is not in your configuration.\nPlease add a section 'data:rasters:{file_key}' to your configuration file.")
73
+ log.debug(f"Skipping {file_key} as it is not in your configuration.\nPlease add a section 'data:rasters:{file_key}' to your configuration file.")
64
74
  continue
65
75
 
66
76
  # check if file already exists
@@ -75,7 +85,7 @@ def download_ma_rasters(which="all", overwrite=None, update_user_config=False):
75
85
  "Do you want to overwrite it? [y/n] "))
76
86
 
77
87
  if skip:
78
- print(f"Skipping {file_key} as overwriting is not allowed.")
88
+ log.debug(f"Skipping {file_key} as overwriting is not allowed.")
79
89
  continue
80
90
 
81
91
  # check if the directory exists
@@ -126,24 +136,42 @@ def download_ma_rasters(which="all", overwrite=None, update_user_config=False):
126
136
  if config.has_user_config:
127
137
  config.update_user_config(f"data:rasters:{file_key}", "file", str(file_path))
128
138
  else:
129
- print(f"No user configuration file found, therefor the raster '{file_key}' is not set in the user configuration file.")
139
+ log.error(f"No user configuration file found, therefor the raster '{file_key}' is not set in the user configuration file.")
130
140
 
141
+ # DEM data
142
+ # --------
143
+ def _check_write_fp(fp, overwrite):
144
+ """Check if a file exists and if it should be overwritten.
131
145
 
132
- def download_dem(overwrite=None, extent=(5.3, 46.1, 15.6, 55.4), update_user_config=False):
133
- """Download the newest DEM data from the Copernicus Sentinel dataset.
134
-
135
- Only the GLO-30 DEM, which has a 30m resolution, is downloaded as it is freely available.
136
- If you register as a scientific researcher also the EEA-10, with 10 m resolution, is available.
137
- You will have to download the data yourself and define it in the configuration file.
138
-
139
- After downloading the data, the files are merged and saved as a single tif file in the data directory in a subfolder called 'DEM'.
140
- To use the DEM data in the WeatherDB, you will have to define the path to the tif file in the configuration file.
146
+ Parameters
147
+ ----------
148
+ fp : str or Path
149
+ The path to the file to check.
150
+ overwrite : bool
151
+ Should the file be overwritten?
152
+
153
+ Returns
154
+ -------
155
+ bool
156
+ Should the file be written?
157
+ """
158
+ fp = Path(fp)
159
+ if fp.exists():
160
+ log.info(f"The file already exists at {fp}.")
161
+ if overwrite is None:
162
+ overwrite = strtobool(input(f"{fp} already exists. Do you want to overwrite it? [y/n] "))
163
+ if not overwrite:
164
+ log.info("Skipping, because overwritting was turned of.")
165
+ return False
166
+ return True
141
167
 
142
- Source:
143
- Copernicus DEM - Global and European Digital Elevation Model. Digital Surface Model (DSM) provided in 3 different resolutions (90m, 30m, 10m) with varying geographical extent (EEA: European and GLO: global) and varying format (INSPIRE, DGED, DTED). DOI:10.5270/ESA-c5d3d65.
168
+ def _download_dem_prism(out_dir, overwrite=None, extent=(5.3, 46.1, 15.6, 55.4)):
169
+ """Download the DEM data from the Copernicus PRISM service.
144
170
 
145
171
  Parameters
146
172
  ----------
173
+ out_dir: str or Path
174
+ The directory to save the DEM data to.
147
175
  overwrite : bool, optional
148
176
  Should the DEM data be downloaded even if it already exists?
149
177
  If None the user will be asked.
@@ -151,9 +179,11 @@ def download_dem(overwrite=None, extent=(5.3, 46.1, 15.6, 55.4), update_user_con
151
179
  extent : tuple, optional
152
180
  The extent in WGS84 of the DEM data to download.
153
181
  The default is the boundary of germany + ~40km = (5.3, 46.1, 15.6, 55.4).
154
- update_user_config : bool, optional
155
- Should the downloaded DEM be set as the used DEM in the user configuration file?
156
- The default is False.
182
+
183
+ Returns
184
+ -------
185
+ fp : Path
186
+ The path to the downloaded DEM file.
157
187
  """
158
188
  # import necessary modules
159
189
  import rasterio as rio
@@ -164,10 +194,8 @@ def download_dem(overwrite=None, extent=(5.3, 46.1, 15.6, 55.4), update_user_con
164
194
  import re
165
195
  import json
166
196
 
167
- # get dem_dir
168
- base_dir = Path(config.get("data", "base_dir"))
169
- dem_dir = base_dir / "DEM"
170
- dem_dir.mkdir(parents=True, exist_ok=True)
197
+ # check dir
198
+ out_dir = Path(out_dir)
171
199
 
172
200
  # get available datasets
173
201
  prism_url = "https://prism-dem-open.copernicus.eu/pd-desk-open-access/publicDemURLs"
@@ -191,20 +219,12 @@ def download_dem(overwrite=None, extent=(5.3, 46.1, 15.6, 55.4), update_user_con
191
219
  )[-1]["id"]
192
220
 
193
221
  # check if dataset already exists
194
- dem_file = dem_dir / f'{ds_id.replace("/", "__")}.tif'
195
- if dem_file.exists():
196
- print(f"The DEM data already exists at {dem_file}.")
197
- if overwrite is None:
198
- overwrite = strtobool(input("Do you want to overwrite it? [y/n] "))
199
- if not overwrite:
200
- print("Skipping, because overwritting was turned of.")
201
- return
202
- else:
203
- print("Overwriting the dataset.")
204
- dem_dir.mkdir(exist_ok=True)
222
+ dem_file = out_dir / f'{ds_id.replace("/", "__")}.tif'
223
+ if not _check_write_fp(dem_file, overwrite):
224
+ return
205
225
 
206
226
  # selecting DEM tiles
207
- print(f"getting available tiles for Copernicus dataset '{ds_id}'")
227
+ log.info(f"getting available tiles for Copernicus dataset '{ds_id}'")
208
228
  ds_files_req = json.loads(
209
229
  requests.get(
210
230
  f"{prism_url}/{ds_id.replace('/', '__')}",
@@ -225,13 +245,13 @@ def download_dem(overwrite=None, extent=(5.3, 46.1, 15.6, 55.4), update_user_con
225
245
  ds_files_all))
226
246
 
227
247
  # download DEM tiles
228
- print("downloading tiles")
248
+ log.info("downloading tiles")
229
249
  with TemporaryDirectory() as tmp_dir:
230
250
  tmp_dir_fp = Path(tmp_dir)
231
251
  for f in pb.progressbar(ds_files):
232
252
  with open(tmp_dir_fp / Path(f["nativeDemUrl"]).name, "wb") as d:
233
253
  d.write(requests.get(f["nativeDemUrl"]).content)
234
- print("downloaded all files")
254
+ log.info("downloaded all files")
235
255
 
236
256
  # extracting tifs from tars
237
257
  for i, f in pb.progressbar(list(enumerate(tmp_dir_fp.glob("*.tar")))):
@@ -269,17 +289,161 @@ def download_dem(overwrite=None, extent=(5.3, 46.1, 15.6, 55.4), update_user_con
269
289
  tmp_eula_fp = next(tmp_dir_fp.glob("*.pdf"))
270
290
  shutil.copyfile(
271
291
  tmp_eula_fp,
272
- dem_dir / tmp_eula_fp.name
292
+ out_dir / tmp_eula_fp.name
273
293
  )
274
294
 
275
- print(f"created DEM at '{dem_file}'.")
295
+ log.info(f"created DEM at '{dem_file}'.")
296
+ return dem_file
297
+
298
+ def _download_dem_opentopo(
299
+ out_dir,
300
+ overwrite=None,
301
+ extent=(5.3, 46.1, 15.6, 55.4),
302
+ api_key=os.environ.get(
303
+ "WEATHERDB_OPENTOPO_API_KEY",
304
+ fallback=keyring.get_password("weatherdb", "opentopo_api_key"))):
305
+ """Download the DEM data from the OpenTopography service.
306
+
307
+ Get an API key from (OpenTopography)[https://portal.opentopography.org/] to use this service.
308
+
309
+ Parameters
310
+ ----------
311
+ out_dir : str or Path
312
+ The directory to save the DEM data to.
313
+ overwrite : bool, optional
314
+ Should the DEM data be downloaded even if it already exists?
315
+ If None the user will be asked.
316
+ The default is None.
317
+ extent : tuple, optional
318
+ The extent in WGS84 of the DEM data to download.
319
+ Should be in the format (south, west, north, east).
320
+ The default is the boundary of germany + ~40km = (5.3, 46.1, 15.6, 55.4).
321
+ api_key : str, optional
322
+ The API key for the OpenTopography service.
323
+ If None the user will be asked.
324
+ The default is to check if the environment variable "WEATHERDB_OPENTOPO_API_KEY" is set or if the keyring has a password for "weatherdb" and "opentopo_api_key".
325
+
326
+ Returns
327
+ -------
328
+ fp : Path
329
+ The path to the downloaded DEM file.
330
+ """
331
+ # check api key
332
+ if api_key is None:
333
+ print("No API key for OpenTopography was given or found in the keyring or environment variable.")
334
+ api_key = getpass("Please enter your API key for OpenTopography: ")
335
+
336
+ # make query
337
+ w, s, e, n = extent
338
+ url = f"https://portal.opentopography.org/API/globaldem?demtype=COP30&west={w}&south={s}&east={e}&north={n}&outputFormat=GTiff&API_Key={api_key}"
339
+ r = requests.get(url)
340
+ if r.status_code == 200:
341
+ # store api key
342
+ if api_key != keyring.get_password("weatherdb", "opentopo_api_key"):
343
+ keyring.set_password("weatherdb", "opentopo_api_key", api_key)
344
+
345
+ # get dem file
346
+ out_fp = out_dir / "OpenTopo_COP30.tif"
347
+
348
+ # check if file already exists
349
+ if not _check_write_fp(out_fp, overwrite):
350
+ return
351
+
352
+ # download file
353
+ with open(out_fp, "wb") as f:
354
+ for chunk in r.iter_content(chunk_size=1024):
355
+ f.write(chunk)
356
+ log.info(f"Downloaded DEM data from OpenTopography to '{out_fp}'.")
357
+ return out_fp
358
+
359
+ log.error(f"Request to openTopography API with url {r.url.replace(api_key, "[MASKED]")} returned status code {r.status_code}")
360
+
361
+ def download_dem(out_dir=None,
362
+ overwrite=None,
363
+ extent=(5.3, 46.1, 15.6, 55.4),
364
+ update_user_config=False,
365
+ service=["prism", "openTopography"], **kwargs):
366
+ """Download the newest DEM data from the Copernicus Sentinel dataset.
367
+
368
+ Only the GLO-30 DEM, which has a 30m resolution, is downloaded as it is freely available.
369
+ If you register as a scientific researcher also the EEA-10, with 10 m resolution, is available.
370
+ You will have to download the data yourself and define it in the configuration file.
371
+
372
+ After downloading the data, the files are merged and saved as a single tif file in the data directory in a subfolder called 'DEM'.
373
+ To use the DEM data in the WeatherDB, you will have to define the path to the tif file in the configuration file.
374
+
375
+ Source:
376
+ Copernicus DEM - Global and European Digital Elevation Model. Digital Surface Model (DSM) provided in 3 different resolutions (90m, 30m, 10m) with varying geographical extent (EEA: European and GLO: global) and varying format (INSPIRE, DGED, DTED). DOI:10.5270/ESA-c5d3d65.
377
+
378
+ Parameters
379
+ ----------
380
+ out_dir : str or Path, optional
381
+ The directory to save the DEM data to.
382
+ If None the data is saved in the data directory in a subfolder called 'DEM'.
383
+ The default is None.
384
+ overwrite : bool, optional
385
+ Should the DEM data be downloaded even if it already exists?
386
+ If None the user will be asked.
387
+ The default is None.
388
+ extent : tuple, optional
389
+ The extent in WGS84 of the DEM data to download.
390
+ The default is the boundary of germany + ~40km = (5.3, 46.1, 15.6, 55.4).
391
+ update_user_config : bool, optional
392
+ Should the downloaded DEM be set as the used DEM in the user configuration file?
393
+ The default is False.
394
+ service : str or list of str, optional
395
+ The service to use to download the DEM data.
396
+ Options are "prism" and "openTopography".
397
+ If Both are given they are executed in the order they are given.
398
+ If OpenTopography is selected, you will have to provide an API key.
399
+ The default is ["prism", "openTopography"].
400
+ """
401
+ # check service
402
+ if isinstance(service, str):
403
+ service = [service]
404
+
405
+ # check dir
406
+ if out_dir is None:
407
+ out_dir = Path(config.get("data", "base_dir")) / "DEM"
408
+ else:
409
+ out_dir = Path(out_dir)
410
+ out_dir.mkdir(parents=True, exist_ok=True)
411
+
412
+ # download data
413
+ fp=None
414
+ for s in service:
415
+ if s == "prism":
416
+ try:
417
+ fp = _download_dem_prism(
418
+ out_dir=out_dir,
419
+ overwrite=overwrite,
420
+ extent=extent,
421
+ **kwargs)
422
+ break
423
+ except Exception as e:
424
+ log.debug(f"Error while downloading DEM from PRISM: {e}")
425
+ elif s == "openTopography":
426
+ try:
427
+ fp = _download_dem_opentopo(
428
+ out_dir=out_dir,
429
+ overwrite=overwrite,
430
+ extent=extent,
431
+ **kwargs)
432
+ break
433
+ except Exception as e:
434
+ log.debug(f"Error while downloading DEM from OpenTopography: {e}")
435
+
436
+ # check if file was downloaded
437
+ if fp is None:
438
+ log.error("No DEM data was downloaded.")
439
+ return
276
440
 
277
441
  # update user config
278
442
  if update_user_config:
279
443
  if config.has_user_config:
280
- config.update_user_config("data:rasters", "dems", str(dem_file))
444
+ config.update_user_config("data:rasters", "dems", str(fp))
281
445
  return
282
446
  else:
283
- print("No user configuration file found, therefor the DEM is not set in the user configuration file.")
447
+ log.info("No user configuration file found, therefor the DEM is not set in the user configuration file.")
284
448
 
285
- print("To use the DEM data in the WeatherDB, you will have to define the path to the tif file in the user configuration file.")
449
+ log.info("To use the DEM data in the WeatherDB, you will have to define the path to the tif file in the user configuration file.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: weatherdb
3
- Version: 1.1.1
3
+ Version: 1.1.2
4
4
  Summary: This is a package to work with and to create the Weather Database which handles, checks, fills and corrects DWD Weather Station data.
5
5
  Author-email: Max Schmit <max.schmit@hydrology.uni-freiburg.de>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -1 +0,0 @@
1
- __version__ = "1.1.1"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes