예제 #1
0
  def getpf(self, verbose):
    """                                    
    Calculate the partition function for a grid of temperatures for
    HITRAN molecules.

    Notes:
    ------
    This function is a wrapper of the TIPS library written by
    Patricio Cubillos, which is itself a C implementation of the
    Fortran TIPS routine by R. R. Gamache.
    The range of temperatures is limited to: 70K -- 3000K.

    Parameters:
    -----------
    verbose: Integer
       Verbosity threshold.

    Returns:
    --------
    Temp: 1D float ndarray
       The array of temeratures where the partition function was evaluated.
    PF: 2D float ndarray
       A 2D array (N temperatures, N isotopes) with the partition
       function values for each isotope (columns) as function of temperature
       (first column).

    Modification History:
    ---------------------
    2012-11-22  patricio  Initial implementation.  [email protected]
    2014-03-10  patricio  Adapted previous code.
    2015-06-29  aj-foster Swapped Fortran for C implementation of TIPS.
    """

    # Get molecule ID as  integer:
    molID = int(self.molID)
 
    # Get Number of isotopes:
    Niso = len(self.isotopes)

    # Array of temperatures:
    Temp = np.arange(70.0, 3000.1, 10)
    # TIPS range of temperature is: [70K, 3000K]
    Ntemp = len(Temp)

    # Output array for table of Temperature and PF values: 
    PF = np.zeros((Niso, Ntemp), np.double)
    ut.lrprint(verbose-14, "Temperature sample:\n" + str(Temp))
    ut.lrprint(verbose-5, "Ntemp: %d, Niso: %d"%(Ntemp, Niso))

    for i in np.arange(Niso):

      # Molecule ID, isotope ID, and temperature arrays:
      mol = np.repeat(molID, len(Temp))
      iso = np.repeat(int(self.isotopes[i]), len(Temp))

      # Call TIPS with the given arrays:
      PF[i] = tips.tips(mol, iso, Temp)

    return Temp, PF
예제 #2
0
    def getpf(self, verbose):
        """                                    
    Calculate the partition function for a grid of temperatures for
    HITRAN molecules.

    Notes:
    ------
    This function is a wrapper of the TIPS library written by
    Patricio Cubillos, which is itself a C implementation of the
    Fortran TIPS routine by R. R. Gamache.
    The range of temperatures is limited to: 70K -- 3000K.

    Parameters:
    -----------
    verbose: Integer
       Verbosity threshold.

    Returns:
    --------
    Temp: 1D float ndarray
       The array of temeratures where the partition function was evaluated.
    PF: 2D float ndarray
       A 2D array (N temperatures, N isotopes) with the partition
       function values for each isotope (columns) as function of temperature
       (first column).

    Modification History:
    ---------------------
    2012-11-22  patricio  Initial implementation.  [email protected]
    2014-03-10  patricio  Adapted previous code.
    2015-06-29  aj-foster Swapped Fortran for C implementation of TIPS.
    """

        # Get molecule ID as  integer:
        molID = int(self.molID)

        # Get Number of isotopes:
        Niso = len(self.isotopes)

        # Array of temperatures:
        Temp = np.arange(70.0, 3000.1, 10)
        # TIPS range of temperature is: [70K, 3000K]
        Ntemp = len(Temp)

        # Output array for table of Temperature and PF values:
        PF = np.zeros((Niso, Ntemp), np.double)
        ut.lrprint(verbose - 14, "Temperature sample:\n" + str(Temp))
        ut.lrprint(verbose - 5, "Ntemp: %d, Niso: %d" % (Ntemp, Niso))

        for i in np.arange(Niso):

            # Molecule ID, isotope ID, and temperature arrays:
            mol = np.repeat(molID, len(Temp))
            iso = np.repeat(int(self.isotopes[i]), len(Temp))

            # Call TIPS with the given arrays:
            PF[i] = tips.tips(mol, iso, Temp)

        return Temp, PF
예제 #3
0
    def getpf(self, verbose):
        """
    Open, read, and store values from the partition function file.
 
    Parameters:
    -----------
    verbose: Integer
      Verbosity threshold.
 
    Returns:
    --------
    Temp: 1D ndarray
       An array with the tabulated temperatures at which the PF is evaluated
    PF: 2D ndarray
       A 2D array (N isotopes, N temperatures) with the partition
      function values for each isotope as function of temperature

    Modification History:
    ---------------------
    2013        madison   Initial version based on P. Rojo's C code.
                                                [email protected]
    2014-03-05  patricio  Added documentation.  [email protected]
    2014-03-08  patricio  Moved to pands.py
    2014-03-10  patricio  Added DBname return.
    2014-03-24  patricio  Rewritten as subclass of dbdriver.
    """
        ut.lrprint(verbose, "Parsing the partition function file.")
        # Open and read partition function file:
        partDB = open(self.pffile)
        PFlines = partDB.readlines()
        partDB.close()

        # Skip header lines (first 5 lines):
        PFlines = PFlines[self.pf_ignore:]
        # Number of Temperatures (number of lines):
        Ntemp = len(PFlines)
        # Number of isotopes:
        Niso = len(PFlines[0].split()) - 1

        # Allocate array for table of temperatures:
        Temp = np.zeros(Ntemp, np.double)
        # Allocate array for table of PF values:
        PF = np.zeros((Niso, Ntemp), np.double)

        for i in np.arange(Ntemp):
            values = PFlines[i].split()
            # Store values in arrays (automatic casting, so much wow!):
            Temp[i] = values[0]
            PF[:, i] = values[1:]
            ut.lrprint(verbose - 15, "Reading line %d: T=%4d." % (i, Temp[i]))

        return Temp, PF
예제 #4
0
    def getpf(self, verbose):
        """                                    
    Calculate the partition function for a grid of temperatures for
    HITRAN molecules.

    Notes:
    ------
    This function is a wrapper of the TIPS library written by
    Patricio Cubillos, which is itself a C implementation of the
    Fortran TIPS routine by R. R. Gamache.
    The range of temperatures is limited to: 70K -- 3000K.

    Parameters:
    -----------
    verbose: Integer
       Verbosity threshold.

    Returns:
    --------
    Temp: 1D float ndarray
       The array of temeratures where the partition function was evaluated.
    PF: 2D float ndarray
       A 2D array (N temperatures, N isotopes) with the partition
       function values for each isotope (columns) as function of temperature
       (first column).
    """
        ut.lrprint(verbose, "Parsing the partition function file.")
        # Open and read partition function file:
        partDB = open(self.pffile)
        PFlines = partDB.readlines()
        partDB.close()

        # Skip header lines (first 5 lines):
        PFlines = PFlines[2:]
        # Number of Temperatures (number of lines):
        Ntemp = len(PFlines)
        # Number of isotopes:
        Niso = len(PFlines[0].split()) - 1

        # Allocate array for table of temperatures:
        Temp = np.zeros(Ntemp, np.double)
        # Allocate array for table of PF values:
        PF = np.zeros((Niso, Ntemp), np.double)

        for i in np.arange(Ntemp):
            values = PFlines[i].split()
            # Store values in arrays (automatic casting, so much wow!):
            Temp[i] = values[0]
            PF[:, i] = values[1:]
            ut.lrprint(verbose - 15, "Reading line %d: T=%4d." % (i, Temp[i]))

        return Temp, PF
