Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
spec: Spectrum
'''
unit = None
def get_radiance_unit(unit_emisscoeff):
''' get radiance_noslit unit from emisscoeff unit'''
if '/cm3' in unit_emisscoeff:
return unit_emisscoeff.replace('/cm3', '/cm2')
else:
return unit_emisscoeff + '*cm'
# case where we recomputed it already (somehow... ex: no_change signaled)
if 'radiance_noslit' in rescaled:
if __debug__:
printdbg('... rescale: radiance_noslit was scaled already')
assert 'radiance_noslit' in units
return rescaled, units
# Rescale!
if 'emisscoeff' in rescaled and true_path_length and optically_thin:
if __debug__:
printdbg('... rescale: radiance_noslit I2 = j2 * L2 ' +
'(optically thin)')
emisscoeff = rescaled['emisscoeff'] # x already scaled
radiance_noslit = emisscoeff*new_path_length # recalculate L
unit = get_radiance_unit(units['emisscoeff'])
elif ('emisscoeff' in rescaled and 'transmittance_noslit' in rescaled
and 'abscoeff' in rescaled and true_path_length and not optically_thin): # not optically thin
if __debug__:
printdbg('... rescale: radiance_noslit I2 = j2*(1-T2)/k2')
if __debug__:
printdbg('... rescale: radiance_noslit I2 = j2*(1-T2)/k2')
emisscoeff = rescaled['emisscoeff'] # x already scaled
abscoeff = rescaled['abscoeff'] # x already scaled
# mole_fraction, path_length already scaled
transmittance_noslit = rescaled['transmittance_noslit']
b = (transmittance_noslit == 1) # optically thin mask
radiance_noslit = np.empty_like(emisscoeff) # calculate L
radiance_noslit[~b] = emisscoeff[~b] / abscoeff[~b]*(1-transmittance_noslit[~b])
radiance_noslit[b] = emisscoeff[b] * new_path_length # optically thin limit
unit = get_radiance_unit(units['emisscoeff'])
elif ('emisscoeff' in rescaled and 'abscoeff' in rescaled and true_path_length
and not optically_thin): # not optically thin
if __debug__:
printdbg('... rescale: radiance_noslit I2 = j2*(1-exp(-k2*L2))/k2')
emisscoeff = rescaled['emisscoeff'] # x already scaled
abscoeff = rescaled['abscoeff'] # x already scaled
b = (abscoeff == 0) # optically thin mask
radiance_noslit = np.empty_like(emisscoeff) # calculate
radiance_noslit[~b] = emisscoeff[~b]/abscoeff[~b] *(1-exp(-abscoeff[~b]*new_path_length))
radiance_noslit[b] = emisscoeff[b] * new_path_length # optically thin limit
unit = get_radiance_unit(units['emisscoeff'])
elif 'radiance_noslit' in initial and optically_thin:
if __debug__:
printdbg('... rescale: radiance_noslit I2 = I1*N2/N1*L2/L1 ' +
'(optically thin)')
_, radiance_noslit = spec.get(
'radiance_noslit', wunit=waveunit, Iunit=units['radiance_noslit'])
radiance_noslit *= new_mole_fraction / old_mole_fraction # rescale
radiance_noslit *= new_path_length / old_path_length # rescale
assert 'radiance_noslit' in units
return rescaled, units
# Rescale!
if 'emisscoeff' in rescaled and true_path_length and optically_thin:
if __debug__:
printdbg('... rescale: radiance_noslit I2 = j2 * L2 ' +
'(optically thin)')
emisscoeff = rescaled['emisscoeff'] # x already scaled
radiance_noslit = emisscoeff*new_path_length # recalculate L
unit = get_radiance_unit(units['emisscoeff'])
elif ('emisscoeff' in rescaled and 'transmittance_noslit' in rescaled
and 'abscoeff' in rescaled and true_path_length and not optically_thin): # not optically thin
if __debug__:
printdbg('... rescale: radiance_noslit I2 = j2*(1-T2)/k2')
emisscoeff = rescaled['emisscoeff'] # x already scaled
abscoeff = rescaled['abscoeff'] # x already scaled
# mole_fraction, path_length already scaled
transmittance_noslit = rescaled['transmittance_noslit']
b = (transmittance_noslit == 1) # optically thin mask
radiance_noslit = np.empty_like(emisscoeff) # calculate L
radiance_noslit[~b] = emisscoeff[~b] / abscoeff[~b]*(1-transmittance_noslit[~b])
radiance_noslit[b] = emisscoeff[b] * new_path_length # optically thin limit
unit = get_radiance_unit(units['emisscoeff'])
elif ('emisscoeff' in rescaled and 'abscoeff' in rescaled and true_path_length
and not optically_thin): # not optically thin
if __debug__:
printdbg('... rescale: radiance_noslit I2 = j2*(1-exp(-k2*L2))/k2')
emisscoeff = rescaled['emisscoeff'] # x already scaled
abscoeff = rescaled['abscoeff'] # x already scaled
assert 'transmittance_noslit' in units
return rescaled, units
# Calculate rescaled value directly
# ---------------------------------
# Rescale
if 'absorbance' in rescaled:
if __debug__:
printdbg('... rescale: transmittance_noslit T2 = exp(-A2)')
absorbance = rescaled['absorbance'] # x and L already scaled
transmittance_noslit = exp(-absorbance) # recalculate
unit = get_unit()
elif 'abscoeff' in rescaled and true_path_length:
if __debug__:
printdbg('... rescale: transmittance_noslit T2 = exp(-j2*L2)')
abscoeff = rescaled['abscoeff'] # x already scaled
absorbance = abscoeff*new_path_length # calculate
transmittance_noslit = exp(-absorbance) # recalculate
unit = get_unit()
elif 'transmittance_noslit' in initial:
if __debug__:
printdbg('... rescale: transmittance_noslit T2 = ' +
'exp( ln(T1) * N2/N1 * L2/L1)')
# get transmittance from initial transmittance
_, T1 = spec.get('transmittance_noslit', wunit=waveunit,
Iunit=units['transmittance_noslit'])
# We'll have a problem if the spectrum is optically thick
b = (T1 == 0) # optically thick mask
if b.sum() > 0 and (new_mole_fraction < old_mole_fraction or
new_path_length < old_path_length):
'Unknown normalization type: `norm_by` = {0}'.format(norm_by))
# Plot in correct unit (plot_slit deals with the conversion if needed)
fig, ax = plot_slit(wslit0, Islit0, waveunit=waveunit, plot_unit=wunit,
Iunit=Iunit)
# Plot other slit functions if dispersion was applied:
if 'slit_dispersion' in self.conditions:
slit_dispersion = self.conditions['slit_dispersion']
if slit_dispersion is not None:
waveunit = self.get_waveunit()
if waveunit == 'nm':
wslit0_nm = wslit0
else:
wslit0_nm = cm2nm(wslit0)
w_nm = self.get_wavelength(medium='default', which='non_convoluted')
wings = len(wslit0) # note: hardcoded. Make sure it's the same as in apply_slit
wings *= max(1, abs(int(np.diff(wslit0_nm).mean() / np.diff(w_nm).mean())))
slice_windows, wings_min, wings_max = _cut_slices(w_nm, slit_dispersion, wings=wings)
# Loop over all waverange slices (needed if slit changes over the spectral range)
for islice, slice_window in enumerate(slice_windows):
w_nm_sliced = w_nm[slice_window]
w_min = w_nm_sliced.min()
w_max = w_nm_sliced.max()
# apply spectrometer linear dispersion function.
# dont forget it has to be added in nm and not cm-1
wslit, Islit = offset_dilate_slit_function(wslit0_nm, Islit0,
w_nm[slice_window],
'A (top, base) tuple must be used with a trapezoidal slit')
# ... first get FWHM in our wavespace unit
if return_unit == 'cm-1' and unit == 'nm':
# center_wavespace ~ nm, FWHM ~ nm
top = dnm2dcm(top, center_wavespace) # wavelength > wavenumber
base = dnm2dcm(base, center_wavespace) # wavelength > wavenumber
center_wavespace = nm2cm(center_wavespace)
if norm_by == 'max':
scale_slit = sum(slit_function) / \
(top+base) # [unit/return_unit]
elif return_unit == 'nm' and unit == 'cm-1':
# center_wavespace ~ cm-1, FWHM ~ cm-1
top = dcm2dnm(top, center_wavespace) # wavenumber > wavelength
base = dcm2dnm(base, center_wavespace) # wavenumber > wavelength
center_wavespace = cm2nm(center_wavespace)
if norm_by == 'max':
scale_slit = sum(slit_function) / \
(top+base) # [unit/return_unit]
else:
pass # correct unit already
FWHM = (top+base)/2
# ... now, build it (in our wavespace)
if __debug__:
printdbg('get_slit_function: {0}, FWHM {1:.2f}{2}, center {3:.2f}{2}, norm_by {4}'.format(
shape, FWHM, return_unit, center_wavespace, norm_by))
wslit, Islit = trapezoidal_slit(top, base, wstep,
center=center_wavespace, bplot=plot,
norm_by=norm_by,
# TODO @dev: rewrite with wunit='cm-1', 'nm_air', 'nm_vac'
waveunit = s.get_waveunit()
wmin0, wmax0 = wmin, wmax
if wunit == 'nm' and waveunit == 'cm-1':
if medium == 'air':
if wmax0: wmin = nm_air2cm(wmax0) # reverted
if wmin0: wmax = nm_air2cm(wmin0) # reverted
else:
if wmax0: wmin = nm2cm(wmax0) # reverted
if wmin0: wmax = nm2cm(wmin0) # reverted
elif wunit == 'cm-1' and waveunit == 'nm':
if s.get_medium() == 'air':
if wmax0: wmin = cm2nm_air(wmax0) # nm in air
if wmin0: wmax = cm2nm_air(wmin0) # nm in air
else:
if wmax0: wmin = cm2nm(wmax0) # get nm in vacuum
if wmin0: wmax = cm2nm(wmin0) # get nm in vacuum
elif wunit == 'nm' and waveunit == 'nm':
if s.get_medium() == 'air' and medium == 'vacuum':
# convert from given medium ('vacuum') to spectrum medium ('air')
if wmin0: wmin = vacuum2air(wmin0)
if wmax0: wmax = vacuum2air(wmax0)
elif s.get_medium() == 'vacuum' and medium == 'air':
# the other way around
if wmin0: wmin = air2vacuum(wmin0)
if wmax0: wmax = air2vacuum(wmax0)
else:
assert wunit == waveunit # correct wmin, wmax
# Crop non convoluted
if len(s._q)>0:
b = ones_like(s._q['wavespace'], dtype=bool)
try:
# 143 us (2 ms with deepcopy(lines))
lines = self.lines.copy(deep=True)
except AttributeError:
pass
try:
populations = self.populations
except AttributeError:
populations = None
waveunit = self.get_waveunit() # 163 ns
name = self.name
# Generate copied Spectrum
s = Spectrum( # 1.51 ms
quantities=quantities,
conditions=conditions,
cond_units=cond_units,
populations=populations,
lines=lines,
units=units,
waveunit=waveunit,
name=name,
warnings=False, # saves about 3.5 ms on the Performance test object
)
# Add extra information
# ... file name (if exists)
s.file = self.file
if not inplace:
s = s.copy()
# Convert wmin, wmax to Spectrum wavespace
# (deal with cases where wavelength are given in 'air' or 'vacuum')
# TODO @dev: rewrite with wunit='cm-1', 'nm_air', 'nm_vac'
waveunit = s.get_waveunit()
wmin0, wmax0 = wmin, wmax
if wunit == 'nm' and waveunit == 'cm-1':
if medium == 'air':
if wmax0: wmin = nm_air2cm(wmax0) # reverted
if wmin0: wmax = nm_air2cm(wmin0) # reverted
else:
if wmax0: wmin = nm2cm(wmax0) # reverted
if wmin0: wmax = nm2cm(wmin0) # reverted
elif wunit == 'cm-1' and waveunit == 'nm':
if s.get_medium() == 'air':
if wmax0: wmin = cm2nm_air(wmax0) # nm in air
if wmin0: wmax = cm2nm_air(wmin0) # nm in air
else:
if wmax0: wmin = cm2nm(wmax0) # get nm in vacuum
if wmin0: wmax = cm2nm(wmin0) # get nm in vacuum
elif wunit == 'nm' and waveunit == 'nm':
if s.get_medium() == 'air' and medium == 'vacuum':
# convert from given medium ('vacuum') to spectrum medium ('air')
if wmin0: wmin = vacuum2air(wmin0)
if wmax0: wmax = vacuum2air(wmax0)
elif s.get_medium() == 'vacuum' and medium == 'air':
# the other way around
if wmin0: wmin = air2vacuum(wmin0)
if wmax0: wmax = air2vacuum(wmax0)
wstep = abs(diff(w)).min()
assert wstep > 0
waveunit = self.get_waveunit()
if __debug__:
printdbg('apply_slit: {0} in {1}, center `{2}`{1}, applied in waveunit {3}'.format(
slit_function, unit, center_wavespace, waveunit))
if center_wavespace is None:
# center_wavespace should be ~ unit
center_wavespace = w[len(w)//2] # w ~ waveunit
if waveunit == 'cm-1' and unit == 'nm':
center_wavespace = cm2nm(
center_wavespace) # wavenum > wavelen
elif waveunit == 'nm' and unit == 'cm-1':
center_wavespace = nm2cm(
center_wavespace) # wavelen > wavenum
# Get slit once and for all (and convert the slit unit
# to the Spectrum `waveunit` if wavespaces are different)
# -------
wslit0, Islit0 = get_slit_function(slit_function, unit=unit, norm_by=norm_by,
shape=shape, center_wavespace=center_wavespace,
return_unit=waveunit, wstep=wstep,
auto_recenter_crop=auto_recenter_crop,
verbose=verbose,
plot=plot_slit, *args, **kwargs)
# Check if dispersion is too large
# ----
if waveunit == 'nm':
w_nm = w