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.
Files changed (146) hide show
  1. vortex/__init__.py +135 -0
  2. vortex/algo/__init__.py +12 -0
  3. vortex/algo/components.py +2136 -0
  4. vortex/algo/mpitools.py +1648 -0
  5. vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +27 -0
  6. vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +29 -0
  7. vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +18 -0
  8. vortex/algo/serversynctools.py +170 -0
  9. vortex/config.py +115 -0
  10. vortex/data/__init__.py +13 -0
  11. vortex/data/abstractstores.py +1572 -0
  12. vortex/data/containers.py +780 -0
  13. vortex/data/contents.py +596 -0
  14. vortex/data/executables.py +284 -0
  15. vortex/data/flow.py +113 -0
  16. vortex/data/geometries.ini +2689 -0
  17. vortex/data/geometries.py +703 -0
  18. vortex/data/handlers.py +1021 -0
  19. vortex/data/outflow.py +67 -0
  20. vortex/data/providers.py +465 -0
  21. vortex/data/resources.py +201 -0
  22. vortex/data/stores.py +1271 -0
  23. vortex/gloves.py +282 -0
  24. vortex/layout/__init__.py +27 -0
  25. vortex/layout/appconf.py +109 -0
  26. vortex/layout/contexts.py +511 -0
  27. vortex/layout/dataflow.py +1069 -0
  28. vortex/layout/jobs.py +1276 -0
  29. vortex/layout/monitor.py +833 -0
  30. vortex/layout/nodes.py +1424 -0
  31. vortex/layout/subjobs.py +464 -0
  32. vortex/nwp/__init__.py +11 -0
  33. vortex/nwp/algo/__init__.py +12 -0
  34. vortex/nwp/algo/assim.py +483 -0
  35. vortex/nwp/algo/clim.py +920 -0
  36. vortex/nwp/algo/coupling.py +609 -0
  37. vortex/nwp/algo/eda.py +632 -0
  38. vortex/nwp/algo/eps.py +613 -0
  39. vortex/nwp/algo/forecasts.py +745 -0
  40. vortex/nwp/algo/fpserver.py +927 -0
  41. vortex/nwp/algo/ifsnaming.py +403 -0
  42. vortex/nwp/algo/ifsroot.py +311 -0
  43. vortex/nwp/algo/monitoring.py +202 -0
  44. vortex/nwp/algo/mpitools.py +554 -0
  45. vortex/nwp/algo/odbtools.py +974 -0
  46. vortex/nwp/algo/oopsroot.py +735 -0
  47. vortex/nwp/algo/oopstests.py +186 -0
  48. vortex/nwp/algo/request.py +579 -0
  49. vortex/nwp/algo/stdpost.py +1285 -0
  50. vortex/nwp/data/__init__.py +12 -0
  51. vortex/nwp/data/assim.py +392 -0
  52. vortex/nwp/data/boundaries.py +261 -0
  53. vortex/nwp/data/climfiles.py +539 -0
  54. vortex/nwp/data/configfiles.py +149 -0
  55. vortex/nwp/data/consts.py +929 -0
  56. vortex/nwp/data/ctpini.py +133 -0
  57. vortex/nwp/data/diagnostics.py +181 -0
  58. vortex/nwp/data/eda.py +148 -0
  59. vortex/nwp/data/eps.py +383 -0
  60. vortex/nwp/data/executables.py +1039 -0
  61. vortex/nwp/data/fields.py +96 -0
  62. vortex/nwp/data/gridfiles.py +308 -0
  63. vortex/nwp/data/logs.py +551 -0
  64. vortex/nwp/data/modelstates.py +334 -0
  65. vortex/nwp/data/monitoring.py +220 -0
  66. vortex/nwp/data/namelists.py +644 -0
  67. vortex/nwp/data/obs.py +748 -0
  68. vortex/nwp/data/oopsexec.py +72 -0
  69. vortex/nwp/data/providers.py +182 -0
  70. vortex/nwp/data/query.py +217 -0
  71. vortex/nwp/data/stores.py +147 -0
  72. vortex/nwp/data/surfex.py +338 -0
  73. vortex/nwp/syntax/__init__.py +9 -0
  74. vortex/nwp/syntax/stdattrs.py +375 -0
  75. vortex/nwp/tools/__init__.py +10 -0
  76. vortex/nwp/tools/addons.py +35 -0
  77. vortex/nwp/tools/agt.py +55 -0
  78. vortex/nwp/tools/bdap.py +48 -0
  79. vortex/nwp/tools/bdcp.py +38 -0
  80. vortex/nwp/tools/bdm.py +21 -0
  81. vortex/nwp/tools/bdmp.py +49 -0
  82. vortex/nwp/tools/conftools.py +1311 -0
  83. vortex/nwp/tools/drhook.py +62 -0
  84. vortex/nwp/tools/grib.py +268 -0
  85. vortex/nwp/tools/gribdiff.py +99 -0
  86. vortex/nwp/tools/ifstools.py +163 -0
  87. vortex/nwp/tools/igastuff.py +249 -0
  88. vortex/nwp/tools/mars.py +56 -0
  89. vortex/nwp/tools/odb.py +548 -0
  90. vortex/nwp/tools/partitioning.py +234 -0
  91. vortex/nwp/tools/satrad.py +56 -0
  92. vortex/nwp/util/__init__.py +6 -0
  93. vortex/nwp/util/async.py +184 -0
  94. vortex/nwp/util/beacon.py +40 -0
  95. vortex/nwp/util/diffpygram.py +359 -0
  96. vortex/nwp/util/ens.py +198 -0
  97. vortex/nwp/util/hooks.py +128 -0
  98. vortex/nwp/util/taskdeco.py +81 -0
  99. vortex/nwp/util/usepygram.py +591 -0
  100. vortex/nwp/util/usetnt.py +87 -0
  101. vortex/proxy.py +6 -0
  102. vortex/sessions.py +341 -0
  103. vortex/syntax/__init__.py +9 -0
  104. vortex/syntax/stdattrs.py +628 -0
  105. vortex/syntax/stddeco.py +176 -0
  106. vortex/toolbox.py +982 -0
  107. vortex/tools/__init__.py +11 -0
  108. vortex/tools/actions.py +457 -0
  109. vortex/tools/addons.py +297 -0
  110. vortex/tools/arm.py +76 -0
  111. vortex/tools/compression.py +322 -0
  112. vortex/tools/date.py +20 -0
  113. vortex/tools/ddhpack.py +10 -0
  114. vortex/tools/delayedactions.py +672 -0
  115. vortex/tools/env.py +513 -0
  116. vortex/tools/folder.py +663 -0
  117. vortex/tools/grib.py +559 -0
  118. vortex/tools/lfi.py +746 -0
  119. vortex/tools/listings.py +354 -0
  120. vortex/tools/names.py +575 -0
  121. vortex/tools/net.py +1790 -0
  122. vortex/tools/odb.py +10 -0
  123. vortex/tools/parallelism.py +336 -0
  124. vortex/tools/prestaging.py +186 -0
  125. vortex/tools/rawfiles.py +10 -0
  126. vortex/tools/schedulers.py +413 -0
  127. vortex/tools/services.py +871 -0
  128. vortex/tools/storage.py +1061 -0
  129. vortex/tools/surfex.py +61 -0
  130. vortex/tools/systems.py +3396 -0
  131. vortex/tools/targets.py +384 -0
  132. vortex/util/__init__.py +9 -0
  133. vortex/util/config.py +1071 -0
  134. vortex/util/empty.py +24 -0
  135. vortex/util/helpers.py +184 -0
  136. vortex/util/introspection.py +63 -0
  137. vortex/util/iosponge.py +76 -0
  138. vortex/util/roles.py +51 -0
  139. vortex/util/storefunctions.py +103 -0
  140. vortex/util/structs.py +26 -0
  141. vortex/util/worker.py +150 -0
  142. vortex_nwp-2.0.0b1.dist-info/LICENSE +517 -0
  143. vortex_nwp-2.0.0b1.dist-info/METADATA +50 -0
  144. vortex_nwp-2.0.0b1.dist-info/RECORD +146 -0
  145. vortex_nwp-2.0.0b1.dist-info/WHEEL +5 -0
  146. vortex_nwp-2.0.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,334 @@
