def read_cross_sections_xy (file, commentChar):
	""" Read one cross section file (xy ascii format; typically one molecule, several p,T pairs). """
	# initialize list of cross sections to be returned
	xsList = []
	# read entire cross section file (incl. commented header lines)
	try:
		xyData, comments = readDataAndComments(file,commentChar)
	except:
		raise SystemExit, 'ERROR:  reading cross section file failed (check format etc!?!)\n' + repr(file)

	# parse comment header and extract some infos
	need = ('pressure', 'temperature', 'molecule')
	headerDict = parse_file_header (comments, need)

	npT = xyData.shape[1]-1
	xLimits = Interval(xyData[0,0], xyData[-1,0])
	for l in range(1,npT+1):
		xsList.append({'molecule': headerDict['molecule'],  'x': xLimits,  'y': xyData[:,l]})

	pValues, pUnit = headerDict['pressure'][0], headerDict['pressure'][1]
	pValues = unitConversion (pValues, 'pressure', pUnit)
	if len(pValues)==npT:
		for l in range(npT): xsList[l]['p'] = pValues[l]

	TValues, TUnit = headerDict['temperature'][0], headerDict['temperature'][1]
	TValues = unitConversion (TValues, 'temperature', TUnit)
	if len(TValues)==npT:
		for l in range(npT): xsList[l]['T'] = TValues[l]

	return xsList
示例#2
0
def save_optDepth_xy (vGrid, optDepth, outFile=None, atmos=None, nanometer=False, yOnly=False, flipUpDown=False, commentChar='#'):
	""" Save optical depth (vs wavenumber or wavelength) in ascii tabular format. """
	out = open_outFile (outFile, commentChar)
	
	nLevels = len(atmos.z)
	nGas    = len(atmos.gases)
	if flipUpDown:
		if len(optDepth.shape)==2:  optDepth = np.fliplr(optDepth) # swap columns
		comments = ['altitudes [km]:  ' + nLevels*' %10.1f' % tuple(unitConversion(atmos.z[::-1],'length',new='km')),
	                    'temperatures [K]:' + nLevels*' %10.2f' % tuple(atmos.T[::-1]),
	                    'pressures [mb]:  ' + nLevels*' %10.4g' % tuple(unitConversion(atmos.p[::-1],'p',new='mb'))]
	else:
		comments = ['altitudes [km]:  ' + nLevels*' %10.1f' % tuple(unitConversion(atmos.z,'length',new='km')),
	                    'temperatures [K]:' + nLevels*' %10.2f' % tuple(atmos.T),
	                    'pressures [mb]:  ' + nLevels*' %10.4g' % tuple(unitConversion(atmos.p,'p',new='mb'))]
	comments += ['gases:           ' +    nGas*' %10s'   % tuple(atmos.gases),
	             'vcd [molec/cm^2]:' +    nGas*' %10.2g' % tuple(atmos.vcd())]
	if nanometer:
		if yOnly: 
			writeArray (np.flipud(optDepth),                  out, comments=comments, format= '%10g')
		else:
			comments += ['%10s %10s' % ('wavelength','optical depth'),  '%10s' % 'nm']
			writeArray (np.flipud(paste(1e7/vGrid,optDepth)), out, comments=comments, format= '%10f %10g')
	else:
		if yOnly:
			writeArray (optDepth,              out, comments=comments, format= '%10g')
		else:	
			comments += ['%10s %10s' % ('wavenumber','optical depth'),  '%10s' % '1/cm']
			writeArray (paste(vGrid,optDepth), out, comments=comments, format= '%10f %10g')

	out.close()
def pyplot_xs (crossSections):
	
	if isinstance(crossSections,dict):
		figure()
		xs  = crossSections
		xGrid=np.linspace(xs['x'].lower,xs['x'].upper,len(xs['y']))
		semilogy (xGrid, xs['y'], label='%10.3gmb %7.2fK' % (unitConversion(xs['p'],'p',new='mb'), xs['T']))
		#show()
	elif isinstance(crossSections,list):
		figure()
		for xs in crossSections:
			xGrid=np.linspace(xs['x'].lower,xs['x'].upper,len(xs['y']))
			semilogy (xGrid, xs['y'], label='%10.3gmb %7.2fK' % (unitConversion(xs['p'],'p',new='mb'), xs['T']))
		title('%s  %10.3gmb %7.2fK' % (xs['molecule'], unitConversion(xs['p'],'p','mb'), xs['T']) )
		legend()
