vortex-nwp 2.0.0b1__py3-none-any.whl → 2.0.0b2__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.
- vortex/__init__.py +59 -45
- vortex/algo/__init__.py +3 -2
- vortex/algo/components.py +940 -614
- vortex/algo/mpitools.py +802 -497
- vortex/algo/serversynctools.py +34 -33
- vortex/config.py +19 -22
- vortex/data/__init__.py +9 -3
- vortex/data/abstractstores.py +593 -655
- vortex/data/containers.py +217 -162
- vortex/data/contents.py +65 -39
- vortex/data/executables.py +93 -102
- vortex/data/flow.py +40 -34
- vortex/data/geometries.py +228 -132
- vortex/data/handlers.py +428 -225
- vortex/data/outflow.py +15 -15
- vortex/data/providers.py +185 -163
- vortex/data/resources.py +48 -42
- vortex/data/stores.py +544 -413
- vortex/gloves.py +114 -87
- vortex/layout/__init__.py +1 -8
- vortex/layout/contexts.py +150 -84
- vortex/layout/dataflow.py +353 -202
- vortex/layout/monitor.py +264 -128
- vortex/nwp/__init__.py +5 -2
- vortex/nwp/algo/__init__.py +14 -5
- vortex/nwp/algo/assim.py +205 -151
- vortex/nwp/algo/clim.py +683 -517
- vortex/nwp/algo/coupling.py +447 -225
- vortex/nwp/algo/eda.py +437 -229
- vortex/nwp/algo/eps.py +403 -231
- vortex/nwp/algo/forecasts.py +420 -271
- vortex/nwp/algo/fpserver.py +683 -307
- vortex/nwp/algo/ifsnaming.py +205 -145
- vortex/nwp/algo/ifsroot.py +210 -122
- vortex/nwp/algo/monitoring.py +132 -76
- vortex/nwp/algo/mpitools.py +321 -191
- vortex/nwp/algo/odbtools.py +617 -353
- vortex/nwp/algo/oopsroot.py +449 -273
- vortex/nwp/algo/oopstests.py +90 -56
- vortex/nwp/algo/request.py +287 -206
- vortex/nwp/algo/stdpost.py +878 -522
- vortex/nwp/data/__init__.py +22 -4
- vortex/nwp/data/assim.py +125 -137
- vortex/nwp/data/boundaries.py +121 -68
- vortex/nwp/data/climfiles.py +193 -211
- vortex/nwp/data/configfiles.py +73 -69
- vortex/nwp/data/consts.py +426 -401
- vortex/nwp/data/ctpini.py +59 -43
- vortex/nwp/data/diagnostics.py +94 -66
- vortex/nwp/data/eda.py +50 -51
- vortex/nwp/data/eps.py +195 -146
- vortex/nwp/data/executables.py +440 -434
- vortex/nwp/data/fields.py +63 -48
- vortex/nwp/data/gridfiles.py +183 -111
- vortex/nwp/data/logs.py +250 -217
- vortex/nwp/data/modelstates.py +180 -151
- vortex/nwp/data/monitoring.py +72 -99
- vortex/nwp/data/namelists.py +254 -202
- vortex/nwp/data/obs.py +400 -308
- vortex/nwp/data/oopsexec.py +22 -20
- vortex/nwp/data/providers.py +90 -65
- vortex/nwp/data/query.py +71 -82
- vortex/nwp/data/stores.py +49 -36
- vortex/nwp/data/surfex.py +136 -137
- vortex/nwp/syntax/__init__.py +1 -1
- vortex/nwp/syntax/stdattrs.py +173 -111
- vortex/nwp/tools/__init__.py +2 -2
- vortex/nwp/tools/addons.py +22 -17
- vortex/nwp/tools/agt.py +24 -12
- vortex/nwp/tools/bdap.py +16 -5
- vortex/nwp/tools/bdcp.py +4 -1
- vortex/nwp/tools/bdm.py +3 -0
- vortex/nwp/tools/bdmp.py +14 -9
- vortex/nwp/tools/conftools.py +728 -378
- vortex/nwp/tools/drhook.py +12 -8
- vortex/nwp/tools/grib.py +65 -39
- vortex/nwp/tools/gribdiff.py +22 -17
- vortex/nwp/tools/ifstools.py +82 -42
- vortex/nwp/tools/igastuff.py +167 -143
- vortex/nwp/tools/mars.py +14 -2
- vortex/nwp/tools/odb.py +234 -125
- vortex/nwp/tools/partitioning.py +61 -37
- vortex/nwp/tools/satrad.py +27 -12
- vortex/nwp/util/async.py +83 -55
- vortex/nwp/util/beacon.py +10 -10
- vortex/nwp/util/diffpygram.py +174 -86
- vortex/nwp/util/ens.py +144 -63
- vortex/nwp/util/hooks.py +30 -19
- vortex/nwp/util/taskdeco.py +28 -24
- vortex/nwp/util/usepygram.py +278 -172
- vortex/nwp/util/usetnt.py +31 -17
- vortex/sessions.py +72 -39
- vortex/syntax/__init__.py +1 -1
- vortex/syntax/stdattrs.py +410 -171
- vortex/syntax/stddeco.py +31 -22
- vortex/toolbox.py +327 -192
- vortex/tools/__init__.py +11 -2
- vortex/tools/actions.py +125 -59
- vortex/tools/addons.py +111 -92
- vortex/tools/arm.py +42 -22
- vortex/tools/compression.py +72 -69
- vortex/tools/date.py +11 -4
- vortex/tools/delayedactions.py +242 -132
- vortex/tools/env.py +75 -47
- vortex/tools/folder.py +342 -171
- vortex/tools/grib.py +311 -149
- vortex/tools/lfi.py +423 -216
- vortex/tools/listings.py +109 -40
- vortex/tools/names.py +218 -156
- vortex/tools/net.py +632 -298
- vortex/tools/parallelism.py +93 -61
- vortex/tools/prestaging.py +55 -31
- vortex/tools/schedulers.py +172 -105
- vortex/tools/services.py +402 -333
- vortex/tools/storage.py +293 -358
- vortex/tools/surfex.py +24 -24
- vortex/tools/systems.py +1211 -631
- vortex/tools/targets.py +156 -100
- vortex/util/__init__.py +1 -1
- vortex/util/config.py +377 -327
- vortex/util/empty.py +2 -2
- vortex/util/helpers.py +56 -24
- vortex/util/introspection.py +18 -12
- vortex/util/iosponge.py +8 -4
- vortex/util/roles.py +4 -6
- vortex/util/storefunctions.py +39 -13
- vortex/util/structs.py +3 -3
- vortex/util/worker.py +29 -17
- vortex_nwp-2.0.0b2.dist-info/METADATA +66 -0
- vortex_nwp-2.0.0b2.dist-info/RECORD +142 -0
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/WHEEL +1 -1
- vortex/layout/appconf.py +0 -109
- vortex/layout/jobs.py +0 -1276
- vortex/layout/nodes.py +0 -1424
- vortex/layout/subjobs.py +0 -464
- vortex_nwp-2.0.0b1.dist-info/METADATA +0 -50
- vortex_nwp-2.0.0b1.dist-info/RECORD +0 -146
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/LICENSE +0 -0
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/top_level.txt +0 -0
vortex/tools/listings.py
CHANGED
|
@@ -17,7 +17,7 @@ __all__ = []
|
|
|
17
17
|
|
|
18
18
|
def use_in_shell(sh, **kw):
|
|
19
19
|
"""Extend current shell with the arpifs_listings interface defined by optional arguments."""
|
|
20
|
-
kw[
|
|
20
|
+
kw["shell"] = sh
|
|
21
21
|
return footprints.proxy.addon(**kw)
|
|
22
22
|
|
|
23
23
|
|
|
@@ -30,10 +30,10 @@ class ArpIfsListingDiff_Result:
|
|
|
30
30
|
self._jos_diff = jos_diff
|
|
31
31
|
|
|
32
32
|
def __str__(self):
|
|
33
|
-
return
|
|
34
|
-
repr(self).rstrip(
|
|
33
|
+
return "{:s} | NormsOk={:b} JoTablesOk={:b}>".format(
|
|
34
|
+
repr(self).rstrip(">"),
|
|
35
35
|
all(self._norms_eq.values()),
|
|
36
|
-
all(self._jos_eq.values())
|
|
36
|
+
all(self._jos_eq.values()),
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
def differences(self):
|
|
@@ -43,10 +43,24 @@ class ArpIfsListingDiff_Result:
|
|
|
43
43
|
if all(self._norms_eq.values()):
|
|
44
44
|
print("Norms check succeeded for all steps.")
|
|
45
45
|
else:
|
|
46
|
-
print(
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
print(
|
|
47
|
+
"Norms check succeeded for steps:\n {:s}".format(
|
|
48
|
+
"\n ".join(
|
|
49
|
+
[str(k) for k, v in self._norms_eq.items() if v]
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
print(
|
|
54
|
+
"Norms check FAILED for steps:\n {:s}".format(
|
|
55
|
+
"\n ".join(
|
|
56
|
+
[
|
|
57
|
+
str(k)
|
|
58
|
+
for k, v in self._norms_eq.items()
|
|
59
|
+
if not v
|
|
60
|
+
]
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
)
|
|
50
64
|
else:
|
|
51
65
|
print("No norms found in the new listing or no matching norms.")
|
|
52
66
|
# print() # activation breaks test_arpifs_listings_integration.py
|
|
@@ -62,14 +76,22 @@ class ArpIfsListingDiff_Result:
|
|
|
62
76
|
for otype_k, otype_v in todo.items():
|
|
63
77
|
for sensor_k, sensor_v in otype_v.items():
|
|
64
78
|
for var_k, var_v in sensor_v.items():
|
|
65
|
-
if var_k ==
|
|
79
|
+
if var_k == "GLOBAL":
|
|
66
80
|
continue
|
|
67
|
-
print(
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
print(
|
|
82
|
+
" > {:s} > {:s} > {:4s} : d_n={:<9d} d_jo={:f}".format(
|
|
83
|
+
otype_k,
|
|
84
|
+
sensor_k,
|
|
85
|
+
var_k,
|
|
86
|
+
var_v["n"]["diff"],
|
|
87
|
+
var_v["jo"]["diff"],
|
|
88
|
+
)
|
|
89
|
+
)
|
|
70
90
|
diffprinted = True
|
|
71
91
|
else:
|
|
72
|
-
print(
|
|
92
|
+
print(
|
|
93
|
+
"No Jo-Tables were found or the number of Jo-Tables do not match."
|
|
94
|
+
)
|
|
73
95
|
|
|
74
96
|
|
|
75
97
|
class ArpIfsListingDiff_Status:
|
|
@@ -81,7 +103,7 @@ class ArpIfsListingDiff_Status:
|
|
|
81
103
|
self._result = ArpIfsListingDiff_Result(norms_eq, jos_eq, jos_diff)
|
|
82
104
|
|
|
83
105
|
def __str__(self):
|
|
84
|
-
return
|
|
106
|
+
return "{:s} | rc={:b}>".format(repr(self).rstrip(">"), bool(self))
|
|
85
107
|
|
|
86
108
|
@property
|
|
87
109
|
def result(self):
|
|
@@ -96,12 +118,12 @@ class ArpIfsListingsTool(addons.Addon):
|
|
|
96
118
|
"""Interface to arpifs_listings (designed as a shell Addon)."""
|
|
97
119
|
|
|
98
120
|
_footprint = dict(
|
|
99
|
-
info=
|
|
121
|
+
info="Default arpifs_listings interface",
|
|
100
122
|
attr=dict(
|
|
101
123
|
kind=dict(
|
|
102
|
-
values=[
|
|
124
|
+
values=["arpifs_listings"],
|
|
103
125
|
),
|
|
104
|
-
)
|
|
126
|
+
),
|
|
105
127
|
)
|
|
106
128
|
|
|
107
129
|
def arpifslist_diff(self, listing1, listing2):
|
|
@@ -147,17 +169,24 @@ class ArpIfsListingsTool(addons.Addon):
|
|
|
147
169
|
if not l1_jos == l2_jos:
|
|
148
170
|
# If the JoTables list is not consistent: do nothing
|
|
149
171
|
if list(l1_jos.keys()) == list(l2_jos.keys()):
|
|
150
|
-
for table1, table2 in zip(
|
|
172
|
+
for table1, table2 in zip(
|
|
173
|
+
l1_jos.values(), l2_jos.values()
|
|
174
|
+
):
|
|
151
175
|
jos_eq[table1.name] = table1 == table2
|
|
152
176
|
if not jos_eq[table1.name]:
|
|
153
177
|
jos_diff[table1.name] = OrderedDict()
|
|
154
178
|
# We only save differences when deltaN or deltaJo != 0
|
|
155
|
-
for otype_k, otype_v in table2.compute_diff(
|
|
179
|
+
for otype_k, otype_v in table2.compute_diff(
|
|
180
|
+
table1
|
|
181
|
+
).items():
|
|
156
182
|
otype_tmp = OrderedDict()
|
|
157
183
|
for sensor_k, sensor_v in otype_v.items():
|
|
158
184
|
sensor_tmp = OrderedDict()
|
|
159
185
|
for k, v in sensor_v.items():
|
|
160
|
-
if
|
|
186
|
+
if (
|
|
187
|
+
v["n"]["diff"] != 0
|
|
188
|
+
or v["jo"]["diff"] != 0
|
|
189
|
+
):
|
|
161
190
|
sensor_tmp[k] = v
|
|
162
191
|
if len(sensor_tmp):
|
|
163
192
|
otype_tmp[sensor_k] = sensor_tmp
|
|
@@ -174,7 +203,9 @@ class ArpifsListingsFormatAdapter(FormatAdapterAbstractImplementation):
|
|
|
174
203
|
_footprint = dict(
|
|
175
204
|
attr=dict(
|
|
176
205
|
format=dict(
|
|
177
|
-
values=[
|
|
206
|
+
values=[
|
|
207
|
+
"ARPIFSLIST",
|
|
208
|
+
],
|
|
178
209
|
),
|
|
179
210
|
)
|
|
180
211
|
)
|
|
@@ -196,8 +227,15 @@ class ArpifsListingsFormatAdapter(FormatAdapterAbstractImplementation):
|
|
|
196
227
|
def lines(self):
|
|
197
228
|
"""Return an array populated with the listing file lines."""
|
|
198
229
|
if self._lines is None:
|
|
199
|
-
with open(
|
|
200
|
-
self.
|
|
230
|
+
with open(
|
|
231
|
+
self.filename,
|
|
232
|
+
self.openmode,
|
|
233
|
+
encoding="utf-8",
|
|
234
|
+
errors="replace",
|
|
235
|
+
) as f:
|
|
236
|
+
self._lines = [
|
|
237
|
+
l.rstrip("\n") for l in f
|
|
238
|
+
] # to remove trailing '\n'
|
|
201
239
|
return self._lines
|
|
202
240
|
|
|
203
241
|
def flush_lines(self):
|
|
@@ -210,7 +248,14 @@ class ArpifsListingsFormatAdapter(FormatAdapterAbstractImplementation):
|
|
|
210
248
|
if self._end_is_reached is None:
|
|
211
249
|
self._end_is_reached = False
|
|
212
250
|
for line in self.lines:
|
|
213
|
-
if any(
|
|
251
|
+
if any(
|
|
252
|
+
[
|
|
253
|
+
p in line
|
|
254
|
+
for p in listings.OutputListing.patterns[
|
|
255
|
+
"end_is_reached"
|
|
256
|
+
]
|
|
257
|
+
]
|
|
258
|
+
):
|
|
214
259
|
self._end_is_reached = True
|
|
215
260
|
break
|
|
216
261
|
return self._end_is_reached
|
|
@@ -237,7 +282,9 @@ class ArpifsListingsFormatAdapter(FormatAdapterAbstractImplementation):
|
|
|
237
282
|
def cost_functions(self):
|
|
238
283
|
"""Return a :class:`arpifs_listings.jo_tables.JoTables` object."""
|
|
239
284
|
if self._costs is None:
|
|
240
|
-
self._costs = cost_functions.CostFunctions(
|
|
285
|
+
self._costs = cost_functions.CostFunctions(
|
|
286
|
+
self.filename, self.lines
|
|
287
|
+
)
|
|
241
288
|
if not self.fmtdelayedopen:
|
|
242
289
|
self.flush_lines()
|
|
243
290
|
return self._costs
|
|
@@ -266,12 +313,15 @@ class ListBasedCutoffDispenser:
|
|
|
266
313
|
if f_dates:
|
|
267
314
|
f_cutoffs[k] = f_dates
|
|
268
315
|
if f_cutoffs:
|
|
269
|
-
self._max_cutoff = max(
|
|
316
|
+
self._max_cutoff = max(
|
|
317
|
+
[max(dates) for dates in f_cutoffs.values()]
|
|
318
|
+
)
|
|
270
319
|
else:
|
|
271
320
|
self._max_cutoff = None
|
|
272
321
|
self._default_cutoffs = defaultdict(lambda: self._max_cutoff)
|
|
273
|
-
self._default_cutoffs.update(
|
|
274
|
-
|
|
322
|
+
self._default_cutoffs.update(
|
|
323
|
+
{k: max(dates) for k, dates in f_cutoffs.items()}
|
|
324
|
+
)
|
|
275
325
|
self._fuse_per_obstype = fuse_per_obstype
|
|
276
326
|
|
|
277
327
|
@property
|
|
@@ -300,15 +350,21 @@ class BdmBufrListingsFormatAdapter(FormatAdapterAbstractImplementation):
|
|
|
300
350
|
_footprint = dict(
|
|
301
351
|
attr=dict(
|
|
302
352
|
format=dict(
|
|
303
|
-
values=[
|
|
353
|
+
values=[
|
|
354
|
+
"BDMBUFR_LISTING",
|
|
355
|
+
],
|
|
304
356
|
),
|
|
305
357
|
)
|
|
306
358
|
)
|
|
307
359
|
|
|
308
|
-
_RE_OBSTYPE_GRP = re.compile(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
360
|
+
_RE_OBSTYPE_GRP = re.compile(
|
|
361
|
+
r"^.*tentative\s+(?:d')?extraction\s+pour\s+'?(?P<obstype>\w+)'?\b",
|
|
362
|
+
re.IGNORECASE,
|
|
363
|
+
)
|
|
364
|
+
_RE_OBSTYPE_CUT = re.compile(
|
|
365
|
+
r"^.*cutoff\s+pour\s+'?(?P<obstype>\w+)'?\s*:\s*(?P<datetime>\d+)\b",
|
|
366
|
+
re.IGNORECASE,
|
|
367
|
+
)
|
|
312
368
|
|
|
313
369
|
def __init__(self, *kargs, **kwargs):
|
|
314
370
|
super().__init__(*kargs, **kwargs)
|
|
@@ -321,8 +377,15 @@ class BdmBufrListingsFormatAdapter(FormatAdapterAbstractImplementation):
|
|
|
321
377
|
def lines(self):
|
|
322
378
|
"""Return an array populated with the listing file lines."""
|
|
323
379
|
if self._lines is None:
|
|
324
|
-
with open(
|
|
325
|
-
self.
|
|
380
|
+
with open(
|
|
381
|
+
self.filename,
|
|
382
|
+
self.openmode,
|
|
383
|
+
encoding="utf-8",
|
|
384
|
+
errors="replace",
|
|
385
|
+
) as f:
|
|
386
|
+
self._lines = [
|
|
387
|
+
l.rstrip("\n") for l in f
|
|
388
|
+
] # to remove trailing '\n'
|
|
326
389
|
return self._lines
|
|
327
390
|
|
|
328
391
|
@property
|
|
@@ -338,11 +401,16 @@ class BdmBufrListingsFormatAdapter(FormatAdapterAbstractImplementation):
|
|
|
338
401
|
if l_match:
|
|
339
402
|
if cur_obstype is not None:
|
|
340
403
|
self._cutoffs[cur_obstype].append(None)
|
|
341
|
-
cur_obstype = l_match.group(
|
|
404
|
+
cur_obstype = l_match.group("obstype").lower()
|
|
342
405
|
if cur_obstype:
|
|
343
406
|
l_match = self._RE_OBSTYPE_CUT.match(line)
|
|
344
|
-
if
|
|
345
|
-
|
|
407
|
+
if (
|
|
408
|
+
l_match
|
|
409
|
+
and l_match.group("obstype").lower() == cur_obstype
|
|
410
|
+
):
|
|
411
|
+
self._cutoffs[cur_obstype].append(
|
|
412
|
+
Date(l_match.group("datetime"))
|
|
413
|
+
)
|
|
346
414
|
cur_obstype = None
|
|
347
415
|
if cur_obstype is not None:
|
|
348
416
|
self._cutoffs[cur_obstype].append(None)
|
|
@@ -350,5 +418,6 @@ class BdmBufrListingsFormatAdapter(FormatAdapterAbstractImplementation):
|
|
|
350
418
|
|
|
351
419
|
def cutoffs_dispenser(self, fuse_per_obstype=False):
|
|
352
420
|
"""Return a new :class:`CutoffDispenser` object."""
|
|
353
|
-
return ListBasedCutoffDispenser(
|
|
354
|
-
|
|
421
|
+
return ListBasedCutoffDispenser(
|
|
422
|
+
copy.deepcopy(self.cutoffs), fuse_per_obstype=fuse_per_obstype
|
|
423
|
+
)
|