def load_spectrum(spec_fil): '''Load X-Shooter spectra''' # Load Spectrum uvb_spec = XSpectrum1D.from_file(spec_fil) vis_specfil = spec_fil.replace('uvb', 'vis') vis_spec = XSpectrum1D.from_file(vis_specfil) comb_spec = uvb_spec.splice(vis_spec) comb_spec.filename = spec_fil # Return return comb_spec
def load_1dspec(fname, exten=None, extract='OPT', objname=None, flux=False): """ Parameters ---------- fname : str Name of the file exten : int, optional Extension of the spectrum If not given, all spectra in the file are loaded extract : str, optional Extraction type ('opt', 'box') objname : str, optional Identify extension based on input object name flux : bool, optional Return fluxed spectra? Returns ------- spec : XSpectrum1D """ # Identify extension from objname? if objname is not None: hdulist = fits.open(fname) hdu_names = [hdu.name for hdu in hdulist] exten = hdu_names.index(objname) if exten < 0: msgs.error("Bad input object name: {:s}".format(objname)) # Keywords for Table rsp_kwargs = {} if flux: rsp_kwargs['flux_tag'] = '{:s}_FLAM'.format(extract) rsp_kwargs['sig_tag'] = '{:s}_FLAM_SIG'.format(extract) else: rsp_kwargs['flux_tag'] = '{:s}_COUNTS'.format(extract) rsp_kwargs['sig_tag'] = '{:s}_COUNTS_SIG'.format(extract) # Use the WAVE_GRID (for 2d coadds) if it exists, otherwise use WAVE rsp_kwargs['wave_tag'] = '{:s}_WAVE_GRID'.format(extract) # Load try: spec = XSpectrum1D.from_file(fname, exten=exten, **rsp_kwargs) except ValueError: rsp_kwargs['wave_tag'] = '{:s}_WAVE'.format(extract) spec = XSpectrum1D.from_file(fname, exten=exten, **rsp_kwargs) # Return return spec
def test_get_local_s2n(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) wv0 = 4000 * u.AA s2n, sig_s2n = spec.get_local_s2n(wv0, 20, flux_th=0.9) np.testing.assert_allclose(s2n, 9.30119800567627, rtol=1e-5) np.testing.assert_allclose(sig_s2n, 1.0349911451339722, rtol=1e-5) # test with continuum spec.co = np.ones_like(spec.flux) s2n, sig_s2n = spec.get_local_s2n(wv0, 20, flux_th=0.9) np.testing.assert_allclose(s2n, 10.330545425415039, rtol=1e-5) np.testing.assert_allclose(sig_s2n, 0.4250050187110901, rtol=1e-5) # test errors # out of range with pytest.raises(IOError): spec.get_local_s2n(1215 * u.AA, 20) # sig not defined spec = XSpectrum1D.from_tuple((spec.wavelength, spec.flux)) with pytest.raises(ValueError): spec.get_local_s2n(wv0, 20) # bad shape for flux_th with pytest.raises(ValueError): spec.get_local_s2n(wv0, 20, flux_th=np.array([1, 2, 3, 4, 5])) # npix too big with pytest.raises(ValueError): spec.get_local_s2n(wv0, 1 + len(spec.wavelength))
def test_get_local_s2n(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) wv0 = 4000 * u.AA s2n, sig_s2n = spec.get_local_s2n(wv0, 20, flux_th=0.9) np.testing.assert_allclose(s2n, 9.30119800567627, rtol=1e-5) np.testing.assert_allclose(sig_s2n, 1.0349911451339722, rtol=1e-5) # test with continuum spec.co = np.ones_like(spec.flux) s2n, sig_s2n = spec.get_local_s2n(wv0, 20, flux_th=0.9) np.testing.assert_allclose(s2n, 10.330545425415039, rtol=1e-5) np.testing.assert_allclose(sig_s2n, 0.4250050187110901, rtol=1e-5) # test errors # out of range with pytest.raises(IOError): spec.get_local_s2n(1215*u.AA, 20) # sig not defined spec = XSpectrum1D.from_tuple((spec.wavelength, spec.flux)) with pytest.raises(ValueError): spec.get_local_s2n(wv0, 20) # bad shape for flux_th with pytest.raises(ValueError): spec.get_local_s2n(wv0, 20, flux_th=np.array([1,2,3,4,5])) # npix too big with pytest.raises(ValueError): spec.get_local_s2n(wv0, 1 + len(spec.wavelength))
def fit_cont(filename): from linetools.spectra.xspectrum1d import XSpectrum1D import re from astropy.coordinates import SkyCoord from linetools.isgm import abssystem as lt_absys from linetools.spectralline import AbsLine from linetools.isgm.abscomponent import AbsComponent from linetools import line_utils as ltlu from linetools.spectralline import AbsLine, SpectralLine import numpy from astropy.io import fits from glob import glob from astropy import units as u from linetools.lists.linelist import LineList import warnings warnings.filterwarnings('ignore') # Create a spectrum class object from the fits file sp = XSpectrum1D.from_file(filename) data, radec = get_prop(filename) # Call the GUI to interactively fit the continuum sp.fit_continuum(kind='QSO', redshift=data['zq']) # Normalize the Continuum sp.normalize(co=sp.co) # Write the Normalized Continuum to a new fits file sp.write_to_fits('n_' + filename) return print(filename + ' has been normalized and written to ' + 'n_' + filename)
def __init__(self): super().__init__() self.setWindowTitle('My simple dialog app') button = QPushButton('Press me for a dialog!') button.clicked.connect(self.button_clicked) self.setCentralWidget(button) #Add your flux extraction code in here sp = XSpectrum1D.from_file('./example-data/test.fits') wave = sp.wavelength.value flux = sp.flux.value error = sp.sig.value q = np.where((wave > 1330) & (wave < 1340)) self.wave = wave[q] self.flux = flux[q] self.error = error[q] sizeObj = QDesktopWidget().screenGeometry(-1) print('Screen size:' + str(sizeObj.height()) + 'x' + str(sizeObj.width())) availObj = QDesktopWidget().availableGeometry(-1) print('Availble size:' + str(availObj.height()) + 'x' + str(availObj.width())) self.move(sizeObj.width() // 2, sizeObj.height() // 2)
def test_from_file(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) idl = ascii.read(data_path('UM184.dat.gz'), names=['wave', 'flux', 'sig']) np.testing.assert_allclose(spec.dispersion.value, idl['wave']) np.testing.assert_allclose(spec.sig, idl['sig'], atol=2e-3, rtol=0) assert spec.dispersion.unit == u.Unit('AA')
def __init__(self, filepath=''): self.fitsobj = FitsObj(wave=[]) self.filepath = filepath self.warning = '' try: self.sp = XSpectrum1D.from_file(self.filepath) except (OSError, KeyError, AttributeError): self.warning += 'XSpectrum1D cannot read this file.'
def load_spec(self): '''Input the Spectrum ''' from linetools.spectra.xspectrum1d import XSpectrum1D if self._specfil is None: self.get_specfil() # if self.verbose: print('SdssQso: Loading spectrum from {:s}'.format(self._specfil)) self.spec = XSpectrum1D.from_file(self._specfil)
def __init__(self, filepath=''): self.fitsobj = FitsObj(wave=[]) self.filepath = filepath self.warning = '' # try if XSpectrum1D can read current file try: self.sp = XSpectrum1D.from_file(self.filepath) except (OSError, KeyError, AttributeError): # give warning without GUI crashing self.warning += 'XSpectrum1D cannot read this file.'
def test_addmask(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) assert not spec.data['flux'][0].mask[100] mask = spec.data['flux'][0].mask.copy() mask[100:110] = True spec.add_to_mask(mask) assert spec.data['flux'][0].mask[100] # Compressed badp = spec.flux < 0.1 spec.add_to_mask(badp, compressed=True) assert np.sum(spec.data['flux'][0].mask) > 3000
def test_from_file(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) idl = ascii.read(data_path('UM184.dat.gz'), names=['wave', 'flux', 'sig']) np.testing.assert_allclose(spec.data['wave'][spec.select].data, idl['wave']) np.testing.assert_allclose(spec.data['sig'][spec.select].data, idl['sig'], atol=2e-3, rtol=0) assert spec.wavelength.unit == u.Unit('AA')
def measure_sodium_EW(filename): from linetools.lists.linelist import LineList from astropy import units as u from linetools.spectralline import AbsLine from linetools.spectra.xspectrum1d import XSpectrum1D import matplotlib.pyplot as plt sp = XSpectrum1D.from_file('RF_' + filename) sp.normalize(co=sp.co) wvlim = [5880, 6030] * u.AA strong = LineList('Strong') transitions = strong.available_transitions(wvlim, n_max_tuple=None, min_strength=0.0) line1 = transitions['wrest'][0] line2 = transitions['wrest'][1] avg_line = (line1 + line2) / 2.0 # Plot the spectrum to get limits for EW fig = plt.figure() plt.axvline(x=line1, color='k', linestyle='--') plt.axhline(y=1.0, color='r', linestyle='--') plt.axvline(x=line2, color='k', linestyle='--') sp.plot(xlim=(avg_line - 30, avg_line + 30)) S1 = AbsLine(transitions['wrest'][0] * u.AA, z=0.0) S1.analy['spec'] = sp S2 = AbsLine(transitions['wrest'][1] * u.AA, z=0.0) S2.analy['spec'] = sp #x = float(input("Enter a lower lim: ")) #y = float(input("Enter a higher lim: ")) x = 5888 y = 5896 S1.limits.set([x, y] * u.AA) S1.measure_ew(flg=1) # Measure the EW of the first line EW1 = S1.attrib['EW'], S1.attrib['sig_EW'] #x = float(input("Enter a lower lim: ")) #y = float(input("Enter a higher lim: ")) x = 5895 y = 5905 S2.limits.set([x, y] * u.AA) S2.measure_ew() # Measure the EW of the second line EW2 = S2.attrib['EW'], S2.attrib['sig_EW'] return EW1, EW2
def fig_lya_forest(zoom_in=False, redshift=False): outfile = 'fig_lya_forest.png' xmnx = (3950., 4363) if zoom_in: xmnx = (4130., 4183) outfile = 'fig_lya_forest_zoom.png' if redshift: outfile = 'fig_lya_forest_z.png' xmnx = np.array(xmnx) / 1215.6701 - 1. # Read spectrum spec_file = os.getenv( 'DROPBOX_DIR') + 'Keck/HIRES/RedData/Q1759+75/Q1759+75T_f.fits' xspec = XSpectrum1D.from_file(spec_file) plt.figure(figsize=(9, 5)) plt.clf() gs = gridspec.GridSpec(1, 1) ax = plt.subplot(gs[:, :]) # Plot if redshift: xplt = xspec.wavelength.value / 1215.6701 - 1. else: xplt = xspec.wavelength.value ax.plot(xplt, xspec.flux, 'k') ax.plot([0., 5000], [0., 0.], 'g--') ax.set_xlim(xmnx) ax.set_ylim(-0.05, 1.1) ax.set_ylabel('Normalized Flux') if redshift: ax.set_xlabel('Redshift (z)') else: ax.set_xlabel('Wavelength (A)') set_fontsize(ax, 15.) # Write plt.tight_layout(pad=0.2, h_pad=0., w_pad=0.1) plt.savefig(outfile, dpi=500) plt.close() print("Wrote: {:s}".format(outfile))
def measure_ew_lim(filename): from linetools.lists.linelist import LineList import numpy from astropy import units as u from linetools.spectralline import AbsLine from linetools.spectra.xspectrum1d import XSpectrum1D sp = XSpectrum1D.from_file('RF_' + filename) sp.normalize(co=sp.co) wv0 = 5891.5833 * u.AA R = 4013.0 / .3 d_lambda_pix = 0.13333317282580992 d_lambda_res = 5891.5833 / R N_pix = d_lambda_res / d_lambda_pix s_2_n = sp.get_local_s2n(wv0, npix=100)[0] #/100 S_2_N per pixel EW_lim = 3.0 * numpy.sqrt(N_pix) * d_lamba_pix / s_2_n # 1 sigma limit return EW_lim
def load_1dspec(fname, exten=None, extract='opt', objname=None, flux=False): """ Parameters ---------- fname : str Name of the file exten : int, optional Extension of the spectrum If not given, all spectra in the file are loaded extract : str, optional Extraction type ('opt', 'box') objname : str, optional Identify extension based on input object name flux : bool, optional Return fluxed spectra? Returns ------- spec : XSpectrum1D """ from astropy.io import fits from linetools.spectra.xspectrum1d import XSpectrum1D # Keywords for Table rsp_kwargs = {} rsp_kwargs['wave_tag'] = '{:s}_wave'.format(extract) if flux: rsp_kwargs['flux_tag'] = '{:s}_flam'.format(extract) rsp_kwargs['var_tag'] = '{:s}_flam_var'.format(extract) else: rsp_kwargs['flux_tag'] = '{:s}_counts'.format(extract) rsp_kwargs['var_tag'] = '{:s}_var'.format(extract) # Identify extension from objname? if objname is not None: hdulist = fits.open(fname) hdu_names = [hdu.name for hdu in hdulist] exten = hdu_names.index(objname) if exten < 0: msgs.error("Bad input object name: {:s}".format(objname)) # Load spec = XSpectrum1D.from_file(fname, exten=exten, **rsp_kwargs) # Return return spec
def spec_dered(filename): from linetools.lists.linelist import LineList from astropy import units as u from linetools.spectra.xspectrum1d import XSpectrum1D # Create a json file and centroid the lines spec_inspect(filename) # Read in the json file data = read_json(filename[:-5] + '.json') z_new = data['zabs'] # Create a spectrum object, and normalize it, using the # already fitted continuum. sp = XSpectrum1D.from_file('n_' + filename) sp.normalize(co=sp.co) # Transform the spectra into the rest frame sp.wavelength = de_redshift(sp, z_new) sp.write_to_fits('RF_' + filename) sp.plot() return print('The Spectrum has been transformed into the Lab Frame')
def from_file(cls, filename, filetype=False, efil=None, **kwargs): if filetype == False: #Take File Extention and try if filename == False: if 'wave' in kwargs: wave = kwargs['wave'] else: raise IOError("Input wavelength array") if 'flux' in kwargs: flux = kwargs['flux'] else: raise IOError("Input flux array") if 'error' in kwargs: error = kwargs['error'] else: raise IOError("Input error array") else: tt = os.path.splitext(filename)[1] if (tt == 'txt') | (tt == 'dat'): filetype = 'ascii' else: filetype = tt[1:len(tt)] # Read in Files in differet formats if filetype == 'ascii': from astropy.io import ascii dat = ascii.read(filename) tab = dat.keys() wave = np.array(dat[tab[0]]) flux = np.array(dat[tab[1]]) if (len(dat.keys()) >= 3): error = dat[tab[2]] else: error = 0. * flux elif filetype == 'fits': from astropy.io import fits file = fits.open(filename) #(cwd+'/'+filename) dat = file[1].data tab = dat.names wave = np.array(dat['wave'][0]) flux = np.array(dat['flux'][0]) if (len(tab) >= 3): error = np.array(dat['error'][0]) else: error = 0. * flux elif filetype == 'HSLA': from astropy.io import fits file = fits.open(filename) #(cwd+'/'+filename) dat = file[1].data tab = dat.names wave = np.array(dat['WAVE']) flux = np.array(dat['FLUX']) #/np.median(np.array(dat['FLUX'])) if (len(tab) >= 3): error = np.array( dat['ERROR']) #/np.median(np.array(dat['FLUX'])) else: error = 0. * flux if filetype == 'xfits': from linetools.spectra.xspectrum1d import XSpectrum1D sp = XSpectrum1D.from_file(filename) wave = sp.wavelength.value flux = sp.flux.value error = sp.sig.value if sp.co_is_set == True: print('Normalizing spectrum using given continuum...') flux = sp.flux.value / sp.co.value error = sp.sig.value / sp.co.value elif filetype == 'p': import pickle dat = pickle.load(open(filename, "rb")) #tab=dat.keys() wave = np.array(dat['wave']) flux = np.array(dat['flux']) if (len(tab) >= 3): error = np.array(dat['error']) else: error = 0. * flux elif filetype == 'temp': from astropy.io import fits file = fits.open(filename) #(cwd+'/'+filename) #a=fits.open(path+'spec_knotA.fits') wave = file[2].data flux = file[0].data error = file[1].data #Use linetools.io.readspec to read file elif filetype == 'linetools': from linetools.spectra import io as tio sp = tio.readspec(filename, inflg=None, efil=efil, **kwargs) wave = sp.wavelength.value flux = sp.flux.value if sp.sig_is_set == False: print('Assuiming arbiarbitrary 10% error on flux') error = 0.1 * flux else: error = sp.sig.value return cls(wave, flux, error, filename=filename)
def test_co_kludges(): spec = XSpectrum1D.from_file(data_path('SDSSJ220248.31+123656.3.fits'), masking='edges') assert spec.co.size == 4599
def simple_coadd(uves_table=None, outputbase=None, airtovac=True): """simple_coadd(uves_table=None, outputbase=None,airtovac=True): Combine multiple UVES exposures obtained with the same set-up into a single spectrum, weighting by the inverse variance of the input data. For multiple set-ups, outputs an individual file for each unique wavelength range. """ import numpy as np from astropy.table import Table from linetools.spectra.xspectrum1d import XSpectrum1D if uves_table == None: # There is no input table; let's create one. uves_table = uves_log() # Select unique wavelengths to identify the setups # Table should be the output from UVES log or at least contain wavelengths and filenames. uniq_setup, uniq_indeces, uniq_inverse = np.unique(np.around( uves_table['WAVELMIN'], 1), return_index=True, return_inverse=True) num_setups = np.size(uniq_indeces) # Loop over the setups. for j in np.arange(num_setups): # Work out the setups that are to be coadded setup_obs = (np.where(uniq_inverse == j))[0] num_setup_obs = np.size(setup_obs) # Hold object name setup_obj = uves_table[uniq_indeces[j]]['OBJECT'] # Loop over the files in this setup for k in np.arange(num_setup_obs): # inspec = fits.getdata(uves_table[setup_obs[k]]['fitsName']) specfile = uves_table[setup_obs[k]]['fitsName'] inspec = Table.read(specfile) # Load the spectrum with XSpectrum1D: inspec = XSpectrum1D.from_file(specfile) inspec.meta['airvac'] = 'air' # Unless user requests, we transform to vacuum. if airtovac == True: inspec.airtovac() # Check for sig = 0: badErrors = (inspec.sig == 0) inspec.flux[badErrors] = np.nan inspec.sig[badErrors] = np.nan inspec.ivar[badErrors] = np.nan # Set up the arrays if it's the first spectrum. if k == 0: out_file_list = specfile out_wave = inspec.wavelength.value # Do weighted average; calculate the inverse variance and the inv var-weighted flux. out_inv_variance = inspec.ivar.value out_flux_weighted = \ inspec.flux.value*inspec.ivar.value # For subsequent spectra: else: #Test for same array length: new_length = np.min( [np.size(inspec.flux.value), np.size(out_flux_weighted)]) out_file_list += ', ' + specfile out_inv_variance[:new_length] += \ inspec.ivar.value[:new_length] out_flux_weighted[:new_length] += \ inspec.flux.value[:new_length]*inspec.ivar.value[:new_length] # Calculate the output weighted mean flux and error. out_flux = out_flux_weighted / out_inv_variance out_err = np.sqrt(1. / out_inv_variance) # Book-keeping: set up filename if outputbase == None: # If there is no base for the filenames, use the object name. outputfilename = uves_table[setup_obs[k]]['OBJECT'] else: outputfilename = outputbase outputfilename = "{0}.uves.{1:0.0f}.{2:0.0f}.fits".format( outputfilename, uves_table[setup_obs[k]]['WAVELMIN'] * 10., uves_table[setup_obs[k]]['WAVELMAX'] * 10.) # Set up the output table outputtable = Table([out_wave, out_flux, out_err], names=['wave', 'flux', 'err']) # Load the spectrum in the standard way to get the units right: inspec = Table.read(uves_table[0]['fitsName']) # Assign units outputtable['wave'].unit = inspec['WAVE'].unit outputtable['flux'].unit = inspec['FLUX'].unit outputtable['err'].unit = inspec['ERR'].unit outputtable.meta = inspec.meta outputtable.meta['COMMENT'] = 'Simple coadd of ' + out_file_list outputtable.write(outputfilename, overwrite=True) print('Wrote ' + outputfilename + '.')
def xspec(z_bin, plot=False): """ :param z_bin: (list) min and max redshift values of the desired bin ex:[2.0,2.5] :return: (numpy array) XSpectrum1D objects, corresponding redshifts and coordinates """ import numpy as np import matplotlib.pyplot as plt from astropy.table import Table import astropy.units as u from linetools.spectra.xspectrum1d import XSpectrum1D path_16 = "../../spectra/2016/" path_17 = "../../spectra/2017/" spec_atr_16 = Table.read(path_16 + "spec_atr.txt", format='ascii') spec_atr_17 = Table.read(path_17 + "spec_atr.txt", format='ascii') # read in spec_16 = [] z_16 = [] coord_16 = [] for entry in spec_atr_16: # from the CLAMATO 2016 survey if np.min(z_bin) <= entry["zspec"] <= np.max( z_bin): # creating the bin size if entry["Conf"] < 10.0: # excluding any QSOs temp = XSpectrum1D.from_file(path_16 + entry["Filename"]) if temp.wvmin < (1216 * u.AA) * (1 + entry["zspec"]) < temp.wvmax: coord_16.append([entry["RA"], entry["Dec"]]) # coordinates in deg z_16.append(entry["zspec"]) spec_16.append( XSpectrum1D.from_file(path_16 + entry["Filename"])) spec_17 = [] z_17 = [] coord_17 = [] for entry in spec_atr_17: if np.min(z_bin) <= entry["col5"] <= np.max(z_bin): if entry["col4"] < 10.0: temp = XSpectrum1D.from_file(path_17 + entry["col1"]) if temp.wvmin < (1216 * u.AA) * (1 + entry["col5"]) < temp.wvmax: coord_17.append([entry["col7"], entry["col8"]]) z_17.append(entry["col5"]) spec_17.append( XSpectrum1D.from_file(path_17 + entry["col1"])) # array creation spec = np.asarray(spec_16 + spec_17) red = np.asarray(z_16 + z_17) coord = np.asarray(coord_16 + coord_17) print("Number of spectra in the redshift bin:", len(spec)) z_16_tot = [entry["zspec"] for entry in spec_atr_16] # from the CLAMATO 2016 survey z_17_tot = [entry["col5"] for entry in spec_atr_17] # from the CLAMATO 2017 survey z_tot = z_16_tot + z_17_tot # a histogram to illustrate the sample selected if plot == True: plt.figure(figsize=(8, 8)) plt.hist(z_tot, bins=70, edgecolor='white', linewidth=1.2, label="Full Sample", color="grey") plt.hist(red, bins=12, edgecolor='black', linewidth=1.2, label="Reduced Sample", color="#fd8d3c") plt.ylabel("Number of Galaxies", fontsize=15) plt.xlabel("$z$", fontsize=15) plt.xlim(1.5, 3.5) plt.legend(fontsize=12) plt.xticks(fontsize=12) plt.yticks(fontsize=12) plt.show() return spec, red, coord
def test_unmask(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits'), masking='edges') assert np.sum(spec.data['wave'].mask) > 0 spec.unmask() assert np.sum(spec.data['wave'].mask) == 0
def fit_lines(spec_file, z_init=0., do_plot=True, file_out=None, no_tie_5008=False): # from astropy.modeling import models, fitting from linetools.spectra.xspectrum1d import XSpectrum1D import matplotlib.pyplot as plt # Redshift scale: scale_factor = (1. + z_init) # Read in the spectrum. **ASSUME VACUUM WAVELENGTHS?** mods_spec = XSpectrum1D.from_file(spec_file) # mods_spec = Table.read(spec_file) # Set up a convenient wavelength, flux, error arrays wave = mods_spec.wavelength.value flux = mods_spec.flux.value err = mods_spec.sig.value # wave = mods_spec['wave'] # flux = mods_spec['flux'] # err = mods_spec['err'] # Load the data for the lines to be fit. Starts with MANGA line list, modified for MODS. line_data = get_linelist() # Exclude lines outside of the wavelength coverage. keep_lines = np.where( (line_data['lambda'] <= np.max(wave) / scale_factor) & (line_data['lambda'] >= np.min(wave) / scale_factor))[0] keep_line_index = line_data['indx'][keep_lines] ########## # MODEL DEFINITION # Define a joint model as the sums of Gaussians for each line # Initial parameters amplitude_init = 0.1 * np.max(flux) stddev_init = 1.5 # Constraint parameters: amplitude_bounds, stddev_bounds, velocity_range = _define_bounds() # Start up the constraints on the mean wavelength [separate bounds for each lambda0] mean_bounds_scale = (velocity_range / c.c.to('km/s').value) * np.array( [-1., 1.]) + 1. mean_bounds = [] ##### DEFINE THE MODEL: # Initial Gaussian: j = 0 wave0 = line_data['lambda'][j] line_center = wave0 * scale_factor model_name = np.str(line_data['name'][j]) # Traditional astropy 1D Gaussian model: joint_model = models.Gaussian1D(amplitude=amplitude_init, mean=line_center, stddev=stddev_init, name=model_name) # Set constraints on how much the central value can vary mean_bounds.append([ line_center * mean_bounds_scale[0], line_center * mean_bounds_scale[1] ]) # Loop through the remaining lines to create their Gaussian model: for j in np.arange(1, np.size(line_data)): wave0 = line_data['lambda'][j] line_center = wave0 * scale_factor model_name = np.str(line_data['name'][j]) # Traditional astropy 1D Gaussian fit: joint_model += models.Gaussian1D(amplitude=amplitude_init, mean=line_center, stddev=stddev_init, name=model_name) # Set constraints on how much the central value can vary mean_bounds.append([ line_center * mean_bounds_scale[0], line_center * mean_bounds_scale[1] ]) # Extract the model names: model_names = joint_model.submodel_names # Now we have to loop through the same models, applying the # remaining bounds. This includes tying parameters: for k in np.arange(0, np.size(line_data)): mdlnm = model_names[k] joint_model[mdlnm].bounds['amplitude'] = amplitude_bounds joint_model[mdlnm].bounds['mean'] = (mean_bounds[k][0], mean_bounds[k][1]) joint_model[mdlnm].bounds['stddev'] = stddev_bounds # Tie some parameters together, checking that reference lines # are actually covered by the spectrum: if (line_data['mode'][k] == 't33') & (np.in1d(33, keep_line_index)): joint_model[mdlnm].stddev.tied = _tie_sigma_4862 elif (line_data['mode'][k] == 't35') & (np.in1d(35, keep_line_index)): #joint_model[mdlnm].stddev.tied = _tie_sigma_4862 joint_model[mdlnm].stddev.tied = _tie_sigma_5008 elif (line_data['mode'][k] == 't45') & (np.in1d(45, keep_line_index)): joint_model[mdlnm].stddev.tied = _tie_sigma_6585 # Tie amplitudes of doublets if (line_data['line'][k] == 'd35') & (np.in1d(35, keep_line_index)): joint_model[mdlnm].amplitude.tied = _tie_ampl_5008 # 4959/5008 if (line_data['line'][k] == 'd45') & (np.in1d(45, keep_line_index)): joint_model[mdlnm].amplitude.tied = _tie_ampl_6585 # 6549/6585 # Finally, tie redshifts of OII 3727, 3729, OIII 4364, 4960 to 5008 if not no_tie_5008: if (line_data['indx'][k] == '16') & (np.in1d(35, keep_line_index)): joint_model[mdlnm].redshift.tied = _tie_mean_3727_5008 if (line_data['indx'][k] == '17') & (np.in1d(35, keep_line_index)): joint_model[mdlnm].redshift.tied = _tie_mean_3729_5008 if (line_data['indx'][k] == '29') & (np.in1d(35, keep_line_index)): joint_model[mdlnm].redshift.tied = _tie_mean_4364_5008 if (line_data['indx'][k] == '34') & (np.in1d(35, keep_line_index)): joint_model[mdlnm].redshift.tied = _tie_mean_4960_5008 # TODO Assess quality of emission line fits. # Standard astropy fit: fitter = fitting.LevMarLSQFitter() fitted_model = fitter(joint_model, wave, flux, weights=1. / err**2, maxiter=500) fitted_flux = fitted_model(wave) # Print the reason the fitter stops: fitter.fit_info['message'] # Plot the results if do_plot: plt.clf() plt.plot(wave, flux, drawstyle='steps-mid', linewidth=2) plt.plot(wave, fitted_flux, color='orange', linewidth=2) ##### Create integrated fluxes and errors # The integration range is over +/-stddev * int_delta_factor int_delta_factor = _define_integration_delta() # Test whether we've constructed output or not: output_construct = 0 # Loop through the list of lines: # --One could imagine only looping over lines covered by the spectrum, # but this screws up the way we tie parameters. for j in np.arange(np.size(line_data)): # Only fit those lines that are covered by the spectrum if np.in1d(j, keep_lines): # Calculate integrated fluxes, errors; deal with the blended O II 3727/3729 doublet if line_data[j]['name'] == '[OII]3727': # Calculate the integrated fluxes and errors iflux, ierr = integrate_line_flux(wave, flux, err, fitted_model[j].mean.value, fitted_model[j].stddev * int_delta_factor, line3727=True) elif line_data[j]['name'] == '[OII]3729': # pdb.set_trace() # For 3729, use the flux derived for 3726 iflux = output_table['int_flux'][j - 1] #iflux = 0. # For 3729, use its own error. This is appropriate for the fitted errors of both liness crap, ierr = integrate_line_flux( wave, flux, err, fitted_model[j].mean.value, fitted_model[j].stddev * int_delta_factor) else: # Calculate the integrated fluxes and errors iflux, ierr = integrate_line_flux( wave, flux, err, fitted_model[j].mean.value, fitted_model[j].stddev * int_delta_factor) redshift_out = (fitted_model[j].mean / line_data[j]['lambda'] - 1.) fitted_flux_out = np.sqrt( 2. * np.pi) * fitted_model[j].amplitude * fitted_model[j].stddev if output_construct == 0: # Define and construct the initial table to hold the results output_col_names, output_format, output_dtype = _define_output_table( ) output_data = [[line_data[j]['name']], [line_data[j]['ion']], [line_data[j]['lambda']], [line_data[j]['indx']], [line_data[j]['mode']], [fitted_model[j].mean.value], [fitted_model[j].amplitude.value], [fitted_model[j].stddev.value], [redshift_out], [fitted_flux_out], [iflux], [ierr], [iflux / ierr]] output_table = Table(output_data, names=output_col_names, dtype=output_dtype) output_construct = 1 else: output_table.add_row([ line_data[j]['name'], line_data[j]['ion'], line_data[j]['lambda'], line_data[j]['indx'], line_data[j]['mode'], fitted_model[j].mean.value, fitted_model[j].amplitude.value, fitted_model[j].stddev.value, redshift_out, fitted_flux_out, iflux, ierr, iflux / ierr ]) # Set the output format of the results table: colnames = output_table.colnames for j in np.arange(np.size(colnames)): output_table[colnames[j]].format = output_format[j] # Set up the spectral table: spec_table = Table([wave, flux, err, fitted_flux], names=['wave', 'flux', 'err', 'spec_fit']) # # Excise lines that weren't part of the fitting process: # output_table = output_table[keep_lines] # Write summary FITS files if file_out is None: file_base = spec_file.strip('.fits') else: file_base = file_out table_file = file_base + '.HIIFitTable.fits' fit_file = file_base + '.HIIFitSpec.fits' output_table.write(table_file, overwrite=True) spec_table.write(fit_file, overwrite=True) return output_table
def __init__(self, redrock_file, parent=None, zdict=None, coadd_dict=None, outfile='tmp.json', unit_test=False, screen_scale=1., **kwargs): QMainWindow.__init__(self, parent) """ redrock_file = str Input RedRock output FITS file from our redrock script parent : Widget parent, optional zsys : float, optional intial redshift either from a previous vet_rr json or the original rr guesses screen_scale : float, optional Scale the default sizes for the gui size """ # Load up self.outfile = outfile self.rr_hdul = fits.open(redrock_file) if coadd_dict is not None: self.slit_info = {} for key in coadd_dict.keys(): if isinstance(coadd_dict[key], dict): if '2D_xval' in coadd_dict[key].keys(): name = coadd_dict[key]['outfile'].replace('.fits', '') self.slit_info[name] = {} self.slit_info[name]['xval'] = coadd_dict[key][ '2D_xval'] self.slit_info[name]['Gslit'] = coadd_dict[key][ 'Gemini_slit'] else: self.slit_info = None # names, spectra, zs = [], [], [] names, spectra = [], [] if zdict is None: self.zdict = OrderedDict() load_z = True else: self.zdict = OrderedDict() load_z = False for hdu in self.rr_hdul[1:]: # Grab the spectrum spec_file = hdu.name # tmp = XSpectrum1D.from_file(spec_file.replace('FITS','fits')) spectra.append( XSpectrum1D.from_file(spec_file.replace('FITS', 'fits'), masking='edges')) names.append(spec_file.replace('.FITS', '')) # RedRock data = hdu.data # Init the dict if load_z: self.zdict[names[-1]] = {} self.zdict[names[-1]]['zRR'] = data['z'] self.zdict[names[-1]]['ZQ'] = -99 self.zdict[names[-1]]['Comment'] = '' self.zdict[names[-1]]['z'] = data['z'][0] else: self.zdict[names[-1]] = zdict[names[-1]] # Collate ispec = lspu.collate(spectra, masking='edges') # Fill ispec.labels = names ispec.stypes = ['galaxy'] * ispec.nspec # ispec.z = zs # DO NOT SET THE REDSHIFT HERE self.RRi = 0 self.scale = screen_scale # Needed to avoid crash in large spectral files rcParams['agg.path.chunksize'] = 20000 # avoid scientific notation in axes tick labels rcParams['axes.formatter.useoffset'] = False # Build a widget combining several others self.main_widget = QWidget() # Status bar self.create_status_bar() # ZQ window self.ZQ_widg = ltgsm.EditBox(-99, 'ZQ', '{:d}') self.ZQ_values = [-99, -1, 0, 1, 3, 4] # Comment window self.comment_widg = ltgsm.EditBox('', 'Comment', '{:s}') # Grab the pieces and tie together self.pltline_widg = ltgl.PlotLinesWidget(status=self.statusBar, screen_scale=self.scale) self.pltline_widg.setMaximumWidth(300 * self.scale) # Hook the spec widget to Plot Line self.spec_widg = ltgsp.ExamineSpecWidget(ispec, status=self.statusBar, parent=self, llist=self.pltline_widg.llist, screen_scale=self.scale, **kwargs) # Reset redshift from spec # Auto set line list if spec has proper object type if hasattr(self.spec_widg.spec, 'stypes'): if self.spec_widg.spec.stypes[ self.spec_widg.select].lower() == 'galaxy': self.pltline_widg.llist = ltgu.set_llist( 'Galaxy', in_dict=self.pltline_widg.llist) elif self.spec_widg.spec.stypes[ self.spec_widg.select].lower() == 'absorber': self.pltline_widg.llist = ltgu.set_llist( 'Strong', in_dict=self.pltline_widg.llist) self.pltline_widg.llist['Plot'] = True idx = self.pltline_widg.lists.index( self.pltline_widg.llist['List']) self.pltline_widg.llist_widget.setCurrentRow(idx) # self.pltline_widg.spec_widg = self.spec_widg # Multi spec self.mspec_widg = ltgsp.MultiSpecWidget(self.spec_widg, extra_method=self) self.spec_widg.canvas.mpl_connect('key_press_event', self.on_key) self.spec_widg.canvas.mpl_connect('button_press_event', self.on_click) self.prev_select = 0 # Index of previous spectrum; starts at 0 # Legend -- specific to this GUI self.legend = {} self.wv_dict = {'*': 3727., '(': 3950., ')': 4940., '_': 6564.} self.legend['zoom'] = self.wv_dict self.legend['&'] = 'Toggle through ZQ' self.legend[ '#'] = 'Toggle through zRR (WARNING: will not necessary start at the first one)' self.legend['%'] = 'Set z=0 (for stars)' self.legend['9'] = 'Skip to next spectrum with ZQ=-99' self.legend['x'] = 'Next spectrum' for key, value in self.legend.items(): print(key, value) # Extras extras = QWidget() extras.setMinimumWidth(180 * self.scale) extras.setMaximumWidth(280 * self.scale) vbox = QVBoxLayout() qbtn = QPushButton(self) qbtn.setText('Quit') qbtn.clicked.connect(self.quit) vbox.addWidget(self.pltline_widg) vbox.addWidget(self.ZQ_widg) vbox.addWidget(self.comment_widg) vbox.addWidget(self.mspec_widg) vbox.addWidget(qbtn) extras.setLayout(vbox) # Main window hbox = QHBoxLayout() hbox.addWidget(self.spec_widg) hbox.addWidget(extras) self.main_widget.setLayout(hbox) # Point MainWindow self.setCentralWidget(self.main_widget) if unit_test: self.quit() # Giddy up self.run_with_select(save=False)
efil = sys.argv[3] # Read in Files in differet formats if filetype == 'ascii': from astropy.io import ascii dat = ascii.read(cwd + '/' + filename) tab = dat.keys() wave = np.array(dat[tab[0]]) flux = np.array(dat[tab[1]]) if (len(dat.keys()) >= 3): error = dat[tab[2]] elif (filetype == 'fits') | (filetype == 'linetools'): #Use linetools.io.readspec to read file #from linetools.spectra import io as tio if (len(sys.argv) > 3): sp = XSpectrum1D.from_file(filename, efil=efil) else: sp = XSpectrum1D.from_file(filename) #sp=tio.readspec(filename,inflg=None, efil=efil,**kwargs) wave = sp.wavelength.value flux = sp.flux.value if sp.sig_is_set == False: print('Assuiming arbiarbitrary 10% error on flux') error = 0.1 * flux else: error = sp.sig.value #from astropy.io import fits #file=fits.open(cwd+'/'+filename)
from linetools.spectralline import AbsLine from linetools.spectra.xspectrum1d import XSpectrum1D import imp import warnings try: import seaborn as sns sns.set(context="notebook", font_scale=2) except: pass warnings.filterwarnings('ignore') #Background info lt_path = imp.find_module('linetools')[1] xspec = XSpectrum1D.from_file(lt_path + '/spectra/tests/files/UM184_nF.fits') names = ['Mg II 2796', 'Mg II 2803', 'Mg I 2852'] #for loop manipulating background info abslines = [] for trans in names: iline = AbsLine(trans) clear_CACHE_LLIST = True iline.attrib['z'] = .603 iline.analy['vlim'] = [-3000., 500.] * u.km / u.s iline.analy['spec'] = xspec abslines.append(iline) #Wavelengths of interest MgII2796wrest = 2796.3542699 MgII2803wrest = 2803.5314853
def fit_lines_sherpa(spec_file, z_init=0., file_out=None, do_plot=True, monte_carlo=False): """Fit an HII region spectrum using Sherpa package. """ # from astropy.modeling.fitting import SherpaFitter from saba import SherpaFitter import matplotlib.pyplot as plt from linetools.spectra.xspectrum1d import XSpectrum1D # Redshift scale: scale_factor = (1. + z_init) # Read in the spectrum. **ASSUME VACUUM WAVELENGTHS?** mods_spec = XSpectrum1D.from_file(spec_file) # Set up a convenient wavelength, flux, error arrays wave = mods_spec.wavelength.value flux = mods_spec.flux.value err = mods_spec.sig.value ###### ------ FOR TESTING!! ------ ### To test this, let's constrain ourselves to only the wavelengths between ~Hbeta, OIII # g = np.where((wave >= 4000) & (wave <= 5400.)) # wave = wave[g] # flux = flux[g] # err = err[g] # Load the data for the lines to be fit. Starts with MANGA line list, modified for MODS. line_data = get_linelist() # Exclude lines outside of the wavelength coverage. keep_lines = np.where( (line_data['lambda'] <= np.max(wave) / scale_factor) & (line_data['lambda'] >= np.min(wave) / scale_factor))[0] keep_line_index = line_data['indx'][keep_lines] # For now...debugging. jch keep_lines = np.array(len(line_data)) keep_line_index = line_data['indx'][keep_lines] ##### MODEL DEFINITIONS # Define initial parameters amplitude_init = 0.1 * np.max(mods_spec.flux) stddev_init = 1.5 amplitude_bounds, stddev_bounds, velocity_range = _define_bounds() # Calculate the redshift delta z_bounds_scale = (velocity_range / c.c.to('km/s').value) * scale_factor z_bounds = (z_init - z_bounds_scale, z_init + z_bounds_scale) # Define a joint model as the sums of Gaussians for each line # Gaussian for first line: j = 0 wave0 = line_data['lambda'][j] line_center = wave0 * scale_factor model_name = np.str(line_data['name'][j]) # Here we use a custom Gaussian class to fix redshifts together joint_model = GaussianEmission(amplitude=amplitude_init, redshift=z_init, stddev=stddev_init, wave0=wave0, name=model_name) # The rest wavelength is not a free parameter: joint_model.wave0.fixed = True # Loop through the remaining lines: for j in np.arange(1, np.size(line_data)): wave0 = line_data['lambda'][j] line_center = wave0 * scale_factor model_name = np.str(line_data['name'][j]) joint_model += GaussianEmission(amplitude=amplitude_init, redshift=z_init, stddev=stddev_init, wave0=wave0, name=model_name) # Extract the model names: model_names = joint_model.submodel_names # Now we have to loop through the same models, applying the bounds: for mdlnms in model_names: joint_model[mdlnms].bounds['amplitude'] = amplitude_bounds joint_model[mdlnms].bounds['redshift'] = z_bounds joint_model[mdlnms].bounds['stddev'] = stddev_bounds # The rest wavelength is not a free parameter: joint_model[mdlnms].wave0.fixed = True # TODO Get tied parameters to work. # Tie some parameters together, checking that reference lines # are actually covered by the spectrum: for k in np.arange(0, np.size(line_data)): mdlnm = model_names[k] if (line_data['mode'][k] == 't33') & (np.in1d(33, keep_line_index)): joint_model[mdlnm].stddev.tied = _tie_sigma_4862 joint_model[mdlnm].redshift.tied = _tie_redshift_4862 elif (line_data['mode'][k] == 't35') & (np.in1d(35, keep_line_index)): joint_model[mdlnm].stddev.tied = _tie_sigma_5008 joint_model[mdlnm].redshift.tied = _tie_redshift_5008 elif (line_data['mode'][k] == 't45') & (np.in1d(45, keep_line_index)): joint_model[mdlnm].stddev.tied = _tie_sigma_6585 joint_model[mdlnm].redshift.tied = _tie_redshift_6585 elif (line_data['mode'][k] == 't46') & (np.in1d(46, keep_line_index)): joint_model[mdlnm].stddev.tied = _tie_sigma_6718 joint_model[mdlnm].redshift.tied = _tie_redshift_6718 # 3727/3729 lines: if mdlnm == '[OII]3727': import IPython IPython.embed() joint_model[mdlnm].stddev.tied = _tie_sigma_3729 joint_model[mdlnm].redshift.tied = _tie_redshift_3729 # Tie amplitudes of doublets if (line_data['line'][k] == 'd35') & (np.in1d(35, keep_line_index)): joint_model[mdlnm].amplitude.tied = _tie_ampl_5008 # 4959/5008 if (line_data['line'][k] == 'd45') & (np.in1d(45, keep_line_index)): joint_model[mdlnm].amplitude.tied = _tie_ampl_6585 # 6549/6585 ##### FITTING # Sherpa model fitting from SABA package sfit = SherpaFitter(statistic='chi2', optimizer='levmar', estmethod='confidence') sfit_lm = SherpaFitter(statistic='chi2', optimizer='neldermead', estmethod='confidence') sfit_mc = SherpaFitter(statistic='chi2', optimizer='moncar', estmethod='confidence') # Do the fit sfitted_model = sfit(joint_model, wave, flux, err=err) # Refine with different optimizer temp_model = sfitted_model.copy() sfitted_model = sfit_lm(temp_model, wave, flux, err=err) if monte_carlo: # If requested, do a second fit with the very slow Monte Carlo approach sfitted_model = sfit_mc(sfitted_model.copy(), wave, flux, err=err) # Create the fitted flux array sfitted_flux = sfitted_model(wave) # TODO Get error estimates from Sherpa # Work out the errors... #sfit.est_config['maxiters']=200 #sfitted_err = sfit.est_errors(sigma=3) # Plot the results if do_plot: plt.clf() plt.plot(wave, flux, drawstyle='steps-mid', linewidth=2) plt.plot(wave, sfitted_flux, color='orange', linewidth=2) ##### Create integrated fluxes and errors # The integration range is over +/-stddev * int_delta_factor int_delta_factor = _define_integration_delta() output_construct = 0 for j in np.arange(np.size(line_data)): # Calculate integrated fluxes, errors; # -- First test that the lines are in the range covered by data if np.in1d(j, keep_lines): mean_lambda = line_data[j]['lambda'] * (1. + sfitted_model[j].redshift) # deal with blended O II 3727/3729 doublet if line_data[j]['name'] == '[OII]3727': # Calculate the integrated fluxes and errors iflux, ierr = integrate_line_flux(wave, flux, err, mean_lambda, sfitted_model[j].stddev * int_delta_factor, line3727=True) elif line_data[j]['name'] == '[OII]3729': # pdb.set_trace() # For 3729, use the flux derived for 3726 iflux = output_table['int_flux'][j - 1] #iflux = 0. # For 3729, use its own error. This is appropriate for the fitted errors of both lines crap, ierr = integrate_line_flux( wave, flux, err, mean_lambda, sfitted_model[j].stddev * int_delta_factor) else: # Calculate the integrated fluxes and errors iflux, ierr = integrate_line_flux( wave, flux, err, mean_lambda, sfitted_model[j].stddev * int_delta_factor) redshift_out = (sfitted_model[j].redshift)[0] sfitted_flux_out = np.sqrt( 2. * np.pi) * sfitted_model[j].amplitude * sfitted_model[j].stddev if output_construct == 0: # Define and construct the initial table to hold the results output_col_names, output_format, output_dtype = _define_output_table( ) output_data = [[line_data[j]['name']], [line_data[j]['ion']], [line_data[j]['lambda']], [line_data[j]['indx']], [line_data[j]['mode']], [mean_lambda], [sfitted_model[j].amplitude.value], [sfitted_model[j].stddev.value], [redshift_out], [sfitted_flux_out], [iflux], [ierr], [iflux / ierr]] output_table = Table(output_data, names=output_col_names, dtype=output_dtype) output_construct = 1 else: output_table.add_row([ line_data[j]['name'], line_data[j]['ion'], line_data[j]['lambda'], line_data[j]['indx'], line_data[j]['mode'], mean_lambda, sfitted_model[j].amplitude.value, sfitted_model[j].stddev.value, redshift_out, sfitted_flux_out, iflux, ierr, iflux / ierr ]) # Set the output format of the results table: colnames = output_table.colnames for j in np.arange(np.size(colnames)): output_table[colnames[j]].format = output_format[j] # Set up the spectral table: spec_table = Table([wave, flux, err, sfitted_flux], names=['wave', 'flux', 'err', 'spec_fit']) # Write summary FITS files if file_out is None: file_base = spec_file.strip('.fits') else: file_base = file_out table_file = file_base + '.HIIFitTable.fits' fit_file = file_base + '.HIIFitSpec.fits' output_table.write(table_file, overwrite=True) spec_table.write(fit_file, overwrite=True) return output_table
def __init__(self, filename, filetype=False, efil=None, **kwargs): """ creates the spectrum object """ self.filename = filename if filetype == False: #Take File Extention and try tt = os.path.splitext(filename)[1] if (tt == 'txt') | (tt == 'dat'): filetype = 'ascii' else: filetype = tt[1:len(tt)] # Read in Files in differet formats if filetype == 'ascii': from astropy.io import ascii dat = ascii.read(filename) tab = dat.keys() wave = np.array(dat[tab[0]]) flux = np.array(dat[tab[1]]) if (len(dat.keys()) >= 3): error = dat[tab[2]] else: error = 0. * flux elif filetype == 'fits': from astropy.io import fits file = fits.open(filename) #(cwd+'/'+filename) dat = file[1].data tab = dat.names wave = np.array(dat['wave'][0]) flux = np.array(dat['flux'][0]) if (len(tab) >= 3): error = np.array(dat['error'][0]) else: error = 0. * flux elif filetype == 'HSLA': from astropy.io import fits file = fits.open(filename) #(cwd+'/'+filename) dat = file[1].data tab = dat.names wave = np.array(dat['WAVE']) flux = np.array(dat['FLUX']) #/np.median(np.array(dat['FLUX'])) if (len(tab) >= 3): error = np.array( dat['ERROR']) #/np.median(np.array(dat['FLUX'])) else: error = 0. * flux if filetype == 'xfits': from linetools.spectra.xspectrum1d import XSpectrum1D sp = XSpectrum1D.from_file(filename) wave = sp.wavelength.value flux = sp.flux.value error = sp.sig.value elif filetype == 'p': import pickle dat = pickle.load(open(filename, "rb")) #tab=dat.keys() wave = np.array(dat['wave']) flux = np.array(dat['flux']) if (len(tab) >= 3): error = np.array(dat['error']) else: error = 0. * flux elif filetype == 'temp': from astropy.io import fits file = fits.open(filename) #(cwd+'/'+filename) #a=fits.open(path+'spec_knotA.fits') wave = file[2].data flux = file[0].data error = file[1].data #Use linetools.io.readspec to read file elif filetype == 'linetools': from linetools.spectra import io as tio sp = tio.readspec(filename, inflg=None, efil=efil, **kwargs) wave = sp.wavelength.value flux = sp.flux.value if sp.sig_is_set == False: print('Assuiming arbiarbitrary 10% error on flux') error = 0.1 * flux else: error = sp.sig.value self.wave = wave self.flux = flux self.error = error self.wrest = wave * (1. + 0.) self.zabs = 0.
#ax.get_xaxis().get_major_formatter().set_useOffset(False) plt.ylim(0., 1.1) plt.show() plt.close() ism = LineList('ISM') abslin = AbsLine(1215.670 * u.AA, z=2.0, linelist=ism) #abslin = AbsLine(1215.670*u.AA, linelist=ism) abslin.attrib['N'] = 10**14. / u.cm**2 # log N abslin.attrib['b'] = 25. * u.km / u.s abslin.attrib['z'] = 2.0 xspec = XSpectrum1D.from_file( resource_filename('linetools', '/spectra/tests/files/UM184_nF.fits')) #xspec = lsio.readspec(resource_filename('linetools','/spectra/tests/files/UM184_nF.fits')) #Load abslin.analy['spec'] = xspec #lsio.readspec(resource_filename('linetools','/spectra/tests/files/UM184_nF.fits'))#('../../linetools/spectra/tests/files/UM184_nF.fits') #Generate vmodel = abslin.generate_voigt() # Plot plt_line(vmodel) abslin.attrib['N'] = 10**17.5 / u.cm**2 abslin.attrib['b'] = 20. * u.km / u.s wave = np.linspace(3644, 3650, 100) * u.AA
def test_unmask(): spec = XSpectrum1D.from_file(data_path('UM184_nF.fits')) assert np.sum(spec.data['wave'].mask) > 0 spec.unmask() assert np.sum(spec.data['wave'].mask) == 0
def full_coadd(uves_table=None, outputbase=None, wavelength_range=None, airtovac=True): """full_coadd(uves_table=None, outputbase=None, wavelength_range=None, airtovac=True): Combine multiple UVES exposures UVES into a single spectrum, weighting by the inverse variance of the input data. Creates a single spectrum covering the full wavelength range of the individual exposures. Note: no guarantee the fluxes will be continuous if there are issues with the flux calibration of individual datasets. """ import numpy as np import astropy.units as u from astropy.table import Table from linetools.spectra.xspectrum1d import XSpectrum1D if uves_table == None: # There is no input table; let's create one. uves_table = uves_log() # Create minmax wavelengths for filename, wavelength array wave_minmax = [] wave_minmax.append(np.min(uves_table['WAVELMIN']) * 10.) wave_minmax.append(np.max(uves_table['WAVELMAX']) * 10.) wave_minmax = np.around(wave_minmax) if wavelength_range == None: wavelength_range = wave_minmax # Store the string to make the filename: file_wave = '{0:0.0f}.{1:0.0f}'.format(wavelength_range[0], wavelength_range[1]) # TODO: Allow for linear-space regular array # Create the wavelength array. For now uniform in log space log_steps = True if log_steps: wavelength_range = np.log10(wavelength_range) wavelength_step = 2.e-6 # log-space step out_wave = np.arange(wavelength_range[0], wavelength_range[1], wavelength_step, dtype=np.float64) out_wave = 10.**out_wave # Create the holder arrays out_inv_variance = np.zeros(np.size(out_wave), dtype=np.float32) out_weighted_flux = np.zeros(np.size(out_wave), dtype=np.float32) # Loop over files: for j in np.arange(np.size(uves_table)): # Filename: specfile = uves_table[j]['fitsName'] print('{0}: {1}'.format(j, specfile)) # Load the spectrum with XSpectrum1D: inspec = XSpectrum1D.from_file(specfile) inspec.meta['airvac'] = 'air' # Unless user requests, we transform to vacuum. if airtovac == True: inspec.airtovac() # Check for sig = 0: badErrors = (inspec.sig == 0) inspec.flux[badErrors] = np.nan inspec.sig[badErrors] = np.nan inspec.ivar[badErrors] = np.nan # Interpolate the UVES fluxes onto the wavelength grid using the XSpectrum1D functionality grid_spec = inspec.rebin(out_wave * u.angstrom, do_sig=True, grow_bad_sig=True) # Add new fluxes, errors into output weighting, flux arrays # The inverse variance is stored in the XSpectrum1D class out_inv_variance += grid_spec.ivar.value out_weighted_flux += grid_spec.flux.value * grid_spec.ivar.value ##### # Calculate the final output weighted mean flux and error by taking out the weighting out_flux = out_weighted_flux / out_inv_variance out_err = np.sqrt(1. / out_inv_variance) # Book-keeping: set up filename if outputbase == None: # If there is no base for the filenames, use the object name. outputbase = uves_table[0]['OBJECT'] # Create final filename outputfilename = "{0}.uves.{1}.fits".format(outputbase, file_wave) # Set up the output table outputtable = Table([out_wave, out_flux, out_err], names=['wave', 'flux', 'err']) # Load the spectrum in the standard way to get the units right: inspec = Table.read(uves_table[0]['fitsName']) # Assign units outputtable['wave'].unit = inspec['WAVE'].unit outputtable['flux'].unit = inspec['FLUX'].unit outputtable['err'].unit = inspec['ERR'].unit # TODO: Get the header information to save # The header: outputtable.meta = inspec.meta outputtable.meta['NCOMBINE'] = np.size(uves_table) outputtable.meta['HISTORY'] = 'Coadd of {0}'.format( uves_table[0]['fitsName']) for j in np.arange(1, np.size(uves_table)): outputtable.meta['HISTORY'] += ', {0}'.format( uves_table[j]['fitsName']) # TODO: Switch back to the XSpectrum1D format? # # Put the results into the XSpectrum1D format #out_spec = XSpectrum1D.from_tuple((out_wave*u.angstrom,out_flux,out_err), # verbose=False) #out_spec.write(outputfilename) # Write the output outputtable.write(outputfilename, overwrite=True) print('Wrote ' + outputfilename + '.')
def get_position(iden): targ_ra_hr = name[48:50] targ_ra_min = name[50:52] targ_dec_hr = name[53:55] targ_dec_min = name[55:57] targ_RA = targ_ra_hr + ':' + targ_ra_min targ_DEC = targ_dec_hr + ':' + targ_dec_min return targ_RA, targ_DEC # Now let's plot all the spectra and save each figure fname = glob('/Users/ryan/Desktop/keck_spectra/2017mar5/*F.fits') for name in fname: sp = XSpectrum1D.from_file(name) targ_coord = get_position(name[42:-5]) targ_coord = get_position(name) dtype = [('RA', 'U5'), ('DEC', 'U5'), ('zq', float), ('z', float), ('b', float), ('logM', float), ('QSO_mag', float), ('Sod_line', float)] prop = numpy.genfromtxt( '/Users/ryan/Desktop/keck_spectra/2017mar5/target_list.dat', usecols=(0, 1, 2, 3, 4, 5, 6, 7), dtype=dtype) # Match the target with its properties by using RA and DEC cooords w = numpy.logical_and(targ_coord[0] == prop['RA'], targ_coord[1] == prop['DEC']) data = prop[w]