def write_crossSections_xyy (crossSections, outFile=None, linePositions=None, interpolate='3', commentChar='#'):
	""" Write cross section(s) to output (file) in tabular xy format.
	    (All cross sections of a given molecule (i.e., data for all p,T levels) 
	     are interpolated to a common wavenumber grid and written to a single file) """

	out = open_outFile (outFile, commentChar)
	if outFile:
		# print a summary
		molecules = tuple([xs.get('molecule') for xs in crossSections])
		sameMolec = np.alltrue([molecules[0] == other for other in molecules[1:]])
		if sameMolec:      out.write ( '%1s  %-16s %s\n' % (commentChar, 'molecule:', molecules[0]))

		lineShapes = tuple([xs.get('lineShape') for xs in crossSections])
		sameShapes = np.alltrue([lineShapes[0] == other for other in lineShapes[1:]])
		if sameShapes:     out.write ( '%1s  %-16s %s\n' % (commentChar, 'lineshape:', lineShapes[0]))

		if isinstance(linePositions,np.ndarray):
			out.write ( '%1s  %i %s %f ... %f\n' % (commentChar, len(linePositions), 'lines in ', min(linePositions),max(linePositions)) )
		# extract pressure and temperatures
		nXS = len(crossSections)
		pressures    = tuple([unitConversion(xs.get('p',0.0),'p',new='mb') for xs in crossSections])
		temperatures = tuple([xs.get('T',0.0) for xs in crossSections])
		out.write ( commentChar+'  pressure [mb]:  ' + nXS*' %10g' % pressures + '\n')
		out.write ( commentChar+'  temperature [K]:' + nXS*' %10.2f' % temperatures + '\n')
		out.write ( commentChar + '\n' )

	# select an interpolation method
	if   interpolate.lower() in 'sb':
                try:                      from scipy.interpolate import splrep, splev
	        except ImportError, msg:  raise SystemExit, msg
                else:                     intMethod =  'Spline interpolation (scipy splrep/splev)'
示例#5
0
def reGridAtmos1d (atmos1d, zToA=None, pRatio=None, zGrid=None):
	if bool(zGrid)+bool(pRatio)+bool(zToA)>1:
		raise SystemExit, 'either specify ToA altitude OR new zGrid OR pressure ratio for atmospheric profile interpolation!'
	elif pRatio>0.0 or zGrid:
		zOld = atmos1d.z
		if pRatio>0.0:
			zNew, pNew = change_pressure_grid (atmos1d.z, atmos1d.p, pRatio)
		else:           
			zNew = change_altitude_grid (atmos1d.z, zGrid)
			pNew = np.exp(np.interp(zNew, zOld, np.log(atmos1d.p))); atmos1d.p = pNew
		atmos1d.z   = zNew
		atmos1d.T   = np.interp(zNew, zOld, atmos1d.T)
		atmos1d.air = np.exp(np.interp(zNew, zOld, np.log(atmos1d.air)))
		for m,mol in enumerate(atmos1d.gases):
    			atmos1d.densities[:,m] = np.interp(zNew, zOld, atmos1d.densities[:,m])
    	elif zToA:
		if zToA<200.:
			zToA = unitConversion(zToA, 'length', old='km')
			print 'WARNING --- reGridAtmos1d:  zToA very small, assuming kilometer units'
		nz = sum([1 for z in atmos1d.z if z<=zToA])
		atmos1d.z = atmos1d.z[:nz]
		atmos1d.p = atmos1d.p[:nz]
		atmos1d.T = atmos1d.T[:nz]
		atmos1d.air = atmos1d.air[:nz]
		atmos1d.densities = atmos1d.densities[:nz,:]
	return atmos1d
def _cross_section_ (iFile, oFile=None, commentChar='#', format=None, interpolate='3', columns=[], plot=False):
	# read cross sections from file
	crossSections = read_cross_sections (iFile, commentChar)
	
	# remove unwanted cross sections
	if columns:
		columns = [int(C)-1 for C in columns.split(",")]
		newCrossSections = [xs for l,xs in enumerate(crossSections) if l in columns]
		crossSections = newCrossSections

	# print summary
	for xs in crossSections:
		nv     = len(xs['y']) - 1 # number of intervals !!!
		deltaX = xs['x'].size() / nv
		iMin   = np.argmin(xs['y'])
		iMax   = np.argmax(xs['y'])
		print '%-10s %10i wavenumber %10.3g %s %10gmb %8.2fK %12.3g < xs < %10.3g  @ %10i %10f   avg %10.3g' % \
		      (xs['molecule'], nv+1, deltaX, xs['x'], unitConversion(xs['p'], 'p', new='mb'), xs['T'],
		       min(xs['y']), max(xs['y']), iMax, xs['x'].lower+iMax*deltaX, np.mean(xs['y']))

	if plot:  pyplot_xs(crossSections)
	
	# save cross sections
	if oFile:
		if format=='xy':
			if interpolate=='0':
				write_crossSections_xy (crossSections, oFile, commentChar=commentChar)
			else:
				write_crossSections_xyy (crossSections, oFile, interpolate=interpolate, commentChar=commentChar)
		elif format.startswith('h'):
			write_crossSections_hitran (crossSections, oFile)
		else:
			write_crossSections_pickled (crossSections, oFile)
