wrfrun 0.1.8__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/base.py +8 -5
- wrfrun/core/config.py +81 -150
- wrfrun/core/replay.py +1 -1
- wrfrun/core/server.py +81 -78
- wrfrun/extension/goos_sst/__init__.py +5 -5
- wrfrun/extension/goos_sst/core.py +4 -1
- wrfrun/extension/goos_sst/res/Vtable.ERA_GOOS_SST +1 -1
- wrfrun/extension/goos_sst/res/__init__.py +17 -0
- wrfrun/extension/goos_sst/utils.py +21 -5
- 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 +215 -99
- wrfrun/model/wrf/exec_wrap.py +49 -35
- wrfrun/model/wrf/namelist.py +79 -4
- wrfrun/model/wrf/{_metgrid.py → utils.py} +36 -2
- wrfrun/model/wrf/vtable.py +2 -1
- wrfrun/res/__init__.py +8 -5
- wrfrun/res/config/config.template.toml +50 -0
- wrfrun/res/{config.toml.template → config/wrf.template.toml} +7 -46
- 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.8.dist-info → wrfrun-0.1.9.dist-info}/METADATA +3 -2
- 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.8.dist-info/RECORD +0 -51
- {wrfrun-0.1.8.dist-info → wrfrun-0.1.9.dist-info}/WHEEL +0 -0
wrfrun/core/server.py
CHANGED
|
@@ -8,7 +8,6 @@ In order to report the progress to user, ``wrfrun`` provides :class:`WRFRunServe
|
|
|
8
8
|
.. autosummary::
|
|
9
9
|
:toctree: generated/
|
|
10
10
|
|
|
11
|
-
get_wrf_simulated_seconds
|
|
12
11
|
WRFRunServer
|
|
13
12
|
WRFRunServerHandler
|
|
14
13
|
stop_server
|
|
@@ -16,11 +15,11 @@ In order to report the progress to user, ``wrfrun`` provides :class:`WRFRunServe
|
|
|
16
15
|
|
|
17
16
|
import socket
|
|
18
17
|
import socketserver
|
|
19
|
-
import
|
|
18
|
+
from collections.abc import Callable
|
|
20
19
|
from datetime import datetime
|
|
21
20
|
from json import dumps
|
|
22
21
|
from time import time
|
|
23
|
-
from typing import Tuple
|
|
22
|
+
from typing import Tuple
|
|
24
23
|
|
|
25
24
|
from .config import WRFRUNConfig
|
|
26
25
|
from ..utils import logger
|
|
@@ -29,40 +28,6 @@ WRFRUN_SERVER_INSTANCE = None
|
|
|
29
28
|
WRFRUN_SERVER_THREAD = None
|
|
30
29
|
|
|
31
30
|
|
|
32
|
-
def get_wrf_simulated_seconds(start_datetime: datetime, log_file_path: Optional[str] = None) -> int:
|
|
33
|
-
"""
|
|
34
|
-
Read the latest line of WRF's log file and calculate how many seconds WRF has integrated.
|
|
35
|
-
|
|
36
|
-
:param start_datetime: WRF start datetime.
|
|
37
|
-
:type start_datetime: datetime
|
|
38
|
-
:param log_file_path: Absolute path of the log file to be parsed.
|
|
39
|
-
:type log_file_path: str
|
|
40
|
-
:return: Integrated seconds. If this method fails to calculate the time, the returned value is ``-1``.
|
|
41
|
-
:rtype: int
|
|
42
|
-
"""
|
|
43
|
-
# use linux cmd to get the latest line of wrf log files
|
|
44
|
-
if log_file_path is None:
|
|
45
|
-
log_file_path = WRFRUNConfig.parse_resource_uri(f"{WRFRUNConfig.WRF_WORK_PATH}/rsl.out.0000")
|
|
46
|
-
res = subprocess.run(["tail", "-n", "1", log_file_path], capture_output=True)
|
|
47
|
-
log_text = res.stdout.decode()
|
|
48
|
-
|
|
49
|
-
if not (log_text.startswith("d01") or log_text.startswith("d02")):
|
|
50
|
-
return -1
|
|
51
|
-
|
|
52
|
-
time_string = log_text.split()[1]
|
|
53
|
-
|
|
54
|
-
try:
|
|
55
|
-
current_datetime = datetime.strptime(time_string, "%Y-%m-%d_%H:%M:%S")
|
|
56
|
-
# remove timezone info so we can calculate.
|
|
57
|
-
date_delta = current_datetime - start_datetime.replace(tzinfo=None)
|
|
58
|
-
seconds = date_delta.days * 24 * 60 * 60 + date_delta.seconds
|
|
59
|
-
|
|
60
|
-
except ValueError:
|
|
61
|
-
seconds = -1
|
|
62
|
-
|
|
63
|
-
return seconds
|
|
64
|
-
|
|
65
|
-
|
|
66
31
|
class WRFRunServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
|
67
32
|
"""
|
|
68
33
|
A socket server to report time usage.
|
|
@@ -98,13 +63,13 @@ class WRFRunServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
|
|
98
63
|
Path of the log file the server will read.
|
|
99
64
|
"""
|
|
100
65
|
|
|
101
|
-
def __init__(self, start_date: datetime,
|
|
66
|
+
def __init__(self, start_date: datetime, total_simulate_seconds: int, *args, **kwargs) -> None:
|
|
102
67
|
"""
|
|
103
68
|
|
|
104
69
|
:param start_date: The simulation's start date.
|
|
105
70
|
:type start_date: datetime
|
|
106
|
-
:param
|
|
107
|
-
:type
|
|
71
|
+
:param total_simulate_seconds: The total seconds the simulation will integrate.
|
|
72
|
+
:type total_simulate_seconds: int
|
|
108
73
|
:param args: Other positional arguments passed to parent class.
|
|
109
74
|
:type args:
|
|
110
75
|
:param kwargs: Other keyword arguments passed to parent class.
|
|
@@ -119,12 +84,7 @@ class WRFRunServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
|
|
119
84
|
self.start_date = start_date
|
|
120
85
|
|
|
121
86
|
# record how many seconds the wrf will integral
|
|
122
|
-
self.
|
|
123
|
-
|
|
124
|
-
# we need to parse the log file to track the simulation progress.
|
|
125
|
-
self.wrf_log_path = WRFRUNConfig.parse_resource_uri(f"{WRFRUNConfig.WRF_WORK_PATH}/rsl.out.0000")
|
|
126
|
-
logger.debug("WRFRun Server will try to track simulation progress with following log files:")
|
|
127
|
-
logger.debug(f"WRF: {self.wrf_log_path}")
|
|
87
|
+
self.total_simulate_seconds = total_simulate_seconds
|
|
128
88
|
|
|
129
89
|
def server_bind(self):
|
|
130
90
|
"""
|
|
@@ -144,33 +104,84 @@ class WRFRunServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
|
|
144
104
|
"""
|
|
145
105
|
return self.start_timestamp
|
|
146
106
|
|
|
147
|
-
def
|
|
107
|
+
def get_model_simulate_settings(self) -> Tuple[datetime, int]:
|
|
148
108
|
"""
|
|
149
109
|
Get the start date of the case the NWP simulates and the total seconds of the simulation.
|
|
150
110
|
|
|
151
111
|
:return: (start date, simulation seconds)
|
|
152
112
|
:rtype: tuple
|
|
153
113
|
"""
|
|
154
|
-
return self.start_date, self.
|
|
114
|
+
return self.start_date, self.total_simulate_seconds
|
|
155
115
|
|
|
156
116
|
|
|
157
117
|
class WRFRunServerHandler(socketserver.StreamRequestHandler):
|
|
158
118
|
"""
|
|
159
|
-
|
|
119
|
+
:class:`WRFRunServer` handler.
|
|
120
|
+
|
|
121
|
+
This handler can report time usage and simulation progress of the running model, simulation settings, and stop the server:
|
|
122
|
+
|
|
123
|
+
1. If this handler receives ``"stop"``, it stops the server.
|
|
124
|
+
2. If this handler receives ``"debug"``, it returns the simulation settings in JSON.
|
|
125
|
+
3. It returns time usage and simulation progress in JSON when receiving any other messages.
|
|
126
|
+
|
|
127
|
+
**On receiving "stop"**
|
|
128
|
+
|
|
129
|
+
This handler will stop the server, and return a plain message ``Server stop``.
|
|
130
|
+
|
|
131
|
+
**On receiving "debug"**
|
|
132
|
+
|
|
133
|
+
This handler will return simulation settings in a JSON string like:
|
|
134
|
+
|
|
135
|
+
.. code-block:: json
|
|
136
|
+
|
|
137
|
+
{
|
|
138
|
+
"start_date": "2021-03-25 00:00",
|
|
139
|
+
"total_simulate_seconds": 360000,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
**On receiving any other messages**
|
|
143
|
+
|
|
144
|
+
This handler will return time usage and simulation progress in a JSON string like:
|
|
145
|
+
|
|
146
|
+
.. code-block:: json
|
|
147
|
+
|
|
148
|
+
{
|
|
149
|
+
"usage": 3600,
|
|
150
|
+
"status": "geogrid",
|
|
151
|
+
"progress": 35,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
where ``usage`` represents the seconds ``wrfrun`` has spent running the NWP model,
|
|
155
|
+
``status`` represents work status,
|
|
156
|
+
``progress`` represents simulation progress of the status in percentage.
|
|
160
157
|
"""
|
|
161
|
-
def __init__(self, request, client_address, server: WRFRunServer) -> None:
|
|
158
|
+
def __init__(self, request, client_address, server: WRFRunServer, log_parse_func: Callable[[datetime], int] | None) -> None:
|
|
159
|
+
"""
|
|
160
|
+
:class:`WRFRunServer` handler.
|
|
161
|
+
|
|
162
|
+
:param request:
|
|
163
|
+
:type request:
|
|
164
|
+
:param client_address:
|
|
165
|
+
:type client_address:
|
|
166
|
+
:param server: :class:`WRFRunServer` instance.
|
|
167
|
+
:type server: WRFRunServer
|
|
168
|
+
:param log_parse_func: Function used to get simulated seconds from model's log file.
|
|
169
|
+
If the function can't parse the simulated seconds, it should return ``-1``.
|
|
170
|
+
:type log_parse_func: Callable[[datetime], int]
|
|
171
|
+
"""
|
|
162
172
|
super().__init__(request, client_address, server)
|
|
163
173
|
|
|
164
174
|
# get server
|
|
165
175
|
self.server: WRFRunServer = server
|
|
176
|
+
self.log_parse_func = log_parse_func
|
|
166
177
|
|
|
167
|
-
def calculate_time_usage(self) ->
|
|
178
|
+
def calculate_time_usage(self) -> int:
|
|
168
179
|
"""
|
|
169
180
|
Calculate the duration from the server's start time to the present,
|
|
170
181
|
which represents the time ``wrfrun`` has spent running the NWP model.
|
|
171
182
|
|
|
172
|
-
:return:
|
|
173
|
-
:rtype:
|
|
183
|
+
:return: Seconds.
|
|
184
|
+
:rtype: int
|
|
174
185
|
"""
|
|
175
186
|
# get current timestamp
|
|
176
187
|
current_timestamp = datetime.fromtimestamp(time())
|
|
@@ -179,42 +190,34 @@ class WRFRunServerHandler(socketserver.StreamRequestHandler):
|
|
|
179
190
|
seconds_diff = current_timestamp - self.server.get_start_time()
|
|
180
191
|
seconds_diff = seconds_diff.seconds
|
|
181
192
|
|
|
182
|
-
|
|
183
|
-
seconds = seconds_diff % 60
|
|
184
|
-
minutes = (seconds_diff % 3600) // 60
|
|
185
|
-
hours = seconds_diff // 3600
|
|
186
|
-
|
|
187
|
-
time_usage = ":".join([
|
|
188
|
-
str(hours).rjust(2, '0'),
|
|
189
|
-
str(minutes).rjust(2, '0'),
|
|
190
|
-
str(seconds).rjust(2, '0')
|
|
191
|
-
])
|
|
193
|
+
return seconds_diff
|
|
192
194
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def calculate_progress(self) -> str:
|
|
195
|
+
def calculate_progress(self) -> tuple[str, int]:
|
|
196
196
|
"""
|
|
197
197
|
Read the log file and calculate the simulation progress.
|
|
198
198
|
|
|
199
|
-
:return:
|
|
200
|
-
|
|
199
|
+
:return: ``(status, progress)``. ``status`` represents work status,
|
|
200
|
+
``progress`` represents simulation progress of the status in percentage.
|
|
201
|
+
:rtype: tuple[str, int]
|
|
201
202
|
"""
|
|
202
|
-
start_date, simulate_seconds = self.server.
|
|
203
|
+
start_date, simulate_seconds = self.server.get_model_simulate_settings()
|
|
203
204
|
|
|
204
|
-
|
|
205
|
+
if self.log_parse_func is None:
|
|
206
|
+
simulated_seconds = -1
|
|
207
|
+
else:
|
|
208
|
+
simulated_seconds = self.log_parse_func(start_date)
|
|
205
209
|
|
|
206
210
|
if simulated_seconds > 0:
|
|
207
211
|
progress = simulated_seconds * 100 // simulate_seconds
|
|
208
|
-
|
|
209
212
|
else:
|
|
210
|
-
progress =
|
|
213
|
+
progress = -1
|
|
211
214
|
|
|
212
215
|
status = WRFRUNConfig.WRFRUN_WORK_STATUS
|
|
213
216
|
|
|
214
217
|
if status == "":
|
|
215
218
|
status = "*"
|
|
216
219
|
|
|
217
|
-
return
|
|
220
|
+
return status, progress
|
|
218
221
|
|
|
219
222
|
def handle(self) -> None:
|
|
220
223
|
"""
|
|
@@ -229,17 +232,17 @@ class WRFRunServerHandler(socketserver.StreamRequestHandler):
|
|
|
229
232
|
self.wfile.write(f"Server stop\n".encode())
|
|
230
233
|
|
|
231
234
|
elif msg == "debug":
|
|
232
|
-
start_date, simulate_seconds = self.server.
|
|
235
|
+
start_date, simulate_seconds = self.server.get_model_simulate_settings()
|
|
233
236
|
start_date = start_date.strftime("%Y-%m-%d %H:%M")
|
|
234
237
|
|
|
235
|
-
self.wfile.write(
|
|
238
|
+
self.wfile.write(dumps({"start_date": start_date, "total_seconds": simulate_seconds}).encode())
|
|
236
239
|
|
|
237
240
|
else:
|
|
238
|
-
progress = self.calculate_progress()
|
|
241
|
+
status, progress = self.calculate_progress()
|
|
239
242
|
time_usage = self.calculate_time_usage()
|
|
240
243
|
|
|
241
244
|
# send the message
|
|
242
|
-
self.wfile.write(
|
|
245
|
+
self.wfile.write(dumps({"usage": time_usage, "status": status, "progress": progress}).encode())
|
|
243
246
|
|
|
244
247
|
|
|
245
248
|
def stop_server(socket_ip: str, socket_port: int):
|
|
@@ -266,4 +269,4 @@ def stop_server(socket_ip: str, socket_port: int):
|
|
|
266
269
|
logger.warning("Fail to stop WRFRunServer, maybe it doesn't start at all.")
|
|
267
270
|
|
|
268
271
|
|
|
269
|
-
__all__ = ["WRFRunServer", "WRFRunServerHandler", "
|
|
272
|
+
__all__ = ["WRFRunServer", "WRFRunServerHandler", "stop_server"]
|
|
@@ -4,11 +4,11 @@ wrfrun.extension.goos_sst
|
|
|
4
4
|
|
|
5
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
6
|
|
|
7
|
-
|
|
8
|
-
:doc:`
|
|
9
|
-
:doc:`res </api/extension.goos_sst.res>`
|
|
10
|
-
:doc:`utils </api/extension.goos_sst.utils>`
|
|
11
|
-
|
|
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
12
|
|
|
13
13
|
Important Note
|
|
14
14
|
**************
|
|
@@ -16,7 +16,6 @@ from os.path import dirname
|
|
|
16
16
|
import cfgrib as cf
|
|
17
17
|
import numpy as np
|
|
18
18
|
from pandas import to_datetime
|
|
19
|
-
from seafog import goos_sst_find_data, goos_sst_parser
|
|
20
19
|
from xarray import DataArray
|
|
21
20
|
|
|
22
21
|
from .utils import create_sst_grib
|
|
@@ -40,6 +39,10 @@ def merge_era5_goos_sst_grib(surface_grib_path: str, save_path: str, sst_data_sa
|
|
|
40
39
|
Please check ``seafog.goos_sst_find_data`` for more information.
|
|
41
40
|
:type resolution: str
|
|
42
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
|
+
|
|
43
46
|
dataset_list = cf.open_datasets(surface_grib_path)
|
|
44
47
|
|
|
45
48
|
dataset = None
|
|
@@ -4,4 +4,4 @@ Code | Code | 1 | 2 | Name | Units | Description
|
|
|
4
4
|
34 | 1 | 0 | | SST | K | Sea-Surface Temperature |
|
|
5
5
|
-----+------+------+------+----------+----------+------------------------------------------+
|
|
6
6
|
|
|
7
|
-
# Vtable setting for GRIB file created by wrfrun.extension.
|
|
7
|
+
# Vtable setting for GRIB file created by wrfrun.extension.goos_sst
|
|
@@ -1,3 +1,20 @@
|
|
|
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
|
+
|
|
1
18
|
from os.path import abspath, dirname
|
|
2
19
|
|
|
3
20
|
|
|
@@ -1,3 +1,15 @@
|
|
|
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
|
+
|
|
1
13
|
from cfgrib.xarray_to_grib import to_grib
|
|
2
14
|
from numpy.dtypes import DateTime64DType
|
|
3
15
|
from pandas import to_datetime
|
|
@@ -8,12 +20,16 @@ from wrfrun.utils import logger
|
|
|
8
20
|
|
|
9
21
|
def create_sst_grib(data: DataArray, save_path: str):
|
|
10
22
|
"""
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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**.
|
|
16
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
|
|
17
33
|
"""
|
|
18
34
|
# check the data's dimensions.
|
|
19
35
|
for _dim in ["time", "longitude", "latitude"]:
|
|
@@ -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 *
|