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