示例#7
0
def _lbl2xs_ (iFile, oFile=None, commentChar='#', molecule=None, pressures=None, temperatures=None, ptFile=None,
              lineShape='Voigt',
              xLimits=None, airWidth=0.1, sampling=5.0, wingExt=5.0, interpolate='3', nGrids=1, gridRatio=8, nWidths=25.0,
	      format=None, verbose=False):
	from cross_section import write_crossSections

	# read a couple of lines and convert to actual pressure and temperature
	Line_Data, Mol_Data = get_lbl_data (iFile, xLimits, airWidth, wingExt, molecule, commentChar)

	if len(Line_Data['position'])<1:
		print 'no line data in ', xLimits; return

	# pressure(s) and temperature(s)
	if ptFile and (pressures or temperatures):
		raise SystemExit, 'either give p,T file or pressure(s) and temperature(s) as command line option'
	elif ptFile:
		try:
                        pT = np.loadtxt(ptFile,comments=commentChar)
		except:
                        raise SystemExit, ' ERROR: reading ' + ptFile + ' failed!'
                pressures      = unitConversion(pT[:,0], 'p', 'mb')
                temperatures   = pT[:,1]
		# some simple tests
		if pT.shape[1]!=2 or min(temperatures)<100 or max(temperatures)>1000:
			print 'WARNING --- check your pT file:  more than 2 columns OR strange (very low, high) temperatures!'
	else:
		# if unset on command line, use line parameter reference values (redo for every line file, ref. values might change!)
		if isinstance(pressures,NoneType):     pressures    = np.array([Line_Data['pressure']])
		else:                                  pressures    = unitConversion(pressures, 'p', 'mb')
		if isinstance(temperatures, NoneType): temperatures = np.array([Line_Data['temperature']])
		pressures, temperatures = check_pT (pressures, temperatures)

	# interpolation method used in multigrid algorithms: only Lagrange!
	if   interpolate in 'bBsScC':  lagrange=4
	elif interpolate in 'qQ':      lagrange=3
	elif interpolate in 'lL':      lagrange=2
	else:                          lagrange=int(interpolate)

	# compute cross sections for selected line shape
	crossSections = lbl_xs (Line_Data, Mol_Data, pressures, temperatures, xLimits, lineShape,
	                        sampling, wingExt, nGrids, gridRatio, nWidths, lagrange, verbose)

	# save cross sections (and lines)
	print ' %-8s %5i %s %s' % (Line_Data['molecule'], len(crossSections), ' cross sections:  save to ', oFile)
	write_crossSections (crossSections, oFile, format, Line_Data['position'], interpolate, commentChar)
示例#8
0
def write_atmos_xy (out, data, pT=False, saveVMR=False):
	""" print profiles in xy format suitable for pfui or xmgr. """
	nz, ny = data.shape()

	if saveVMR:
		if not hasattr(data,'air'):  raise SystemExit, 'ERROR --- write_atmos_xy:  no air number density ---> no conversion to VMR'

	saveAltitudes = not pT # do not print altitudes, use pressure as first column (e.g. to save a pressure/temp file as input for lbl2xs)

	# print column identifiers
	if saveAltitudes:
		what  = '%7s%3s' % ('#what: ', 'z')
		units = '%7s%3s' % ('#units:', 'km')
		zGrid = unitConversion (data.z, 'length', new='km')
	else:
		what=''; units=''

	# print file header (column id's)
	if hasattr(data,'p'):
		#what  = what  + ' %11s' % 'pressure';     units = units + ' %11s' % 'g/cm/s**2'
		what  = what  + ' %11s' % 'pressure';     units = units + ' %11s' % 'mb'
	if hasattr(data,'T'):
		what  = what  + ' %11s' % 'temperature';  units = units + ' %11s' % 'K'
	if hasattr(data,'air'):
		what  = what  + ' %11s' % 'air';          units = units + ' %11s' % '1/cm**3'
	if hasattr(data,'densities'):
		what  = what  + ' ' + join(['%11s' % gas for gas in data.gases])
		if saveVMR:  units = units + ' ' + join(['%11s'%'ppm' for gas in data.gases])
		else:        units = units + ' ' + join(['%11s'%'1/cm**3' for gas in data.gases])
	out.write (what + '\n' + units + '\n')

	# print data in nxy format
	for l in range(nz):
		if saveAltitudes:  out.write ( '%10.1f' % zGrid[l] )
		#if hasattr(data,'p'):   out.write ( ' %11g' % data.p[l])
		if hasattr(data,'p'):   out.write ( ' %11g' % unitConversion(data.p[l],'p',new='mb'))
		if hasattr(data,'T'):   out.write ( ' %11.3f' % data.T[l])
		if hasattr(data,'air'): out.write ( ' %11.4g' % data.air[l])
		if saveVMR:
			if hasattr(data,'densities'): out.write ( data.densities.shape[1]*' %11.3g' % tuple(1.e6*data.densities[l,:]/data.air[l]) )
		else:
			if hasattr(data,'densities'): out.write ( data.densities.shape[1]*' %11.3g' % tuple(data.densities[l,:]) )
		out.write('\n')
