def emissivity(self, density: u.cm**(-3), include_energy=False, **kwargs):
"""
Calculate emissivity for all lines as a function of temperature and density
"""
populations = self.level_populations(density, include_protons=kwargs.get('include_protons', True))
if populations is None:
return (None, None)
wavelengths = np.fabs(self._wgfa['wavelength'])
# Exclude 0 wavelengths which correspond to two-photon decays
upper_levels = self._wgfa['upper_level'][wavelengths != 0*u.angstrom]
a_values = self._wgfa['A'][wavelengths != 0*u.angstrom]
wavelengths = wavelengths[wavelengths != 0*u.angstrom]
if include_energy:
energy = const.h.cgs*const.c.cgs/wavelengths.to(u.cm)
else:
energy = 1.*u.photon
emissivity = populations[:, :, upper_levels - 1]*(a_values*energy)
return wavelengths, emissivity
python类angstrom()的实例源码
def make_box_filter(cls, center, width):
"""
Make a box filter with the given parameters. Both center and width should either be in angstroms,
or be astropy quantities.
"""
if not isinstance(center, u.quantity.Quantity):
center *= u.angstrom
if not isinstance(width, u.quantity.Quantity):
width *= u.angstrom
return pysynphot.Box(center.to(u.angstrom).value, width.to(u.angstrom).value)
def test_creation():
wvln = np.linspace(1000., 4000., 1024)
flux = np.random.uniform(0., 1., wvln.size)
# try with list, array, Quantity input
s = Spectrum(list(wvln), list(flux))
s = Spectrum(wvln, flux)
s = Spectrum(wvln*u.angstrom, flux*u.erg/u.cm**2/u.angstrom)
# ------------------------------------------------------------------------
# Check that creation fails as expected if:
# 1) shapes don't match
with pytest.raises(ValueError):
s = Spectrum(wvln[:-1], flux)
with pytest.raises(ValueError):
s = Spectrum(wvln, flux[:-1])
# 2) object can't be coerced to a Quantity
with pytest.raises(TypeError):
s = Spectrum(wvln, None)
with pytest.raises(TypeError):
s = Spectrum(None, flux)
with pytest.raises(TypeError):
s = Spectrum(None, None)
# 3) wavelength goes negative
wvln2 = wvln.copy()
wvln2[:-10] *= -1.
with pytest.raises(ValueError):
s = Spectrum(wvln2, flux)
def test_integrate():
subslice = slice(100,200)
wvln = np.linspace(1000., 4000., 1024)
flux = np.zeros_like(wvln)
flux[subslice] = 1./np.ptp(wvln[subslice]) # so the integral is 1
s = Spectrum(wvln*u.angstrom, flux*u.erg/u.cm**2/u.angstrom)
# the integration grid is a sub-section of the full wavelength array
wvln_grid = s.wavelength[subslice]
i_flux = s.integrate(wvln_grid)
assert np.allclose(i_flux.value, 1.) # "close" because this is float comparison
def spec_to_redmonster_format(spec, fitsname, n_id=None, mag=None):
"""
Function used to create a spectrum in the REDMONSTER software format
:param spec: XSpectrum1D object
:param mag: List containing 2 elements, the first is the keyword in the header that will contain the magnitud saved in the second element
:param fitsname: Name of the fitsfile that will be created
:return:
"""
from scipy import interpolate
wave = spec.wavelength.value
wave_log = np.log10(wave)
n = len(wave)
spec.wavelength = wave_log * u.angstrom
new_wave_log = np.arange(wave_log[1], wave_log[n - 2], 0.0001)
spec_rebined = spec.rebin(new_wv=new_wave_log * u.angstrom)
flux = spec_rebined.flux.value
f = interpolate.interp1d(wave_log, spec.sig.value)
sig = f(new_wave_log)
inv_sig = 1. / np.array(sig) ** 2
inv_sig = np.where(np.isinf(inv_sig), 0, inv_sig)
inv_sig = np.where(np.isnan(inv_sig), 0, inv_sig)
hdu1 = fits.PrimaryHDU([flux])
hdu2 = fits.ImageHDU([inv_sig])
hdu1.header['COEFF0'] = new_wave_log[0]
hdu1.header['COEFF1'] = new_wave_log[1] - new_wave_log[0]
if n_id != None:
hdu1.header['ID'] = n_id
if mag != None:
hdu1.header[mag[0]] = mag[1]
hdulist_new = fits.HDUList([hdu1, hdu2])
hdulist_new.writeto(fitsname, clobber=True)
def predicted_wavelength(self, pixel):
"""Find the predicted wavelength value for a given pixel
It is possible to estimate the wavelength position of any pixel given
the instrument configuration.
Notes:
The equations are not precise enough so the value returned here has
to be used as an estimate only.
Args:
pixel (int): Pixel number.
Returns:
Wavelength value in angstrom.
"""
# TODO (simon): Update with bruno's new calculations
alpha = self.alpha
beta = self.beta
# pixel_count = self.pixel_count
binning = self.serial_binning
grating_frequency = self.grating_frequency
wavelength = 10 * (1e6 / grating_frequency) * \
(np.sin(alpha * np.pi / 180.) +
np.sin((beta * np.pi / 180.) +
np.arctan((pixel * binning - 2048) *
0.015 / 377.2)))
return wavelength
def register_mark(self, event):
"""Marks a line
Detects where the click was done or m-key was pressed and calls the
corresponding method. It handles the middle button click and m-key being
pressed. There are two regions of interest as for where a click was
done. The raw and reference data respectively. For any of such regions
it will call the method that recenter the line and once the desired
value is returned it will be appended to the list that contains all the
correspondent line positions, raw (pixels) and reference (angstrom)
Args:
event (object): Click or m-key pressed event
"""
if event.xdata is not None and event.ydata is not None:
figure_x, figure_y = \
self.i_fig.transFigure.inverted().transform((event.x, event.y))
if self.reference_bb.contains(figure_x, figure_y):
# self.reference_marks.append([event.xdata, event.ydata])
self.reference_marks_x.append(
self.recenter_line_by_data('reference', event.xdata))
self.reference_marks_y.append(event.ydata)
self.update_marks_plot('reference')
elif self.raw_data_bb.contains(figure_x, figure_y):
# self.raw_data_marks.append([event.xdata, event.ydata])
self.raw_data_marks_x.append(
self.recenter_line_by_data('raw-data', event.xdata))
self.raw_data_marks_y.append(event.ydata)
self.update_marks_plot('raw_data')
else:
self.log.debug('{:f} {:f} Are not contained'.format(figure_x,
figure_y))
else:
self.log.error('Clicked Region is out of boundaries')
def __init__(self, observing_time, observing_area=None, window=0.5*u.angstrom, apply_psf=True):
super().__init__(observing_time, observing_area)
self._setup_channels()
self.apply_psf = apply_psf
self.window = window
def make_fits_header(self, field, channel):
"""
Extend base method to include extra wavelength dimension.
"""
header = super().make_fits_header(field, channel)
header['wavelnth'] = channel['wavelength'].value
header['naxis3'] = len(channel['response']['x'])
header['ctype3'] = 'wavelength'
header['cunit3'] = 'angstrom'
header['cdelt3'] = np.fabs(np.diff(channel['response']['x']).value[0])
return header
def __init__(self, filename_cube, filename_white=None, pixelsize=0.2 * u.arcsec, n_fig=1,
flux_units=1E-20 * u.erg / u.s / u.cm ** 2 / u.angstrom, vmin=None, vmax=None, wave_cal='air'):
"""
Parameters
----------
filename_cube: string
Name of the MUSE datacube .fits file
filename_white: string
Name of the MUSE white image .fits file
pixel_size : float or Quantity, optional
Pixel size of the datacube, if float it assumes arcsecs.
Default is 0.2 arcsec
n_fig : int, optional
XXXXXXXX
flux_units : Quantity
XXXXXXXXXX
"""
# init
self.color = False
self.cmap = ""
self.flux_units = flux_units
self.n = n_fig
plt.close(self.n)
self.wave_cal = wave_cal
self.filename = filename_cube
self.filename_white = filename_white
self.load_data()
self.white_data = fits.open(self.filename_white)[1].data
self.hdulist_white = fits.open(self.filename_white)
self.white_data = np.where(self.white_data < 0, 0, self.white_data)
if not vmin:
self.vmin=np.nanpercentile(self.white_data,0.25)
else:
self.vmin = vmin
if not vmax:
self.vmax=np.nanpercentile(self.white_data,98.)
else:
self.vmax = vmax
self.gc2 = aplpy.FITSFigure(self.filename_white, figure=plt.figure(self.n))
self.gc2.show_grayscale(vmin=self.vmin, vmax=self.vmax)
# self.gc = aplpy.FITSFigure(self.filename, slices=[1], figure=plt.figure(20))
self.pixelsize = pixelsize
gc.enable()
# plt.close(20)
print("MuseCube: Ready!")
def __init__(self, filename_cube, filename_white=None, pixelsize=0.2 * u.arcsec, n_fig=1,
flux_units=1E-20 * u.erg / u.s / u.cm ** 2 / u.angstrom, vmin=None, vmax=None, wave_cal='air'):
"""
Parameters
----------
filename_cube: string
Name of the MUSE datacube .fits file
filename_white: string
Name of the MUSE white image .fits file
pixel_size : float or Quantity, optional
Pixel size of the datacube, if float it assumes arcsecs.
Default is 0.2 arcsec
n_fig : int, optional
XXXXXXXX
flux_units : Quantity
XXXXXXXXXX
"""
# init
self.color = False
self.cmap = ""
self.flux_units = flux_units
self.n = n_fig
plt.close(self.n)
self.wave_cal = wave_cal
self.filename = filename_cube
self.filename_white = filename_white
self.load_data()
self.white_data = fits.open(self.filename_white)[1].data
self.hdulist_white = fits.open(self.filename_white)
self.white_data = np.where(self.white_data < 0, 0, self.white_data)
if not vmin:
self.vmin=np.nanpercentile(self.white_data,0.25)
else:
self.vmin = vmin
if not vmax:
self.vmax=np.nanpercentile(self.white_data,98.)
else:
self.vmax = vmax
self.gc2 = aplpy.FITSFigure(self.filename_white, figure=plt.figure(self.n))
self.gc2.show_grayscale(vmin=self.vmin, vmax=self.vmax)
# self.gc = aplpy.FITSFigure(self.filename, slices=[1], figure=plt.figure(20))
self.pixelsize = pixelsize
gc.enable()
# plt.close(20)
print("MuseCube: Ready!")
def __init__(self,
solution_type=None,
model_name=None,
model_order=0,
model=None,
ref_lamp=None,
eval_comment='',
header=None):
"""Init method for the WavelengthSolution class
Args:
solution_type (str): Type of wavelength solution.
model_name (str): Mathematical model name.
model_order (int): Order of the mathematical model in case it is a
polynomial which in most cases it is.
model (object): Instance of astropy.modeling.Model, represents the
transformation from pixel to angstrom.
ref_lamp (str): File name of reference lamp used to find the
wavelength solution
eval_comment (str): Text describing the qualitative evaluation of
the wavelength solution.
header (object): Instance of astropy.io.fits.header.Header
"""
self.log = logging.getLogger(__name__)
self.dtype_dict = {None: -1,
'linear': 0,
'log_linear': 1,
'non_linear': 2}
# if solution_type == 'non_linear' and model_name is not None:
self.ftype_dict = {'chebyshev': 1,
'legendre': 2,
'cubic_spline': 3,
'linear_spline': 4,
'pixel_coords': 5,
'samples_coords': 6,
None: None}
self.solution_type = solution_type
self.model_name = model_name
self.model_order = model_order
self.wsolution = model
self.reference_lamp = ref_lamp
self.evaluation_comment = eval_comment
self.spectral_dict = self.set_spectral_features(header)
self.solution_name = self.set_solution_name(header)