def test_rssmodel(): # load the image and determine its spectrograph parameters 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() # create the RSS Model rss = RSSModel.RSSModel(grating_name=grating, gratang=grang, camang=arang, slit=slit, xbin=int(xbin), ybin=int(ybin)) alpha = rss.alpha() beta = rss.beta() sigma = 1e7 * rss.calc_resolelement(alpha, beta) print("SIGMA: ", sigma) # test to see if giving the wrong name it will raise an error try: rss = RSSModel.RSSModel(grating_name="not a grating", gratang=grang, camang=arang, slit=slit, xbin=int(xbin), ybin=int(ybin)) except RSSModel.RSSError as e: pass
def test_Identify(): hdu = fits.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))
def calcsol(xarr, y_i, instrume, grating, grang, arang, filtername, slit, xbin, ybin, function, order): rss = RSSModel.RSSModel(grating_name=grating.strip(), gratang=grang, camang=arang, slit=slit, xbin=xbin, ybin=ybin) gamma = 180.0 / math.pi * math.atan((y_i * rss.detector.pix_size * rss.detector.ybin - 0.5 * rss.detector.find_height()) / rss.camera.focallength) # y_i/rssmodel.detector.height*rssmodel d = rss.detector.xbin * rss.detector.pix_size * \ (xarr - rss.detector.get_xpixcenter()) alpha = rss.alpha() beta = -rss.beta() dbeta = -np.degrees(np.arctan(d / rss.camera.focallength)) w_arr = 1e7 * rss.calc_wavelength(alpha, beta + dbeta, gamma=gamma) return w_arr
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 test_ModelSolution(): hdu = fits.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)) err = xp * 0.0 + 0.1 ls = MS.ModelSolution(xp, wp, rssmodel.rss, xlen=len(data[0]), order=4) ls.fit(cfit='all') ls.fit(ls.ndcoef) for c in ls.coef: print(c(), end=' ') print() print(ls.sigma(ls.x, ls.y)) print(ls.chisq(ls.x, ls.y, err)) print(ls.value(2000)) pl.figure() pl.plot(xp, wp - ls.value(xp), ls='', marker='o') # pl.plot(ls.x, ls.y-ls(ls.x), ls='', marker='o') pl.show() return
def calc_resolution(hdu): """Calculate the resolution for a setup""" instrume=saltkey.get('INSTRUME', hdu[0]).strip() grating=saltkey.get('GRATING', hdu[0]).strip() grang=saltkey.get('GR-ANGLE', hdu[0]) grasteps=saltkey.get('GRTILT', hdu[0]) arang=saltkey.get('AR-ANGLE', hdu[0]) arsteps=saltkey.get('CAMANG', hdu[0]) rssfilter=saltkey.get('FILTER', hdu[0]) specmode=saltkey.get('OBSMODE', hdu[0]) masktype=saltkey.get('MASKTYP', hdu[0]).strip().upper() slitname=saltkey.get('MASKID', hdu[0]) xbin, ybin = saltkey.ccdbin( hdu[0], '') slit=st.getslitsize(slitname) #create RSS Model rss=RSSModel.RSSModel(grating_name=grating.strip(), gratang=grang, \ camang=arang,slit=slit, xbin=xbin, ybin=ybin, \ ) res=1e7*rss.calc_resolelement(rss.alpha(), -rss.beta()) return res
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 rssinfo(grating, grang, arang, slitname, xbin, ybin): """RSSINFO--Given informtion about the set up of the spectrograph, return information about the spectrograph grating--name of the grating used gratang--angle of the grating in degrees arang--articulation ange in degrees slitname--name of the slit being used xbin--binning in x-direction ybin--binning in y-direction returns central wavelength, blue wavelength, red wavelenth, resolution resolution element """ #get the slitsize slit = getslitsize(slitname) #set up the rss model rss=RSSModel.RSSModel(grating_name=grating, gratang=grang, \ camang=arang,slit=slit, xbin=xbin, ybin=ybin) #calcuation the resolution element res = 1e7 * rss.calc_resolelement(rss.alpha(), -rss.beta()) #calculate the central wavelength wcen = 1e7 * rss.calc_centralwavelength() #calculate the wavelength edges w2 = 1e7 * rss.calc_bluewavelength() w1 = 1e7 * rss.calc_redwavelength() print w1, w2 #calculate the R = rss.calc_resolution(wcen / 1e7, rss.alpha(), rss.beta()) return wcen, w1, w2, res, R, slit
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 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()
print 'CHECK RESULTS' print return ivec[pk], xcorval[pk] filename = 'mbxgpP201206140058.fits' #??data,hdr=pyfits.getdata(filename,extname='sci',header='t') data = pyfits.getdata(filename) hdr = pyfits.getheader(filename) grname = hdr['grating'] camang = hdr['camang'] gratang = hdr['gr-angle'] #create the spectrograph model rss = RSSModel.RSSModel(grating_name=grname, gratang=gratang, camang=camang, slit=1.50, xbin=2, ybin=2) #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, :] xarr = np.arange(len(d_arr)) w = 1e7 * rss.get_wavelength(xarr)
def find_wavelength_solution(filename, line, debug=False): logger = logging.getLogger("FindWLS") if (type(filename) == str and os.path.isfile(filename)): hdulist = fits.open(filename) elif (type(filename) == fits.hdu.hdulist.HDUList): hdulist = filename else: logger.error("Invalid input, needs to be either HDUList or string, but found %s" % (str(type(filename)))) return None if (line is None): line = hdulist['SCI'].data.shape[0] / 2 logger.debug("Picking the central row, # = %d" % (line)) else: logger.info("Using line %d for wavelength calibration" % (line)) avg_width = 10 spec = extract_arc_spectrum(hdulist, line, avg_width) if (debug): numpy.savetxt("findwls.spec", spec) binx, biny = pysalt.get_binning(hdulist) logger.debug("Binning: %d x %d" % (binx, biny)) hdr = hdulist[0].header rss = RSSModel.RSSModel( grating_name=hdr['GRATING'], gratang=hdr['GR-ANGLE'], #45, camang=hdr['CAMANG'], #45, slit=1.0, xbin=binx, ybin=biny, xpos=-0.30659999999999998, ypos=0.0117, wavelength=None) central_wl = rss.calc_centralwavelength() * mm_to_A #print central_wl blue_edge = rss.calc_bluewavelength() * mm_to_A red_edge = rss.calc_redwavelength() * mm_to_A wl_range = red_edge - blue_edge #print "blue:", blue_edge #print "red:", red_edge dispersion = (rss.calc_redwavelength()-rss.calc_bluewavelength())*mm_to_A/spec.shape[0] #print "dispersion: A/px", dispersion #print "ang.dispersion:", rss.calc_angdisp(rss.beta()) #print "ang.dispersion:", rss.calc_angdisp(-rss.beta()) pixelsize = 15e-6 #print "lin.dispersion:", rss.calc_lindisp(rss.beta()) #print "lin.dispersion:", rss.calc_lindisp(rss.beta()) / (mm_to_A*pixelsize) #print "resolution @ central w.l.:", rss.calc_resolution( # w=rss.calc_centralwavelength(), # alpha=rss.alpha(), # beta=-rss.beta()) # print "resolution element:", rss.calc_resolelement(rss.alpha(), -rss.beta()) * mm_to_A logger.info("From RSS model: wl-range: %.1f - %.1f [%.1f], dispersion: %.3f" % ( blue_edge, red_edge, central_wl, dispersion)) # # Now find a list of strong lines # lineinfo = find_list_of_lines(spec, avg_width) if (debug): numpy.savetxt("findwls.foundlines", lineinfo) ############################################################################ # # Now we have a full line-list with signal-to-noise ratios as brightness # indicators that we can use to select bright and/or faint lines. # ############################################################################ # based on the wavelength model from RSS translate x-positions into wavelengths #print dispersion #print lineinfo[:,0] # Use Ken's RSS model data here logger.info("Creating dispersion model") cols = hdulist['SCI'].data.shape[1] kens_model = KenRSSModel(hdulist[0].header, cols) # primhdr = hdulist[0].header # rbin,cbin = numpy.array(primhdr["CCDSUM"].split(" ")).astype(int) # grating = primhdr['GRATING'].strip() # grang = float(primhdr['GR-ANGLE']) # artic = float(primhdr['CAMANG']) # logger.info("RSS model: bin: %d,%d - grating: %s - angle: %.2f - artic: %.2f - columns: %d" % ( # rbin,cbin,grating,grang,artic,cols)) # all_wavelength = rssmodelwave(grating,grang,artic,cbin,cols) # # fit a simple linear interpolation to the curve so we can look up # # wavelengths for a given pixel more easily # wl_interpol = scipy.interpolate.interp1d( # x=numpy.arange(all_wavelength.shape[0]), # y=all_wavelength # ) # Now use the wavelength model to translate line position in pixel coordinates # into wavelength positions wl = kens_model.compute_wl(lineinfo[:,0]) if (debug): numpy.savetxt("rss_lines", numpy.append(wl.reshape((-1,1)), lineinfo, axis=1)) _x = numpy.arange(hdulist['SCI'].data.shape[1]) _wl = kens_model.compute_wl(_x) numpy.savetxt("findwls.wl_vs_x", numpy.array([_x,_wl]).T) # wl = lineinfo[:,0] * dispersion + blue_edge #lineinfo = numpy.append(lineinfo, wl.reshape((-1,1)), axis=1) #numpy.savetxt("linecal", lineinfo) # # Load linelist # lamp=hdulist[0].header['LAMPID'].strip().replace(' ', '') lampfile=pysalt.get_data_filename("pysalt$data/linelists/%s.txt" % lamp) #lampfile=pysalt.get_data_filename("pysalt$data/linelists/%s.salt" % lamp) _, fn_only = os.path.split(lampfile) logger.info("Reading calibration line wavelengths from data->%s" % (fn_only)) logger.debug("Full path to lamp line list: %s" % (lampfile)) #lampfile=pysalt.get_data_filename("pysalt$data/linelists/%s.wav" % lamp) #lampfile=pysalt.get_data_filename("pysalt$data/linelists/Ar.salt") #lampfile="Ar.lines" if (os.path.isfile(lampfile)): try: lines = numpy.loadtxt(lampfile) except: lines = manual_loadtxt(lampfile) else: return None #print lines.shape #print lines # # Now select only lines that are in the estimated range of our ARC spectrum # in_range = (lines[:,0] > numpy.min(wl)) & (lines[:,0] < numpy.max(wl)) ref_lines = lines #[in_range] logger.debug("Found these lines for fitting (range: %.2f -- %.2f):\n%s" % ( numpy.min(wl), numpy.max(wl), "\n".join(["%10.4f" % l for l in ref_lines[:,0]]))) if (debug): numpy.savetxt("findwls.reflines", ref_lines) #print ref_lines ############################################################################ # # Next step for wavelength calibration: # # Match lines between ARC spectrum and reference line list, # allowing for a small uncertainty in dispersion # ############################################################################ camangle = kens_model.artic gratingangle = kens_model.grang max_d_camangle = 1. max_d_gratingangle = 1. step_camangle = 0.05 step_gratingangle = 0.1 n_steps_camangle = int(math.ceil(2*max_d_camangle / step_camangle + 1)) n_steps_gratingangle = int(math.ceil(2*max_d_gratingangle / step_gratingangle + 1)) results = numpy.zeros((n_steps_camangle, n_steps_gratingangle)) try_camangles = numpy.linspace(camangle-max_d_camangle, camangle+max_d_camangle, n_steps_camangle) try_gratingangles = numpy.linspace(gratingangle-max_d_gratingangle, gratingangle+max_d_gratingangle, n_steps_gratingangle) ref_kdtree = scipy.spatial.cKDTree(ref_lines[:,0].reshape((-1,1))) matching_radius=5.0 for idx_camangle, idx_gratingangle in \ itertools.product(range(n_steps_camangle), range(n_steps_gratingangle)): camangle = try_camangles[idx_camangle] gratingangle = try_gratingangles[idx_gratingangle] #print camangle, gratingangle #match_line_catalogs(arc, ref, matching_radius, verbose=False, # col_ref=0, col_arc=-1, dumpfile=None): # compute the wavelength position for all lines using the # spectrograph parameters of this iteration wl_lines = kens_model.compute(grang=gratingangle, artic=camangle, colpos=lineinfo[:,0]) #print wl_lines, ref_lines.shape nearest_neighbor, i = ref_kdtree.query( x=wl_lines.reshape((-1,1)), k=1, # only find 1 nearest neighbor p=1, # use linear distance distance_upper_bound=matching_radius) # i is the index with the closest match # good matches have i within legal range good_match = i < ref_lines.shape[0] results[idx_camangle, idx_gratingangle] = numpy.sum(good_match) numpy.savetxt("results", results) # fig=matplotlib.pyplot.figure() # ax=fig.add_subplot(111) # ax.imshow(results, interpolation='none') # fig.show() # matplotlib.pyplot.show() most_matches = numpy.unravel_index(numpy.argmax(results), results.shape) logger.info("best results: %d matches for camangle=%.3f (%.3f), gratingangle=%.3f (%.3f)" % ( results[most_matches], try_camangles[most_matches[0]], hdulist[0].header['CAMANG'], try_gratingangles[most_matches[1]], hdulist[0].header['GR-ANGLE'], )) best_camangle = try_camangles[most_matches[0]] best_gratingangle = try_gratingangles[most_matches[1]] # # Now write the complete spectrum with the wavelength calibration # #print spec.shape kens_model.compute(artic=best_camangle, grang=best_gratingangle, ncols=spec.shape[0]) spec_wl = kens_model.get_wavelength_list() numpy.savetxt("spec_precalib", numpy.append(spec_wl.reshape((-1,1)), spec.reshape((-1,1)), axis=1)) # # Now cross-identify all lines, and do a least-sq fit to further optimize # the spectrograph angles and compute the final wavelength calibration fit # lineinfo[:,5] = kens_model.compute( artic=best_camangle, grang=best_gratingangle, colpos = lineinfo[:,0], ) numpy.savetxt("linelist.calib", lineinfo) # one last time, match the two line lists, using the same matching radius # as above nearest_neighbor, i = ref_kdtree.query( x=lineinfo[:,5].reshape((-1,1)), k=1, # only find 1 nearest neighbor p=1, # use linear distance distance_upper_bound=matching_radius) good_matches = i < ref_lines.shape[0] # print "\n-------------"*5 # print nearest_neighbor.shape # print nearest_neighbor # print i.shape # print i # print good_matches # print lineinfo.shape # print ref_lines.shape # print numpy.sum(good_matches) n_matches = numpy.sum(good_matches) # matched_ref = ref_lines[:,0][good_matches] # matched_line_idx = i[good_matches] # print "============" matched_catalog = numpy.zeros((n_matches, lineinfo.shape[1]+ref_lines.shape[1])) # print matched_catalog.shape matched_catalog[:,:lineinfo.shape[1]] = lineinfo[good_matches] matched_catalog[:,lineinfo.shape[1]:] = ref_lines[i[good_matches]] numpy.savetxt("matched_lines.dat", matched_catalog) # print "xxxxxxxxxxxxx" def fit__wavelength(p_fit, line_x, rssmodel): computed_wl = rssmodel.compute( grang=p_fit[0], artic=p_fit[1], colpos=line_x) return computed_wl def fit__wavelength_error(p_fit, matched_lines, rssmodel): line_wl = fit__wavelength(p_fit, matched_lines[:,0], rssmodel) ref_wl = matched_lines[:,len(lineinfo_cols)] delta_wl = line_wl - ref_wl # add some weighting here??? return delta_wl p_start = [best_gratingangle, best_camangle] fit_args = (matched_catalog, kens_model) _fit = scipy.optimize.leastsq(fit__wavelength_error, p_start, args=fit_args, maxfev=500, full_output=1) p_final = _fit[0] logger.info("Fit results: Was: %s --> Now: %s" % ( " ".join(["%.4f" % f for f in p_start]), " ".join(["%.4f" % f for f in p_final]), )) # print p_start, " ==> ", p_final lineinfo[:,lineinfo_colidx['WAVELENGTH']] = fit__wavelength( p_final, lineinfo[:, lineinfo_colidx["PIXELPOS"]], kens_model) matched_catalog[:, lineinfo_colidx['WAVELENGTH']] = fit__wavelength( p_final, matched_catalog[:, lineinfo_colidx["PIXELPOS"]], kens_model) numpy.savetxt("matched_lines_afterfit.dat", matched_catalog) # # compute rms # rms = numpy.std(matched_catalog[:, lineinfo_colidx['WAVELENGTH']] - \ matched_catalog[:, len(lineinfo_cols)]) logger.info("Found RMS: %f" % (rms)) wls = compute_wavelength_solution(matched_catalog, max_order=3) logger.info("Best fit wavelength solution: L = %9.3f %+9.3f * x %+9.3e x^2 %+9.3e x^3" % ( wls[0], wls[1], wls[2], wls[3])) # # # set the indices for bad matches to a valid value # # i[~good_matches] = 0 # # matched = numpy.zeros((arc.shape[0], (arc.shape[1]+ref.shape[1]))) # # matched[:,:arc.shape[1]] = arc # # matched[:,arc.shape[1]:] = ref[i] # # #print "XXXXXXXXXXXX\n"*3,ref.shape, ref[i].shape, i.shape, bad_matches.shape # # #print bad_matches # # numpy.savetxt("matched_raw", matched) # # numpy.savetxt("matched_bad", bad_matches) # # #sys.exit(0) # # #print "XXXX\n"*3 # # matched = matched[~bad_matches] # return # i = numpy.array(i) # bad_matches = (i>=ref.shape[0]) # i[bad_matches] = 0 # return # reference_pixel_x = 0.5 * spec.shape[0] # # dispersion was calculated above # # central wavelength # central_wavelength = kens_model.central_wavelength() #numpy.median(all_wavelength) # 0.5 * (blue_edge + red_edge) # max_dispersion_error = 0.00 #10 # +/- 10% should be plenty # dispersion_search_steps = 0.01 # vary dispersion in 1% steps # n_dispersion_steps = (max_dispersion_error / dispersion_search_steps) * 2 + 1 # # # # compute what dispersion factors we are trying # # # trial_dispersions = numpy.linspace(1.0-max_dispersion_error, # 1.0+max_dispersion_error, # n_dispersion_steps) * dispersion # n_matches = numpy.zeros((trial_dispersions.shape[0])) # matched_cats = [None] * trial_dispersions.shape[0] # # # # Now try each dispersion, one by one, and compute what wavelength offset # # we would need to make the maximum number of lines match known lines from # # the line catalog. # # # # # # New: Assume we know line centers to within a pixel, then we can match # # lines that lie within a 1-pixel radius # # # # Remember: units here are angstroem !!! # matching_radius = 2 * dispersion # logger.debug("Considering lines within %.1f A of a known ARC line as matched!" % ( # matching_radius)) # # print "before loop:", lineinfo.shape # for idx, _dispersion in enumerate(trial_dispersions): # # compute dispersion including the correction # #_dispersion = dispersion * disp_factor # # copy the original line info so we don't accidently overwrite important data # _lineinfo = numpy.array(lineinfo) # # find optimal line shifts and match lines # # consider lines within 5A of each other matches # # --> this most likely will depend on spectral resolution and binning # matched_cat = find_matching_lines(ref_lines, _lineinfo, # rss, # _dispersion, central_wavelength, # reference_pixel_x, # matching_radius = matching_radius, # ) # # Save results for later picking of the best one # n_matches[idx] = matched_cat.shape[0] # matched_cats[idx] = matched_cat # numpy.savetxt("dispersion_scale_%.3f" % (_dispersion), matched_cat) # # # # Find the solution with the most matched lines # # # n_max = numpy.argmax(n_matches) # #print # #print "most matched lines:", n_matches[n_max], # #print "best dispersion: %f" % (trial_dispersions[n_max]) # logger.debug("Choosing best solution: %4d for dispersion %8.4f A/px" % ( # n_matches[n_max], trial_dispersions[n_max])) # numpy.savetxt("matchcount", numpy.append(trial_dispersions.reshape((-1,1)), # n_matches.reshape((-1,1)), # axis=1)) # matched = matched_cats[n_max] # numpy.savetxt("matched.lines.best", matched) # # print "***************************\n"*5 # # print lineinfo.shape # logger.info("Computing an analytical wavelength calibration...") # wls = compute_wavelength_solution(matched, max_order=3) # spec_x = numpy.polynomial.polynomial.polyval( # numpy.arange(spec.shape[0]), wls).reshape((-1,1)) # spec_combined = numpy.append(spec_x, spec.reshape((-1,1)), axis=1) # numpy.savetxt("spec.calib.start", spec_combined) # # # # Now we have a best-match solution # # Match lines again to see what the RMS is - use a small matching radius now # # # ############################################################################ # # # # Since the original matching was done using a simple polynomial form, # # let's now iterate the rough solution using higher order polynomials to # # (hopefully) match a larger number of lines # # # # Add here: # # - Keep an eye on r.m.s. of the fit, and the number of matched lines # # - with every step, reduce the matching radius to make sure we are matching # # only with the most likely counterpart in case of close line (blends) # # # ############################################################################ # #prev_wls = wls # matching_radius = 2*dispersion # logger.debug("Refining WLS using all %d lines" % (lineinfo.shape[0])) # for iteration in range(3): # #sys.stdout.write("\n\n\n"); sys.stdout.flush() # _linelist = numpy.array(lineinfo) # # Now compute the new wavelength for each line # _linelist[:,lineinfo_colidx['WAVELENGTH']] = numpy.polynomial.polynomial.polyval( # _linelist[:,lineinfo_colidx['PIXELPOS']], wls) # numpy.savetxt("lineinfo.iteration=%d" % (iteration+1), _linelist, "%10.4f") # # compute wl with polyval # # _wl = lineinfo[:,0] # # numpy.savetxt("final.1", _wl) # # numpy.savetxt("final.2", numpy.polynomial.polynomial.polyval(_wl, wls)) # # numpy.savetxt("final.3", _wl*wls[1]+wls[0]) # # With the refined wavelength solution, match lines between the # # ARC spectrum and the reference line catalog # new_matches = match_line_catalogs(_linelist, ref_lines, # matching_radius=1.7, #matching_radius, # wsa 50 XXX # verbose=False, # col_arc=lineinfo_colidx['WAVELENGTH'], # col_ref=0, # dumpfile="finalmatch.%d" % (iteration+1)) # logger.debug("WLS Refinement step %3d: now %3d matches!" % ( # iteration+1, new_matches.shape[0])) # # -- for debugging -- # numpy.savetxt("matched.cat.iter%d" % (iteration+1), new_matches) # # # # Before fitting, iteratively reject obvious outliers most likely caused # # by matching wrong lines # # # likely_outlier = numpy.isnan(new_matches[:,lineinfo_colidx['WAVELENGTH']]) # for reject in range(3): # diff_angstroem = new_matches[:,lineinfo_colidx['WAVELENGTH']] - \ # new_matches[:,len(lineinfo_colidx)] # med = numpy.median(diff_angstroem[~likely_outlier]) # stdx = numpy.std(diff_angstroem[~likely_outlier]) # sigma = scipy.stats.scoreatpercentile(diff_angstroem[~likely_outlier], [16,84]) # std = 0.5*(sigma[1]-sigma[0]) # likely_outlier = (diff_angstroem > med+2*std) | (diff_angstroem < med-2*std) # logger.debug("Med/Std/StdX= %f / %f / %f" % (med, std, stdx)) # # Now we have a better idea on outliers, so reject them and work with # # what's left # new_matches = new_matches[~likely_outlier] # logger.debug("WLS Refinement step %3d: %3d matches left after outliers!" % ( # iteration+1, new_matches.shape[0])) # # And with the matched line list, compute a new wavelength solution # wls = compute_wavelength_solution(new_matches, max_order=4)#+iteration) # # -- for debugging -- # numpy.savetxt("matched.outlierreject.iter%d" % (iteration+1), new_matches) # # # spec_x = numpy.polynomial.polynomial.polyval( # numpy.arange(spec.shape[0])+1., wls).reshape((-1,1)) # spec_combined = numpy.append(spec_x, spec.reshape((-1,1)), axis=1) # numpy.savetxt("spec.calib.iteration_%d" % (iteration+1), spec_combined) # #prev_wls = wls # #return # final_match = matched # numpy.savetxt("matched.cat.final", final_match) # Also save the original spectrum as text file spec_x = numpy.polynomial.polynomial.polyval(numpy.arange(spec.shape[0]), wls).reshape((-1,1)) spec_combined = numpy.append(spec_x, spec.reshape((-1,1)), axis=1) numpy.savetxt("spec.calib", spec_combined) # print lines # print _linelist # print spec.shape # print spec_combined.shape # print line # print wls return { 'spec': spec, 'spec_combined': spec_combined, 'linelist_ref': lines, # 'linelist_arc': _linelist, 'linelist_arc': lineinfo, 'line': line, 'wl_fit_coeffs': wls, }
def test_ModelSolution(): 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)) xarr = np.arange(len(data[0]), dtype='int64') rss = rssmodel.rss alpha = rss.gratang beta = rss.gratang - rss.camang d = rss.detector.xbin * rss.detector.pix_size * (xarr - 0.5 * len(xarr)) dbeta = np.degrees(np.arctan(d / rss.camera.focallength)) y = 1e7 * rss.calc_wavelength(alpha, beta - dbeta) #ws=WS.WavelengthSolution(xp, wp, function='model', sgraph=rssmodel.rss, xlen=len(data[0]), order=4, cfit='all') ws = WS.WavelengthSolution(xarr, y, function='model', sgraph=rssmodel.rss, xlen=len(data[0]), order=4, cfit='ndcoef') #ws=WS.WavelengthSolution(xarr, y, function='poly', order=3) #ws=WS.WavelengthSolution(xp, wp, function='poly', order=3) ws.fit() print ws.coef print ws.func.result for c in ws.func.spcoef: print c() for c in ws.func.ndcoef: print c() print ws.value(2000) print ws.sigma(xp, wp) print ws.chisq(xp, wp, ep) pl.figure() # pl.plot(xarr,y) #pl.plot(xarr, ws.value(xarr)) #pl.plot(xp, wp-ws.value(xp), ls='', marker='o') pl.plot(xarr, y - ws.value(xarr)) #pl.plot(ls.x, ls.y-ls(ls.x), ls='', marker='o') pl.show()
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 specidentify(images, linelist, outfile, guesstype='rss', guessfile='', automethod='Matchlines', function='poly', order=3, rstep=100, rstart='middlerow', mdiff=5, thresh=3, niter=5, smooth=0, subback=0, inter=True, startext=0, clobber=False, textcolor='black', preprocess=False, logfile='salt.log', verbose=True): with logging(logfile, debug) as log: # set up the variables infiles = [] outfiles = [] # Check the input images infiles = saltio.argunpack('Input', images) # create list of output files outfiles = saltio.argunpack('Output', outfile) # open the line lists slines, sfluxes = st.readlinelist(linelist) # Identify the lines in each file for img, ofile in zip(infiles, outfiles): # open the image hdu = saltio.openfits(img) # get the basic information about the spectrograph dateobs = saltkey.get('DATE-OBS', hdu[0]) try: utctime = saltkey.get('UTC-OBS', hdu[0]) except SaltError: utctime = saltkey.get('TIME-OBS', hdu[0]) instrume = saltkey.get('INSTRUME', hdu[0]).strip() grating = saltkey.get('GRATING', hdu[0]).strip() grang = saltkey.get('GR-ANGLE', hdu[0]) grasteps = saltkey.get('GRTILT', hdu[0]) arang = saltkey.get('AR-ANGLE', hdu[0]) arsteps = saltkey.get('CAMANG', hdu[0]) rssfilter = saltkey.get('FILTER', hdu[0]) specmode = saltkey.get('OBSMODE', hdu[0]) masktype = saltkey.get('MASKTYP', hdu[0]).strip().upper() slitname = saltkey.get('MASKID', hdu[0]) xbin, ybin = saltkey.ccdbin(hdu[0], img) for i in range(startext, len(hdu)): if hdu[i].name == 'SCI': log.message('Proccessing extension %i in %s' % (i, img)) # things that will change for each slit if masktype == 'LONGSLIT': slit = st.getslitsize(slitname) xpos = -0.2666 ypos = 0.0117 objid = None elif masktype == 'MOS': slit = 1. #slit=saltkey.get('SLIT', hdu[i]) # set up the x and y positions miny = hdu[i].header['MINY'] maxy = hdu[i].header['MAXY'] ras = hdu[i].header['SLIT_RA'] des = hdu[i].header['SLIT_DEC'] objid = hdu[i].header['SLITNAME'] # TODO: Check the perfomance of masks at different PA rac = hdu[0].header['MASK_RA'] dec = hdu[0].header['MASK_DEC'] pac = hdu[0].header['PA'] # these are hard wired at the moment xpixscale = 0.1267 * xbin ypixscale = 0.1267 * ybin cx = int(3162 / xbin) cy = int(2050 / ybin) x, y = mt.convert_fromsky(ras, des, rac, dec, xpixscale=xpixscale, ypixscale=ypixscale, position_angle=-pac, ccd_cx=cx, ccd_cy=cy) xpos = 0.015 * 2 * (cx - x[0]) ypos = 0.0117 else: msg = '%s is not a currently supported masktype' % masktype raise SALTSpecError(msg) if instrume not in ['PFIS', 'RSS']: msg = '%s is not a currently supported instrument' % instrume raise SALTSpecError(msg) # create RSS Model rss = RSSModel.RSSModel(grating_name=grating.strip(), gratang=grang, camang=arang, slit=slit, xbin=xbin, ybin=ybin, xpos=xpos, ypos=ypos) res = 1e7 * rss.calc_resolelement(rss.alpha(), -rss.beta()) dres = res / 10.0 wcen = 1e7 * rss.calc_centralwavelength() R = rss.calc_resolution(wcen / 1e7, rss.alpha(), -rss.beta()) logmsg = '\nGrating\tGR-ANGLE\tAR-ANGLE\tSlit\tWCEN\tR\n' logmsg += '%s\t%8.3f\t%8.3f\t%4.2f\t%6.2f\t%4f\n' % ( grating, grang, arang, slit, wcen, R) if log: log.message(logmsg, with_header=False) # set up the data for the source try: data = hdu[i].data except Exception, e: message = 'Unable to read in data array in %s because %s' % ( img, e) raise SALTSpecError(message) # set up the center row if rstart == 'middlerow': ystart = int(0.5 * len(data)) else: ystart = int(rstart) rss.gamma = 0.0 if masktype == 'MOS': rss.gamma = 180.0 / math.pi * math.atan( (y * rss.detector.pix_size * rss.detector.ybin - 0.5 * rss.detector.find_height()) / rss.camera.focallength) # set up the xarr array based on the image xarr = np.arange(len(data[ystart]), dtype='int64') # get the guess for the wavelength solution if guesstype == 'rss': # set up the rss model ws = st.useRSSModel(xarr, rss, function=function, order=order, gamma=rss.gamma) if function in ['legendre', 'chebyshev']: ws.func.func.domain = [xarr.min(), xarr.max()] elif guesstype == 'file': soldict = {} soldict = readsolascii(guessfile, soldict) timeobs = enterdatetime('%s %s' % (dateobs, utctime)) exptime = saltkey.get('EXPTIME', hdu[0]) filtername = saltkey.get('FILTER', hdu[0]).strip() try: slitid = saltkey.get('SLITNAME', hdu[i]) except: slitid = None function, order, coef, domain = findlinesol(soldict, ystart, True, timeobs, exptime, instrume, grating, grang, arang, filtername, slitid, xarr=xarr) ws = WavelengthSolution.WavelengthSolution( xarr, xarr, function=function, order=order) ws.func.func.domain = domain ws.set_coef(coef) else: raise SALTSpecError( 'This guesstype is not currently supported') # identify the spectral lines ImageSolution = identify(data, slines, sfluxes, xarr, ystart, ws=ws, function=function, order=order, rstep=rstep, mdiff=mdiff, thresh=thresh, niter=niter, method=automethod, res=res, dres=dres, smooth=smooth, inter=inter, filename=img, subback=0, textcolor=textcolor, preprocess=preprocess, log=log, verbose=verbose) if outfile and len(ImageSolution): writeIS(ImageSolution, outfile, dateobs=dateobs, utctime=utctime, instrume=instrume, grating=grating, grang=grang, grasteps=grasteps, arsteps=arsteps, arang=arang, rfilter=rssfilter, slit=slit, xbin=xbin, ybin=ybin, objid=objid, filename=img, log=log, verbose=verbose)
import pylab as pl import numpy as np import PySpectrograph from PySpectrograph.Models import RSSModel from PySpectrograph.Spectra import Spectrum # create the spectrograph model rss = RSSModel.RSSModel(grating_name="PG0900", gratang=15.875, camang=31.76496, slit=1.50, xbin=2, ybin=2) # 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, :] w = 1e7 * rss.get_wavelength(xarr) # set up the artificial spectrum sw, sf = pl.loadtxt('Ne.txt', usecols=(0, 1), unpack=True) wrange = [1e7 * rss.calc_bluewavelength(), 1e7 * rss.calc_redwavelength()] spec = Spectrum.Spectrum(sw,