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/eps.py CHANGED
@@ -22,7 +22,10 @@ __all__ = []
22
22
  logger = loggers.getLogger(__name__)
23
23
 
24
24
 
25
- @namebuilding_insert('radical', lambda s: {'unit': 'u', 'normed': 'n'}.get(s.processing, '') + s.realkind)
25
+ @namebuilding_insert(
26
+ "radical",
27
+ lambda s: {"unit": "u", "normed": "n"}.get(s.processing, "") + s.realkind,
28
+ )
26
29
  class PerturbedState(Historic):
27
30
  """
28
31
  Class for numbered historic resources, for example perturbations or perturbed states of the EPS.
@@ -31,77 +34,95 @@ class PerturbedState(Historic):
31
34
  _footprint = [
32
35
  number_deco,
33
36
  dict(
34
- info = 'Perturbation or perturbed state',
35
- attr = dict(
36
- kind = dict(
37
- values = ['perturbation', 'perturbed_historic', 'perturbed_state', 'pert'],
38
- remap = dict(autoremap = 'first')
37
+ info="Perturbation or perturbed state",
38
+ attr=dict(
39
+ kind=dict(
40
+ values=[
41
+ "perturbation",
42
+ "perturbed_historic",
43
+ "perturbed_state",
44
+ "pert",
45
+ ],
46
+ remap=dict(autoremap="first"),
39
47
  ),
40
- term = dict(
41
- optional = True,
42
- default = Time(0)
48
+ term=dict(optional=True, default=Time(0)),
49
+ processing=dict(
50
+ values=["unit", "normed"],
51
+ optional=True,
43
52
  ),
44
- processing = dict(
45
- values = ['unit', 'normed'],
46
- optional = True,
47
- ),
48
- )
49
- )
53
+ ),
54
+ ),
50
55
  ]
51
56
 
52
57
  @property
53
58
  def realkind(self):
54
- return 'pert'
59
+ return "pert"
55
60
 
56
61
  def olive_basename(self):
57
62
  """OLIVE specific naming convention."""
58
- raise NotImplementedError("Perturbations were previously tar files, not supported yet.")
63
+ raise NotImplementedError(
64
+ "Perturbations were previously tar files, not supported yet."
65
+ )
59
66
 
60
67
  def archive_basename(self):
61
68
  """OP ARCHIVE specific naming convention."""
62
- raise NotImplementedError("Perturbations were previously tar files, not supported yet.")
69
+ raise NotImplementedError(
70
+ "Perturbations were previously tar files, not supported yet."
71
+ )
63
72
 
64
73
 
65
- @namebuilding_insert('radical', lambda s: s.realkind + '-' + s.zone)
74
+ @namebuilding_insert("radical", lambda s: s.realkind + "-" + s.zone)
66
75
  class SingularVector(Historic):
67
76
  """
68
77
  Generic class for resources internal to singular vectors.
69
78
  """
79
+
70
80
  _footprint = [
71
81
  number_deco,
72
82
  dict(
73
- info = 'Singular vector',
74
- attr = dict(
75
- kind = dict(
76
- values = ['svector'],
83
+ info="Singular vector",
84
+ attr=dict(
85
+ kind=dict(
86
+ values=["svector"],
77
87
  ),
78
- zone = dict(
79
- values = ['ateur', 'hnc', 'hs', 'pno', 'oise', 'an', 'pne',
80
- 'oiso', 'ps', 'oin', 'trop1', 'trop2', 'trop3', 'trop4'],
88
+ zone=dict(
89
+ values=[
90
+ "ateur",
91
+ "hnc",
92
+ "hs",
93
+ "pno",
94
+ "oise",
95
+ "an",
96
+ "pne",
97
+ "oiso",
98
+ "ps",
99
+ "oin",
100
+ "trop1",
101
+ "trop2",
102
+ "trop3",
103
+ "trop4",
104
+ ],
81
105
  ),
82
- term = dict(
83
- optional = True,
84
- default = Time(0)
106
+ term=dict(optional=True, default=Time(0)),
107
+ optime=dict(
108
+ type=Time,
109
+ optional=True,
85
110
  ),
86
- optime = dict(
87
- type = Time,
88
- optional = True,
89
- )
90
- )
91
- )
111
+ ),
112
+ ),
92
113
  ]
93
114
 
94
115
  @property
95
116
  def realkind(self):
96
- return 'svector'
117
+ return "svector"
97
118
 
98
119
  def olive_basename(self):
99
120
  """OLIVE specific naming convention."""
100
- return 'SVARPE' + '{:03d}'.format(self.number) + '+0000'
121
+ return "SVARPE" + "{:03d}".format(self.number) + "+0000"
101
122
 
102
123
  def archive_basename(self):
103
124
  """OP ARCHIVE specific naming convention."""
104
- return 'SVARPE' + '{:03d}'.format(self.number) + '+0000'
125
+ return "SVARPE" + "{:03d}".format(self.number) + "+0000"
105
126
 
106
127
 
107
128
  @use_flow_logs_stack
@@ -111,30 +132,30 @@ class NormCoeff(FlowResource):
111
132
  """