예제 #5
0
  def getpf(self, verbose):
    """
    Open, read, and store values from the partition function file.
 
    Parameters:
    -----------
    verbose: Integer
      Verbosity threshold.
 
    Returns:
    --------
    Temp: 1D ndarray
       An array with the tabulated temperatures at which the PF is evaluated
    PF: 2D ndarray
       A 2D array (N isotopes, N temperatures) with the partition
      function values for each isotope as function of temperature

    Modification History:
    ---------------------
    2013        madison   Initial version based on P. Rojo's C code.
                                                [email protected]
    2014-03-05  patricio  Added documentation.  [email protected]
    2014-03-08  patricio  Moved to pands.py
    2014-03-10  patricio  Added DBname return.
    2014-03-24  patricio  Rewritten as subclass of dbdriver.
    """
    ut.lrprint(verbose, "Parsing the partition function file.")
    # Open and read partition function file:
    partDB = open(self.pffile)
    PFlines = partDB.readlines()
    partDB.close()
 
    # Skip header lines (first 5 lines):
    PFlines = PFlines[self.pf_ignore:]
    # Number of Temperatures (number of lines):
    Ntemp = len(PFlines)
    # Number of isotopes:
    Niso  = len(PFlines[0].split()) - 1

    # Allocate array for table of temperatures:
    Temp = np.zeros(Ntemp, np.double)
    # Allocate array for table of PF values:
    PF = np.zeros((Niso, Ntemp), np.double)
 
    for i in np.arange(Ntemp):
      values = PFlines[i].split()
      # Store values in arrays (automatic casting, so much wow!):
      Temp[i]  = values[0]
      PF[:, i] = values[1:]
      ut.lrprint(verbose-15, "Reading line %d: T=%4d."%(i, Temp[i]))
 
    return Temp, PF
예제 #6
0
    def getpf(self, verbose):
        """
    Open, read, and store values from the partition function file.
 
    Parameters:
    -----------
    verbose: Integer
      Verbosity threshold.
 
    Returns:
    --------
    Temp: 1D ndarray
       An array with the tabulated temperatures at which the PF is evaluated
    PF: 2D ndarray
       A 2D array (N isotopes, N temperatures) with the partition
      function values for each isotope as function of temperature

    Modification History:
    ---------------------
    2012-11-30  patricio  Initial implementation.  [email protected]
    2014-03-11  patricio  Adapted to work with pylineread.
    2014-03-24  patricio  Rewritten as subclass of dbdriver. 
    """
        # Open and read the partition function file:
        partDB = open(self.pffile)
        PFlines = partDB.readlines()
        partDB.close()

        # Skip header lines (first 5 lines):
        PFlines = PFlines[self.pf_ignore:]
        # Number of Temperatures (number of lines):
        Ntemp = len(PFlines)
        # Number of isotopes:
        Niso = len(PFlines[0].split()) - 1

        # Allocate array for table of temperatures:
        Temp = np.zeros(Ntemp, np.double)
        # Allocate array for table of PF values:
        PF = np.zeros((Niso, Ntemp), np.double)

        for i in np.arange(Ntemp):
            values = PFlines[i].split()
            # Store values in array:
            Temp[i] = values[0]
            PF[:, i] = values[1:]
            ut.lrprint(verbose - 15, "Reading line %d: T=%4d." % (i, Temp[i]))

        return Temp, PF
예제 #7
0
  def getpf(self, verbose):
    """
    Open, read, and store values from the partition function file.
 
    Parameters:
    -----------
    verbose: Integer
      Verbosity threshold.
 
    Returns:
    --------
    Temp: 1D ndarray
       An array with the tabulated temperatures at which the PF is evaluated
    PF: 2D ndarray
       A 2D array (N isotopes, N temperatures) with the partition
      function values for each isotope as function of temperature

    Modification History:
    ---------------------
    2012-11-30  patricio  Initial implementation.  [email protected]
    2014-03-11  patricio  Adapted to work with pylineread.
    2014-03-24  patricio  Rewritten as subclass of dbdriver. 
    """
    # Open and read the partition function file:
    partDB = open(self.pffile)
    PFlines = partDB.readlines()
    partDB.close()

    # Skip header lines (first 5 lines):
    PFlines = PFlines[self.pf_ignore:]
    # Number of Temperatures (number of lines):
    Ntemp = len(PFlines)
    # Number of isotopes:
    Niso  = len(PFlines[0].split()) - 1

    # Allocate array for table of temperatures:
    Temp = np.zeros(Ntemp, np.double)
    # Allocate array for table of PF values:
    PF = np.zeros((Niso, Ntemp), np.double)
 
    for i in np.arange(Ntemp):
      values = PFlines[i].split()
      # Store values in array:
      Temp[i]  = values[0]
      PF[:, i] = values[1:]
      ut.lrprint(verbose-15, "Reading line %d: T=%4d."%(i, Temp[i]))
 
    return Temp, PF
