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.
Files changed (139) hide show
  1. vortex/__init__.py +59 -45
  2. vortex/algo/__init__.py +3 -2
  3. vortex/algo/components.py +940 -614
  4. vortex/algo/mpitools.py +802 -497
  5. vortex/algo/serversynctools.py +34 -33
  6. vortex/config.py +19 -22
  7. vortex/data/__init__.py +9 -3
  8. vortex/data/abstractstores.py +593 -655
  9. vortex/data/containers.py +217 -162
  10. vortex/data/contents.py +65 -39
  11. vortex/data/executables.py +93 -102
  12. vortex/data/flow.py +40 -34
  13. vortex/data/geometries.py +228 -132
  14. vortex/data/handlers.py +428 -225
  15. vortex/data/outflow.py +15 -15
  16. vortex/data/providers.py +185 -163
  17. vortex/data/resources.py +48 -42
  18. vortex/data/stores.py +544 -413
  19. vortex/gloves.py +114 -87
  20. vortex/layout/__init__.py +1 -8
  21. vortex/layout/contexts.py +150 -84
  22. vortex/layout/dataflow.py +353 -202
  23. vortex/layout/monitor.py +264 -128
  24. vortex/nwp/__init__.py +5 -2
  25. vortex/nwp/algo/__init__.py +14 -5
  26. vortex/nwp/algo/assim.py +205 -151
  27. vortex/nwp/algo/clim.py +683 -517
  28. vortex/nwp/algo/coupling.py +447 -225
  29. vortex/nwp/algo/eda.py +437 -229
  30. vortex/nwp/algo/eps.py +403 -231
  31. vortex/nwp/algo/forecasts.py +420 -271
  32. vortex/nwp/algo/fpserver.py +683 -307
  33. vortex/nwp/algo/ifsnaming.py +205 -145
  34. vortex/nwp/algo/ifsroot.py +210 -122
  35. vortex/nwp/algo/monitoring.py +132 -76
  36. vortex/nwp/algo/mpitools.py +321 -191
  37. vortex/nwp/algo/odbtools.py +617 -353
  38. vortex/nwp/algo/oopsroot.py +449 -273
  39. vortex/nwp/algo/oopstests.py +90 -56
  40. vortex/nwp/algo/request.py +287 -206
  41. vortex/nwp/algo/stdpost.py +878 -522
  42. vortex/nwp/data/__init__.py +22 -4
  43. vortex/nwp/data/assim.py +125 -137
  44. vortex/nwp/data/boundaries.py +121 -68
  45. vortex/nwp/data/climfiles.py +193 -211
  46. vortex/nwp/data/configfiles.py +73 -69
  47. vortex/nwp/data/consts.py +426 -401
  48. vortex/nwp/data/ctpini.py +59 -43
  49. vortex/nwp/data/diagnostics.py +94 -66
  50. vortex/nwp/data/eda.py +50 -51
  51. vortex/nwp/data/eps.py +195 -146
  52. vortex/nwp/data/executables.py +440 -434
  53. vortex/nwp/data/fields.py +63 -48
  54. vortex/nwp/data/gridfiles.py +183 -111
  55. vortex/nwp/data/logs.py +250 -217
  56. vortex/nwp/data/modelstates.py +180 -151
  57. vortex/nwp/data/monitoring.py +72 -99
  58. vortex/nwp/data/namelists.py +254 -202
  59. vortex/nwp/data/obs.py +400 -308
  60. vortex/nwp/data/oopsexec.py +22 -20
  61. vortex/nwp/data/providers.py +90 -65
  62. vortex/nwp/data/query.py +71 -82
  63. vortex/nwp/data/stores.py +49 -36
  64. vortex/nwp/data/surfex.py +136 -137
  65. vortex/nwp/syntax/__init__.py +1 -1
  66. vortex/nwp/syntax/stdattrs.py +173 -111
  67. vortex/nwp/tools/__init__.py +2 -2
  68. vortex/nwp/tools/addons.py +22 -17
  69. vortex/nwp/tools/agt.py +24 -12
  70. vortex/nwp/tools/bdap.py +16 -5
  71. vortex/nwp/tools/bdcp.py +4 -1
  72. vortex/nwp/tools/bdm.py +3 -0
  73. vortex/nwp/tools/bdmp.py +14 -9
  74. vortex/nwp/tools/conftools.py +728 -378
  75. vortex/nwp/tools/drhook.py +12 -8
  76. vortex/nwp/tools/grib.py +65 -39
  77. vortex/nwp/tools/gribdiff.py +22 -17
  78. vortex/nwp/tools/ifstools.py +82 -42
  79. vortex/nwp/tools/igastuff.py +167 -143
  80. vortex/nwp/tools/mars.py +14 -2
  81. vortex/nwp/tools/odb.py +234 -125
  82. vortex/nwp/tools/partitioning.py +61 -37
  83. vortex/nwp/tools/satrad.py +27 -12
  84. vortex/nwp/util/async.py +83 -55
  85. vortex/nwp/util/beacon.py +10 -10
  86. vortex/nwp/util/diffpygram.py +174 -86
  87. vortex/nwp/util/ens.py +144 -63
  88. vortex/nwp/util/hooks.py +30 -19
  89. vortex/nwp/util/taskdeco.py +28 -24
  90. vortex/nwp/util/usepygram.py +278 -172
  91. vortex/nwp/util/usetnt.py +31 -17
  92. vortex/sessions.py +72 -39
  93. vortex/syntax/__init__.py +1 -1
  94. vortex/syntax/stdattrs.py +410 -171
  95. vortex/syntax/stddeco.py +31 -22
  96. vortex/toolbox.py +327 -192
  97. vortex/tools/__init__.py +11 -2
  98. vortex/tools/actions.py +125 -59
  99. vortex/tools/addons.py +111 -92
  100. vortex/tools/arm.py +42 -22
  101. vortex/tools/compression.py +72 -69
  102. vortex/tools/date.py +11 -4
  103. vortex/tools/delayedactions.py +242 -132
  104. vortex/tools/env.py +75 -47
  105. vortex/tools/folder.py +342 -171
  106. vortex/tools/grib.py +311 -149
  107. vortex/tools/lfi.py +423 -216
  108. vortex/tools/listings.py +109 -40
  109. vortex/tools/names.py +218 -156
  110. vortex/tools/net.py +632 -298
  111. vortex/tools/parallelism.py +93 -61
  112. vortex/tools/prestaging.py +55 -31
  113. vortex/tools/schedulers.py +172 -105
  114. vortex/tools/services.py +402 -333
  115. vortex/tools/storage.py +293 -358
  116. vortex/tools/surfex.py +24 -24
  117. vortex/tools/systems.py +1211 -631
  118. vortex/tools/targets.py +156 -100
  119. vortex/util/__init__.py +1 -1
  120. vortex/util/config.py +377 -327
  121. vortex/util/empty.py +2 -2
  122. vortex/util/helpers.py +56 -24
  123. vortex/util/introspection.py +18 -12
  124. vortex/util/iosponge.py +8 -4
  125. vortex/util/roles.py +4 -6
  126. vortex/util/storefunctions.py +39 -13
  127. vortex/util/structs.py +3 -3
  128. vortex/util/worker.py +29 -17
  129. vortex_nwp-2.0.0b2.dist-info/METADATA +66 -0
  130. vortex_nwp-2.0.0b2.dist-info/RECORD +142 -0
  131. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/WHEEL +1 -1
  132. vortex/layout/appconf.py +0 -109
  133. vortex/layout/jobs.py +0 -1276
  134. vortex/layout/nodes.py +0 -1424
  135. vortex/layout/subjobs.py +0 -464
  136. vortex_nwp-2.0.0b1.dist-info/METADATA +0 -50
  137. vortex_nwp-2.0.0b1.dist-info/RECORD +0 -146
  138. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/LICENSE +0 -0
  139. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.0.0b2.dist-info}/top_level.txt +0 -0
