wrfrun 0.2.0__py3-none-any.whl → 0.3.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.
- wrfrun/__init__.py +8 -3
- wrfrun/cli.py +69 -29
- wrfrun/core/__init__.py +27 -10
- wrfrun/core/_config.py +308 -0
- wrfrun/core/_constant.py +236 -0
- wrfrun/core/_exec_db.py +105 -0
- wrfrun/core/_namelist.py +287 -0
- wrfrun/core/_record.py +178 -0
- wrfrun/core/_resource.py +172 -0
- wrfrun/core/base.py +132 -406
- wrfrun/core/core.py +196 -0
- wrfrun/core/error.py +28 -2
- wrfrun/core/replay.py +10 -96
- wrfrun/core/server.py +52 -27
- wrfrun/core/type.py +171 -0
- wrfrun/data.py +304 -139
- wrfrun/extension/goos_sst/__init__.py +2 -2
- wrfrun/extension/goos_sst/core.py +9 -14
- wrfrun/extension/goos_sst/res/__init__.py +0 -1
- wrfrun/extension/goos_sst/utils.py +50 -44
- wrfrun/extension/littler/core.py +105 -88
- wrfrun/extension/utils.py +4 -3
- wrfrun/log.py +117 -0
- wrfrun/model/__init__.py +11 -7
- wrfrun/model/constants.py +52 -0
- wrfrun/model/palm/__init__.py +30 -0
- wrfrun/model/palm/core.py +145 -0
- wrfrun/model/palm/namelist.py +33 -0
- wrfrun/model/plot.py +99 -119
- wrfrun/model/type.py +116 -0
- wrfrun/model/utils.py +9 -20
- wrfrun/model/wrf/__init__.py +4 -9
- wrfrun/model/wrf/core.py +246 -161
- wrfrun/model/wrf/exec_wrap.py +13 -12
- wrfrun/model/wrf/geodata.py +116 -100
- wrfrun/model/wrf/log.py +103 -0
- wrfrun/model/wrf/namelist.py +90 -73
- wrfrun/model/wrf/plot.py +102 -0
- wrfrun/model/wrf/scheme.py +108 -52
- wrfrun/model/wrf/utils.py +39 -25
- wrfrun/model/wrf/vtable.py +35 -3
- wrfrun/plot/__init__.py +20 -0
- wrfrun/plot/wps.py +90 -73
- wrfrun/res/__init__.py +103 -5
- wrfrun/res/config/config.template.toml +8 -0
- wrfrun/res/config/palm.template.toml +23 -0
- wrfrun/run.py +105 -77
- wrfrun/scheduler/__init__.py +1 -0
- wrfrun/scheduler/lsf.py +3 -2
- wrfrun/scheduler/pbs.py +3 -2
- wrfrun/scheduler/script.py +17 -5
- wrfrun/scheduler/slurm.py +3 -2
- wrfrun/scheduler/utils.py +14 -2
- wrfrun/utils.py +88 -199
- wrfrun/workspace/__init__.py +8 -5
- wrfrun/workspace/core.py +20 -12
- wrfrun/workspace/palm.py +137 -0
- wrfrun/workspace/wrf.py +16 -15
- wrfrun-0.3.0.dist-info/METADATA +240 -0
- wrfrun-0.3.0.dist-info/RECORD +78 -0
- wrfrun/core/config.py +0 -923
- wrfrun/model/base.py +0 -14
- wrfrun-0.2.0.dist-info/METADATA +0 -68
- wrfrun-0.2.0.dist-info/RECORD +0 -62
- {wrfrun-0.2.0.dist-info → wrfrun-0.3.0.dist-info}/WHEEL +0 -0
- {wrfrun-0.2.0.dist-info → wrfrun-0.3.0.dist-info}/entry_points.txt +0 -0
wrfrun/data.py
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.data
|
|
3
|
+
###########
|
|
4
|
+
|
|
5
|
+
.. autosummary::
|
|
6
|
+
:toctree: generated/
|
|
7
|
+
|
|
8
|
+
ERA5CONFIG
|
|
9
|
+
_check_variables_and_datasets
|
|
10
|
+
_check_pressure_level
|
|
11
|
+
find_era5_data
|
|
12
|
+
prepare_wps_input_data
|
|
13
|
+
download_data
|
|
14
|
+
"""
|
|
15
|
+
|
|
1
16
|
from datetime import datetime
|
|
2
17
|
from os import makedirs
|
|
3
18
|
from os.path import dirname, exists
|
|
4
|
-
from typing import List, Tuple, Union
|
|
19
|
+
from typing import List, Literal, Tuple, Union
|
|
5
20
|
|
|
6
21
|
from pandas import date_range
|
|
7
22
|
|
|
8
|
-
from .core import
|
|
9
|
-
from .
|
|
23
|
+
from .core import WRFRUN
|
|
24
|
+
from .log import logger
|
|
10
25
|
|
|
11
26
|
# from seafog import goos_sst_find_data
|
|
12
27
|
|
|
@@ -17,6 +32,68 @@ CDS_CLIENT = None
|
|
|
17
32
|
class ERA5CONFIG:
|
|
18
33
|
"""
|
|
19
34
|
A class to store parameters we will use to download ERA5 data from cdsapi.
|
|
35
|
+
|
|
36
|
+
.. py:attribute:: DATASET_ERA5_SINGLE_LEVEL
|
|
37
|
+
:type: str
|
|
38
|
+
:value: "reanalysis-era5-single-levels"
|
|
39
|
+
|
|
40
|
+
ERA5 dataset type.
|
|
41
|
+
|
|
42
|
+
.. py:attribute:: DATASET_ERA5_PRESSURE_LEVEL
|
|
43
|
+
:type: str
|
|
44
|
+
:value: "reanalysis-era5-pressure-levels"
|
|
45
|
+
|
|
46
|
+
ERA5 dataset type.
|
|
47
|
+
|
|
48
|
+
.. py:attribute:: TYPE_REANALYSIS
|
|
49
|
+
:type: str
|
|
50
|
+
:value: "reanalysis"
|
|
51
|
+
|
|
52
|
+
ERA5 product type.
|
|
53
|
+
|
|
54
|
+
.. py:attribute:: FORMAT_NETCDF
|
|
55
|
+
:type: str
|
|
56
|
+
:value: "netcdf"
|
|
57
|
+
|
|
58
|
+
ERA5 data format type.
|
|
59
|
+
|
|
60
|
+
.. py:attribute:: FORMAT_GRIB
|
|
61
|
+
:type: str
|
|
62
|
+
:value: "grib"
|
|
63
|
+
|
|
64
|
+
ERA5 data format type.
|
|
65
|
+
|
|
66
|
+
.. py:attribute:: DOWNLOAD_ZIP
|
|
67
|
+
:type: str
|
|
68
|
+
:value: "zip"
|
|
69
|
+
|
|
70
|
+
ERA5 download type.
|
|
71
|
+
|
|
72
|
+
.. py:attribute:: DOWNLOAD_UNZIP
|
|
73
|
+
:type: str
|
|
74
|
+
:value: "unarchived"
|
|
75
|
+
|
|
76
|
+
ERA5 download type.
|
|
77
|
+
|
|
78
|
+
.. py:attribute:: PRESSURE_LEVEL
|
|
79
|
+
:type: list
|
|
80
|
+
|
|
81
|
+
ERA5 available pressure levels.
|
|
82
|
+
|
|
83
|
+
.. py:attribute:: VARIABLE_*
|
|
84
|
+
:type: str
|
|
85
|
+
|
|
86
|
+
ERA5 variable names. Please check the code to see available values (too many to list here).
|
|
87
|
+
|
|
88
|
+
.. py:attribute:: NAME_MAP
|
|
89
|
+
:type: dict
|
|
90
|
+
|
|
91
|
+
Dictionary maps variable to its name in data.
|
|
92
|
+
|
|
93
|
+
.. py:attribute:: TYPE_MAP
|
|
94
|
+
:type: dict
|
|
95
|
+
|
|
96
|
+
Dictionary to distinguish between two types of data.
|
|
20
97
|
"""
|
|
21
98
|
|
|
22
99
|
# dataset name
|
|
@@ -36,19 +113,43 @@ class ERA5CONFIG:
|
|
|
36
113
|
|
|
37
114
|
# all level
|
|
38
115
|
PRESSURE_LEVEL = [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
116
|
+
"1",
|
|
117
|
+
"2",
|
|
118
|
+
"3",
|
|
119
|
+
"5",
|
|
120
|
+
"7",
|
|
121
|
+
"10",
|
|
122
|
+
"20",
|
|
123
|
+
"30",
|
|
124
|
+
"50",
|
|
125
|
+
"70",
|
|
126
|
+
"100",
|
|
127
|
+
"125",
|
|
128
|
+
"150",
|
|
129
|
+
"175",
|
|
130
|
+
"200",
|
|
131
|
+
"225",
|
|
132
|
+
"250",
|
|
133
|
+
"300",
|
|
134
|
+
"350",
|
|
135
|
+
"400",
|
|
136
|
+
"450",
|
|
137
|
+
"500",
|
|
138
|
+
"550",
|
|
139
|
+
"600",
|
|
140
|
+
"650",
|
|
141
|
+
"700",
|
|
142
|
+
"750",
|
|
143
|
+
"775",
|
|
144
|
+
"800",
|
|
145
|
+
"825",
|
|
146
|
+
"850",
|
|
147
|
+
"875",
|
|
148
|
+
"900",
|
|
149
|
+
"925",
|
|
150
|
+
"950",
|
|
151
|
+
"975",
|
|
152
|
+
"1000",
|
|
52
153
|
]
|
|
53
154
|
|
|
54
155
|
# variable name
|
|
@@ -102,7 +203,7 @@ class ERA5CONFIG:
|
|
|
102
203
|
"volumetric_soil_water_layer_1": "swvl1",
|
|
103
204
|
"volumetric_soil_water_layer_2": "swvl2",
|
|
104
205
|
"volumetric_soil_water_layer_3": "swvl3",
|
|
105
|
-
"volumetric_soil_water_layer_4": "swvl4"
|
|
206
|
+
"volumetric_soil_water_layer_4": "swvl4",
|
|
106
207
|
}
|
|
107
208
|
|
|
108
209
|
# use a dict to distinguish between two types of data
|
|
@@ -125,8 +226,7 @@ class ERA5CONFIG:
|
|
|
125
226
|
"volumetric_soil_water_layer_1",
|
|
126
227
|
"volumetric_soil_water_layer_2",
|
|
127
228
|
"volumetric_soil_water_layer_3",
|
|
128
|
-
"volumetric_soil_water_layer_4"
|
|
129
|
-
|
|
229
|
+
"volumetric_soil_water_layer_4",
|
|
130
230
|
),
|
|
131
231
|
"reanalysis-era5-pressure-levels": (
|
|
132
232
|
"specific_humidity",
|
|
@@ -134,20 +234,21 @@ class ERA5CONFIG:
|
|
|
134
234
|
"v_component_of_wind",
|
|
135
235
|
"geopotential",
|
|
136
236
|
"relative_humidity",
|
|
137
|
-
"temperature"
|
|
138
|
-
)
|
|
237
|
+
"temperature",
|
|
238
|
+
),
|
|
139
239
|
}
|
|
140
240
|
|
|
141
241
|
|
|
142
242
|
def _check_variables_and_datasets(variables: Union[str, Tuple[str, ...]], dataset: str) -> bool:
|
|
143
|
-
"""
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
243
|
+
"""
|
|
244
|
+
Check if variables and datasets correspond.
|
|
245
|
+
|
|
246
|
+
:param variables: Variables type.
|
|
247
|
+
:type variables: Union[str, Tuple[str, ...]]
|
|
248
|
+
:param dataset: Dataset type.
|
|
249
|
+
:type dataset: str
|
|
250
|
+
:return: If check passed, return ``True``, else ``False``.
|
|
251
|
+
:rtype: bool
|
|
151
252
|
"""
|
|
152
253
|
if isinstance(variables, str):
|
|
153
254
|
if variables in ERA5CONFIG.TYPE_MAP[dataset]:
|
|
@@ -163,28 +264,52 @@ def _check_variables_and_datasets(variables: Union[str, Tuple[str, ...]], datase
|
|
|
163
264
|
|
|
164
265
|
|
|
165
266
|
def _check_pressure_level(pressure_level: Union[str, List[str]]) -> bool:
|
|
166
|
-
"""
|
|
167
|
-
|
|
168
|
-
Args:
|
|
169
|
-
pressure_level (int | list[int]): A integer value or a list contains pressure values
|
|
267
|
+
"""
|
|
268
|
+
Check pressure level.
|
|
170
269
|
|
|
171
|
-
|
|
172
|
-
|
|
270
|
+
:param pressure_level: A integer value or a list contains pressure values.
|
|
271
|
+
:type pressure_level: Union[str, List[str]]
|
|
272
|
+
:return: If check passed, return ``True``, else ``False``.
|
|
273
|
+
:rtype: bool
|
|
173
274
|
"""
|
|
174
275
|
valid_pressure_level = [
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
276
|
+
"1",
|
|
277
|
+
"2",
|
|
278
|
+
"3",
|
|
279
|
+
"5",
|
|
280
|
+
"7",
|
|
281
|
+
"10",
|
|
282
|
+
"20",
|
|
283
|
+
"30",
|
|
284
|
+
"50",
|
|
285
|
+
"70",
|
|
286
|
+
"100",
|
|
287
|
+
"125",
|
|
288
|
+
"150",
|
|
289
|
+
"175",
|
|
290
|
+
"200",
|
|
291
|
+
"225",
|
|
292
|
+
"250",
|
|
293
|
+
"300",
|
|
294
|
+
"350",
|
|
295
|
+
"400",
|
|
296
|
+
"450",
|
|
297
|
+
"500",
|
|
298
|
+
"550",
|
|
299
|
+
"600",
|
|
300
|
+
"650",
|
|
301
|
+
"700",
|
|
302
|
+
"750",
|
|
303
|
+
"775",
|
|
304
|
+
"800",
|
|
305
|
+
"825",
|
|
306
|
+
"850",
|
|
307
|
+
"875",
|
|
308
|
+
"900",
|
|
309
|
+
"925",
|
|
310
|
+
"950",
|
|
311
|
+
"975",
|
|
312
|
+
"1000",
|
|
188
313
|
]
|
|
189
314
|
|
|
190
315
|
for level in pressure_level:
|
|
@@ -194,32 +319,49 @@ def _check_pressure_level(pressure_level: Union[str, List[str]]) -> bool:
|
|
|
194
319
|
return True
|
|
195
320
|
|
|
196
321
|
|
|
197
|
-
def find_era5_data(
|
|
198
|
-
|
|
199
|
-
|
|
322
|
+
def find_era5_data(
|
|
323
|
+
date: Union[List[str], List[datetime]],
|
|
324
|
+
area: Tuple[int, int, int, int],
|
|
325
|
+
variables: Union[Tuple[str, ...], str],
|
|
326
|
+
save_path: str,
|
|
327
|
+
product_type=ERA5CONFIG.TYPE_REANALYSIS,
|
|
328
|
+
data_format=ERA5CONFIG.FORMAT_NETCDF,
|
|
329
|
+
dataset=ERA5CONFIG.DATASET_ERA5_SINGLE_LEVEL,
|
|
330
|
+
download_format=ERA5CONFIG.DOWNLOAD_UNZIP,
|
|
331
|
+
pressure_level: Union[int, List[int], str, List[str], None] = None,
|
|
332
|
+
overwrite=False,
|
|
333
|
+
) -> str:
|
|
200
334
|
"""
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
335
|
+
Download data from ERA5.
|
|
336
|
+
|
|
337
|
+
:param date: List of date string or datetime object, UTC time.
|
|
338
|
+
:type date: Union[List[str], List[datetime]]
|
|
339
|
+
:param area: Range of longitude and latitude, ``[lon1, lon2, lat1, lat2]``.
|
|
340
|
+
:type area: Tuple[int, int, int, int]
|
|
341
|
+
:param variables: Variables to be download. Check :class:`ERA5CONFIG` for valid values.
|
|
342
|
+
:type variables: Union[Tuple[str, ...], str]
|
|
343
|
+
:param save_path: Data save path.
|
|
344
|
+
:type save_path: str
|
|
345
|
+
:param product_type: Product type. Check :class:`ERA5CONFIG` for valid values.
|
|
346
|
+
:type product_type: str
|
|
347
|
+
:param data_format: Data format. Check :class:`ERA5CONFIG` for valid values.
|
|
348
|
+
:type data_format: str
|
|
349
|
+
:param dataset: Dataset type. Check :class:`ERA5CONFIG` for valid values.
|
|
350
|
+
:type dataset: str
|
|
351
|
+
:param download_format: Download format. Check :class:`ERA5CONFIG` for valid values.
|
|
352
|
+
:type download_format: str
|
|
353
|
+
:param pressure_level: Pressure levels to be download. Check :class:`ERA5CONFIG` for valid values.
|
|
354
|
+
:type pressure_level: Union[int, List[int], str, List[str], None]
|
|
355
|
+
:param overwrite: If the data file exists, force to download it when ``overwrite==True``.
|
|
356
|
+
:type overwrite: bool
|
|
357
|
+
:return: Data path.
|
|
358
|
+
:rtype: str
|
|
216
359
|
"""
|
|
217
360
|
global CDS_CLIENT
|
|
218
361
|
|
|
219
362
|
# check variables and datasets
|
|
220
363
|
if not _check_variables_and_datasets(variables, dataset):
|
|
221
|
-
logger.error(
|
|
222
|
-
f"Variables {variables} and dataset {dataset} doesn't correspond, check it")
|
|
364
|
+
logger.error(f"Variables {variables} and dataset {dataset} doesn't correspond, check it")
|
|
223
365
|
exit(1)
|
|
224
366
|
|
|
225
367
|
# check if we need to create directory
|
|
@@ -232,8 +374,10 @@ def find_era5_data(date: Union[List[str], List[datetime]], area: Tuple[int, int,
|
|
|
232
374
|
|
|
233
375
|
# parse date
|
|
234
376
|
if isinstance(date[0], str):
|
|
235
|
-
date = [
|
|
236
|
-
|
|
377
|
+
date = [
|
|
378
|
+
datetime.strptime(_date, "%Y-%m-%d %H:%M") # type: ignore
|
|
379
|
+
for _date in date
|
|
380
|
+
]
|
|
237
381
|
year = list(set(_date.strftime("%Y") for _date in date)) # type: ignore
|
|
238
382
|
month = list(set(_date.strftime("%m") for _date in date)) # type: ignore
|
|
239
383
|
day = list(set(_date.strftime("%d") for _date in date)) # type: ignore
|
|
@@ -251,15 +395,15 @@ def find_era5_data(date: Union[List[str], List[datetime]], area: Tuple[int, int,
|
|
|
251
395
|
|
|
252
396
|
# create params dict
|
|
253
397
|
params_dict = {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
398
|
+
"product_type": product_type,
|
|
399
|
+
"data_format": data_format,
|
|
400
|
+
"download_format": download_format,
|
|
401
|
+
"variable": variables,
|
|
402
|
+
"year": year,
|
|
403
|
+
"month": month,
|
|
404
|
+
"day": day,
|
|
405
|
+
"time": time,
|
|
406
|
+
"area": area,
|
|
263
407
|
}
|
|
264
408
|
|
|
265
409
|
# check if we need to add pressure_level to params dict
|
|
@@ -269,12 +413,11 @@ def find_era5_data(date: Union[List[str], List[datetime]], area: Tuple[int, int,
|
|
|
269
413
|
exit(1)
|
|
270
414
|
# convert value to str
|
|
271
415
|
if not isinstance(pressure_level, list):
|
|
272
|
-
pressure_level = [pressure_level]
|
|
416
|
+
pressure_level = [pressure_level] # type: ignore
|
|
273
417
|
if not isinstance(pressure_level[0], str): # type: ignore
|
|
274
|
-
pressure_level = [str(int(x))
|
|
275
|
-
for x in pressure_level] # type: ignore
|
|
418
|
+
pressure_level = [str(int(x)) for x in pressure_level] # type: ignore
|
|
276
419
|
# check
|
|
277
|
-
if _check_pressure_level(pressure_level):
|
|
420
|
+
if _check_pressure_level(pressure_level): # type: ignore
|
|
278
421
|
params_dict["pressure_level"] = pressure_level
|
|
279
422
|
else:
|
|
280
423
|
logger.error("You have passed wrong pressure level to download data, check it")
|
|
@@ -285,6 +428,7 @@ def find_era5_data(date: Union[List[str], List[datetime]], area: Tuple[int, int,
|
|
|
285
428
|
|
|
286
429
|
if CDS_CLIENT is None:
|
|
287
430
|
import cdsapi
|
|
431
|
+
|
|
288
432
|
CDS_CLIENT = cdsapi.Client()
|
|
289
433
|
|
|
290
434
|
CDS_CLIENT.retrieve(dataset, params_dict, save_path)
|
|
@@ -293,12 +437,13 @@ def find_era5_data(date: Union[List[str], List[datetime]], area: Tuple[int, int,
|
|
|
293
437
|
|
|
294
438
|
|
|
295
439
|
def prepare_wps_input_data(area: Tuple[int, int, int, int]):
|
|
296
|
-
"""
|
|
440
|
+
"""
|
|
441
|
+
Download essential data for WPS.
|
|
297
442
|
|
|
298
|
-
|
|
299
|
-
|
|
443
|
+
:param area: Range of longitude and latitude, ``[lon1, lon2, lat1, lat2]``.
|
|
444
|
+
:type area: Tuple[int, int, int, int]
|
|
300
445
|
"""
|
|
301
|
-
wrf_config =
|
|
446
|
+
wrf_config = WRFRUN.config.get_model_config("wrf")
|
|
302
447
|
# get start and end date from config
|
|
303
448
|
start_date = wrf_config["time"]["start_date"]
|
|
304
449
|
end_date = wrf_config["time"]["end_date"]
|
|
@@ -311,16 +456,32 @@ def prepare_wps_input_data(area: Tuple[int, int, int, int]):
|
|
|
311
456
|
hour_step = wrf_config["time"]["input_data_interval"] // 3600
|
|
312
457
|
|
|
313
458
|
# get data save path
|
|
314
|
-
data_save_path =
|
|
459
|
+
data_save_path = WRFRUN.config.get_input_data_path()
|
|
315
460
|
|
|
316
461
|
# download data
|
|
317
|
-
logger.info(
|
|
318
|
-
download_data(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
462
|
+
logger.info("Download background data of surface level...")
|
|
463
|
+
download_data(
|
|
464
|
+
start_date,
|
|
465
|
+
end_date,
|
|
466
|
+
hour_step,
|
|
467
|
+
area,
|
|
468
|
+
f"{data_save_path}/surface.grib",
|
|
469
|
+
data_format="grib",
|
|
470
|
+
data_type="surface",
|
|
471
|
+
overwrite=True,
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
logger.info("Download background data of pressure level...")
|
|
475
|
+
download_data(
|
|
476
|
+
start_date,
|
|
477
|
+
end_date,
|
|
478
|
+
hour_step,
|
|
479
|
+
area,
|
|
480
|
+
f"{data_save_path}/pressure.grib",
|
|
481
|
+
data_format="grib",
|
|
482
|
+
data_type="pressure",
|
|
483
|
+
overwrite=True,
|
|
484
|
+
)
|
|
324
485
|
|
|
325
486
|
# logger.info(f"Download NearGOOS data...")
|
|
326
487
|
# download_data(start_date, end_date, hour_step, area,
|
|
@@ -328,57 +489,61 @@ def prepare_wps_input_data(area: Tuple[int, int, int, int]):
|
|
|
328
489
|
|
|
329
490
|
|
|
330
491
|
def download_data(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
492
|
+
start_date: str,
|
|
493
|
+
end_date: str,
|
|
494
|
+
hour_step: int,
|
|
495
|
+
area: Tuple[int, int, int, int],
|
|
496
|
+
save_path: str,
|
|
497
|
+
data_format: Literal["nc", "grib"] = "nc",
|
|
498
|
+
data_type: Literal["pressure", "surface"] = "pressure",
|
|
499
|
+
overwrite=False,
|
|
500
|
+
) -> str:
|
|
501
|
+
"""
|
|
502
|
+
Download essential data from ERA5.
|
|
503
|
+
|
|
504
|
+
:param start_date: Begin date, for example, ``"2022-05-19 12:00"``.
|
|
505
|
+
:type start_date: str
|
|
506
|
+
:param end_date: End date, for example, ``"2022-05-22 18:00"``.
|
|
507
|
+
:type end_date: str
|
|
508
|
+
:param hour_step: Hour step.
|
|
509
|
+
:type hour_step: int
|
|
510
|
+
:param area: Range of longitude and latitude, ``[lon1, lon2, lat1, lat2]``.
|
|
511
|
+
:type area: Tuple[int, int, int, int]
|
|
512
|
+
:param save_path: Data save path.
|
|
513
|
+
:type save_path: str
|
|
514
|
+
:param data_format: Download data format. Default is ``"nc"``.
|
|
515
|
+
:type data_format: Literal["nc", "grib"]
|
|
516
|
+
:param data_type: Download data type. Default is ``"pressure"``.
|
|
517
|
+
:param overwrite: If the data file exists, force to download it when ``overwrite==True``.
|
|
518
|
+
:return: Data path.
|
|
519
|
+
:rtype: str
|
|
353
520
|
"""
|
|
354
521
|
# generate date list
|
|
355
|
-
date_list = date_range(
|
|
356
|
-
start_date, end_date, freq=f"{hour_step}H"
|
|
357
|
-
).strftime("%Y-%m-%d %H:%M").to_list()
|
|
522
|
+
date_list = date_range(start_date, end_date, freq=f"{hour_step}H").strftime("%Y-%m-%d %H:%M").to_list()
|
|
358
523
|
|
|
359
524
|
# check format
|
|
360
525
|
if data_format == "nc":
|
|
361
|
-
|
|
526
|
+
_data_format = ERA5CONFIG.FORMAT_NETCDF
|
|
362
527
|
elif data_format == "grib":
|
|
363
|
-
|
|
528
|
+
_data_format = ERA5CONFIG.FORMAT_GRIB
|
|
364
529
|
else:
|
|
365
|
-
logger.error(f"Wrong data format: {
|
|
530
|
+
logger.error(f"Wrong data format: {_data_format}")
|
|
366
531
|
raise KeyError
|
|
367
532
|
|
|
368
533
|
# check data type
|
|
369
534
|
if data_type == "pressure":
|
|
370
|
-
|
|
535
|
+
_data_type = ERA5CONFIG.DATASET_ERA5_PRESSURE_LEVEL
|
|
371
536
|
variables = (
|
|
372
537
|
ERA5CONFIG.VARIABLE_GEOPOTENTIAL,
|
|
373
538
|
ERA5CONFIG.VARIABLE_RELATIVE_HUMIDITY,
|
|
374
539
|
ERA5CONFIG.VARIABLE_SPECIFIC_HUMIDITY,
|
|
375
540
|
ERA5CONFIG.VARIABLE_TEMPERATURE,
|
|
376
541
|
ERA5CONFIG.VARIABLE_U_WIND,
|
|
377
|
-
ERA5CONFIG.VARIABLE_V_WIND
|
|
542
|
+
ERA5CONFIG.VARIABLE_V_WIND,
|
|
378
543
|
)
|
|
379
544
|
pressure_level = ERA5CONFIG.PRESSURE_LEVEL
|
|
380
545
|
elif data_type == "surface":
|
|
381
|
-
|
|
546
|
+
_data_type = ERA5CONFIG.DATASET_ERA5_SINGLE_LEVEL
|
|
382
547
|
variables = (
|
|
383
548
|
ERA5CONFIG.VARIABLE_SURFACE_PRESSURE,
|
|
384
549
|
ERA5CONFIG.VARIABLE_MEAN_SEA_LEVEL_PRESSURE,
|
|
@@ -397,25 +562,25 @@ def download_data(
|
|
|
397
562
|
ERA5CONFIG.VARIABLE_VOLUMETRIC_SOIL_WATER_LAYER_3,
|
|
398
563
|
ERA5CONFIG.VARIABLE_VOLUMETRIC_SOIL_WATER_LAYER_4,
|
|
399
564
|
ERA5CONFIG.VARIABLE_SNOW_DEPTH,
|
|
400
|
-
ERA5CONFIG.VARIABLE_SNOW_DENSITY
|
|
565
|
+
ERA5CONFIG.VARIABLE_SNOW_DENSITY,
|
|
401
566
|
)
|
|
402
567
|
pressure_level = None
|
|
403
|
-
elif data_type == "goos":
|
|
404
|
-
logger.warning(f"NEAR-GOOS SST data hasn't been supported yet")
|
|
405
|
-
# download sst data
|
|
406
|
-
# for _date in date_list:
|
|
407
|
-
# _ = goos_sst_find_data(_date, save_path=save_path)
|
|
408
|
-
|
|
409
|
-
return ""
|
|
410
568
|
else:
|
|
411
|
-
logger.error(f"Wrong data type: {
|
|
569
|
+
logger.error(f"Wrong data type: {_data_type}")
|
|
412
570
|
raise KeyError
|
|
413
571
|
|
|
414
572
|
# download data
|
|
415
|
-
return find_era5_data(
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
573
|
+
return find_era5_data(
|
|
574
|
+
date=date_list,
|
|
575
|
+
area=area,
|
|
576
|
+
variables=variables,
|
|
577
|
+
save_path=save_path,
|
|
578
|
+
data_format=_data_format,
|
|
579
|
+
dataset=_data_type,
|
|
580
|
+
pressure_level=pressure_level,
|
|
581
|
+
download_format=ERA5CONFIG.DOWNLOAD_UNZIP,
|
|
582
|
+
overwrite=overwrite,
|
|
583
|
+
)
|
|
419
584
|
|
|
420
585
|
|
|
421
586
|
__all__ = ["find_era5_data", "ERA5CONFIG", "download_data", "prepare_wps_input_data"]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
wrfrun.extension.goos_sst
|
|
3
3
|
#########################
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Extension help user create a GRIB file from ERA5 skin temperature (SKT) data and NEAR-GOOS sea surface temperature (SST) data.
|
|
6
6
|
|
|
7
7
|
============================================= =============================================
|
|
8
8
|
:doc:`core </api/extension.goos_sst.core>` Core functionality submodule.
|
|
@@ -50,7 +50,7 @@ The code snap below shows you how to use this extension.
|
|
|
50
50
|
if __name__ == '__main__':
|
|
51
51
|
era5_data_path = "data/ear5-reanalysis-data.grib"
|
|
52
52
|
merge_era5_goos_sst_grib(era5_data_path, "data/near-goos-data.grib")
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
Please check :func:`core.merge_era5_goos_sst_grib` for more information.
|
|
55
55
|
|
|
56
56
|
.. toctree::
|
|
@@ -7,19 +7,19 @@ Implementation of ``extension.goos_sst``'s core functionality.
|
|
|
7
7
|
|
|
8
8
|
.. autosummary::
|
|
9
9
|
:toctree: generated/
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
merge_era5_goos_sst_grib
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
from os.path import dirname
|
|
15
15
|
|
|
16
|
-
import cfgrib as cf
|
|
17
16
|
import numpy as np
|
|
18
17
|
from pandas import to_datetime
|
|
19
18
|
from xarray import DataArray
|
|
20
19
|
|
|
20
|
+
from wrfrun.log import logger
|
|
21
|
+
|
|
21
22
|
from .utils import create_sst_grib
|
|
22
|
-
from wrfrun.utils import logger
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def merge_era5_goos_sst_grib(surface_grib_path: str, save_path: str, sst_data_save_path: str | None = None, resolution="low"):
|
|
@@ -41,6 +41,7 @@ def merge_era5_goos_sst_grib(surface_grib_path: str, save_path: str, sst_data_sa
|
|
|
41
41
|
"""
|
|
42
42
|
# lazy import seafog to fix libcurl error in readthedocs
|
|
43
43
|
# T^T
|
|
44
|
+
import cfgrib as cf
|
|
44
45
|
from seafog import goos_sst_find_data, goos_sst_parser
|
|
45
46
|
|
|
46
47
|
dataset_list = cf.open_datasets(surface_grib_path)
|
|
@@ -55,10 +56,10 @@ def merge_era5_goos_sst_grib(surface_grib_path: str, save_path: str, sst_data_sa
|
|
|
55
56
|
logger.error(f"'skt' data not found in {surface_grib_path}")
|
|
56
57
|
raise ValueError
|
|
57
58
|
|
|
58
|
-
skt: DataArray = dataset["skt"]
|
|
59
|
+
skt: DataArray = dataset["skt"] # type: ignore
|
|
59
60
|
|
|
60
|
-
longitude_start, longitude_end = skt["longitude"][0].data, skt["longitude"][-1].data
|
|
61
|
-
latitude_start, latitude_end = skt["latitude"][-1].data, skt["latitude"][0].data
|
|
61
|
+
longitude_start, longitude_end = skt["longitude"][0].data, skt["longitude"][-1].data # type: ignore
|
|
62
|
+
latitude_start, latitude_end = skt["latitude"][-1].data, skt["latitude"][0].data # type: ignore
|
|
62
63
|
|
|
63
64
|
data_time = skt["time"].to_numpy() # type: ignore
|
|
64
65
|
data_time = to_datetime(data_time).strftime("%Y-%m-%d %H:%M")
|
|
@@ -95,14 +96,8 @@ def merge_era5_goos_sst_grib(surface_grib_path: str, save_path: str, sst_data_sa
|
|
|
95
96
|
name="sst",
|
|
96
97
|
data=sst,
|
|
97
98
|
dims=["time", "latitude", "longitude"],
|
|
98
|
-
coords={
|
|
99
|
-
|
|
100
|
-
"latitude": skt["latitude"],
|
|
101
|
-
"longitude": skt["longitude"]
|
|
102
|
-
}, attrs={
|
|
103
|
-
"units": "K",
|
|
104
|
-
"long_name": "Sea surface temperature"
|
|
105
|
-
}
|
|
99
|
+
coords={"time": skt["time"], "latitude": skt["latitude"], "longitude": skt["longitude"]},
|
|
100
|
+
attrs={"units": "K", "long_name": "Sea surface temperature"},
|
|
106
101
|
)
|
|
107
102
|
|
|
108
103
|
create_sst_grib(sst, save_path=save_path)
|