vortex-nwp 2.0.0b1__py3-none-any.whl → 2.1.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.
Files changed (141) hide show
  1. vortex/__init__.py +75 -47
  2. vortex/algo/__init__.py +3 -2
  3. vortex/algo/components.py +944 -618
  4. vortex/algo/mpitools.py +802 -497
  5. vortex/algo/mpitools_templates/__init__.py +1 -0
  6. vortex/algo/serversynctools.py +34 -33
  7. vortex/config.py +19 -22
  8. vortex/data/__init__.py +9 -3
  9. vortex/data/abstractstores.py +593 -655
  10. vortex/data/containers.py +217 -162
  11. vortex/data/contents.py +65 -39
  12. vortex/data/executables.py +93 -102
  13. vortex/data/flow.py +40 -34
  14. vortex/data/geometries.py +228 -132
  15. vortex/data/handlers.py +436 -227
  16. vortex/data/outflow.py +15 -15
  17. vortex/data/providers.py +185 -163
  18. vortex/data/resources.py +48 -42
  19. vortex/data/stores.py +540 -417
  20. vortex/data/sync_templates/__init__.py +0 -0
  21. vortex/gloves.py +114 -87
  22. vortex/layout/__init__.py +1 -8
  23. vortex/layout/contexts.py +150 -84
  24. vortex/layout/dataflow.py +353 -202
  25. vortex/layout/monitor.py +264 -128
  26. vortex/nwp/__init__.py +5 -2
  27. vortex/nwp/algo/__init__.py +14 -5
  28. vortex/nwp/algo/assim.py +205 -151
  29. vortex/nwp/algo/clim.py +683 -517
  30. vortex/nwp/algo/coupling.py +447 -225
  31. vortex/nwp/algo/eda.py +437 -229
  32. vortex/nwp/algo/eps.py +403 -231
  33. vortex/nwp/algo/forecasts.py +416 -275
  34. vortex/nwp/algo/fpserver.py +683 -307
  35. vortex/nwp/algo/ifsnaming.py +205 -145
  36. vortex/nwp/algo/ifsroot.py +215 -122
  37. vortex/nwp/algo/monitoring.py +137 -76
  38. vortex/nwp/algo/mpitools.py +330 -190
  39. vortex/nwp/algo/odbtools.py +637 -353
  40. vortex/nwp/algo/oopsroot.py +454 -273
  41. vortex/nwp/algo/oopstests.py +90 -56
  42. vortex/nwp/algo/request.py +287 -206
  43. vortex/nwp/algo/stdpost.py +878 -522
  44. vortex/nwp/data/__init__.py +22 -4
  45. vortex/nwp/data/assim.py +125 -137
  46. vortex/nwp/data/boundaries.py +121 -68
  47. vortex/nwp/data/climfiles.py +193 -211
  48. vortex/nwp/data/configfiles.py +73 -69
  49. vortex/nwp/data/consts.py +426 -401
  50. vortex/nwp/data/ctpini.py +59 -43
  51. vortex/nwp/data/diagnostics.py +94 -66
  52. vortex/nwp/data/eda.py +50 -51
  53. vortex/nwp/data/eps.py +195 -146
  54. vortex/nwp/data/executables.py +440 -434
  55. vortex/nwp/data/fields.py +63 -48
  56. vortex/nwp/data/gridfiles.py +183 -111
  57. vortex/nwp/data/logs.py +250 -217
  58. vortex/nwp/data/modelstates.py +180 -151
  59. vortex/nwp/data/monitoring.py +72 -99
  60. vortex/nwp/data/namelists.py +254 -202
  61. vortex/nwp/data/obs.py +400 -308
  62. vortex/nwp/data/oopsexec.py +22 -20
  63. vortex/nwp/data/providers.py +90 -65
  64. vortex/nwp/data/query.py +71 -82
  65. vortex/nwp/data/stores.py +49 -36
  66. vortex/nwp/data/surfex.py +136 -137
  67. vortex/nwp/syntax/__init__.py +1 -1
  68. vortex/nwp/syntax/stdattrs.py +173 -111
  69. vortex/nwp/tools/__init__.py +2 -2
  70. vortex/nwp/tools/addons.py +22 -17
  71. vortex/nwp/tools/agt.py +24 -12
  72. vortex/nwp/tools/bdap.py +16 -5
  73. vortex/nwp/tools/bdcp.py +4 -1
  74. vortex/nwp/tools/bdm.py +3 -0
  75. vortex/nwp/tools/bdmp.py +14 -9
  76. vortex/nwp/tools/conftools.py +728 -378
  77. vortex/nwp/tools/drhook.py +12 -8
  78. vortex/nwp/tools/grib.py +65 -39
  79. vortex/nwp/tools/gribdiff.py +22 -17
  80. vortex/nwp/tools/ifstools.py +82 -42
  81. vortex/nwp/tools/igastuff.py +167 -143
  82. vortex/nwp/tools/mars.py +14 -2
  83. vortex/nwp/tools/odb.py +234 -125
  84. vortex/nwp/tools/partitioning.py +61 -37
  85. vortex/nwp/tools/satrad.py +27 -12
  86. vortex/nwp/util/async.py +83 -55
  87. vortex/nwp/util/beacon.py +10 -10
  88. vortex/nwp/util/diffpygram.py +174 -86
  89. vortex/nwp/util/ens.py +144 -63
  90. vortex/nwp/util/hooks.py +30 -19
  91. vortex/nwp/util/taskdeco.py +28 -24
  92. vortex/nwp/util/usepygram.py +278 -172
  93. vortex/nwp/util/usetnt.py +31 -17
  94. vortex/sessions.py +72 -39
  95. vortex/syntax/__init__.py +1 -1
  96. vortex/syntax/stdattrs.py +410 -171
  97. vortex/syntax/stddeco.py +31 -22
  98. vortex/toolbox.py +327 -192
  99. vortex/tools/__init__.py +11 -2
  100. vortex/tools/actions.py +110 -121
  101. vortex/tools/addons.py +111 -92
  102. vortex/tools/arm.py +42 -22
  103. vortex/tools/compression.py +72 -69
  104. vortex/tools/date.py +11 -4
  105. vortex/tools/delayedactions.py +242 -132
  106. vortex/tools/env.py +75 -47
  107. vortex/tools/folder.py +342 -171
  108. vortex/tools/grib.py +341 -162
  109. vortex/tools/lfi.py +423 -216
  110. vortex/tools/listings.py +109 -40
  111. vortex/tools/names.py +218 -156
  112. vortex/tools/net.py +655 -299
  113. vortex/tools/parallelism.py +93 -61
  114. vortex/tools/prestaging.py +55 -31
  115. vortex/tools/schedulers.py +172 -105
  116. vortex/tools/services.py +403 -334
  117. vortex/tools/storage.py +293 -358
  118. vortex/tools/surfex.py +24 -24
  119. vortex/tools/systems.py +1234 -643
  120. vortex/tools/targets.py +156 -100
  121. vortex/util/__init__.py +1 -1
  122. vortex/util/config.py +378 -327
  123. vortex/util/empty.py +2 -2
  124. vortex/util/helpers.py +56 -24
  125. vortex/util/introspection.py +18 -12
  126. vortex/util/iosponge.py +8 -4
  127. vortex/util/roles.py +4 -6
  128. vortex/util/storefunctions.py +39 -13
  129. vortex/util/structs.py +3 -3
  130. vortex/util/worker.py +29 -17
  131. vortex_nwp-2.1.0.dist-info/METADATA +67 -0
  132. vortex_nwp-2.1.0.dist-info/RECORD +144 -0
  133. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info}/WHEEL +1 -1
  134. vortex/layout/appconf.py +0 -109
  135. vortex/layout/jobs.py +0 -1276
  136. vortex/layout/nodes.py +0 -1424
  137. vortex/layout/subjobs.py +0 -464
  138. vortex_nwp-2.0.0b1.dist-info/METADATA +0 -50
  139. vortex_nwp-2.0.0b1.dist-info/RECORD +0 -146
  140. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info/licenses}/LICENSE +0 -0
  141. {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info}/top_level.txt +0 -0
