def loadStdSpectrum(self, objectName="G158-100"): #import the known spectrum of the calibrator and rebin to the histogram parameters given #must be imported into array with dtype float so division later does not have error std = MKIDStd.MKIDStd() a = std.load(objectName) a = std.countsToErgs(a) #convert std spectrum to ergs/s/Angs/cm^2 for BB fitting and cleaning self.stdWvls = np.array(a[:,0]) self.stdFlux = np.array(a[:,1]) #std object spectrum in ergs/s/Angs/cm^2 if self.plots: #create figure for plotting standard spectrum modifications self.stdFig = plt.figure() self.stdAx = self.stdFig.add_subplot(111) plt.xlim(4000,11000) plt.plot(self.stdWvls,self.stdFlux*1E15,linewidth=1,color='grey',alpha=0.75) convX_rev,convY_rev = self.cleanSpectrum(self.stdWvls,self.stdFlux) convX = convX_rev[::-1] #convolved spectrum comes back sorted backwards, from long wvls to low which screws up rebinning convY = convY_rev[::-1] #rebin cleaned spectrum to flat cal's wvlBinEdges newa = rebin(convX,convY,self.wvlBinEdges) rebinnedWvl = np.array(newa[:,0]) rebinnedFlux = np.array(newa[:,1]) if self.plots: #plot final resampled spectrum plt.plot(convX,convY*1E15,color='blue') plt.step(rebinnedWvl,rebinnedFlux*1E15,color = 'black',where='mid') plt.legend(['%s Spectrum'%self.objectName,'Blackbody Fit','Gaussian Convolved Spectrum','Rebinned Spectrum'],'upper right', numpoints=1) plt.xlabel(ur"Wavelength (\r{A})") plt.ylabel(ur"Flux (10$^{-15}$ ergs s$^{-1}$ cm$^{-2}$ \r{A}$^{-1}$)") plt.ylim(1,5) plt.savefig(self.plotSavePath+'FluxCal_StdSpectrum_%s.eps'%self.objectName,format='eps') #convert standard spectrum back into counts/s/angstrom/cm^2 newa = std.ergsToCounts(newa) self.binnedSpectrum = np.array(newa[:,1])
def cleanSpectrum_old(self,x,y,objectName): ''' function to take high resolution spectrum of standard star, extend IR coverage with an exponential tail, then rebin down to ARCONS resolution. This function has since been deprecated with the current cleanSpectrum which uses a BB fit to extend IR coverage, and does the rebinning using a gaussian convolution. This is left in for reference. ''' #locations and widths of absorption features in Angstroms #features = [3890,3970,4099,4340,4860,6564,6883,7619] #widths = [50,50,50,50,50,50,50,50] #for i in xrange(len(features)): # #check for absorption feature in std spectrum # ind = np.where((x<(features[i]+15)) & (x>(features[i]-15)))[0] # if len(ind)!=0: # ind = ind[len(ind)/2] # #if feature is found (flux is higher on both sides of the specified wavelength where the feature should be) # if y[ind]<y[ind+1] and y[ind]<y[ind-1]: # #cut out width[i] around feature[i] # inds = np.where((x >= features[i]+widths[i]) | (x <= features[i]-widths[i])) # x = x[inds] # y = y[inds] #fit a tail to the end of the spectrum to interpolate out to desired wavelength in angstroms fraction = 3.0/4.0 newx = np.arange(int(x[fraction*len(x)]),20000) slopeguess = (np.log(y[-1])-np.log(y[fraction*len(x)]))/(x[-1]-x[fraction*len(x)]) print "Guess at exponential slope is %f"%(slopeguess) guess_a, guess_b, guess_c = float(y[fraction*len(x)]), x[fraction*len(x)], slopeguess guess = [guess_a, guess_b, guess_c] fitx = x[fraction*len(x):] fity = y[fraction*len(x):] exp_decay = lambda fx, A, x0, t: A * np.exp((fx-x0) * t) params, cov = curve_fit(exp_decay, fitx, fity, p0=guess, maxfev=2000) A, x0, t= params print "A = %s\nx0 = %s\nt = %s\n"%(A, x0, t) best_fit = lambda fx: A * np.exp((fx-x0)*t) calcx = np.array(newx,dtype=float) newy = best_fit(calcx) #func = interpolate.splrep(x[fration*len(x):],y[fraction*len(x):],s=smooth) #newx = np.arange(int(x[fraction*len(x)]),self.wvlBinEdges[-1]) #newy = interpolate.splev(newx,func) wl = np.concatenate((x,newx[newx>max(x)])) flux = np.concatenate((y,newy[newx>max(x)])) #new method, rebin data to grid of wavelengths generated from a grid of evenly spaced energy bins #R=7.0 at 4500 #R=E/dE -> dE = R/E dE = 0.3936 #eV start = 1000 #Angs stop = 20000 #Angs enBins = ObsFile.makeWvlBins(dE,start,stop) rebinned = rebin(wl,flux,enBins) re_wl = rebinned[:,0] re_flux = rebinned[:,1] #plt.plot(re_wl,re_flux,color='r') re_wl = re_wl[np.isnan(re_flux)==False] re_flux = re_flux[np.isnan(re_flux)==False] start1 = self.wvlBinEdges[0] stop1 = self.wvlBinEdges[-1] #regrid downsampled data new_wl = np.arange(start1,stop1) #print re_wl #print re_flux #print new_wl #weight=1.0/(re_flux)**(2/1.00) print len(re_flux) weight = np.ones(len(re_flux)) #decrease weights near peak ind = np.where(re_flux == max(re_flux))[0] weight[ind] = 0.3 for p in [1,2,3]: if p==1: wt = 0.3 elif p==2: wt = 0.6 elif p==3: wt = 0.7 try: weight[ind+p] = wt except IndexError: pass try: if ind-p >= 0: weight[ind-p] = wt except IndexError: pass weight[-4:] = 1.0 #weight = [0.7,1,0.3,0.3,0.5,0.7,1,1,1] #print len(weight) #weight = re_flux/min(re_flux) #weight = 1.0/weight #weight = weight/max(weight) #print weight f = interpolate.splrep(re_wl,re_flux,w=weight,k=3,s=max(re_flux)**1.71) new_flux = interpolate.splev(new_wl,f,der=0) return new_wl, new_flux
def cleanSpectrum(x,y,objectName, wvlBinEdges): #locations and widths of absorption features in Angstroms #features = [3890,3970,4099,4340,4860,6564,6883,7619] #widths = [50,50,50,50,50,50,50,50] #for i in xrange(len(features)): # #check for absorption feature in std spectrum # ind = np.where((x<(features[i]+15)) & (x>(features[i]-15)))[0] # if len(ind)!=0: # ind = ind[len(ind)/2] # #if feature is found (flux is higher on both sides of the specified wavelength where the feature should be) # if y[ind]<y[ind+1] and y[ind]<y[ind-1]: # #cut out width[i] around feature[i] # inds = np.where((x >= features[i]+widths[i]) | (x <= features[i]-widths[i])) # x = x[inds] # y = y[inds] #fit a tail to the end of the spectrum to interpolate out to desired wavelength in angstroms fraction = 0 #4.0/5.0 newx = np.arange(int(x[fraction*len(x)]),20000) #slopeguess = (np.log(y[-1])-np.log(y[fraction*len(x)]))/(x[-1]-x[fraction*len(x)]) #print "Guess at exponential slope is %f"%(slopeguess) #guess_a, guess_b, guess_c = float(y[fraction*len(x)]), x[fraction*len(x)], slopeguess #guess = [guess_a, guess_b, guess_c] fitx = x[fraction*len(x)::] fity = y[fraction*len(x)::] #exp_decay = lambda fx, A, x0, t: A * np.exp((fx-x0) * t) #params, cov = curve_fit(exp_decay, fitx, fity, p0=guess, maxfev=2000) #A, x0, t= params #print "A = %s\nx0 = %s\nt = %s\n"%(A, x0, t) #best_fit = lambda fx: A * np.exp((fx-x0)*t) #calcx = np.array(newx,dtype=float) #newy = best_fit(calcx) #normalizing norm = fity.max() fity/=norm guess_a, guess_b = 1/(2*h*c**2/1e-9), 5600 #Constant, Temp guess = [guess_a, guess_b] blackbody = lambda fx, N, T: N * 2*h*c**2 / (fx)**5 * (exp(h*c/(k*T*(fx))) - 1)**-1 # Planck Law #blackbody = lambda fx, N, T: N*2*c*k*T/(fx)**4 #Rayleigh Jeans tail #blackbody = lambda fx, N, T: N*2*h*c**2/(fx**5) * exp(-h*c/(k*T*fx)) #Wein Approx params, cov = curve_fit(blackbody, fitx*1.0e-8, fity, p0=guess, maxfev=2000) N, T= params print "N = %s\nT = %s\n"%(N, T) best_fit = lambda fx: N * 2*h*c**2 / (fx)**5 * (exp(h*c/(k*T*(fx))) - 1)**-1 #Planck Law #best_fit = lambda fx: N*2*c*k*T/(fx)**4 # Rayleigh Jeans Tail #best_fit = lambda fx: N*2*h*c**2/(fx**5) * exp(-h*c/(k*T*fx)) #Wein Approx calcx = np.array(newx,dtype=float) bbfit = best_fit(calcx*1.0E-8) calcx = np.array(newx,dtype=float) newy = best_fit(calcx*1.0E-8) fity*=norm newy*=norm plt.plot(calcx[3.0*len(fitx)/4.0::],newy[3.0*len(fitx)/4.0::]*1E15,linestyle='--',linewidth=2, color="black",alpha=0.5) #plot fit #func = interpolate.splrep(x[fration*len(x):],y[fraction*len(x):],s=smooth) #newx = np.arange(int(x[fraction*len(x)]),self.wvlBinEdges[-1]) #newy = interpolate.splev(newx,func) wl = np.concatenate((x,newx[newx>max(x)])) flux = np.concatenate((y,newy[newx>max(x)])) #new method, rebin data to grid of wavelengths generated from a grid of evenly spaced energy bins #R=7.0 at 4500 #R=E/dE -> dE = E/R dE = 0.3936 #eV start = 1000 #Angs stop = 25000 #Angs enBins = ObsFile.makeWvlBins(dE,start,stop) rebinned = rebin(wl,flux,enBins) re_wl = rebinned[:,0] re_flux = rebinned[:,1] plt.plot(re_wl,re_flux*1E15,linestyle="o", marker="o",markersize=10, color="blue") #plot rebinned spectrum with exp tail re_wl = re_wl[np.isnan(re_flux)==False] re_flux = re_flux[np.isnan(re_flux)==False] start1 = wvlBinEdges[0] stop1 = wvlBinEdges[-1] #regrid downsampled data new_wl = np.arange(start1,stop1) #print re_wl #print re_flux #print new_wl #weight=1.0/(re_flux)**(2/1.00) print len(re_flux) weight = np.ones(len(re_flux)) #decrease weights near peak ind = np.where(re_flux == max(re_flux))[0] weight[ind] = 0.3 for p in [1,2,3]: if p==1: wt = 0.3 elif p==2: wt = 0.6 elif p==3: wt = 0.7 try: weight[ind+p] = wt except IndexError: pass try: if ind-p >= 0: weight[ind-p] = wt except IndexError: pass #change weights to set how tightly fit must match data points #weight[-4:] = 1.0 weight = [0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7,0.7] #print len(weight) #weight = re_flux/min(re_flux) #weight = 1.0/weight #weight = weight/max(weight) print weight f = interpolate.splrep(re_wl,re_flux,w=weight,k=2,s=0)#max(re_flux)**300) new_flux = interpolate.splev(new_wl,f,der=0) return new_wl, new_flux
a = std.load(objectName) stdWvls = np.array(a[:, 0], dtype=float) # wavelengths in angstroms stdFlux = np.array(a[:, 1], dtype=float) # flux in counts/s/cm^2/Angs stdFlux *= h * c * 1e10 / stdWvls # flux in J/s/cm^2/Angs or W/cm^2/Angs # cut spectrum arrays to our wavelength region stdFlux = stdFlux[(stdWvls > 3000) & (stdWvls < 13000)] stdWvls = stdWvls[(stdWvls > 3000) & (stdWvls < 13000)] plt.plot(stdWvls[(stdWvls > 3158) & (stdWvls < 11089)], stdFlux[(stdWvls > 3158) & (stdWvls < 11089)]) total = integrate.simps(stdFlux[(stdWvls > 3158) & (stdWvls < 11089)], x=stdWvls[(stdWvls > 3158) & (stdWvls < 11089)]) print "Original total flux = ", total # rebin test dE = 0.3936 # eV start = 3000 # Angs stop = 13000 # Angs for n in xrange(10): n = float(n) + 1.0 enBins = ObsFile.makeWvlBins(dE / n, start, stop) rebinned = rebin(stdWvls, stdFlux, enBins) re_wl = rebinned[:, 0] re_flux = rebinned[:, 1] print re_wl[0] print re_wl[-1] plt.plot(re_wl[(re_wl > 3158) & (re_wl < 11089)], re_flux[(re_wl > 3158) & (re_wl < 11089)]) total = integrate.simps(re_flux[(re_wl > 3158) & (re_wl < 11089)], x=re_wl[(re_wl > 3158) & (re_wl < 11089)]) print "Total flux for dE = ", dE / n, "eV is ", total, "W/cm^2" plt.show()
y = np.array(fdata[:,1])/scale #convert to flux in Janskys y = y*(3E-5)/(x**2) #flux in ergs/s/cm^2/Angs #y = y/(h*c/x) #flux in counts/s/cm^2/Angs #print y print "Loaded standard spectrum of %s"%(objectName) '''#End manual standard loading block plt.plot(x,y*1E15,linewidth=1,color='grey',alpha=0.75) newwl, newflux = cleanSpectrum(x,y,objectName,wvlBinEdges) print newwl print newflux #plt.plot(newwl,newflux*1E15,color = 'red') #plt.show() newa = rebin(newwl,newflux,wvlBinEdges) x = newa[:,0] y = newa[:,1] plt.step(x,y*1E15,color = 'black',where='mid') #convert ARCONS measured spectrum to ergs/s/cm^2/A curve*=h*(c*1E8)/x #print x #print y #fig = plt.figure() #ax = fig.add_subplot(111) #plt.plot(wvls,curve*1E15) #plot ARCONS measured spectrum