示例#9
0
	def __init__ (self, atmData):
		""" Given a list of profile data (dictionaries with entries for 'what', 'data' etc) generate an atmos instance. """
		if not isinstance(atmData,list):  raise SystemExit, 'Atmos1D initialization failed, need a list of profiles!'
		self.gases = []

		for prof in atmData:
			what = prof.what
			if lower(what).startswith('alt') or lower(what)=='z': 
				self.z = unitConversion (prof.data, 'length', prof.unit)
			elif lower(what).startswith('press') or what=='p': 
				if hasattr(self,'p'):  raise SystemExit, 'ERROR Atmos1D init:  pressure already present!'
				self.p = unitConversion (prof.data, 'pressure', prof.unit)
			elif lower(what).startswith('temp') or what=='T': 
				if hasattr(self,'T'):  raise SystemExit, 'ERROR Atmos1D init:  temperature already present!'
				self.T = cgsTemperature (prof.data, prof.unit)
			elif lower(what).startswith('air') or lower(what).startswith('rho'): 
				if hasattr(self,'air'):  raise SystemExit, 'ERROR Atmos1D init:  "air" already present!'
				self.air = unitConversion (prof.data, 'density', prof.unit)
			elif what[0] in ascii_uppercase: 
			    	if what not in self.gases:  self.gases.append(what)
			    	else:                       raise SystemExit, '%s %s %s' % ('ERROR Atmos1D init:  gas ', what, 'already defined')
				
			    	if prof.unit.startswith('pp') or prof.unit=='%' or lower(prof.unit)=='vmr':
					densities = unitConversion (prof.data, 'MixingRatio', prof.unit)
			    	elif prof.unit.endswith('m-3') or prof.unit.endswith('m**3') or prof.unit.endswith('m^3'): 
					densities = unitConversion (prof.data, 'density', prof.unit)
				else:
					raise SystemExit, '%s %s %s %s' % ('unknown profile unit ', repr(prof.unit), ' for molecule',  prof.what)
				if not hasattr(self,'densities'): self.densities = densities
				else:                             self.densities = np.column_stack((self.densities,densities))
		# pressure <---> temperature <---> air number density
		if   hasattr(self,'p')+hasattr(self,'T')+hasattr(self,'air')==3:  print 'Atmos1d: got p, T, air'
		elif hasattr(self,'p') and hasattr(self,'T'):       self.air = self.p / (kBoltzmann*self.T)
		elif hasattr(self,'T') and hasattr(self,'air'):     self.p   = self.air * (kBoltzmann*self.T)
		elif hasattr(self,'p') and hasattr(self,'air'):     self.T   = self.p / (kBoltzmann*self.air)
		else:  raise SystemExit, 'ERROR --- Atmos1D init: need at least two of three data: p, T, air'
		# finally convert all mixing ratios to number densities
		if len(self.gases)>0:
			if len(self.densities.shape)==1:  self.densities = np.expand_dims(self.densities,1)
			for m,gas in enumerate(self.gases):
				if max(self.densities[:,m])<1.0:
					self.densities[:,m] = self.air * self.densities[:,m]
					print 'gas #', m+1, gas, ' vmr converted to number density'
示例#10
0
def write_voigtLines (positions, strengths, gammaL, gammaD, pressure, temperature, molecule, outFile=None, commentChar='#'):
	""" Write Voigt line parameters (strengths, Lorentz and Gaussian widths vs line positionsp. """
	out = open_outFile (outFile, commentChar)
	out.write ('%s %s %s\n' % (commentChar, "molecule:", molecule))
	out.write ('%s %s %-12g\n' % (commentChar, "pressure  [mb]:     " ,  unitConversion(pressure,'p', new='mb')))
	out.write ('%s %s %8.2f\n' % (commentChar, "temperature  [K]: ", temperature))
	out.write ('%s %10s  %11s %11s %11s\n' % (commentChar, "position", "strength", "gammaL", "gammaG"))
	format = '%12f  %11.3e %11.3g %11.3g\n'
	for v,S, gL, gG in zip(positions, strengths, gammaL, gammaD):  out.write ( format % (v,S,gL,gG) )
	# close the output file (if its not stdout)
	if outFile: out.close()
示例#11
0
def lbl_xs (Line_Data, Mol_Data,  pressures, temperatures, xLimits=None, lineShape="Voigt",
            sampling=5.0, wingExt=5.0, nGrids=1, gridRatio=1, nWidths=25.0, lagrange=3, verbose=False):
	""" Compute cross sections for a given molecule and some p,T pairs by summation of lines.
	    Returns a list of dictionaries with cross sections given on an equidistant wavenumber grid. """

	# extract line position
	positions = Line_Data['position']

	# if no limits specified, add some points to the left and right of the first/last line
	if xLimits:
		vLow, vHigh = xLimits.limits()
	else:
		vLow    = max(positions[ 0]-0.1*wingExt,0.0)
		vHigh   =     positions[-1]+0.1*wingExt
		xLimits = Interval(vLow,vHigh)
	     	print ' no wavenumber range set, added some points to left and right of the first, last line', xLimits

	# initialize list of cross sections
	nLevels = len(pressures); lvl=0
	crossSections = []
	# loop over all levels or layers
	for p, T in zip(pressures, temperatures):
		lvl = lvl+1
		print '%-10s%-8s lvl %2i/%2i  %20s %10g %s %g\n%50s %10.2f %s %6.2f' % (' lbl_xs:',  Line_Data['molecule'], lvl, nLevels,
		                                                           'pressure [g/cm/s**2]', Line_Data['pressure'], '--->', p,
		                                                           'temperature      [K]', Line_Data['temperature'], ' --->',  T)
		# adjust line parameters to p, T
		strengths, gammaL, gammaD = strengths_and_widths (Line_Data, Mol_Data, p, T)
 
		# compute cross sections by summing profiles of all contributing lines
		tStart = time.clock()
		if nGrids==3:
			v, xs  =  lbl_3grids (positions, strengths, gammaL, gammaD, vLow, vHigh, lineShape,
			                      sampling, gridRatio, nWidths, lagrange, verbose=verbose)
		elif nGrids==2:
			v, xs  =  lbl_2grids (positions, strengths, gammaL, gammaD, vLow, vHigh, lineShape,
			                      sampling, gridRatio, nWidths, lagrange, verbose)
		else:
			v, xs  =  lbl_brute (positions, strengths, gammaL, gammaD, vLow, vHigh, lineShape, sampling, verbose)
		tStop = time.clock(); deltaTime = tStop-tStart

		print '%s %-8s (%i %s, %8gmb, %5.1fK, %10i %.2fsec %.2fns):  %8g %s %8g\n' % \
			(' cross section ', Line_Data['molecule'], len(positions),'lines', unitConversion(p,'p',new='mb'), T, \
			 len(xs), deltaTime, 1.e9*deltaTime/(len(xs)*len(positions)), min(xs),'< xs <',max(xs))

		# brute force remedy to get rid of negative values most likely due to higer order interpolation
		if lagrange>2 and min(xs)<0.0:
			print 'truncate negative xs:', sum(np.where(xs<0,1,0))
			np.putmask(xs, xs<0.0, 0.0)

		# save new cross sections along with attributes in dictionary and append to list of cross sections
		crossSections.append({'molecule': Line_Data['molecule'], 'lineShape': lineShape,  'x': xLimits, 'p': p,  'T': T,  'y': xs})

	return crossSections