vortex/nwp/data/obs.py CHANGED
@@ -18,14 +18,16 @@ from vortex.syntax import stdattrs, stddeco
18
18
  from ..syntax.stdattrs import gvar, GenvKey
19
19
 
20
20
  #: Automatic export of Observations class
21
- __all__ = ['Observations', ]
21
+ __all__ = [
22
+ "Observations",
23
+ ]
22
24
 
23
25
  logger = loggers.getLogger(__name__)
24
26
 
25
27
 
26
- @stddeco.namebuilding_insert('style', lambda s: 'obs')
27
- @stddeco.namebuilding_insert('stage', lambda s: s.stage)
28
- @stddeco.namebuilding_insert('part', lambda s: s.part)
28
+ @stddeco.namebuilding_insert("style", lambda s: "obs")
29
+ @stddeco.namebuilding_insert("stage", lambda s: s.stage)
30
+ @stddeco.namebuilding_insert("part", lambda s: s.part)
29
31
  class Observations(GeoFlowResource):
30
32
  """
31
33
  Abstract observation resource.
@@ -33,135 +35,176 @@ class Observations(GeoFlowResource):
33
35
 
34
36
  _abstract = True
35
37
  _footprint = dict(
36
- info = 'Observations file',
37
- attr = dict(
38
- kind = dict(
39
- values = ['observations', 'obs'],
40
- remap = dict(obs = 'observations'),
38
+ info="Observations file",
39
+ attr=dict(
40
+ kind=dict(
41
+ values=["observations", "obs"],
42
+ remap=dict(obs="observations"),
41
43
  ),
42
- part = dict(
43
- info = 'The name of this subset of observations.'
44
- ),
45
- nativefmt = dict(
46
- alias = ('format',),
44
+ part=dict(info="The name of this subset of observations."),
45
+ nativefmt=dict(
46
+ alias=("format",),
47
47
  ),
48
- stage = dict(
49
- info = 'The processing stage for this subset of observations.'
48
+ stage=dict(
49
+ info="The processing stage for this subset of observations."
50
50
  ),
51
- )
51
+ ),
52
52
  )
53
53
 
54
54
  @property
55
55
  def realkind(self):
56
- return 'observations'
56
+ return "observations"
57
57
 
58
58
 
59
59
  class ObsProcessed(Observations):
60
60
  """Pre-Processed or Processed observations."""
61
61
 
62
62
  _footprint = dict(
63
- info = 'Pre-Processed observations.',
64
- attr = dict(
65
- nativefmt = dict(
66
- values = ['ascii', 'netcdf', 'hdf5'],
63
+ info="Pre-Processed observations.",
64
+ attr=dict(
65
+ nativefmt=dict(
66
+ values=["ascii", "netcdf", "hdf5"],
67
67
  ),
68
- stage = dict(
69
- values = ['preprocessing', ],
68
+ stage=dict(
69
+ values=[
70
+ "preprocessing",
71
+ ],
70
72
  ),
71
- )
73
+ ),
72
74
  )
73
75
 
74
76
 
75
- @stddeco.namebuilding_insert('layout', lambda s: s.layout)
77
+ @stddeco.namebuilding_insert("layout", lambda s: s.layout)
76
78
  class ObsODB(Observations):
77
79
  """Observations in ODB format associated to a given stage."""
78
80
 
79
81
  _footprint = dict(
80
- info = 'Packed observations (ODB, CCMA, etc.)',
81
- attr = dict(
82
- nativefmt = dict(
83
- values = ['odb', 'odb/split', 'odb/compressed'],
84
- remap = {
85
- 'odb/split': 'odb',
86
- 'odb/compressed': 'odb'
87
- },
82
+ info="Packed observations (ODB, CCMA, etc.)",
83
+ attr=dict(
84
+ nativefmt=dict(
85
+ values=["odb", "odb/split", "odb/compressed"],
86
+ remap={"odb/split": "odb", "odb/compressed": "odb"},
88
87
  ),
89
- layout = dict(
90
- info = 'The layout of the ODB database.',
91
- optional = True,
92
- default = 'ecma',
93
- values = [
94
- 'ccma', 'ecma', 'ecmascr',
95
- 'CCMA', 'ECMA', 'ECMASCR',
96
- 'rstbias', 'countryrstrhbias', 'sondetyperstrhbias',
97
- 'RSTBIAS', 'COUNTRYRSTRHBIAS', 'SONDETYPERSTRHBIAS',
88
+ layout=dict(
89
+ info="The layout of the ODB database.",
90
+ optional=True,
91
+ default="ecma",
92
+ values=[
93
+ "ccma",
94
+ "ecma",
95
+ "ecmascr",
96
+ "CCMA",
97
+ "ECMA",
98
+ "ECMASCR",
99
+ "rstbias",
100
+ "countryrstrhbias",
101
+ "sondetyperstrhbias",
102
+ "RSTBIAS",
103
+ "COUNTRYRSTRHBIAS",
104
+ "SONDETYPERSTRHBIAS",
98
105
  ],
99
- remap = dict(
100
- CCMA = 'ccma', ECMA = 'ecma', ECMASCR = 'ecmascr',
101
- RSTBIAS = 'rstbias',
102
- COUNTRYRSTRHBIAS = 'countryrstrhbias',
103
- SONDETYPERSTRHBIAS = 'sondetyperstrhbias',
104
- )
106
+ remap=dict(
107
+ CCMA="ccma",
108
+ ECMA="ecma",
109
+ ECMASCR="ecmascr",
110
+ RSTBIAS="rstbias",
111
+ COUNTRYRSTRHBIAS="countryrstrhbias",
112
+ SONDETYPERSTRHBIAS="sondetyperstrhbias",
113
+ ),
105
114
  ),
106
- stage = dict(
107
- values = [
108
- 'void', 'avg', 'average', 'screen', 'screening', 'split', 'build',
109
- 'traj', 'min', 'minim', 'complete', 'matchup',
110
- 'canari', 'cans'
115
+ stage=dict(
116
+ values=[
117
+ "void",
118
+ "avg",
119
+ "average",
120
+ "screen",
121
+ "screening",
122
+ "split",
123
+ "build",
124
+ "traj",
125
+ "min",
126
+ "minim",
127
+ "complete",
128
+ "matchup",
129
+ "canari",
130
+ "cans",
111
131
  ],
112
- remap = dict(
113
- avg = 'average',
114
- min = 'minim',
115
- cans = 'canari',
116
- split = 'build',
117
- screen = 'screening',
132
+ remap=dict(
133
+ avg="average",
134
+ min="minim",
135
+ cans="canari",
136
+ split="build",
137
+ screen="screening",
118
138
  ),
119
139
  ),
120
- )
140
+ ),
121
141
  )
122
142
 
123
143
  def olive_basename(self):
124
144
  """OLIVE specific naming convention."""
125
- stage_map = dict(screening='screen', build='split', minim='min', canari='cans')
145
+ stage_map = dict(
146
+ screening="screen", build="split", minim="min", canari="cans"
147
+ )
126
148
  mystage = stage_map.get(self.stage, self.stage)
127
- return '_'.join((self.layout, mystage, self.part)) + '.tar'
149
+ return "_".join((self.layout, mystage, self.part)) + ".tar"
128
150
 
129
151
  @property
130
152
  def _archive_mapping(self):
131
- re_fullmix = re.compile(r'^(?:altitude|mix|full)$')
132
- ecma_map = dict(void='ecmascr.tar',
133
- screening='odb_screen.tar',
134
- matchup='odb_cpl.tar', complete='odb_cpl.tar')
135
- ecma_prefix = {('matchup', 'arpege'): 'BASE/',
136
- ('complete', 'arpege'): 'BASE/',
137
- ('matchup', 'arome'): 'BASE/',
138
- ('complete', 'arome'): 'BASE/',
139
- ('screening', 'arome'): './'}
140
- if self.stage in ecma_map and self.layout == 'ecma':
153
+ re_fullmix = re.compile(r"^(?:altitude|mix|full)$")
154
+ ecma_map = dict(
155
+ void="ecmascr.tar",
156
+ screening="odb_screen.tar",
157
+ matchup="odb_cpl.tar",
158
+ complete="odb_cpl.tar",
159
+ )
160
+ ecma_prefix = {
161
+ ("matchup", "arpege"): "BASE/",
162
+ ("complete", "arpege"): "BASE/",
163
+ ("matchup", "arome"): "BASE/",
164
+ ("complete", "arome"): "BASE/",
165
+ ("screening", "arome"): "./",
166
+ }
167
+ if self.stage in ecma_map and self.layout == "ecma":
141
168
  if re_fullmix.match(self.part):
142
- return (ecma_map[self.stage], 'extract=all&format=unknown')
143
- elif self.part == 'virtual':
144
- return (ecma_map[self.stage],
145
- 'extract={:s}ECMA&format=unknown'
146
- .format(ecma_prefix.get((self.stage, self.model), '')))
169
+ return (ecma_map[self.stage], "extract=all&format=unknown")
170
+ elif self.part == "virtual":
171
+ return (
172
+ ecma_map[self.stage],
173
+ "extract={:s}ECMA&format=unknown".format(
174
+ ecma_prefix.get((self.stage, self.model), "")
175
+ ),
176
+ )
147
177
  else:
148
- return (ecma_map[self.stage],
149
- 'extract={:s}ECMA.{:s}&format=unknown'
150
- .format(ecma_prefix.get((self.stage, self.model), ''), self.part))
151
- elif self.stage == 'screening' and self.layout == 'ccma':
152
- return ('odb_ccma_screen.tar', '')
153
- elif re_fullmix.match(self.part) and self.stage == 'traj':
154
- return ('odb_traj.tar', '')
155
- elif re_fullmix.match(self.part) and self.stage == 'minim' and self.model == 'aladin':
156
- return ('odb_cpl.tar', '')
157
- elif re_fullmix.match(self.part) and self.stage == 'minim':
158
- return ('odb_min.tar', '')
159
- elif self.part in ('ground', 'surf') and self.stage in ('canari', 'surfan'):
160
- return ('odb_canari.tar', '')
178
+ return (
179
+ ecma_map[self.stage],
180
+ "extract={:s}ECMA.{:s}&format=unknown".format(
181
+ ecma_prefix.get((self.stage, self.model), ""),
182
+ self.part,
183
+ ),
184
+ )
185
+ elif self.stage == "screening" and self.layout == "ccma":
186
+ return ("odb_ccma_screen.tar", "")
187
+ elif re_fullmix.match(self.part) and self.stage == "traj":
188
+ return ("odb_traj.tar", "")
189
+ elif (
190
+ re_fullmix.match(self.part)
191
+ and self.stage == "minim"
192
+ and self.model == "aladin"
193
+ ):
194
+ return ("odb_cpl.tar", "")
195
+ elif re_fullmix.match(self.part) and self.stage == "minim":
196
+ return ("odb_min.tar", "")
197
+ elif self.part in ("ground", "surf") and self.stage in (
198
+ "canari",
199
+ "surfan",
200
+ ):
201
+ return ("odb_canari.tar", "")
161
202
  else:
162
203
  logger.error(
163
- 'No archive basename defined for such observations (format=%s, part=%s, stage=%s)',
164
- self.nativefmt, self.part, self.stage
204
+ "No archive basename defined for such observations (format=%s, part=%s, stage=%s)",
205
+ self.nativefmt,
206
+ self.part,
207
+ self.stage,
165
208
  )
166
209
  return (None, None)
167
210
 
@@ -180,88 +223,102 @@ class ObsRaw(Observations):
180
223
  """
