ARTS  2.3.1285(git:92a29ea9-dirty)
linerecord.cc
Go to the documentation of this file.
1 /* Copyright (C) 2000-2013
2  Stefan Buehler <sbuehler@ltu.se>
3  Axel von Engeln <engeln@uni-bremen.de>
4 
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of the GNU General Public License as published by the
7  Free Software Foundation; either version 2, or (at your option) any
8  later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18  USA. */
19 
27 #include "linerecord.h"
28 #include <cfloat>
29 #include "absorption.h"
30 #include "quantum_parser_hitran.h"
31 
32 #include "global_data.h"
33 
34 #include "file.h"
35 
37  ostringstream os;
38  os << "ARTSCAT-" << mversion;
39  return os.str();
40 }
41 
43  // The species lookup data:
45  const SpeciesRecord& sr = species_data[mqid.Species()];
46  return sr.Name() + "-" + sr.Isotopologue()[mqid.Isotopologue()].Name();
47 }
48 
50  // The species lookup data:
52  return species_data[mqid.Species()];
53 }
54 
56  // The species lookup data:
58  return species_data[mqid.Species()].Isotopologue()[mqid.Isotopologue()];
59 }
60 
62  const Verbosity& verbosity) {
64 
65  // Global species lookup data:
67 
68  // This value is used to flag missing data both in species and
69  // isotopologue lists. Could be any number, it just has to be made sure
70  // that it is neither the index of a species nor of an isotopologue.
71  const Index missing = species_data.nelem() + 100;
72 
73  // We need a species index sorted by HITRAN tag. Keep this in a
74  // static variable, so that we have to do this only once. The ARTS
75  // species index is hind[<HITRAN tag>].
76  //
77  // Allow for up to 100 species in HITRAN in the future.
78  static Array<Index> hspec(100);
79 
80  // This is an array of arrays for each hitran tag. It contains the
81  // ARTS indices of the HITRAN isotopologues.
82  static Array<ArrayOfIndex> hiso(100);
83 
84  // Remember if this stuff has already been initialized:
85  static bool hinit = false;
86 
87  // Remember, about which missing species we have already issued a
88  // warning:
89  static ArrayOfIndex warned_missing;
90 
91  if (!hinit) {
92  // Initialize hspec.
93  // The value of missing means that we don't have this species.
94  hspec = missing; // Matpack can set all elements like this.
95 
96  for (Index i = 0; i < species_data.nelem(); ++i) {
97  const SpeciesRecord& sr = species_data[i];
98 
99  // We have to be careful and check for the case that all
100  // HITRAN isotopologue tags are -1 (this species is missing in HITRAN).
101 
102  if (sr.Isotopologue().nelem() && 0 < sr.Isotopologue()[0].HitranTag()) {
103  // The HITRAN tags are stored as species plus isotopologue tags
104  // (MO and ISO)
105  // in the Isotopologue() part of the species record.
106  // We can extract the MO part from any of the isotopologue tags,
107  // so we use the first one. We do this by taking an integer
108  // division by 10.
109 
110  Index mo = sr.Isotopologue()[0].HitranTag() / 10;
111  // cout << "mo = " << mo << endl;
112  hspec[mo] = i;
113 
114  // Get a nicer to handle array of HITRAN iso tags:
115  Index n_iso = sr.Isotopologue().nelem();
116  ArrayOfIndex iso_tags;
117  iso_tags.resize(n_iso);
118  for (Index j = 0; j < n_iso; ++j) {
119  iso_tags[j] = sr.Isotopologue()[j].HitranTag();
120  }
121 
122  // Reserve elements for the isotopologue tags. How much do we
123  // need? This depends on the largest HITRAN tag that we know
124  // about!
125  // Also initialize the tags to missing.
126  // cout << "iso_tags = " << iso_tags << endl;
127  // cout << "static_cast<Index>(max(iso_tags))%10 + 1 = "
128  // << static_cast<Index>(max(iso_tags))%10 + 1 << endl;
129  hiso[mo].resize(max(iso_tags) % 10 + 1);
130  hiso[mo] = missing; // Matpack can set all elements like this.
131 
132  // Set the isotopologue tags:
133  for (Index j = 0; j < n_iso; ++j) {
134  if (0 < iso_tags[j]) // ignore -1 elements
135  {
136  // To get the iso tags from HitranTag() we also have to take
137  // modulo 10 to get rid of mo.
138  hiso[mo][iso_tags[j] % 10] = j;
139  }
140  }
141  }
142  }
143 
144  // Print the generated data structures (for debugging):
145  out3 << " HITRAN index table:\n";
146  for (Index i = 0; i < hspec.nelem(); ++i) {
147  if (missing != hspec[i]) {
148  // The explicit conversion of Name to a c-String is
149  // necessary, because setw does not work correctly for
150  // stl Strings.
151  out3 << " mo = " << i << " Species = " << setw(10)
152  << setiosflags(ios::left) << species_data[hspec[i]].Name().c_str()
153  << "iso = ";
154  for (Index j = 1; j < hiso[i].nelem(); ++j) {
155  if (missing == hiso[i][j])
156  out3 << " "
157  << "m";
158  else
159  out3 << " "
160  << species_data[hspec[i]].Isotopologue()[hiso[i][j]].Name();
161  }
162  out3 << "\n";
163  }
164  }
165 
166  hinit = true;
167  }
168 
169  // This contains the rest of the line to parse. At the beginning the
170  // entire line. Line gets shorter and shorter as we continue to
171  // extract stuff from the beginning.
172  String line;
173 
174  // The first item is the molecule number:
175  Index mo;
176 
177  // Look for more comments?
178  bool comment = true;
179 
180  while (comment) {
181  // Return true if eof is reached:
182  if (is.eof()) return true;
183 
184  // Throw runtime_error if stream is bad:
185  if (!is) throw runtime_error("Stream bad.");
186 
187  // Read line from file into linebuffer:
188  getline(is, line);
189 
190  // It is possible that we were exactly at the end of the file before
191  // calling getline. In that case the previous eof() was still false
192  // because eof() evaluates only to true if one tries to read after the
193  // end of the file. The following check catches this.
194  if (line.nelem() == 0 && is.eof()) return true;
195 
196  // If the catalogue is in dos encoding, throw away the
197  // additional carriage return
198  if (line[line.nelem() - 1] == 13) {
199  line.erase(line.nelem() - 1, 1);
200  }
201 
202  // Because of the fixed FORTRAN format, we need to break up the line
203  // explicitly in apropriate pieces. Not elegant, but works!
204 
205  // Extract molecule number:
206  mo = 0;
207  // Initialization of mo is important, because mo stays the same
208  // if line is empty.
209  extract(mo, line, 2);
210  // cout << "mo = " << mo << endl;
211 
212  // If mo == 0 this is just a comment line:
213  if (0 != mo) {
214  // See if we know this species. Exit with an error if the species is unknown.
215  if (missing != hspec[mo]) {
216  comment = false;
217 
218  // Check if data record has the right number of characters for the
219  // in Hitran 1986-2001 format
220  Index nChar = line.nelem() + 2; // number of characters in data record;
221  if (nChar != 100) {
222  ostringstream os;
223  os << "Invalid HITRAN 1986-2001 line data record with " << nChar
224  << " characters (expected: 100)." << endl
225  << line << " n: " << line.nelem();
226  throw runtime_error(os.str());
227  }
228 
229  } else {
230  // See if this is already in warned_missing, use
231  // std::count for that:
232  if (0 == std::count(warned_missing.begin(), warned_missing.end(), mo)) {
233  CREATE_OUT0;
234  out0 << "Error: HITRAN mo = " << mo << " is not "
235  << "known to ARTS.\n";
236  warned_missing.push_back(mo);
237  }
238  }
239  }
240  }
241 
242  // Ok, we seem to have a valid species here.
243 
244  // Set mspecies from my cool index table:
245  mqid.SetSpecies(hspec[mo]);
246 
247  // Extract isotopologue:
248  Index iso;
249  extract(iso, line, 1);
250  // cout << "iso = " << iso << endl;
251 
252  // Set misotopologue from the other cool index table.
253  // We have to be careful to issue an error for unknown iso tags. Iso
254  // could be either larger than the size of hiso[mo], or set
255  // explicitly to missing. Unfortunately we have to test both cases.
256  mqid.SetIsotopologue(missing);
257  if (iso < hiso[mo].nelem())
258  if (missing != hiso[mo][iso]) mqid.SetIsotopologue(hiso[mo][iso]);
259 
260  // Issue error message if misotopologue is still missing:
261  if (missing == mqid.Isotopologue()) {
262  ostringstream os;
263  os << "Species: " << species_data[mqid.Species()].Name()
264  << ", isotopologue iso = " << iso << " is unknown.";
265  throw runtime_error(os.str());
266  }
267 
268  // Position.
269  {
270  // HITRAN position in wavenumbers (cm^-1):
271  Numeric v;
272  // External constant from constants.cc:
273  extern const Numeric SPEED_OF_LIGHT;
274  // Conversion from wavenumber to Hz. If you multiply a line
275  // position in wavenumber (cm^-1) by this constant, you get the
276  // frequency in Hz.
277  const Numeric w2Hz = SPEED_OF_LIGHT * 100.;
278 
279  // Extract HITRAN postion:
280  extract(v, line, 12);
281 
282  // ARTS position in Hz:
283  mf = v * w2Hz;
284  // cout << "mf = " << mf << endl;
285  }
286 
287  // Intensity.
288  {
289  extern const Numeric SPEED_OF_LIGHT; // in [m/s]
290 
291  // HITRAN intensity is in cm-1/(molec * cm-2) at 296 Kelvin.
292  // It already includes the isotpic ratio.
293  // The first cm-1 is the frequency unit (it cancels with the
294  // 1/frequency unit of the line shape function).
295  //
296  // We need to do the following:
297  // 1. Convert frequency from wavenumber to Hz (factor 1e2 * c).
298  // 2. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4).
299  // 3. Take out the isotopologue ratio.
300 
301  const Numeric hi2arts = 1e-2 * SPEED_OF_LIGHT;
302 
303  Numeric s;
304 
305  // Extract HITRAN intensity:
306  extract(s, line, 10);
307  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
308  mi0 = s * hi2arts;
309  // Take out isotopologue ratio:
311  .Isotopologue()[mqid.Isotopologue()]
312  .Abundance();
313  }
314 
315  // Skip transition probability:
316  {
317  Numeric r;
318  extract(r, line, 10);
319  }
320 
321  // Air broadening parameters.
322  Numeric agam, sgam;
323  {
324  // HITRAN parameter is in cm-1/atm at 296 Kelvin
325  // All parameters are HWHM (I hope this is true!)
326  Numeric gam;
327  // External constant from constants.cc: Converts atm to
328  // Pa. Multiply value in atm by this number to get value in Pa.
329  extern const Numeric ATM2PA;
330  // External constant from constants.cc:
331  extern const Numeric SPEED_OF_LIGHT;
332  // Conversion from wavenumber to Hz. If you multiply a value in
333  // wavenumber (cm^-1) by this constant, you get the value in Hz.
334  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
335  // Ok, put together the end-to-end conversion that we need:
336  const Numeric hi2arts = w2Hz / ATM2PA;
337 
338  // Extract HITRAN AGAM value:
339  extract(gam, line, 5);
340 
341  // ARTS parameter in Hz/Pa:
342  agam = gam * hi2arts;
343 
344  // Extract HITRAN SGAM value:
345  extract(gam, line, 5);
346 
347  // ARTS parameter in Hz/Pa:
348  sgam = gam * hi2arts;
349 
350  // If zero, set to agam:
351  if (0 == sgam) sgam = agam;
352 
353  // cout << "agam, sgam = " << magam << ", " << msgam << endl;
354  }
355 
356  // Lower state energy.
357  {
358  // HITRAN parameter is in wavenumbers (cm^-1).
359  // We have to convert this to the ARTS unit Joule.
360 
361  // Extract from Catalogue line
362  extract(melow, line, 10);
363 
364  // Convert to Joule:
366  }
367 
368  // Temperature coefficient of broadening parameters.
369  Numeric nair, nself;
370  {
371  // This is dimensionless, we can also extract directly.
372  extract(nair, line, 4);
373 
374  // Set self broadening temperature coefficient to the same value:
375  nself = nair;
376  // cout << "mnair = " << mnair << endl;
377  }
378 
379  // Pressure shift.
380  Numeric psf;
381  {
382  // HITRAN value in cm^-1 / atm. So the conversion goes exactly as
383  // for the broadening parameters.
384  Numeric d;
385  // External constant from constants.cc: Converts atm to
386  // Pa. Multiply value in atm by this number to get value in Pa.
387  extern const Numeric ATM2PA;
388  // External constant from constants.cc:
389  extern const Numeric SPEED_OF_LIGHT;
390  // Conversion from wavenumber to Hz. If you multiply a value in
391  // wavenumber (cm^-1) by this constant, you get the value in Hz.
392  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
393  // Ok, put together the end-to-end conversion that we need:
394  const Numeric hi2arts = w2Hz / ATM2PA;
395 
396  // Extract HITRAN value:
397  extract(d, line, 8);
398 
399  // ARTS value in Hz/Pa
400  psf = d * hi2arts;
401  }
402  // Set the accuracies using the definition of HITRAN
403  // indices. If some are missing, they are set to -1.
404 
405  //Skip upper state global quanta index
406  {
407  Index eu;
408  extract(eu, line, 3);
409  }
410 
411  //Skip lower state global quanta index
412  {
413  Index el;
414  extract(el, line, 3);
415  }
416 
417  //Skip upper state local quanta
418  {
419  Index eul;
420  extract(eul, line, 9);
421  }
422 
423  //Skip lower state local quanta
424  {
425  Index ell;
426  extract(ell, line, 9);
427  }
428 
429  // Accuracy index for frequency reference
430  {
431  Index df;
432  // Extract HITRAN value:
433  extract(df, line, 1);
434  }
435 
436  // Accuracy index for intensity reference
437  {
438  Index di0;
439  // Extract HITRAN value:
440  extract(di0, line, 1);
441  }
442 
443  // Accuracy index for halfwidth reference
444  {
445  Index dgam;
446  // Extract HITRAN value:
447  extract(dgam, line, 1);
448  }
449 
450  // These were all the parameters that we can extract from
451  // HITRAN. However, we still have to set the reference temperatures
452  // to the appropriate value:
453 
454  // Reference temperature for Intensity in K.
455  mti0 = 296.0;
456 
457  // Set line shape computer
458  mlineshapemodel = LineShape::Model(sgam, nself, agam, nair, psf);
459  mstandard = true;
460 
461  // That's it!
462  return false;
463 }
464 
465 // The below is a derivative of ReadFromHitran2001Stream
466 bool LineRecord::ReadFromLBLRTMStream(istream& is, const Verbosity& verbosity) {
467  CREATE_OUT3;
468 
469  // Global species lookup data:
471 
472  // This value is used to flag missing data both in species and
473  // isotopologue lists. Could be any number, it just has to be made sure
474  // that it is neither the index of a species nor of an isotopologue.
475  const Index missing = species_data.nelem() + 100;
476 
477  // We need a species index sorted by HITRAN tag. Keep this in a
478  // static variable, so that we have to do this only once. The ARTS
479  // species index is hind[<HITRAN tag>].
480  //
481  // Allow for up to 100 species in HITRAN in the future.
482  static Array<Index> hspec(100);
483 
484  // This is an array of arrays for each hitran tag. It contains the
485  // ARTS indices of the HITRAN isotopologues.
486  static Array<ArrayOfIndex> hiso(100);
487 
488  // Remember if this stuff has already been initialized:
489  static bool hinit = false;
490 
491  // Remember, about which missing species we have already issued a
492  // warning:
493  static ArrayOfIndex warned_missing;
494 
495  if (!hinit) {
496  // Initialize hspec.
497  // The value of missing means that we don't have this species.
498  hspec = missing; // Matpack can set all elements like this.
499  for (Index i = 0; i < species_data.nelem(); ++i) {
500  const SpeciesRecord& sr = species_data[i];
501  // We have to be careful and check for the case that all
502  // HITRAN isotopologue tags are -1 (this species is missing in HITRAN).
503  if (sr.Isotopologue().nelem() && 0 < sr.Isotopologue()[0].HitranTag()) {
504  // The HITRAN tags are stored as species plus isotopologue tags
505  // (MO and ISO)
506  // in the Isotopologue() part of the species record.
507  // We can extract the MO part from any of the isotopologue tags,
508  // so we use the first one. We do this by taking an integer
509  // division by 10.
510 
511  Index mo = sr.Isotopologue()[0].HitranTag() / 10;
512  // cout << "mo = " << mo << endl;
513  hspec[mo] = i;
514 
515  // Get a nicer to handle array of HITRAN iso tags:
516  Index n_iso = sr.Isotopologue().nelem();
517  ArrayOfIndex iso_tags;
518  iso_tags.resize(n_iso);
519  for (Index j = 0; j < n_iso; ++j) {
520  iso_tags[j] = sr.Isotopologue()[j].HitranTag();
521  }
522 
523  // Reserve elements for the isotopologue tags. How much do we
524  // need? This depends on the largest HITRAN tag that we know
525  // about!
526  // Also initialize the tags to missing.
527  // cout << "iso_tags = " << iso_tags << endl;
528  // cout << "static_cast<Index>(max(iso_tags))%10 + 1 = "
529  // << static_cast<Index>(max(iso_tags))%10 + 1 << endl;
530  hiso[mo].resize(max(iso_tags) % 10 + 1);
531  hiso[mo] = missing; // Matpack can set all elements like this.
532 
533  // Set the isotopologue tags:
534  for (Index j = 0; j < n_iso; ++j) {
535  if (0 < iso_tags[j]) // ignore -1 elements
536  {
537  // To get the iso tags from HitranTag() we also have to take
538  // modulo 10 to get rid of mo.
539  hiso[mo][iso_tags[j] % 10] = j;
540  }
541  }
542  }
543  }
544 
545  // Print the generated data structures (for debugging):
546  out3 << " HITRAN index table:\n";
547  for (Index i = 0; i < hspec.nelem(); ++i) {
548  if (missing != hspec[i]) {
549  // The explicit conversion of Name to a c-String is
550  // necessary, because setw does not work correctly for
551  // stl Strings.
552  out3 << " mo = " << i << " Species = " << std::setw(10)
553  << std::setiosflags(std::ios::left)
554  << species_data[hspec[i]].Name().c_str() << "iso = ";
555  for (Index j = 1; j < hiso[i].nelem(); ++j) {
556  if (missing == hiso[i][j])
557  out3 << " "
558  << "m";
559  else
560  out3 << " "
561  << species_data[hspec[i]].Isotopologue()[hiso[i][j]].Name();
562  }
563  out3 << "\n";
564  }
565  }
566 
567  hinit = true;
568  }
569 
570  // This contains the rest of the line to parse. At the beginning the
571  // entire line. Line gets shorter and shorter as we continue to
572  // extract stuff from the beginning.
573  String line;
574 
575  // The first item is the molecule number:
576  Index mo;
577 
578  // Look for more comments?
579  bool comment = true;
580 
581  while (comment) {
582  // Return true if eof is reached:
583  if (is.eof()) return true;
584 
585  // Throw runtime_error if stream is bad:
586  if (!is) throw std::runtime_error("Stream bad.");
587 
588  // Read line from file into linebuffer:
589  getline(is, line);
590 
591  // It is possible that we were exactly at the end of the file before
592  // calling getline. In that case the previous eof() was still false
593  // because eof() evaluates only to true if one tries to read after the
594  // end of the file. The following check catches this.
595  if (line.nelem() == 0 && is.eof()) return true;
596 
597  // If the catalogue is in dos encoding, throw away the
598  // additional carriage return
599  if (line[line.nelem() - 1] == 13) {
600  line.erase(line.nelem() - 1, 1);
601  }
602 
603  // Because of the fixed FORTRAN format, we need to break up the line
604  // explicitly in apropriate pieces. Not elegant, but works!
605 
606  // Extract molecule number:
607  mo = 0;
608  // Initialization of mo is important, because mo stays the same
609  // if line is empty.
610  extract(mo, line, 2);
611  // cout << "mo = " << mo << endl;
612 
613  // If mo == 0 this is just a comment line:
614  if (0 != mo) {
615  // See if we know this species. Exit with an error if the species is unknown.
616  if (missing != hspec[mo]) {
617  comment = false;
618 
619  // Check if data record has the right number of characters for the
620  // in Hitran 1986-2001 format
621  Index nChar = line.nelem() + 2; // number of characters in data record;
622  if (nChar != 100) {
623  ostringstream os;
624  os << "Invalid HITRAN 1986-2001 line data record with " << nChar
625  << " characters (expected: 100)." << endl
626  << line << " n: " << line.nelem();
627  throw std::runtime_error(os.str());
628  }
629 
630  } else {
631  // See if this is already in warned_missing, use
632  // std::count for that:
633  if (0 == std::count(warned_missing.begin(), warned_missing.end(), mo)) {
634  CREATE_OUT0;
635  out0 << "Error: HITRAN mo = " << mo << " is not "
636  << "known to ARTS.\n";
637  warned_missing.push_back(mo);
638  }
639  }
640  }
641  }
642 
643  // Ok, we seem to have a valid species here.
644 
645  // Set mspecies from my cool index table:
646  mqid.SetSpecies(hspec[mo]);
647 
648  // Extract isotopologue:
649  Index iso;
650  extract(iso, line, 1);
651  // cout << "iso = " << iso << endl;
652 
653  // Set misotopologue from the other cool index table.
654  // We have to be careful to issue an error for unknown iso tags. Iso
655  // could be either larger than the size of hiso[mo], or set
656  // explicitly to missing. Unfortunately we have to test both cases.
657  mqid.SetIsotopologue(missing);
658  if (iso < hiso[mo].nelem())
659  if (missing != hiso[mo][iso]) mqid.SetIsotopologue(hiso[mo][iso]);
660 
661  // Issue error message if misotopologue is still missing:
662  if (missing == mqid.Isotopologue()) {
663  ostringstream os;
664  os << "Species: " << species_data[mqid.Species()].Name()
665  << ", isotopologue iso = " << iso << " is unknown.";
666  throw std::runtime_error(os.str());
667  }
668 
669  // Position.
670  {
671  // HITRAN position in wavenumbers (cm^-1):
672  Numeric v;
673  // External constant from constants.cc:
674  extern const Numeric SPEED_OF_LIGHT;
675  // Conversion from wavenumber to Hz. If you multiply a line
676  // position in wavenumber (cm^-1) by this constant, you get the
677  // frequency in Hz.
678  const Numeric w2Hz = SPEED_OF_LIGHT * 100.;
679 
680  // Extract HITRAN postion:
681  extract(v, line, 12);
682 
683  // ARTS position in Hz:
684  mf = v * w2Hz;
685  // cout << "mf = " << mf << endl;
686  }
687 
688  // Intensity.
689  {
690  extern const Numeric SPEED_OF_LIGHT; // in [m/s]
691 
692  // HITRAN intensity is in cm-1/(molec * cm-2) at 296 Kelvin.
693  // It already includes the isotpic ratio.
694  // The first cm-1 is the frequency unit (it cancels with the
695  // 1/frequency unit of the line shape function).
696  //
697  // We need to do the following:
698  // 1. Convert frequency from wavenumber to Hz (factor 1e2 * c).
699  // 2. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4).
700  // 3. Take out the isotopologue ratio.
701 
702  const Numeric hi2arts = 1e-2 * SPEED_OF_LIGHT;
703 
704  Numeric s;
705  if (line[6] == 'D') line[6] = 'E';
706  // Extract HITRAN intensity:
707  extract(s,
708  line,
709  10); // NOTE: If error shooting, FORTRAN "D" is not read properly.
710  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
711  mi0 = s * hi2arts;
712  // Take out isotopologue ratio:
714  .Isotopologue()[mqid.Isotopologue()]
715  .Abundance();
716  }
717 
718  // Skip transition probability:
719  {
720  Numeric r;
721  extract(r, line, 10);
722  }
723 
724  // Air broadening parameters.
725  Numeric sgam, agam;
726  {
727  // HITRAN parameter is in cm-1/atm at 296 Kelvin
728  // All parameters are HWHM (I hope this is true!)
729  Numeric gam;
730  // External constant from constants.cc: Converts atm to
731  // Pa. Multiply value in atm by this number to get value in Pa.
732  extern const Numeric ATM2PA;
733  // External constant from constants.cc:
734  extern const Numeric SPEED_OF_LIGHT;
735  // Conversion from wavenumber to Hz. If you multiply a value in
736  // wavenumber (cm^-1) by this constant, you get the value in Hz.
737  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
738  // Ok, put together the end-to-end conversion that we need:
739  const Numeric hi2arts = w2Hz / ATM2PA;
740 
741  // Extract HITRAN AGAM value:
742  extract(gam, line, 5);
743 
744  // ARTS parameter in Hz/Pa:
745  agam = gam * hi2arts;
746 
747  // Extract HITRAN SGAM value:
748  extract(gam, line, 5);
749 
750  // ARTS parameter in Hz/Pa:
751  sgam = gam * hi2arts;
752 
753  // If zero, set to agam:
754  if (0 == sgam) sgam = agam;
755 
756  // cout << "agam, sgam = " << magam << ", " << msgam << endl;
757  }
758 
759  // Lower state energy.
760  {
761  // HITRAN parameter is in wavenumbers (cm^-1).
762  // We have to convert this to the ARTS unit Joule.
763 
764  // Extract from Catalogue line
765  extract(melow, line, 10);
766 
767  // Convert to Joule:
769  }
770 
771  // Temperature coefficient of broadening parameters.
772  Numeric nair, nself;
773  {
774  // This is dimensionless, we can also extract directly.
775  extract(nair, line, 4);
776 
777  // Set self broadening temperature coefficient to the same value:
778  nself = nair;
779  // cout << "mnair = " << mnair << endl;
780  }
781 
782  // Pressure shift.
783  Numeric psf;
784  {
785  // HITRAN value in cm^-1 / atm. So the conversion goes exactly as
786  // for the broadening parameters.
787  Numeric d;
788  // External constant from constants.cc: Converts atm to
789  // Pa. Multiply value in atm by this number to get value in Pa.
790  extern const Numeric ATM2PA;
791  // External constant from constants.cc:
792  extern const Numeric SPEED_OF_LIGHT;
793  // Conversion from wavenumber to Hz. If you multiply a value in
794  // wavenumber (cm^-1) by this constant, you get the value in Hz.
795  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
796  // Ok, put together the end-to-end conversion that we need:
797  const Numeric hi2arts = w2Hz / ATM2PA;
798 
799  // Extract HITRAN value:
800  extract(d, line, 8);
801 
802  // ARTS value in Hz/Pa
803  psf = d * hi2arts;
804  }
805  // Set the accuracies using the definition of HITRAN
806  // indices. If some are missing, they are set to -1.
807 
808  //Skip upper state global quanta index
809  {
810  Index eu;
811  extract(eu, line, 3);
812  }
813 
814  //Skip lower state global quanta index
815  {
816  Index el;
817  extract(el, line, 3);
818  }
819 
820  //Skip upper state local quanta
821  {
822  Index eul;
823  extract(eul, line, 9);
824  }
825 
826  //Skip lower state local quanta
827  {
828  Index ell;
829  if (species_data[mqid.Species()].Name() == "O2") {
830  String helper = line.substr(0, 9);
831  Index DJ = -helper.compare(3, 1, "Q");
832  Index DN = -helper.compare(0, 1, "Q");
833  Index N = atoi(helper.substr(1, 2).c_str());
834  Index J = atoi(helper.substr(4, 2).c_str());
835 
840  }
841 
842  extract(ell, line, 9);
843  }
844 
845  // Accuracy index for frequency reference
846  {
847  Index df;
848  // Extract HITRAN value:
849  extract(df, line, 1);
850  }
851 
852  // Accuracy index for intensity reference
853  {
854  Index di0;
855  // Extract HITRAN value:
856  extract(di0, line, 1);
857  }
858 
859  // Accuracy index for halfwidth reference
860  {
861  Index dgam;
862  // Extract HITRAN value:
863  extract(dgam, line, 1);
864  }
865 
866  // These were all the parameters that we can extract from
867  // HITRAN. However, we still have to set the reference temperatures
868  // to the appropriate value:
869 
870  // Reference temperature for Intensity in K.
871  // (This is fix for HITRAN)
872  mti0 = 296.0;
873 
874  // Skip four
875  {
876  Index four;
877  extract(four, line, 4);
878  }
879 
880  // This is the test for the last two characters of the line
881  {
882  /*
883  * 0 is nothing,
884  * -1 is linemixing on the next line,
885  * -3 is the non-resonant line
886  */
887  Index test;
888  extract(test, line, 2);
889  //If the tag is as it should be, then a minus one means that more should be read
890  if (test == -1 || test == -3)
891  getline(is, line);
892  else // the line is done and we are happy to leave
893  {
894  mlineshapemodel = LineShape::Model(sgam, nself, agam, nair, psf);
895  mstandard = true;
896  return false;
897  }
898  }
899 
900  // In case we are unable to leave, the next line is a line mixing parameter line
901 
902  // First is the molecular number. This should be the same as above.
903  {
904  Index mo2;
905  extract(mo2, line, 2);
906  // Skip one
907 
908  if (mo != mo2)
909  throw std::runtime_error("There is an error in the line mixing\n");
910  }
911 
912  Vector Y(4), G(4), T(4);
913 
914  // These are constants for AER but should be included because we need their grid.
915  T[0] = 200;
916  T[1] = 250;
917  T[2] = 296;
918  T[3] = 340;
919 
920  // Next is the Y and G at various temperatures
921  {
922  Numeric Y_200K;
923  extract(Y_200K, line, 13);
924  Y[0] = Y_200K;
925  }
926  {
927  Numeric G_200K;
928  extract(G_200K, line, 11);
929  G[0] = G_200K;
930  }
931  {
932  Numeric Y_250K;
933  extract(Y_250K, line, 13);
934  Y[1] = Y_250K;
935  }
936  {
937  Numeric G_250K;
938  extract(G_250K, line, 11);
939  G[1] = G_250K;
940  }
941  {
942  Numeric Y_296K;
943  extract(Y_296K, line, 13);
944  Y[2] = Y_296K;
945  }
946  {
947  Numeric G_296K;
948  extract(G_296K, line, 11);
949  G[2] = G_296K;
950  }
951  {
952  Numeric Y_340K;
953  extract(Y_340K, line, 13);
954  Y[3] = Y_340K;
955  }
956  {
957  Numeric G_340K;
958  extract(G_340K, line, 11);
959  G[3] = G_340K;
960  }
961 
962  extern const Numeric ATM2PA;
963 
964  Y /= ATM2PA;
965  G /= ATM2PA / ATM2PA;
966  Y *=
967  -1; // ARTS uses (1-iY) as line-mixing factor, LBLRTM CO2 uses (1+iY), so we must change sign
968 
969  // Test that this is the end
970  {
971  Index test;
972  extract(test, line, 2);
973  if (test == -1) {
975  nself,
976  agam,
977  nair,
978  psf,
979  {T[0],
980  T[1],
981  T[2],
982  T[3],
983  Y[0],
984  Y[1],
985  Y[2],
986  Y[3],
987  G[0],
988  G[1],
989  G[2],
990  G[3]});
991  mstandard = true;
992 
993  return false;
994  } else if (test == -3) {
996  nself,
997  agam,
998  nair,
999  psf,
1000  {T[0],
1001  T[1],
1002  T[2],
1003  T[3],
1004  Y[0],
1005  Y[1],
1006  Y[2],
1007  Y[3],
1008  G[0],
1009  G[1],
1010  G[2],
1011  G[3]});
1012  mstandard = true;
1013 
1014  return false;
1015  } else
1016  return true;
1017  }
1018 }
1019 
1021  const Verbosity& verbosity,
1022  const Numeric fmin) {
1023  CREATE_OUT3;
1024 
1025  // Global species lookup data:
1027 
1028  // This value is used to flag missing data both in species and
1029  // isotopologue lists. Could be any number, it just has to be made sure
1030  // that it is neither the index of a species nor of an isotopologue.
1031  const Index missing = species_data.nelem() + 100;
1032 
1033  // We need a species index sorted by HITRAN tag. Keep this in a
1034  // static variable, so that we have to do this only once. The ARTS
1035  // species index is hind[<HITRAN tag>].
1036  //
1037  // Allow for up to 100 species in HITRAN in the future.
1038  static Array<Index> hspec(100);
1039 
1040  // This is an array of arrays for each hitran tag. It contains the
1041  // ARTS indices of the HITRAN isotopologues.
1042  static Array<ArrayOfIndex> hiso(100);
1043 
1044  // Remember if this stuff has already been initialized:
1045  static bool hinit = false;
1046 
1047  // Remember, about which missing species we have already issued a
1048  // warning:
1049  static ArrayOfIndex warned_missing;
1050 
1051  if (!hinit) {
1052  // Initialize hspec.
1053  // The value of missing means that we don't have this species.
1054  hspec = missing; // Matpack can set all elements like this.
1055 
1056  for (Index i = 0; i < species_data.nelem(); ++i) {
1057  const SpeciesRecord& sr = species_data[i];
1058 
1059  // We have to be careful and check for the case that all
1060  // HITRAN isotopologue tags are -1 (this species is missing in HITRAN).
1061 
1062  if (sr.Isotopologue().nelem() && 0 < sr.Isotopologue()[0].HitranTag()) {
1063  // The HITRAN tags are stored as species plus isotopologue tags
1064  // (MO and ISO)
1065  // in the Isotopologue() part of the species record.
1066  // We can extract the MO part from any of the isotopologue tags,
1067  // so we use the first one. We do this by taking an integer
1068  // division by 10.
1069 
1070  Index mo = sr.Isotopologue()[0].HitranTag() / 10;
1071  // cout << "mo = " << mo << endl;
1072  hspec[mo] = i;
1073 
1074  // Get a nicer to handle array of HITRAN iso tags:
1075  Index n_iso = sr.Isotopologue().nelem();
1076  ArrayOfIndex iso_tags;
1077  iso_tags.resize(n_iso);
1078  for (Index j = 0; j < n_iso; ++j) {
1079  iso_tags[j] = sr.Isotopologue()[j].HitranTag();
1080  }
1081 
1082  // Reserve elements for the isotopologue tags. How much do we
1083  // need? This depends on the largest HITRAN tag that we know
1084  // about!
1085  // Also initialize the tags to missing.
1086  // cout << "iso_tags = " << iso_tags << endl;
1087  // cout << "static_cast<Index>(max(iso_tags))%10 + 1 = "
1088  // << static_cast<Index>(max(iso_tags))%10 + 1 << endl;
1089  hiso[mo].resize(max(iso_tags) % 10 + 1);
1090  hiso[mo] = missing; // Matpack can set all elements like this.
1091 
1092  // Set the isotopologue tags:
1093  for (Index j = 0; j < n_iso; ++j) {
1094  if (0 < iso_tags[j]) // ignore -1 elements
1095  {
1096  // To get the iso tags from HitranTag() we also have to take
1097  // modulo 10 to get rid of mo.
1098  hiso[mo][iso_tags[j] % 10] = j;
1099  }
1100  }
1101  }
1102  }
1103 
1104  // Print the generated data structures (for debugging):
1105  out3 << " HITRAN index table:\n";
1106  for (Index i = 0; i < hspec.nelem(); ++i) {
1107  if (missing != hspec[i]) {
1108  // The explicit conversion of Name to a c-String is
1109  // necessary, because setw does not work correctly for
1110  // stl Strings.
1111  out3 << " mo = " << i << " Species = " << setw(10)
1112  << setiosflags(ios::left) << species_data[hspec[i]].Name().c_str()
1113  << "iso = ";
1114  for (Index j = 1; j < hiso[i].nelem(); ++j) {
1115  if (missing == hiso[i][j])
1116  out3 << " "
1117  << "m";
1118  else
1119  out3 << " "
1120  << species_data[hspec[i]].Isotopologue()[hiso[i][j]].Name();
1121  }
1122  out3 << "\n";
1123  }
1124  }
1125 
1126  hinit = true;
1127  }
1128 
1129  // This contains the rest of the line to parse. At the beginning the
1130  // entire line. Line gets shorter and shorter as we continue to
1131  // extract stuff from the beginning.
1132  String line;
1133 
1134  // The first item is the molecule number:
1135  Index mo;
1136 
1137  // Look for more comments?
1138  bool comment = true;
1139 
1140  while (comment) {
1141  // Return true if eof is reached:
1142  if (is.eof()) return true;
1143 
1144  // Throw runtime_error if stream is bad:
1145  if (!is) throw runtime_error("Stream bad.");
1146 
1147  // Read line from file into linebuffer:
1148  getline(is, line);
1149 
1150  // It is possible that we were exactly at the end of the file before
1151  // calling getline. In that case the previous eof() was still false
1152  // because eof() evaluates only to true if one tries to read after the
1153  // end of the file. The following check catches this.
1154  if (line.nelem() == 0 && is.eof()) return true;
1155 
1156  // If the catalogue is in dos encoding, throw away the
1157  // additional carriage return
1158  if (line[line.nelem() - 1] == 13) {
1159  line.erase(line.nelem() - 1, 1);
1160  }
1161 
1162  // Because of the fixed FORTRAN format, we need to break up the line
1163  // explicitly in apropriate pieces. Not elegant, but works!
1164 
1165  // Extract molecule number:
1166  mo = 0;
1167  // Initialization of mo is important, because mo stays the same
1168  // if line is empty.
1169  extract(mo, line, 2);
1170  // cout << "mo = " << mo << endl;
1171 
1172  // If mo == 0 this is just a comment line:
1173  if (0 != mo) {
1174  // See if we know this species.
1175  if (missing != hspec[mo]) {
1176  comment = false;
1177 
1178  // Check if data record has the right number of characters for the
1179  // in Hitran 2004 format
1180  Index nChar = line.nelem() + 2; // number of characters in data record;
1181  if ((nChar == 161 && line[158] != ' ') || nChar > 161) {
1182  ostringstream os;
1183  os << "Invalid HITRAN 2004 line data record with " << nChar
1184  << " characters (expected: 160).";
1185  throw std::runtime_error(os.str());
1186  }
1187 
1188  } else {
1189  // See if this is already in warned_missing, use
1190  // std::count for that:
1191  if (0 == std::count(warned_missing.begin(), warned_missing.end(), mo)) {
1192  CREATE_OUT1;
1193  out1 << "Warning: HITRAN molecule number mo = " << mo << " is not "
1194  << "known to ARTS.\n";
1195  warned_missing.push_back(mo);
1196  }
1197  }
1198  }
1199  }
1200 
1201  // Ok, we seem to have a valid species here.
1202 
1203  // Set mspecies from my cool index table:
1204  mqid.SetSpecies(hspec[mo]);
1205 
1206  // Extract isotopologue:
1207  Index iso;
1208  extract(iso, line, 1);
1209  // cout << "iso = " << iso << endl;
1210 
1211  // Set misotopologue from the other cool index table.
1212  // We have to be careful to issue an error for unknown iso tags. Iso
1213  // could be either larger than the size of hiso[mo], or set
1214  // explicitly to missing. Unfortunately we have to test both cases.
1215  mqid.SetIsotopologue(missing);
1216  if (iso < hiso[mo].nelem())
1217  if (missing != hiso[mo][iso]) mqid.SetIsotopologue(hiso[mo][iso]);
1218 
1219  // Issue error message if misotopologue is still missing:
1220  if (missing == mqid.Isotopologue()) {
1221  ostringstream os;
1222  os << "Species: " << species_data[mqid.Species()].Name()
1223  << ", isotopologue iso = " << iso << " is unknown.";
1224  throw std::runtime_error(os.str());
1225  }
1226 
1227  // Position.
1228  {
1229  // HITRAN position in wavenumbers (cm^-1):
1230  Numeric v;
1231  // External constant from constants.cc:
1232  extern const Numeric SPEED_OF_LIGHT;
1233  // Conversion from wavenumber to Hz. If you multiply a line
1234  // position in wavenumber (cm^-1) by this constant, you get the
1235  // frequency in Hz.
1236  const Numeric w2Hz = SPEED_OF_LIGHT * 100.;
1237 
1238  // Extract HITRAN postion:
1239  extract(v, line, 12);
1240 
1241  // ARTS position in Hz:
1242  mf = v * w2Hz;
1243  // cout << "mf = " << mf << endl;
1244  if (mf < fmin) {
1245  mf = -1;
1246  return false;
1247  }
1248  }
1249 
1250  // Intensity.
1251  {
1252  extern const Numeric SPEED_OF_LIGHT; // in [m/s]
1253 
1254  // HITRAN intensity is in cm-1/(molec * cm-2) at 296 Kelvin.
1255  // It already includes the isotpic ratio.
1256  // The first cm-1 is the frequency unit (it cancels with the
1257  // 1/frequency unit of the line shape function).
1258  //
1259  // We need to do the following:
1260  // 1. Convert frequency from wavenumber to Hz (factor 1e2 * c).
1261  // 2. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4).
1262  // 3. Take out the isotopologue ratio.
1263 
1264  const Numeric hi2arts = 1e-2 * SPEED_OF_LIGHT;
1265 
1266  Numeric s;
1267 
1268  // Extract HITRAN intensity:
1269  extract(s, line, 10);
1270  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
1271  mi0 = s * hi2arts;
1272  // Take out isotopologue ratio:
1274  .Isotopologue()[mqid.Isotopologue()]
1275  .Abundance();
1276  }
1277 
1278  // Einstein coefficient
1279  {
1280  Numeric r;
1281  extract(r, line, 10);
1282  ma = r;
1283  }
1284 
1285  // Air broadening parameters.
1286  Numeric agam, sgam;
1287  {
1288  // HITRAN parameter is in cm-1/atm at 296 Kelvin
1289  // All parameters are HWHM (I hope this is true!)
1290  Numeric gam;
1291  // External constant from constants.cc: Converts atm to
1292  // Pa. Multiply value in atm by this number to get value in Pa.
1293  extern const Numeric ATM2PA;
1294  // External constant from constants.cc:
1295  extern const Numeric SPEED_OF_LIGHT;
1296  // Conversion from wavenumber to Hz. If you multiply a value in
1297  // wavenumber (cm^-1) by this constant, you get the value in Hz.
1298  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
1299  // Ok, put together the end-to-end conversion that we need:
1300  const Numeric hi2arts = w2Hz / ATM2PA;
1301 
1302  // Extract HITRAN AGAM value:
1303  extract(gam, line, 5);
1304 
1305  // ARTS parameter in Hz/Pa:
1306  agam = gam * hi2arts;
1307 
1308  // Extract HITRAN SGAM value:
1309  extract(gam, line, 5);
1310 
1311  // ARTS parameter in Hz/Pa:
1312  sgam = gam * hi2arts;
1313 
1314  // If zero, set to agam:
1315  if (0 == sgam) sgam = agam;
1316 
1317  // cout << "agam, sgam = " << magam << ", " << msgam << endl;
1318  }
1319 
1320  // Lower state energy.
1321  {
1322  // HITRAN parameter is in wavenumbers (cm^-1).
1323  // We have to convert this to the ARTS unit Joule.
1324 
1325  // Extract from Catalogue line
1326  extract(melow, line, 10);
1327 
1328  // Convert to Joule:
1330  }
1331 
1332  // Temperature coefficient of broadening parameters.
1333  Numeric nair, nself;
1334  {
1335  // This is dimensionless, we can also extract directly.
1336  extract(nair, line, 4);
1337 
1338  // Set self broadening temperature coefficient to the same value:
1339  nself = nair;
1340  // cout << "mnair = " << mnair << endl;
1341  }
1342 
1343  // Pressure shift.
1344  Numeric psf;
1345  {
1346  // HITRAN value in cm^-1 / atm. So the conversion goes exactly as
1347  // for the broadening parameters.
1348  Numeric d;
1349  // External constant from constants.cc: Converts atm to
1350  // Pa. Multiply value in atm by this number to get value in Pa.
1351  extern const Numeric ATM2PA;
1352  // External constant from constants.cc:
1353  extern const Numeric SPEED_OF_LIGHT;
1354  // Conversion from wavenumber to Hz. If you multiply a value in
1355  // wavenumber (cm^-1) by this constant, you get the value in Hz.
1356  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
1357  // Ok, put together the end-to-end conversion that we need:
1358  const Numeric hi2arts = w2Hz / ATM2PA;
1359 
1360  // Extract HITRAN value:
1361  extract(d, line, 8);
1362 
1363  // ARTS value in Hz/Pa
1364  psf = d * hi2arts;
1365  }
1366  // Set the accuracies using the definition of HITRAN
1367  // indices. If some are missing, they are set to -1.
1368 
1369  static QuantumParserHITRAN2004 quantum_parser;
1370  const String qstr = line.substr(0, 15 * 4);
1371 
1372  // Upper state global quanta
1373  {
1374  Index eu;
1375  extract(eu, line, 15);
1376  }
1377 
1378  // Lower state global quanta
1379  {
1380  Index el;
1381  extract(el, line, 15);
1382  }
1383 
1384  // Upper state local quanta
1385  {
1386  Index eul;
1387  extract(eul, line, 15);
1388  }
1389 
1390  // Lower state local quanta
1391  {
1392  Index ell;
1393  extract(ell, line, 15);
1394  }
1395 
1396  // Parse quantum numbers.
1397  quantum_parser.Parse(mqid, qstr);
1398 
1399  // Accuracy index for frequency
1400  {
1401  Index df;
1402  // Extract HITRAN value:
1403  extract(df, line, 1);
1404  }
1405 
1406  // Accuracy index for intensity
1407  {
1408  Index di0;
1409  // Extract HITRAN value:
1410  extract(di0, line, 1);
1411  }
1412 
1413  // Accuracy index for air-broadened halfwidth
1414  {
1415  Index dgam;
1416  // Extract HITRAN value:
1417  extract(dgam, line, 1);
1418  }
1419 
1420  // Accuracy index for self-broadened half-width
1421  {
1422  Index dgam;
1423  // Extract HITRAN value:
1424  extract(dgam, line, 1);
1425  }
1426 
1427  // Accuracy index for temperature-dependence exponent for agam
1428  {
1429  Index dn;
1430  // Extract HITRAN value:
1431  extract(dn, line, 1);
1432  }
1433 
1434  // Accuracy index for pressure shift
1435  {
1436  Index dpsfi;
1437  // Extract HITRAN value (given in cm-1):
1438  extract(dpsfi, line, 1);
1439  }
1440 
1441  // These were all the parameters that we can extract from
1442  // HITRAN 2004. However, we still have to set the reference temperatures
1443  // to the appropriate value:
1444 
1445  // Reference temperature for Intensity in K.
1446  mti0 = 296.0;
1447 
1448  // Set line shape computer
1449  mlineshapemodel = LineShape::Model(sgam, nself, agam, nair, psf);
1450  mstandard = true;
1451  {
1452  Index garbage;
1453  extract(garbage, line, 13);
1454 
1455  // The statistical weights
1456  extract(mgupper, line, 7);
1457  extract(mglower, line, 7);
1458  }
1459 
1460  // That's it!
1461  return false;
1462 }
1463 
1465  const Verbosity& verbosity) {
1466  CREATE_OUT3;
1467 
1468  // Global species lookup data:
1470 
1471  // This value is used to flag missing data both in species and
1472  // isotopologue lists. Could be any number, it just has to be made sure
1473  // that it is neither the index of a species nor of an isotopologue.
1474  const Index missing = species_data.nelem() + 100;
1475 
1476  // We need a species index sorted by MYTRAN tag. Keep this in a
1477  // static variable, so that we have to do this only once. The ARTS
1478  // species index is hind[<MYTRAN tag>]. The value of
1479  // missing means that we don't have this species.
1480  //
1481  // Allow for up to 100 species in MYTRAN in the future.
1482  static Array<Index> hspec(100, missing);
1483 
1484  // This is an array of arrays for each mytran tag. It contains the
1485  // ARTS indices of the MYTRAN isotopologues.
1486  static Array<ArrayOfIndex> hiso(100);
1487 
1488  // Remember if this stuff has already been initialized:
1489  static bool hinit = false;
1490 
1491  // Remember, about which missing species we have already issued a
1492  // warning:
1493  static ArrayOfIndex warned_missing;
1494 
1495  if (!hinit) {
1496  for (Index i = 0; i < species_data.nelem(); ++i) {
1497  const SpeciesRecord& sr = species_data[i];
1498 
1499  // We have to be careful and check for the case that all
1500  // MYTRAN isotopologue tags are -1 (this species is missing in MYTRAN).
1501 
1502  if (0 < sr.Isotopologue()[0].MytranTag()) {
1503  // The MYTRAN tags are stored as species plus isotopologue tags
1504  // (MO and ISO)
1505  // in the Isotopologue() part of the species record.
1506  // We can extract the MO part from any of the isotopologue tags,
1507  // so we use the first one. We do this by taking an integer
1508  // division by 10.
1509 
1510  Index mo = sr.Isotopologue()[0].MytranTag() / 10;
1511  // cout << "mo = " << mo << endl;
1512  hspec[mo] = i;
1513 
1514  // Get a nicer to handle array of MYTRAN iso tags:
1515  Index n_iso = sr.Isotopologue().nelem();
1516  ArrayOfIndex iso_tags;
1517  iso_tags.resize(n_iso);
1518  for (Index j = 0; j < n_iso; ++j) {
1519  iso_tags[j] = sr.Isotopologue()[j].MytranTag();
1520  }
1521 
1522  // Reserve elements for the isotopologue tags. How much do we
1523  // need? This depends on the largest MYTRAN tag that we know
1524  // about!
1525  // Also initialize the tags to missing.
1526  // cout << "iso_tags = " << iso_tags << endl;
1527  // cout << "static_cast<Index>(max(iso_tags))%10 + 1 = "
1528  // << static_cast<Index>(max(iso_tags))%10 + 1 << endl;
1529  hiso[mo].resize(max(iso_tags) % 10 + 1);
1530  hiso[mo] = missing; // Matpack can set all elements like this.
1531 
1532  // Set the isotopologue tags:
1533  for (Index j = 0; j < n_iso; ++j) {
1534  if (0 < iso_tags[j]) // ignore -1 elements
1535  {
1536  // To get the iso tags from MytranTag() we also have to take
1537  // modulo 10 to get rid of mo.
1538  // cout << "iso_tags[j] % 10 = " << iso_tags[j] % 10 << endl;
1539  hiso[mo][iso_tags[j] % 10] = j;
1540  }
1541  }
1542  }
1543  }
1544 
1545  // cout << "hiso = " << hiso << endl << "***********" << endl;
1546 
1547  // Print the generated data structures (for debugging):
1548  out3 << " MYTRAN index table:\n";
1549  for (Index i = 0; i < hspec.nelem(); ++i) {
1550  if (missing != hspec[i]) {
1551  // The explicit conversion of Name to a c-String is
1552  // necessary, because setw does not work correctly for
1553  // stl Strings.
1554  out3 << " mo = " << i << " Species = " << setw(10)
1555  << setiosflags(ios::left) << species_data[hspec[i]].Name().c_str()
1556  << "iso = ";
1557  for (Index j = 1; j < hiso[i].nelem(); ++j) {
1558  if (missing == hiso[i][j])
1559  out3 << " "
1560  << "m";
1561  else
1562  out3 << " "
1563  << species_data[hspec[i]].Isotopologue()[hiso[i][j]].Name();
1564  }
1565  out3 << "\n";
1566  }
1567  }
1568 
1569  hinit = true;
1570  }
1571 
1572  // This contains the rest of the line to parse. At the beginning the
1573  // entire line. Line gets shorter and shorter as we continue to
1574  // extract stuff from the beginning.
1575  String line;
1576 
1577  // The first item is the molecule number:
1578  Index mo;
1579 
1580  // Look for more comments?
1581  bool comment = true;
1582 
1583  while (comment) {
1584  // Return true if eof is reached:
1585  if (is.eof()) return true;
1586 
1587  // Throw runtime_error if stream is bad:
1588  if (!is) throw runtime_error("Stream bad.");
1589 
1590  // Read line from file into linebuffer:
1591  getline(is, line);
1592 
1593  // It is possible that we were exactly at the end of the file before
1594  // calling getline. In that case the previous eof() was still false
1595  // because eof() evaluates only to true if one tries to read after the
1596  // end of the file. The following check catches this.
1597  if (line.nelem() == 0 && is.eof()) return true;
1598 
1599  // Because of the fixed FORTRAN format, we need to break up the line
1600  // explicitly in apropriate pieces. Not elegant, but works!
1601 
1602  // Extract molecule number:
1603  mo = 0;
1604  // Initialization of mo is important, because mo stays the same
1605  // if line is empty.
1606  extract(mo, line, 2);
1607  // cout << "mo = " << mo << endl;
1608 
1609  // If mo == 0 this is just a comment line:
1610  if (0 != mo) {
1611  // See if we know this species. We will give an error if a
1612  // species is not known.
1613  if (missing != hspec[mo])
1614  comment = false;
1615  else {
1616  // See if this is already in warned_missing, use
1617  // std::count for that:
1618  if (0 == std::count(warned_missing.begin(), warned_missing.end(), mo)) {
1619  CREATE_OUT0;
1620  out0 << "Error: MYTRAN mo = " << mo << " is not "
1621  << "known to ARTS.\n";
1622  warned_missing.push_back(mo);
1623  }
1624  }
1625  }
1626  }
1627 
1628  // Ok, we seem to have a valid species here.
1629 
1630  // Set mspecies from my cool index table:
1631  mqid.SetSpecies(hspec[mo]);
1632 
1633  // Extract isotopologue:
1634  Index iso;
1635  extract(iso, line, 1);
1636  // cout << "iso = " << iso << endl;
1637 
1638  // Set misotopologue from the other cool index table.
1639  // We have to be careful to issue an error for unknown iso tags. Iso
1640  // could be either larger than the size of hiso[mo], or set
1641  // explicitly to missing. Unfortunately we have to test both cases.
1642  mqid.SetIsotopologue(missing);
1643  if (iso < hiso[mo].nelem())
1644  if (missing != hiso[mo][iso]) mqid.SetIsotopologue(hiso[mo][iso]);
1645 
1646  // Issue error message if misotopologue is still missing:
1647  if (missing == mqid.Isotopologue()) {
1648  ostringstream os;
1649  os << "Species: " << species_data[mqid.Species()].Name()
1650  << ", isotopologue iso = " << iso << " is unknown.";
1651  throw runtime_error(os.str());
1652  }
1653 
1654  // Position.
1655  {
1656  // MYTRAN position in MHz:
1657  Numeric v;
1658 
1659  // Extract MYTRAN postion:
1660  extract(v, line, 13);
1661 
1662  // ARTS position in Hz:
1663  mf = v * 1E6;
1664  // cout << "mf = " << mf << endl;
1665  }
1666 
1667  // Accuracy for line position
1668  {
1669  // Extract MYTRAN postion accuracy:
1670  Numeric df;
1671  extract(df, line, 8);
1672  }
1673 
1674  // Intensity.
1675  {
1676  extern const Numeric SPEED_OF_LIGHT; // in [m/s]
1677 
1678  // MYTRAN2 intensity is in cm-1/(molec * cm-2) at 296 Kelvin.
1679  // (just like HITRAN, only isotopologue ratio is not included)
1680  // The first cm-1 is the frequency unit (it cancels with the
1681  // 1/frequency unit of the line shape function).
1682  //
1683  // We need to do the following:
1684  // 1. Convert frequency from wavenumber to Hz (factor 1e2 * c)
1685  // 2. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4)
1686 
1687  const Numeric hi2arts = 1e-2 * SPEED_OF_LIGHT;
1688 
1689  Numeric s;
1690 
1691  // Extract HITRAN intensity:
1692  extract(s, line, 10);
1693 
1694  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
1695  mi0 = s * hi2arts;
1696  }
1697 
1698  // Air broadening parameters.
1699  Numeric agam, sgam;
1700  {
1701  // MYTRAN parameter is in MHz/Torr at reference temperature
1702  // All parameters are HWHM
1703  Numeric gam;
1704  // External constant from constants.cc: Converts torr to
1705  // Pa. Multiply value in torr by this number to get value in Pa.
1706  extern const Numeric TORR2PA;
1707 
1708  // Extract HITRAN AGAM value:
1709  extract(gam, line, 5);
1710 
1711  // ARTS parameter in Hz/Pa:
1712  agam = gam * 1E6 / TORR2PA;
1713 
1714  // Extract MYTRAN SGAM value:
1715  extract(gam, line, 5);
1716 
1717  // ARTS parameter in Hz/Pa:
1718  sgam = gam * 1E6 / TORR2PA;
1719 
1720  // cout << "agam, sgam = " << magam << ", " << msgam << endl;
1721  }
1722 
1723  // Lower state energy.
1724  {
1725  // MYTRAN parameter is in wavenumbers (cm^-1).
1726  // We have to convert this to the ARTS unit Joule.
1727 
1728  // Extract from Catalogue line
1729  extract(melow, line, 10);
1730 
1731  // Convert to Joule:
1733  }
1734 
1735  // Temperature coefficient of broadening parameters.
1736  Numeric nself, nair;
1737  {
1738  // This is dimensionless, we can also extract directly.
1739  extract(nair, line, 4);
1740 
1741  // Extract the self broadening parameter:
1742  extract(nself, line, 4);
1743  // cout << "mnair = " << mnair << endl;
1744  }
1745 
1746  // Reference temperature for broadening parameter in K:
1747  Numeric tgam;
1748  {
1749  // correct units, extract directly
1750  extract(tgam, line, 7);
1751  }
1752 
1753  // Pressure shift.
1754  Numeric psf;
1755  {
1756  // MYTRAN value in MHz/Torr
1757  Numeric d;
1758  // External constant from constants.cc: Converts torr to
1759  // Pa. Multiply value in torr by this number to get value in Pa.
1760  extern const Numeric TORR2PA;
1761 
1762  // Extract MYTRAN value:
1763  extract(d, line, 9);
1764 
1765  // ARTS value in Hz/Pa
1766  psf = d * 1E6 / TORR2PA;
1767  }
1768  // Set the accuracies using the definition of MYTRAN accuracy
1769  // indices. If some are missing, they are set to -1.
1770 
1771  //Skip upper state global quanta index
1772  {
1773  Index eu;
1774  extract(eu, line, 3);
1775  }
1776 
1777  //Skip lower state global quanta index
1778  {
1779  Index el;
1780  extract(el, line, 3);
1781  }
1782 
1783  //Skip upper state local quanta
1784  {
1785  Index eul;
1786  extract(eul, line, 9);
1787  }
1788 
1789  //Skip lower state local quanta
1790  {
1791  Index ell;
1792  extract(ell, line, 9);
1793  }
1794  // Accuracy index for intensity
1795  {
1796  Index di0;
1797  // Extract MYTRAN value:
1798  extract(di0, line, 1);
1799  }
1800 
1801  // Accuracy index for AGAM
1802  {
1803  Index dgam;
1804  // Extract MYTRAN value:
1805  extract(dgam, line, 1);
1806  }
1807 
1808  // Accuracy index for NAIR
1809  {
1810  Index dair;
1811  // Extract MYTRAN value:
1812  extract(dair, line, 1);
1813  }
1814 
1815  // These were all the parameters that we can extract from
1816  // MYTRAN. However, we still have to set the reference temperatures
1817  // to the appropriate value:
1818 
1819  // Reference temperature for Intensity in K.
1820  // (This is fix for MYTRAN2)
1821  mti0 = 296.0;
1822 
1823  // It is important that you intialize here all the new parameters that
1824  // you added to the line record. (This applies to all the reading
1825  // functions, also for ARTS, JPL, and HITRAN format.) Parameters
1826  // should be either set from the catalogue, or set to -1.)
1827 
1828  // Convert to correct temperature if tgam != ti0
1829  if (tgam != mti0) {
1830  agam *= pow(tgam / mti0, nair);
1831  sgam *= pow(tgam / mti0, nself);
1832  psf *= pow(tgam / mti0, (Numeric).25 + (Numeric)1.5 * nair);
1833  }
1834 
1835  // Set line shape computer
1836  mlineshapemodel = LineShape::Model(sgam, nself, agam, nair, psf);
1837  mstandard = true;
1838 
1839  // That's it!
1840  return false;
1841 }
1842 
1843 bool LineRecord::ReadFromJplStream(istream& is, const Verbosity& verbosity) {
1844  CREATE_OUT3;
1845 
1846  // Global species lookup data:
1848 
1849  // We need a species index sorted by JPL tag. Keep this in a
1850  // static variable, so that we have to do this only once. The ARTS
1851  // species index is JplMap[<JPL tag>]. We need Index in this map,
1852  // because the tag array within the species data is an Index array.
1853  static map<Index, SpecIsoMap> JplMap;
1854 
1855  // Remember if this stuff has already been initialized:
1856  static bool hinit = false;
1857 
1858  if (!hinit) {
1859  out3 << " JPL index table:\n";
1860 
1861  for (Index i = 0; i < species_data.nelem(); ++i) {
1862  const SpeciesRecord& sr = species_data[i];
1863 
1864  for (Index j = 0; j < sr.Isotopologue().nelem(); ++j) {
1865  for (Index k = 0; k < sr.Isotopologue()[j].JplTags().nelem(); ++k) {
1866  SpecIsoMap indicies(i, j);
1867 
1868  JplMap[sr.Isotopologue()[j].JplTags()[k]] = indicies;
1869 
1870  // Print the generated data structures (for debugging):
1871  // The explicit conversion of Name to a c-String is
1872  // necessary, because setw does not work correctly for
1873  // stl Strings.
1874  const Index& i1 =
1875  JplMap[sr.Isotopologue()[j].JplTags()[k]].Speciesindex();
1876  const Index& i2 =
1877  JplMap[sr.Isotopologue()[j].JplTags()[k]].Isotopologueindex();
1878 
1879  out3 << " JPL TAG = " << sr.Isotopologue()[j].JplTags()[k]
1880  << " Species = " << setw(10) << setiosflags(ios::left)
1881  << species_data[i1].Name().c_str()
1882  << "iso = " << species_data[i1].Isotopologue()[i2].Name().c_str()
1883  << "\n";
1884  }
1885  }
1886  }
1887  hinit = true;
1888  }
1889 
1890  // This contains the rest of the line to parse. At the beginning the
1891  // entire line. Line gets shorter and shorter as we continue to
1892  // extract stuff from the beginning.
1893  String line;
1894 
1895  // Look for more comments?
1896  bool comment = true;
1897 
1898  while (comment) {
1899  // Return true if eof is reached:
1900  if (is.eof()) return true;
1901 
1902  // Throw runtime_error if stream is bad:
1903  if (!is) throw runtime_error("Stream bad.");
1904 
1905  // Read line from file into linebuffer:
1906  getline(is, line);
1907 
1908  // It is possible that we were exactly at the end of the file before
1909  // calling getline. In that case the previous eof() was still false
1910  // because eof() evaluates only to true if one tries to read after the
1911  // end of the file. The following check catches this.
1912  if (line.nelem() == 0 && is.eof()) return true;
1913 
1914  // Because of the fixed FORTRAN format, we need to break up the line
1915  // explicitly in apropriate pieces. Not elegant, but works!
1916 
1917  // Extract center frequency:
1918  // Initialization of v is important, because v stays the same
1919  // if line is empty.
1920  // JPL position in MHz:
1921  Numeric v = 0.0;
1922 
1923  // Extract JPL position:
1924  extract(v, line, 13);
1925 
1926  // check for empty line
1927  if (v != 0.0) {
1928  // ARTS position in Hz:
1929  mf = v * 1E6;
1930 
1931  comment = false;
1932  }
1933  }
1934 
1935  // Accuracy for line position
1936  {
1937  Numeric df;
1938  extract(df, line, 8);
1939  }
1940 
1941  // Intensity.
1942  {
1943  // JPL has log (10) of intensity in nm2 MHz at 300 Kelvin.
1944  //
1945  // We need to do the following:
1946  // 1. take 10^intensity
1947  // 2. convert to cm-1/(molecule * cm-2): devide by c * 1e10
1948  // 3. Convert frequency from wavenumber to Hz (factor 1e2 * c)
1949  // 4. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4)
1950 
1951  Numeric s;
1952 
1953  // Extract JPL intensity:
1954  extract(s, line, 8);
1955 
1956  // remove log
1957  s = pow((Numeric)10., s);
1958 
1959  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
1960  mi0 = s / 1E12;
1961  }
1962 
1963  // Degrees of freedom
1964  {
1965  Index dr;
1966 
1967  // Extract degrees of freedom
1968  extract(dr, line, 2);
1969  }
1970 
1971  // Lower state energy.
1972  {
1973  // JPL parameter is in wavenumbers (cm^-1).
1974  // We have to convert this to the ARTS unit Joule.
1975 
1976  // Extract from Catalogue line
1977  extract(melow, line, 10);
1978 
1979  // Convert to Joule:
1981  }
1982 
1983  // Upper state degeneracy
1984  {
1985  Index gup;
1986 
1987  // Extract upper state degeneracy
1988  extract(gup, line, 3);
1989  }
1990 
1991  // Tag number
1992  Index tag;
1993  {
1994  // Extract Tag number
1995  extract(tag, line, 7);
1996 
1997  // make sure tag is not negative (damned jpl cat):
1998  tag = tag > 0 ? tag : -tag;
1999  }
2000 
2001  // ok, now for the cool index map:
2002 
2003  // is this tag valid?
2004  const map<Index, SpecIsoMap>::const_iterator i = JplMap.find(tag);
2005  if (i == JplMap.end()) {
2006  ostringstream os;
2007  os << "JPL Tag: " << tag << " is unknown.";
2008  throw runtime_error(os.str());
2009  }
2010 
2011  SpecIsoMap id = i->second;
2012 
2013  // Set line ID
2014  mqid.SetSpecies(id.Speciesindex());
2015  mqid.SetIsotopologue(id.Isotopologueindex());
2016 
2017  // Air broadening parameters: unknown to jpl, use old iup forward
2018  // model default values, which is mostly set to 0.0025 GHz/hPa, even
2019  // though for some lines the pressure broadening is given explicitly
2020  // in the program code. The explicitly given values are ignored and
2021  // only the default value is set. Self broadening was in general not
2022  // considered in the old forward model.
2023  Numeric agam, sgam;
2024  {
2025  // ARTS parameter in Hz/Pa:
2026  agam = 2.5E4;
2027 
2028  // ARTS parameter in Hz/Pa:
2029  sgam = agam;
2030  }
2031 
2032  // Temperature coefficient of broadening parameters. Was set to 0.75
2033  // in old forward model, even though for some lines the parameter is
2034  // given explicitly in the program code. The explicitly given values
2035  // are ignored and only the default value is set. Self broadening
2036  // not considered.
2037  Numeric nair, nself;
2038  {
2039  nair = 0.75;
2040  nself = 0.0;
2041  }
2042 
2043  // Reference temperature for broadening parameter in K, was
2044  // generally set to 300 K in old forward model, with the exceptions
2045  // as already mentioned above: //DEPRECEATED but is same as for mti0 so moving on
2046  // {
2047  // mtgam = 300.0;
2048  // }
2049 
2050  // Pressure shift: not given in JPL, set to 0
2051  Numeric psf;
2052  { psf = 0.0; }
2053 
2054  // These were all the parameters that we can extract from
2055  // JPL. However, we still have to set the reference temperatures
2056  // to the appropriate value:
2057 
2058  // Reference temperature for Intensity in K.
2059  mti0 = 300.0;
2060 
2061  // Set line shape computer
2062  mlineshapemodel = LineShape::Model(sgam, nself, agam, nair, psf);
2063  mstandard = true;
2064 
2065  // That's it!
2066  return false;
2067 }
2068 
2070  const Verbosity& verbosity) {
2071  CREATE_OUT3;
2072 
2073  // Global species lookup data:
2075 
2076  // We need a species index sorted by Arts identifier. Keep this in a
2077  // static variable, so that we have to do this only once. The ARTS
2078  // species index is ArtsMap[<Arts String>].
2079  static map<String, SpecIsoMap> ArtsMap;
2080 
2081  // Remember if this stuff has already been initialized:
2082  static bool hinit = false;
2083 
2084  mversion = 5;
2085 
2086  if (!hinit) {
2087  out3 << " ARTS index table:\n";
2088 
2089  for (Index i = 0; i < species_data.nelem(); ++i) {
2090  const SpeciesRecord& sr = species_data[i];
2091 
2092  for (Index j = 0; j < sr.Isotopologue().nelem(); ++j) {
2093  SpecIsoMap indicies(i, j);
2094  String buf = sr.Name() + "-" + sr.Isotopologue()[j].Name();
2095 
2096  ArtsMap[buf] = indicies;
2097 
2098  // Print the generated data structures (for debugging):
2099  // The explicit conversion of Name to a c-String is
2100  // necessary, because setw does not work correctly for
2101  // stl Strings.
2102  const Index& i1 = ArtsMap[buf].Speciesindex();
2103  const Index& i2 = ArtsMap[buf].Isotopologueindex();
2104 
2105  out3 << " Arts Identifier = " << buf << " Species = " << setw(10)
2106  << setiosflags(ios::left) << species_data[i1].Name().c_str()
2107  << "iso = " << species_data[i1].Isotopologue()[i2].Name().c_str()
2108  << "\n";
2109  }
2110  }
2111  hinit = true;
2112  }
2113 
2114  // This always contains the rest of the line to parse. At the
2115  // beginning the entire line. Line gets shorter and shorter as we
2116  // continue to extract stuff from the beginning.
2117  String line;
2118 
2119  // Look for more comments?
2120  bool comment = true;
2121 
2122  while (comment) {
2123  // Return true if eof is reached:
2124  if (is.eof()) return true;
2125 
2126  // Throw runtime_error if stream is bad:
2127  if (!is) throw runtime_error("Stream bad.");
2128 
2129  // Read line from file into linebuffer:
2130  getline(is, line);
2131 
2132  // It is possible that we were exactly at the end of the file before
2133  // calling getline. In that case the previous eof() was still false
2134  // because eof() evaluates only to true if one tries to read after the
2135  // end of the file. The following check catches this.
2136  if (line.nelem() == 0 && is.eof()) return true;
2137 
2138  // @ as first character marks catalogue entry
2139  char c;
2140  extract(c, line, 1);
2141 
2142  // check for empty line
2143  if (c == '@') {
2144  comment = false;
2145  }
2146  }
2147 
2148  // read the arts identifier String
2149  istringstream icecream(line);
2150 
2151  String artsid;
2152  icecream >> artsid;
2153 
2154  if (artsid.length() != 0) {
2155  // ok, now for the cool index map:
2156  // is this arts identifier valid?
2157  const map<String, SpecIsoMap>::const_iterator i = ArtsMap.find(artsid);
2158  if (i == ArtsMap.end()) {
2159  ostringstream os;
2160  os << "ARTS Tag: " << artsid << " is unknown.";
2161  throw runtime_error(os.str());
2162  }
2163 
2164  SpecIsoMap id = i->second;
2165 
2166  // Set mspecies:
2167  mqid.SetSpecies(id.Speciesindex());
2168 
2169  // Set misotopologue:
2170  mqid.SetIsotopologue(id.Isotopologueindex());
2171 
2172  // Extract center frequency:
2173  icecream >> mf;
2174 
2175  Numeric psf;
2176  // Extract pressure shift:
2177  icecream >> psf;
2178 
2179  // Extract intensity:
2180  icecream >> mi0;
2181 
2182  // Extract reference temperature for Intensity in K:
2183  icecream >> mti0;
2184 
2185  // Extract lower state energy:
2186  icecream >> melow;
2187 
2188  // Extract air broadening parameters:
2189  Numeric agam, sgam;
2190  icecream >> agam;
2191  icecream >> sgam;
2192 
2193  // Extract temperature coefficient of broadening parameters:
2194  Numeric nair, nself;
2195  icecream >> nair;
2196  icecream >> nself;
2197 
2198  // Extract reference temperature for broadening parameter in K:
2199  Numeric tgam;
2200  icecream >> tgam;
2201 
2202  // Extract the aux parameters:
2203  Index naux;
2204  icecream >> naux;
2205 
2206  // resize the aux array and read it
2207  ArrayOfNumeric maux;
2208  maux.resize(naux);
2209 
2210  for (Index j = 0; j < naux; j++) {
2211  icecream >> maux[j];
2212  //cout << "maux" << j << " = " << maux[j] << "\n";
2213  }
2214 
2215  // Extract accuracies:
2216  Numeric dagam, dsgam, dnair, dnself, dpsf;
2217  try {
2218  Numeric mdf, mdi0;
2219  icecream >> mdf;
2220  icecream >> mdi0;
2221  icecream >> dagam;
2222  icecream >> dsgam;
2223  icecream >> dnair;
2224  icecream >> dnself;
2225  icecream >> dpsf;
2226  } catch (const std::runtime_error&) {
2227  // Nothing to do here, the accuracies are optional, so we
2228  // just set them to -1 and continue reading the next line of
2229  // the catalogue
2230  dagam = -1;
2231  dsgam = -1;
2232  dnair = -1;
2233  dnself = -1;
2234  dpsf = -1;
2235  }
2236 
2237  // Fix if tgam is different from ti0
2238  if (tgam != mti0) {
2239  agam = agam * pow(tgam / mti0, nair);
2240  sgam = sgam * pow(tgam / mti0, nself);
2241  psf = psf * pow(tgam / mti0, (Numeric).25 + (Numeric)1.5 * nair);
2242  }
2243 
2244  // Set line shape computer
2245  mlineshapemodel = LineShape::Model(sgam, nself, agam, nair, psf);
2246  mstandard = true;
2247  }
2248 
2249  // That's it!
2250  return false;
2251 }
2252 
2254  const Verbosity& verbosity) {
2255  CREATE_OUT3;
2256 
2257  // Global species lookup data:
2259 
2260  // We need a species index sorted by Arts identifier. Keep this in a
2261  // static variable, so that we have to do this only once. The ARTS
2262  // species index is ArtsMap[<Arts String>].
2263  static map<String, SpecIsoMap> ArtsMap;
2264 
2265  // Remember if this stuff has already been initialized:
2266  static bool hinit = false;
2267 
2268  mversion = 5;
2269 
2270  if (!hinit) {
2271  out3 << " ARTS index table:\n";
2272 
2273  for (Index i = 0; i < species_data.nelem(); ++i) {
2274  const SpeciesRecord& sr = species_data[i];
2275 
2276  for (Index j = 0; j < sr.Isotopologue().nelem(); ++j) {
2277  SpecIsoMap indicies(i, j);
2278  String buf = sr.Name() + "-" + sr.Isotopologue()[j].Name();
2279 
2280  ArtsMap[buf] = indicies;
2281 
2282  // Print the generated data structures (for debugging):
2283  // The explicit conversion of Name to a c-String is
2284  // necessary, because setw does not work correctly for
2285  // stl Strings.
2286  const Index& i1 = ArtsMap[buf].Speciesindex();
2287  const Index& i2 = ArtsMap[buf].Isotopologueindex();
2288 
2289  out3 << " Arts Identifier = " << buf << " Species = " << setw(10)
2290  << setiosflags(ios::left) << species_data[i1].Name().c_str()
2291  << "iso = " << species_data[i1].Isotopologue()[i2].Name().c_str()
2292  << "\n";
2293  }
2294  }
2295  hinit = true;
2296  }
2297 
2298  // This always contains the rest of the line to parse. At the
2299  // beginning the entire line. Line gets shorter and shorter as we
2300  // continue to extract stuff from the beginning.
2301  String line;
2302 
2303  // Look for more comments?
2304  bool comment = true;
2305 
2306  while (comment) {
2307  // Return true if eof is reached:
2308  if (is.eof()) return true;
2309 
2310  // Throw runtime_error if stream is bad:
2311  if (!is) throw runtime_error("Stream bad.");
2312 
2313  // Read line from file into linebuffer:
2314  getline(is, line);
2315 
2316  // It is possible that we were exactly at the end of the file before
2317  // calling getline. In that case the previous eof() was still false
2318  // because eof() evaluates only to true if one tries to read after the
2319  // end of the file. The following check catches this.
2320  if (line.nelem() == 0 && is.eof()) return true;
2321 
2322  // @ as first character marks catalogue entry
2323  char c;
2324  extract(c, line, 1);
2325 
2326  // check for empty line
2327  if (c == '@') {
2328  comment = false;
2329  }
2330  }
2331 
2332  // read the arts identifier String
2333  istringstream icecream(line);
2334 
2335  String artsid;
2336  icecream >> artsid;
2337 
2338  if (artsid.length() != 0) {
2339  // ok, now for the cool index map:
2340  // is this arts identifier valid?
2341  const map<String, SpecIsoMap>::const_iterator i = ArtsMap.find(artsid);
2342  if (i == ArtsMap.end()) {
2343  ostringstream os;
2344  os << "ARTS Tag: " << artsid << " is unknown.";
2345  throw runtime_error(os.str());
2346  }
2347 
2348  SpecIsoMap id = i->second;
2349 
2350  // Set line ID
2351  mqid.SetSpecies(id.Speciesindex());
2352  mqid.SetIsotopologue(id.Isotopologueindex());
2353 
2354  // Extract center frequency:
2355  icecream >> mf;
2356 
2357  // Extract intensity:
2358  icecream >> mi0;
2359 
2360  // Extract reference temperature for Intensity in K:
2361  icecream >> mti0;
2362 
2363  // Extract lower state energy:
2364  icecream >> melow;
2365 
2366  // Extract Einstein A-coefficient:
2367  icecream >> ma;
2368 
2369  // Extract upper state stat. weight:
2370  icecream >> mgupper;
2371 
2372  // Extract lower state stat. weight:
2373  icecream >> mglower;
2374 
2376  mstandard = true;
2377 
2378  // Remaining entries are the quantum numbers
2379  String mquantum_numbers_str;
2380  getline(icecream, mquantum_numbers_str);
2381 
2382  mquantum_numbers_str.trim();
2383  // FIXME: OLE: Added this if to catch crash for species like CO, PH3
2384  // where the line in the catalog is too short. Better would be to
2385  // only read the n and j for Zeeman species, but we don't have that
2386  // information here
2387 
2388  if (species_data[mqid.Species()].Name() == "SO") {
2389  // Note that atoi converts *** to 0.
2392  Rational(atoi(mquantum_numbers_str.substr(0, 3).c_str())));
2395  Rational(atoi(mquantum_numbers_str.substr(6, 3).c_str())));
2398  Rational(atoi(mquantum_numbers_str.substr(3, 3).c_str())));
2401  Rational(atoi(mquantum_numbers_str.substr(9, 3).c_str())));
2402  }
2403 
2404  if (mquantum_numbers_str.nelem() >= 25) {
2405  if (species_data[mqid.Species()].Name() == "O2") {
2406  String vstr = mquantum_numbers_str.substr(0, 3);
2407  ArrayOfIndex v(3);
2408  for (Index vi = 0; vi < 3; vi++) {
2409  if (vstr[0] != ' ')
2410  extract(v[vi], vstr, 1);
2411  else
2412  v[vi] = -1;
2413  }
2414 
2415  if (v[2] > -1) {
2418  }
2419 
2420  String qstr1 = mquantum_numbers_str.substr(4, 12);
2421  String qstr2 = mquantum_numbers_str.substr(4 + 12 + 1, 12);
2422  ArrayOfIndex q(6);
2423  for (Index qi = 0; qi < 3; qi++) {
2424  if (qstr1.substr(0, 4) != " ")
2425  extract(q[qi], qstr1, 4);
2426  else
2427  q[qi] = -1;
2428  }
2429  for (Index qi = 3; qi < 6; qi++) {
2430  if (qstr2.substr(0, 4) != " ")
2431  extract(q[qi], qstr2, 4);
2432  else
2433  q[qi] = -1;
2434  }
2435 
2436  if (q[0] > -1)
2438  if (q[1] > -1)
2440  if (q[2] > -1)
2442  q[2] - Rational(1, 2));
2443  if (q[3] > -1)
2445  if (q[4] > -1)
2447  if (q[5] > -1)
2449  q[5] - Rational(1, 2));
2450  }
2451  }
2452  }
2453 
2454  // That's it!
2455  return false;
2456 }
2457 
2459  const Verbosity& verbosity) {
2460  CREATE_OUT3;
2461 
2462  // Global species lookup data:
2464 
2465  // We need a species index sorted by Arts identifier. Keep this in a
2466  // static variable, so that we have to do this only once. The ARTS
2467  // species index is ArtsMap[<Arts String>].
2468  static map<String, SpecIsoMap> ArtsMap;
2469 
2470  // Remember if this stuff has already been initialized:
2471  static bool hinit = false;
2472 
2473  mversion = 5;
2474 
2475  LineShape::Model line_mixing_model;
2476  bool lmd_found = false;
2477 
2478  if (!hinit) {
2479  out3 << " ARTS index table:\n";
2480 
2481  for (Index i = 0; i < species_data.nelem(); ++i) {
2482  const SpeciesRecord& sr = species_data[i];
2483 
2484  for (Index j = 0; j < sr.Isotopologue().nelem(); ++j) {
2485  SpecIsoMap indicies(i, j);
2486  String buf = sr.Name() + "-" + sr.Isotopologue()[j].Name();
2487 
2488  ArtsMap[buf] = indicies;
2489 
2490  // Print the generated data structures (for debugging):
2491  // The explicit conversion of Name to a c-String is
2492  // necessary, because setw does not work correctly for
2493  // stl Strings.
2494  const Index& i1 = ArtsMap[buf].Speciesindex();
2495  const Index& i2 = ArtsMap[buf].Isotopologueindex();
2496 
2497  out3 << " Arts Identifier = " << buf << " Species = " << setw(10)
2498  << setiosflags(ios::left) << species_data[i1].Name().c_str()
2499  << "iso = " << species_data[i1].Isotopologue()[i2].Name().c_str()
2500  << "\n";
2501  }
2502  }
2503  hinit = true;
2504  }
2505 
2506  // This always contains the rest of the line to parse. At the
2507  // beginning the entire line. Line gets shorter and shorter as we
2508  // continue to extract stuff from the beginning.
2509  String line;
2510 
2511  // Look for more comments?
2512  bool comment = true;
2513 
2514  while (comment) {
2515  // Return true if eof is reached:
2516  if (is.eof()) return true;
2517 
2518  // Throw runtime_error if stream is bad:
2519  if (!is) throw runtime_error("Stream bad.");
2520 
2521  // Read line from file into linebuffer:
2522  getline(is, line);
2523 
2524  // It is possible that we were exactly at the end of the file before
2525  // calling getline. In that case the previous eof() was still false
2526  // because eof() evaluates only to true if one tries to read after the
2527  // end of the file. The following check catches this.
2528  if (line.nelem() == 0 && is.eof()) return true;
2529 
2530  // @ as first character marks catalogue entry
2531  char c;
2532  extract(c, line, 1);
2533 
2534  // check for empty line
2535  if (c == '@') {
2536  comment = false;
2537  }
2538  }
2539 
2540  // read the arts identifier String
2541  istringstream icecream(line);
2542 
2543  try {
2544  String artsid;
2545  icecream >> artsid;
2546 
2547  if (artsid.length() != 0) {
2548  // ok, now for the cool index map:
2549  // is this arts identifier valid?
2550  const map<String, SpecIsoMap>::const_iterator i = ArtsMap.find(artsid);
2551  if (i == ArtsMap.end()) {
2552  ostringstream os;
2553  os << "ARTS Tag: " << artsid << " is unknown.";
2554  throw runtime_error(os.str());
2555  }
2556 
2557  SpecIsoMap id = i->second;
2558 
2559  // Set line ID:
2560  mqid.SetSpecies(id.Speciesindex());
2561  mqid.SetIsotopologue(id.Isotopologueindex());
2562 
2563  // Extract center frequency:
2564  icecream >> double_imanip() >> mf;
2565 
2566  // Extract intensity:
2567  icecream >> double_imanip() >> mi0;
2568 
2569  // Extract reference temperature for Intensity in K:
2570  icecream >> double_imanip() >> mti0;
2571 
2572  // Extract lower state energy:
2573  icecream >> double_imanip() >> melow;
2574 
2575  // Extract Einstein A-coefficient:
2576  icecream >> double_imanip() >> ma;
2577 
2578  // Extract upper state stat. weight:
2579  icecream >> double_imanip() >> mgupper;
2580 
2581  // Extract lower state stat. weight:
2582  icecream >> double_imanip() >> mglower;
2583 
2584  String token;
2585  Index nelem;
2586  icecream >> token;
2587 
2588  while (icecream) {
2589  // Read pressure broadening (LEGACY)
2590  if (token == "PB") {
2591  mstandard = true;
2593  icecream, mlineshapemodel, mqid);
2594  icecream >> token;
2595  } else if (token == "QN") {
2596  // Quantum numbers
2597 
2598  icecream >> token;
2599  if (token != "UP") {
2600  ostringstream os;
2601  os << "Unknown quantum number tag: " << token;
2602  throw std::runtime_error(os.str());
2603  }
2604 
2605  icecream >> token;
2606  Rational r;
2607  while (icecream) {
2609  icecream >> r;
2610  mqid.UpperQuantumNumbers().Set(token, r);
2611  icecream >> token;
2612  if (token == "LO") break;
2613  }
2614 
2615  if (!is || token != "LO") {
2616  std::ostringstream os;
2617  os << "Error in catalog. Lower quantum number tag 'LO' not found.";
2618  throw std::runtime_error(os.str());
2619  }
2620 
2621  icecream >> token;
2622  while (icecream && IsValidQuantumNumberName(token)) {
2623  icecream >> r;
2624  mqid.LowerQuantumNumbers().Set(token, r);
2625  icecream >> token;
2626  }
2627  } else if (token == "LM") // LEGACY
2628  {
2629  LineShape::from_linemixingdata(icecream, line_mixing_model);
2630  icecream >> token;
2631  lmd_found = true;
2632  } else if (token == "LF") {
2633  mstandard = true;
2635  icecream >> token;
2636  } else if (token == "LS") {
2637  mstandard = true;
2638  icecream >> mlineshapemodel;
2639  icecream >> token;
2640  } else if (token == "ZM") {
2641  // Zeeman effect
2642  icecream >> mzeemanmodel;
2643  icecream >> token;
2644  } else if (token == "LSM") {
2645  // Line shape modifications
2646 
2647  // Starts with the number of modifications
2648  icecream >> nelem;
2649  for (Index lsm = 0; lsm < nelem; lsm++) {
2650  icecream >> token;
2651 
2652  // cutoff frequency
2653  if (token == "CUT") {
2654  Numeric value = NAN;
2655  icecream >> double_imanip() >> value;
2656  mcutoff = value;
2657  }
2658 
2659  // linemixing pressure limit
2660  if (token == "LML") {
2661  Numeric value = NAN;
2662  icecream >> double_imanip() >> value;
2663  mlinemixing_limit = value;
2664  }
2665 
2666  // mirroring
2667  else if (token == "MTM") {
2668  String value;
2669  icecream >> value;
2670 
2672  }
2673 
2674  // line normalization
2675  else if (token == "LNT") {
2676  String value;
2677  icecream >> value;
2678 
2680  }
2681 
2682  else {
2683  ostringstream os;
2684  os << "Unknown line modifications given: " << token;
2685  throw std::runtime_error(os.str());
2686  }
2687  }
2688  icecream >> token;
2689  } else {
2690  ostringstream os;
2691  os << "Unknown line data tag: " << token;
2692  throw std::runtime_error(os.str());
2693  }
2694  }
2695  }
2696  } catch (const std::runtime_error& e) {
2697  ostringstream os;
2698  os << "Parse error in catalog line: " << endl;
2699  os << line << endl;
2700  os << e.what();
2701  throw std::runtime_error(os.str());
2702  }
2703 
2704  if (lmd_found)
2705  mlineshapemodel.SetLineMixingModel(line_mixing_model.Data()[0]);
2706 
2707  // That's it!
2708  return false;
2709 }
2710 
2711 ostream& operator<<(ostream& os, const LineRecord& lr) {
2712  // Determine the precision, depending on whether Numeric is double
2713  // or float:
2714  int precision;
2715 #ifdef USE_FLOAT
2716  precision = FLT_DIG;
2717 #else
2718 #ifdef USE_DOUBLE
2719  precision = DBL_DIG;
2720 #else
2721 #error Numeric must be double or float
2722 #endif
2723 #endif
2724 
2725  ostringstream ls;
2726 
2727  switch (lr.Version()) {
2728  case 5:
2729  ls << "@"
2730  << " " << lr.Name() << " " << setprecision(precision) << lr.F() << " "
2731  << lr.I0() << " " << lr.Ti0() << " " << lr.Elow() << " " << lr.A()
2732  << " " << lr.G_upper() << " " << lr.G_lower();
2733 
2734  // Write Pressure Broadening and Line Mixing
2735  { ls << " LS " << lr.GetLineShapeModel(); }
2736 
2737  // Write Quantum Numbers
2738  {
2739  Index nUpper = lr.UpperQuantumNumbers().nNumbers();
2740  Index nLower = lr.LowerQuantumNumbers().nNumbers();
2741 
2742  if (nUpper || nLower) {
2743  ls << " QN";
2744 
2745  if (nUpper) ls << " UP " << lr.UpperQuantumNumbers();
2746 
2747  if (nLower) ls << " LO " << lr.LowerQuantumNumbers();
2748  }
2749  }
2750 
2751  // Write Zeeman Effect Data
2752  ls << " ZM " << lr.ZeemanModel();
2753 
2754  // Line shape modifications
2755  {
2756  const Numeric CUT = lr.CutOff();
2757  const Numeric LML = lr.LineMixingLimit();
2758  const Index MTM = (Index)lr.GetMirroringType();
2759  const Index LNT = (Index)lr.GetLineNormalizationType();
2760 
2761  const bool need_cut = CUT > 0, need_lml = not(LML < 0), need_mtm = MTM,
2762  need_lnt = LNT;
2763 
2764  const Index nelem = (Index)need_cut + (Index)need_lml +
2765  (Index)need_mtm + (Index)need_lnt;
2766 
2767  if (nelem) {
2768  ls << " LSM " << nelem;
2769  if (need_cut) ls << " CUT " << CUT;
2770  if (need_lml) ls << " LML " << LML;
2771  if (need_mtm) ls << " MTM " << lr.GetMirroringTypeString();
2772  if (need_lnt) ls << " LNT " << lr.GetLineNormalizationTypeString();
2773  }
2774  }
2775 
2776  os << ls.str();
2777 
2778  break;
2779 
2780  default:
2781  os << "Unknown ARTSCAT version: " << lr.Version();
2782  break;
2783  }
2784 
2785  return os;
2786 }
2787 
2790  if (in == "NONE")
2791  mmirroring = MirroringType::None;
2792  else if (in == "LP")
2793  mmirroring = MirroringType::Lorentz;
2794  else if (in == "SAME")
2795  mmirroring = MirroringType::SameAsLineShape;
2796  else if (in == "MAN")
2797  mmirroring = MirroringType::Manual;
2798  else
2799  throw std::runtime_error("Cannot recognize the mirroring type");
2800  return mmirroring;
2801 }
2802 
2804  switch (mmirroring) {
2805  case MirroringType::None:
2806  return "NONE";
2808  return "LP";
2810  return "SAME";
2811  case MirroringType::Manual:
2812  return "MAN";
2813  }
2814  throw std::runtime_error(
2815  "Developer bug: Add new population types to GetMirroringTypeString");
2816 }
2817 
2820  if (in == "NONE")
2821  mlinenorm = LineNormalizationType::None;
2822  else if (in == "VVH")
2823  mlinenorm = LineNormalizationType::VVH;
2824  else if (in == "VVW")
2825  mlinenorm = LineNormalizationType::VVW;
2826  else if (in == "RQ")
2828  else
2829  throw std::runtime_error("Cannot recognize the normalization type");
2830  return mlinenorm;
2831 }
2832 
2834  switch (mlinenorm) {
2836  return "NONE";
2838  return "VVH";
2840  return "VVW";
2842  return "RQ";
2843  }
2844  throw std::runtime_error(
2845  "Developer bug: Add new population types to GetLineNormalizationTypeString");
2846 }
2847 
2850  if (in == "LTE")
2851  mpopulation = LinePopulationType::ByLTE;
2852  else if (in == "TV")
2854  else if (in == "ND")
2856  else
2857  throw std::runtime_error("Cannot recognize the population type");
2858  return mpopulation;
2859 }
2860 
2862  switch (mpopulation) {
2864  return "LTE";
2866  return "TV";
2868  return "ND";
2869  }
2870  throw std::runtime_error(
2871  "Developer bug: Add new population types to GetLinePopulationTypeString");
2872 }
Numeric Ti0() const
Reference temperature for I0 in K:
Definition: linerecord.h:375
void iso(Array< IsotopologueRecord >::iterator &ii, String name, const ArrayOfNumeric &coeff, const ArrayOfNumeric &temp_range, const Index &coefftype)
Initialize isotopologue and move iterator to next one.
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
QuantumIdentifier mqid
Definition: linerecord.h:1148
#define precision
Definition: logic.cc:43
const QuantumNumbers & UpperQuantumNumbers() const noexcept
Return the upper quantum numbers by const reference.
Definition: quantum.h:587
const SpeciesRecord & SpeciesData() const
The matching SpeciesRecord from species_data.
Definition: linerecord.cc:49
Numeric mgupper
Definition: linerecord.h:1178
bool mstandard
FIXME Richard, please explain.
Definition: linerecord.h:1190
MirroringType
Spectral line catalog data.
Definition: linerecord.h:201
std::istream & from_linefunctiondata(std::istream &data, Model &lsc)
Index nelem() const
Number of elements.
Definition: array.h:195
void Isotopologue(Index iso)
Set the Isotopologue.
Definition: quantum.h:487
Zeeman::Model mzeemanmodel
Zeeman effect model class.
Definition: linerecord.h:1193
LinePopulationType mpopulation
Line LTE/NLTE type.
Definition: linerecord.h:1208
Numeric mti0
Definition: linerecord.h:1157
LineNormalizationType
Definition: linerecord.h:210
bool ReadFromArtscat3Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with an ARTSCAT-3 file.
Definition: linerecord.cc:2069
The Vector class.
Definition: matpackI.h:860
const QuantumNumbers & LowerQuantumNumbers() const
Definition: linerecord.h:476
const IsotopologueRecord & IsotopologueData() const
The matching IsotopologueRecord from species_data.
Definition: linerecord.cc:55
Main line shape model class.
void SetLineNormalizationType(const LineNormalizationType in)
Definition: linerecord.h:792
LinePopulationType LinePopulationTypeFromString(const String &in)
Definition: linerecord.cc:2848
This file contains basic functions to handle ASCII files.
Numeric Elow() const
Lower state energy in cm^-1:
Definition: linerecord.h:378
LineShape::Model & GetLineShapeModel()
Definition: linerecord.h:573
const Numeric TORR2PA
Global constant, converts torr to Pa.
const std::vector< SingleSpeciesModel > & Data() const noexcept
const Array< SpeciesRecord > species_data
Species Data.
Numeric G_upper() const
ARTSCAT-4/5 Upper state stat.
Definition: linerecord.h:449
const Array< IsotopologueRecord > & Isotopologue() const
Definition: absorption.h:199
std::istream & from_artscat4(std::istream &is, Model &lsc, const QuantumIdentifier &qid)
Parser for quantum numbers from HITRAN 2004 and later.
const QuantumNumbers & UpperQuantumNumbers() const
Definition: linerecord.h:479
Numeric melow
Definition: linerecord.h:1160
void ThrowIfQuantumNumberNameInvalid(String name)
Check for valid quantum number name and throws if it is invalid.
Definition: quantum.cc:168
Index Version() const
Return the version number.
Definition: linerecord.h:304
_CS_string_type str() const
Definition: sstream.h:491
String GetLinePopulationTypeString() const
Definition: linerecord.cc:2861
String Name() const
The full name of the species and isotopologue.
Definition: linerecord.cc:42
Numeric mcutoff
Cutoff frequency.
Definition: linerecord.h:1196
void Species(Index sp)
Set the Species.
Definition: quantum.h:481
Implements rational numbers to work with other ARTS types.
Definition: rational.h:54
String GetMirroringTypeString() const
Definition: linerecord.cc:2803
Numeric mi0
Definition: linerecord.h:1154
Contains the lookup data for one species.
Definition: absorption.h:144
#define CREATE_OUT1
Definition: messages.h:205
void extract(T &x, String &line, Index n)
Extract something from the beginning of a string.
Definition: mystring.h:297
Zeeman::Model ZeemanModel() const
Definition: linerecord.h:772
Numeric A() const
ARTSCAT-4/5 Einstein A-coefficient in 1/s :
Definition: linerecord.h:410
String VersionString() const
Return the version String.
Definition: linerecord.cc:36
void SetLineMixingModel(SingleSpeciesModel x)
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Index nelem() const
Number of elements.
Definition: mystring.h:246
const String & Name() const
Definition: absorption.h:197
Declarations required for the calculation of absorption coefficients.
bool ReadFromJplStream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with a JPL file.
Definition: linerecord.cc:1843
String GetLineNormalizationTypeString() const
Definition: linerecord.cc:2833
Numeric pow(const Rational base, Numeric exp)
Power of.
Definition: rational.h:628
std::istream & from_linemixingdata(std::istream &data, Model &lsc)
Legacy reading of old deprecated LineMixingData class.
void trim()
Trim leading and trailing whitespace.
Definition: mystring.h:225
void Set(Index qn, Rational r)
Set quantum number at position.
Definition: quantum.h:310
LineNormalizationType mlinenorm
Line shape normalization type.
Definition: linerecord.h:1205
basic_ostringstream< char, string_char_traits< char >, alloc > ostringstream
Definition: sstream.h:204
Contains the lookup data for one isotopologue.
Definition: absorption.h:45
LinePopulationType
Definition: linerecord.h:220
void SetMirroringType(const MirroringType in)
Definition: linerecord.h:785
const QuantumNumbers & LowerQuantumNumbers() const noexcept
Return the lower quantum numbers by const reference.
Definition: quantum.h:592
Numeric mf
Definition: linerecord.h:1151
bool ReadFromArtscat4Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with an ARTSCAT-4 file.
Definition: linerecord.cc:2253
ostream & operator<<(ostream &os, const LineRecord &lr)
Output operator for LineRecord.
Definition: linerecord.cc:2711
Parser for quantum number strings from HITRAN 2004 and later.
const Numeric & LineMixingLimit() const
Line mixing pressure limit.
Definition: linerecord.h:780
Numeric ma
Definition: linerecord.h:1175
void Parse(QuantumIdentifier &qid, const String &quantum_string) const
Parse quantum numbers from string.
#define max(a, b)
bool ReadFromLBLRTMStream(istream &is, const Verbosity &verbosity)
LBLRTM uses the same format as HITRAN pre-2004 but also carry line mixing data, so we must read it se...
Definition: linerecord.cc:466
Numeric mlinemixing_limit
Line mixing pressure limit.
Definition: linerecord.h:1199
std::istream & from_pressurebroadeningdata(std::istream &data, Model &lsc, const QuantumIdentifier &qid)
Index nelem(const Lines &l)
Number of lines.
LineNormalizationType LineNormalizationTypeFromString(const String &in)
Definition: linerecord.cc:2818
LineRecord class for managing line catalog data.
Numeric G_lower() const
ARTSCAT-4/5 Lower state stat.
Definition: linerecord.h:452
bool IsValidQuantumNumberName(String name)
Check for valid quantum number name.
Definition: quantum.cc:164
#define q
const Index & Speciesindex() const
Definition: absorption.h:345
Index nNumbers() const
The number of defined quantum numbers.
Definition: quantum.h:344
bool ReadFromArtscat5Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with an ARTSCAT-5 file.
Definition: linerecord.cc:2458
#define CREATE_OUT0
Definition: messages.h:204
#define CREATE_OUT3
Definition: messages.h:207
LineShape::Model mlineshapemodel
Line function data (pressure broadening and line mixing)
Definition: linerecord.h:1187
const Numeric ATM2PA
Global constant, converts atm to Pa.
MirroringType mmirroring
Line shape mirroring effect type.
Definition: linerecord.h:1202
Numeric I0() const
The line intensity in m^2*Hz at the reference temperature Ti0.
Definition: linerecord.h:369
Numeric mglower
Definition: linerecord.h:1181
MirroringType MirroringTypeFromString(const String &in)
Definition: linerecord.cc:2788
const LineNormalizationType & GetLineNormalizationType() const
Line shape normalization factor.
Definition: linerecord.h:789
const Numeric & CutOff() const
Cutoff frequency.
Definition: linerecord.h:776
const Numeric SPEED_OF_LIGHT
bool ReadFromHitran2004Stream(istream &is, const Verbosity &verbosity, const Numeric fmin=0)
Read one line from a stream associated with a HITRAN 2004 file.
Definition: linerecord.cc:1020
bool ReadFromHitran2001Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with a HITRAN 1986-2001 file.
Definition: linerecord.cc:61
Numeric F() const
The line center frequency in Hz.
Definition: linerecord.h:349
Index mversion
Definition: linerecord.h:1145
Input manipulator class for doubles to enable nan and inf parsing.
Definition: file.h:117
bool ReadFromMytran2Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with a MYTRAN2 file.
Definition: linerecord.cc:1464
Numeric wavenumber_to_joule(Numeric e)
A little helper function to convert energy from units of wavenumber (cm^-1) to Joule (J)...
Definition: absorption.cc:500
const MirroringType & GetMirroringType() const
Line shape mirroring factor.
Definition: linerecord.h:784