示例#12
0
def write_atmos_namelist (out, data, saveVMR=False):
	""" Write atmospheric data in namelist format suitable for MIRART. """
	nz = len(data.z)
	# print altitude information
	write_namelist_altitude (out, unitConversion(data.z,'length',new='km'), unit='km', format='%10.2f')
	# print profiles
	#write_namelist_profile (out, data.p, 'pressure', unit='g/cm/s**2', format='%10.4g')
	write_namelist_profile (out, unitConversion(data.p, 'p', new='mb'), 'pressure', unit='mb', format='%10.4g')
	write_namelist_profile (out, data.T, 'temperature', unit='K', format='%10.2f')
	write_namelist_profile (out, data.air, 'air', unit='1/cm**3', format='%10.4g')
	for m,gas in enumerate(data.gases):
		vmr = max(data.densities[:,m])<1.0 # very primitive test !!!
		if vmr:
			write_namelist_profile (out, data.densities[:,m], data.gases[m], unit='ppv', format='%10.4g')
		else:
			if saveVMR and hasattr(data,'densities'):
				VMR = 1.e6*data.densities[:,m]/data.air
				write_namelist_profile (out, VMR, data.gases[m], unit='ppm', format='%10.4g')
			else:
				write_namelist_profile (out, data.densities[:,m], data.gases[m], unit='1/cm**3', format='%10.4g')
示例#13
0
def write_crossSections_xy (crossSections, outFile=None, linePositions=None, commentChar='#'):
	""" Write cross section(s) to output (file) in tabular xy format.
	    (Cross sections of a given molecule (i.e., data for all p,T levels) are written to a individual files) """

	# extract attributes like pressure and temperatures
	nXS = len(crossSections)
	molecules    = tuple([xs.get('molecule') for xs in crossSections])
	pressures    = tuple([unitConversion(xs.get('p',0.0),'p',new='mb') for xs in crossSections])
	temperatures = tuple([xs.get('T',0.0) for xs in crossSections])
	lineShapes   = tuple([xs.get('lineShape') for xs in crossSections])
	if isinstance(linePositions,np.ndarray):
		lineInfo =  '%i %s %f ... %f' % (len(linePositions), 'lines in ', min(linePositions),max(linePositions))
	else:
		lineInfo = ''

	for l, xs in enumerate(crossSections):
		if isinstance(outFile,str) and '.' in outFile:
			outRoot, outExt = os.path.splitext(outFile)
			oFile = '%s_%2.2i_%gmb_%.1fK%s' % (outRoot, l+1, pressures[l], temperatures[l], outExt)
		else:   
			oFile = '%s_%gmb_%.1fK.%s' % (molecules[l], pressures[l], temperatures[l], 'xs')
		out = open_outFile (oFile, commentChar)
		# print a summary
		out.write ( '%1s  %-16s %s\n' % (commentChar, 'molecule:', molecules[l]))
		out.write ( '%1s  %-16s %s\n' % (commentChar, 'lineshape:', lineShapes[l]))
		if lineInfo:  out.write ( '%1s  %s\n' % (commentChar, lineInfo))
		out.write ( commentChar+'  pressure [mb]:  ' + ' %10g' % pressures[l] + '\n')
		out.write ( commentChar+'  temperature [K]:' + ' %10.2f' % temperatures[l] + '\n')
		out.write ( commentChar + '\n' )

		# extract cross section spectra and save in list
		yyy  = xs['y']
		nxy  = len(yyy)-1
		xLow, xHigh = crossSections[0]['x'].limits()
		xLo,  xHi   = float(xLow/nxy), float(xHigh/nxy)
		# and write cross section vs wavenumber
		out.write ( '%1s%12s %15s\n' % (commentChar, 'wavenumber', 'cross section') )
		format = ' %12f %12.6g\n'
		for i,y in enumerate(yyy): 
			x = i*xHi + (nxy-i)*xLo
			out.write (format % (x,y))
		
		if outFile: out.close()