vortex/nwp/data/fields.py CHANGED
@@ -11,86 +11,101 @@ from vortex.syntax.stddeco import namebuilding_delete, namebuilding_insert
11
11
  __all__ = []
12
12
 
13
13
 
14
- @namebuilding_insert('radical', lambda s: s.fields)
15
- @namebuilding_insert('src', lambda s: [s.origin, ])
16
- @namebuilding_delete('fmt')
14
+ @namebuilding_insert("radical", lambda s: s.fields)
15
+ @namebuilding_insert(
16
+ "src",
17
+ lambda s: [
18
+ s.origin,
19
+ ],
20
+ )
21
+ @namebuilding_delete("fmt")
17
22
  class RawFields(StaticResource):
18
-
19
23
  _footprint = [
20
- date_deco, cutoff_deco,
24
+ date_deco,
25
+ cutoff_deco,
21
26
  dict(
22
- info = 'File containing a limited list of observations fields',
23
- attr = dict(
24
- kind = dict(
25
- values = ['rawfields']
26
- ),
27
- origin = dict(
28
- values = [
29
- 'bdm', 'nesdis', 'ostia', 'psy4',
30
- 'mercator_global', 'bdpe', 'safosi',
31
- 'safosi_hn', 'safosi_hs',
27
+ info="File containing a limited list of observations fields",
28
+ attr=dict(
29
+ kind=dict(values=["rawfields"]),
30
+ origin=dict(
31
+ values=[
32
+ "bdm",
33
+ "nesdis",
34
+ "ostia",
35
+ "psy4",
36
+ "mercator_global",
37
+ "bdpe",
38
+ "safosi",
39
+ "safosi_hn",
40
+ "safosi_hs",
32
41
  ]
33
42
  ),
34
- fields = dict(
35
- values = ['sst', 'seaice', 'ocean', 'seaice_conc', 'seaice_thick']
43
+ fields=dict(
44
+ values=[
45
+ "sst",
46
+ "seaice",
47
+ "ocean",
48
+ "seaice_conc",
49
+ "seaice_thick",
50
+ ]
36
51
  ),
37
- )
38
- )
52
+ ),
53
+ ),
39
54
  ]
40
55
 
41
56
  @property
42
57
  def realkind(self):
43
- return 'rawfields'
58
+ return "rawfields"
44
59
 
45
60
  def olive_basename(self):
46
- if self.origin == 'nesdis' and self.fields == 'sst':
47
- bname = '.'.join((self.fields, self.origin, 'bdap'))
48
- elif self.fields == 'seaice':
49
- bname = 'ice_concent'
61
+ if self.origin == "nesdis" and self.fields == "sst":
62
+ bname = ".".join((self.fields, self.origin, "bdap"))
63
+ elif self.fields == "seaice":
64
+ bname = "ice_concent"
50
65
  else:
51
- bname = '.'.join((self.fields, self.origin))
66
+ bname = ".".join((self.fields, self.origin))
52
67
  return bname
53
68
 
54
69
  def archive_basename(self):
55
- if self.origin == 'nesdis' and self.fields == 'sst':
56
- bname = '.'.join((self.fields, self.origin, 'bdap'))
57
- elif self.fields == 'seaice':
58
- bname = 'ice_concent'
70
+ if self.origin == "nesdis" and self.fields == "sst":
71
+ bname = ".".join((self.fields, self.origin, "bdap"))
72
+ elif self.fields == "seaice":
73
+ bname = "ice_concent"
59
74
  else:
60
- bname = '.'.join((self.fields, self.origin))
75
+ bname = ".".join((self.fields, self.origin))
61
76
  return bname
62
77
 
63
78
 
64
- @namebuilding_insert('radical', lambda s: s.fields)
79
+ @namebuilding_insert("radical", lambda s: s.fields)
65
80
  class GeoFields(GeoFlowResource):
66
-
67
81
  _footprint = [
68
82
  dict(
69
- info = 'File containing a limited list of fields in a specific geometry',
70
- attr = dict(
71
- kind = dict(
72
- values = ['geofields']
73
- ),
74
- fields = dict(
75
- values = ['sst', 'seaice', 'ocean', 'seaice_conc', 'seaice_thick']
76
- ),
77
- nativefmt = dict(
78
- values = ['fa'],
79
- default = 'fa'
83
+ info="File containing a limited list of fields in a specific geometry",
84
+ attr=dict(
85
+ kind=dict(values=["geofields"]),
86
+ fields=dict(
87
+ values=[
88
+ "sst",
89
+ "seaice",
90
+ "ocean",
91
+ "seaice_conc",
92
+ "seaice_thick",
93
+ ]
80
94
  ),
81
- )
95
+ nativefmt=dict(values=["fa"], default="fa"),
96
+ ),
82
97
  )
83
98
  ]
84
99
 
85
100
  @property
86
101
  def realkind(self):
87
- return 'geofields'
102
+ return "geofields"
88
103
 
89
104
  def olive_basename(self):
90
- bname = 'icmshanal' + self.fields
91
- if self.fields == 'seaice':
105
+ bname = "icmshanal" + self.fields
106
+ if self.fields == "seaice":
92
107
  bname = bname.upper()
93
108
  return bname
94
109
 
95
110
  def archive_basename(self):
96
- return 'icmshanal' + self.fields
111
+ return "icmshanal" + self.fields
@@ -21,7 +21,7 @@ _ORIGIN_INFO = """Describes where the data originaly comes from. The most common
21
21
  values are: ana (that stands for analysis), fcst (that stands for
22
22
  forecast), hst (that stands for Historic file. i.e a file that contains a
23
23
  full model state variable), stat_ad (that stands for statistical adapatation)."""
24
- _ORIGIN_INFO = _ORIGIN_INFO.replace('\n', ' ')
24
+ _ORIGIN_INFO = _ORIGIN_INFO.replace("\n", " ")
25
25
 
26
26
 
27
27
  class AbstractGridpoint(GeoFlowResource):
@@ -35,48 +35,67 @@ class AbstractGridpoint(GeoFlowResource):
35
35
 
36
36
  _abstract = True
37
37
  _footprint = dict(
38
- info = 'Any kind of GridPoint file.',
39
- attr = dict(
40
- origin = dict(
41
- info = _ORIGIN_INFO,
42
- values = [
43
- 'analyse', 'ana', 'guess', 'gss', 'arpege', 'arp', 'arome', 'aro',
44
- 'aladin', 'ald', 'historic', 'hst', 'forecast', 'fcst', 'era40', 'e40',
45
- 'era15', 'e15', 'interp', 'sumo', 'filter', 'stat_ad',
38
+ info="Any kind of GridPoint file.",
39
+ attr=dict(
40
+ origin=dict(
41
+ info=_ORIGIN_INFO,
42
+ values=[
43
+ "analyse",
44
+ "ana",
45
+ "guess",
46
+ "gss",
47
+ "arpege",
48
+ "arp",
49
+ "arome",
50
+ "aro",
51
+ "aladin",
52
+ "ald",
53
+ "historic",
54
+ "hst",
55
+ "forecast",
56
+ "fcst",
57
+ "era40",
58
+ "e40",
59
+ "era15",
60
+ "e15",
61
+ "interp",
62
+ "sumo",
63
+ "filter",
64
+ "stat_ad",
46
65
  ],
47
- remap = dict(
48
- analyse = 'ana',
49
- guess = 'gss',
50
- arpege = 'arp',
51
- aladin = 'ald',
52
- arome = 'aro',
53
- historic = 'hst',
54
- forecast = 'fcst',
55
- era40 = 'e40',
56
- era15 = 'e15'
57
- )
66
+ remap=dict(
67
+ analyse="ana",
68
+ guess="gss",
69
+ arpege="arp",
70
+ aladin="ald",
71
+ arome="aro",
72
+ historic="hst",
73
+ forecast="fcst",
74
+ era40="e40",
75
+ era15="e15",
76
+ ),
58
77
  ),
59
- kind = dict(
60
- values = ['gridpoint', 'gribfile', 'fullpos'],
61
- remap = dict(
62
- fullpos = 'gridpoint'
63
- )
78
+ kind=dict(
79
+ values=["gridpoint", "gribfile", "fullpos"],
80
+ remap=dict(fullpos="gridpoint"),
64
81
  ),
65
- nativefmt = dict(
66
- values = ['grib', 'grib1', 'grib2', 'netcdf', 'fa'],
82
+ nativefmt=dict(
83
+ values=["grib", "grib1", "grib2", "netcdf", "fa"],
67
84
  ),
68
- filtername = dict(
85
+ filtername=dict(
69
86
  # Dummy argument but avoid priority related messages with footprints
70
- info = 'With GridPoint files, leave filtername empty...',
71
- optional = True,
72
- values = [None, ],
87
+ info="With GridPoint files, leave filtername empty...",
88
+ optional=True,
89
+ values=[
90
+ None,
91
+ ],
73
92
  ),
74
- )
93
+ ),
75
94
  )
76
95
 
77
96
  @property
78
97
  def realkind(self):
79
- return 'gridpoint'
98
+ return "gridpoint"
80
99
 
81
100
  def olive_basename(self):
82
101
  """OLIVE specific naming convention (abstract)."""
@@ -89,35 +108,32 @@ class AbstractGridpoint(GeoFlowResource):
89
108
  def namebuilding_info(self):
90
109
  """Generic information, radical = ``grid``."""
91
110
  ninfo = super().namebuilding_info()
92
- if self.origin in ('stat_ad', ):
111
+ if self.origin in ("stat_ad",):
93
112
  # For new ``origin`` please use this code path... Please, no more
94
113
  # weird logic like the one hard-coded in the else statement !
95
114
  source = self.origin
96
115
  else:
97
- if self.model == 'mocage':
98
- if self.origin == 'hst':
99
- source = 'forecast'
116
+ if self.model == "mocage":
117
+ if self.origin == "hst":
118
+ source = "forecast"
100
119
  else:
101
- source = 'sumo'
102
- elif self.model in ('hycom', 'mfwam'):
103
- if self.origin == 'ana':
104
- source = 'analysis'
120
+ source = "sumo"
121
+ elif self.model in ("hycom", "mfwam"):
122
+ if self.origin == "ana":
123
+ source = "analysis"
105
124
  else:
106
- source = 'forecast'
125
+ source = "forecast"
107
126
  else:
108
- source = 'forecast'
127
+ source = "forecast"
109
128
  ninfo.update(
110
- radical='grid',
129
+ radical="grid",
111
130
  src=[self.model, source],
112
131
  )
113
132
  return ninfo
114
133
 
115
134
  def iga_pathinfo(self):
116
135
  """Standard path information for IGA inline cache."""
117
- directory = dict(
118
- fa='fic_day',
119
- grib='bdap'
120
- )
136
+ directory = dict(fa="fic_day", grib="bdap")
121
137
  return dict(
122
138
  fmt=directory[self.nativefmt],
123
139
  nativefmt=self.nativefmt,
@@ -132,7 +148,9 @@ class GridPoint(AbstractGridpoint):
132
148
  """
133
149
 
134
150
  _abstract = True
135
- _footprint = [term_deco, ]
151
+ _footprint = [
152
+ term_deco,
153
+ ]
136
154
 
137
155
 
138
156
  class TimePeriodGridPoint(AbstractGridpoint):
@@ -145,33 +163,48 @@ class TimePeriodGridPoint(AbstractGridpoint):
145
163
  _footprint = [
146
164
  timeperiod_deco,
147
165
  dict(
148
- attr = dict(
149
- begintime = dict(
150
- optional = True,
151
- default = Time(0),
166
+ attr=dict(
167
+ begintime=dict(
168
+ optional=True,
169
+ default=Time(0),
152
170
  )
153
171
  )
154
- )
172
+ ),
155
173
  ]
156
174
 
157
175
 
158
176
  # A bunch of generic footprint declaration to ease with class creation
159
177
  _NATIVEFMT_FULLPOS_FP = footprints.Footprint(
160
- info='Abstract nativefmt for fullpos files.',
161
- attr=dict(nativefmt=dict(values=['fa'],
162
- default='fa', ))
178
+ info="Abstract nativefmt for fullpos files.",
179
+ attr=dict(
180
+ nativefmt=dict(
181
+ values=["fa"],
182
+ default="fa",
183
+ )
184
+ ),
163
185
  )
164
186
  _NATIVEFMT_GENERIC_FP = footprints.Footprint(
165
- info='Abstract nativefmt for any other gridpoint files.',
166
- attr=dict(nativefmt=dict(values=['grib', 'grib1', 'grib2', 'netcdf'],
167
- default='grib'))
187
+ info="Abstract nativefmt for any other gridpoint files.",
188
+ attr=dict(
189
+ nativefmt=dict(
190
+ values=["grib", "grib1", "grib2", "netcdf"], default="grib"
191
+ )
192
+ ),
168
193
  )
169
194
  _FILTERNAME_AWARE_FPDECO = footprints.DecorativeFootprint(
170
195
  footprints.Footprint(
171
- info='Abstract filtering attribute (used when the filtername attribute is allowed).',
172
- attr=dict(filtername=dict(info="The filter used to obtain this data.",
173
- optional=False, values=[],))),
174
- decorator=[namebuilding_insert('filtername', lambda s: s.filtername), ]
196
+ info="Abstract filtering attribute (used when the filtername attribute is allowed).",
197
+ attr=dict(
198
+ filtername=dict(
199
+ info="The filter used to obtain this data.",
200
+ optional=False,
201
+ values=[],
202
+ )
203
+ ),
204
+ ),
205
+ decorator=[
206
+ namebuilding_insert("filtername", lambda s: s.filtername),
207
+ ],
175
208
  )
176
209
 
177
210
 
@@ -179,25 +212,27 @@ class GridPointMap(FlowResource):
179
212
  """Map of the gridpoint files as produced by fullpos."""
180
213
 
181
214
  _footprint = dict(
182
- info = 'Gridpoint Files Map',
183
- attr = dict(
184
- kind = dict(
185
- values = ['gridpointmap', 'gribfilemap', 'fullposmap'],
186
- remap = dict(fullposmap = 'gridpointmap', )
215
+ info="Gridpoint Files Map",
216
+ attr=dict(
217
+ kind=dict(
218
+ values=["gridpointmap", "gribfilemap", "fullposmap"],
219
+ remap=dict(
220
+ fullposmap="gridpointmap",
221
+ ),
187
222
  ),
188
- clscontents = dict(
189
- default = JsonDictContent,
223
+ clscontents=dict(
224
+ default=JsonDictContent,
190
225
  ),
191
- nativefmt = dict(
192
- values = ['json'],
193
- default = 'json',
226
+ nativefmt=dict(
227
+ values=["json"],
228
+ default="json",
194
229
  ),
195
- )
230
+ ),
196
231
  )
197
232
 
198
233
  @property
199
234
  def realkind(self):
200
- return 'gridpointmap'
235
+ return "gridpointmap"
201
236
 
202
237
 
203
238
  class GridPointFullPos(GridPoint):
@@ -205,7 +240,7 @@ class GridPointFullPos(GridPoint):
205
240
 
206
241
  _footprint = [
207
242
  _NATIVEFMT_FULLPOS_FP,
208
- dict(info='GridPoint file produced by Fullpos (with a single term)'),
243
+ dict(info="GridPoint file produced by Fullpos (with a single term)"),
209
244
  ]
210
245
 
211
246
  def olive_basename(self):
@@ -213,46 +248,60 @@ class GridPointFullPos(GridPoint):
213
248
 
214
249
  t = self.term.hour
215
250
  e = env.current()
216
- if 'VORTEX_ANA_TERMSHIFT' not in e and self.origin == 'ana':
251
+ if "VORTEX_ANA_TERMSHIFT" not in e and self.origin == "ana":
217
252
  t = 0
218
253
 
219
254
  name = None
220
- if self.model == 'mocage':
221
- if self.origin == 'hst':
222
- name = 'HM' + self.geometry.area + '+' + self.term.fmthour
223
- elif self.origin == 'sumo':
224
- deltastr = 'PT{!s}H'.format(self.term.hour)
255
+ if self.model == "mocage":
256
+ if self.origin == "hst":
257
+ name = "HM" + self.geometry.area + "+" + self.term.fmthour
258
+ elif self.origin == "sumo":
259
+ deltastr = "PT{!s}H".format(self.term.hour)
225
260
  deltadate = self.date + deltastr
226
- name = 'SM' + self.geometry.area + '_void' + '+' + deltadate.ymd
227
- elif self.origin == 'interp':
228
- deltastr = 'PT{!s}H'.format(self.term.hour)
261
+ name = (
262
+ "SM" + self.geometry.area + "_void" + "+" + deltadate.ymd
263
+ )
264
+ elif self.origin == "interp":
265
+ deltastr = "PT{!s}H".format(self.term.hour)
229
266
  deltadate = self.date + deltastr
230
- name = 'SM' + self.geometry.area + '_interp' + '+' + deltadate.ymd
267
+ name = (
268
+ "SM" + self.geometry.area + "_interp" + "+" + deltadate.ymd
269
+ )
231
270
  else:
232
- name = 'PFFPOS' + self.origin.upper() + self.geometry.area + '+' + self.term.nice(t)
271
+ name = (
272
+ "PFFPOS"
273
+ + self.origin.upper()
274
+ + self.geometry.area
275
+ + "+"
276
+ + self.term.nice(t)
277
+ )
233
278
 
234
279
  if name is None:
235
- raise ValueError('Could not build a proper olive name: {!s}'.format(self))
280
+ raise ValueError(
281
+ "Could not build a proper olive name: {!s}".format(self)
282
+ )
236
283
 
237
284
  return name
238
285
 
239
286
  def archive_basename(self):
240
287
  """OP ARCHIVE specific naming convention."""
241
288
 
242
- deltastr = 'PT{!s}H'.format(self.term.hour)
289
+ deltastr = "PT{!s}H".format(self.term.hour)
243
290
  deltadate = self.date + deltastr
244
291
 
245
292
  name = None
246
- if self.origin == 'hst':
247
- if self.model == 'ifs':
248
- name = 'PFFPOS' + self.geometry.area + '+' + self.term.fmthour
293
+ if self.origin == "hst":
294
+ if self.model == "ifs":
295
+ name = "PFFPOS" + self.geometry.area + "+" + self.term.fmthour
249
296
  else:
250
- name = 'HM' + self.geometry.area + '+' + deltadate.ymdh
251
- elif self.origin == 'interp':
252
- name = 'SM' + self.geometry.area + '+' + deltadate.ymd
297
+ name = "HM" + self.geometry.area + "+" + deltadate.ymdh
298
+ elif self.origin == "interp":
299
+ name = "SM" + self.geometry.area + "+" + deltadate.ymd
253
300
 
254
301
  if name is None:
255
- raise ValueError('Could not build a proper archive name: {!s}'.format(self))
302
+ raise ValueError(
303
+ "Could not build a proper archive name: {!s}".format(self)
304
+ )
256
305
 
257
306
  return name
258
307
 
@@ -262,7 +311,7 @@ class GridPointExport(GridPoint):
262
311
 
263
312
  _footprint = [
264
313
  _NATIVEFMT_GENERIC_FP,
265
- dict(info='Generic gridpoint file (with a single term)'),
314
+ dict(info="Generic gridpoint file (with a single term)"),
266
315
  ]
267
316
 
268
317
  def olive_basename(self):
@@ -270,39 +319,62 @@ class GridPointExport(GridPoint):
270
319
 
271
320
  t = self.term.hour
272
321
  e = env.current()
273
- if 'VORTEX_ANA_TERMSHIFT' not in e and self.origin == 'ana':
322
+ if "VORTEX_ANA_TERMSHIFT" not in e and self.origin == "ana":
274
323
  t = 0
275
- return 'GRID' + self.origin.upper() + self.geometry.area + '+' + self.term.nice(t)
324
+ return (
325
+ "GRID"
326
+ + self.origin.upper()
327
+ + self.geometry.area
328
+ + "+"
329
+ + self.term.nice(t)
330
+ )
276
331
 
277
332
  def archive_basename(self):
278
333
  """OP ARCHIVE specific naming convention."""
279
334
 
280
335
  name = None
281
- if re.match('aladin|arome', self.model):
282
- name = 'GRID' + self.geometry.area + 'r{!s}'.format(self.date.hour) + '_' + self.term.fmthour
283
- elif re.match('arp|hycom|surcotes', self.model):
284
- name = '(gribfix:igakey)'
285
- elif self.model == 'ifs':
286
- deltastr = 'PT{!s}H'.format(self.term.hour)
336
+ if re.match("aladin|arome", self.model):
337
+ name = (
338
+ "GRID"
339
+ + self.geometry.area
340
+ + "r{!s}".format(self.date.hour)
341
+ + "_"
342
+ + self.term.fmthour
343
+ )
344
+ elif re.match("arp|hycom|surcotes", self.model):
345
+ name = "(gribfix:igakey)"
346
+ elif self.model == "ifs":
347
+ deltastr = "PT{!s}H".format(self.term.hour)
287
348
  deltadate = self.date + deltastr
288
- name = 'MET' + deltadate.ymd + '.' + self.geometry.area + '.grb'
349
+ name = "MET" + deltadate.ymd + "." + self.geometry.area + ".grb"
289
350
 
290
351
  if name is None:
291
- raise ValueError('Could not build a proper archive name: {!s}'.format(self))
352
+ raise ValueError(
353
+ "Could not build a proper archive name: {!s}".format(self)
354
+ )
292
355
 
293
356
  return name
294
357
 
295
358
 
296
359
  class FilteredGridPointExport(GridPointExport):
297
360
  """Generic single term gridpoint file using a standard format."""
298
- _footprint = [_FILTERNAME_AWARE_FPDECO, ]
361
+
362
+ _footprint = [
363
+ _FILTERNAME_AWARE_FPDECO,
364
+ ]
299
365
 
300
366
 
301
367
  class TimePeriodGridPointExport(TimePeriodGridPoint):
302
368
  """Generic multi term gridpoint file using a standard format."""
303
- _footprint = [_NATIVEFMT_GENERIC_FP, ]
369
+
370
+ _footprint = [
371
+ _NATIVEFMT_GENERIC_FP,
372
+ ]
304
373
 
305
374
 
306
375
  class FilteredTimePeriodGridPointExport(TimePeriodGridPointExport):
307
376
  """Generic multi term gridpoint file using a standard format."""
308
- _footprint = [_FILTERNAME_AWARE_FPDECO, ]
377
+
378
+ _footprint = [
379
+ _FILTERNAME_AWARE_FPDECO,
380
+ ]