예제 #8
0
    def dbread(self, iwl, fwl, verbose, *args):
        """
    Read a HITRAN or HITEMP database (dbfile) between wavelengths iwl and fwl.

    Parameters:
    -----------
    dbfile: String
       A HITRAN or HITEMP database filename.
    iwl: Scalar
       Initial wavelength limit (in microns).
    fwl: Scalar
       Final wavelength limit (in microns).
    verbose: Integer
       Verbosity threshold.
    pffile: String
       Partition function filename.

    Returns:
    --------
    wlength: 1D ndarray (double)
      Line-transition central wavelength (microns).
    gf: 1D ndarray (double)
      gf value (unitless).
    elow: 1D ndarray (double)
      Lower-state energy (cm^-1).
    isoID: 2D ndarray (integer)
      Isotope index (1, 2, 3, ...).

    Modification History:
    ---------------------
    2012-12-10  patricio  Initial implementation.  [email protected]
    2014-03-10  patricio  Adapted for pylineread.
    2014-07-06  patricio  Updated to return 1D arrays.
    """
        # Open HITRAN file for reading:
        data = open(self.dbfile, "rb")
        # Get Total number of transitions in file:
        data.seek(0, 2)
        nlines = data.tell() // 28

        # Rewrite wavelength limits as given in HITRAN file:
        fwn = 1.0 / (iwl * c.MTC)  # Microns to centimeters
        iwn = 1.0 / (fwl * c.MTC)  # Microns to centimeters

        # Find the record index for iwn and fwn:
        irec_init = self.binsearch(data, iwn, 0, nlines - 1, 0)
        irec_fin = self.binsearch(data, fwn, irec_init, nlines - 1, 1)

        # Allocates arrays for values to extract:
        wnumber = np.zeros(irec_fin - irec_init + 1, np.double)
        gf = np.zeros(irec_fin - irec_init + 1, np.double)
        elow = np.zeros(irec_fin - irec_init + 1, np.double)
        isoID = np.zeros(irec_fin - irec_init + 1, int)

        i = 0  # Stored record index
        chk = 0
        interval = (irec_fin - irec_init) // 20  # Check-point interval
        while irec_init + i <= irec_fin:
            data.seek((irec_init + i) * 28)
            wnumber[i], elow[i], gf[i], isoID[i] = struct.unpack(
                'dddi', data.read(28))
            # Print a checkpoint statement every 1/20th interval
            if verbose > 1:
                if (i % interval) == 0.0:
                    ut.lrprint(verbose - 1, "checkpoint %d/20..." % chk)
                    chk += 1
            i += 1

        data.close()
        isoID = np.array([self.iso_dict[iso] for iso in isoID])
        return 1e4 / wnumber, gf, elow, isoID
예제 #9
0
    def dbread(self, iwl, fwl, verbose, *args):
        """
    Read a HITRAN or HITEMP database (dbfile) between wavelengths iwl and fwl.

    Parameters:
    -----------
    dbfile: String
       A HITRAN or HITEMP database filename.
    iwl: Scalar
       Initial wavelength limit (in microns).
    fwl: Scalar
       Final wavelength limit (in microns).
    verbose: Integer
       Verbosity threshold.
    pffile: String
       Partition function filename.

    Returns:
    --------
    wlength: 1D ndarray (double)
      Line-transition central wavelength (microns).
    gf: 1D ndarray (double)
      gf value (unitless).
    elow: 1D ndarray (double)
      Lower-state energy (cm^-1).
    isoID: 2D ndarray (integer)
      Isotope index (1, 2, 3, ...).

    Modification History:
    ---------------------
    2012-12-10  patricio  Initial implementation.  [email protected]
    2014-03-10  patricio  Adapted for pylineread.
    2014-07-06  patricio  Updated to return 1D arrays.
    """
        # Open HITRAN file for reading:
        if six.PY2:
            data = open(self.dbfile, "r")
        else:
            data = open(self.dbfile, "r", newline='\n')
        # Read first line to get the record size:
        data.seek(0)
        line = data.readline()
        self.recsize = len(line)
        # Get Total number of transitions in file:
        data.seek(0, 2)
        nlines = data.tell() // self.recsize
        # Get Molecule ID:
        molID = int(self.molID)

        # Rewrite wavelength limits as given in HITRAN file:
        fwn = 1.0 / (iwl * c.MTC)  # Microns to centimeters
        iwn = 1.0 / (fwl * c.MTC)  # Microns to centimeters

        # Find the record index for iwn and fwn:
        irec_init = self.binsearch(data, fwn, 0, nlines - 1, 1)
        irec_fin = self.binsearch(data, iwn, 0, irec_init, 0)

        # Allocates arrays for values to extract:
        wlength = np.zeros(irec_init - irec_fin + 1, np.double)
        gf = np.zeros(irec_init - irec_fin + 1, np.double)
        elow = np.zeros(irec_init - irec_fin + 1, np.double)
        isoID = np.zeros(irec_init - irec_fin + 1, int)
        # Einstein A coefficient:
        A21 = np.zeros(irec_init - irec_fin + 1, np.double)
        # Lower statistical weight:
        g2 = np.zeros(irec_init - irec_fin + 1, np.double)
        # Line intensity, used to calculate gf:
        S0 = np.zeros(irec_init - irec_fin + 1, np.double)
        # Wavenumber:
        wnumber = np.zeros(irec_init - irec_fin + 1, np.double)

        # Get the partition function at T0:
        PFzero = self.PFzero()

        i = 0  # Stored record index
        chk = 0
        interval = (irec_fin - irec_init) // 20  # Check-point interval
        while irec_init - i >= irec_fin:
            data.seek((irec_init - i) * self.recsize)
            # Read in wavenumber
            line = data.read(self.recsize)
            # Get the isotope index:
            isoID[i] = float(line[self.recisopos:self.recwnpos])
            # Get the wavenumber:
            wnumber[i] = float(line[self.recwnpos:self.reclinpos])
            # Get the line intensity:
            S0[i] = float(line[self.reclinpos:self.reclinend])
            # Get Elow:
            elow[i] = float(line[self.recelpos:self.recelend])
            A21[i] = float(line[self.recApos:self.recairpos])
            g2[i] = float(line[self.recg2pos:self.recsize])
            # Print a checkpoint statement every 1/20th interval
            if verbose > 1:
                pos = data.tell() / self.recsize
                if (pos / interval) % 1 == 0.0:
                    chk += 1
                    ut.lrprint(verbose - 1, "checkpoint %d/20..." % chk)
                    ut.lrprint(
                        verbose - 3, "Wavenumber: %s, S0: %s, Elow: "
                        "%s" % (wnumber[i], S0[i], elow[i]))
                    ut.lrprint(
                        verbose - 2,
                        "Wavelength: %.3f, IsoID: %d, Elow: %.3f" %
                        (1.0 / (wnumber[i] * c.MTC), isoID[i], elow[i]))
            i += 1

        # Calculate the wavelength in microns:
        wlength[:] = 1.0 / (wnumber * c.MTC)
        # Set isotopic index to start counting from 0:
        isoID -= 1
        isoID[np.where(isoID < 0)] = 9  # 10th isotope had index 0 --> 10-1=9
        # Calculate gf:
        Ia = np.asarray(self.isoratio)
        gf = (S0 * c.C1 * PFzero[isoID] / Ia[isoID] *
              np.exp(c.C2 * elow / self.T0) /
              (1.0 - np.exp(-c.C2 * wnumber / self.T0)))
        # Alternative way:
        gf2 = A21 * g2 * c.C1 / (8.0 * np.pi * sc.c * 100.0) / wnumber**2.0

        # FINDME: Delete me when gf-vs-gf2 issue solved.
        # print(gf)
        # print(gf2)
        # print((gf/gf2)[:20])
        # print(isoID[:20])
        # print(np.amax(gf/gf2), np.amin(gf/gf2))
        # import matplotlib.pyplot as plt
        # plt.figure(1)
        # plt.plot(isoID, gf/gf2, "b,")
        # plt.ylim(0,4)
        # plt.xlim(-0.5, 5.5)
        # plt.savefig("gf.png")
        # plt.figure(2)
        # print(np.shape(self.gi), np.shape(PFzero))
        # ggi = np.asarray(self.gi)[isoID]
        # plt.plot(ggi, gf2/gf, "b,")
        # plt.plot([0,12], [0,12], "r")
        # plt.ylim(0,15)
        # plt.xlim(-0.5, 12.5)
        # plt.savefig("gf2.png")

        ut.lrprint(verbose - 14, "GF values: " + str(gf))
        data.close()
        return wlength, gf2, elow, isoID
  def dbread(self, iwl, fwl, verbose, procnum, return_dict, *args):
    """
    Read the B. Plez VO database between the wavelengths iwl and fwl.
 
    Parameters:
    -----------
    iwl: Scalar
       Initial wavelength limit (in microns).
    fwl: Scalar
       Final wavelength limit (in microns).
    verbose: Integer
       Verbosity threshold.
    procnum: Integer
       Index of the process which calls the function
    return_dict: Dict
       Dictionary to contain return values (indexed by process number)
    args:
       Additional arguments, not needed for voplez.
 
    Returns:
    --------
    wlength: 1D ndarray (double)
      Line-transition central wavelength (microns).
    gf: 1D ndarray (double)
      gf value (unitless).
    elow: 1D ndarray (double)
      Lower-state energe (centimeter^-1).
    isoID: 2D ndarray (integer)
      Isotope index (1, 2, 3, ...).

    Modification History:
    ---------------------
    2012-11-30  patricio  Initial implementation.  [email protected]
    """
 
    # Open the file:
    data = open(self.dbfile, "r")
    data.seek(0, 2)
    nlines   = data.tell() / self.recsize

    # Find the record index for iwl and fwl:
    irec_init = self.binsearch(data, iwl, 0,         nlines-1, 1)
    irec_fin  = self.binsearch(data, fwl, irec_init, nlines-1, 0)

    # Number of records to read:
    nread = irec_fin - irec_init + 1

    # Store data in two arrays for doubles and integers:
    # For Wavelength, Elow, and log(gf):
    wlength = np.zeros(nread, np.double)
    gf      = np.zeros(nread, np.double)
    elow    = np.zeros(nread, np.double)
    # For Isotope index:
    isoID   = np.zeros(nread,     int)
 
    ut.lrprint(verbose, "Beginning to read Plez VO database, between "
                        "records %d and %d."%(irec_init, irec_fin))
    # When the wavelength surpasses the max wavelength, stop the loop
    chk = 1  # Check-point counter
    i   = 0  # Stored record index
    interval = float((irec_fin - irec_init)/20)  # Check-point interval

    wnumber = np.zeros(nread)
    gf      = np.zeros(nread)
    elow    = np.zeros(nread)

    while (i < nread):
      # Read a record:
      data.seek((irec_init+i) * self.recsize)
      line = data.read(self.recsize)
      wnumber[i] = float(line[self.recwnpos:self.recwnend])
      gf     [i] = float(line[self.recgfpos:self.recgfend])
      elow   [i] = float(line[self.recelpos:self.recelend])

      # Print a checkpoint statement every 1/20th interval:
      if verbose > 1:
        pos = float(data.tell()/self.recsize)
        if (pos/interval)%1 == 0.0:
          ut.lrprint(verbose-1, "checkpoint %d/20..."%chk)
          chk += 1
          ut.lrprint(verbose-3, "Wavenumber (cm-1): {:.2f}, Elow (eV): {:.3f}, "
                     "gf: {:.4e}".format(wnumber[i], elow[i], gf[i]))
          ut.lrprint(verbose-2, "Wavelength (um): {:.3f},  IsoID: {:d},  "
                     "Elow (cm-1): {:.5e}, gf: {:.5e}".
                     format(1.0/(wnumber[i]*c.MTC), isoID[i],
                            elow[i]*c.eV2kayser, gf[i]))
      i += 1

    # Convert wavelength to TLI format (microns):
    wlength[:] = 1.0 / (wnumber * c.MTC)
    # Convert Elow from eV to cm-1:
    elow[:] = elow * c.eV2kayser

    ut.lrprint(verbose, "Done.\n")
    data.close()
    return_dict[procnum] = (wlength, gf, elow, isoID)
    return wlength, gf, elow, isoID