示例#14
0
def read_line_file (lineFile, xLimits=None, airWidth=0.1, wingExt=0.0, molecule=None,  commentChar='#'):
	""" Read a simple line parameter list and return a dictionary:  lines and some attributes. """

	# wavenumber interval to be searched
	if xLimits:
		xLow, xHigh = xLimits.limits()
	else:
		xLow, xHigh = 0.0, 0.0

	# read entire line file and return a dictionary
	lines, comments = readDataAndComments (lineFile,commentChar)
	# if there is just a single line in the dataset, a 1dim array is returned
	lines = np.atleast_2d (lines)

	# parse comment header and extract some infos
	Line_Data = parse_file_header (comments, ['molecule','format','pressure','temperature'])

	# check if molecule is specified  (and consistent if specified in file and on command line)
	if molecule and Line_Data.has_key('molecule'):
		if not molecule==Line_Data['molecule']:
			raise SystemExit, 'ERROR:  inconsistent molecule specification!   ' + \
			                  repr(molecule) + ' <--> ' + repr(Line_Data['molecule'])
	elif Line_Data.has_key('molecule'):
		pass
	elif molecule:
		Line_Data['molecule'] = molecule
	else:
		print 'lineFile: ', lineFile
		raise SystemExit, 'ERROR:  molecule not specified (neither in line list header nor as command option)!'

	# also need reference pressure and temperature
	if Line_Data.has_key('temperature'):
		# remove unit spec 'Kelvin'
		Line_Data['temperature'] = float(split(Line_Data['temperature'])[0])
	else:
		raise SystemExit, 'ERROR:  reference temperature of line parameters not given!'
	if Line_Data.has_key('pressure'):
		try:    # remove unit spec 'millibar' and return pressure in cgs units!
			value_unit = split(Line_Data['pressure'])
			Line_Data['pressure'] = unitConversion(float(value_unit[0]), 'pressure', value_unit[1])
		except StandardError,errMsg: 
			raise SystemExit, str(errMsg) + '\nparsing pressure spec in line file failed ' + repr(Line_Data['pressure'])
示例#15
0
def write_voigtLines(voigtLines,
                     pressure,
                     temperature,
                     molecule,
                     outFile=None,
                     commentChar='#'):
    """ Write Voigt line parameters (strengths, Lorentz and Gaussian widths vs line positions. """
    out = open_outFile(outFile, commentChar)
    out.write('%s %s %s\n' % (commentChar, "molecule:", molecule))
    out.write('%s %s %-12g\n' % (commentChar, "pressure  [mb]:     ",
                                 unitConversion(pressure, 'p', new='mb')))
    out.write('%s %s %8.2f\n' %
              (commentChar, "temperature  [K]: ", temperature))
    out.write('%s %10s  %11s %11s %11s\n' %
              (commentChar, "position", "strength", "gammaL", "gammaG"))
    frmt = '%12f  %11.3e %11.3g %11.3g\n'
    for line in voigtLines:
        out.write(frmt % tuple(line))
    # close the output file (if its not stdout)
    if outFile: out.close()
示例#16
0
def write_crossSections_hitran (crossSections, outFile=None, lineLength=-1, format=' %12g'):
	""" Write cross section to output (file) in hitran format. """
	if outFile: out = open (outFile, 'w')
	else:       out = sys.stdout
	for xs in crossSections:
		nxs = len(xs['y'])
		xLow, xHigh = crossSections[0]['x'].limits()
		maxXS = max(xs['y'])
		out.write ('%s %f %f %i %g %8.3f %g\n' % (xs['molecule'], xLow, xHigh, nxs, unitConversion(xs['p'],'p',new='mb'), xs['T'], maxXS))
		if lineLength<1:
			# all data in a single long line
    			out.write ( str(nxs*format+'\n') % tuple(xs['y']) )
		elif lineLength>1:
			for i in xrange(0,nxs,lineLength):
    				lo, hi = i, min(i+lineLength,nxs)
    				out.write ( (hi-lo)*format % tuple(xs['y'][i:min(i+lineLength,nxs)]) + '\n' )
		else:
			# just one value per line
			frmt = format+'\n'
			for i in xrange(0,nxs):  out.write ( frmt % xs['y'][i])
    	if outFile: out.close()