112
133
 
113
134
  _footprint = dict(
114
- info = 'Perturbations coefficient',
115
- attr = dict(
116
- kind = dict(
117
- values = ['coeffnorm', 'coeffpert'],
118
- remap = dict(autoremap = 'first'),
135
+ info="Perturbations coefficient",
136
+ attr=dict(
137
+ kind=dict(
138
+ values=["coeffnorm", "coeffpert"],
139
+ remap=dict(autoremap="first"),
119
140
  ),
120
- clscontents = dict(
121
- default = JsonDictContent,
141
+ clscontents=dict(
142
+ default=JsonDictContent,
122
143
  ),
123
- nativefmt = dict(
124
- values = ['json'],
125
- default = 'json',
144
+ nativefmt=dict(
145
+ values=["json"],
146
+ default="json",
126
147
  ),
127
- pertkind = dict(
128
- values = ['sv', 'bd'],
129
- optional = True,
130
- default = 'sv',
148
+ pertkind=dict(
149
+ values=["sv", "bd"],
150
+ optional=True,
151
+ default="sv",
131
152
  ),
132
- )
153
+ ),
133
154
  )
134
155
 
135
156
  @property
136
157
  def realkind(self):
137
- return 'coeff' + self.pertkind
158
+ return "coeff" + self.pertkind
138
159
 
139
160
 
140
161
  class SampleContent(JsonDictContent):
@@ -142,8 +163,16 @@ class SampleContent(JsonDictContent):
142
163
 
143
164
  def drawing(self, g, x):
144
165
  """Return the number of a sampled element according to the local number."""
145
- n = g.get('number', x.get('number', None))
146
- virgin = g.get('untouched', x.get('untouched', [0, ]))
166
+ n = g.get("number", x.get("number", None))
167
+ virgin = g.get(
168
+ "untouched",
169
+ x.get(
170
+ "untouched",
171
+ [
172
+ 0,
173
+ ],
174
+ ),
175
+ )
147
176
  if n is None:
148
177
  return None
149
178
  else:
@@ -159,17 +188,21 @@ class SampleContent(JsonDictContent):
159
188
  return n
160
189
  else:
161
190
  try:
162
- return self.data['drawing'][n - 1]
191
+ return self.data["drawing"][n - 1]
163
192
  except KeyError:
164
193
  return None
165
194
 
166
195
  @secure_getattr
167
196
  def __getattr__(self, attr):
168
197
  # Return an access function that corresponds to the key in "drawing"
169
- drawing_keys = {item
170
- for d in self.data.get('drawing', []) if isinstance(d, dict)
171
- for item in d.keys()}
198
+ drawing_keys = {
199
+ item
200
+ for d in self.data.get("drawing", [])
201
+ if isinstance(d, dict)
202
+ for item in d.keys()
203
+ }
172
204
  if attr in drawing_keys:
205
+
173
206
  def _attr_access(g, x):
174
207
  elt = self.drawing(g, x)
175
208
  # drawing may returns
@@ -177,52 +210,68 @@ class SampleContent(JsonDictContent):
177
210
  # * An integer if 'number' is in the 'untouched' list
178
211
  # * A dictionary
179
212
  if elt is None:
180
- choices = {d[attr] for d in self.data['drawing']}
213
+ choices = {d[attr] for d in self.data["drawing"]}
181
214
  return None if len(choices) > 1 else choices.pop()
182
215
  else:
183
216
  return elt[attr] if isinstance(elt, dict) else None
217
+
184
218
  return _attr_access
185
219
  # Return an access function that corresponds to the key in "population"
186
- population_keys = {item
187
- for d in self.data.get('population', []) if isinstance(d, dict)
188
- for item in d.keys()}
220
+ population_keys = {
221
+ item
222
+ for d in self.data.get("population", [])
223
+ if isinstance(d, dict)
224
+ for item in d.keys()
225
+ }
189
226
  if attr in population_keys:
227
+
190
228
  def _attr_access(g, x):
191
- n = g.get('number', x.get('number', None))
229
+ n = g.get("number", x.get("number", None))
192
230
  if n is None:
193
231
  return None
194
232
  else:
195
- return self.data['population'][n - 1][attr]
233
+ return self.data["population"][n - 1][attr]
234
+
196
235
  return _attr_access
197
236
  # Returns the list of drawn keys
198
- listing_keys = {item + 's'
199
- for d in self.data.get('drawing', []) if isinstance(d, dict)
200
- for item in d.keys()}
237
+ listing_keys = {
238
+ item + "s"
239
+ for d in self.data.get("drawing", [])
240
+ if isinstance(d, dict)
241
+ for item in d.keys()
242
+ }
201
243
  if attr in listing_keys:
202
- return [d[attr[:-1]] for d in self.data['drawing']]
244
+ return [d[attr[:-1]] for d in self.data["drawing"]]
203
245
  # Return the list of available keys
204
- listing_keys = {item + 's'
205
- for d in self.data['population'] if isinstance(d, dict)
206
- for item in d.keys()}
246
+ listing_keys = {
247
+ item + "s"
248
+ for d in self.data["population"]
249
+ if isinstance(d, dict)
250
+ for item in d.keys()
251
+ }
207
252
  if attr in listing_keys:
208
- return [d[attr[:-1]] for d in self.data['population']]
253
+ return [d[attr[:-1]] for d in self.data["population"]]
209
254
  raise AttributeError()
210
255
 
211
256
  def targetdate(self, g, x):
212
- targetdate = g.get('targetdate', x.get('targetdate', None))
257
+ targetdate = g.get("targetdate", x.get("targetdate", None))
213
258
  if targetdate is None:
214
- raise ValueError("A targetdate attribute must be present if targetdate is used")
259
+ raise ValueError(
260
+ "A targetdate attribute must be present if targetdate is used"
261
+ )
215
262
  return Date(targetdate)
216
263
 
217
264
  def targetterm(self, g, x):
218
- targetterm = g.get('targetterm', x.get('targetterm', None))
265
+ targetterm = g.get("targetterm", x.get("targetterm", None))
219
266
  if targetterm is None:
220
- raise ValueError("A targetterm attribute must be present if targetterm is used")
267
+ raise ValueError(
268
+ "A targetterm attribute must be present if targetterm is used"
269
+ )
221
270
  return Time(targetterm)
222
271
 
223
272
  def timedelta(self, g, x):
224
273
  """Find the time difference between the resource's date and the targetdate."""
225
- targetterm = Time(g.get('targetterm', x.get('targetterm', 0)))
274
+ targetterm = Time(g.get("targetterm", x.get("targetterm", 0)))
226
275
  thedate = Date(self.date(g, x))
227
276
  period = (self.targetdate(g, x) + targetterm) - thedate
228
277
  return period.time()
@@ -230,13 +279,15 @@ class SampleContent(JsonDictContent):
230
279
  def _actual_diff(self, ref):
231
280
  me = copy.copy(self.data)
232
281
  other = copy.copy(ref.data)
233
- me.pop('experiment', None) # Do not compare the experiment ID (if present)
234
- other.pop('experiment', None)
282
+ me.pop(
283
+ "experiment", None
284
+ ) # Do not compare the experiment ID (if present)
285
+ other.pop("experiment", None)
235
286
  return me == other
236
287
 
237
288
 
238
289
  @use_flow_logs_stack
239
- @namebuilding_delete('src')
290
+ @namebuilding_delete("src")
240
291
  class PopulationList(FlowResource):
241
292
  """
242
293
  Description of available data
@@ -244,60 +295,58 @@ class PopulationList(FlowResource):
244
295
 
245
296
  _abstract = True
246
297
  _footprint = dict(
247
- info = 'A Population List',
248
- attr = dict(
249
- clscontents = dict(
250
- default = SampleContent,
298
+ info="A Population List",
299
+ attr=dict(
300
+ clscontents=dict(
301
+ default=SampleContent,
251
302
  ),
252
- nativefmt = dict(
253
- values = ['json'],
254
- default = 'json',
303
+ nativefmt=dict(
304
+ values=["json"],
305
+ default="json",
255
306
  ),
256
- nbsample = dict(
257
- optional = True,
258
- type = int,
307
+ nbsample=dict(
308
+ optional=True,
309
+ type=int,
259
310
  ),
260
- checkrole = dict(
261
- optional = True
262
- )
263
- )
311
+ checkrole=dict(optional=True),
312
+ ),
264
313
  )
265
314
 
266
315
 
267
316
  class MembersPopulation(PopulationList):
268
-
269
317
  _footprint = dict(
270
- info = 'Members population',
271
- attr = dict(
272
- kind = dict(
273
- values = ['mbpopulation', ],
318
+ info="Members population",
319
+ attr=dict(
320
+ kind=dict(
321
+ values=[
322
+ "mbpopulation",
323
+ ],
274
324
  ),
275
- )
325
+ ),
276
326
  )
277
327
 
278
328
  @property
279
329
  def realkind(self):
280
- return 'mbpopulation'
330
+ return "mbpopulation"
281
331
 
282
332
 
283
- @namebuilding_insert('radical', lambda s: '{:s}of{:d}'.format(s.realkind, s.nbsample))
333
+ @namebuilding_insert(
334
+ "radical", lambda s: "{:s}of{:d}".format(s.realkind, s.nbsample)
335
+ )
284
336
  class Sample(PopulationList):
285
337
  """
286
338
  Lot drawn out of a set.
287
339
  """
288
340
 
289
- _abstract = True,
341
+ _abstract = (True,)
290
342
  _footprint = dict(
291
- info = 'Sample',
292
- attr = dict(
293
- nbsample = dict(
294
- optional = False,
343
+ info="Sample",
344
+ attr=dict(
345
+ nbsample=dict(
346
+ optional=False,
295
347
  ),
296
- population = dict(
297
- type = footprints.stdtypes.FPList,
298
- optional = True
299
- ),
300
- )
348
+ population=dict(type=footprints.stdtypes.FPList, optional=True),
349
+ ),
301
350
  )
302
351
 
303
352
 
@@ -307,18 +356,18 @@ class MembersSample(Sample):
307
356
  """
308
357
 
309
358
  _footprint = dict(
310
- info = 'Members sample',
311
- attr = dict(
312
- kind = dict(
313
- values = ['mbsample', 'mbselect', 'mbdrawing', 'members_select'],
314
- remap = dict(autoremap = 'first'),
359
+ info="Members sample",
360
+ attr=dict(
361
+ kind=dict(
362
+ values=["mbsample", "mbselect", "mbdrawing", "members_select"],
363
+ remap=dict(autoremap="first"),
315
364
  ),
316
- )
365
+ ),
317
366
  )
318
367
 
319
368
  @property
320
369
  def realkind(self):
321
- return 'mbsample'
370
+ return "mbsample"
322
371
 
323
372
 
324
373
  class MultiphysicsSample(Sample):
@@ -327,18 +376,18 @@ class MultiphysicsSample(Sample):
327
376
  """
328
377
 
329
378
  _footprint = dict(
330
- info = 'Physical packages sample',
331
- attr = dict(
332
- kind = dict(
333
- values = ['physample', 'physelect', 'phydrawing'],
334
- remap = dict(autoremap = 'first'),
379
+ info="Physical packages sample",
380
+ attr=dict(
381
+ kind=dict(
382
+ values=["physample", "physelect", "phydrawing"],
383
+ remap=dict(autoremap="first"),
335
384
  ),
336
- )
385
+ ),
337
386
  )
338
387
 
339
388
  @property
340
389
  def realkind(self):
341
- return 'physample'
390
+ return "physample"
342
391
 
343
392
 
344
393
  class ClustContent(TextContent):
@@ -349,35 +398,35 @@ class ClustContent(TextContent):
349
398
 
350
399
 
351
400
  @use_flow_logs_stack
352
- @namebuilding_delete('src')
401
+ @namebuilding_delete("src")
353
402
  class GeneralCluster(FlowResource):
354
403
  """
355
404
  Files produced by the clustering step of the LAM PE.
356
405
  """
357
406
 
358
407
  _footprint = dict(
359
- info = 'Clustering stuff',
360
- attr = dict(
361
- kind = dict(
362
- values = ['clustering', 'clust', 'members_select'],
363
- remap = dict(autoremap = 'first'),
408
+ info="Clustering stuff",
409
+ attr=dict(
410
+ kind=dict(
411
+ values=["clustering", "clust", "members_select"],
412
+ remap=dict(autoremap="first"),
364
413
  ),
365
- clscontents = dict(
366
- default = ClustContent,
414
+ clscontents=dict(
415
+ default=ClustContent,
367
416
  ),
368
- nativefmt = dict(
369
- values = ['ascii', 'txt'],
370
- default = 'txt',
371
- remap = dict(ascii = 'txt'),
417
+ nativefmt=dict(
418
+ values=["ascii", "txt"],
419
+ default="txt",
420
+ remap=dict(ascii="txt"),
372
421
  ),
373
- filling = dict(
374
- values = ['population', 'pop', 'members', 'full'],
375
- remap = dict(population = 'pop'),
376
- default = '',
422
+ filling=dict(
423
+ values=["population", "pop", "members", "full"],
424
+ remap=dict(population="pop"),
425
+ default="",
377
426
  ),
378
- )
427
+ ),
379
428
  )
380
429
 
381
430
  @property
382
431
  def realkind(self):
383
- return 'clustering' + '_' + self.filling
432
+ return "clustering" + "_" + self.filling