예제 #11
0
  # Number of files:
  Nfiles = len(dblist)
  # Driver routine to read the databases:
  driver = []
  for i in np.arange(Nfiles):
    if   dbtype[i] == "ps":
      driver.append(ps.pands(dblist[i],       pflist[i]))
    elif dbtype[i] == "hit":
      driver.append(hit.hitran(dblist[i],     pflist[i]))
    elif dbtype[i] == "ts":
      driver.append(ts.tioschwenke(dblist[i], pflist[i]))
    elif dbtype[i] == "vo":
      driver.append(vo.voplez(dblist[i],      pflist[i]))
    else:
      ut.printexit("Unknown Database type (%d): '%s'"%(i+1, dbtype[i]))
    ut.lrprint(verbose-10, "File %d, database name: '%s'"%(i+1, driver[i].name))

  ut.lrprint(verbose, "Beginning to write the TLI file: '%s'"%outputfile)
  # Open output file:
  TLIout  = open(outputfile, "wb")

  # Get the machine endian type (big/little):
  endianness = sys.byteorder

  # Hardcoded implementation of lineread's "magic number" check for endianness
  # derived from binary encoding the letters TLI into binary location
  # and checking the order
  if endianness == 'big':
    magic = '\xab\xb3\xb6\xff'
  if endianness == 'little':
    magic = '\xff\xb6\xb3\xab'