示例#17
0
		raise SystemExit, 'ERROR:  no format specifier in line list!'

	# check if at least position and strengths are found
	if Line_Data.has_key('position') and Line_Data.has_key('strength'):
		firstLine = min(Line_Data['position'])
		lastLine  = max(Line_Data['position'])
		print '\n %-20s %8i lines in %10f ... %10f cm-1  with %8.2g < S < %8.2g   (T=%5.1fK)' % \
		       ( os.path.basename(lineFile), lines.shape[0], firstLine, lastLine, \
		         min(Line_Data['strength']), max(Line_Data['strength']), Line_Data['temperature'])
	else:
		raise SystemExit, 'ERROR:  Need at least line positions and strengths!'

	# set air broadening parameter to default if not found in line file
	if Line_Data.has_key('airWidth'):
		print '%s %8g < g < %8g   (p=%gmb)' % \
		       ( 75*' ', min(Line_Data['airWidth']), max(Line_Data['airWidth']), unitConversion(Line_Data['pressure'],'p', new='mb'))
	else:
		Line_Data['airWidth'] = np.zeros_like(Line_Data['position']) + airWidth
		print 'Air width initialized to ', airWidth

	if Line_Data.has_key('TempDep'):
		print '%s %8g < n < %8g' % ( 75*' ', min(Line_Data['TempDep']), max(Line_Data['TempDep']))

	if xLow and xHigh:
		# subset of lines requested, truncate lists
		print ' get_line_data:  xLow,xHigh specified: ', xLow, xHigh, '  (extension:  +/-', wingExt,')'
		Line_Data   = truncate_lineList (Line_Data,  xLow-wingExt, xHigh+wingExt)

	return Line_Data

####################################################################################################################################
示例#18
0
def _lines_(lineFiles,
            outFile='',
            commentChar='#',
            pressure=None,
            temperature=None,
            xLimits=None,
            airWidth=0.1,
            lineAtlas='S',
            verbose=False):
    """ Read a couple of lines from vSEan file(s) and convert to new pressure|temperature and/or plot|save data."""

    # get the line data
    dictOfLineLists = read_line_file(lineFiles,
                                     xLimits,
                                     airWidth,
                                     commentChar=commentChar,
                                     verbose=verbose)

    # extract the attributes
    #lineAttr = dict([(key,dictOfLineLists.pop(key)) for key in ['pressure','temperature']])

    #if abs(pressure-lineAttr['pressure'])/lineAttr['pressure']>0.01 and abs(temperature-lineAttr['temperature'])>1.0:
    if isinstance(pressure,
                  (int, float)) or isinstance(temperature, (int, float)):
        if pressure: pressure = unitConversion(pressure, 'p', old='mb')

        for molec, data in list(dictOfLineLists.items()):
            if not molec == data.molec:
                raise SystemExit('%s %s %s' %
                                 ('ERROR --- _lines__:  inconsistent molec ',
                                  molec, data.molec))
            # read molecular data (mass etc.)
            molData = get_molec_data(molec)
            if verbose: print(molec, molData)

            # adjust line parameters to p, T
            if not pressure:
                pressure = data.p
                print(
                    ' INFO --- _lines_:  set pressure to line reference pressure',
                    data.p, data.molec)
            if not temperature:
                temperature = data.t
                print(
                    ' INFO --- _lines_:  set temperature to line reference temperature',
                    data.t, data.molec)
            voigtLines = voigt_parameters(data, molData, pressure, temperature,
                                          verbose)
            if verbose:
                print('%10s %10.2g <S<%10.2g' %
                      (molec, min(voigtLines['S']), max(voigtLines['S'])))

            # plot line strength vs position
            if lineAtlas == 'T':
                vlines(voigtLines['v'],
                       data['S'],
                       voigtLines['S'],
                       label=molec)
            elif lineAtlas:
                semilogy(voigtLines['v'], voigtLines['S'], '+', label=molec)
            ylabel(r'$S(T)$')

            # optionally save converted line data
            if isinstance(outFile, str):
                write_voigtLines(voigtLines, pressure, temperature, molec,
                                 molec + outFile, commentChar)

        # annotate plot
        if lineAtlas:
            title(r'$p$=%.2edyn/cm**2 \qquad $T$=%.1fK' %
                  (pressure, temperature))
    else:
        if not lineAtlas == 'T': atlas(dictOfLineLists, yType=lineAtlas)

    if lineAtlas:
        legend()
        show()