1
+ """
2
+ Resources to handle any NWP model state variable.
3
+ """
4
+
5
+ import re
6
+
7
+ from bronx.fancies import loggers
8
+
9
+ from vortex.data.flow import GeoFlowResource
10
+ from vortex.syntax.stdattrs import term_deco, term
11
+ from vortex.syntax.stddeco import namebuilding_insert
12
+ from bronx.stdtypes.date import Time
13
+
14
+ from ..tools.igastuff import archive_suffix
15
+ from vortex.data.geometries import CurvlinearGeometry
16
+
17
+ #: No automatic export
18
+ __all__ = []
19
+
20
+ logger = loggers.getLogger(__name__)
21
+
22
+
23
+ @namebuilding_insert('src', lambda s: [s.filling, s.model])
24
+ class AbstractAnalysis(GeoFlowResource):
25
+ """Analysis resource.
26
+
27
+ It can be an atmospheric, surface or full analysis (full = atmospheric + surface).
28
+ """
29
+ _abstract = True
30
+ _footprint = dict(
31
+ info = 'Analysis',
32
+ attr = dict(
33
+ kind = dict(
34
+ values = ['analysis', 'analyse', 'atm_analysis']
35
+ ),
36
+ nativefmt = dict(
37
+ values = ['fa', 'grib', 'lfi', 'netcdf', 'txt', 'unknown'],
38
+ default = 'fa',
39
+ ),
40
+ filtering = dict(
41
+ info = "The filtering that was applied during the generating process.",
42
+ optional = True,
43
+ values = ['dfi'],
44
+ doc_zorder = -5,
45
+ ),
46
+ filling = dict(
47
+ info = "The content/coverage of the analysis.",
48
+ optional = True,
49
+ default = 'full',
50
+ values = ['surface', 'surf', 'atmospheric', 'atm', 'full', 'soil'],
51
+ remap = dict(
52
+ surface = 'surf',
53
+ atmospheric = 'atm',
54
+ ),
55
+ )
56
+ )
57
+ )
58
+
59
+ @property
60
+ def realkind(self):
61
+ return 'analysis'
62
+
63
+
64
+ class Analysis3D(AbstractAnalysis):
65
+ """3D Analysis resource (i.e. the resource has no term attribute).
66
+
67
+ The data is assumed to be valid for **date** (i.e. term = 0).
68
+ """
69
+
70
+ _footprint = [
71
+ term,
72
+ dict(
73
+ attr = dict(
74
+ term = dict(
75
+ values = [Time(0), ],
76
+ optional = True,
77
+ default = Time(0)
78
+ )
79
+ )
80
+ )
81
+ ]
82
+
83
+ def archive_basename(self):
84
+ """OP ARCHIVE specific naming convention."""
85
+ ananame = 'analyse'
86
+ if 'surf' in self.filling:
87
+ if re.match('aladin|arome', self.model):
88
+ ananame = 'analyse_surf'
89
+ elif self.model == 'surfex':
90
+ ananame = 'analyse'
91
+ elif self.model in ('hycom', 'mfwam'):
92
+ ananame = '(prefix:modelkey)(termfix:modelkey)(suffix:modelkey)'
93
+ else:
94
+ ananame = 'analyse_surface1'
95
+
96
+ if self.filtering is not None:
97
+ if 'aladin' in self.model:
98
+ ananame = 'ANALYSE_DFI'
99
+
100
+ if self.model == 'surfex':
101
+ ananame += '.sfx'
102
+
103
+ return ananame
104
+
105
+ def olive_basename(self):
106
+ """OLIVE specific naming convention."""
107
+ olivename_map = {'atm': 'TRAJ' + self.model[:4].upper() + '+0000',
108
+ 'surf': 'surfanalyse',
109
+ 'full': 'analyse'}
110
+ if self.model != 'arpege':
111
+ olivename_map['surf'] = 'analyse'
112
+ if self.model == 'surfex':
113
+ olivename_map = {k: x + '.sfx' for k, x in olivename_map.items()}
114
+ return olivename_map[self.filling]
115
+
116
+ def iga_pathinfo(self):
117
+ """Standard path information for IGA inline cache."""
118
+ if self.model == 'arome':
119
+ if self.filling == 'surf':
120
+ directory = 'fic_day'
121
+ else:
122
+ directory = 'workdir/analyse'
123
+ elif self.model == 'arpege':
124
+ if self.filling == 'surf':
125
+ directory = 'workdir/analyse'
126
+ else:
127
+ directory = 'autres'
128
+ elif self.model in ('hycom', 'mfwam'):
129
+ if self.filling == 'surf':
130
+ directory = 'guess'
131
+ elif self.model == 'surfex':
132
+ directory = 'fic_day'
133
+ else:
134
+ if self.filling == 'surf':
135
+ directory = 'autres'
136
+ else:
137
+ directory = 'workdir/analyse'
138
+ return dict(
139
+ fmt=directory,
140
+ model=self.model,
141
+ nativefmt=self.nativefmt,
142
+ )
143
+
144
+
145
+ class Analysis4D(AbstractAnalysis):
146
+ """4D Analysis resource (i.e. the resource has a term attribute)."""
147
+
148
+ _footprint = [
149
+ term_deco,
150
+ dict(
151
+ attr = dict(
152
+ term = dict(
153
+ outcast = [Time(0), ]
154
+ )
155
+ )
156
+ )
157
+ ]
158
+
159
+
160
+ class InitialCondition(AbstractAnalysis):
161
+ """
162
+ Class for initial condition resources : anything from which a model run can be performed.
163
+ """
164
+ _footprint = dict(
165
+ info = 'Initial condition',
166
+ attr = dict(
167
+ kind = dict(
168
+ values = ['initial_condition', 'ic', 'starting_point'],
169
+ remap = dict(autoremap = 'first'),
170
+ ),
171
+ )
172
+ )
173
+
174
+ @property
175
+ def term(self):
176
+ """Fake term for duck typing."""
177
+ return Time(0)
178
+
179
+ @property
180
+ def realkind(self):
181
+ return 'ic'
182
+
183
+ def olive_basename(self):
184
+ """OLIVE specific naming convention."""
185
+ logger.warning("The member number is only known by the provider, so the generic historic name is returned.")
186
+ return 'ICMSH' + self.model[:4].upper() + '+' + self.term.fmthour
187
+
188
+ def archive_basename(self):
189
+ """OP ARCHIVE specific naming convention."""
190
+ return 'ICFC_(memberfix:member)'
191
+
192
+
193
+ class Historic(GeoFlowResource):
194
+ """
195
+ Class for historical state of a model (e.g. from a forecast).
196
+ """
197
+ _footprint = [
198
+ term_deco,
199
+ dict(
200
+ info = 'Historic forecast file',
201
+ attr = dict(
202
+ kind = dict(
203
+ values = ['historic', 'modelstate'],
204
+ remap = dict(
205
+ modelstate = 'historic'
206
+ )
207
+ ),
208
+ subset = dict(
209
+ # Dummy argument but avoid priority related messages with footprints
210
+ info = 'With Historical files, leave subset empty...',
211
+ optional = True,
212
+ values = [None, ],
213
+ ),
214
+ nativefmt = dict(
215
+ values = ['fa', 'grib', 'lfi', 'netcdf', 'unknown', 'nc'],
216
+ remap = dict(nc='netcdf'),
217
+ default = 'fa',
218
+ ),
219
+ )
220
+ )
221
+ ]
222
+
223
+ @property
224
+ def realkind(self):
225
+ return 'historic'
226
+
227
+ def archive_basename(self):
228
+ """OP ARCHIVE specific naming convention."""
229
+ if self.model in ('mfwam', 'hycom'):
230
+ prefix = '(prefix:modelkey)'
231
+ midfix = ''
232
+ else:
233
+ prefix = '(icmshfix:modelkey)'
234
+ midfix = '(histfix:igakey)'
235
+ termfix = '(termfix:modelkey)'
236
+ suffix = '(suffix:modelkey)'
237
+
238
+ if self.geometry.lam and re.match('testms1|testmp1|testmp2', self.geometry.area):
239
+ suffix = '.r' + archive_suffix(self.model, self.cutoff, self.date)
240
+
241
+ if self.model == 'mocage':
242
+ prefix = 'HM'
243
+ midfix = self.geometry.area
244
+ if self.nativefmt == 'netcdf':
245
+ suffix = '.nc'
246
+
247
+ return prefix + midfix + termfix + suffix
248
+
249
+ def olive_basename(self):
250
+ """OLIVE specific naming convention."""
251
+ if self.model == 'mesonh':
252
+ return '.'.join(
253
+ (self.model.upper(), self.geometry.area[:4].upper() + '+' + self.term.fmthour, self.nativefmt)
254
+ )
255
+ else:
256
+ return 'ICMSH' + self.model[:4].upper() + '+' + self.term.fmthour
257
+
258
+ def _geo2basename_info(self, add_stretching=True):
259
+ """Return an array describing the geometry for the Vortex's name builder."""
260
+ if isinstance(self.geometry, CurvlinearGeometry) and self.model == 'hycom':
261
+ # return the old naming convention for surges restart files
262
+ lgeo = [self.geometry.area, self.geometry.rnice]
263
+ return lgeo
264
+ else:
265
+ return super()._geo2basename_info(add_stretching=add_stretching)
266
+
267
+
268
+ @namebuilding_insert('filtername', lambda s: s.subset)
269
+ class HistoricSubset(GeoFlowResource):
270
+ """
271
+ Class for a subset of the historical state of a model (e.g. from a forecast).
272
+ """
273
+ _footprint = [
274
+ term_deco,
275
+ dict(
276
+ info = 'Subset of an historic forecast file',
277
+ attr = dict(
278
+ kind = dict(
279
+ values = ['historic', 'modelstate'],
280
+ remap = dict(
281
+ modelstate = 'historic'
282
+ )
283
+ ),
284
+ subset = dict(
285
+ info = "The subset of fields contained in this data.",
286
+ ),
287
+ nativefmt = dict(
288
+ values = ['fa', 'grib', 'lfi', 'netcdf', 'unknown', 'nc'],
289
+ remap = dict(nc='netcdf'),
290
+ default = 'fa',
291
+ ),
292
+ )
293
+ )
294
+ ]
295
+
296
+ @property
297
+ def realkind(self):
298
+ return 'historic'
299
+
300
+
301
+ class BiasDFI(GeoFlowResource):
302
+ """
303
+ Class for some kind of DFI bias (please add proper documentation).
304
+ """
305
+ _footprint = [
306
+ term_deco,
307
+ dict(
308
+ info = 'DFI bias file',
309
+ attr = dict(
310
+ kind = dict(
311
+ values = ['biasdfi', 'dfibias'],
312
+ remap = dict(
313
+ dfibias = 'biasdfi'
314
+ )
315
+ ),
316
+ nativefmt = dict(
317
+ values = ['fa'],
318
+ default = 'fa',
319
+ ),
320
+ )
321
+ )
322
+ ]
323
+
324
+ @property
325
+ def realkind(self):
326
+ return 'biasdfi'
327
+
328
+ def archive_basename(self):
329
+ """OP ARCHIVE specific naming convention."""
330
+ return 'BIASDFI+{:04d}'.format(self.term.hour)
331
+
332
+ def olive_basename(self):
333
+ """OLIVE specific naming convention."""
334
+ return 'BIASDFI{:s}+{:04d}'.format(self.model[:4].upper(), self.term.hour)
@@ -0,0 +1,220 @@
1
+ """
2
+ Various Resources to handle data produce by the obserations monitoring.
3
+ """
4
+
5
+ from bronx.fancies import loggers
6
+
7
+ from vortex.data.flow import FlowResource
8
+ from vortex.syntax.stddeco import namebuilding_append, namebuilding_insert
9
+ from .consts import GenvModelResource
10
+
11
+ #: Automatic export of Observations class
12
+ __all__ = []
13
+
14
+ logger = loggers.getLogger(__name__)
15
+
16
+
17
+ @namebuilding_insert('src', lambda s: [s.stage, s.obs])
18
+ class Monitoring(FlowResource):
19
+ """Abstract monitoring resource."""
20
+
21
+ _abstract = True
22
+ _footprint = dict(
23
+ info = 'Observations monitoring file',
24
+ attr = dict(
25
+ kind = dict(
26
+ values = ['monitoring', ],
27
+ ),
28
+ nativefmt = dict(
29
+ values =['ascii', 'binary', 'txt', 'bin'],
30
+ remap = dict(ascii='txt', binary='bin')
31
+ ),
32
+ stage = dict(
33
+ values = ['can', 'surf', 'surface', 'atm', 'atmospheric'],
34
+ remap = dict(can='surf', surface='surf', atmospheric='atm'),
35
+ info = 'The processing stage of the ODB base.',
36
+ ),
37
+ obs = dict(
38
+ values = ['all', 'used'],
39
+ info = 'The processing part of the ODB base.',
40
+ ),
41
+ )
42
+ )
43
+
44
+ @property
45
+ def realkind(self):
46
+ return 'monitoring'
47
+
48
+
49
+ class MntObsThreshold(GenvModelResource):
50
+ """Observations threshold file.
51
+
52
+ A GenvKey can be given.
53
+ """
54
+
55
+ _footprint = dict(
56
+ info='Observations threshold',
57
+ attr=dict(
58
+ kind=dict(
59
+ values=['obs_threshold']
60
+ ),
61
+ gvar=dict(
62
+ default='monitoring_seuils_obs'
63
+ ),
64
+ source=dict(
65
+ ),
66
+ )
67
+ )
68
+
69
+ @property
70
+ def realkind(self):
71
+ return 'obs_threshold'
72
+
73
+ def gget_urlquery(self):
74
+ """GGET specific query : ``extract``."""
75
+ return 'extract=' + self.source
76
+
77
+
78
+ @namebuilding_insert('period', lambda s: s.periodicity)
79
+ class MntCumulStat(Monitoring):
80
+ """Accumulated statistics file."""
81
+
82
+ _footprint = dict(
83
+ info='Monthly accumulated statistics',
84
+ attr=dict(
85
+ kind=dict(
86
+ values=['accumulated_stats']
87
+ ),
88
+ nativefmt=dict(
89
+ values=['binary', 'bin'],
90
+ default='bin',
91
+ optional = True
92
+ ),
93
+ periodicity = dict(
94
+ values = ['monthly',
95
+ 'weekly_on_mondays',
96
+ 'weekly_on_sundays'],
97
+ default = 'monthly',
98
+ optional =True
99
+ )
100
+ )
101
+ )
102
+
103
+ @property
104
+ def realkind(self):
105
+ return 'accumulated_stats'
106
+
107
+
108
+ @namebuilding_append('src', lambda s: s.monitor)
109
+ class MntStat(Monitoring):
110
+ """Monitoring statistics file."""
111
+
112
+ _footprint = dict(
113
+ info='Monitoring statistics',
114
+ attr=dict(
115
+ kind=dict(
116
+ values=['monitoring_stats']
117
+ ),
118
+ nativefmt=dict(
119
+ values=['ascii', 'txt'],
120
+ default='txt',
121
+ optional=True
122
+ ),
123
+ monitor=dict(
124
+ values=['bias', 'analysis'],
125
+ remap=dict(cy='analysis', deb='bias'),
126
+ )
127
+ )
128
+ )
129
+
130
+ @property
131
+ def realkind(self):
132
+ return 'monitoring_stats'
133
+
134
+
135
+ class MntGrossErrors(Monitoring):
136
+ """Gross errors file."""
137
+
138
+ _footprint = dict(
139
+ info='Gross errors',
140
+ attr=dict(
141
+ kind=dict(
142
+ values=['gross_errors']
143
+ ),
144
+ nativefmt = dict(
145
+ values=['ascii', 'txt'],
146
+ default='txt',
147
+ optional=True
148
+ ),
149
+ )
150
+ )
151
+
152
+ @property
153
+ def realkind(self):
154
+ return 'gross_errors'
155
+
156
+
157
+ class MntNbMessages(Monitoring):
158
+ """Number of messages for each observations type"""
159
+
160
+ _footprint = dict(
161
+ info='Obs messages',
162
+ attr=dict(
163
+ kind=dict(
164
+ values=['nbmessages']
165
+ ),
166
+ nativefmt = dict(
167
+ values=['ascii', 'txt'],
168
+ default='txt',
169
+ optional=True
170
+ ),
171
+ )
172
+ )
173
+
174
+ @property
175
+ def realkind(self):
176
+ return 'nbmessages'
177
+
178
+
179
+ class MntMissingObs(Monitoring):
180
+ """Missing observations."""
181
+
182
+ _footprint = dict(
183
+ info='Missing observations',
184
+ attr=dict(
185
+ kind=dict(
186
+ values=['missing_obs']
187
+ ),
188
+ nativefmt = dict(
189
+ values=['ascii', 'txt'],
190
+ default='txt',
191
+ optional=True
192
+ ),
193
+ )
194
+ )
195
+
196
+ @property
197
+ def realkind(self):
198
+ return 'missing_obs'
199
+
200
+
201
+ class MntObsLocation(Monitoring):
202
+ """Observations location."""
203
+
204
+ _footprint = dict(
205
+ info='Observations location',
206
+ attr=dict(
207
+ kind=dict(
208
+ values=['obslocation']
209
+ ),
210
+ nativefmt = dict(
211
+ values=['obslocationpack'],
212
+ default='obslocationpack',
213
+ optional=True
214
+ ),
215
+ )
216
+ )
217
+
218
+ @property
219
+ def realkind(self):
220
+ return 'obslocation'