vortex-nwp 2.2.0__py3-none-any.whl → 2.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.
- vortex/__init__.py +3 -2
- vortex/algo/components.py +20 -2
- vortex/algo/mpitools.py +5 -6
- vortex/data/executables.py +28 -0
- vortex/data/geometries.ini +89 -24
- vortex/data/providers.py +44 -10
- vortex/data/stores.py +110 -3
- vortex/nwp/algo/assim.py +1 -31
- vortex/nwp/algo/forecasts.py +30 -0
- vortex/nwp/algo/ifsroot.py +34 -20
- vortex/nwp/algo/monitoring.py +2 -2
- vortex/nwp/algo/odbtools.py +2 -2
- vortex/nwp/data/consts.py +61 -1
- vortex/nwp/data/diagnostics.py +2 -4
- vortex/nwp/tools/conftools.py +7 -6
- vortex/tools/systems.py +33 -3
- {vortex_nwp-2.2.0.dist-info → vortex_nwp-2.3.0.dist-info}/METADATA +4 -1
- {vortex_nwp-2.2.0.dist-info → vortex_nwp-2.3.0.dist-info}/RECORD +21 -21
- {vortex_nwp-2.2.0.dist-info → vortex_nwp-2.3.0.dist-info}/WHEEL +1 -1
- {vortex_nwp-2.2.0.dist-info → vortex_nwp-2.3.0.dist-info}/licenses/LICENSE +0 -0
- {vortex_nwp-2.2.0.dist-info → vortex_nwp-2.3.0.dist-info}/top_level.txt +0 -0
vortex/__init__.py
CHANGED
|
@@ -50,13 +50,14 @@ from .toolbox import promise as promise
|
|
|
50
50
|
from .toolbox import diff as diff
|
|
51
51
|
from .toolbox import defaults as defaults
|
|
52
52
|
from .toolbox import algo as task
|
|
53
|
+
from .toolbox import VortexForceComplete as VortexForceComplete
|
|
53
54
|
|
|
54
55
|
from . import nwp as nwp # footprints import
|
|
55
56
|
|
|
56
|
-
__version__ = "2.
|
|
57
|
+
__version__ = "2.3.0"
|
|
57
58
|
__prompt__ = "Vortex v-" + __version__ + ":"
|
|
58
59
|
|
|
59
|
-
__nextversion__ = "2.
|
|
60
|
+
__nextversion__ = "2.3.1"
|
|
60
61
|
__tocinfoline__ = "VORTEX core package"
|
|
61
62
|
|
|
62
63
|
__all__ = [
|
vortex/algo/components.py
CHANGED
|
@@ -1548,12 +1548,25 @@ class Expresso(ExecutableAlgoComponent):
|
|
|
1548
1548
|
attr=dict(
|
|
1549
1549
|
interpreter=dict(
|
|
1550
1550
|
info="The interpreter needed to run the script.",
|
|
1551
|
-
values=[
|
|
1551
|
+
values=[
|
|
1552
|
+
"current",
|
|
1553
|
+
"awk",
|
|
1554
|
+
"ksh",
|
|
1555
|
+
"bash",
|
|
1556
|
+
"perl",
|
|
1557
|
+
"python",
|
|
1558
|
+
"singularity",
|
|
1559
|
+
],
|
|
1552
1560
|
),
|
|
1553
1561
|
interpreter_path=dict(
|
|
1554
1562
|
info="The interpreter command.",
|
|
1555
1563
|
optional=True,
|
|
1556
1564
|
),
|
|
1565
|
+
interpreter_args=dict(
|
|
1566
|
+
info="Some options to pass to the expresso",
|
|
1567
|
+
optional=True,
|
|
1568
|
+
default="",
|
|
1569
|
+
),
|
|
1557
1570
|
engine=dict(values=["exec", "launch"]),
|
|
1558
1571
|
),
|
|
1559
1572
|
)
|
|
@@ -1581,11 +1594,16 @@ class Expresso(ExecutableAlgoComponent):
|
|
|
1581
1594
|
)
|
|
1582
1595
|
|
|
1583
1596
|
def _interpreter_args_fix(self, rh, opts):
|
|
1597
|
+
cmd_opts = shlex.split(self.interpreter_args)
|
|
1598
|
+
|
|
1584
1599
|
absexec = self.absexcutable(rh.container.localpath())
|
|
1585
1600
|
if self.interpreter == "awk":
|
|
1586
|
-
return ["-f", absexec]
|
|
1601
|
+
return [*cmd_opts, "-f", absexec]
|
|
1602
|
+
if self.interpreter == "singularity":
|
|
1603
|
+
return ["run", *cmd_opts, absexec]
|
|
1587
1604
|
else:
|
|
1588
1605
|
return [
|
|
1606
|
+
*cmd_opts,
|
|
1589
1607
|
absexec,
|
|
1590
1608
|
]
|
|
1591
1609
|
|
vortex/algo/mpitools.py
CHANGED
|
@@ -544,10 +544,6 @@ class MpiTool(footprints.FootprintBase):
|
|
|
544
544
|
"""When group are defined, associate each MPI rank with a "real" slot."""
|
|
545
545
|
if self._ranks_map_cache is None:
|
|
546
546
|
self._complex_ranks_map = False
|
|
547
|
-
if not self.envelope:
|
|
548
|
-
raise RuntimeError(
|
|
549
|
-
"Ranks mapping should always be used within an envelope."
|
|
550
|
-
)
|
|
551
547
|
# First deal with bingroups
|
|
552
548
|
ranks_map = dict()
|
|
553
549
|
has_bin_groups = not all([b.group is None for b in self.binaries])
|
|
@@ -624,7 +620,7 @@ class MpiTool(footprints.FootprintBase):
|
|
|
624
620
|
if self._complex_ranks_map or do_bin_distribution:
|
|
625
621
|
if not self.envelope:
|
|
626
622
|
raise RuntimeError(
|
|
627
|
-
"Ranks mapping
|
|
623
|
+
"Ranks mapping should always be used within an envelope."
|
|
628
624
|
)
|
|
629
625
|
if do_bin_distribution:
|
|
630
626
|
if not self._supports_manual_ranks_mapping:
|
|
@@ -1404,7 +1400,10 @@ class SRun(MpiTool):
|
|
|
1404
1400
|
),
|
|
1405
1401
|
optmap=dict(
|
|
1406
1402
|
default=footprints.FPDict(
|
|
1407
|
-
nn="nodes",
|
|
1403
|
+
nn="nodes",
|
|
1404
|
+
nnp="ntasks-per-node",
|
|
1405
|
+
np="ntasks",
|
|
1406
|
+
openmp="cpus-per-task",
|
|
1408
1407
|
)
|
|
1409
1408
|
),
|
|
1410
1409
|
slurmversion=dict(type=int, optional=True),
|
vortex/data/executables.py
CHANGED
|
@@ -106,6 +106,34 @@ class Script(Executable):
|
|
|
106
106
|
return self.rawopts
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
class SingularityImage(Executable):
|
|
110
|
+
"""Singularity container image executable."""
|
|
111
|
+
|
|
112
|
+
_footprint = dict(
|
|
113
|
+
attr=dict(
|
|
114
|
+
kind=dict(
|
|
115
|
+
values=["image"],
|
|
116
|
+
),
|
|
117
|
+
cmd=dict(
|
|
118
|
+
info="Command to run inside the container",
|
|
119
|
+
optional=True,
|
|
120
|
+
default="",
|
|
121
|
+
),
|
|
122
|
+
),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def realkind(self):
|
|
127
|
+
return "image"
|
|
128
|
+
|
|
129
|
+
# Called by AlgoComponent.spawn_command_line
|
|
130
|
+
def command_line(self, **opts):
|
|
131
|
+
return " ".join(
|
|
132
|
+
["--{:s} {:s}".format(opt, val) for opt, val in opts.items()]
|
|
133
|
+
+ [self.cmd]
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
109
137
|
class GnuScript(Executable):
|
|
110
138
|
"""Basic interpreted executable with standard command line arguments."""
|
|
111
139
|
|
vortex/data/geometries.ini
CHANGED
|
@@ -659,6 +659,13 @@ area = indonesie1
|
|
|
659
659
|
resolution = 2.50
|
|
660
660
|
runit = km
|
|
661
661
|
|
|
662
|
+
[asscomindonesie2sp]
|
|
663
|
+
info = Arome asscom14 - indonesie2 spectral geometry
|
|
664
|
+
kind = projected
|
|
665
|
+
area = indonesie2
|
|
666
|
+
resolution = 2.50
|
|
667
|
+
runit = km
|
|
668
|
+
|
|
662
669
|
[lace20km]
|
|
663
670
|
info = Coupling grid for LACE partners
|
|
664
671
|
kind = projected
|
|
@@ -673,6 +680,13 @@ area = lace
|
|
|
673
680
|
resolution = 8.0
|
|
674
681
|
runit = km
|
|
675
682
|
|
|
683
|
+
[lace47]
|
|
684
|
+
info = LACE canari domain
|
|
685
|
+
kind = projected
|
|
686
|
+
area = lace47
|
|
687
|
+
resolution = 4.71
|
|
688
|
+
runit = km
|
|
689
|
+
|
|
676
690
|
[afgt20km]
|
|
677
691
|
info = Coupling grid for afgt-Praha
|
|
678
692
|
kind = projected
|
|
@@ -1201,15 +1215,15 @@ nlon = 641
|
|
|
1201
1215
|
[paris1s100]
|
|
1202
1216
|
info = PARIS 0.01
|
|
1203
1217
|
kind = lonlat
|
|
1204
|
-
area =
|
|
1218
|
+
area = PARIS1S100
|
|
1205
1219
|
resolution = 0.01
|
|
1206
|
-
nlat =
|
|
1207
|
-
nlon =
|
|
1220
|
+
nlat = 187
|
|
1221
|
+
nlon = 279
|
|
1208
1222
|
|
|
1209
1223
|
[medalp1s100]
|
|
1210
1224
|
info = MEDALP 0.01
|
|
1211
1225
|
kind = lonlat
|
|
1212
|
-
area =
|
|
1226
|
+
area = MEDALP1S100
|
|
1213
1227
|
resolution = 0.01
|
|
1214
1228
|
nlat = 481
|
|
1215
1229
|
nlon = 501
|
|
@@ -1677,6 +1691,17 @@ nlat = 172800
|
|
|
1677
1691
|
latmax = 83.999
|
|
1678
1692
|
latmin = -55.999
|
|
1679
1693
|
|
|
1694
|
+
[srtm_01s]
|
|
1695
|
+
info = alternative to no_arctics7.5s used to create arome-500m PGD clim
|
|
1696
|
+
kind = lonlat
|
|
1697
|
+
area = srtm
|
|
1698
|
+
resolution = 1
|
|
1699
|
+
runit = s
|
|
1700
|
+
nlon = 999
|
|
1701
|
+
nlat = 999
|
|
1702
|
+
latmax = 999
|
|
1703
|
+
latmin = 999
|
|
1704
|
+
|
|
1680
1705
|
[europe_sw3s]
|
|
1681
1706
|
kind = lonlat
|
|
1682
1707
|
area = europe_sw
|
|
@@ -2468,39 +2493,39 @@ nlon = 896
|
|
|
2468
2493
|
resolution = 0.05
|
|
2469
2494
|
runit = deg
|
|
2470
2495
|
|
|
2471
|
-
[
|
|
2472
|
-
info = Shom HYCOM3D Med-
|
|
2496
|
+
[hycom3dmednowe]
|
|
2497
|
+
info = Shom HYCOM3D Med-NorthWest at 1/60
|
|
2473
2498
|
kind = lonlat
|
|
2474
|
-
area =
|
|
2475
|
-
nlat =
|
|
2476
|
-
nlon =
|
|
2499
|
+
area = mednowe
|
|
2500
|
+
nlat = 437
|
|
2501
|
+
nlon = 761
|
|
2477
2502
|
resolution = 0.017
|
|
2478
2503
|
runit = deg
|
|
2479
2504
|
|
|
2480
|
-
[
|
|
2481
|
-
info = Shom HYCOM3D Med-
|
|
2505
|
+
[hycom3dmedsowe]
|
|
2506
|
+
info = Shom HYCOM3D Med-SouthWest at 1/60
|
|
2482
2507
|
kind = lonlat
|
|
2483
|
-
area =
|
|
2484
|
-
nlat =
|
|
2485
|
-
nlon =
|
|
2508
|
+
area = medsowe
|
|
2509
|
+
nlat = 481
|
|
2510
|
+
nlon = 1080
|
|
2486
2511
|
resolution = 0.017
|
|
2487
2512
|
runit = deg
|
|
2488
2513
|
|
|
2489
|
-
[
|
|
2490
|
-
info = Shom HYCOM3D Med-
|
|
2514
|
+
[hycom3dmedea]
|
|
2515
|
+
info = Shom HYCOM3D Med-East at 1/60
|
|
2491
2516
|
kind = lonlat
|
|
2492
|
-
area =
|
|
2493
|
-
nlat =
|
|
2494
|
-
nlon =
|
|
2517
|
+
area = medea
|
|
2518
|
+
nlat = 706
|
|
2519
|
+
nlon = 855
|
|
2495
2520
|
resolution = 0.017
|
|
2496
2521
|
runit = deg
|
|
2497
2522
|
|
|
2498
|
-
[
|
|
2499
|
-
info = Shom HYCOM3D
|
|
2523
|
+
[hycom3dmedinte]
|
|
2524
|
+
info = Shom HYCOM3D Med-Interior at 1/60
|
|
2500
2525
|
kind = lonlat
|
|
2501
|
-
area =
|
|
2502
|
-
nlat =
|
|
2503
|
-
nlon =
|
|
2526
|
+
area = medinte
|
|
2527
|
+
nlat = 935
|
|
2528
|
+
nlon = 781
|
|
2504
2529
|
resolution = 0.017
|
|
2505
2530
|
runit = deg
|
|
2506
2531
|
|
|
@@ -2575,6 +2600,13 @@ area = corsica
|
|
|
2575
2600
|
resolution = 2.5
|
|
2576
2601
|
runit = km
|
|
2577
2602
|
|
|
2603
|
+
[nl2500]
|
|
2604
|
+
info = HARMONIE-AROME 2.5km NL domain for DAVAI
|
|
2605
|
+
kind = projected
|
|
2606
|
+
area = nl
|
|
2607
|
+
resolution = 2.5
|
|
2608
|
+
runit = km
|
|
2609
|
+
|
|
2578
2610
|
[cors1s40]
|
|
2579
2611
|
info = Corsica 0.025 deg
|
|
2580
2612
|
kind = lonlat
|
|
@@ -2669,6 +2701,39 @@ area = chmh2325
|
|
|
2669
2701
|
resolution = 2.33
|
|
2670
2702
|
runit = km
|
|
2671
2703
|
|
|
2704
|
+
[armcu]
|
|
2705
|
+
info = MUSC Single point ARMCU
|
|
2706
|
+
kind = unstructured
|
|
2707
|
+
area = armcu
|
|
2708
|
+
|
|
2709
|
+
[global31c1]
|
|
2710
|
+
info = ARPEGE T31C1.0 geometry (from Mitraillette tests)
|
|
2711
|
+
kind = gauss
|
|
2712
|
+
area = france
|
|
2713
|
+
truncation = 31
|
|
2714
|
+
stretching = 1.0
|
|
2715
|
+
|
|
2716
|
+
[global30c24]
|
|
2717
|
+
info = ARPEGE T30C2.4 geometry (from Mitraillette tests)
|
|
2718
|
+
kind = gauss
|
|
2719
|
+
area = france
|
|
2720
|
+
truncation = 30
|
|
2721
|
+
stretching = 2.4
|
|
2722
|
+
|
|
2723
|
+
[portugal21km]
|
|
2724
|
+
info = Mitraillette Portugal grid
|
|
2725
|
+
kind = projected
|
|
2726
|
+
area = portugal
|
|
2727
|
+
resolution = 21.3
|
|
2728
|
+
runit = km
|
|
2729
|
+
|
|
2730
|
+
[occitanie4km]
|
|
2731
|
+
info = Mitraillette Occitanie grid
|
|
2732
|
+
kind = projected
|
|
2733
|
+
area = occitanie
|
|
2734
|
+
resolution = 4.4
|
|
2735
|
+
runit = km
|
|
2736
|
+
|
|
2672
2737
|
#R ===================
|
|
2673
2738
|
#R Combined geometries
|
|
2674
2739
|
#R ===================
|
vortex/data/providers.py
CHANGED
|
@@ -64,13 +64,6 @@ class Provider(footprints.FootprintBase):
|
|
|
64
64
|
fastkeys={"namespace"},
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
-
def __init__(self, *args, **kw):
|
|
68
|
-
logger.debug("Abstract provider init %s", self.__class__)
|
|
69
|
-
super().__init__(*args, **kw)
|
|
70
|
-
|
|
71
|
-
if not self.username:
|
|
72
|
-
self.username = vortex.ticket().glove.user
|
|
73
|
-
|
|
74
67
|
def _str_more(self):
|
|
75
68
|
"""Additional information to print representation."""
|
|
76
69
|
try:
|
|
@@ -92,7 +85,9 @@ class Provider(footprints.FootprintBase):
|
|
|
92
85
|
|
|
93
86
|
def netuser_name(self, resource): # @UnusedVariable
|
|
94
87
|
"""Abstract method."""
|
|
95
|
-
|
|
88
|
+
if self.username is not None:
|
|
89
|
+
return self.username
|
|
90
|
+
return vortex.ticket().glove.user
|
|
96
91
|
|
|
97
92
|
def pathname(self, resource):
|
|
98
93
|
"""Abstract method."""
|
|
@@ -124,10 +119,11 @@ class Provider(footprints.FootprintBase):
|
|
|
124
119
|
The different operations of the algorithm can be redefined by subclasses.
|
|
125
120
|
"""
|
|
126
121
|
username = self.netuser_name(resource)
|
|
122
|
+
netloc = self.netloc(resource)
|
|
127
123
|
fullnetloc = (
|
|
128
124
|
"{:s}@{:s}".format(username, self.netloc(resource))
|
|
129
|
-
if username
|
|
130
|
-
else
|
|
125
|
+
if (username and netloc)
|
|
126
|
+
else netloc
|
|
131
127
|
)
|
|
132
128
|
logger.debug(
|
|
133
129
|
"scheme %s netloc %s normpath %s urlquery %s",
|
|
@@ -279,6 +275,44 @@ def set_namespace_from_cache_settings(usecache, usearchive):
|
|
|
279
275
|
return ".".join(("vortex", domain, "fr"))
|
|
280
276
|
|
|
281
277
|
|
|
278
|
+
class Git(Provider):
|
|
279
|
+
_footprint = dict(
|
|
280
|
+
info="Git provider",
|
|
281
|
+
attr=dict(
|
|
282
|
+
ref=dict(
|
|
283
|
+
type=str,
|
|
284
|
+
optional=True,
|
|
285
|
+
default=None,
|
|
286
|
+
info="The reference's SHA-1 hash id",
|
|
287
|
+
),
|
|
288
|
+
repo=dict(
|
|
289
|
+
type=str,
|
|
290
|
+
info="Path to the Git repository",
|
|
291
|
+
),
|
|
292
|
+
path=dict(
|
|
293
|
+
type=str,
|
|
294
|
+
info="File path within the repository",
|
|
295
|
+
),
|
|
296
|
+
),
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
def scheme(self, resource):
|
|
300
|
+
return "git"
|
|
301
|
+
|
|
302
|
+
def urlquery(self, resource):
|
|
303
|
+
return (
|
|
304
|
+
f"repo={self.repo}&ref={self.ref}"
|
|
305
|
+
if self.ref
|
|
306
|
+
else f"repo={self.repo}"
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
def basename(self, resource):
|
|
310
|
+
return self.path
|
|
311
|
+
|
|
312
|
+
def pathname(sef, resource):
|
|
313
|
+
return "."
|
|
314
|
+
|
|
315
|
+
|
|
282
316
|
class Vortex(Provider):
|
|
283
317
|
"""Main provider of the toolbox, using a fix-size path and a dedicated name factory."""
|
|
284
318
|
|
vortex/data/stores.py
CHANGED
|
@@ -8,8 +8,11 @@ Store objects use the :mod:`footprints` mechanism.
|
|
|
8
8
|
import copy
|
|
9
9
|
import ftplib
|
|
10
10
|
import io
|
|
11
|
+
from pathlib import Path
|
|
11
12
|
import os
|
|
12
13
|
import re
|
|
14
|
+
import shutil
|
|
15
|
+
import subprocess
|
|
13
16
|
|
|
14
17
|
from bronx.fancies import loggers
|
|
15
18
|
import footprints
|
|
@@ -33,6 +36,13 @@ __all__ = []
|
|
|
33
36
|
|
|
34
37
|
logger = loggers.getLogger(__name__)
|
|
35
38
|
|
|
39
|
+
try:
|
|
40
|
+
import pygit2
|
|
41
|
+
|
|
42
|
+
NO_PYGIT2 = False
|
|
43
|
+
except ImportError:
|
|
44
|
+
NO_PYGIT2 = True
|
|
45
|
+
|
|
36
46
|
|
|
37
47
|
def get_cache_location():
|
|
38
48
|
try:
|
|
@@ -335,7 +345,6 @@ class Finder(Store):
|
|
|
335
345
|
def _ftpinfos(self, remote, **kwargs):
|
|
336
346
|
args = kwargs.copy()
|
|
337
347
|
args["hostname"] = self.hostname()
|
|
338
|
-
args["logname"] = remote["username"]
|
|
339
348
|
port = self.hostname().netport
|
|
340
349
|
if port is not None:
|
|
341
350
|
args["port"] = port
|
|
@@ -422,6 +431,98 @@ class Finder(Store):
|
|
|
422
431
|
return rc
|
|
423
432
|
|
|
424
433
|
|
|
434
|
+
class GitStore(Store):
|
|
435
|
+
_footprint = dict(
|
|
436
|
+
info="A store to access Git repositories",
|
|
437
|
+
attr=dict(
|
|
438
|
+
scheme=dict(
|
|
439
|
+
values=["git"],
|
|
440
|
+
),
|
|
441
|
+
),
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
def gitget(self, remote, local, options):
|
|
445
|
+
if NO_PYGIT2:
|
|
446
|
+
raise ModuleNotFoundError(
|
|
447
|
+
"pygit2 is not installed in the current environment"
|
|
448
|
+
)
|
|
449
|
+
annex_cache_path = Path(remote["query"]["repo"][0])
|
|
450
|
+
|
|
451
|
+
# If no git reference is provided, only make a copy of the
|
|
452
|
+
# worktree
|
|
453
|
+
if "ref" not in remote["query"]:
|
|
454
|
+
shutil.copy(
|
|
455
|
+
src=Path(annex_cache_path) / remote["path"].lstrip("/"),
|
|
456
|
+
dst=local,
|
|
457
|
+
)
|
|
458
|
+
return local
|
|
459
|
+
|
|
460
|
+
assert "ref" in remote["query"]
|
|
461
|
+
path = remote["path"].lstrip("/")
|
|
462
|
+
repo = pygit2.Repository(annex_cache_path)
|
|
463
|
+
oid = repo.revparse_single(remote["query"]["ref"][0])
|
|
464
|
+
obj = oid.peel(pygit2.Tree) / path
|
|
465
|
+
if obj.filemode == pygit2.enums.FileMode.LINK:
|
|
466
|
+
# Here we need to discriminate between links that point
|
|
467
|
+
# to git-annex managed files and all other symlinks.
|
|
468
|
+
|
|
469
|
+
# If the file is a git-annex link, work out the location
|
|
470
|
+
# of the data within the .git/annex dir and copy this
|
|
471
|
+
# file into the cwd with the right name
|
|
472
|
+
if ".git/annex/objects" in obj.data.decode("ASCII"):
|
|
473
|
+
gitannex_key = Path(obj.data.decode("ASCII")).name
|
|
474
|
+
subprocess.run(
|
|
475
|
+
args=["git-annex", "get", "--key", gitannex_key],
|
|
476
|
+
cwd=str(annex_cache_path),
|
|
477
|
+
)
|
|
478
|
+
gitannex_content_location = subprocess.run(
|
|
479
|
+
args=["git-annex", "contentlocation", gitannex_key],
|
|
480
|
+
cwd=str(annex_cache_path),
|
|
481
|
+
capture_output=True,
|
|
482
|
+
encoding="ASCII",
|
|
483
|
+
).stdout
|
|
484
|
+
shutil.copy(
|
|
485
|
+
src=annex_cache_path / Path(gitannex_content_location),
|
|
486
|
+
dst=local,
|
|
487
|
+
follow_symlinks=True,
|
|
488
|
+
)
|
|
489
|
+
return local
|
|
490
|
+
os.symlink(
|
|
491
|
+
src=obj.data.decode("ASCII"),
|
|
492
|
+
dst=local,
|
|
493
|
+
)
|
|
494
|
+
return local
|
|
495
|
+
|
|
496
|
+
if obj.filemode == pygit2.enums.FileMode.BLOB:
|
|
497
|
+
with open(local, "wb") as dst:
|
|
498
|
+
# Could also use pygit2.BlobIO to stream content
|
|
499
|
+
# without having to load the entire blob data in
|
|
500
|
+
# memory:
|
|
501
|
+
#
|
|
502
|
+
# with pygit2.BlobIO(obj) as src:
|
|
503
|
+
# shutil.copyfileobj(fsrc=src, fdst=dst)
|
|
504
|
+
dst.write(obj.data)
|
|
505
|
+
return local
|
|
506
|
+
|
|
507
|
+
if obj.filemode == pygit2.enums.FileMode.TREE:
|
|
508
|
+
if local.endswith("/"):
|
|
509
|
+
localpath = "."
|
|
510
|
+
else:
|
|
511
|
+
localpath = local
|
|
512
|
+
os.mkdir(local)
|
|
513
|
+
for subobj in obj:
|
|
514
|
+
r = {
|
|
515
|
+
"query": {"ref": remote["query"]["ref"]},
|
|
516
|
+
"path": str(Path(path) / subobj.name),
|
|
517
|
+
}
|
|
518
|
+
self.gitget(
|
|
519
|
+
remote=r,
|
|
520
|
+
local=str(Path(localpath) / subobj.name),
|
|
521
|
+
options=None,
|
|
522
|
+
)
|
|
523
|
+
return local
|
|
524
|
+
|
|
525
|
+
|
|
425
526
|
class _VortexStackedStorageMixin:
|
|
426
527
|
"""Mixin class that adds utility functions to work with stacked data."""
|
|
427
528
|
|
|
@@ -985,7 +1086,10 @@ class VortexCacheMtStore(_VortexCacheBaseStore):
|
|
|
985
1086
|
except config.ConfigurationError:
|
|
986
1087
|
cacheloc = os.path.join(os.environ["HOME"], ".vortex.d")
|
|
987
1088
|
|
|
988
|
-
|
|
1089
|
+
current_vortex_user = self.system.glove.user
|
|
1090
|
+
cacheloc = cacheloc.replace("%usr%", current_vortex_user)
|
|
1091
|
+
|
|
1092
|
+
if self.username != current_vortex_user:
|
|
989
1093
|
return os.path.join(cacheloc, self.username)
|
|
990
1094
|
|
|
991
1095
|
return cacheloc
|
|
@@ -1205,6 +1309,9 @@ class VortexStackStore(_AbstractVortexStackMultiStore):
|
|
|
1205
1309
|
"""Go through the various stacked stores."""
|
|
1206
1310
|
return [f"{self.netloc.firstname}.stacked-cache-mt.fr"]
|
|
1207
1311
|
|
|
1312
|
+
def alternates_fpextras(self):
|
|
1313
|
+
return dict(username=self.username)
|
|
1314
|
+
|
|
1208
1315
|
|
|
1209
1316
|
class VortexVsopStackStore(_AbstractVortexStackMultiStore):
|
|
1210
1317
|
"""Store intended to read and write data into VORTEX R&D stacks."""
|
|
@@ -1336,7 +1443,7 @@ class PromiseCacheStore(VortexCacheMtStore):
|
|
|
1336
1443
|
)
|
|
1337
1444
|
|
|
1338
1445
|
@property
|
|
1339
|
-
def
|
|
1446
|
+
def cache_entry(self):
|
|
1340
1447
|
return os.path.join(super().cache_entry, "promise")
|
|
1341
1448
|
|
|
1342
1449
|
@staticmethod
|
vortex/nwp/algo/assim.py
CHANGED
|
@@ -5,7 +5,7 @@ AlgoComponents dedicated to computations related to Data Assimilation systems.
|
|
|
5
5
|
from bronx.fancies import loggers
|
|
6
6
|
from bronx.stdtypes.date import Date
|
|
7
7
|
|
|
8
|
-
from vortex.algo.components import BlindRun
|
|
8
|
+
from vortex.algo.components import BlindRun
|
|
9
9
|
from vortex.syntax.stdattrs import a_date
|
|
10
10
|
from .ifsroot import IFSParallel
|
|
11
11
|
from ..tools import odb, drhook
|
|
@@ -16,36 +16,6 @@ __all__ = []
|
|
|
16
16
|
logger = loggers.getLogger(__name__)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class MergeVarBC(Parallel):
|
|
20
|
-
"""Merge two VarBC files.
|
|
21
|
-
|
|
22
|
-
The VarBC file resulting from the MergeVarBC contains all the items of the
|
|
23
|
-
first VarBC file plus any new item that would be present in the second file.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
_footprint = dict(
|
|
27
|
-
attr=dict(
|
|
28
|
-
kind=dict(
|
|
29
|
-
values=["mergevarbc"],
|
|
30
|
-
),
|
|
31
|
-
varbcout=dict(
|
|
32
|
-
optional=True,
|
|
33
|
-
default="VARBC.cycle_out",
|
|
34
|
-
),
|
|
35
|
-
)
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
def prepare(self, rh, opts):
|
|
39
|
-
"""Find any ODB candidate in input files."""
|
|
40
|
-
|
|
41
|
-
sh = self.system
|
|
42
|
-
|
|
43
|
-
sh.touch(self.varbcout)
|
|
44
|
-
|
|
45
|
-
# Let ancesters doing real stuff
|
|
46
|
-
super().prepare(rh, opts)
|
|
47
|
-
|
|
48
|
-
|
|
49
19
|
class Anamix(IFSParallel):
|
|
50
20
|
"""Merge the surface and atmospheric analyses into a single file"""
|
|
51
21
|
|
vortex/nwp/algo/forecasts.py
CHANGED
|
@@ -112,6 +112,8 @@ class Forecast(IFSParallel):
|
|
|
112
112
|
# Possibly fix post-processing clim files
|
|
113
113
|
self.all_localclim_fixer(rh, thismonth)
|
|
114
114
|
|
|
115
|
+
self.grab(analysis, comment="analysis")
|
|
116
|
+
|
|
115
117
|
# File linking for IAU increments
|
|
116
118
|
#
|
|
117
119
|
# In the case of a forecast with IAU, the IFS executable
|
|
@@ -884,3 +886,31 @@ class OfflineSurfex(Parallel, DrHookDecoMixin):
|
|
|
884
886
|
if namsec.rh.contents.dumps_needs_update:
|
|
885
887
|
namsec.rh.save()
|
|
886
888
|
logger.info("Namelist dump: \n%s", namsec.rh.container.read())
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
class MUSCForecast(Forecast):
|
|
892
|
+
"""Forecast for MUSC single-column model."""
|
|
893
|
+
|
|
894
|
+
_footprint = dict(
|
|
895
|
+
info="Run a forecast with a MUSC single-column model.",
|
|
896
|
+
attr=dict(
|
|
897
|
+
kind=dict(
|
|
898
|
+
values=["musc"],
|
|
899
|
+
),
|
|
900
|
+
),
|
|
901
|
+
)
|
|
902
|
+
|
|
903
|
+
def postfix(self, rh, opts):
|
|
904
|
+
"""Post forecast information and cleaning."""
|
|
905
|
+
sh = self.system
|
|
906
|
+
# rename specific output files with hours term on 4 digits for compatibility for fmth formatting
|
|
907
|
+
fmt = re.compile(r"Out\.(?P<termh>\d{3})\.\d{4}\.lfa$")
|
|
908
|
+
for f in [
|
|
909
|
+
fmt.match(f)
|
|
910
|
+
for f in sh.listdir()
|
|
911
|
+
if f.startswith("Out.") and f.endswith(".lfa")
|
|
912
|
+
]:
|
|
913
|
+
sh.rename(
|
|
914
|
+
f.string, "Out.{:>04}.0000.lfa".format(int(f.group("termh")))
|
|
915
|
+
)
|
|
916
|
+
super().postfix(rh, opts)
|
vortex/nwp/algo/ifsroot.py
CHANGED
|
@@ -91,7 +91,7 @@ class IFSParallel(
|
|
|
91
91
|
),
|
|
92
92
|
fcterm=dict(
|
|
93
93
|
info="The forecast term of the Arpege/IFS model.",
|
|
94
|
-
type=
|
|
94
|
+
type=float,
|
|
95
95
|
optional=True,
|
|
96
96
|
default=0,
|
|
97
97
|
),
|
|
@@ -346,24 +346,6 @@ class IFSParallel(
|
|
|
346
346
|
# be done by an extra class ... and it could be generalized to mpi
|
|
347
347
|
# setup by the way !
|
|
348
348
|
nam_updated = False
|
|
349
|
-
# For cy41 onward, replace some namelist macros with the command line
|
|
350
|
-
# arguments
|
|
351
|
-
if rh.resource.cycle >= "cy41":
|
|
352
|
-
if "NAMARG" in namcontents:
|
|
353
|
-
opts_arg = self.spawn_command_options()
|
|
354
|
-
self._set_nam_macro(
|
|
355
|
-
namcontents, namlocal, "CEXP", opts_arg["name"]
|
|
356
|
-
)
|
|
357
|
-
self._set_nam_macro(
|
|
358
|
-
namcontents, namlocal, "TIMESTEP", opts_arg["timestep"]
|
|
359
|
-
)
|
|
360
|
-
fcstop = "{:s}{:d}".format(
|
|
361
|
-
opts_arg["fcunit"], opts_arg["fcterm"]
|
|
362
|
-
)
|
|
363
|
-
self._set_nam_macro(namcontents, namlocal, "FCSTOP", fcstop)
|
|
364
|
-
nam_updated = True
|
|
365
|
-
else:
|
|
366
|
-
logger.info("No NAMARG block in %s", namlocal)
|
|
367
349
|
|
|
368
350
|
if self.member is not None:
|
|
369
351
|
for macro_name in ("MEMBER", "PERTURB"):
|
|
@@ -371,7 +353,39 @@ class IFSParallel(
|
|
|
371
353
|
namcontents, namlocal, macro_name, self.member
|
|
372
354
|
)
|
|
373
355
|
nam_updated = True
|
|
374
|
-
|
|
356
|
+
|
|
357
|
+
if rh.resource.cycle < "cy41":
|
|
358
|
+
return nam_updated
|
|
359
|
+
|
|
360
|
+
if "NAMARG" not in namcontents:
|
|
361
|
+
logger.info("No NAMARG block in %s", namlocal)
|
|
362
|
+
return nam_updated
|
|
363
|
+
|
|
364
|
+
# For cy41 onward, replace some namelist macros with the command line
|
|
365
|
+
# arguments
|
|
366
|
+
opts_arg = self.spawn_command_options()
|
|
367
|
+
self._set_nam_macro(namcontents, namlocal, "CEXP", opts_arg["name"])
|
|
368
|
+
self._set_nam_macro(
|
|
369
|
+
namcontents, namlocal, "TIMESTEP", opts_arg["timestep"]
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
if self.fcunit == "t":
|
|
373
|
+
fcstop = "t{:d}".format(int(self.fcterm))
|
|
374
|
+
elif self.fcterm.is_integer():
|
|
375
|
+
# Round number of hours
|
|
376
|
+
fcstop = "h{:d}".format(int(self.fcterm))
|
|
377
|
+
else:
|
|
378
|
+
# IFS expects the forecast term to be given as an integer,
|
|
379
|
+
# whether this integer represents hours or timesteps. This
|
|
380
|
+
# means terms that are not round hours (e.g. 01:45) can only
|
|
381
|
+
# be expressed as a number of timesteps.
|
|
382
|
+
# See http://gitlab.meteo.fr/cnrm-gmap/vortex/-/issues/9
|
|
383
|
+
nsteps = int(self.fcterm * 3600 // self.timestep)
|
|
384
|
+
fcstop = "t{:d}".format(nsteps)
|
|
385
|
+
logger.info(f"Converting {self.fcterm} hours into {nsteps}")
|
|
386
|
+
|
|
387
|
+
self._set_nam_macro(namcontents, namlocal, "FCSTOP", fcstop)
|
|
388
|
+
return True
|
|
375
389
|
|
|
376
390
|
def prepare_namelists(self, rh, opts=None):
|
|
377
391
|
"""Update each of the namelists."""
|
vortex/nwp/algo/monitoring.py
CHANGED
|
@@ -4,7 +4,7 @@ AlgoComponents dedicated to computations related to observations monitoring.
|
|
|
4
4
|
|
|
5
5
|
from bronx.fancies import loggers
|
|
6
6
|
|
|
7
|
-
from vortex.algo.components import
|
|
7
|
+
from vortex.algo.components import BlindRun
|
|
8
8
|
from vortex.syntax.stdattrs import a_date, a_model, a_cutoff
|
|
9
9
|
from ..tools import odb, drhook
|
|
10
10
|
|
|
@@ -15,7 +15,7 @@ logger = loggers.getLogger(__name__)
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class OdbMonitoring(
|
|
18
|
-
|
|
18
|
+
BlindRun, odb.OdbComponentDecoMixin, drhook.DrHookDecoMixin
|
|
19
19
|
):
|
|
20
20
|
"""Compute monitoring statistics."""
|
|
21
21
|
|
vortex/nwp/algo/odbtools.py
CHANGED
|
@@ -16,7 +16,7 @@ from taylorism import Boss
|
|
|
16
16
|
|
|
17
17
|
from vortex.tools.systems import ExecutionError
|
|
18
18
|
|
|
19
|
-
from vortex.algo.components import Parallel, ParaBlindRun
|
|
19
|
+
from vortex.algo.components import Parallel, ParaBlindRun, BlindRun
|
|
20
20
|
from vortex.tools.parallelism import VortexWorkerBlindRun
|
|
21
21
|
|
|
22
22
|
from ..syntax.stdattrs import arpifs_cycle
|
|
@@ -1217,7 +1217,7 @@ class OdbReshuffle(
|
|
|
1217
1217
|
|
|
1218
1218
|
|
|
1219
1219
|
class FlagsCompute(
|
|
1220
|
-
|
|
1220
|
+
BlindRun, odb.OdbComponentDecoMixin, drhook.DrHookDecoMixin
|
|
1221
1221
|
):
|
|
1222
1222
|
"""Compute observations flags."""
|
|
1223
1223
|
|
vortex/nwp/data/consts.py
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
Various Resources for constant files used in NWP.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import random
|
|
6
|
+
|
|
5
7
|
import footprints
|
|
8
|
+
from footprints import FPList
|
|
6
9
|
from ..syntax.stdattrs import gvar
|
|
7
10
|
from vortex.data.contents import DataRaw, JsonDictContent, TextContent
|
|
8
11
|
from vortex.data.geometries import GaussGeometry, LonlatGeometry
|
|
9
12
|
from vortex.data.outflow import ModelGeoResource, ModelResource, StaticResource
|
|
10
|
-
from vortex.syntax.stdattrs import month_deco
|
|
13
|
+
from vortex.syntax.stdattrs import date_deco, member, month_deco
|
|
11
14
|
from vortex.syntax.stddeco import (
|
|
12
15
|
namebuilding_append,
|
|
13
16
|
namebuilding_delete,
|
|
@@ -180,6 +183,63 @@ class RtCoef(GenvModelResource):
|
|
|
180
183
|
return "rtcoef"
|
|
181
184
|
|
|
182
185
|
|
|
186
|
+
class RtCoefMulti(GenvModelResource):
|
|
187
|
+
"""
|
|
188
|
+
RtCoeff Satellite coefficients, randomly chosen depending on the member of an ensemble.
|
|
189
|
+
|
|
190
|
+
Reproducibility is ensured by the stability of the random generation for a given date (ymdh) and member.
|
|
191
|
+
With member=0 or None, or with choices=0, the choice is always 0, even if 0 is excluded.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
_footprint = [
|
|
195
|
+
date_deco,
|
|
196
|
+
member,
|
|
197
|
+
dict(
|
|
198
|
+
info="Set of satellite coefficients",
|
|
199
|
+
attr=dict(
|
|
200
|
+
kind=dict(
|
|
201
|
+
values=["rtcoef_multi", "mwave_rtcoef_multi"],
|
|
202
|
+
),
|
|
203
|
+
choices=dict(
|
|
204
|
+
info="Number of choices to choose from (0..choices-1)",
|
|
205
|
+
type=int,
|
|
206
|
+
optional=True,
|
|
207
|
+
),
|
|
208
|
+
excluded=dict(
|
|
209
|
+
info="List of values excluded from choice",
|
|
210
|
+
type=footprints.stdtypes.FPList,
|
|
211
|
+
optional=True,
|
|
212
|
+
default=FPList([]),
|
|
213
|
+
),
|
|
214
|
+
gvar=dict(
|
|
215
|
+
info="Will be modified by the random choice",
|
|
216
|
+
default="[kind]_0",
|
|
217
|
+
access="rwx",
|
|
218
|
+
),
|
|
219
|
+
),
|
|
220
|
+
),
|
|
221
|
+
]
|
|
222
|
+
|
|
223
|
+
def __init__(self, *args, **kw):
|
|
224
|
+
super().__init__(*args, **kw)
|
|
225
|
+
if self.member is None or self.member == 0 or self.choices == 0:
|
|
226
|
+
choice = 0
|
|
227
|
+
else:
|
|
228
|
+
# a random generator entirely determined by the date
|
|
229
|
+
rgen = random.Random(int(self.date.ymdh))
|
|
230
|
+
# drawing must be reproducible for a given member:
|
|
231
|
+
# generate 'member' values, but only keep the last
|
|
232
|
+
choice = rgen.choices(
|
|
233
|
+
[n for n in range(self.choices) if n not in self.excluded],
|
|
234
|
+
k=self.member,
|
|
235
|
+
)[-1]
|
|
236
|
+
self.gvar = self.gvar[:-1] + str(choice)
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def realkind(self):
|
|
240
|
+
return "rtcoef"
|
|
241
|
+
|
|
242
|
+
|
|
183
243
|
class RRTM(GenvModelResource):
|
|
184
244
|
"""
|
|
185
245
|
Class of a tar-zip file of coefficients for radiative transfers computations.
|
vortex/nwp/data/diagnostics.py
CHANGED
|
@@ -145,10 +145,7 @@ _surfex_diag_decofp = footprints.DecorativeFootprint(
|
|
|
145
145
|
]
|
|
146
146
|
),
|
|
147
147
|
nativefmt=dict(
|
|
148
|
-
values=[
|
|
149
|
-
"netcdf",
|
|
150
|
-
"grib",
|
|
151
|
-
],
|
|
148
|
+
values=["netcdf", "grib", "fa"],
|
|
152
149
|
default="netcdf",
|
|
153
150
|
optional=True,
|
|
154
151
|
),
|
|
@@ -185,6 +182,7 @@ class ObjTrack(GeoFlowResource):
|
|
|
185
182
|
values=[
|
|
186
183
|
"json",
|
|
187
184
|
"hdf5",
|
|
185
|
+
"tar",
|
|
188
186
|
"foo",
|
|
189
187
|
],
|
|
190
188
|
default="foo",
|
vortex/nwp/tools/conftools.py
CHANGED
|
@@ -1045,11 +1045,11 @@ class ArpIfsForecastTermConfTool(ConfTool):
|
|
|
1045
1045
|
The forecast term can be retrieved:
|
|
1046
1046
|
|
|
1047
1047
|
>>> print(ct.fcterm('assim', 6))
|
|
1048
|
-
6
|
|
1048
|
+
6.0
|
|
1049
1049
|
>>> print(ct.fcterm('production', 0))
|
|
1050
|
-
102
|
|
1050
|
+
102.0
|
|
1051
1051
|
>>> print(ct.fcterm('production', 12))
|
|
1052
|
-
24
|
|
1052
|
+
24.0
|
|
1053
1053
|
|
|
1054
1054
|
If nothing is defined it crashes:
|
|
1055
1055
|
|
|
@@ -1451,11 +1451,12 @@ class ArpIfsForecastTermConfTool(ConfTool):
|
|
|
1451
1451
|
return self._lookup_rangex_cache[(what_desc, cutoff, hh)]
|
|
1452
1452
|
|
|
1453
1453
|
def fcterm(self, cutoff, hh):
|
|
1454
|
-
"""The forecast term for **cutoff** and **hh
|
|
1454
|
+
"""The forecast term for **cutoff** and **hh** as a float or int."""
|
|
1455
1455
|
fcterm = self._cutoff_hh_lookup("fcterm", cutoff, hh)
|
|
1456
|
-
if isinstance(fcterm, Time)
|
|
1457
|
-
return fcterm.hour
|
|
1456
|
+
if isinstance(fcterm, Time):
|
|
1457
|
+
return fcterm.hour + (fcterm.minute / 60)
|
|
1458
1458
|
else:
|
|
1459
|
+
# fcterm is an int representing nb of timesteps
|
|
1459
1460
|
return fcterm
|
|
1460
1461
|
|
|
1461
1462
|
def hist_terms(self, cutoff, hh):
|
vortex/tools/systems.py
CHANGED
|
@@ -67,7 +67,6 @@ from vortex.tools.compression import CompressionPipeline
|
|
|
67
67
|
from vortex.tools.env import Environment
|
|
68
68
|
from vortex.tools.net import AssistedSsh, AutoRetriesFtp, DEFAULT_FTP_PORT
|
|
69
69
|
from vortex.tools.net import FtpConnectionPool, LinuxNetstats, StdFtp
|
|
70
|
-
import vortex.tools.storage
|
|
71
70
|
from vortex import config
|
|
72
71
|
|
|
73
72
|
#: No automatic export
|
|
@@ -1161,6 +1160,7 @@ class OSExtended(System):
|
|
|
1161
1160
|
logger.warning(
|
|
1162
1161
|
"Bad return code [%d] for %s", p.returncode, str(args)
|
|
1163
1162
|
)
|
|
1163
|
+
self.dump_spawn_to_script(args)
|
|
1164
1164
|
if isinstance(output, bool) and output:
|
|
1165
1165
|
sys.stderr.write(p_err.decode(plocale, "replace"))
|
|
1166
1166
|
if fatal:
|
|
@@ -1183,6 +1183,31 @@ class OSExtended(System):
|
|
|
1183
1183
|
|
|
1184
1184
|
return rc
|
|
1185
1185
|
|
|
1186
|
+
def dump_spawn_to_script(self, args):
|
|
1187
|
+
"""Dump spawn environment to a script that can be executed 'out-of-vortex'."""
|
|
1188
|
+
script = [
|
|
1189
|
+
"#!/bin/bash",
|
|
1190
|
+
"",
|
|
1191
|
+
'SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )',
|
|
1192
|
+
"cd $SCRIPT_DIR",
|
|
1193
|
+
"",
|
|
1194
|
+
"ulimit -s unlimited",
|
|
1195
|
+
"",
|
|
1196
|
+
]
|
|
1197
|
+
# env vars
|
|
1198
|
+
for k in sorted(self.env.keys()):
|
|
1199
|
+
if not (k.startswith("SLURM") or k.startswith("MTOOL")):
|
|
1200
|
+
script.append('export {}="{}"'.format(k, self.env[k]))
|
|
1201
|
+
# command line
|
|
1202
|
+
script.append("\n" + " ".join(args))
|
|
1203
|
+
# replace any MTOOL dirs from spool to abort
|
|
1204
|
+
for i, line in enumerate(script):
|
|
1205
|
+
script[i] = line.replace("spool/spool_", "abort/dump_")
|
|
1206
|
+
# write to file
|
|
1207
|
+
with open("spawn_dump.sh", "w") as o:
|
|
1208
|
+
for l in script:
|
|
1209
|
+
o.write(l + "\n")
|
|
1210
|
+
|
|
1186
1211
|
def getlogname(self):
|
|
1187
1212
|
"""Be sure to get the actual login name."""
|
|
1188
1213
|
return passwd.getpwuid(self._os.getuid())[0]
|
|
@@ -1860,10 +1885,15 @@ class OSExtended(System):
|
|
|
1860
1885
|
"""Return a cache object for the FtSpool."""
|
|
1861
1886
|
if self._ftspool_cache is not None:
|
|
1862
1887
|
return self._ftspool_cache
|
|
1888
|
+
try:
|
|
1889
|
+
cacheloc = config.from_config(section="data-tree", key="rootdir")
|
|
1890
|
+
except config.ConfigurationError:
|
|
1891
|
+
cacheloc = os.path.join(os.environ["HOME"], ".vortex.d")
|
|
1892
|
+
|
|
1863
1893
|
self._ftspool_cache = footprints.proxy.cache(
|
|
1864
1894
|
entry=os.path.join(
|
|
1865
|
-
|
|
1866
|
-
)
|
|
1895
|
+
cacheloc.replace("%usr%", self.glove.user), "ftspool"
|
|
1896
|
+
)
|
|
1867
1897
|
)
|
|
1868
1898
|
return self._ftspool_cache
|
|
1869
1899
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vortex-nwp
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: A Python library to write Numerical Weather Prediction pipelines components
|
|
5
5
|
Author-email: The Vortex Team <vortex.support@meteo.fr>
|
|
6
6
|
License: CECILL-C
|
|
@@ -14,6 +14,7 @@ Requires-Dist: footprints
|
|
|
14
14
|
Requires-Dist: taylorism
|
|
15
15
|
Requires-Dist: tomli
|
|
16
16
|
Requires-Dist: arpifs_listings
|
|
17
|
+
Requires-Dist: importlib_metadata; python_version < "3.8"
|
|
17
18
|
Provides-Extra: docs
|
|
18
19
|
Requires-Dist: sphinx; extra == "docs"
|
|
19
20
|
Requires-Dist: sphinx-book-theme; extra == "docs"
|
|
@@ -21,6 +22,8 @@ Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
|
21
22
|
Provides-Extra: dev
|
|
22
23
|
Requires-Dist: ruff==0.9.1; extra == "dev"
|
|
23
24
|
Requires-Dist: pytest; extra == "dev"
|
|
25
|
+
Provides-Extra: git
|
|
26
|
+
Requires-Dist: pygit2; extra == "git"
|
|
24
27
|
Dynamic: license-file
|
|
25
28
|
|
|
26
29
|
## vortex
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
vortex/__init__.py,sha256=
|
|
1
|
+
vortex/__init__.py,sha256=iF0Qyy8b-ZIznlaDuFfFtuA3PU4d3OxQZVYM1TyU7fQ,4438
|
|
2
2
|
vortex/config.py,sha256=YEpcc81wR94jvn36fPONmKc1tM4ap0s8Rc7v3KfDUok,2948
|
|
3
3
|
vortex/gloves.py,sha256=GKz27S8eLfRlk8fNqVL_z1gsQ8zvEj73p5uVi11ou00,8487
|
|
4
4
|
vortex/proxy.py,sha256=OlPrVUJS5FoKt5pX8ApN1crFFDj8RJAqhDEilwvfrYU,127
|
|
5
5
|
vortex/sessions.py,sha256=zWVhsFGKl-SovyVAZz3mpvmojjHROt5iyERjwA6kudQ,10017
|
|
6
6
|
vortex/toolbox.py,sha256=fDTvfghg8Yl7ggAwhIaY3V6owO3V1IG9LBf6F97A_50,42385
|
|
7
7
|
vortex/algo/__init__.py,sha256=I_9COn_QBRbwvbqhs0X3CdHeR97NZhBacIqwKjnVBTg,359
|
|
8
|
-
vortex/algo/components.py,sha256=
|
|
9
|
-
vortex/algo/mpitools.py,sha256=
|
|
8
|
+
vortex/algo/components.py,sha256=BodJA593f0OM1Tj5BAh-u-p55IbL81rwQR_g_Ee-mL0,89990
|
|
9
|
+
vortex/algo/mpitools.py,sha256=4J-qGZ4olkgq6kpC2F81ogXeksXp4030ARg-QbCdQ9Y,74154
|
|
10
10
|
vortex/algo/serversynctools.py,sha256=fPel0txVHsrUfk6VFaeKa0D6i21fOskIAR_BbByBv9g,5601
|
|
11
11
|
vortex/algo/mpitools_templates/__init__.py,sha256=Jbw903aPqVKF-AaSoB-mGMxthSvm88O_yqGoGmf_S_U,18
|
|
12
12
|
vortex/algo/mpitools_templates/envelope_wrapper_default.tpl,sha256=4VhkDx_YbOYywKQ82HIxRJXGcDpLuOgqcY7Edx9Rxyw,453
|
|
@@ -16,15 +16,15 @@ vortex/data/__init__.py,sha256=XaHof5W6oCalr4X6oYAK4zW3z3F6mKuwdbKxmmmDraY,560
|
|
|
16
16
|
vortex/data/abstractstores.py,sha256=eghm3HSlUcZM8AGdx0js4Nt_IdxEiYffOmqS5gkpVsQ,55297
|
|
17
17
|
vortex/data/containers.py,sha256=Qny5rqwXEdDWxG4JlC8KcsSAsHK3pp8qukZj1PTFBOM,26004
|
|
18
18
|
vortex/data/contents.py,sha256=ZrwlJfOvkTemzikFRgYBQH3ApC-TPNrbZxpZstzDdbY,19079
|
|
19
|
-
vortex/data/executables.py,sha256=
|
|
19
|
+
vortex/data/executables.py,sha256=aFIf0gTEw1z60SlznfDzGG58vzE4191ObDrASt0hszw,7381
|
|
20
20
|
vortex/data/flow.py,sha256=P1itBnA8jaoCWnVQjqbD_Pf26rpzud1JdwSLECDnDl4,3008
|
|
21
|
-
vortex/data/geometries.ini,sha256=
|
|
21
|
+
vortex/data/geometries.ini,sha256=W2yDVXwG5J0amjRt3xHjOrFr_xI7h3v75WFQcFda16w,54103
|
|
22
22
|
vortex/data/geometries.py,sha256=q-0xmfBFN_TrMaojljO0wEpEwY9w1cbUuoBo49cvYhc,28221
|
|
23
23
|
vortex/data/handlers.py,sha256=bChvizJnN5zxQxVf0oeUqcw_Wj-jnVszSqT1ovVUXFA,50525
|
|
24
24
|
vortex/data/outflow.py,sha256=IPKJkn75lRvhSqN5969TuhRAPnsZKlrWR4Cmw6VBFDs,1475
|
|
25
|
-
vortex/data/providers.py,sha256=
|
|
25
|
+
vortex/data/providers.py,sha256=s1CHOuogjzyPUHfK6gPpKU3IDCtySLTjPgkmuC4xiJA,16614
|
|
26
26
|
vortex/data/resources.py,sha256=UOwvQDTJxS9z66Aa7JM2nWM3IxrMWvY3L2J9D5w3sZw,6348
|
|
27
|
-
vortex/data/stores.py,sha256=
|
|
27
|
+
vortex/data/stores.py,sha256=e4fhTTHcnh7FhZ21M93bH5ixl_owArSMKlvlPIxHIF4,47735
|
|
28
28
|
vortex/data/sync_templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
29
|
vortex/layout/__init__.py,sha256=aZsDhVJrd3-648vw-UESI_2BLxyGl71sHdyrg9cL638,826
|
|
30
30
|
vortex/layout/contexts.py,sha256=GkysEtOOUj3nQvGUWrFjOOjzv7SmWFPUSLTH_pMMycI,20363
|
|
@@ -32,18 +32,18 @@ vortex/layout/dataflow.py,sha256=SKOUJKbtftW4POStjyBqNrqjvfbutsNHnWQ-p_75l_8,447
|
|
|
32
32
|
vortex/layout/monitor.py,sha256=DIUXoW242tg5B6fFEEe2Og-NOxli1T_xpcNWFvTaWXQ,34316
|
|
33
33
|
vortex/nwp/__init__.py,sha256=UfB2il-lEjF87PyVO9sGxjcuy3OYhZwskZw3z52VYAE,311
|
|
34
34
|
vortex/nwp/algo/__init__.py,sha256=_it4GhWxay_WAy0qr2IxLdIqsjWxXcsSSB7wx1BitB4,577
|
|
35
|
-
vortex/nwp/algo/assim.py,sha256=
|
|
35
|
+
vortex/nwp/algo/assim.py,sha256=HIyOAkzWc8U42ttWy7nYpHiDoBjTp9WoO7F_SQau9v8,15209
|
|
36
36
|
vortex/nwp/algo/clim.py,sha256=Z9QwUfosH0X_xTg6mam68qWIvw6Ts6CZIpc7Nb0NO1s,37511
|
|
37
37
|
vortex/nwp/algo/coupling.py,sha256=6KQ_YB7PCvVbt6c2VEtpCzwIyWRTjLfu54mNpKnXL9Q,29755
|
|
38
38
|
vortex/nwp/algo/eda.py,sha256=Wf2mt1r6v_ZYDz4BFyt-4JP1XAsO8sZW3O1UAOSRzmU,30746
|
|
39
39
|
vortex/nwp/algo/eps.py,sha256=JCBFiaFF9TQ-x7Szgw44Cd39tRD9184UXqOtoT6aRCs,26812
|
|
40
|
-
vortex/nwp/algo/forecasts.py,sha256=
|
|
40
|
+
vortex/nwp/algo/forecasts.py,sha256=qgpSYYsD0C9agBusBX38ulDesw01uU_QvOc28gspNCI,30971
|
|
41
41
|
vortex/nwp/algo/fpserver.py,sha256=98HQZsdQE22spy_mIE1G-NORQMMjfA5grEjeIMSlP9w,50163
|
|
42
42
|
vortex/nwp/algo/ifsnaming.py,sha256=WfpSpRJ7ua3ihqv8Y4UkrvE4pb0CkNWKIlW9EjY-2ao,11188
|
|
43
|
-
vortex/nwp/algo/ifsroot.py,sha256=
|
|
44
|
-
vortex/nwp/algo/monitoring.py,sha256=
|
|
43
|
+
vortex/nwp/algo/ifsroot.py,sha256=RIJzn1r9uZ5Cno3WHQ6swEZUAlmndvYRtn9TQ3BVIXc,14771
|
|
44
|
+
vortex/nwp/algo/monitoring.py,sha256=qwWupx4ITJx4vaQVfl3XhWdkaq2T8bNwk72Ur4v-Xw8,8893
|
|
45
45
|
vortex/nwp/algo/mpitools.py,sha256=QO3I9iMdY69znnA6hJy8XUAzBoejDpsVMQFRo3YzXro,24876
|
|
46
|
-
vortex/nwp/algo/odbtools.py,sha256=
|
|
46
|
+
vortex/nwp/algo/odbtools.py,sha256=SjYCYseLqrxlPtEHu4APwSZoCPwjl2rLvT1XC2kvql4,44104
|
|
47
47
|
vortex/nwp/algo/oopsroot.py,sha256=es3p7RPOixQT74TcglJX1q8MswxveVnLZa84kyhu3uM,33806
|
|
48
48
|
vortex/nwp/algo/oopstests.py,sha256=owQAS7_fGbUGZGzMsJek32dbb3JQ6dafSVBrdmveQ-Q,6654
|
|
49
49
|
vortex/nwp/algo/request.py,sha256=y5N9RUfKoPXR6EbSely37Zz6d-2HYyfV3UCvvoenqbY,22809
|
|
@@ -53,9 +53,9 @@ vortex/nwp/data/assim.py,sha256=Dv5nmRYDDzYopC6xIwAl92HFTIz3k18C1jFE_IhYzuU,1009
|
|
|
53
53
|
vortex/nwp/data/boundaries.py,sha256=xZoIriM5L-Q66_am6rOD2ZO0s-31iAUeTE7NZIXXvHI,8114
|
|
54
54
|
vortex/nwp/data/climfiles.py,sha256=hlpe51wc-qrLFV_PX3vCedfLJu8Ko4VHa_qoVmA-Wcg,12610
|
|
55
55
|
vortex/nwp/data/configfiles.py,sha256=0c3VvM25dhU6-QEJs5Wo4IckIVjXFHc-tTEzh1Bho1c,3760
|
|
56
|
-
vortex/nwp/data/consts.py,sha256=
|
|
56
|
+
vortex/nwp/data/consts.py,sha256=LCVZEqONqgDSeWbGSVYTIcdsFnvs0tpuoA3C_fYaEJU,23894
|
|
57
57
|
vortex/nwp/data/ctpini.py,sha256=wEpJG7Px2hb7Vudn4eY2vJHKi8YYO99Sd6UJAeT5kMI,3537
|
|
58
|
-
vortex/nwp/data/diagnostics.py,sha256=
|
|
58
|
+
vortex/nwp/data/diagnostics.py,sha256=Ckemxx6O7-nhOLKyZK3R8dlwMdEAcbSPEC2H4lk3Ikk,5040
|
|
59
59
|
vortex/nwp/data/eda.py,sha256=rVQ35SpHVdHAQ10-LhyGy1k6P9Dbd6os8Crz2I4ThvY,4112
|
|
60
60
|
vortex/nwp/data/eps.py,sha256=nLKTEpEeMxV9oE_sf87xihspMqwzXA8r9uJPP6PdycE,11861
|
|
61
61
|
vortex/nwp/data/executables.py,sha256=xFRHzE5rK71m7gkd-LgMO3KSs0uBeCLqW-8vmedMHqQ,25036
|
|
@@ -80,7 +80,7 @@ vortex/nwp/tools/bdap.py,sha256=GdqC4QclVHzZUNQGYQPu9EmFPNEEBadDNGsLmrE2XUs,1689
|
|
|
80
80
|
vortex/nwp/tools/bdcp.py,sha256=cDlkIVZW9grF2YnieIoiwsDhPxQsJIcaBuOCu6rsCzo,986
|
|
81
81
|
vortex/nwp/tools/bdm.py,sha256=e9o3IpR9C4GGd7NhXWt0bpogrcVkqn_hbEJBtThSV5g,360
|
|
82
82
|
vortex/nwp/tools/bdmp.py,sha256=tlsaPvsPtKSXrq2T7X_xtAdWGZ3Hg2qJUJfH8Fetx3E,1506
|
|
83
|
-
vortex/nwp/tools/conftools.py,sha256=
|
|
83
|
+
vortex/nwp/tools/conftools.py,sha256=Awnf9Tied8qeWhv24GXbe3VF9DWPYScnPXjN2Viez-I,59578
|
|
84
84
|
vortex/nwp/tools/drhook.py,sha256=8BgHw1UGxgviLche73XUltuUtkN9rqjBPy4oBLyG4KY,1972
|
|
85
85
|
vortex/nwp/tools/grib.py,sha256=Uur8z4NjGoRXV4Via-63F9Px59FKG5UxiLM9yMgNkUs,10262
|
|
86
86
|
vortex/nwp/tools/gribdiff.py,sha256=VD4nH06DuFheE9HsFT1UXWnvAC5vUfVBPeqQhCK4wbo,3137
|
|
@@ -125,7 +125,7 @@ vortex/tools/schedulers.py,sha256=7JtfYfSJgViytM7T26B61V8W83dvNwkDWdb2jY_Bn-A,15
|
|
|
125
125
|
vortex/tools/services.py,sha256=hprRFmLcQRLVGDUnFxUFHaEB7ll1tNdt38hRQz8SWF8,29795
|
|
126
126
|
vortex/tools/storage.py,sha256=e2GGTN_fl2wDNdEeYoD2V7jmwpZecb8u32rYvnqPMZk,34522
|
|
127
127
|
vortex/tools/surfex.py,sha256=qbCIGt-dmfIRWRRMjOQnzc9sGNnt8PIFSqQYT77trhw,1408
|
|
128
|
-
vortex/tools/systems.py,sha256=
|
|
128
|
+
vortex/tools/systems.py,sha256=fU46ZU6feCPkyCYti2Cs_jWbbYWv4zSBZskJwfSy_8U,150269
|
|
129
129
|
vortex/tools/targets.py,sha256=-n2uMoEFdz3AeoSd1IGhlr7dYYb8xantUeh9_ggk9iI,14896
|
|
130
130
|
vortex/util/__init__.py,sha256=Zt0OASbKbNnnwUqFHFoq5Mk13sGYSQhxqh7bUvJH6Y8,198
|
|
131
131
|
vortex/util/config.py,sha256=KJHq0GMNRlwzh2WUdpwn1FIKCuAXla7nPRe7j3IZGcI,40045
|
|
@@ -137,8 +137,8 @@ vortex/util/roles.py,sha256=9un_QAijaMn5iTS7PrdoWI5_NNw7uHxMWTnyhc5aNzg,1150
|
|
|
137
137
|
vortex/util/storefunctions.py,sha256=uSfG-G_A88iJf3DwFBd-j0rw6eJta8opfRT39aQHsHM,3615
|
|
138
138
|
vortex/util/structs.py,sha256=vapErq0MNhiKlsnjrv_a5M0Rn29KbP3WE_oiy4Hfwb8,683
|
|
139
139
|
vortex/util/worker.py,sha256=zp8f2tx4SXwf1v55XMdYLAx7n3vSlg8PRGrkHgnfdmg,4721
|
|
140
|
-
vortex_nwp-2.
|
|
141
|
-
vortex_nwp-2.
|
|
142
|
-
vortex_nwp-2.
|
|
143
|
-
vortex_nwp-2.
|
|
144
|
-
vortex_nwp-2.
|
|
140
|
+
vortex_nwp-2.3.0.dist-info/licenses/LICENSE,sha256=ewBJPmWAcQqtBPrydH10tt6ECkcYP3b1o2RfH85pJF0,21863
|
|
141
|
+
vortex_nwp-2.3.0.dist-info/METADATA,sha256=IYexH93RR5LZEqUCVzTfE5IIlngnReB61R5T7bHcErs,2301
|
|
142
|
+
vortex_nwp-2.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
143
|
+
vortex_nwp-2.3.0.dist-info/top_level.txt,sha256=3xfbSD7kw8xKl0jk4GNHsOPKbhubstfWHPl6bxHciRQ,7
|
|
144
|
+
vortex_nwp-2.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|