示例#19
0
def read_line_file(lineFile,
                   xLimits=None,
                   wingExt=0.0,
                   airWidth=0.1,
                   molecule=None,
                   commentChar='#',
                   verbose=False):
    """ Read a simple line parameter list and return a structured numpy array with data and some attributes.

	    ARGUMENTS:
	    ----------
	    lineFile    a single file or a list thereof
	                (if it is a list of files, a dictionary of line lists will be returned!)
	    xLimits     accept only lines with position in this interval (extended by `wingExt`)
	    airWidth    default air broadening halfwidth, only used when not given in lineFile
	    wingExt     extend the line position interval xLimits (unused otherwise)
	    molecule    molecular name, only used when not given in lineFile

	    RETURNS:
	    --------
            lineArray   a structured numpy array with line position, strengths, etc.
	                and attributes (molecule, pressure, temperature) added by subclassing
			(OR a dictionary of lineArray's for a list of input files)

	    NOTE:
	    -----
	    If you want to read all/several (line) files in a directory, you can use Python's glob function, e.g.
	    dll = read_line_file(glob('*'))       # returns a Dictionary of LineLists (one per file)
	    dll = read_line_file(glob('*.vSEan'))
	"""

    #from glob import glob
    #if '*' in lineFile or '?' in lineFile:  lineFile = glob(lineFile)

    if isinstance(lineFile, (list, tuple)):
        dictLineLists = {}
        for file in lineFile:
            lineListArray = read_line_file(file, xLimits, wingExt, airWidth,
                                           molecule, commentChar, verbose)
            dictLineLists[lineListArray.molec] = lineListArray
        return dictLineLists

    # read entire line file and return a structured array and a dictionary of attributes
    lines = loadStrucArray(lineFile,
                           'position',
                           changeNames=long2short,
                           verbose=verbose)
    # if there is just a single line in the dataset, a 1dim array is returned
    if lines.ndim == 0:
        raise SystemExit(
            'WARNING --- lines.read_line_file: just one line, needs more work')
    #lines = np.atleast_2d (lines)

    # parse comment header and extract some attributes (returned as dictionary)
    lineAttr = parse_comments(
        readFileHeader(lineFile, commentChar),
        ['molecule', 'gas', 'format', 'pressure', 'temperature'])

    # check if molecule is specified  (and consistent if specified in file and on command line)
    if molecule and 'molecule' in lineAttr:
        if not molecule == lineAttr['molecule']:
            raise SystemExit(
                'ERROR --- lines.read_line_file:  inconsistent molecule specification!   '
                + repr(molecule) + ' <--> ' + repr(lineAttr['molecule']))
    elif 'gas' in lineAttr:
        lineAttr['molecule'] = lineAttr.pop('gas')
    elif 'molecule' in lineAttr:
        pass
    elif molecule:
        lineAttr['molecule'] = molecule
    else:
        fileRoot = os.path.splitext(lineFile)[0]
        if os.path.sep in fileRoot: fileRoot = os.path.split(fileRoot)[1]
        if fileRoot in list(molecules.keys()):
            lineAttr['molecule'] = molecule
        else:
            raise SystemExit(
                'ERROR --- lines.read_line_file:  ' + lineFile +
                '\nmolecule not specified!' +
                '\n(neither in line list header nor root of filename nor as command option)'
            )

    # also need reference pressure and temperature
    if 'temperature' in lineAttr:
        # remove unit spec 'Kelvin'
        lineAttr['temperature'] = float(lineAttr['temperature'].split()[0])
    else:
        raise SystemExit(
            'ERROR --- lines.read_line_file:  reference temperature of line parameters not given!'
        )

    if 'pressure' in lineAttr:
        try:  # remove unit spec 'millibar' and return pressure in cgs units!
            value, unit = lineAttr['pressure'].split()
            lineAttr['pressure'] = unitConversion(float(value), 'pressure',
                                                  unit)
        except Exception as errMsg:
            raise SystemExit(
                str(errMsg) + '\nparsing pressure spec in line file failed ' +
                repr(lineAttr['pressure']))
    else:
        raise SystemExit(
            'ERROR --- lines.read_line_file:  reference pressure of line parameters not given!'
        )

    # check if at least position and strengths are found
    if 'v' in lines.dtype.names and 'S' in lines.dtype.names:
        print(
            '\n %-18s %8i lines in  %10f ... %10f cm-1   with  %8.2g < S < %8.2g   (T=%5.1fK)'
            % (os.path.basename(lineFile), lines.shape[0], min(
                lines['v']), max(lines['v']), min(lines['S']), max(
                    lines['S']), lineAttr['temperature']))
    else:
        raise SystemExit(
            'ERROR --- lines.read_line_file:  Need at least line positions and strengths!'
        )

    # lower state energy
    if 'E' in lines.dtype.names:
        if verbose:
            print('%s %8g < E < %8g' %
                  (77 * ' ', min(lines['E']), max(lines['E'])))
    else:
        print(
            'WARNING --- lines.read_line_file:  no lower state energy, no S(T) conversion!'
        )

    # set air broadening parameter to default if not found in line file
    if 'a' in lines.dtype.names:
        if verbose:
            print('%s %8g < a < %8g   (p=%gmb)' %
                  (77 * ' ', min(lines['a']), max(lines['a']),
                   unitConversion(lineAttr['pressure'], 'p', new='mb')))
    else:
        lines = strucArrayAddField(lines,
                                   np.zeros_like(lines['v']) + airWidth, 'a')
        print('INFO --- lines.read_line_file:  air width initialized to ',
              airWidth)

    if verbose:
        if 's' in lines.dtype.names:
            print('%s %8g < s < %8g' %
                  (77 * ' ', min(lines['s']), max(lines['s'])))
        if 'n' in lines.dtype.names:
            print('%s %8g < n < %8g' %
                  (77 * ' ', min(lines['n']), max(lines['n'])))
        if 'm' in lines.dtype.names:
            print('%s %8g < Y < %8g' %
                  (77 * ' ', min(lines['m']), max(lines['m'])))  # line Mixing

    if xLimits:
        if isinstance(xLimits, (list, tuple)): xLimits = Interval(*xLimits)
        # subset of lines requested, truncate lists
        print(' read_line_file:  xLow,xHigh specified: ', xLimits,
              '  (extension:  +/-', wingExt, ')')
        lines = truncate_lineList(lines, xLimits + wingExt)

    # All data and attributes defined, finally add attributes to the numpy array by subclassing
    return lineArray(lines,
                     p=lineAttr['pressure'],
                     t=lineAttr['temperature'],
                     molec=lineAttr['molecule'])