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
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
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
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
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
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
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
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
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
# 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'
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
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
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
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
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':
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
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