def test_Linefit(): hdu = fits.open(inimage) # create the header information grating = hdu[1].header['GRATING'].strip() grang = hdu[1].header['GR-ANGLE'] arang = hdu[1].header['AR-ANGLE'] slit = float(hdu[1].header['MASKID']) xbin, ybin = hdu[1].header['CCDSUM'].strip().split() # print instrume, grating, grang, arang, filter # print xbin, ybin # print len(data), len(data[0]) # create the RSS Model rssmodel = RSSModel.RSSModel(grating_name=grating, gratang=grang, camang=arang, slit=slit, xbin=int(xbin), ybin=int(ybin)) alpha = rssmodel.rss.gratang beta = rssmodel.rss.gratang - rssmodel.rss.camang sigma = 1e7 * rssmodel.rss.calc_resolelement(alpha, beta) # create artificial spectrum # create the spectrum stype = 'line' w, s = np.loadtxt(inspectra, usecols=(0, 1), unpack=True) spec = Spectrum(w, s, wrange=[4000, 5000], dw=0.1, stype=stype, sigma=sigma) spec.flux = spec.set_dispersion(sigma=sigma)
def test_Linefit(): hdu = fits.open(inimage) # create the data arra data = hdu[1].data # create the header information grating = hdu[1].header['GRATING'].strip() grang = hdu[1].header['GR-ANGLE'] arang = hdu[1].header['AR-ANGLE'] slit = float(hdu[1].header['MASKID']) xbin, ybin = hdu[1].header['CCDSUM'].strip().split() # print instrume, grating, grang, arang, filter # print xbin, ybin # print len(data), len(data[0]) # create the RSS Model rssmodel = RSSModel.RSSModel(grating_name=grating, gratang=grang, camang=arang, slit=slit, xbin=int(xbin), ybin=int(ybin)) alpha = rssmodel.rss.gratang beta = rssmodel.rss.gratang - rssmodel.rss.camang sigma = 1e7 * rssmodel.rss.calc_resolelement(alpha, beta) # create the observed spectrum midpoint = int(0.5 * len(data)) xarr = np.arange(len(data[0]), dtype='float') farr = data[midpoint, :] obs_spec = Spectrum(xarr, farr, stype='continuum') # create artificial spectrum stype = 'line' w, s = np.loadtxt(inspectra, usecols=(0, 1), unpack=True) cal_spec = Spectrum(w, s, wrange=[4000, 5000], dw=0.1, stype=stype, sigma=sigma) cal_spec.flux = cal_spec.set_dispersion(sigma=sigma) cal_spec.flux = cal_spec.flux * obs_spec.flux.max() / cal_spec.flux.max() + 1 lf = LF.LineFit(obs_spec, cal_spec, function='legendre', order=3) lf.set_coef([4.23180070e+03, 2.45517852e-01, -4.46931562e-06, -2.22067766e-10]) print(lf(2000)) print(lf.obs_spec.get_flux(2000), lf.flux(2000)) print('chisq ', (lf.errfit(lf.coef, xarr, farr) ** 2).sum() / 1e7) lf.set_coef([4.23280070e+03, 2.45517852e-01, -4.46931562e-06, -2.22067766e-10]) print(lf(2000)) print(lf.obs_spec.get_flux(2000), lf.flux(2000)) print('chisq ', (lf.errfit(lf.coef, xarr, farr) ** 2).sum() / 1e7) # print lf.lfit(xarr) # print lf.coef # print lf(2000) # print lf.results pl.figure() pl.plot(lf(lf.obs_spec.wavelength), lf.obs_spec.get_flux(xarr)) pl.plot(lf.cal_spec.wavelength, lf.cal_spec.flux) pl.show()
def specsens(specfile, outfile, stdfile, extfile, airmass=None, exptime=None, stdzp=3.68e-20, function='polynomial', order=3, thresh=3, niter=5, clobber=True, logfile='salt.log',verbose=True): with logging(logfile,debug) as log: #read in the specfile and create a spectrum object obs_spectra=st.readspectrum(specfile, error=True, ftype='ascii') #read in the std file and convert from magnitudes to fnu #then convert it to fwave (ergs/s/cm2/A) std_spectra=st.readspectrum(stdfile, error=False, ftype='ascii') std_spectra.flux=Spectrum.magtoflux(std_spectra.flux, stdzp) std_spectra.flux=Spectrum.fnutofwave(std_spectra.wavelength, std_spectra.flux) #read in the extinction file (leave in magnitudes) ext_spectra=st.readspectrum(extfile, error=False, ftype='ascii') #determine the airmass if not specified if saltio.checkfornone(airmass) is None: message='Airmass was not supplied' raise SALTSpecError(message) #determine the exptime if not specified if saltio.checkfornone(airmass) is None: message='Exposure Time was not supplied' raise SALTSpecError(message) #calculate the calibrated spectra log.message('Calculating the calibration curve for %s' % specfile) cal_spectra=sensfunc(obs_spectra, std_spectra, ext_spectra, airmass, exptime) #fit the spectra--first take a first cut of the spectra #using the median absolute deviation to throw away bad points cmed=np.median(cal_spectra.flux) cmad=saltstat.mad(cal_spectra.flux) mask=(abs(cal_spectra.flux-cmed)<thresh*cmad) mask=(cal_spectra.flux>0) #now fit the data fit=interfit(cal_spectra.wavelength[mask], cal_spectra.flux[mask], function=function, order=order, thresh=thresh, niter=niter) fit.interfit() #print 'plotting...' #figure() #plot(cal_spectra.wavelength, cal_spectra.flux) #plot(obs_spectra.wavelength, obs_spectra.flux*cal_spectra.flux.mean()/obs_spectra.flux.mean()) #plot(std_spectra.wavelength, std_spectra.flux*cal_spectra.flux.mean()/std_spectra.flux.mean()) #plot(cal_spectra.wavelength, fit(cal_spectra.wavelength)) #show() #write the spectra out cal_spectra.flux=fit(cal_spectra.wavelength) st.writespectrum(cal_spectra, outfile, ftype='ascii')
def test_Linefit(): hdu = pyfits.open(inimage) # create the data arra data = hdu[1].data # create the header information instrume = hdu[1].header['INSTRUME'].strip() grating = hdu[1].header['GRATING'].strip() grang = hdu[1].header['GR-ANGLE'] arang = hdu[1].header['AR-ANGLE'] filter = hdu[1].header['FILTER'].strip() slit = float(hdu[1].header['MASKID']) xbin, ybin = hdu[1].header['CCDSUM'].strip().split() # print instrume, grating, grang, arang, filter # print xbin, ybin # print len(data), len(data[0]) # create the RSS Model rssmodel = RSSModel.RSSModel(grating_name=grating, gratang=grang, camang=arang, slit=slit, xbin=int(xbin), ybin=int(ybin)) alpha = rssmodel.rss.gratang beta = rssmodel.rss.gratang - rssmodel.rss.camang sigma = 1e7 * rssmodel.rss.calc_resolelement(alpha, beta) # create artificial spectrum # create the spectrum stype = 'line' w, s = np.loadtxt(inspectra, usecols=(0, 1), unpack=True) spec = Spectrum(w, s, wrange=[4000, 5000], dw=0.1, stype='line', sigma=sigma) spec.flux = spec.set_dispersion(sigma=sigma) sw_arr, sf_arr = spec.wavelength, spec.flux
def extract(hdu, ext=1, method='normal', section=[], minsize=3.0, thresh=3.0, convert=True): """For a given image, extract a 1D spectra from the image and write the spectra to the output file """ ap_list = [] i = ext if hdu[i].name == 'SCI': # set up the data, variance, and bad pixel frames # first step is to find the region to extract data_arr = hdu[i].data try: var_arr = hdu[hdu[i].header['VAREXT']].data except: var_arr = None try: bpm_arr = hdu[hdu[i].header['BPMEXT']].data except: bpm_arr = None var_arr = None bpm_arr = None xarr = np.arange(len(data_arr[0])) # convert using the WCS information try: w0 = hdu[i].header['CRVAL1'] dw = hdu[i].header['CD1_1'] except Exception as e: msg = 'Error on Ext %i: %s' % (i, e) raise Exception(msg) warr = w0 + dw * xarr # convert from air to vacuum if convert: warr = Spectrum.air2vac(warr) # set up the sections in case of findobj if section is None: section = findobj.findObjects( data_arr, method='median', specaxis=1, minsize=minsize, thresh=thresh, niter=5) # extract all of the regions for sec in section: ap = apext.apext(warr, data_arr, ivar=var_arr) y1, y2 = sec ap.flatten(y1, y2) ap_list.append(ap) return ap_list
def makeartificial(sw, sf, fmax, res, dw, pad=10, nkern=200, wrange=None): """For a given line list with fluxes, create an artifical spectrum""" if wrange is None: wrange = [sw.min() - pad, sw.max() + pad] spec = Spectrum.Spectrum( sw, sf, wrange=wrange, dw=dw, stype='line', sigma=res) spec.flux = spec.flux * fmax / spec.flux.max() return spec.wavelength, spec.flux
def getfitsspec(dw=0.1, res=0.1): wrange = None #[y.min(), y.max()] shdu = fits.open('thar.fits') ctype1=shdu[0].header['CTYPE1'] crval1=shdu[0].header['CRVAL1'] cdelt1=shdu[0].header['CDELT1'] sf=shdu[0].data sw=crval1+cdelt1*np.arange(len(shdu[0].data)) spec=Spectrum.Spectrum(sw, sf, wrange=wrange, dw=dw, stype='continuum', sigma=res) return spec
def readspectrum(specfile, stype='continuum', error=True, cols=None, ftype=None): """Given a specfile, read in the spectra and return a spectrum object specfile--file containing the input spectra error--include an error column in the creation of the spectrum object cols--columns or column names for the wavelength, flux, and/or flux error ftype--type of file (ascii or fits) """ # set the ftype for a fits file if ftype is None: if specfile[-5] == '.fits': ftype = 'fits' else: ftype = 'ascii' if ftype == 'ascii': if error: if cols is None: cols = (0, 1, 2) warr, farr, farr_err = np.loadtxt( specfile, usecols=cols, unpack=True) spectra = Spectrum.Spectrum(warr, farr, farr_err, stype=stype) else: if cols is None: cols = (0, 1) warr, farr = np.loadtxt(specfile, usecols=cols, unpack=True) spectra = Spectrum.Spectrum(warr, farr, stype=stype) elif ftype == 'fits': message = 'Support for FITS files not provided yet' raise SaltError(message) else: message = 'Support for %s files is not provided' raise SaltError(message) return spectra
def calfunc(obs_spectra, std_spectra, ext_spectra, airmass, exptime, error=False): """Given an observe spectra, calculate the calibration curve for the spectra. All data is interpolated to the binning of the obs_spectra. The calibrated spectra is then calculated from: C = F_obs/ F_std / 10**(-0.4*A*E)/T/dW where F_obs is the observed flux from the source, F_std is the standard spectra, A is the airmass, E is the extinction in mags, T is the exposure time and dW is the bandpass Parameters ----------- obs_spectra--spectrum of the observed star (counts/A) std_spectra--know spectrum of the standard star (ergs/s/cm2/A) ext_spectra--spectrum of the extinction curve (in mags) airmass--airmass of the observations exptime--exposure time of the observations function """ # re-interpt the std_spectra over the same wavelength std_spectra.interp(obs_spectra.wavelength) # re-interp the ext_spetra over the sam ewavelength ext_spectra.interp(obs_spectra.wavelength) # create the calibration spectra cal_spectra = Spectrum.Spectrum( obs_spectra.wavelength, obs_spectra.flux.copy(), stype='continuum') # set up the bandpass bandpass = np.diff(obs_spectra.wavelength).mean() # correct for extinction cal_spectra.flux = obs_spectra.flux / \ 10 ** (-0.4 * airmass * ext_spectra.flux) # correct for the exposure time and calculation the calitivity curve cal_spectra.flux = cal_spectra.flux / exptime / bandpass / std_spectra.flux # correct the error calc if error: cal_spectra.var = obs_spectra.var * cal_spectra.flux / obs_spectra.flux return cal_spectra
def test_CreateImage(): # read in the data hdu = fits.open(inimg) im_arr = hdu[1].data hdu.close() # set up the spectrum stype = 'line' w, s = np.loadtxt('Xe.dat', usecols=(0, 1), unpack=True) spec = Spectrum(w, s, wrange=[4000, 5000], dw=0.1, stype=stype) # set up the spectrograph dx = 2 * 0.015 * 8.169 dy = 2 * 0.015 * 0.101 # set up the spectrograph # rssmodel=RSSModel.RSSModel(grating_name='PG0900', gratang=13.625, camang=27.25, slit=1.0, xbin=2, ybin=2, xpos=dx, ypos=dy) rssmodel = RSSModel.RSSModel( grating_name='PG3000', gratang=43.625, camang=87.25, slit=2.0, xbin=2, ybin=2, xpos=dx, ypos=dy) rssmodel.set_camera(name='RSS', focallength=330.0) rss = rssmodel.rss # set up the outfile if os.path.isfile(outfile): os.remove(outfile) arr = im_arr.copy() arr = CreateImage(spec, rss) arr = arr * im_arr.max() / spec.flux.max() writeout(arr, outfile)
def specsens(specfile, outfile, stdfile, extfile, airmass=None, exptime=None, stdzp=3.68e-20, function='polynomial', order=3, thresh=3, niter=5, fitter='gaussian', clobber=True, logfile='salt.log', verbose=True): with logging(logfile, debug) as log: # read in the specfile and create a spectrum object obs_spectra = st.readspectrum(specfile.strip(), error=True, ftype='ascii') # smooth the observed spectrum # read in the std file and convert from magnitudes to fnu # then convert it to fwave (ergs/s/cm2/A) std_spectra = st.readspectrum(stdfile.strip(), error=False, ftype='ascii') std_spectra.flux = Spectrum.magtoflux(std_spectra.flux, stdzp) std_spectra.flux = Spectrum.fnutofwave(std_spectra.wavelength, std_spectra.flux) # Get the typical bandpass of the standard star, std_bandpass = np.diff(std_spectra.wavelength).mean() # Smooth the observed spectrum to that bandpass obs_spectra.flux = st.boxcar_smooth(obs_spectra, std_bandpass) # read in the extinction file (leave in magnitudes) ext_spectra = st.readspectrum(extfile.strip(), error=False, ftype='ascii') # determine the airmass if not specified if saltio.checkfornone(airmass) is None: message = 'Airmass was not supplied' raise SALTSpecError(message) # determine the exptime if not specified if saltio.checkfornone(exptime) is None: message = 'Exposure Time was not supplied' raise SALTSpecError(message) # calculate the calibrated spectra log.message('Calculating the calibration curve for %s' % specfile) cal_spectra = sensfunc(obs_spectra, std_spectra, ext_spectra, airmass, exptime) # plot(cal_spectra.wavelength, cal_spectra.flux * std_spectra.flux) # fit the spectra--first take a first cut of the spectra # using the median absolute deviation to throw away bad points cmed = np.median(cal_spectra.flux) cmad = saltstat.mad(cal_spectra.flux) mask = (abs(cal_spectra.flux - cmed) < thresh * cmad) mask = np.logical_and(mask, (cal_spectra.flux > 0)) # now fit the data # Fit using a gaussian process. if fitter == 'gaussian': from sklearn.gaussian_process import GaussianProcess #Instanciate a Gaussian Process model dy = obs_spectra.var[mask]**0.5 dy /= obs_spectra.flux[mask] / cal_spectra.flux[mask] y = cal_spectra.flux[mask] gp = GaussianProcess(corr='squared_exponential', theta0=1e-2, thetaL=1e-4, thetaU=0.1, nugget=(dy / y)**2.0) X = np.atleast_2d(cal_spectra.wavelength[mask]).T # Fit to data using Maximum Likelihood Estimation of the parameters gp.fit(X, y) x = np.atleast_2d(cal_spectra.wavelength).T # Make the prediction on the meshed x-axis (ask for MSE as well) y_pred = gp.predict(x) cal_spectra.flux = y_pred else: fit = interfit(cal_spectra.wavelength[mask], cal_spectra.flux[mask], function=function, order=order, thresh=thresh, niter=niter) fit.interfit() cal_spectra.flux = fit(cal_spectra.wavelength) # write the spectra out st.writespectrum(cal_spectra, outfile, ftype='ascii')
def plotarcspectra(arclist='Ne.txt', grating='PG0900', gratang=15.0, camang=30.0, slit=1.5, xbin=2, ybin=2): """Plot an Arc Line list for a given RSS set up arclist--an arc line list in the format of 'wavelength flux' for arc lines grating--name of the grating gratang--angle of the grating camang--angle of the camera (articulation angle) slit--slit width in arcseconds xbin--xbinning ybin--ybinning """ rss = RSSModel.RSSModel(grating_name=grating, gratang=gratang, camang=camang, slit=slit, xbin=xbin, ybin=ybin) #print out some basic statistics print 1e7 * rss.calc_bluewavelength(), 1e7 * rss.calc_centralwavelength( ), 1e7 * rss.calc_redwavelength() R = rss.calc_resolution(rss.calc_centralwavelength(), rss.alpha(), -rss.beta()) res = 1e7 * rss.calc_resolelement(rss.alpha(), -rss.beta()) print R, res #set up the detector ycen = rss.detector.get_ypixcenter() d_arr = rss.detector.make_detector()[ycen, :] #creates 1-D detector map xarr = np.arange(len(d_arr)) w = 1e7 * rss.get_wavelength(xarr) #set up the artificial spectrum sw, sf = pl.loadtxt(arclist, usecols=(0, 1), unpack=True) wrange = [1e7 * rss.calc_bluewavelength(), 1e7 * rss.calc_redwavelength()] spec = Spectrum.Spectrum(sw, sf, wrange=wrange, dw=res / 10, stype='line', sigma=res) #interpolate it over the same range as the detector spec.interp(w) #plot it pl.figure() pl.plot(spec.wavelength, d_arr * ((spec.flux) / spec.flux.max())) print pl.gca().get_ylim() for i, f in zip(sw, sf): if i > spec.wavelength.min() and i < spec.wavelength.max(): print i, f, sf.max(), spec.flux.max() #pl.text(i, f/sf.max(), i, fontsize='large', rotation=90) y = max(0.1, f / sf.max()) pl.text(i, y, i, rotation=90) pl.show()
def extract(hdu, ext=1, method='normal', section=[], minsize=3.0, thresh=3.0, convert=True): """For a given image, extract a 1D spectra from the image and write the spectra to the output file """ ap_list = [] i = ext if hdu[i].name == 'SCI': # set up the data, variance, and bad pixel frames # first step is to find the region to extract data_arr = hdu[i].data try: var_arr = hdu[hdu[i].header['VAREXT']].data except: var_arr = None try: bpm_arr = hdu[hdu[i].header['BPMEXT']].data except: bpm_arr = None var_arr = None bpm_arr = None xarr = np.arange(len(data_arr[0])) # convert using the WCS information try: w0 = saltkey.get('CRVAL1', hdu[i]) dw = saltkey.get('CD1_1', hdu[i]) except Exception as e: msg = 'Error on Ext %i: %s' % (i, e) raise SALTSpecError(msg) warr = w0 + dw * xarr # convert from air to vacuum if convert: warr = Spectrum.air2vac(warr) # set up the sections in case of findobj if section is None: section = findobj.findObjects(data_arr, method='median', specaxis=1, minsize=minsize, thresh=thresh, niter=5) # extract all of the regions for sec in section: ap = apext.apext(warr, data_arr, ivar=var_arr) y1, y2 = sec ap.flatten(y1, y2) ap_list.append(ap) return ap_list
def test_Linefit(): hdu = fits.open(inimage) # create the data arra data = hdu[1].data # create the header information grating = hdu[1].header['GRATING'].strip() grang = hdu[1].header['GR-ANGLE'] arang = hdu[1].header['AR-ANGLE'] slit = float(hdu[1].header['MASKID']) xbin, ybin = hdu[1].header['CCDSUM'].strip().split() # print instrume, grating, grang, arang, filter # print xbin, ybin # print len(data), len(data[0]) # create the RSS Model rssmodel = RSSModel.RSSModel(grating_name=grating, gratang=grang, camang=arang, slit=slit, xbin=int(xbin), ybin=int(ybin)) alpha = rssmodel.rss.gratang beta = rssmodel.rss.gratang - rssmodel.rss.camang sigma = 1e7 * rssmodel.rss.calc_resolelement(alpha, beta) # create the observed spectrum midpoint = int(0.5 * len(data)) xarr = np.arange(len(data[0]), dtype='float') farr = data[midpoint, :] obs_spec = Spectrum(xarr, farr, stype='continuum') # create artificial spectrum stype = 'line' w, s = np.loadtxt(inspectra, usecols=(0, 1), unpack=True) cal_spec = Spectrum(w, s, wrange=[4000, 5000], dw=0.1, stype=stype, sigma=sigma) cal_spec.flux = cal_spec.set_dispersion(sigma=sigma) cal_spec.flux = cal_spec.flux * obs_spec.flux.max() / cal_spec.flux.max( ) + 1 lf = LF.LineFit(obs_spec, cal_spec, function='legendre', order=3) lf.set_coef( [4.23180070e+03, 2.45517852e-01, -4.46931562e-06, -2.22067766e-10]) print(lf(2000)) print(lf.obs_spec.get_flux(2000), lf.flux(2000)) print('chisq ', (lf.errfit(lf.coef, xarr, farr)**2).sum() / 1e7) lf.set_coef( [4.23280070e+03, 2.45517852e-01, -4.46931562e-06, -2.22067766e-10]) print(lf(2000)) print(lf.obs_spec.get_flux(2000), lf.flux(2000)) print('chisq ', (lf.errfit(lf.coef, xarr, farr)**2).sum() / 1e7) # print lf.lfit(xarr) # print lf.coef # print lf(2000) # print lf.results pl.figure() pl.plot(lf(lf.obs_spec.wavelength), lf.obs_spec.get_flux(xarr)) pl.plot(lf.cal_spec.wavelength, lf.cal_spec.flux) pl.show()
R = rss.calc_resolution(rss.calc_centralwavelength(), rss.alpha(), -rss.beta()) res = 1e7 * rss.calc_resolelement(rss.alpha(), -rss.beta()) print R, res #set up the detector ycen = rss.detector.get_ypixcenter() d_arr = rss.detector.make_detector()[ycen, :] xarr = np.arange(len(d_arr)) w = 1e7 * rss.get_wavelength(xarr) #set up the artificial spectrum sw, sf = pl.loadtxt('Ar.txt', usecols=(0, 1), unpack=True) wrange = [1e7 * rss.calc_bluewavelength(), 1e7 * rss.calc_redwavelength()] spec = Spectrum.Spectrum(sw, sf, wrange=wrange, dw=res / 10, stype='line', sigma=res) #interpolate it over the same range as the detector spec.interp(w) #plot it pl.figure() pl.plot(spec.wavelength, d_arr * ((spec.flux) / spec.flux.max())) pl.plot(spec.wavelength, d_arr * 0.1) yy = np.median(data[1000:1050, 3:3173], 0) pl.plot(spec.wavelength, yy / yy.max()) ymod = d_arr * ((spec.flux) / spec.flux.max()) ydata = yy / yy.max()
def arclisfromhdr(hdr, slitwidth=1.50, xbin=2, ybin=2, lamp='Ar.txt'): # ** some numbers below hardwired for 2x2 binning (~3170 pix) ** grname = hdr['grating'] camang = hdr['camang'] gratang = hdr['gr-angle'] rss = RSSModel.RSSModel(grating_name=grname, gratang=gratang, camang=camang, slit=slitwidth, xbin=xbin, ybin=ybin) # set up the detector ycen = rss.detector.get_ypixcenter() d_arr = rss.detector.make_detector()[ycen, :] xarr = np.arange(len(d_arr)) w = 1e7 * rss.get_wavelength(xarr) #set up the artificial spectrum res = 1e7 * rss.calc_resolelement(rss.alpha(), -rss.beta()) sw, sf = pl.loadtxt(lamp, usecols=(0, 1), unpack=True) wrange = [1e7 * rss.calc_bluewavelength(), 1e7 * rss.calc_redwavelength()] spec = Spectrum.Spectrum(sw, sf, wrange=wrange, dw=res / 10, stype='line', sigma=res) #interpolate it over the same range as the detector spec.interp(w) if (0): #plot it pl.figure() pl.plot(spec.wavelength, d_arr * ((spec.flux) / spec.flux.max())) pl.plot(spec.wavelength, d_arr * 0.1) #yy=np.median(data[1000:1050,3:3173],0) #pl.plot(spec.wavelength,yy/yy.max()) ymod = d_arr * ((spec.flux) / spec.flux.max()) ydata = yy / yy.max() off, rval = xcor2(ydata, ymod, 100.) yyy = np.roll(yy, -int(off)) / yy.max() pl.plot(spec.wavelength, yyy) pl.show() stop() # We need to return # - a matched list of wavelength(of each pixel),flux for the arc # - a list of the arc lines modarclam = spec.wavelength modarcspec = d_arr * ((spec.flux) / spec.flux.max()) # extract pixel positions for lines of wavelength sw: xpix = np.arange(np.size(modarclam)) ixp = np.interp(sw, modarclam, xpix, left=0, right=0) ok = np.reshape(((ixp > 0.) & (ixp < 3170)).nonzero(), -1) np.savetxt('_tmparc.lis', np.transpose((ixp[ok], sw[ok], sw[ok]))) return modarclam, modarcspec
def extract_spectra(hdu, yc, dy, outfile, minsize=5, thresh=3, grow=0, smooth=False, maskzeros=False, convert=True, cleanspectra=True, calfile=None, clobber=True, specformat='ascii'): """From an image, extract a spectra. """ data=hdu[1].data #replace the zeros with the average from the frame if maskzeros: mean,std=iterstat(data[data>0]) #rdata=mean np.random.normal(mean, std, size=data.shape) data[data<=0]=mean #rdata[data<=0] y1=yc-dy y2=yc+dy #sy1=y2-2*dy #sy2=y2+2*dy #sdata = 1.0 * data #y,x = np.indices(sdata.shape) #for i in range(sdata.shape[1]): # mask=(hdu[3].data[:,i]==0) # mask[sy1:sy2] = 0 # if mask.sum()>0: # sdata[y1:y2,i] = np.interp(y[y1:y2,i], y[:,i][mask], data[:,i][mask]) #hdu[1].data = sdata #sk_list=extract(hdu, method='normal', section=[(y1,y2)], minsize=minsize, thresh=thresh, convert=True) #ap_list[0].ldata=ap_list[0].ldata-sk_list[0].ldata #ap_list[0].ldata=ap_list[0].ldata-float(y2-y1)/(sy2-sy1)*sk_list[0].ldata ap_list=extract(hdu, method='normal', section=[(y1,y2)], minsize=minsize, thresh=thresh, convert=convert) sy1a=y2 sy2a=sy1a+2.0*dy ska_list=extract(hdu, method='normal', section=[(sy1a,sy2a)], minsize=minsize, thresh=thresh, convert=convert) sy2b=y1-dy sy1b=sy2b-2.0*dy skb_list=extract(hdu, method='normal', section=[(sy1b,sy2b)], minsize=minsize, thresh=thresh, convert=convert) print sy1b, sy2b sdata = 0.5*(ska_list[0].ldata/(sy2a-sy1a) + skb_list[0].ldata/(sy2b-sy1b)) #sdata = ska_list[0].ldata/(sy2a-sy1a) #sdata = skb_list[0].ldata/(sy2b-sy1b) raw = 1.0 * ap_list[0].ldata ap_list[0].ldata=ap_list[0].ldata-float(y2-y1) * sdata print ap_list[0].wave[10], ap_list[0].ldata[10], ap_list[0].lvar[10] flux_spec=Spectrum.Spectrum(ap_list[0].wave, ap_list[0].ldata, abs(ap_list[0].lvar)**0.5, stype='continuum') print flux_spec.wavelength[10], flux_spec.flux[10], flux_spec.var[10] if cleanspectra: clean_spectra(ap_list[0], grow=grow) if calfile: cal_spectra=st.readspectrum(calfile, error=False, ftype='ascii') airmass=hdu[0].header['AIRMASS'] exptime=hdu[0].header['EXPTIME'] extfile=iraf.osfn("pysalt$data/site/suth_extinct.dat") ext_spectra=st.readspectrum(extfile, error=False, ftype='ascii') flux_spec=Spectrum.Spectrum(ap_list[0].wave, ap_list[0].ldata, abs(ap_list[0].lvar)**0.5, stype='continuum') print flux_spec.flux[10], flux_spec.var[10] flux_spec=calfunc(flux_spec, cal_spectra, ext_spectra, airmass, exptime, True) print flux_spec.flux[10], flux_spec.var[10] else: flux_spec = Spectrum.Spectrum(ap_list[0].wave, ap_list[0].ldata, abs(ap_list[0].lvar)**0.5, stype='continuum') if specformat == 'ascii': write_ascii(outfile, flux_spec, clobber=clobber) elif specformat == 'lcogt': write_lcogt(outfile, flux_spec, hdu, sky=float(y2-y1) * sdata, raw = raw, clobber=clobber)
def specsens(specfile, outfile, stdfile, extfile, airmass=None, exptime=None, stdzp=3.68e-20, function='polynomial', order=3, thresh=3, niter=5, fitter='gaussian', clobber=True, logfile='salt.log', verbose=True): with logging(logfile, debug) as log: # read in the specfile and create a spectrum object obs_spectra = st.readspectrum(specfile.strip(), error=True, ftype='ascii') # smooth the observed spectrum # read in the std file and convert from magnitudes to fnu # then convert it to fwave (ergs/s/cm2/A) std_spectra = st.readspectrum(stdfile.strip(), error=False, ftype='ascii') std_spectra.flux = Spectrum.magtoflux(std_spectra.flux, stdzp) std_spectra.flux = Spectrum.fnutofwave( std_spectra.wavelength, std_spectra.flux) # Get the typical bandpass of the standard star, std_bandpass = np.diff(std_spectra.wavelength).mean() # Smooth the observed spectrum to that bandpass obs_spectra.flux = st.boxcar_smooth(obs_spectra, std_bandpass) # read in the extinction file (leave in magnitudes) ext_spectra = st.readspectrum(extfile.strip(), error=False, ftype='ascii') # determine the airmass if not specified if saltio.checkfornone(airmass) is None: message = 'Airmass was not supplied' raise SALTSpecError(message) # determine the exptime if not specified if saltio.checkfornone(exptime) is None: message = 'Exposure Time was not supplied' raise SALTSpecError(message) # calculate the calibrated spectra log.message('Calculating the calibration curve for %s' % specfile) cal_spectra = sensfunc( obs_spectra, std_spectra, ext_spectra, airmass, exptime) # plot(cal_spectra.wavelength, cal_spectra.flux * std_spectra.flux) # fit the spectra--first take a first cut of the spectra # using the median absolute deviation to throw away bad points cmed = np.median(cal_spectra.flux) cmad = saltstat.mad(cal_spectra.flux) mask = (abs(cal_spectra.flux - cmed) < thresh * cmad) mask = np.logical_and(mask, (cal_spectra.flux > 0)) # now fit the data # Fit using a gaussian process. if fitter=='gaussian': from sklearn.gaussian_process import GaussianProcess #Instanciate a Gaussian Process model dy = obs_spectra.var[mask] ** 0.5 dy /= obs_spectra.flux[mask] / cal_spectra.flux[mask] y = cal_spectra.flux[mask] gp = GaussianProcess(corr='squared_exponential', theta0=1e-2, thetaL=1e-4, thetaU=0.1, nugget=(dy / y) ** 2.0) X = np.atleast_2d(cal_spectra.wavelength[mask]).T # Fit to data using Maximum Likelihood Estimation of the parameters gp.fit(X, y) x = np.atleast_2d(cal_spectra.wavelength).T # Make the prediction on the meshed x-axis (ask for MSE as well) y_pred = gp.predict(x) cal_spectra.flux = y_pred else: fit=interfit(cal_spectra.wavelength[mask], cal_spectra.flux[mask], function=function, order=order, thresh=thresh, niter=niter) fit.interfit() cal_spectra.flux=fit(cal_spectra.wavelength) # write the spectra out st.writespectrum(cal_spectra, outfile, ftype='ascii')