vortex-nwp 2.0.0b1__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 +135 -0
- vortex/algo/__init__.py +12 -0
- vortex/algo/components.py +2136 -0
- vortex/algo/mpitools.py +1648 -0
- vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +27 -0
- vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +29 -0
- vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +18 -0
- vortex/algo/serversynctools.py +170 -0
- vortex/config.py +115 -0
- vortex/data/__init__.py +13 -0
- vortex/data/abstractstores.py +1572 -0
- vortex/data/containers.py +780 -0
- vortex/data/contents.py +596 -0
- vortex/data/executables.py +284 -0
- vortex/data/flow.py +113 -0
- vortex/data/geometries.ini +2689 -0
- vortex/data/geometries.py +703 -0
- vortex/data/handlers.py +1021 -0
- vortex/data/outflow.py +67 -0
- vortex/data/providers.py +465 -0
- vortex/data/resources.py +201 -0
- vortex/data/stores.py +1271 -0
- vortex/gloves.py +282 -0
- vortex/layout/__init__.py +27 -0
- vortex/layout/appconf.py +109 -0
- vortex/layout/contexts.py +511 -0
- vortex/layout/dataflow.py +1069 -0
- vortex/layout/jobs.py +1276 -0
- vortex/layout/monitor.py +833 -0
- vortex/layout/nodes.py +1424 -0
- vortex/layout/subjobs.py +464 -0
- vortex/nwp/__init__.py +11 -0
- vortex/nwp/algo/__init__.py +12 -0
- vortex/nwp/algo/assim.py +483 -0
- vortex/nwp/algo/clim.py +920 -0
- vortex/nwp/algo/coupling.py +609 -0
- vortex/nwp/algo/eda.py +632 -0
- vortex/nwp/algo/eps.py +613 -0
- vortex/nwp/algo/forecasts.py +745 -0
- vortex/nwp/algo/fpserver.py +927 -0
- vortex/nwp/algo/ifsnaming.py +403 -0
- vortex/nwp/algo/ifsroot.py +311 -0
- vortex/nwp/algo/monitoring.py +202 -0
- vortex/nwp/algo/mpitools.py +554 -0
- vortex/nwp/algo/odbtools.py +974 -0
- vortex/nwp/algo/oopsroot.py +735 -0
- vortex/nwp/algo/oopstests.py +186 -0
- vortex/nwp/algo/request.py +579 -0
- vortex/nwp/algo/stdpost.py +1285 -0
- vortex/nwp/data/__init__.py +12 -0
- vortex/nwp/data/assim.py +392 -0
- vortex/nwp/data/boundaries.py +261 -0
- vortex/nwp/data/climfiles.py +539 -0
- vortex/nwp/data/configfiles.py +149 -0
- vortex/nwp/data/consts.py +929 -0
- vortex/nwp/data/ctpini.py +133 -0
- vortex/nwp/data/diagnostics.py +181 -0
- vortex/nwp/data/eda.py +148 -0
- vortex/nwp/data/eps.py +383 -0
- vortex/nwp/data/executables.py +1039 -0
- vortex/nwp/data/fields.py +96 -0
- vortex/nwp/data/gridfiles.py +308 -0
- vortex/nwp/data/logs.py +551 -0
- vortex/nwp/data/modelstates.py +334 -0
- vortex/nwp/data/monitoring.py +220 -0
- vortex/nwp/data/namelists.py +644 -0
- vortex/nwp/data/obs.py +748 -0
- vortex/nwp/data/oopsexec.py +72 -0
- vortex/nwp/data/providers.py +182 -0
- vortex/nwp/data/query.py +217 -0
- vortex/nwp/data/stores.py +147 -0
- vortex/nwp/data/surfex.py +338 -0
- vortex/nwp/syntax/__init__.py +9 -0
- vortex/nwp/syntax/stdattrs.py +375 -0
- vortex/nwp/tools/__init__.py +10 -0
- vortex/nwp/tools/addons.py +35 -0
- vortex/nwp/tools/agt.py +55 -0
- vortex/nwp/tools/bdap.py +48 -0
- vortex/nwp/tools/bdcp.py +38 -0
- vortex/nwp/tools/bdm.py +21 -0
- vortex/nwp/tools/bdmp.py +49 -0
- vortex/nwp/tools/conftools.py +1311 -0
- vortex/nwp/tools/drhook.py +62 -0
- vortex/nwp/tools/grib.py +268 -0
- vortex/nwp/tools/gribdiff.py +99 -0
- vortex/nwp/tools/ifstools.py +163 -0
- vortex/nwp/tools/igastuff.py +249 -0
- vortex/nwp/tools/mars.py +56 -0
- vortex/nwp/tools/odb.py +548 -0
- vortex/nwp/tools/partitioning.py +234 -0
- vortex/nwp/tools/satrad.py +56 -0
- vortex/nwp/util/__init__.py +6 -0
- vortex/nwp/util/async.py +184 -0
- vortex/nwp/util/beacon.py +40 -0
- vortex/nwp/util/diffpygram.py +359 -0
- vortex/nwp/util/ens.py +198 -0
- vortex/nwp/util/hooks.py +128 -0
- vortex/nwp/util/taskdeco.py +81 -0
- vortex/nwp/util/usepygram.py +591 -0
- vortex/nwp/util/usetnt.py +87 -0
- vortex/proxy.py +6 -0
- vortex/sessions.py +341 -0
- vortex/syntax/__init__.py +9 -0
- vortex/syntax/stdattrs.py +628 -0
- vortex/syntax/stddeco.py +176 -0
- vortex/toolbox.py +982 -0
- vortex/tools/__init__.py +11 -0
- vortex/tools/actions.py +457 -0
- vortex/tools/addons.py +297 -0
- vortex/tools/arm.py +76 -0
- vortex/tools/compression.py +322 -0
- vortex/tools/date.py +20 -0
- vortex/tools/ddhpack.py +10 -0
- vortex/tools/delayedactions.py +672 -0
- vortex/tools/env.py +513 -0
- vortex/tools/folder.py +663 -0
- vortex/tools/grib.py +559 -0
- vortex/tools/lfi.py +746 -0
- vortex/tools/listings.py +354 -0
- vortex/tools/names.py +575 -0
- vortex/tools/net.py +1790 -0
- vortex/tools/odb.py +10 -0
- vortex/tools/parallelism.py +336 -0
- vortex/tools/prestaging.py +186 -0
- vortex/tools/rawfiles.py +10 -0
- vortex/tools/schedulers.py +413 -0
- vortex/tools/services.py +871 -0
- vortex/tools/storage.py +1061 -0
- vortex/tools/surfex.py +61 -0
- vortex/tools/systems.py +3396 -0
- vortex/tools/targets.py +384 -0
- vortex/util/__init__.py +9 -0
- vortex/util/config.py +1071 -0
- vortex/util/empty.py +24 -0
- vortex/util/helpers.py +184 -0
- vortex/util/introspection.py +63 -0
- vortex/util/iosponge.py +76 -0
- vortex/util/roles.py +51 -0
- vortex/util/storefunctions.py +103 -0
- vortex/util/structs.py +26 -0
- vortex/util/worker.py +150 -0
- vortex_nwp-2.0.0b1.dist-info/LICENSE +517 -0
- vortex_nwp-2.0.0b1.dist-info/METADATA +50 -0
- vortex_nwp-2.0.0b1.dist-info/RECORD +146 -0
- vortex_nwp-2.0.0b1.dist-info/WHEEL +5 -0
- vortex_nwp-2.0.0b1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A set of AlgoComponents interrogating various databases.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import copy
|
|
6
|
+
|
|
7
|
+
from bronx.fancies import loggers
|
|
8
|
+
from bronx.stdtypes.date import Time
|
|
9
|
+
import footprints
|
|
10
|
+
|
|
11
|
+
from vortex.algo.components import AlgoComponent, AlgoComponentDecoMixin, Expresso, BlindRun
|
|
12
|
+
from vortex.algo.components import algo_component_deco_mixin_autodoc
|
|
13
|
+
from vortex.syntax.stdattrs import a_date
|
|
14
|
+
from vortex.tools.systems import ExecutionError
|
|
15
|
+
from ..tools.bdap import BDAPrequest_actual_command, BDAPGetError, BDAPRequestConfigurationError
|
|
16
|
+
from ..tools.bdmp import BDMPrequest_actual_command, BDMPGetError
|
|
17
|
+
from ..tools.bdcp import BDCPrequest_actual_command, BDCPGetError
|
|
18
|
+
from ..tools.bdm import BDMGetError, BDMRequestConfigurationError, BDMError
|
|
19
|
+
from ..tools.mars import MarsGetError, callMarsExtract, findMarsExtractCommand
|
|
20
|
+
from ..data.obs import ObsMapContent
|
|
21
|
+
|
|
22
|
+
#: No automatic export
|
|
23
|
+
__all__ = []
|
|
24
|
+
|
|
25
|
+
logger = loggers.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class GetBDAPResource(AlgoComponent):
|
|
29
|
+
"""Algo component to get BDAP resources considering a BDAP query file."""
|
|
30
|
+
|
|
31
|
+
_footprint = dict(
|
|
32
|
+
info = 'Algo component to get BDAP files.',
|
|
33
|
+
attr = dict(
|
|
34
|
+
kind = dict(
|
|
35
|
+
values = ['get_bdap'],
|
|
36
|
+
),
|
|
37
|
+
date = a_date,
|
|
38
|
+
target_bdap = dict(
|
|
39
|
+
default = 'OPER',
|
|
40
|
+
optional = True,
|
|
41
|
+
values = ['OPER', 'INTE'],
|
|
42
|
+
),
|
|
43
|
+
terms = dict(
|
|
44
|
+
info = "A forecast term or a list of terms (rangex will be used to expand the string)",
|
|
45
|
+
alias = ('term', )
|
|
46
|
+
),
|
|
47
|
+
command = dict(
|
|
48
|
+
default = 'dap3',
|
|
49
|
+
optional =True,
|
|
50
|
+
values = ['dap3', 'dap3_dev'],
|
|
51
|
+
),
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def execute_single(self, rh, opts):
|
|
56
|
+
"""
|
|
57
|
+
Launch the BDAP request(s).
|
|
58
|
+
The results of each request are stored in a directory local_directory to avoid
|
|
59
|
+
files to be overwritten.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
# Determine the target BDAP
|
|
63
|
+
int_bdap = self.target_bdap == 'INTE'
|
|
64
|
+
|
|
65
|
+
# Look for the input queries
|
|
66
|
+
input_queries = self.context.sequence.effective_inputs(
|
|
67
|
+
role='Query',
|
|
68
|
+
kind='bdap_query',
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
rc_all = True
|
|
72
|
+
|
|
73
|
+
for input_query in input_queries:
|
|
74
|
+
for term in [Time(t) for t in footprints.util.rangex(self.terms)]:
|
|
75
|
+
|
|
76
|
+
# Launch each input queries in a dedicated file
|
|
77
|
+
# (to check that the files do not overwrite each other)
|
|
78
|
+
query_file = input_query.rh.container.abspath
|
|
79
|
+
local_directory = '_'.join([query_file, self.date.ymdhms, term.fmtraw])
|
|
80
|
+
|
|
81
|
+
with self.system.cdcontext(local_directory, create=True):
|
|
82
|
+
# Determine the command to be launched
|
|
83
|
+
actual_command = BDAPrequest_actual_command(command=self.command,
|
|
84
|
+
date=self.date,
|
|
85
|
+
term=term,
|
|
86
|
+
query=query_file,
|
|
87
|
+
int_extraenv=int_bdap)
|
|
88
|
+
logger.info(' '.join(['BDAP extract command:', actual_command]))
|
|
89
|
+
logger.info('The %s directive file contains:', query_file)
|
|
90
|
+
self.system.cat(query_file, output=False)
|
|
91
|
+
# Launch the BDAP request
|
|
92
|
+
rc = self.system.spawn([actual_command, ], shell=True, output=False, fatal=False)
|
|
93
|
+
|
|
94
|
+
if not rc:
|
|
95
|
+
logger.exception('Problem during the BDAP request of %s.', query_file)
|
|
96
|
+
if self.system.path.isfile('DIAG_BDAP'):
|
|
97
|
+
raise BDAPRequestConfigurationError
|
|
98
|
+
else:
|
|
99
|
+
raise BDAPGetError
|
|
100
|
+
|
|
101
|
+
rc_all = rc_all and rc
|
|
102
|
+
|
|
103
|
+
if not rc_all:
|
|
104
|
+
logger.exception('Problem during the BDAP request.')
|
|
105
|
+
|
|
106
|
+
return rc_all
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class GetBDMPResource(AlgoComponent):
|
|
110
|
+
"""Algo component to get BDMP resources considering a BDMP query file."""
|
|
111
|
+
|
|
112
|
+
_footprint = dict(
|
|
113
|
+
info = 'Algo component to get BDMP files.',
|
|
114
|
+
attr = dict(
|
|
115
|
+
kind = dict(
|
|
116
|
+
values = ['get_bdmp'],
|
|
117
|
+
),
|
|
118
|
+
target_bdmp = dict(
|
|
119
|
+
default = 'OPER',
|
|
120
|
+
optional = True,
|
|
121
|
+
values = ['OPER', 'INTE', 'ARCH'],
|
|
122
|
+
),
|
|
123
|
+
command = dict(
|
|
124
|
+
default = 'bdmp_lecture',
|
|
125
|
+
optional =True,
|
|
126
|
+
values = ['bdmp_lecture', 'bdmp_lecture_pg', 'bdmp_lecture_ora'],
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def execute_single(self, rh, opts):
|
|
132
|
+
"""
|
|
133
|
+
Launch the BDMP request(s).
|
|
134
|
+
The results of each request are stored in a directory local_directory to avoid
|
|
135
|
+
files to be overwritten.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
# Look for the input queries
|
|
139
|
+
input_queries = self.context.sequence.effective_inputs(
|
|
140
|
+
role='Query',
|
|
141
|
+
kind='bdmp_query',
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
rc_all = True
|
|
145
|
+
|
|
146
|
+
for input_query in input_queries:
|
|
147
|
+
|
|
148
|
+
# Get information on the query file
|
|
149
|
+
query_file = input_query.rh.container.abspath
|
|
150
|
+
logger.info('The %s directive file contains:', query_file)
|
|
151
|
+
self.system.cat(query_file, output=False)
|
|
152
|
+
|
|
153
|
+
# Construct the name of the temporary directory
|
|
154
|
+
local_directory = '_'.join([query_file, 'extract'])
|
|
155
|
+
|
|
156
|
+
# Determine the command to be launched
|
|
157
|
+
actual_command = BDMPrequest_actual_command(command=self.command,
|
|
158
|
+
query=query_file,
|
|
159
|
+
target_bdmp=self.target_bdmp)
|
|
160
|
+
logger.info(' '.join(['BDMP extract command:', actual_command]))
|
|
161
|
+
|
|
162
|
+
# Launch the BDMP request
|
|
163
|
+
with self.system.cdcontext(local_directory, create=True):
|
|
164
|
+
rc = self.system.spawn([actual_command, ], shell=True, output=False, fatal=False)
|
|
165
|
+
|
|
166
|
+
if not rc:
|
|
167
|
+
logger.exception('Problem during the BDMP request of %s.', query_file)
|
|
168
|
+
raise BDMPGetError
|
|
169
|
+
|
|
170
|
+
rc_all = rc_all and rc
|
|
171
|
+
|
|
172
|
+
if not rc_all:
|
|
173
|
+
logger.exception('Problem during the BDMP request.')
|
|
174
|
+
|
|
175
|
+
return rc_all
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class GetBDCPResource(AlgoComponent):
|
|
179
|
+
"""Algo component to get BDCP resources considering a BDCP query file."""
|
|
180
|
+
|
|
181
|
+
_footprint = dict(
|
|
182
|
+
info = 'Algo component to get BDCP files.',
|
|
183
|
+
attr = dict(
|
|
184
|
+
kind = dict(
|
|
185
|
+
values = ['get_bdcp'],
|
|
186
|
+
),
|
|
187
|
+
target_bdcp = dict(
|
|
188
|
+
default = 'OPER',
|
|
189
|
+
optional = True,
|
|
190
|
+
values = ['OPER'],
|
|
191
|
+
),
|
|
192
|
+
command = dict(
|
|
193
|
+
default = 'extraction_directives',
|
|
194
|
+
optional =True,
|
|
195
|
+
values = ['extraction_directives'],
|
|
196
|
+
),
|
|
197
|
+
)
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
def execute_single(self, rh, opts):
|
|
201
|
+
"""
|
|
202
|
+
Launch the BDCP request(s).
|
|
203
|
+
The name of the output and log files are fixed by the AlgoComponent
|
|
204
|
+
according to the attributes of each request.
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
# Look for the input queries
|
|
208
|
+
input_queries = self.context.sequence.effective_inputs(
|
|
209
|
+
role='Query',
|
|
210
|
+
kind='bdcp_query',
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
rc_all = True
|
|
214
|
+
|
|
215
|
+
for input_query in input_queries:
|
|
216
|
+
|
|
217
|
+
# Get information on the query file
|
|
218
|
+
query_file = input_query.rh.container.abspath
|
|
219
|
+
logger.info('The %s directive file contains:', query_file)
|
|
220
|
+
self.system.cat(query_file, output=False)
|
|
221
|
+
|
|
222
|
+
# Construct the name of the output and log files
|
|
223
|
+
local_directory = '_'.join([query_file, 'extract'])
|
|
224
|
+
output_file = 'extract.out'
|
|
225
|
+
output_log = 'extract.out.diag'
|
|
226
|
+
|
|
227
|
+
# Determine the command to be launched
|
|
228
|
+
actual_command = BDCPrequest_actual_command(command=self.command,
|
|
229
|
+
query_file=query_file,
|
|
230
|
+
output_file=output_file)
|
|
231
|
+
logger.info(' '.join(['BDMP extract command:', actual_command]))
|
|
232
|
+
|
|
233
|
+
# Launch the BDCP request
|
|
234
|
+
with self.system.cdcontext(local_directory, create=True):
|
|
235
|
+
rc = self.system.spawn([actual_command, ], shell=True, output=False, fatal=False)
|
|
236
|
+
# Cat the log file
|
|
237
|
+
logger.info('Content of the log file:')
|
|
238
|
+
self.system.cat(output_log, output=False)
|
|
239
|
+
|
|
240
|
+
if not rc:
|
|
241
|
+
logger.exception('Problem during the BDCP request of %s.', query_file)
|
|
242
|
+
raise BDCPGetError
|
|
243
|
+
|
|
244
|
+
rc_all = rc_all and rc
|
|
245
|
+
|
|
246
|
+
if not rc_all:
|
|
247
|
+
logger.exception('Problem during the BDCP request.')
|
|
248
|
+
|
|
249
|
+
return rc_all
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@algo_component_deco_mixin_autodoc
|
|
253
|
+
class _GetBDMDecoMixin(AlgoComponentDecoMixin):
|
|
254
|
+
"""Class variables and methods usefull for BDM extractions."""
|
|
255
|
+
|
|
256
|
+
_MIXIN_EXTRA_FOOTPRINTS = [footprints.Footprint(
|
|
257
|
+
attr=dict(
|
|
258
|
+
date=a_date,
|
|
259
|
+
pwd_file=dict(
|
|
260
|
+
default='/usr/local/sopra/neons_pwd',
|
|
261
|
+
values=['/usr/local/sopra/neons_pwd'],
|
|
262
|
+
optional=True,
|
|
263
|
+
),
|
|
264
|
+
fatal=dict(
|
|
265
|
+
type=bool,
|
|
266
|
+
default=False,
|
|
267
|
+
values=[True, False],
|
|
268
|
+
optional=True,
|
|
269
|
+
),
|
|
270
|
+
defaut_queryname=dict(
|
|
271
|
+
default='vortexdefault_query_name',
|
|
272
|
+
doc_visibility=footprints.doc.visibility.GURU,
|
|
273
|
+
optional=True,
|
|
274
|
+
)
|
|
275
|
+
)
|
|
276
|
+
)]
|
|
277
|
+
|
|
278
|
+
def _verbose_env_export(self, varname, value):
|
|
279
|
+
self.env.setvar(varname, value)
|
|
280
|
+
logger.info('Setting environment variable %s = %s', varname, str(value))
|
|
281
|
+
|
|
282
|
+
def _prepare_commons(self, rh, opts):
|
|
283
|
+
"""
|
|
284
|
+
Prepare the launch of the script
|
|
285
|
+
"""
|
|
286
|
+
# Some exports to be done
|
|
287
|
+
self._verbose_env_export('PWD_FILE', self.pwd_file)
|
|
288
|
+
self._verbose_env_export('DMT_DATE_PIVOT', self.date.ymdhms)
|
|
289
|
+
|
|
290
|
+
_MIXIN_PREPARE_HOOKS = (_prepare_commons, )
|
|
291
|
+
|
|
292
|
+
def _spawn_command_options_extend(self, prev):
|
|
293
|
+
prev['query'] = self.defaut_queryname
|
|
294
|
+
return prev
|
|
295
|
+
|
|
296
|
+
_MIXIN_CLI_OPTS_EXTEND = (_spawn_command_options_extend, )
|
|
297
|
+
|
|
298
|
+
def _execute_commons(self, rh, opts):
|
|
299
|
+
"""Launch the BDM request(s).
|
|
300
|
+
|
|
301
|
+
The results of each request are stored in a directory local_directory
|
|
302
|
+
to avoid files overwritten by others
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
# Look for the input queries
|
|
306
|
+
input_queries = self._get_input_queries()
|
|
307
|
+
# Initialize some variables
|
|
308
|
+
rc_all = True
|
|
309
|
+
|
|
310
|
+
# Loop over the query files
|
|
311
|
+
for input_query in input_queries:
|
|
312
|
+
# Find out the temporary directory name
|
|
313
|
+
query_filename = input_query.rh.container.filename
|
|
314
|
+
query_abspath = input_query.rh.container.abspath
|
|
315
|
+
loc_dir = self._local_directory(query_filename)
|
|
316
|
+
# Launch an execution for each input queries in a dedicated directory
|
|
317
|
+
# (to check that the files do not overwrite one another)
|
|
318
|
+
with self.system.cdcontext(loc_dir, create=True):
|
|
319
|
+
# Make the links needed
|
|
320
|
+
self.system.symlink(query_abspath,
|
|
321
|
+
self.defaut_queryname)
|
|
322
|
+
# Cat the query content
|
|
323
|
+
logger.info('The %s directive file contains:', query_filename)
|
|
324
|
+
self.system.cat(self.defaut_queryname, output=False)
|
|
325
|
+
# Launch the BDM request and catch
|
|
326
|
+
try:
|
|
327
|
+
super(self.mixin_execute_companion(), self).execute(rh, opts)
|
|
328
|
+
except ExecutionError:
|
|
329
|
+
rc_all = False
|
|
330
|
+
logger.error('Problem during the BDM request of %s.', query_filename)
|
|
331
|
+
if self.fatal:
|
|
332
|
+
raise BDMGetError('Problem during the BDM request of {}.'.format(query_filename))
|
|
333
|
+
# Delete the links
|
|
334
|
+
self.system.rm(self.defaut_queryname)
|
|
335
|
+
self.system.dir(output=False, fatal=False)
|
|
336
|
+
|
|
337
|
+
if not rc_all:
|
|
338
|
+
logger.error('At least one of the BDM request failed. Please check the logs above.')
|
|
339
|
+
|
|
340
|
+
_MIXIN_EXECUTE_OVERWRITE = _execute_commons
|
|
341
|
+
|
|
342
|
+
def _postfix_commons(self, rh, opts):
|
|
343
|
+
"""Concatenate the batormap from the different tasks and check if there is no duplicated entries."""
|
|
344
|
+
|
|
345
|
+
# BATORMAP concatenation
|
|
346
|
+
# Determine the name of the batormap produced by the execution in the different directories
|
|
347
|
+
input_queries = self._get_input_queries()
|
|
348
|
+
local_dir = [self._local_directory(input_query.rh.container.filename)
|
|
349
|
+
for input_query in input_queries]
|
|
350
|
+
temp_files = []
|
|
351
|
+
for directory in local_dir:
|
|
352
|
+
glob_files = self.system.glob('/'.join([directory, '*batormap*']))
|
|
353
|
+
for element in glob_files:
|
|
354
|
+
temp_files.append(element)
|
|
355
|
+
# Initialize the resulting batormap file
|
|
356
|
+
obsmap_filename = '_'.join(['OBSMAP', self.date.ymdhms])
|
|
357
|
+
content = []
|
|
358
|
+
# Check if a batormap is already present in the directory (from previous extract)
|
|
359
|
+
if self.system.path.isfile(obsmap_filename):
|
|
360
|
+
temp_files.append(obsmap_filename)
|
|
361
|
+
# Loop over the directories to concatenate the batormap
|
|
362
|
+
for a_file in temp_files:
|
|
363
|
+
file_container = footprints.proxy.container(local=a_file)
|
|
364
|
+
content_tmp = ObsMapContent()
|
|
365
|
+
content_tmp.slurp(file_container)
|
|
366
|
+
content.append(content_tmp)
|
|
367
|
+
out_content = ObsMapContent()
|
|
368
|
+
out_content.merge(unique=True, *content)
|
|
369
|
+
out_content.sort()
|
|
370
|
+
out_container = footprints.proxy.container(local=obsmap_filename)
|
|
371
|
+
out_content.rewrite(out_container)
|
|
372
|
+
out_container.close()
|
|
373
|
+
logger.info('Content of the global batormap:')
|
|
374
|
+
self.system.cat(out_container.filename, output=False)
|
|
375
|
+
|
|
376
|
+
# Listing concatenation
|
|
377
|
+
# Initialize the resulting file
|
|
378
|
+
listing_filename = 'OULOUTPUT'
|
|
379
|
+
# Determine the name of the listing files produced by the execution
|
|
380
|
+
listing_files = []
|
|
381
|
+
for directory in local_dir:
|
|
382
|
+
glob_files = self.system.glob('/'.join([directory, listing_filename]))
|
|
383
|
+
for element in glob_files:
|
|
384
|
+
listing_files.append(element)
|
|
385
|
+
# Check if a listing is already present and has to be merged with the other
|
|
386
|
+
if self.system.path.isfile(listing_filename):
|
|
387
|
+
temp_listing = '.'.join([listing_filename, 'tmp'])
|
|
388
|
+
self.system.mv(listing_filename, temp_listing)
|
|
389
|
+
listing_files.append(temp_listing)
|
|
390
|
+
# Concatenate the listings
|
|
391
|
+
self.system.cat(*listing_files, output=listing_filename)
|
|
392
|
+
|
|
393
|
+
_MIXIN_POSTFIX_HOOKS = (_postfix_commons, )
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
class GetBDMBufr(Expresso, _GetBDMDecoMixin):
|
|
397
|
+
"""Algo component to get BDM resources considering a BDM query file."""
|
|
398
|
+
|
|
399
|
+
_footprint = dict(
|
|
400
|
+
info = 'Algo component to get BDM BUFR.',
|
|
401
|
+
attr = dict(
|
|
402
|
+
kind = dict(
|
|
403
|
+
values = ['get_bdm_bufr'],
|
|
404
|
+
),
|
|
405
|
+
db_file_bdm = dict(
|
|
406
|
+
default = '/usr/local/sopra/neons_db_bdm',
|
|
407
|
+
values = ['/usr/local/sopra/neons_db_bdm',
|
|
408
|
+
'/usr/local/sopra/neons_db_bdm.archi',
|
|
409
|
+
'/usr/local/sopra/neons_db_bdm.intgr'],
|
|
410
|
+
optional = True,
|
|
411
|
+
),
|
|
412
|
+
extra_env_opt = dict(
|
|
413
|
+
values = ['RECHERCHE', 'OPERATIONNEL', 'OPER'],
|
|
414
|
+
default = 'OPER',
|
|
415
|
+
optional = True,
|
|
416
|
+
),
|
|
417
|
+
shlib_path = dict(
|
|
418
|
+
default = '/usr/local/lib',
|
|
419
|
+
optional = True,
|
|
420
|
+
),
|
|
421
|
+
interpreter = dict(
|
|
422
|
+
default = 'awk',
|
|
423
|
+
values = ['awk'],
|
|
424
|
+
optional = True,
|
|
425
|
+
),
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
def _local_directory(self, query_filename):
|
|
430
|
+
return '_'.join(['BUFR', query_filename, self.date.ymdhms])
|
|
431
|
+
|
|
432
|
+
def _get_input_queries(self):
|
|
433
|
+
"""Returns the list of queries to process."""
|
|
434
|
+
return self.context.sequence.effective_inputs(
|
|
435
|
+
role='Query',
|
|
436
|
+
kind='bdm_query',
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
def prepare(self, rh, opts):
|
|
440
|
+
"""
|
|
441
|
+
Prepare the launch of the script
|
|
442
|
+
"""
|
|
443
|
+
# Do the standard pre-treatment
|
|
444
|
+
super().prepare(rh, opts)
|
|
445
|
+
|
|
446
|
+
# Some exports to be done
|
|
447
|
+
self._verbose_env_export('EXTR_ENV', self.extra_env_opt)
|
|
448
|
+
self._verbose_env_export('DB_FILE_BDM', self.db_file_bdm)
|
|
449
|
+
self._verbose_env_export('SHLIB_PATH', ':'.join(['$SHLIB_PATH', self.shlib_path]))
|
|
450
|
+
|
|
451
|
+
# Check if query files are present
|
|
452
|
+
input_queries = self._get_input_queries()
|
|
453
|
+
if len(input_queries) < 1:
|
|
454
|
+
logger.exception('No query file found for the BDM extraction. Stop.')
|
|
455
|
+
raise BDMRequestConfigurationError('No query file found for the BDM extraction')
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
class GetBDMOulan(BlindRun, _GetBDMDecoMixin):
|
|
459
|
+
"""Algo component to get BDM files using Oulan."""
|
|
460
|
+
|
|
461
|
+
_footprint = dict(
|
|
462
|
+
info = "Algo component to get BDM files using Oulan.",
|
|
463
|
+
attr = dict(
|
|
464
|
+
kind = dict(
|
|
465
|
+
values = ['get_bdm_oulan'],
|
|
466
|
+
),
|
|
467
|
+
db_file = dict(
|
|
468
|
+
default = '/usr/local/sopra/neons_db',
|
|
469
|
+
values = ['/usr/local/sopra/neons_db'],
|
|
470
|
+
optional = True,
|
|
471
|
+
),
|
|
472
|
+
defaut_queryname = dict(
|
|
473
|
+
default = 'NAMELIST',
|
|
474
|
+
),
|
|
475
|
+
)
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
def _local_directory(self, query_filename):
|
|
479
|
+
return '_'.join(['Oulan', query_filename, self.date.ymdhms])
|
|
480
|
+
|
|
481
|
+
def _get_input_queries(self):
|
|
482
|
+
"""Returns the list of namelists to process."""
|
|
483
|
+
return self.context.sequence.effective_inputs(
|
|
484
|
+
role='NamelistOulan',
|
|
485
|
+
kind='namutil',
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
def prepare(self, rh, opts):
|
|
489
|
+
"""Prepare the execution of the Oulan extraction binary."""
|
|
490
|
+
# Do the standard pre-treatment
|
|
491
|
+
super().prepare(rh, opts)
|
|
492
|
+
|
|
493
|
+
# Export additional variables
|
|
494
|
+
self._verbose_env_export('DB_FILE', self.db_file)
|
|
495
|
+
|
|
496
|
+
# Check if namelists are present
|
|
497
|
+
input_namelists = self._get_input_queries()
|
|
498
|
+
if len(input_namelists) < 1:
|
|
499
|
+
logger.error('No Oulan namelist found. Stop.')
|
|
500
|
+
raise BDMError('No Oulan namelist found.')
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
class GetMarsResource(AlgoComponent):
|
|
504
|
+
"""AlgoComponent to get Mars resources using a Mars query file"""
|
|
505
|
+
|
|
506
|
+
_footprint = dict(
|
|
507
|
+
info = 'AlgoComponent to get a Mars resource',
|
|
508
|
+
attr = dict(
|
|
509
|
+
kind = dict(
|
|
510
|
+
values = ['get_mars', ]
|
|
511
|
+
),
|
|
512
|
+
date = a_date,
|
|
513
|
+
substitutions = dict(
|
|
514
|
+
info = "A dictionary of values to be substituted",
|
|
515
|
+
type = footprints.stdtypes.FPDict,
|
|
516
|
+
default = footprints.stdtypes.FPDict(),
|
|
517
|
+
optional = True
|
|
518
|
+
),
|
|
519
|
+
command = dict(
|
|
520
|
+
optional = True
|
|
521
|
+
),
|
|
522
|
+
fatal = dict(
|
|
523
|
+
type = bool,
|
|
524
|
+
default = True,
|
|
525
|
+
optional = True
|
|
526
|
+
)
|
|
527
|
+
)
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
def execute(self, rh, opts):
|
|
531
|
+
"""
|
|
532
|
+
Launch the Mars request(s).
|
|
533
|
+
The results of each requests are stored in a directory to avoid
|
|
534
|
+
files to be overwritten.
|
|
535
|
+
"""
|
|
536
|
+
# Look for input queries
|
|
537
|
+
input_queries = self.context.sequence.effective_inputs(
|
|
538
|
+
role='Query',
|
|
539
|
+
kind='mars_query',
|
|
540
|
+
)
|
|
541
|
+
if len(input_queries) < 1:
|
|
542
|
+
logger.exception('No query file found for the Mars extraction. Stop.')
|
|
543
|
+
raise MarsGetError('No query file found for the Mars extraction')
|
|
544
|
+
|
|
545
|
+
rc_all = True
|
|
546
|
+
|
|
547
|
+
# Find the command to be launched
|
|
548
|
+
actual_command = findMarsExtractCommand(sh=self.system, command=self.command)
|
|
549
|
+
|
|
550
|
+
# Prepare the substitutions' dictionnary
|
|
551
|
+
dictkeyvalue = copy.deepcopy(self.substitutions)
|
|
552
|
+
if self.date is not None:
|
|
553
|
+
dictkeyvalue["YYYYMMDDHH"] = self.date.ymdh
|
|
554
|
+
dictkeyvalue["YYYYMMDD"] = self.date.ymd
|
|
555
|
+
dictkeyvalue["HH"] = self.date.hh
|
|
556
|
+
|
|
557
|
+
# For each input query, extract the files
|
|
558
|
+
for input_query in input_queries:
|
|
559
|
+
# Prepare the query file used
|
|
560
|
+
query_content = input_query.rh.contents
|
|
561
|
+
query_content.setitems(dictkeyvalue)
|
|
562
|
+
input_query.rh.save()
|
|
563
|
+
# Launch each input queries in a dedicated file
|
|
564
|
+
# (to check that the files do not overwrite each other)
|
|
565
|
+
query_file_path = input_query.rh.container.abspath
|
|
566
|
+
local_directory = '_'.join([query_file_path, self.date.ymdhms])
|
|
567
|
+
logger.info("Here is the content of the query file %s (after substitution):", query_file_path)
|
|
568
|
+
self.system.cat(query_file_path, output=False)
|
|
569
|
+
with self.system.cdcontext(local_directory, create=True):
|
|
570
|
+
# Launch the command
|
|
571
|
+
rc = callMarsExtract(sh=self.system, query_file=query_file_path, fatal=self.fatal,
|
|
572
|
+
command=actual_command)
|
|
573
|
+
if not rc:
|
|
574
|
+
if self.fatal:
|
|
575
|
+
logger.error("Problem during the Mars request of %s", query_file_path)
|
|
576
|
+
raise MarsGetError
|
|
577
|
+
else:
|
|
578
|
+
logger.warning("Problem during the Mars request of %s", query_file_path)
|
|
579
|
+
rc_all = rc_all and rc
|