wrfrun 0.1.7__py3-none-any.whl → 0.1.9__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/cli.py +128 -0
- wrfrun/core/__init__.py +33 -0
- wrfrun/core/base.py +246 -75
- wrfrun/core/config.py +286 -236
- wrfrun/core/error.py +47 -17
- wrfrun/core/replay.py +65 -32
- wrfrun/core/server.py +139 -79
- wrfrun/data.py +10 -5
- wrfrun/extension/__init__.py +28 -0
- wrfrun/extension/goos_sst/__init__.py +67 -0
- wrfrun/extension/goos_sst/core.py +111 -0
- wrfrun/extension/goos_sst/res/Vtable.ERA_GOOS_SST +7 -0
- wrfrun/extension/goos_sst/res/__init__.py +26 -0
- wrfrun/extension/goos_sst/utils.py +97 -0
- wrfrun/extension/littler/__init__.py +57 -1
- wrfrun/extension/littler/{utils.py → core.py} +326 -40
- wrfrun/extension/utils.py +22 -21
- wrfrun/model/__init__.py +24 -1
- wrfrun/model/plot.py +253 -35
- wrfrun/model/utils.py +17 -8
- wrfrun/model/wrf/__init__.py +41 -0
- wrfrun/model/wrf/core.py +218 -102
- wrfrun/model/wrf/exec_wrap.py +49 -35
- wrfrun/model/wrf/namelist.py +82 -11
- wrfrun/model/wrf/scheme.py +85 -1
- wrfrun/model/wrf/{_metgrid.py → utils.py} +36 -2
- wrfrun/model/wrf/vtable.py +2 -1
- wrfrun/plot/wps.py +66 -58
- wrfrun/res/__init__.py +8 -5
- wrfrun/res/config/config.template.toml +50 -0
- wrfrun/res/{config.toml.template → config/wrf.template.toml} +10 -47
- wrfrun/res/run.template.sh +10 -0
- wrfrun/res/scheduler/lsf.template +5 -0
- wrfrun/res/{job_scheduler → scheduler}/pbs.template +1 -1
- wrfrun/res/{job_scheduler → scheduler}/slurm.template +2 -1
- wrfrun/run.py +19 -23
- wrfrun/scheduler/__init__.py +35 -0
- wrfrun/scheduler/env.py +44 -0
- wrfrun/scheduler/lsf.py +47 -0
- wrfrun/scheduler/pbs.py +48 -0
- wrfrun/scheduler/script.py +70 -0
- wrfrun/scheduler/slurm.py +48 -0
- wrfrun/scheduler/utils.py +14 -0
- wrfrun/utils.py +8 -3
- wrfrun/workspace/__init__.py +38 -0
- wrfrun/workspace/core.py +92 -0
- wrfrun/workspace/wrf.py +121 -0
- {wrfrun-0.1.7.dist-info → wrfrun-0.1.9.dist-info}/METADATA +4 -3
- wrfrun-0.1.9.dist-info/RECORD +62 -0
- wrfrun-0.1.9.dist-info/entry_points.txt +3 -0
- wrfrun/model/wrf/_ndown.py +0 -39
- wrfrun/pbs.py +0 -86
- wrfrun/res/run.sh.template +0 -16
- wrfrun/workspace.py +0 -88
- wrfrun-0.1.7.dist-info/RECORD +0 -46
- {wrfrun-0.1.7.dist-info → wrfrun-0.1.9.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.extension.goos_sst
|
|
3
|
+
#########################
|
|
4
|
+
|
|
5
|
+
This extension can help you create a GRIB file from ERA5 skin temperature (SKT) data and NEAR-GOOS sea surface temperature (SST) data.
|
|
6
|
+
|
|
7
|
+
============================================= =============================================
|
|
8
|
+
:doc:`core </api/extension.goos_sst.core>` Core functionality submodule.
|
|
9
|
+
:doc:`res </api/extension.goos_sst.res>` Resource files provided by this extension.
|
|
10
|
+
:doc:`utils </api/extension.goos_sst.utils>` Utility submodule used by the core submodule.
|
|
11
|
+
============================================= =============================================
|
|
12
|
+
|
|
13
|
+
Important Note
|
|
14
|
+
**************
|
|
15
|
+
|
|
16
|
+
This extension relies on ``cfgrib`` package to create GRIB file.
|
|
17
|
+
While GRIB write support is experimental in ``cfgrib``,
|
|
18
|
+
this extension may **FAIL TO CREATE GRIB FILE**.
|
|
19
|
+
|
|
20
|
+
How This Extension Works
|
|
21
|
+
************************
|
|
22
|
+
|
|
23
|
+
This extension provides a method which merges ERA5 reanalysis skin temperature (SKT) data and NEAR-GOOS SST data,
|
|
24
|
+
and write new data to a GRIB file.
|
|
25
|
+
|
|
26
|
+
How To Use This Extension
|
|
27
|
+
*************************
|
|
28
|
+
|
|
29
|
+
Prerequisite
|
|
30
|
+
============
|
|
31
|
+
|
|
32
|
+
You need to have the following packages installed, because they are not included in ``wrfrun``'s dependency:
|
|
33
|
+
|
|
34
|
+
* cfgrib: Provide the method to create GRIB file.
|
|
35
|
+
* seafog: Provide the method to download and read NEAR-GOOS SST data.
|
|
36
|
+
|
|
37
|
+
And you also have downloaded an ERA5 reanalysis data (GRIB format) which contains SKT data.
|
|
38
|
+
|
|
39
|
+
How To Use
|
|
40
|
+
==========
|
|
41
|
+
|
|
42
|
+
The code snap below shows you how to use this extension.
|
|
43
|
+
|
|
44
|
+
.. code-block:: Python
|
|
45
|
+
:caption: main.py
|
|
46
|
+
|
|
47
|
+
from wrfrun.extension.goos_sst import merge_era5_goos_sst_grib
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == '__main__':
|
|
51
|
+
era5_data_path = "data/ear5-reanalysis-data.grib"
|
|
52
|
+
merge_era5_goos_sst_grib(era5_data_path, "data/near-goos-data.grib")
|
|
53
|
+
|
|
54
|
+
Please check :func:`core.merge_era5_goos_sst_grib` for more information.
|
|
55
|
+
|
|
56
|
+
.. toctree::
|
|
57
|
+
:maxdepth: 1
|
|
58
|
+
:hidden:
|
|
59
|
+
|
|
60
|
+
core <extension.goos_sst.core>
|
|
61
|
+
res <extension.goos_sst.res>
|
|
62
|
+
utils <extension.goos_sst.utils>
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
from .core import *
|
|
66
|
+
from .res import *
|
|
67
|
+
from .utils import *
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.extension.goos_sst.core
|
|
3
|
+
##############################
|
|
4
|
+
|
|
5
|
+
Implementation of ``extension.goos_sst``'s core functionality.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
.. autosummary::
|
|
9
|
+
:toctree: generated/
|
|
10
|
+
|
|
11
|
+
merge_era5_goos_sst_grib
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from os.path import dirname
|
|
15
|
+
|
|
16
|
+
import cfgrib as cf
|
|
17
|
+
import numpy as np
|
|
18
|
+
from pandas import to_datetime
|
|
19
|
+
from xarray import DataArray
|
|
20
|
+
|
|
21
|
+
from .utils import create_sst_grib
|
|
22
|
+
from wrfrun.utils import logger
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def merge_era5_goos_sst_grib(surface_grib_path: str, save_path: str, sst_data_save_path: str | None = None, resolution="low"):
|
|
26
|
+
"""
|
|
27
|
+
This function reads ERA5 skin temperature (SKT) data from the GRIB file,
|
|
28
|
+
interpolates it to the same grib of NEAR-GOOS sea surface temperature (SST) data,
|
|
29
|
+
merges them and creates a new GRIB file with the new data.
|
|
30
|
+
|
|
31
|
+
:param surface_grib_path: GRIB file which contains SKT data.
|
|
32
|
+
:type surface_grib_path: str
|
|
33
|
+
:param save_path: Save path of the new GRIB file.
|
|
34
|
+
:type save_path: str
|
|
35
|
+
:param sst_data_save_path: Save path of downloaded NEAR-GOOS SST data.
|
|
36
|
+
If None, save data to the parent directory of ``save_path``.
|
|
37
|
+
:type sst_data_save_path: str | None
|
|
38
|
+
:param resolution: Resolution of downloaded NEAR-GOO SST data.
|
|
39
|
+
Please check ``seafog.goos_sst_find_data`` for more information.
|
|
40
|
+
:type resolution: str
|
|
41
|
+
"""
|
|
42
|
+
# lazy import seafog to fix libcurl error in readthedocs
|
|
43
|
+
# T^T
|
|
44
|
+
from seafog import goos_sst_find_data, goos_sst_parser
|
|
45
|
+
|
|
46
|
+
dataset_list = cf.open_datasets(surface_grib_path)
|
|
47
|
+
|
|
48
|
+
dataset = None
|
|
49
|
+
for _ds in dataset_list:
|
|
50
|
+
if "skt" in _ds:
|
|
51
|
+
dataset = _ds
|
|
52
|
+
break
|
|
53
|
+
|
|
54
|
+
if dataset is None:
|
|
55
|
+
logger.error(f"'skt' data not found in {surface_grib_path}")
|
|
56
|
+
raise ValueError
|
|
57
|
+
|
|
58
|
+
skt: DataArray = dataset["skt"] # type: ignore
|
|
59
|
+
|
|
60
|
+
longitude_start, longitude_end = skt["longitude"][0].data, skt["longitude"][-1].data # type: ignore
|
|
61
|
+
latitude_start, latitude_end = skt["latitude"][-1].data, skt["latitude"][0].data # type: ignore
|
|
62
|
+
|
|
63
|
+
data_time = skt["time"].to_numpy() # type: ignore
|
|
64
|
+
data_time = to_datetime(data_time).strftime("%Y-%m-%d %H:%M")
|
|
65
|
+
|
|
66
|
+
if sst_data_save_path is None:
|
|
67
|
+
sst_data_save_path = dirname(save_path)
|
|
68
|
+
|
|
69
|
+
# read the first time data, so we can interpolate skt data to the same resolution as sst data.
|
|
70
|
+
_data = goos_sst_find_data(data_time[0], sst_data_save_path, resolution=resolution, show_progress=False)
|
|
71
|
+
_data = goos_sst_parser(_data, resolution=resolution)
|
|
72
|
+
_data = _data.loc[latitude_start:latitude_end, longitude_start:longitude_end]
|
|
73
|
+
|
|
74
|
+
skt = skt.interp({"longitude": _data["longitude"], "latitude": _data["latitude"]})
|
|
75
|
+
sst = np.zeros_like(skt)
|
|
76
|
+
temp_data = np.zeros_like(skt[0])
|
|
77
|
+
|
|
78
|
+
temp_data[:] = skt.to_numpy()[0]
|
|
79
|
+
index = ~np.isnan(_data.to_numpy())
|
|
80
|
+
temp_data[index] = _data.to_numpy()[index]
|
|
81
|
+
sst[0] = temp_data
|
|
82
|
+
|
|
83
|
+
# loop other time.
|
|
84
|
+
for time_index, _data_time in enumerate(data_time[1:], start=1):
|
|
85
|
+
_data = goos_sst_find_data(_data_time, sst_data_save_path, resolution=resolution, show_progress=False)
|
|
86
|
+
_data = goos_sst_parser(_data, resolution=resolution)
|
|
87
|
+
_data = _data.loc[latitude_start:latitude_end, longitude_start:longitude_end]
|
|
88
|
+
|
|
89
|
+
temp_data[:] = skt.to_numpy()[time_index]
|
|
90
|
+
index = ~np.isnan(_data.to_numpy())
|
|
91
|
+
temp_data[index] = _data.to_numpy()[index]
|
|
92
|
+
sst[time_index] = temp_data
|
|
93
|
+
|
|
94
|
+
sst = DataArray(
|
|
95
|
+
name="sst",
|
|
96
|
+
data=sst,
|
|
97
|
+
dims=["time", "latitude", "longitude"],
|
|
98
|
+
coords={
|
|
99
|
+
"time": skt["time"],
|
|
100
|
+
"latitude": skt["latitude"],
|
|
101
|
+
"longitude": skt["longitude"]
|
|
102
|
+
}, attrs={
|
|
103
|
+
"units": "K",
|
|
104
|
+
"long_name": "Sea surface temperature"
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
create_sst_grib(sst, save_path=save_path)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
__all__ = ["merge_era5_goos_sst_grib"]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
GRIB | Level| Level| Level| metgrid | metgrid | metgrid |
|
|
2
|
+
Code | Code | 1 | 2 | Name | Units | Description |
|
|
3
|
+
-----+------+------+------+----------+----------+------------------------------------------+
|
|
4
|
+
34 | 1 | 0 | | SST | K | Sea-Surface Temperature |
|
|
5
|
+
-----+------+------+------+----------+----------+------------------------------------------+
|
|
6
|
+
|
|
7
|
+
# Vtable setting for GRIB file created by wrfrun.extension.goos_sst
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.extension.goos_sst.res
|
|
3
|
+
#############################
|
|
4
|
+
|
|
5
|
+
Resource files provided by :doc:`/api/extension.goos_sst`.
|
|
6
|
+
|
|
7
|
+
VTABLE_ERA_GOOS_SST
|
|
8
|
+
*******************
|
|
9
|
+
|
|
10
|
+
.. py:data:: VTABLE_ERA_GOOS_SST
|
|
11
|
+
:type: str
|
|
12
|
+
:value: Absolute file path.
|
|
13
|
+
|
|
14
|
+
Vtable file used to input the GRIB data created by :doc:`/api/extension.goos_sst` to WRF.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from os.path import abspath, dirname
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
_PATH = abspath(dirname(__file__))
|
|
22
|
+
|
|
23
|
+
VTABLE_ERA_GOOS_SST = f"{_PATH}/Vtable.ERA_GOOS_SST"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
__all__ = ["VTABLE_ERA_GOOS_SST"]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.extension.goos_sst.utils
|
|
3
|
+
###############################
|
|
4
|
+
|
|
5
|
+
Functions that are used by :doc:`/api/extension.goos_sst`.
|
|
6
|
+
|
|
7
|
+
.. autosummary::
|
|
8
|
+
:toctree: generated/
|
|
9
|
+
|
|
10
|
+
create_sst_grib
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from cfgrib.xarray_to_grib import to_grib
|
|
14
|
+
from numpy.dtypes import DateTime64DType
|
|
15
|
+
from pandas import to_datetime
|
|
16
|
+
from xarray import DataArray, Dataset
|
|
17
|
+
|
|
18
|
+
from wrfrun.utils import logger
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def create_sst_grib(data: DataArray, save_path: str):
|
|
22
|
+
"""
|
|
23
|
+
Write SST data to a GRIB file.
|
|
24
|
+
|
|
25
|
+
This function creates GRIB file using ``cfgrib`` package.
|
|
26
|
+
While GRIB write support is experimental in ``cfgrib``,
|
|
27
|
+
this function may **FAIL TO CREATE GRIB FILE**.
|
|
28
|
+
|
|
29
|
+
:param data: ``xarray.DataArray``, which at least has three dimensions: ``["time", "latitude", "longitude"]``.
|
|
30
|
+
:type data: DataArray
|
|
31
|
+
:param save_path: Output GRIB file path.
|
|
32
|
+
:type save_path: str
|
|
33
|
+
"""
|
|
34
|
+
# check the data's dimensions.
|
|
35
|
+
for _dim in ["time", "longitude", "latitude"]:
|
|
36
|
+
if _dim not in data.dims:
|
|
37
|
+
logger.error(f"Essential dimension '{_dim}' not found in data")
|
|
38
|
+
raise KeyError
|
|
39
|
+
|
|
40
|
+
if not isinstance(data["time"].dtype, DateTime64DType): # type: ignore
|
|
41
|
+
data = data.assign_coords(time=to_datetime(data["time"].data))
|
|
42
|
+
|
|
43
|
+
data = data.sortby(data["latitude"], ascending=False)
|
|
44
|
+
|
|
45
|
+
longitude_start, longitude_stop = data["longitude"][0].data, data["longitude"][-1].data
|
|
46
|
+
latitude_start, latitude_stop = data["latitude"][0].data, data["latitude"][-1].data
|
|
47
|
+
delta_longitude = data["longitude"][1].data - data["longitude"][0].data
|
|
48
|
+
delta_latitude = data["latitude"][0].data - data["latitude"][1].data
|
|
49
|
+
longitude_length = data["longitude"].size
|
|
50
|
+
latitude_length = data["latitude"].size
|
|
51
|
+
points_number = data.size
|
|
52
|
+
|
|
53
|
+
data = data.assign_attrs(**{
|
|
54
|
+
"units": "K",
|
|
55
|
+
"long_name": "Sea surface temperature",
|
|
56
|
+
"standard_name": "Sea surface temperature",
|
|
57
|
+
# The following keys and values will be used in GRIB.
|
|
58
|
+
"GRIB_paramId": 34,
|
|
59
|
+
"GRIB_shortName": "sst",
|
|
60
|
+
"GRIB_units": "K",
|
|
61
|
+
"GRIB_name": "Sea surface temperature",
|
|
62
|
+
"GRIB_stepUnits": 1,
|
|
63
|
+
"GRIB_stepType": "instant",
|
|
64
|
+
"GRIB_gridType": "regular_ll",
|
|
65
|
+
"GRIB_iDirectionIncrementInDegrees": delta_longitude,
|
|
66
|
+
"GRIB_iScanNegatively": 0,
|
|
67
|
+
"GRIB_jDirectionIncrementInDegrees": delta_latitude,
|
|
68
|
+
"GRIB_jScanPositively": 0,
|
|
69
|
+
"GRIB_latitudeOfFirstGridPointInDegrees": latitude_start,
|
|
70
|
+
"GRIB_latitudeOfLastGridPointInDegrees": latitude_stop,
|
|
71
|
+
"GRIB_longitudeOfFirstGridPointInDegrees": longitude_start,
|
|
72
|
+
"GRIB_longitudeOfLastGridPointInDegrees": longitude_stop,
|
|
73
|
+
"GRIB_Ny": latitude_length,
|
|
74
|
+
"GRIB_Nx": longitude_length,
|
|
75
|
+
"GRIB_typeOfLevel": "surface",
|
|
76
|
+
# The following keys and values can't be found at ECMWF websites.
|
|
77
|
+
"GRIB_cfName": "unknown",
|
|
78
|
+
"GRIB_cfVarName": "sst",
|
|
79
|
+
"GRIB_dataType": "an", # Analysis data, defined at https://codes.ecmwf.int/grib/format/mars/type/
|
|
80
|
+
"GRIB_gridDefinitionDescription": "Latitude/Longitude Grid",
|
|
81
|
+
# "GRIB_missingValue": -9999,
|
|
82
|
+
"GRIB_numberOfPoints": points_number,
|
|
83
|
+
"GRIB_totalNumber": 0,
|
|
84
|
+
"GRIB_uvRelativeToGird": 0
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
to_grib(
|
|
88
|
+
Dataset({
|
|
89
|
+
"sst": data
|
|
90
|
+
}, attrs={
|
|
91
|
+
"GRIB_centre": "ecmf",
|
|
92
|
+
"GRIB_edition": 1,
|
|
93
|
+
}), save_path
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
__all__ = ["create_sst_grib"]
|
|
@@ -1 +1,57 @@
|
|
|
1
|
-
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.extension.littler
|
|
3
|
+
########################
|
|
4
|
+
|
|
5
|
+
This extension can help you manage observation data, and create ``LITTLE_R`` file for data assimilation.
|
|
6
|
+
|
|
7
|
+
========================================= =============================
|
|
8
|
+
:doc:`core </api/extension.littler.core>` Core functionality submodule.
|
|
9
|
+
========================================= =============================
|
|
10
|
+
|
|
11
|
+
What Can This Extension Do?
|
|
12
|
+
***************************
|
|
13
|
+
|
|
14
|
+
According to the `WRFDA Online Tutorial <https://www2.mmm.ucar.edu/wrf/users/wrfda/OnlineTutorial/Help/littler.html>`_,
|
|
15
|
+
``LITTLE_R`` is an ASCII-based observation file format that is designed to be an intermediate format
|
|
16
|
+
so that WRFDA might be able to assimilate as many observation types as possible in a universal manner.
|
|
17
|
+
|
|
18
|
+
However, ``LITTLE_R`` is really hard to process elegantly from the point of view of Python.
|
|
19
|
+
To help users create ``LITTLE_R`` file easily, this extension introduces :class:`LittleR <core.LittleR>`,
|
|
20
|
+
and **Zipped Little R** file.
|
|
21
|
+
|
|
22
|
+
:class:`LittleR <core.LittleR>` accepts observation datas, and can generate observation reports in proper format.
|
|
23
|
+
Besides, it can save an observation report to a Zipped Little R file,
|
|
24
|
+
so you can read the report later or process the observation data with other program.
|
|
25
|
+
Please check :class:`LittleR <core.LittleR>` for more information.
|
|
26
|
+
|
|
27
|
+
How To Use This Extension?
|
|
28
|
+
**************************
|
|
29
|
+
|
|
30
|
+
The code snap below shows you how to use this extension.
|
|
31
|
+
|
|
32
|
+
.. code-block:: Python
|
|
33
|
+
:caption: main.py
|
|
34
|
+
|
|
35
|
+
from wrfrun.extension.littler import LittleR
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if __name__ == '__main__':
|
|
39
|
+
littler = LittleR()
|
|
40
|
+
littler.set_header(
|
|
41
|
+
longitude=120, latitude=60, fm="FM-19", elevation=0,
|
|
42
|
+
is_bogus=True, date="20250902070000"
|
|
43
|
+
)
|
|
44
|
+
# write to LITTLE_R file
|
|
45
|
+
with open("data/test", "w") as f:
|
|
46
|
+
f.write(str(littler))
|
|
47
|
+
# write to zlr file
|
|
48
|
+
littler.to_zlr("data/test.zlr")
|
|
49
|
+
|
|
50
|
+
.. toctree::
|
|
51
|
+
:maxdepth: 1
|
|
52
|
+
:hidden:
|
|
53
|
+
|
|
54
|
+
core <extension.littler.core>
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
from .core import *
|