ARTS 2.5.0 (git: 9ee3ac6c)
make_auto_md_h.cc
Go to the documentation of this file.
1/* Copyright (C) 2000-2012 Stefan Buehler <sbuehler@ltu.se>
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2, or (at your option) any
6 later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 USA. */
17
68#include "agenda_record.h"
69#include "array.h"
70#include "arts.h"
71#include "file.h"
72#include "global_data.h"
73#include "methods.h"
74#include "workspace_ng.h"
75
76/* Adds commas and indentation to parameter lists. */
77void align(ofstream& ofs, bool& is_first_parameter, const String& indent) {
78 // Add comma and line break, if not first element:
79 if (is_first_parameter)
80 is_first_parameter = false;
81 else {
82 ofs << ",\n";
83 // Make proper indentation:
84 ofs << indent;
85 }
86}
87
89
93void write_method_header_documentation(ofstream& ofs, const MdRecord& mdd) {
94 const Array<WsvRecord>& wsv_data = Workspace::wsv_data;
95
96 String fullname = mdd.Name();
97
98 // This is needed to flag the first function parameter, which
99 // needs no line break before being written:
100 bool is_first_parameter = true;
101
102 // The String indent is needed to achieve the correct
103 // indentation of the functin parameters:
104 String indent(" ");
105
106 // Flag to pass the workspace to the WSM. Only true if the WSM has
107 // an Agenda as input.
108 bool pass_workspace = false;
109
110 // There are four lists of parameters that we have to
111 // write.
112 ArrayOfIndex vo = mdd.Out(); // Output
113 const ArrayOfIndex& vi = mdd.InOnly(); // Input
114 ArrayOfIndex vgo = mdd.GOutType(); // Generic Output
115 ArrayOfIndex vgi = mdd.GInType(); // Generic Input
116 // vo and vi contain handles of workspace variables,
117 // vgo and vgi handles of workspace variable groups.
118
119 // Find out if the WSM gets an agenda as input. If so, pass
120 // the current workspace to this method
121 for (Index j = 0; !pass_workspace && j < mdd.In().nelem(); j++) {
122 if (is_agenda_group_id(wsv_data[mdd.In()[j]].Group())) {
123 pass_workspace = true;
124 }
125 }
126
127 // Find out if the WSM gets an agenda as input. If so, pass
128 // the current workspace to this method
129 for (Index j = 0; !pass_workspace && j < mdd.GInType().nelem(); j++) {
130 if (is_agenda_group_id(mdd.GInType()[j])) {
131 pass_workspace = true;
132 }
133 }
134
135 // Start with the name of the one line description
136 ofs << "//! WORKSPACE METHOD: " << fullname << ".\n";
137
138 ofs << "/*!\n";
139
140 String DoxyDescription = mdd.Description();
141 size_t start_pos = 0;
142
143 while (start_pos != string::npos) {
144 start_pos = DoxyDescription.find("\n ", start_pos);
145 if (start_pos && start_pos != string::npos &&
146 DoxyDescription[start_pos] - 1 != '\n') {
147 DoxyDescription.insert(start_pos + 1, "<br>");
148 start_pos += 5;
149 }
150 }
151
152 // Some characters have to be masqueraded to appear properly in doxygen
153 // documentation
154 DoxyDescription.insert_substr("<", "\\");
155 DoxyDescription.insert_substr(">", "\\");
156
157 ofs << DoxyDescription << "\n";
158
159 // Write the authors:
160 for (Index j = 0; j < mdd.Authors().nelem(); ++j) {
161 ofs << indent << "\\author " << mdd.Authors()[j] << "\n";
162 }
163
164 ofs << "\n";
165
166 if (pass_workspace || mdd.PassWorkspace() || mdd.AgendaMethod()) {
167 ofs << indent << "\\param[in,out] "
168 << "ws Workspace\n";
169 }
170
171 // Write the Output workspace variables:
172 for (Index j = 0; j < vo.nelem(); ++j) {
173 bool inout =
174 (std::find(mdd.In().begin(), mdd.In().end(), vo[j]) != mdd.In().end());
175
176 if (inout) {
177 ofs << indent << "\\param[in,out] " << wsv_data[vo[j]].Name()
178 << " WS Input/Output\n";
179 } else {
180 ofs << indent << "\\param[out] " << wsv_data[vo[j]].Name()
181 << " WS Output\n";
182 }
183 }
184
185 // Write the Generic output workspace variables:
186 for (Index j = 0; j < vgo.nelem(); ++j) {
187 ofs << indent << "\\param[out] ";
188
189 if (mdd.GOut()[j].length())
190 ofs << mdd.GOut()[j];
191 else
192 ofs << "genericoutput" << j + 1;
193
194 if (mdd.Supergeneric())
195 ofs << " Supergeneric output\n";
196 else
197 ofs << " Generic output\n";
198 }
199
200 // Write the Generic output workspace variable names:
201 if (mdd.PassWsvNames()) {
202 for (Index j = 0; j < vgo.nelem(); ++j) {
203 ofs << indent << "\\param[in] ";
204 if (mdd.GOut()[j].length())
205 ofs << mdd.GOut()[j] << "_wsvname";
206 else
207 ofs << "genericoutput" << j + 1 << "_wsvname";
208
209 ofs << " Generic Output Name" << endl;
210 }
211 }
212
213 // Write the Input workspace variables:
214 for (Index j = 0; j < vi.nelem(); ++j) {
215 ofs << indent << "\\param[in] " << wsv_data[vi[j]].Name()
216 << " WS Input\n";
217 }
218
219 // Write the Generic input workspace variables:
220 for (Index j = 0; j < vgi.nelem(); ++j) {
221 ofs << indent << "\\param[in] ";
222 if (mdd.GIn()[j] != "")
223 ofs << mdd.GIn()[j];
224 else
225 ofs << "genericinput" << j + 1;
226
227 ofs << " Generic Input";
228
229 if (mdd.GInDefault()[j] != NODEF) {
230 ofs << " (Default: \"" << mdd.GInDefault()[j] << "\")";
231 }
232 ofs << endl;
233 }
234
235 // Write the Generic input workspace variable names:
236 if (mdd.PassWsvNames()) {
237 for (Index j = 0; j < vgi.nelem(); ++j) {
238 ofs << indent << "\\param[in] ";
239 if (mdd.GIn()[j].length())
240 ofs << mdd.GIn()[j] << "_wsvname";
241 else
242 ofs << "genericinput" << j + 1 << "_wsvname";
243
244 ofs << " Generic Input Name" << endl;
245 }
246 }
247
248 // Write agenda, if there is one:
249 if (mdd.AgendaMethod()) {
250 align(ofs, is_first_parameter, indent);
251 ofs << indent << "\\param[in] "
252 << "input_agenda Agenda from controlfile\n";
253 }
254
255 ofs << "*/\n";
256}
257
259
263void write_method_header(ofstream& ofs, const MdRecord& mdd) {
265 const Array<WsvRecord>& wsv_data = Workspace::wsv_data;
266
267 // // Work out the full name to use:
268 // String fullname;
269 // {
270 // ostringstream os;
271 // os << mdd.Name() << add_to_name;
272 // fullname = os.str();
273 // }
274
275 String fullname = mdd.Name();
276
277 // This is needed to flag the first function parameter, which
278 // needs no line break before being written:
279 bool is_first_parameter = true;
280
281 // The String indent is needed to achieve the correct
282 // indentation of the functin parameters:
283 String indent(fullname.nelem() + 6, ' ');
284
285 // Flag to pass the workspace to the WSM. Only true if the WSM has
286 // an Agenda as input.
287 bool pass_workspace = false;
288
289 // There are four lists of parameters that we have to
290 // write.
291 ArrayOfIndex vo = mdd.Out(); // Output
292 const ArrayOfIndex& vi = mdd.InOnly(); // Input
293 ArrayOfIndex vgo = mdd.GOutType(); // Generic Output
294 ArrayOfIndex vgi = mdd.GInType(); // Generic Input
295 // vo and vi contain handles of workspace variables,
296 // vgo and vgi handles of workspace variable groups.
297
298 // Find out if the WSM gets an agenda as input. If so, pass
299 // the current workspace to this method
300 for (Index j = 0; !pass_workspace && j < mdd.In().nelem(); j++) {
301 if (is_agenda_group_id(wsv_data[mdd.In()[j]].Group())) {
302 pass_workspace = true;
303 }
304 }
305
306 // Find out if the WSM gets an agenda as input. If so, pass
307 // the current workspace to this method
308 for (Index j = 0; !pass_workspace && j < mdd.GInType().nelem(); j++) {
309 if (is_agenda_group_id(mdd.GInType()[j])) {
310 pass_workspace = true;
311 }
312 }
313
314 // There used to be a similar block here for the generic
315 // input/output variables. However, this was a mistake. For
316 // example, if a method has a vector as generic input and a
317 // vector as generic output, this does not mean that it is
318 // the same vector!
319
320 if (mdd.Supergeneric() && mdd.UsesTemplates()) {
321 ofs << "template <typename T>" << endl;
322 }
323
324 // Start with the name of the method:
325 ofs << "void " << fullname << "(";
326
327 if (pass_workspace || mdd.PassWorkspace() || mdd.AgendaMethod()) {
328 ofs << "// Workspace reference:\n";
329 ofs << indent << "Workspace& ws";
330 is_first_parameter = false;
331 }
332
333 // Write the Output workspace variables:
334 {
335 // Flag first parameter of this sort:
336 bool is_first_of_these = true;
337
338 for (Index j = 0; j < vo.nelem(); ++j) {
339 // Add comma and line break, if not first element:
340 align(ofs, is_first_parameter, indent);
341
342 // Add comment if this is the first of this sort
343 if (is_first_of_these) {
344 ofs << "// WS Output:\n";
345 ofs << indent;
346 is_first_of_these = false;
347 }
348
349 ofs << wsv_group_names[Workspace::wsv_data[vo[j]].Group()] << "& "
350 << Workspace::wsv_data[vo[j]].Name();
351 }
352 }
353
354 // Write the Generic output workspace variables:
355 {
356 // Flag first parameter of this sort:
357 bool is_first_of_these = true;
358
359 for (Index j = 0; j < vgo.nelem(); ++j) {
360 // Add comma and line break, if not first element:
361 align(ofs, is_first_parameter, indent);
362
363 // Add comment if this is the first of this sort
364 if (is_first_of_these) {
365 ofs << "// WS Generic Output:\n";
366 ofs << indent;
367 is_first_of_these = false;
368 }
369
370 if (wsv_group_names[mdd.GOutType()[j]] == "Any")
371 ofs << "T& ";
372 else
373 ofs << wsv_group_names[mdd.GOutType()[j]] << "& ";
374
375 if (mdd.GOut()[j].length())
376 ofs << mdd.GOut()[j];
377 else
378 ofs << "genericoutput" << j + 1;
379 }
380 }
381
382 // Write the Generic output workspace variable names:
383 if (mdd.PassWsvNames()) {
384 // Flag first parameter of this sort:
385 bool is_first_of_these = true;
386
387 for (Index j = 0; j < vgo.nelem(); ++j) {
388 // Add comma and line break, if not first element:
389 align(ofs, is_first_parameter, indent);
390
391 // Add comment if this is the first of this sort
392 if (is_first_of_these) {
393 ofs << "// WS Generic Output Names:\n";
394 ofs << indent;
395 is_first_of_these = false;
396 }
397
398 ofs << "const String& ";
399 if (mdd.GOut()[j].length())
400 ofs << mdd.GOut()[j] << "_wsvname";
401 else
402 ofs << "genericoutput" << j + 1 << "_wsvname";
403 }
404 }
405
406 // Write the Input workspace variables:
407 {
408 // Flag first parameter of this sort.
409 bool is_first_of_these = true;
410
411 for (Index j = 0; j < vi.nelem(); ++j) {
412 // Add comma and line break, if not first element:
413 align(ofs, is_first_parameter, indent);
414
415 // Add type if this is the first of this sort.
416 if (is_first_of_these) {
417 ofs << "// WS Input:\n";
418 ofs << indent;
419 is_first_of_these = false;
420 }
421
422 ofs << "const " << wsv_group_names[Workspace::wsv_data[vi[j]].Group()]
423 << "& " << Workspace::wsv_data[vi[j]].Name();
424 }
425 }
426
427 // Write the Generic input workspace variables:
428 {
429 // Flag first parameter of this sort.
430 bool is_first_of_these = true;
431
432 for (Index j = 0; j < vgi.nelem(); ++j) {
433 // Add comma and line break, if not first element:
434 align(ofs, is_first_parameter, indent);
435
436 // Add type if this is the first of this sort.
437 if (is_first_of_these) {
438 ofs << "// WS Generic Input:\n";
439 ofs << indent;
440 is_first_of_these = false;
441 }
442
443 if (wsv_group_names[mdd.GInType()[j]] == "Any") {
444 ofs << "const T& ";
445 if (mdd.GIn()[j].length())
446 ofs << mdd.GIn()[j];
447 else
448 ofs << "genericinput" << j + 1;
449 } else {
450 ofs << "const " << wsv_group_names[mdd.GInType()[j]] << "& ";
451 if (mdd.GIn()[j].length())
452 ofs << mdd.GIn()[j];
453 else
454 ofs << "genericinput" << j + 1;
455 }
456 }
457 }
458
459 // Write the Generic input workspace variable names:
460 if (mdd.PassWsvNames()) {
461 // Flag first parameter of this sort:
462 bool is_first_of_these = true;
463
464 for (Index j = 0; j < vgi.nelem(); ++j) {
465 // Add comma and line break, if not first element:
466 align(ofs, is_first_parameter, indent);
467
468 // Add comment if this is the first of this sort
469 if (is_first_of_these) {
470 ofs << "// WS Generic Input Names:\n";
471 ofs << indent;
472 is_first_of_these = false;
473 }
474
475 ofs << "const String& ";
476 if (mdd.GIn()[j].length())
477 ofs << mdd.GIn()[j] << "_wsvname";
478 else
479 ofs << "genericinput" << j + 1 << "_wsvname";
480 }
481 }
482
483 // Write agenda, if there is one:
484 if (mdd.AgendaMethod()) {
485 align(ofs, is_first_parameter, indent);
486 ofs << "// Agenda from controlfile:\n";
487 ofs << indent;
488 ofs << "const Agenda& input_agenda";
489 }
490
491 // Flag that is set to false if the WSM has verbosity as an input or
492 // output already. Otherwise it's passed as the last parameter.
493 bool pass_verbosity = true;
494
495 // Find out if the WSM has the verbosity as input.
496 for (Index j = 0; pass_verbosity && j < mdd.In().nelem(); j++) {
497 if (wsv_data[mdd.In()[j]].Name() == "verbosity") {
498 pass_verbosity = false;
499 }
500 }
501
502 // Find out if the WSM has the verbosity as output.
503 for (Index j = 0; pass_verbosity && j < mdd.Out().nelem(); j++) {
504 if (wsv_data[mdd.Out()[j]].Name() == "verbosity") {
505 pass_verbosity = false;
506 }
507 }
508
509 if (pass_verbosity) {
510 align(ofs, is_first_parameter, indent);
511 ofs << "// Verbosity object:\n";
512 ofs << indent;
513 ofs << "const Verbosity& verbosity";
514 }
515
516 ofs << ");\n\n";
517}
518
520 ostringstream os;
521
522 bool is_sane = true;
523 for (Array<MdRecord>::const_iterator i = md_data.begin(); i < md_data.end();
524 ++i) {
525 bool invalid_author = false;
526 for (ArrayOfString::const_iterator j = i->Authors().begin();
527 !invalid_author && j < i->Authors().end();
528 ++j) {
529 if (*j == "" || *j == "unknown") invalid_author = true;
530 }
531
532 if (invalid_author) {
533 os << i->Name() << ": Missing or invalid author.\n";
534 is_sane = false;
535 }
536
537 switch (check_newline(i->Description())) {
538 case 1:
539 os << i->Name() << ": Empty description.\n";
540 is_sane = false;
541 break;
542 case 2:
543 os << i->Name() << ": Missing newline at the end of description.\n";
544 is_sane = false;
545 break;
546 case 3:
547 os << i->Name() << ": Extra newline at the end of description.\n";
548 is_sane = false;
549 break;
550 }
551 }
552
553 if (!is_sane) {
554 cerr
555 << "Error(s) found in workspace method documentation (check methods.cc):\n"
556 << os.str();
557 }
558
559 return is_sane;
560}
561
562int main() {
563 try {
564 // Make the global data visible:
567
568 // Initialize the wsv group name array:
570
571 // Initialize wsv data.
573
574 // Initialize WsvMap.
576
577 // Initialize method data.
579
580 // Expand supergeneric methods:
582
583 if (!md_sanity_checks(md_data)) return 1;
584
585 const Index n_md = md_data.nelem();
586
587 // Write auto_md.h:
588 // -----------
589 ofstream ofs;
590 open_output_file(ofs, "auto_md.h");
591
592 ofs << "// This file was generated automatically by make_auto_md_h.cc.\n";
593 ofs << "// DO NOT EDIT !\n";
594 ofs << "// Generated: " << __DATE__ << ", " << __TIME__ << "\n\n";
595
596 ofs << "#ifndef auto_md_h\n";
597 ofs << "#define auto_md_h\n\n";
598
599 ofs << "#include \"matpackI.h\"\n"
600 << "#include \"matpackII.h\"\n"
601 << "#include \"species_tags.h\"\n"
602 << "#include \"artstime.h\"\n"
603 << "#include \"gas_abs_lookup.h\"\n"
604 << "#include \"gridded_fields.h\"\n"
605 << "#include \"linemixing_hitran.h\"\n"
606 << "#include \"optproperties.h\"\n"
607 << "#include \"jacobian.h\"\n"
608 << "#include \"mc_antenna.h\"\n"
609 << "#include \"m_general.h\"\n"
610 << "#include \"parser.h\"\n"
611 << "#include \"workspace_ng.h\"\n"
612 << "#include \"cia.h\"\n"
613 << "#include \"covariance_matrix.h\"\n"
614 << "#include \"propagationmatrix.h\"\n"
615 << "#include \"transmissionmatrix.h\"\n"
616 << "#include \"telsem.h\"\n"
617 << "#include \"tessem.h\"\n"
618 << "#include \"hitran_xsec.h\"\n"
619 << "#include \"absorptionlines.h\"\n"
620 << "#include \"linemixing.h\"\n"
621 << "\n";
622
623 ofs << "// This is only used for a consistency check. You can get the\n"
624 << "// number of WSMs from md_data.nelem().\n"
625 << "#define N_MD " << n_md << "\n\n";
626
627 // Add all the method function declarations
628 ofs << "// Method function declarations:\n\n";
629 for (Index i = 0; i < n_md; ++i) {
630 const MdRecord& mdd = md_data[i];
631 if (!mdd.UsesTemplates()) {
633 write_method_header(ofs, mdd);
634 }
635 }
636
637 // Add all the method function declarations
638 ofs << "// Supergeneric template function declarations:\n\n";
639 for (Index i = 0; i < md_data_raw.nelem(); ++i) {
640 const MdRecord& mdd = md_data_raw[i];
641 if (mdd.Supergeneric() && mdd.UsesTemplates()) {
643 write_method_header(ofs, mdd);
644 }
645 }
646
647 // Add all the get-away function declarations:
648 ofs << "// Get-away function declarations:\n\n";
649 for (Index i = 0; i < n_md; ++i) {
650 const MdRecord& mdd = md_data[i];
651 if (mdd.Supergeneric()) {
652 ofs << "void " << mdd.Name() << "_sg_" << mdd.ActualGroups()
653 << "_g(Workspace& ws, const MRecord& mr);\n";
654 } else {
655 ofs << "void " << mdd.Name()
656 << "_g(Workspace& ws, const MRecord& mr);\n";
657 }
658 }
659
660 ofs << "\n";
661
662 // Create prototypes for the agenda wrappers
663
664 // Initialize agenda data.
667
669 const Array<WsvRecord>& wsv_data = Workspace::wsv_data;
670 for (Index i = 0; i < agenda_data.nelem(); i++) {
671 bool is_agenda_array =
672 wsv_data[get_wsv_id(agenda_data[i].Name())].Group() ==
673 get_wsv_group_id("ArrayOfAgenda");
674 write_agenda_wrapper_header(ofs, agenda_data[i], is_agenda_array);
675
676 ofs << ";\n\n";
677 }
678
679 ofs << "\n#endif // auto_md_h\n";
680
681 // Close auto_md.h.
682 ofs.close();
683
684 } catch (const std::runtime_error& x) {
685 cout << "Something went wrong. Message text:\n";
686 cout << x.what() << '\n';
687 return 1;
688 }
689
690 return 0;
691}
void write_agenda_wrapper_header(ofstream &ofs, const AgRecord &agr, bool is_agenda_array)
Write a agenda wrapper header.
Declarations for AgRecord, storing lookup information for one agenda.
void define_agenda_data()
Definition: agendas.cc:44
This file contains the definition of Array.
The global header file for ARTS.
Index get_wsv_id(const String &name)
Get index of WSV.
Definition: workspace.cc:5752
void define_wsv_group_names()
Define the array of workspace variable group names.
Definition: groups.cc:77
This can be used to make arrays out of anything.
Definition: array.h:107
Index nelem() const ARTS_NOEXCEPT
Number of elements.
Definition: array.h:195
All information for one workspace method.
Definition: methods.h:41
const ArrayOfIndex & In() const
Definition: methods.h:96
const String & Name() const
Definition: methods.h:88
const ArrayOfIndex & InOnly() const
Definition: methods.h:102
bool PassWorkspace() const
Definition: methods.h:109
const ArrayOfIndex & GOutType() const
Definition: methods.h:93
const String & ActualGroups() const
Definition: methods.h:111
const Array< String > & GInDefault() const
Definition: methods.h:100
bool PassWsvNames() const
Definition: methods.h:110
const String & Description() const
Definition: methods.h:89
const ArrayOfString & GOut() const
Definition: methods.h:92
bool UsesTemplates() const
Definition: methods.h:108
bool AgendaMethod() const
Definition: methods.h:106
bool Supergeneric() const
Definition: methods.h:107
const ArrayOfString & Authors() const
Definition: methods.h:90
const ArrayOfIndex & Out() const
Definition: methods.h:91
const ArrayOfIndex & GInType() const
Definition: methods.h:98
const ArrayOfString & GIn() const
Definition: methods.h:97
static void define_wsv_data()
Define workspace variables.
Definition: workspace.cc:39
static void define_wsv_map()
Map WSV names to indices.
Definition: workspace_ng.cc:48
static Array< WsvRecord > wsv_data
Global WSV data.
Definition: workspace_ng.h:58
void insert_substr(const my_basic_string< charT > &searchstr, const my_basic_string< charT > &insstr)
Insert string before all occurrences of the substring.
Definition: mystring.h:191
Index nelem() const
Number of elements.
Definition: mystring.h:253
void open_output_file(ofstream &file, const String &name)
Open a file for writing.
Definition: file.cc:93
int check_newline(const String &s)
Checks if there is exactly one newline character at the end of the string.
Definition: file.cc:271
This file contains basic functions to handle ASCII files.
Index get_wsv_group_id(const String &name)
Returns the id of the given group.
Definition: groups.cc:227
bool is_agenda_group_id(const Index group)
Check if group is an agenda group.
Definition: groups.cc:222
void write_method_header_documentation(ofstream &ofs, const MdRecord &mdd)
Write method header documentation.
void write_method_header(ofstream &ofs, const MdRecord &mdd)
Write a method header.
void align(ofstream &ofs, bool &is_first_parameter, const String &indent)
int main()
bool md_sanity_checks(const Array< MdRecord > &md_data)
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
void define_md_data_raw()
Definition: methods.cc:191
Declaration of the class MdRecord.
void expand_md_data_raw_to_md_data()
Expand supergeneric methods.
Definition: methods_aux.cc:410
#define NODEF
Definition: methods.h:35
Index nelem(const Lines &l)
Number of lines.
constexpr Rational end(Rational Ju, Rational Jl, Polarization type) noexcept
Gives the largest M for a polarization type of this transition.
Definition: zeemandata.h:109
const Array< MdRecord > md_data_raw
Lookup information for workspace methods.
Definition: methods.cc:39
const Array< MdRecord > md_data
Lookup information for workspace methods.
const Array< AgRecord > agenda_data
The lookup information for the agendas.
Definition: agendas.cc:41
const ArrayOfString wsv_group_names
The names associated with Wsv groups as Strings.
Definition: global_data.h:90
This file contains the Workspace class.