예제 #12
0
    def dbread(self, iwl, fwl, verbose, *args):
        """
    Read the Partridge and Schwenke H2O database (dbfile) between the
    wavelengths iwl and fwl.
 
    Parameters:
    -----------
    iwl: Scalar
       Initial wavelength limit (in microns).
    fwl: Scalar
       Final wavelength limit (in microns).
    verbose: Integer
       Verbosity threshold.
    args:
       Additional arguments, not needed for pands.
 
    Returns:
    --------
    wlength: 1D ndarray (double)
      Line-transition central wavelength (microns).
    gf: 1D ndarray (double)
      gf value (unitless).
    elow: 1D ndarray (double)
      Lower-state energy (cm^-1).
    isoID: 2D ndarray (integer)
      Isotope index (1, 2, 3, ...).

    Modification History:
    ---------------------
    2012-11-30  patricio  Initial implementation.  [email protected]
    2014-03-11  patricio  Adapted to work with pylineread.
    2014-03-24  patricio  Rewritten as subclass of dbdriver.
    2014-07-06  patricio  Updated return statement.
    2014-09-23  patricio  Updated for pylineread 5.0.
    """

        # Open the file:
        data = open(self.dbfile, "rb")

        # Get the number of lines in the file:
        data.seek(0, 2)  # Set pointer at the file's end
        nlines = data.tell(
        ) // self.recsize  # Number of lines (bytes/record_size)

        # Rewrite wavelength limits as given in the Database file:
        iwav = iwl * c.MTC / c.NTC  # Microns to nanometer
        fwav = fwl * c.MTC / c.NTC
        iwav = np.log(iwav) / self.ratiolog
        fwav = np.log(fwav) / self.ratiolog

        # Find the positions of iwl and fwl:
        irec = self.binsearch(data, iwav, 0, nlines - 1, 0)
        frec = self.binsearch(data, fwav, irec, nlines - 1, 1)
        nread = frec - irec + 1  # Number of records to read

        # Store data in two arrays for doubles and integers:
        # For Wavelength, Elow, and log(gf):
        wlength = np.zeros(nread, np.double)
        gf = np.zeros(nread, np.double)
        elow = np.zeros(nread, np.double)
        # For Isotope index:
        isoID = np.zeros(nread, int)

        ut.lrprint(
            verbose, "Beginning to read Schwenke database, between "
            "records %d and %d." % (irec, frec))
        # When the wavelength surpasses the max wavelength, stop the loop
        chk = 1  # Check-point counter
        i = 0  # Stored record index
        interval = (frec - irec) // 20  # Check-point interval

        iw = np.zeros(nread, int)
        ieli = np.zeros(nread, np.short)
        ielo = np.zeros(nread, np.short)
        igf = np.zeros(nread, np.short)

        while (i < nread):
            # Read a record:
            data.seek((irec + i) * self.recsize)
            iw[i], ieli[i], ielo[i], igf[i] = struct.unpack(
                'ihhh', data.read(self.recdata))

            # Print a checkpoint statement every 1/20th interval:
            if verbose > 1:
                pos = float(data.tell() // self.recsize)
                if (pos / interval) % 1 == 0.0:
                    ut.lrprint(verbose - 1, "checkpoint %d/20..." % chk)
                    chk += 1
                    ut.lrprint(
                        verbose - 3, "iwl: %d, ielow: %5d, igf: "
                        "%6d" % (iw[i], ielo[i], igf[i]))
                    ut.lrprint(
                        verbose - 2,
                        "Wavelength: %.3f, IsoID: %d, Elow: %.5e, "
                        "gf: %.5e" %
                        (np.exp(iw[i] * self.ratiolog) * c.NTC / c.MTC,
                         np.abs(ieli[i]) - 8950, self.tablog[ielo[i]],
                         self.tablog[igf[i]]))
            i += 1

        # Convert wavelength to TLI format (microns):
        wlength[:] = np.exp(iw * self.ratiolog) * c.NTC / c.MTC
        # Get gf from log table:
        gf[:] = self.tablog[igf]
        # Get lowest state energy from log table:
        elow[:] = self.tablog[ielo]
        # Get isotopic index:
        isoID[:] = np.abs(ieli) - 8950
        ut.lrprint(verbose, "Done.\n")
        data.close()
        return wlength, gf, elow, isoID
예제 #13
0
    def dbread(self, iwl, fwl, verbose, procnum, return_dict, *args):
        """
    Read the Partridge and Schwenke H2O database (dbfile) between the
    wavelengths iwl and fwl.
 
    Parameters:
    -----------
    iwl: Scalar
       Initial wavelength limit (in microns).
    fwl: Scalar
       Final wavelength limit (in microns).
    verbose: Integer
       Verbosity threshold.
    procnum: Integer
       Index of the process which calls the function
    return_dict: Dict
       Dictionary to contain return values (indexed by process number)
    args:
       Additional arguments, not needed for pands.
 
    Returns:
    --------
    wlength: 1D ndarray (double)
      Line-transition central wavelength (microns).
    gf: 1D ndarray (double)
      gf value (unitless).
    elow: 1D ndarray (double)
      Lower-state energe (centimeter^-1).
    isoID: 2D ndarray (integer)
      Isotope index (1, 2, 3, ...).

    Modification History:
    ---------------------
    2013        madison   Initial implementation. madison.stemm@ucf edu
    2014-03-05  patricio  Added documentation.    [email protected]
    2014-03-08  patricio  Moved to pands.py
    2014-03-24  patricio  Rewritten as subclass of dbdriver.
    2014-07-06  patricio  Updated return statement.
    """

        # Open the binary file:
        data = open(self.dbfile, "rb")

        # Get the number of lines in the file:
        data.seek(0, 2)  # Set pointer at the file's end
        nlines = data.tell(
        ) / self.recsize  # Number of lines (8 bytes per line)

        # Rewrite wavelength limits as given in the P&S file:
        iwav = iwl * c.MTC / c.NTC  # Microns to nanometer
        fwav = fwl * c.MTC / c.NTC
        iwav = np.log(iwav) / self.ratiolog
        fwav = np.log(fwav) / self.ratiolog

        # Find the positions of iwl and fwl:
        irec = self.binsearch(data, iwav, 0, nlines - 1, 0)
        frec = self.binsearch(data, fwav, irec, nlines - 1, 1)
        nread = frec - irec + 1  # Number of records to read

        # Store data in two arrays for doubles and integers:
        # For Wavelength, Elow, and log(gf):
        wlength = np.zeros(nread, np.double)
        gf = np.zeros(nread, np.double)
        elow = np.zeros(nread, np.double)
        # For Isotope index:
        isoID = np.zeros(nread, int)

        ut.lrprint(
            verbose, "Beginning to read P&S database, between "
            "records %d and %d." % (irec, frec))
        # When the wavelength surpasses the max wavelength, stop the loop
        chk = 1  # Check-point counter
        i = 0  # Stored record index
        interval = float((frec - irec) / 20)  # Check-point interval

        iw = np.zeros(nread, int)
        ielo = np.zeros(nread, np.short)
        igf = np.zeros(nread, np.short)

        data.seek(irec * self.recsize)
        while (i < nread):
            # Read a record:
            iw[i], ielo[i], igf[i] = struct.unpack('Ihh',
                                                   data.read(self.recsize))

            # Print a checkpoint statement every 1/20th interval
            if verbose > 1:
                pos = float(data.tell() / self.recsize)
                if (pos / interval) % 1 == 0.0:
                    ut.lrprint(verbose - 1, "checkpoint %d/20..." % chk)
                    chk += 1
                    ut.lrprint(
                        verbose - 3, "iwl: %d, ielow: %5d, gf: "
                        "%6d" % (iw[i], ielo[i], igf[i]))
                    ut.lrprint(
                        verbose - 2,
                        "Wavelength: %.3f, IsoID: %d, Elow: %.5e, "
                        "gf: %.5e" %
                        (np.exp(iw[i] * self.ratiolog) * c.NTC / c.MTC, 2 *
                         (ielo[i] < 0) + 1 * (igf[i] < 0), np.abs(
                             ielo[i]), self.tablog[np.abs(igf[i])]))
            i += 1

        # Convert wavelength to TLI format (microns):
        wlength[:] = np.exp(iw * self.ratiolog) * c.NTC / c.MTC
        # Get gf fom log table:
        gf[:] = self.tablog[np.abs(igf)]
        # Set energy of lowest transition level:
        elow[:] = np.abs(ielo)
        # Assign indices for isotopes based on Kurucz's indices-1:
        isoID[:] = 2 * (ielo < 0) + 1 * (igf < 0)

        ut.lrprint(verbose, "Done.\n")
        data.close()
        return_dict[procnum] = (wlength, gf, elow, isoID)
        return wlength, gf, elow, isoID
예제 #14
0
  def dbread(self, iwl, fwl, verbose, procnum, return_dict, *args):
    """
    Read a HITRAN or HITEMP database (dbfile) between wavelengths iwl and fwl.

    Parameters:
    -----------
    dbfile: String
       A HITRAN or HITEMP database filename.
    iwl: Scalar
       Initial wavelength limit (in microns).
    fwl: Scalar
       Final wavelength limit (in microns).
    verbose: Integer
       Verbosity threshold.
    procnum: Integer
       Index of the process which calls the function
    return_dict: Dict
       Dictionary to contain return values (indexed by process number)
    pffile: String
       Partition function filename.

    Returns:
    --------
    wlength: 1D ndarray (double)
      Line-transition central wavelength (microns).
    gf: 1D ndarray (double)
      gf value (unitless).
    elow: 1D ndarray (double)
      Lower-state energy (cm^-1).
    isoID: 2D ndarray (integer)
      Isotope index (1, 2, 3, ...).

    Modification History:
    ---------------------
    2012-12-10  patricio  Initial implementation.  [email protected]
    2014-03-10  patricio  Adapted for pylineread.
    2014-07-06  patricio  Updated to return 1D arrays.
    """
    # Open HITRAN file for reading:
    data = open(self.dbfile, "r")
    # Read first line to get the record size:
    data.seek(0)
    line = data.readline()
    self.recsize = len(line)
    # Get Total number of transitions in file:
    data.seek(0, 2)
    nlines   = data.tell() / self.recsize
    # Get Molecule ID:
    molID = int(self.molID)

    # Rewrite wavelength limits as given in HITRAN file:
    fwn = 1.0 / (iwl * c.MTC)  # Microns to centimeters
    iwn = 1.0 / (fwl * c.MTC)  # Microns to centimeters

    # Find the record index for iwn and fwn:
    irec_init = self.binsearch(data, fwn, 0, nlines-1,  1)
    irec_fin  = self.binsearch(data, iwn, 0, irec_init, 0)

    # Allocates arrays for values to extract:
    wlength = np.zeros(irec_init-irec_fin+1, np.double)
    gf      = np.zeros(irec_init-irec_fin+1, np.double)
    elow    = np.zeros(irec_init-irec_fin+1, np.double)
    isoID   = np.zeros(irec_init-irec_fin+1,       int)
    # Einstein A coefficient:
    A21     = np.zeros(irec_init-irec_fin+1, np.double)
    # Lower statistical weight:
    g2      = np.zeros(irec_init-irec_fin+1, np.double)
    # Line intensity, used to calculate gf:
    S0      = np.zeros(irec_init-irec_fin+1, np.double)
    # Wavenumber:
    wnumber = np.zeros(irec_init-irec_fin+1, np.double)

    # Get the partition function at T0:
    PFzero = self.PFzero()

    i = 0  # Stored record index
    chk = 0
    interval = float((irec_fin - irec_init)/20)  # Check-point interval
    while irec_init - i >= irec_fin:
      data.seek( (irec_init-i) * self.recsize )
      # Read in wavenumber
      line = data.read(self.recsize)
      # Get the isotope index:
      isoID[i]   = float(line[self.recisopos:self.recwnpos ])
      # Get the wavenumber:
      wnumber[i] = float(line[self.recwnpos: self.reclinpos])
      # Get the line intensity:
      S0[i]      = float(line[self.reclinpos:self.reclinend])
      # Get Elow:
      elow[i]    = float(line[self.recelpos: self.recelend ])
      A21[i]     = float(line[self.recApos:  self.recairpos])
      g2[i]      = float(line[self.recg2pos: self.recsize  ])
      # Print a checkpoint statement every 1/20th interval
      if verbose > 1:
        pos = float(data.tell()/self.recsize)
        if (pos/interval)%1 == 0.0:
          ut.lrprint(verbose-1, "checkpoint %d/20..."%chk)
          chk += 1
          ut.lrprint(verbose-3, "Wavenumber: %s, S0: %s, Elow: "
                                "%s"%(wnumber[i], S0[i], elow[i]))
          ut.lrprint(verbose-2, "Wavelength: %.3f, IsoID: %d, Elow: %.3f"%(
                                1.0/(wnumber[i]*c.MTC), isoID[i], elow[i]))
      i += 1


    # Calculate the wavelength in microns:
    wlength[:] = 1.0 / (wnumber * c.MTC)
    # Set isotopic index to start counting from 0:
    isoID -= 1
    isoID[np.where(isoID < 0)] = 9 # 10th isotope had index 0 --> 10-1=9
    # Calculate gf:
    Ia = np.asarray(self.isoratio)
    gf = (S0 * c.C1 * PFzero[isoID] /  Ia[isoID] *
             np.exp( c.C2 * elow / self.T0)  /
                 (1.0-np.exp(-c.C2 * wnumber    / self.T0)) )
    # Alternative way:
    gf2 = A21 * g2 * c.C1 / (8.0 * np.pi * sc.c * 100.0) / wnumber**2.0

    # FINDME: Delete me when gf-vs-gf2 issue solved.
    # print(gf)
    # print(gf2)
    # print((gf/gf2)[:20])
    # print(isoID[:20])
    # print(np.amax(gf/gf2), np.amin(gf/gf2))
    # import matplotlib.pyplot as plt
    # plt.figure(1)
    # plt.plot(isoID, gf/gf2, "b,")
    # plt.ylim(0,4)
    # plt.xlim(-0.5, 5.5)
    # plt.savefig("gf.png")
    # plt.figure(2)
    # print(np.shape(self.gi), np.shape(PFzero))
    # ggi = np.asarray(self.gi)[isoID]
    # plt.plot(ggi, gf2/gf, "b,")
    # plt.plot([0,12], [0,12], "r")
    # plt.ylim(0,15)
    # plt.xlim(-0.5, 12.5)
    # plt.savefig("gf2.png")

    ut.lrprint(verbose-14, "GF values: " + str(gf))
    data.close()
    return_dict[procnum] = (wlength, gf2, elow, isoID)
    return wlength, gf2, elow, isoID
예제 #15
0
  def getpf(self, verbose):
    """                                    
    Calculate the partition function for a grid of temperatures for
    HITRAN molecules.

    Notes:
    ------
    This function is a wrapper of the Fortran TIPS routine written
    by R. R. Gamache.
    The range of temperatures is limited to: 70K -- 3000K.

    Parameters:
    -----------
    verbose: Integer
       Verbosity threshold.

    Returns:
    --------
    Temp: 1D float ndarray
       The array of temeratures where the partition function was evaluated.
    PF: 2D float ndarray
       A 2D array (N temperatures, N isotopes) with the partition
       function values for each isotope (columns) as function of temperature
       (first column).

    Modification History:
    ---------------------
    2012-11-22  patricio  Initial implementation.  [email protected]
    2014-03-10  patricio  Adapted previous code.
    """

    # Get molecule ID as  integer:
    molID = int(self.molID)
 
    # Get Number of isotopes:
    Niso = len(self.isotopes)

    # Array of temperatures:
    Temp = np.arange(70.0, 3000.1, 10)
    # TIPS range of temperature is: [70K, 3000K]
    Ntemp = len(Temp)

    # Output array for table of Temperature and PF values: 
    PF = np.zeros((Niso, Ntemp), np.double)
    ut.lrprint(verbose-14, "Temperature sample:\n" + str(Temp))
    ut.lrprint(verbose-5, "Ntemp: %d, Niso: %d"%(Ntemp, Niso))

    for i in np.arange(Niso):
      # Molecule ID, isotope ID, and temperature array as strings:
      smol  = str(molID) + "\n"
      siso  = str(self.isotopes[i]) + "\n"
      stemp = np.asarray(Temp, '|S6')

      # String input for TIPS:
      input = smol + siso + ("\n" + smol + siso).join(stemp) + "\n99\n"

      # Call fortran routine to calculate the partition function:
      p = sp.Popen([self.pffile], stdout=sp.PIPE, stdin=sp.PIPE,
                   stderr=sp.STDOUT)
      #print("Size: %d"%np.size(PF[i]))
      #tmp =  p.communicate(input=input)[0].strip().split("\n")
      #print(tmp)
      PF[i] = p.communicate(input=input)[0].strip().split("\n") 
      PF[i] /= self.gi[i]
    return Temp, PF
예제 #16
0
  Nfiles = len(dblist)
  # Driver routine to read the databases:
  driver = []
  for i in np.arange(Nfiles):
    if   dbtype[i] == "ps":
      driver.append(ps.pands(dblist[i],       pflist[i]))
    elif dbtype[i] == "hit":
      driver.append(hit.hitran(dblist[i],     pflist[i], defn))
    elif dbtype[i] == "ts":
      driver.append(ts.tioschwenke(dblist[i], pflist[i]))
    elif dbtype[i] == "vo":
      driver.append(vo.voplez(dblist[i],      pflist[i]))
    else:
      ut.printexit("Unknown Database type ({:d}): '{:s}'".
                    format(i+1, dbtype[i]))
    ut.lrprint(verbose-10, "File {:d}, database name: '{:s}'".
                            format(i+1, driver[i].name))

  ut.lrprint(verbose, "Beginning to write the TLI file: '{:s}'".
                       format(outputfile))
  # Open output file:
  TLIout  = open(outputfile, "wb")

  # Get the machine endian type (big/little):
  endianness = sys.byteorder

  # Hardcoded implementation of lineread's "magic number" check for endianness
  # derived from binary encoding the letters TLI into binary location
  # and checking the order
  if endianness == 'big':
    magic = '\xab\xb3\xb6\xff'
  if endianness == 'little':
예제 #17
0
  def dbread(self, iwl, fwl, verbose, procnum, return_dict, *args):
    """
    Read the Partridge and Schwenke H2O database (dbfile) between the
    wavelengths iwl and fwl.
 
    Parameters:
    -----------
    iwl: Scalar
       Initial wavelength limit (in microns).
    fwl: Scalar
       Final wavelength limit (in microns).
    verbose: Integer
       Verbosity threshold.
    procnum: Integer
       Index of the process which calls the function
    return_dict: Dict
       Dictionary to contain return values (indexed by process number)
    args:
       Additional arguments, not needed for pands.
 
    Returns:
    --------
    wlength: 1D ndarray (double)
      Line-transition central wavelength (microns).
    gf: 1D ndarray (double)
      gf value (unitless).
    elow: 1D ndarray (double)
      Lower-state energy (cm^-1).
    isoID: 2D ndarray (integer)
      Isotope index (1, 2, 3, ...).

    Modification History:
    ---------------------
    2012-11-30  patricio  Initial implementation.  [email protected]
    2014-03-11  patricio  Adapted to work with pylineread.
    2014-03-24  patricio  Rewritten as subclass of dbdriver.
    2014-07-06  patricio  Updated return statement.
    2014-09-23  patricio  Updated for pylineread 5.0.
    """
 
    # Open the file:
    data = open(self.dbfile, "rb")
 
    # Get the number of lines in the file:
    data.seek(0, 2)                     # Set pointer at the file's end
    nlines = data.tell() / self.recsize # Number of lines (bytes/record_size)
 
    # Rewrite wavelength limits as given in the Database file:
    iwav = iwl * c.MTC / c.NTC         # Microns to nanometer
    fwav = fwl * c.MTC / c.NTC
    iwav = np.log(iwav) / self.ratiolog
    fwav = np.log(fwav) / self.ratiolog
 
    # Find the positions of iwl and fwl:
    irec = self.binsearch(data, iwav, 0,    nlines-1, 0)
    frec = self.binsearch(data, fwav, irec, nlines-1, 1)
    nread = frec - irec + 1  # Number of records to read

    # Store data in two arrays for doubles and integers:
    # For Wavelength, Elow, and log(gf):
    wlength = np.zeros(nread, np.double)
    gf      = np.zeros(nread, np.double)
    elow    = np.zeros(nread, np.double)
    # For Isotope index:
    isoID   = np.zeros(nread,     int)
 
    ut.lrprint(verbose, "Beginning to read Schwenke database, between "
                        "records %d and %d."%(irec, frec))
    # When the wavelength surpasses the max wavelength, stop the loop
    chk = 1  # Check-point counter
    i   = 0  # Stored record index
    interval = float((frec - irec)/20)  # Check-point interval

    iw   = np.zeros(nread, int)
    ieli = np.zeros(nread, np.short)
    ielo = np.zeros(nread, np.short)
    igf  = np.zeros(nread, np.short)

    while (i < nread):
      # Read a record:
      data.seek((irec+i)*self.recsize)
      iw[i], ieli[i], ielo[i], igf[i] = struct.unpack('ihhh',
                                                      data.read(self.recdata))
 
      # Print a checkpoint statement every 1/20th interval:
      if verbose > 1:
        pos = float(data.tell()/self.recsize)
        if (pos/interval)%1 == 0.0:
          ut.lrprint(verbose-1, "checkpoint %d/20..."%chk)
          chk += 1
          ut.lrprint(verbose-3, "iwl: %d, ielow: %5d, igf: "
                                "%6d"%(iw[i], ielo[i], igf[i]))
          ut.lrprint(verbose-2, "Wavelength: %.3f, IsoID: %d, Elow: %.5e, "
                     "gf: %.5e"%(np.exp(iw[i] * self.ratiolog) * c.NTC/c.MTC,
                                 np.abs(ieli[i]) - 8950,
                                 self.tablog[ielo[i]], self.tablog[igf[i]]))
      i += 1

    # Convert wavelength to TLI format (microns):
    wlength[:] = np.exp(iw * self.ratiolog) * c.NTC/c.MTC
    # Get gf from log table:
    gf[:]      = self.tablog[igf]
    # Get lowest state energy from log table:
    elow[:]    = self.tablog[ielo]
    # Get isotopic index:
    isoID[:]   = np.abs(ieli) - 8950
    ut.lrprint(verbose, "Done.\n")
    data.close()
    return_dict[procnum] = (wlength, gf, elow, isoID)
    return wlength, gf, elow, isoID
예제 #18
0
  def dbread(self, iwl, fwl, verbose, *args):
    """
    Read the Partridge and Schwenke H2O database (dbfile) between the
    wavelengths iwl and fwl.
 
    Parameters:
    -----------
    iwl: Scalar
       Initial wavelength limit (in microns).
    fwl: Scalar
       Final wavelength limit (in microns).
    verbose: Integer
       Verbosity threshold.
    args:
       Additional arguments, not needed for pands.
 
    Returns:
    --------
    wlength: 1D ndarray (double)
      Line-transition central wavelength (microns).
    gf: 1D ndarray (double)
      gf value (unitless).
    elow: 1D ndarray (double)
      Lower-state energe (centimeter^-1).
    isoID: 2D ndarray (integer)
      Isotope index (1, 2, 3, ...).

    Modification History:
    ---------------------
    2013        madison   Initial implementation. madison.stemm@ucf edu
    2014-03-05  patricio  Added documentation.    [email protected]
    2014-03-08  patricio  Moved to pands.py
    2014-03-24  patricio  Rewritten as subclass of dbdriver.
    2014-07-06  patricio  Updated return statement.
    """
 
    # Open the binary file:
    data = open(self.dbfile, "rb")
 
    # Get the number of lines in the file:
    data.seek(0, 2)                      # Set pointer at the file's end
    nlines   = data.tell()/ self.recsize # Number of lines (8 bytes per line)
 
    # Rewrite wavelength limits as given in the P&S file:
    iwav = iwl * c.MTC / c.NTC         # Microns to nanometer
    fwav = fwl * c.MTC / c.NTC
    iwav = np.log(iwav) / self.ratiolog
    fwav = np.log(fwav) / self.ratiolog
 
    # Find the positions of iwl and fwl, then jump to wl_i position:
    irec = self.binsearch(data, iwav, 0,    nlines, 0)
    frec = self.binsearch(data, fwav, irec, nlines, 1)
    nread = frec - irec + 1  # Number of records to read
 
    # Store data in two arrays for doubles and integers:
    # For Wavelength, Elow, and log(gf):
    wlength = np.zeros(nread, np.double)
    gf      = np.zeros(nread, np.double)
    elow    = np.zeros(nread, np.double)
    # For Isotope index:
    isoID   = np.zeros(nread,     int)
 
    ut.lrprint(verbose, "Beginning to read P&S database, between "
                        "records %d and %d."%(irec, frec))
    # When the wavelength surpasses the max wavelength, stop the loop
    chk = 1  # Check-point counter
    i   = 0  # Stored record index
    interval = float((frec - irec)/20)  # Check-point interval

    iw   = np.zeros(nread, int)
    ielo = np.zeros(nread, np.short)
    igf  = np.zeros(nread, np.short)

    data.seek(irec*self.recsize) 
    while (i < nread):
      # Read a record:
      iw[i], ielo[i], igf[i] = struct.unpack('Ihh', data.read(self.recsize))
 
      # Print a checkpoint statement every 1/20th interval
      if verbose > 1:
        pos = float(data.tell()/self.recsize)
        if (pos/interval)%1 == 0.0:
          ut.lrprint(verbose-1, "checkpoint %d/20..."%chk)
          chk += 1
          ut.lrprint(verbose-3, "iwl: %d, ielow: %5d, gf: "
                                "%6d"%(iw[i], ielo[i], igf[i]))
          ut.lrprint(verbose-2, "Wavelength: %.3f, IsoID: %d, Elow: %.5e, "
                    "gf: %.5e"%(np.exp(iw[i] * self.ratiolog) * c.NTC/c.MTC,
                                2*(ielo[i] < 0) + 1*(igf[i] < 0),
                                np.abs(ielo[i]), self.tablog[np.abs(igf[i])]))
      i += 1

    # Convert wavelength to TLI format (microns):
    wlength[:] = np.exp(iw * self.ratiolog) * c.NTC/c.MTC
    # Get gf fom log table:
    gf[:]      = self.tablog[np.abs(igf)]
    # Set energy of lowest transition level:
    elow[:]    = np.abs(ielo)
    # Assign indices for isotopes based on Kurucz's indices-1:
    isoID[:]   = 2*(ielo < 0) + 1*(igf < 0)

    ut.lrprint(verbose, "Done.\n")
    data.close()
    return wlength, gf, elow, isoID