Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
df: DataFrame
list of transitions
Other Parameters
----------------
calc_Evib_harmonic_anharmonic: boolean
if ``True``, calculate harmonic and anharmonic components of
vibrational energies (for Treanor distributions)
'''
if self.verbose:
print('Fetching Evib & Erot.')
if self.verbose >= 2:
printg('If using this code several' +
' times you should consider updating the database' +
' directly. See functions in factory.py ')
from radis.io.hitran import HITRAN_CLASS1, HITRAN_CLASS5
# Different methods to get Evib and Erot:
# fetch energies from precomputed CDSD levels: one Evib per (p, c) group
if self.params.levelsfmt == 'cdsd-pc':
return self._add_EvibErot_CDSD_pc(df, calc_Evib_harmonic_anharmonic=calc_Evib_harmonic_anharmonic)
# fetch energies from precomputed CDSD levels: one Evib per (p, c, N) group
elif self.params.levelsfmt == 'cdsd-pcN':
return self._add_EvibErot_CDSD_pcN(df, calc_Evib_harmonic_anharmonic=calc_Evib_harmonic_anharmonic)
# fetch energies from CDSD levels calculated from Hamiltonian: one Evib per (p, c, J, N) group
Performances of buffer mode:
on the 2Gb CDSD-HITEMP database (1-20), already cached in .h5
- ``'RAM'``: 7.1 s
- ``'h5'``: 21 s
'''
# Check inputs
assert db_use_cached in [True, False, 'regen']
assert buffer in ['RAM', 'h5', 'direct']
if self.verbose >= 2:
printg('Loading Line databank')
t0 = time()
# Init variables
verbose = self.verbose
warnings_default = self.warnings['default'] if self.warnings else False
wavenum_min = self.params.wavenum_min_calc
wavenum_max = self.params.wavenum_max_calc
# Check inputs
if buffer == 'direct':
assert len(database) == 1
assert database[0].endswith('h5')
if drop_columns == 'auto':
drop_columns = (drop_auto_columns_for_dbformat[dbformat] +
drop_auto_columns_for_levelsfmt[levelsfmt])
# # (tested + see https://stackoverflow.com/questions/44954514/efficient-way-to-conditionally-populate-elements-in-a-pandas-groupby-object-pos)
#
# partition function
dgb = df.groupby(by=['id', 'iso'])
for (id, iso), idx in dgb.indices.items():
molecule = get_molecule(id)
state = self.input.state
parsum = get_parsum(molecule, iso, state)
df.at[idx, 'Qref'] = parsum.at(Tref, update_populations=False)
if radis.DEBUG_MODE:
assert (df.loc[idx, 'id'] == id).all()
assert (df.loc[idx, 'iso'] == iso).all()
if self.verbose >= 3:
printg('... map partition functions in {0:.2f}s'.format(time()-t1))
t1 = time()
# Correct linestrength
# ... populations without abundance dependance (already in linestrength)
nu = df.nu # Note: populations are not corrected for abundance
nl = df.nl
# ... remove Qref, nref, etc.
# start from for tabulated linestrength
line_strength = df.int.copy()
# ... correct for lower state population
line_strength /= (df.gl * exp(-hc_k*df.El/Tref)/df.Qref)
line_strength *= nl
# ... correct effect of stimulated emission
self.warn("There are not lines in database in range {0:.5f}-{1:.5f}cm-1 ".format(
wavenum_min, wavenum_min + broadening) + "to calculate the effect " +
"of neighboring lines. Did you add all lines in the database?",
"OutOfRangeLinesWarning")
if maxwavdb < wavenum_max - broadening:
# no lines on right side
self.warn("There are not lines in database in range {0:.5f}-{1:.5f}cm-1 ".format(
maxwavdb - broadening, maxwavdb) + "to calculate the effect " +
"of neighboring lines. Did you add all lines in the database?",
"OutOfRangeLinesWarning")
# Complete database with molecular parameters
self._fetch_molecular_parameters(df)
if self.verbose >= 2:
printg('Loaded databank in {0:.1f}s ({1:,d} lines)'.format(time()-t0, len(df)))
return df
df: DataFrame
list of transitions
'''
if __debug__:
printdbg(
'called _add_Evib123Erot_RADIS_cls5_harmonicanharmonic()')
molecule = self.input.molecule
state = self.input.state # electronic state
# TODO: for multi-molecule mode: add loops on molecules and states too
if self.verbose>=2:
printg('Fetching vib / rot energies for all {0} transitions'.format(len(df)))
t0 = time()
# Check energy levels are here
for iso in self._get_isotope_list(molecule):
if not iso in self.parsum_calc[molecule]:
raise AttributeError('No Partition function calculator defined for isotope {0}'.format(iso)
+ '. You need energies to calculate a non-equilibrium spectrum!'
+ ' Fill the levels parameter in your database definition, '
+ ' with energies of known format: {0}'.format(KNOWN_LVLFORMAT)
+ '. See SpectrumFactory.load_databank() help for more details')
def get_Evib123_RADIS_cls5_1iso_ah(df, iso):
''' Fetch Evib & Erot for a given isotope (energies are specific
to a given isotope). Returns harmonic, anharmonic components
Notes
Returns
-------
None
store weak line status in dataframe as ``self.df1.weak_line``
'''
# Get inputs
wavenumber_calc = self.wavenumber_calc # size W
wstep = self.params.wstep
df = self.df1 # lines already scaled with current temperature, size N
if self.verbose>=2:
printg('... classifying lines as weak or strong')
t0 = time()
# Get approximate spectral absorption coefficient
rough_spectrum, S_density_on_grid, line2grid_proj_left = project_lines_on_grid(
df, wavenumber_calc, wstep)
# :
# ~ 1/(#.cm-2)
# Sizes:
# - rough_spectrum: size W
# - S_density_on_grid: size N
# - line2grid_proj: size N
# Weak line criteria
# ... Compare line density (in 1/(#.cm-2) to sum)
line_is_weak = S_density_on_grid < (
waveunit=self.params.waveunit, # cm-1
# dont check input (much faster, and Spectrum
warnings=False,
# is freshly baken so probably in a good format
name=name,
)
# update database if asked so
if self.autoupdatedatabase:
self.SpecDatabase.add(s, if_exists_then='increment')
# Tvib=Trot=Tgas... but this way names in a database
# generated with eq_spectrum are consistent with names
# in one generated with non_eq_spectrum
if self.verbose >= 2:
printg('Generated spectrum in {0:.2f}s'.format(time()-t1))
return s
except:
# An error occured: clean before crashing
self._clean_temp_file()
raise
sumoflines_calc = np.fft.ifftshift(np.fft.ifft(Idlm_FT).real)
sumoflines_calc = sumoflines_calc[len(wavenumber_calc)//2:len(wavenumber_calc)//2+len(wavenumber_calc)]
sumoflines_calc /= self.params.wstep
else:
raise NotImplementedError(self._broadening_method)
if __debug__:
t3 = time()
# Get valid range (discard wings)
sumoflines = sumoflines_calc[self.woutrange]
if __debug__:
if self.verbose >= 3:
printg('... Initialized vectors in {0:.1f}s'.format(t1-t0))
printg('... Get closest matching line & fraction in {0:.1f}s'.format(t2-t1))
printg('... Distribute lines over DLM {0:.1f}s'.format(t21-t2))
printg('... Convolve and sum on spectral range {0:.1f}s'.format(t3-t21))
return wavenumber, sumoflines
# Reduce line dataset to strong lines only
self.df1 = df_strong_lines
# Update number of lines
self._Nlines_in_continuum = len(df_weak_lines)
self._Nlines_calculated = len(self.df1)
# Check performances
time_spent = time()-t0
# ... Expected broadening time gain (see Rule of Thumb)
expected_broadening_time_gain = (self._broadening_time_ruleofthumb*
self._Nlines_in_continuum*
len(self.wbroad_centered))
if self.verbose>=2:
printg('Calculated pseudo-continuum in {0:.1f}s (expected time saved: {1:.1f}s)'.format(
time_spent, expected_broadening_time_gain))
# Add a warning if it looks like it wasnt worth it
if time_spent > 3*expected_broadening_time_gain:
self.warn('Pseudo-continuum may not be adapted to this kind '+\
'of spectrum. Time spent on continuum calculation '+\
'({0:.1f}s) is much longer than expected gain ({1:.1f}s). '.format(
time_spent, expected_broadening_time_gain)+\
'If the calculation takes a lot of time, consider '+\
'setting pseudo_continuum_threshold=0. If it is fast '+\
'enough already, you can decrease the linestrength cutoff= '+\
'parameter to add discarded weak lines to continuum '+\
'and improve the calculation accuracy.',
'PerformanceWarning')
else:
'''
if __debug__:
printdbg(
'called _add_Evib123Erot_CDSD_pc(calc_Evib_harmonic_anharmonic={0})'.format(calc_Evib_harmonic_anharmonic))
if calc_Evib_harmonic_anharmonic:
raise NotImplementedError
molecule = self.input.molecule
state = self.input.state # electronic state
# TODO: for multi-molecule mode: add loops on molecules and states too
assert molecule == 'CO2'
if self.verbose>=2:
printg('Fetching vib123 / rot energies for all {0} transitions'.format(len(df)))
t0 = time()
# Get Energy database
if self.parsum_calc == {}:
raise AttributeError('No Partition function calculator defined in this database'
+ '. You need energies to calculate a non-equilibrium spectrum!'
+ ' Fill the levels parameter in your database definition, '
+ ' with energies of known format: {0}'.format(KNOWN_LVLFORMAT)
+ '. See SpectrumFactory.load_databank() help for more details')
def get_Evib123_CDSD_pc_1iso(df, iso):
''' Calculate Evib for a given isotope (energies are specific
to a given isotope) '''
# TODO: implement with map() instead (much faster!! see get_Evib_CDSD_* )
energies = self.get_energy_levels(molecule, iso, state)