181
224
 
182
225
  _footprint = dict(
183
- info = 'Raw observations set',
184
- attr = dict(
185
- nativefmt = dict(
186
- values = ['obsoul', 'grib', 'bufr', 'ascii', 'netcdf', 'hdf5'],
187
- remap = dict(
188
- OBSOUL = 'obsoul',
189
- GRIB = 'grib',
190
- BUFR = 'bufr',
191
- ASCII = 'ascii',
192
- NETCDF = 'netcdf',
193
- HDF5 = 'hdf5'
194
- )
195
- ),
196
- stage = dict(
197
- values = ['void', 'extract', 'raw', 'std']
226
+ info="Raw observations set",
227
+ attr=dict(
228
+ nativefmt=dict(
229
+ values=["obsoul", "grib", "bufr", "ascii", "netcdf", "hdf5"],
230
+ remap=dict(
231
+ OBSOUL="obsoul",
232
+ GRIB="grib",
233
+ BUFR="bufr",
234
+ ASCII="ascii",
235
+ NETCDF="netcdf",
236
+ HDF5="hdf5",
237
+ ),
198
238
  ),
199
- olivefmt = dict(
200
- info = 'The mapping between Vortex and Olive formats names.',
201
- type = footprints.FPDict,
202
- optional = True,
203
- default = footprints.FPDict(
204
- ascii = 'ascii',
205
- obsoul = 'obsoul',
206
- grib = 'obsgrib',
207
- bufr = 'obsbufr',
208
- netcdf = 'netcdf',
209
- hdf5 = 'hdf5',
239
+ stage=dict(values=["void", "extract", "raw", "std"]),
240
+ olivefmt=dict(
241
+ info="The mapping between Vortex and Olive formats names.",
242
+ type=footprints.FPDict,
243
+ optional=True,
244
+ default=footprints.FPDict(
245
+ ascii="ascii",
246
+ obsoul="obsoul",
247
+ grib="obsgrib",
248
+ bufr="obsbufr",
249
+ netcdf="netcdf",
250
+ hdf5="hdf5",
210
251
  ),
211
- doc_visibility = footprints.doc.visibility.GURU,
212
- )
213
- )
252
+ doc_visibility=footprints.doc.visibility.GURU,
253
+ ),
254
+ ),
214
255
  )
215
256
 
216
257
  def olive_basename(self):
217
258
  """OLIVE specific naming convention."""
218
- return '_'.join((
219
- self.olivefmt.get(self.nativefmt, 'obsfoo'),
220
- self.stage,
221
- self.part
222
- ))
259
+ return "_".join(
260
+ (
261
+ self.olivefmt.get(self.nativefmt, "obsfoo"),
262
+ self.stage,
263
+ self.part,
264
+ )
265
+ )
223
266
 
224
267
  def archive_basename(self):
225
268
  """OP ARCHIVE specific naming convention."""
226
- if (re.match(r'^(?:bufr|obsoul|grib|netcdf|hdf5)$', self.nativefmt) and
227
- self.part != 'full' and self.stage == 'void'):
228
- return '.'.join((self.nativefmt, self.part))
229
- elif re.match(r'^obsoul$', self.nativefmt) and self.part == 'full' and self.stage == 'void':
230
- return 'obsoul'
269
+ if (
270
+ re.match(r"^(?:bufr|obsoul|grib|netcdf|hdf5)$", self.nativefmt)
271
+ and self.part != "full"
272
+ and self.stage == "void"
273
+ ):
274
+ return ".".join((self.nativefmt, self.part))
275
+ elif (
276
+ re.match(r"^obsoul$", self.nativefmt)
277
+ and self.part == "full"
278
+ and self.stage == "void"
279
+ ):
280
+ return "obsoul"
231
281
  else:
232
282
  logger.error(
233
- 'No archive basename defined for such observations (format=%s, part=%s, stage=%s)',
234
- self.nativefmt, self.part, self.stage
283
+ "No archive basename defined for such observations (format=%s, part=%s, stage=%s)",
284
+ self.nativefmt,
285
+ self.part,
286
+ self.stage,
235
287
  )
236
288
 
237
289
 
238
- @stddeco.namebuilding_insert('radical', lambda s: s.kind)
239
- @stddeco.namebuilding_insert('src', lambda s: [s.part, ])
290
+ @stddeco.namebuilding_insert("radical", lambda s: s.kind)
291
+ @stddeco.namebuilding_insert(
292
+ "src",
293
+ lambda s: [
294
+ s.part,
295
+ ],
296
+ )
240
297
  class ObsFlags(FlowResource):
241
298
  """Class for observations flags."""
242
299
 
243
300
  _footprint = dict(
244
- info = 'Observations flags',
245
- attr = dict(
246
- kind = dict(
247
- values = ['obsflag'],
301
+ info="Observations flags",
302
+ attr=dict(
303
+ kind=dict(
304
+ values=["obsflag"],
248
305
  ),
249
306
  nativefmt=dict(
250
- values=['ascii', 'txt'],
251
- default='txt',
252
- remap=dict(ascii='txt'),
307
+ values=["ascii", "txt"],
308
+ default="txt",
309
+ remap=dict(ascii="txt"),
253
310
  ),
254
- part = dict(),
311
+ part=dict(),
255
312
  ),
256
313
  )
257
314
 
258
315
  @property
259
316
  def realkind(self):
260
- return 'obsflags'
317
+ return "obsflags"
261
318
 
262
319
  def olive_basename(self):
263
320
  """OLIVE specific naming convention."""
264
- return 'BDM_CQ'
321
+ return "BDM_CQ"
265
322
 
266
323
 
267
324
  @nicedeco
@@ -278,7 +335,6 @@ def needs_slurp(mtd):
278
335
 
279
336
 
280
337
  class VarBCContent(AlmostListContent):
281
-
282
338
  # The VarBC file is too big: revert to the good old diff
283
339
  _diffable = False
284
340
 
@@ -305,6 +361,7 @@ class VarBCContent(AlmostListContent):
305
361
  if self._parsed_data is None:
306
362
  # May fail if Numpy is not installed...
307
363
  from bronx.datagrip.varbc import VarbcFile
364
+
308
365
  self._parsed_data = VarbcFile(self.data)
309
366
  return self._parsed_data
310
367
 
@@ -319,68 +376,86 @@ class VarBCContent(AlmostListContent):
319
376
  self._do_delayed_slurp = container
320
377
  with container.preferred_decoding(byte=False):
321
378
  container.rewind()
322
- self._metadata = VarbcHeadersFile([container.readline() for _ in range(3)])
379
+ self._metadata = VarbcHeadersFile(
380
+ [container.readline() for _ in range(3)]
381
+ )
323
382
 
324
383
 
325
- @stddeco.namebuilding_append('src', lambda s: [s.stage, ])
384
+ @stddeco.namebuilding_append(
385
+ "src",
386
+ lambda s: [
387
+ s.stage,
388
+ ],
389
+ )
326
390
  class VarBC(FlowResource):
327
391
  """
328
392
  VarBC file resource. Contains all the coefficients for the VarBC bias correction scheme.
329
393
  """
330
394
 
331
395
  _footprint = dict(
332
- info = 'Varbc file (coefficients for the bias correction of observations).',
333
- attr = dict(
334
- kind = dict(
335
- values = ['varbc']
396
+ info="Varbc file (coefficients for the bias correction of observations).",
397
+ attr=dict(
398
+ kind=dict(values=["varbc"]),
399
+ clscontents=dict(
400
+ default=VarBCContent,
336
401
  ),
337
- clscontents = dict(
338
- default = VarBCContent,
339
- ),
340
- nativefmt = dict(
341
- values = ['ascii', 'txt'],
342
- default = 'txt',
343
- remap = dict(ascii = 'txt'),
402
+ nativefmt=dict(
403
+ values=["ascii", "txt"],
404
+ default="txt",
405
+ remap=dict(ascii="txt"),
344
406
  ),
345
- stage = dict(
346
- optional = True,
347
- values = ['void', 'merge', 'screen', 'screening', 'minim', 'traj'],
348
- remap = dict(screen = 'screening'),
349
- default = 'void'
407
+ stage=dict(
408
+ optional=True,
409
+ values=[
410
+ "void",
411
+ "merge",
412
+ "screen",
413
+ "screening",
414
+ "minim",
415
+ "traj",
416
+ ],
417
+ remap=dict(screen="screening"),
418
+ default="void",
350
419
  ),
351
- mixmodel = dict(
352
- optional = True,
353
- default = None,
354
- values = stdattrs.models,
420
+ mixmodel=dict(
421
+ optional=True,
422
+ default=None,
423
+ values=stdattrs.models,
355
424
  ),
356
- )
425
+ ),
357
426
  )
358
427
 
359
428
  @property
360
429
  def realkind(self):
361
- return 'varbc'
430
+ return "varbc"
362
431
 
363
432
  def olive_basename(self):
364
433
  """OLIVE specific naming convention."""
365
- olivestage_map = {'screening': 'screen', }
366
- return self.realkind.upper() + "." + olivestage_map.get(self.stage, self.stage)
434
+ olivestage_map = {
435
+ "screening": "screen",
436
+ }
437
+ return (
438
+ self.realkind.upper()
439
+ + "."
440
+ + olivestage_map.get(self.stage, self.stage)
441
+ )
367
442
 
368
443
  def archive_basename(self):
369
444
  """OP ARCHIVE specific naming convention."""
370
- if self.stage in ('void', 'traj'):
371
- bname = 'VARBC.cycle'
445
+ if self.stage in ("void", "traj"):
446
+ bname = "VARBC.cycle"
372
447
  if self.mixmodel is not None:
373
- bname += '_'
374
- if self.mixmodel.startswith('alad'):
448
+ bname += "_"
449
+ if self.mixmodel.startswith("alad"):
375
450
  bname = bname + self.mixmodel[:4]
376
451
  else:
377
452
  bname = bname + self.mixmodel[:3]
378
453
  else:
379
- bname = 'VARBC.' + self.stage
454
+ bname = "VARBC." + self.stage
380
455
  return bname
381
456
 
382
457
 
383
- @stddeco.namebuilding_insert('src', lambda s: s.scope)
458
+ @stddeco.namebuilding_insert("src", lambda s: s.scope)
384
459
  class BlackList(FlowResource):
385
460
  """
386
461
  TODO.
@@ -389,66 +464,73 @@ class BlackList(FlowResource):
389
464
  _footprint = [
390
465
  gvar,
391
466
  dict(
392
- info = 'Blacklist file for observations',
393
- attr = dict(
394
- kind = dict(
395
- values = ['blacklist'],
396
- ),
397
- gvar = dict(
398
- default = 'blacklist_[scope]',
399
- values = ['BLACKLIST_LOC', 'BLACKLIST_DIAP', 'BLACKLIST_LOCAL', 'BLACKLIST_GLOBAL'],
400
- remap = dict(
401
- BLACKLIST_LOCAL = 'BLACKLIST_LOC',
402
- BLACKLIST_GLOBAL = 'BLACKLIST_DIAP',
403
- blacklist_local = 'BLACKLIST_LOC',
404
- blacklist_global = 'BLACKLIST_DIAP',
405
- )
467
+ info="Blacklist file for observations",
468
+ attr=dict(
469
+ kind=dict(
470
+ values=["blacklist"],
406
471
  ),
407
- clscontents = dict(
408
- default = TextContent,
472
+ gvar=dict(
473
+ default="blacklist_[scope]",
474
+ values=[
475
+ "BLACKLIST_LOC",
476
+ "BLACKLIST_DIAP",
477
+ "BLACKLIST_LOCAL",
478
+ "BLACKLIST_GLOBAL",
479
+ ],
480
+ remap=dict(
481
+ BLACKLIST_LOCAL="BLACKLIST_LOC",
482
+ BLACKLIST_GLOBAL="BLACKLIST_DIAP",
483
+ blacklist_local="BLACKLIST_LOC",
484
+ blacklist_global="BLACKLIST_DIAP",
485
+ ),
409
486
  ),
410
- nativefmt = dict(
411
- values = ['txt'],
412
- default = 'txt'
487
+ clscontents=dict(
488
+ default=TextContent,
413
489
  ),
414
- scope = dict(
415
- values = ['loc', 'local', 'site', 'global', 'diap', 'diapason'],
416
- remap = dict(
417
- loc = 'local',
418
- site = 'local',
419
- diap = 'global',
420
- diapason = 'global',
421
- )
490
+ nativefmt=dict(values=["txt"], default="txt"),
491
+ scope=dict(
492
+ values=[
493
+ "loc",
494
+ "local",
495
+ "site",
496
+ "global",
497
+ "diap",
498
+ "diapason",
499
+ ],
500
+ remap=dict(
501
+ loc="local",
502
+ site="local",
503
+ diap="global",
504
+ diapason="global",
505
+ ),
422
506
  ),
423
- )
424
- )
507
+ ),
508
+ ),
425
509
  ]
426
510
 
427
511
  @property
428
512
  def realkind(self):
429
- return 'blacklist'
513
+ return "blacklist"
430
514
 
431
515
  def iga_pathinfo(self):
432
516
  """Standard path information for IGA inline cache."""
433
- return dict(
434
- model=self.model
435
- )
517
+ return dict(model=self.model)
436
518
 
437
519
  def archive_map(self):
438
520
  """OP ARCHIVE specific naming convention."""
439
521
  return {
440
- 'local': 'LISTE_LOC',
441
- 'global': 'LISTE_NOIRE_DIAP',
522
+ "local": "LISTE_LOC",
523
+ "global": "LISTE_NOIRE_DIAP",
442
524
  }
443
525
 
444
526
  def archive_basename(self):
445
527
  """OP ARCHIVE local basename."""
446
528
  mapd = self.archive_map()
447
- return mapd.get(self.scope, 'LISTE_NOIRE_X')
529
+ return mapd.get(self.scope, "LISTE_NOIRE_X")
448
530
 
449
531
 
450
532
  #: A namedtuple of the internal fields of an ObsRef file
451
- ObsRefItem = namedtuple('ObsRefItem', ('data', 'fmt', 'instr', 'date', 'time'))
533
+ ObsRefItem = namedtuple("ObsRefItem", ("data", "fmt", "instr", "date", "time"))
452
534
 
453
535
 
454
536
  class ObsRefContent(TextContent):
@@ -460,51 +542,55 @@ class ObsRefContent(TextContent):
460
542
 
461
543
  def slurp(self, container):
462
544
  with container.preferred_decoding(byte=False):
463
- self._data.extend([ObsRefItem(*x.split()[:5]) for x in container if not x.startswith('#')])
545
+ self._data.extend(
546
+ [
547
+ ObsRefItem(*x.split()[:5])
548
+ for x in container
549
+ if not x.startswith("#")
550
+ ]
551
+ )
464
552
  self._size = container.totalsize
465
553
 
466
554
  @classmethod
467
555
  def formatted_data(self, item):
468
556
  """Return a formatted string."""
469
- return '{:8s} {:8s} {:16s} {:s} {!s}'.format(
557
+ return "{:8s} {:8s} {:16s} {:s} {!s}".format(
470
558
  item.data, item.fmt, item.instr, str(item.date), item.time
471
559
  )
472
560
 
473
561
 
474
- @stddeco.namebuilding_append('src', lambda s: [s.part, ])
562
+ @stddeco.namebuilding_append(
563
+ "src",
564
+ lambda s: [
565
+ s.part,
566
+ ],
567
+ )
475
568
  class Refdata(FlowResource):
476
569
  """
477
570
  TODO.
478
571
  """
479
572
 
480
573
  _footprint = dict(
481
- info = 'Refdata file',
482
- attr = dict(
483
- kind = dict(
484
- values = ['refdata']
485
- ),
486
- clscontents = dict(
487
- default = ObsRefContent,
574
+ info="Refdata file",
575
+ attr=dict(
576
+ kind=dict(values=["refdata"]),
577
+ clscontents=dict(
578
+ default=ObsRefContent,
488
579
  ),
489
- nativefmt = dict(
490
- values = ['ascii', 'txt'],
491
- default = 'txt',
492
- remap = dict(ascii = 'txt')
493
- ),
494
- part = dict(
495
- optional = True,
496
- default = 'all'
580
+ nativefmt=dict(
581
+ values=["ascii", "txt"], default="txt", remap=dict(ascii="txt")
497
582
  ),
498
- )
583
+ part=dict(optional=True, default="all"),
584
+ ),
499
585
  )
500
586
 
501
587
  @property
502
588
  def realkind(self):
503
- return 'refdata'
589
+ return "refdata"
504
590
 
505
591
  def olive_basename(self):
506
592
  """OLIVE specific naming convention."""
507
- return self.realkind + '.' + self.part
593
+ return self.realkind + "." + self.part
508
594
 
509
595
  def archive_basename(self):
510
596
  """OP ARCHIVE specific naming convention."""
@@ -512,7 +598,7 @@ class Refdata(FlowResource):
512
598
 
513
599
 
514
600
  #: A namedtuple of the internal fields of an ObsMap file
515
- ObsMapItem = namedtuple('ObsMapItem', ('odb', 'data', 'fmt', 'instr'))
601
+ ObsMapItem = namedtuple("ObsMapItem", ("odb", "data", "fmt", "instr"))
516
602
 
517
603
 
518
604
  class ObsMapContent(TextContent):
@@ -545,8 +631,8 @@ class ObsMapContent(TextContent):
545
631
  """
546
632
 
547
633
  def __init__(self, **kw):
548
- kw.setdefault('discarded', set())
549
- kw.setdefault('only', None)
634
+ kw.setdefault("discarded", set())
635
+ kw.setdefault("only", None)
550
636
  super().__init__(**kw)
551
637
 
552
638
  @property
@@ -566,30 +652,41 @@ class ObsMapContent(TextContent):
566
652
  def slurp(self, container):
567
653
  """Get data from the ``container``."""
568
654
  if self.only is not None:
569
- ofilters = [re.compile(d if ':' in d else d + ':')
570
- for d in self.only]
655
+ ofilters = [
656
+ re.compile(d if ":" in d else d + ":") for d in self.only
657
+ ]
571
658
  else:
572
659
  ofilters = None
573
- dfilters = [re.compile(d if ':' in d else d + ':') for d in self.discarded]
660
+ dfilters = [
661
+ re.compile(d if ":" in d else d + ":") for d in self.discarded
662
+ ]
574
663
 
575
664
  def item_filter(omline):
576
- om = ':'.join([omline.odb, omline.data])
577
- return ((ofilters is None or
578
- any([f.match(om) for f in ofilters])) and
579
- not any([f.match(om) for f in dfilters]))
665
+ om = ":".join([omline.odb, omline.data])
666
+ return (
667
+ ofilters is None or any([f.match(om) for f in ofilters])
668
+ ) and not any([f.match(om) for f in dfilters])
580
669
 
581
670
  with container.preferred_decoding(byte=False):
582
671
  container.rewind()
583
- self.extend(filter(item_filter,
584
- [ObsMapItem(* x.split())
585
- for x in [line.strip() for line in container]
586
- if x and not x.startswith('#')]))
672
+ self.extend(
673
+ filter(
674
+ item_filter,
675
+ [
676
+ ObsMapItem(*x.split())
677
+ for x in [line.strip() for line in container]
678
+ if x and not x.startswith("#")
679
+ ],
680
+ )
681
+ )
587
682
  self._size = container.totalsize
588
683
 
589
684
  @classmethod
590
685
  def formatted_data(self, item):
591
686
  """Return a formatted string."""
592
- return '{:12s} {:12s} {:12s} {:s}'.format(item.odb, item.data, item.fmt, item.instr)
687
+ return "{:12s} {:12s} {:12s} {:s}".format(
688
+ item.odb, item.data, item.fmt, item.instr
689
+ )
593
690
 
594
691
  def odbset(self):
595
692
  """Return set of odb values."""
@@ -623,15 +720,15 @@ class ObsMapContent(TextContent):
623
720
 
624
721
  These naming convention refer to the footprints resolve mechanism.
625
722
  """
626
- part = g.get('part', x.get('part', None))
723
+ part = g.get("part", x.get("part", None))
627
724
  if part is None:
628
725
  return None
629
726
  else:
630
727
  return self.datafmt(part)
631
728
 
632
729
 
633
- @stddeco.namebuilding_insert('style', lambda s: 'obsmap')
634
- @stddeco.namebuilding_insert('stage', lambda s: [s.scope, s.stage])
730
+ @stddeco.namebuilding_insert("style", lambda s: "obsmap")
731
+ @stddeco.namebuilding_insert("stage", lambda s: [s.scope, s.stage])
635
732
  class ObsMap(FlowResource):
636
733
  """Observation mapping.
637
734
 
@@ -648,46 +745,43 @@ class ObsMap(FlowResource):
648
745
  _footprint = [
649
746
  gvar,
650
747
  dict(
651
- info = 'Bator mapping file',
652
- attr = dict(
653
- kind = dict(
654
- values = ['obsmap'],
748
+ info="Bator mapping file",
749
+ attr=dict(
750
+ kind=dict(
751
+ values=["obsmap"],
655
752
  ),
656
- clscontents = dict(
657
- default = ObsMapContent,
753
+ clscontents=dict(
754
+ default=ObsMapContent,
658
755
  ),
659
- nativefmt = dict(
660
- values = ['ascii', 'txt'],
661
- default = 'txt',
662
- remap = dict(ascii = 'txt')
756
+ nativefmt=dict(
757
+ values=["ascii", "txt"],
758
+ default="txt",
759
+ remap=dict(ascii="txt"),
663
760
  ),
664
- stage = dict(
665
- optional = True,
666
- default = 'void'
761
+ stage=dict(optional=True, default="void"),
762
+ scope=dict(
763
+ optional=True,
764
+ default="full",
765
+ remap=dict(surf="surface"),
667
766
  ),
668
- scope = dict(
669
- optional = True,
670
- default = 'full',
671
- remap = dict(surf = 'surface'),
767
+ discard=dict(
768
+ info="Discard some lines of the mapping (see the class documentation).",
769
+ type=footprints.FPSet,
770
+ optional=True,
771
+ default=footprints.FPSet(),
672
772
  ),
673
- discard = dict(
674
- info = "Discard some lines of the mapping (see the class documentation).",
675
- type = footprints.FPSet,
676
- optional = True,
677
- default = footprints.FPSet(),
773
+ only=dict(
774
+ info="Only retain some lines of the mapping (see the class documentation).",
775
+ type=footprints.FPSet,
776
+ optional=True,
678
777
  ),
679
- only = dict(
680
- info = "Only retain some lines of the mapping (see the class documentation).",
681
- type = footprints.FPSet,
682
- optional = True,
683
- )
684
- )
685
- )
778
+ ),
779
+ ),
686
780
  ]
687
781
 
688
782
  @property
689
783
  def realkind(self):
690
- return 'obsmap'
784
+ return "obsmap"
691
785
 
692
786
  def contents_args(self):
693
787
  """Returns default arguments value to class content constructor."""
@@ -695,54 +789,52 @@ class ObsMap(FlowResource):
695
789
 
696
790
  def olive_basename(self):
697
791
  """OLIVE specific naming convention."""
698
- return 'OBSMAP_' + self.stage
792
+ return "OBSMAP_" + self.stage
699
793
 
700
794
  def archive_basename(self):
701
795
  """OP ARCHIVE specific naming convention."""
702
- if self.scope.startswith('surf'):
703
- return 'BATOR_MAP_' + self.scope[:4].lower()
796
+ if self.scope.startswith("surf"):
797
+ return "BATOR_MAP_" + self.scope[:4].lower()
704
798
  else:
705
- return 'BATOR_MAP'
799
+ return "BATOR_MAP"
706
800
 
707
801
  def genv_basename(self):
708
802
  """Genv key naming convention."""
709
- cutoff_map = {'production': 'prod'}
803
+ cutoff_map = {"production": "prod"}
710
804
  if self.gvar is None:
711
- if self.scope == 'surface':
712
- gkey = 'bator_map_surf'
805
+ if self.scope == "surface":
806
+ gkey = "bator_map_surf"
713
807
  else:
714
- gkey = 'bator_map_' + cutoff_map.get(self.cutoff, self.cutoff)
808
+ gkey = "bator_map_" + cutoff_map.get(self.cutoff, self.cutoff)
715
809
  return GenvKey(gkey)
716
810
  else:
717
811
  return self.gvar
718
812
 
719
813
 
720
- @stddeco.namebuilding_insert('src', lambda s: s.satbias)
814
+ @stddeco.namebuilding_insert("src", lambda s: s.satbias)
721
815
  class Bcor(FlowResource):
722
816
  """Bias correction parameters."""
723
817
 
724
818
  _footprint = dict(
725
- info = 'Bias correction parameters',
726
- attr = dict(
727
- kind = dict(
728
- values = ['bcor'],
819
+ info="Bias correction parameters",
820
+ attr=dict(
821
+ kind=dict(
822
+ values=["bcor"],
729
823
  ),
730
- nativefmt = dict(
731
- values = ['ascii', 'txt'],
732
- default = 'txt',
733
- remap = dict(ascii = 'txt')
824
+ nativefmt=dict(
825
+ values=["ascii", "txt"], default="txt", remap=dict(ascii="txt")
734
826
  ),
735
- satbias = dict(
736
- values = ['mtop', 'metop', 'noaa', 'ssmi'],
737
- remap = dict(metop = 'mtop'),
827
+ satbias=dict(
828
+ values=["mtop", "metop", "noaa", "ssmi"],
829
+ remap=dict(metop="mtop"),
738
830
  ),
739
- )
831
+ ),
740
832
  )
741
833
 
742
834
  @property
743
835
  def realkind(self):
744
- return 'bcor'
836
+ return "bcor"
745
837
 
746
838
  def archive_basename(self):
747
839
  """OP ARCHIVE specific naming convention."""
748
- return 'bcor_' + self.satbias + '.dat'
840
+ return "bcor_" + self.satbias + ".dat"