def audit(filename): header, data = IO.readfits(filename) ll0 = header['crval1'] dlam = header['cd1_1'] ls = ll0 + dlam * np.arange(data.shape[1]) linelist = Wavelength.pick_linelist(header) deltas = [] sigs = [] xpos = [] ys = [] for y in np.linspace(750, 1100, 30): #for y in np.linspace(5, 640, 50): sp = np.ma.array(data[y,:]) xs, sxs, sigmas = Wavelength.find_known_lines(linelist, ls, sp, Options.wavelength) xpos.append(xs) ys.append([y] * len(xs)) deltas.append(xs - (linelist - ll0)/dlam) sigs.append(sxs) xpos, ys, deltas, sigs = map(np.array, [xpos, ys, deltas, sigs]) deltas[np.abs(deltas) > .75] = np.nan sigs[np.abs(sigs) > .001] = np.nan pl.clf() size = 0.003/sigs size[size > 30] = 30 size[size < 1] = 1 pl.scatter( xpos, ys, c=deltas, s=size) pl.xlim([0, data.shape[1]]) pl.ylim([0, data.shape[0]]) pl.xlabel("Spectral pixel") pl.ylabel("Spatial pixel") pl.title("Night sky line deviation from solution [pixel]") pl.colorbar() pl.savefig("audit.pdf") pdb.set_trace()
def audit(filename): header, data = IO.readfits(filename) ll0 = header['crval1'] dlam = header['cd1_1'] ls = ll0 + dlam * np.arange(data.shape[1]) linelist = Wavelength.pick_linelist(header) deltas = [] sigs = [] xpos = [] ys = [] for y in np.linspace(750, 1100, 30): #for y in np.linspace(5, 640, 50): sp = np.ma.array(data[y, :]) xs, sxs, sigmas = Wavelength.find_known_lines(linelist, ls, sp, Options.wavelength) xpos.append(xs) ys.append([y] * len(xs)) deltas.append(xs - (linelist - ll0) / dlam) sigs.append(sxs) xpos, ys, deltas, sigs = map(np.array, [xpos, ys, deltas, sigs]) deltas[np.abs(deltas) > .75] = np.nan sigs[np.abs(sigs) > .001] = np.nan pl.clf() size = 0.003 / sigs size[size > 30] = 30 size[size < 1] = 1 pl.scatter(xpos, ys, c=deltas, s=size) pl.xlim([0, data.shape[1]]) pl.ylim([0, data.shape[0]]) pl.xlabel("Spectral pixel") pl.ylabel("Spatial pixel") pl.title("Night sky line deviation from solution [pixel]") pl.colorbar() pl.savefig("audit.pdf") pdb.set_trace()
def stack_rectified(wavenames, maskname, band, wavops): N = len(wavenames) lamnames = [] suffixs = [] for i in xrange(N): lamnames.append(Wavelength.filelist_to_wavename(wavenames[i], band, maskname, wavops).rstrip(".fits")) suffixs.append(lamnames[i].lstrip("wave_stack_%s_" % band)) path = os.path.join(wavops["outdir"], maskname) recs = [] ivars = [] sns = [] try: ls = [get_path(os.path.join(path, "eps_%s_%s_%s.fits") % (maskname, suffix, band)) for suffix in suffixs] imcombine(ls, maskname, "eps_%s_%s.fits" % (maskname, band), wavops, "rate") except: pass try: ls = [get_path(os.path.join(path, "ivars_%s_%s_%s.fits") % (maskname, suffix, band)) for suffix in suffixs] imcombine(ls, maskname, "ivars_%s_%s.fits" % (maskname, band), wavops, "ivar-rate") except: pass try: ls = [get_path(os.path.join(path, "snrs_%s_%s_%s.fits") % (maskname, suffix, band)) for suffix in suffixs] imcombine(ls, maskname, "snrs_%s_%s.fits" % (maskname, band), wavops, "snr-rate") except: pass
def rectify(dname, lamdat, A, B, maskname, band, wavoptions, longoptions): header, data = IO.readfits(dname) raw_img = data * Detector.gain / header['TRUITIME'] dlam = Wavelength.grating_results(band) hpp = np.array(Filters.hpp[band]) ll_fid = np.arange(hpp[0], hpp[1], dlam) rectified = np.zeros((2048, len(ll_fid))) from scipy.interpolate import interp1d for i in xrange(2048): ll = lamdat[i, :] ss = raw_img[i, :] ok = np.isfinite(ll) & np.isfinite(ss) & (ll < hpp[1]) & (ll > hpp[0]) if len(np.where(ok)[0]) < 30: continue f = interp1d(ll[ok], ss[ok], bounds_error=False) rectified[i, :] = f(ll_fid) header.update("wat0_001", "system=world") header.update("wat1_001", "wtype=linear") header.update("wat2_001", "wtype=linear") header.update("dispaxis", 1) header.update("dclog1", "Transform") header.update("dc-flag", 0) header.update("ctype1", "AWAV") header.update("cunit1", "Angstrom") header.update("crval1", ll_fid[0]) header.update("crval2", 0) header.update("crpix1", 1) header.update("crpix2", 1) header.update("cdelt1", 1) header.update("cdelt2", 1) header.update("cname1", "angstrom") header.update("cname2", "pixel") header.update("cd1_1", dlam) header.update("cd1_2", 0) header.update("cd2_1", 0) header.update("cd2_2", 1) header.update("object", "rectified [eps]") IO.writefits(rectified, maskname, "rectified_%s" % (dname), wavoptions, header=header, overwrite=True, lossy_compress=True)
def rectify(dname, lamdat, A, B, maskname, band, wavoptions, longoptions): header, data = IO.readfits(dname) raw_img = data * Detector.gain / header['TRUITIME'] dlam = Wavelength.grating_results(band) hpp = np.array(Filters.hpp[band]) ll_fid = np.arange(hpp[0], hpp[1], dlam) rectified = np.zeros((2048, len(ll_fid))) from scipy.interpolate import interp1d for i in xrange(2048): ll = lamdat[i,:] ss = raw_img[i,:] ok = np.isfinite(ll) & np.isfinite(ss) & (ll < hpp[1]) & (ll > hpp[0]) if len(np.where(ok)[0]) < 30: continue f = interp1d(ll[ok], ss[ok], bounds_error=False) rectified[i,:] = f(ll_fid) header.update("wat0_001", "system=world") header.update("wat1_001", "wtype=linear") header.update("wat2_001", "wtype=linear") header.update("dispaxis", 1) header.update("dclog1", "Transform") header.update("dc-flag", 0) header.update("ctype1", "AWAV") header.update("cunit1", "Angstrom") header.update("crval1", ll_fid[0]) header.update("crval2", 0) header.update("crpix1", 1) header.update("crpix2", 1) header.update("cdelt1", 1) header.update("cdelt2", 1) header.update("cname1", "angstrom") header.update("cname2", "pixel") header.update("cd1_1", dlam) header.update("cd1_2", 0) header.update("cd2_1", 0) header.update("cd2_2", 1) header.update("object", "rectified [eps]") IO.writefits(rectified, maskname, "rectified_%s" % (dname), wavoptions, header=header, overwrite=True, lossy_compress=True)
def rename_files(wavenames, maskname, band, wavops): lamname = Wavelength.filelist_to_wavename(wavenames[0], band, maskname, wavops).rstrip(".fits") suffix = lamname.lstrip("wave_stack_%s_" % band) path = os.path.join(wavops["outdir"], maskname) fnames = ["rectified_%s%s.fits", "rectified_ivar_%s%s.fits", "rectified_sn_%s%s.fits"] for fname in fnames: try: a = get_path(os.path.join(path, fname % (band, "_" + suffix))) b = os.path.join(path, fname % (band, "")) + gz(a) os.rename(a, b) except: print "Ignoring renaming of: ", fname pass edges = IO.load_edges(maskname, band, wavops) n_slits = len(edges[0]) for i in xrange(1, n_slits + 1): S = "S%2.2i" % (i) a = get_path(os.path.join(path, "eps_%s_%s_%s.fits" % (band, suffix, S))) a_h = pf.open(a)[0].header obj = a_h["object"] b = os.path.join(path, "%s_%s_%s_eps.fits" % (maskname, band, obj)) + gz(a) os.rename(a, b) a = get_path(os.path.join(path, "ivar_%s_%s_%s.fits" % (band, suffix, S))) a_h = pf.open(a)[0].header obj = a_h["object"] b = os.path.join(path, "%s_%s_%s_ivar.fits" % (maskname, band, obj)) + gz(a) os.rename(a, b) a = get_path(os.path.join(path, "eps_%s_%s_%s.fits" % (maskname, suffix, band))) b = os.path.join(path, "%s_%s_eps.fits" % (maskname, band)) + gz(a) os.rename(a, b) a = get_path(os.path.join(path, "snrs_%s_%s_%s.fits" % (maskname, suffix, band))) b = os.path.join(path, "%s_%s_snrs.fits" % (maskname, band)) + gz(a) os.rename(a, b) a = get_path(os.path.join(path, "ivars_%s_%s_%s.fits" % (maskname, suffix, band))) b = os.path.join(path, "%s_%s_ivars.fits" % (maskname, band)) + gz(a) os.rename(a, b)
def stack_rectified(wavenames, maskname, band, wavops): N = len(wavenames) lamnames = [] suffixs = [] for i in xrange(N): lamnames.append( Wavelength.filelist_to_wavename(wavenames[i], band, maskname, wavops).rstrip(".fits")) suffixs.append(lamnames[i].lstrip("wave_stack_%s_" % band)) path = os.path.join(wavops["outdir"], maskname) recs = [] ivars = [] sns = [] try: ls = [ get_path( os.path.join(path, "eps_%s_%s_%s.fits") % (maskname, suffix, band)) for suffix in suffixs ] imcombine(ls, maskname, "eps_%s_%s.fits" % (maskname, band), wavops, 'rate') except: pass try: ls = [ get_path( os.path.join(path, "ivars_%s_%s_%s.fits") % (maskname, suffix, band)) for suffix in suffixs ] imcombine(ls, maskname, "ivars_%s_%s.fits" % (maskname, band), wavops, 'ivar-rate') except: pass try: ls = [ get_path( os.path.join(path, "snrs_%s_%s_%s.fits") % (maskname, suffix, band)) for suffix in suffixs ] imcombine(ls, maskname, "snrs_%s_%s.fits" % (maskname, band), wavops, 'snr-rate') except: pass
def printWavelengthFit(self): if self.type is 'longslit' or self.type is 'long2pos': addLongSlit = ",longslit=longslit" else: addLongSlit = "" if self.type is 'slitmask' or self.type is 'longslit': self.useNeon = False self.useArgon = False # determine is Argon and Neon files contain data for K bands if self.isEmpty('Ar.txt') is False and self.band is 'K': self.useArgon = True if self.isEmpty('Ne.txt') is False and self.band is 'K': self.useNeon = True self.addLine("Wavelength.imcombine(obsfiles, maskname, band, waveops)") if self.useArgon: self.addLine("Wavelength.imcombine('Ar.txt', maskname, band, waveops)") if self.useNeon: self.addLine("Wavelength.imcombine('Ne.txt', maskname, band, waveops)") self.addLine("Wavelength.fit_lambda_interactively(maskname, band, obsfiles,waveops"+addLongSlit+", bypass=bypassflag)") if self.useArgon: self.addLine("Wavelength.apply_interactive(maskname, band, waveops, apply=obsfiles, to='Ar.txt', argon=True)") if self.useNeon: self.addLine("Wavelength.apply_interactive(maskname, band, waveops, apply=obsfiles, to='Ne.txt', neon=True)") self.addLine("Wavelength.fit_lambda(maskname, band, obsfiles, obsfiles,waveops"+addLongSlit+")") if self.useArgon and self.useNeon: self.addLine("Wavelength.fit_lambda(maskname, band, 'Ne.txt', 'Ne.txt',waveops, wavenames2='Ar.txt'"+addLongSlit+")") if self.useArgon and not self.useNeon: self.addLine("Wavelength.fit_lambda(maskname, band, 'Ar.txt', 'Ar.txt',waveops"+addLongSlit+")") if self.useNeon and not self.useArgon: self.addLine("Wavelength.fit_lambda(maskname, band, 'Ne.txt', 'Ne.txt',waveops"+addLongSlit+")") if self.useNeon or self.useArgon: self.addLine("LROI = [[21000,22800]]*1") if self.useNeon: self.addLine("LROIs = Wavelength.check_wavelength_roi(maskname, band, obsfiles, 'Ne.txt', LROI, waveops)") if self.useArgon and not self.useNeon: self.addLine("LROIs = Wavelength.check_wavelength_roi(maskname, band, obsfiles, 'Ar.txt', LROI, waveops)") self.addLine("Wavelength.apply_lambda_simple(maskname, band, obsfiles, waveops"+addLongSlit+")") if self.useArgon and self.useNeon: self.addLine("Wavelength.apply_lambda_sky_and_arc(maskname, band, obsfiles, 'Ne.txt', LROIs, waveops)") if self.useArgon and not self.useNeon: self.addLine("Wavelength.apply_lambda_sky_and_arc(maskname, band, obsfiles, 'Ar.txt', LROIs, waveops)") if self.useNeon and not self.useArgon: self.addLine("Wavelength.apply_lambda_sky_and_arc(maskname, band, obsfiles, 'Ne.txt', LROIs, waveops)") # determine waveleng name files = IO.list_file_to_strings(self.offsetFiles) if self.useNeon: neon_files = IO.list_file_to_strings('Ne.txt') self.waveName = "merged_lambda_solution_"+str(Wavelength.filelist_to_wavename(files, self.band, self.maskName,"")).rstrip(".fits")+"_and_"+str(Wavelength.filelist_to_wavename(neon_files, self.band, self.maskName,"")) elif self.useArgon and not self.useNeon: argon_files = IO.list_file_to_strings('Ar.txt') self.waveName = "merged_lambda_solution_"+str(Wavelength.filelist_to_wavename(files, self.band, self.maskName,"")).rstrip(".fits")+"_and_"+str(Wavelength.filelist_to_wavename(argon_files, self.band, self.maskName,"")) else: self.waveName = "lambda_solution_"+str(Wavelength.filelist_to_wavename(files, self.band, self.maskName,"")) if self.type is 'long2pos' or self.type is 'long2pos_specphot': calibWith = "" if self.isEmpty('Ar.txt') is False: self.addLine("argon = ['Ar.txt']") calibWith = "argon" waveFiles = IO.list_file_to_strings('Ar.txt') if self.isEmpty('Ne.txt') is False: self.addLine("neon = ['Ne.txt']") calibWith = "neon" waveFiles = IO.list_file_to_strings('Ne.txt') if calibWith: # we have either Argon, or Neon, or both, so we can use arcs for the reduction self.addLine("Wavelength.imcombine("+str(calibWith)+", maskname, band, waveops)") self.addLine("Wavelength.fit_lambda_interactively(maskname, band, "+str(calibWith)+",waveops,longslit=longslit, "+str(calibWith)+"=True, bypass=bypassflag)") self.addLine("Wavelength.fit_lambda(maskname, band, "+str(calibWith)+","+str(calibWith)+",waveops,longslit=longslit)") self.addLine("Wavelength.apply_lambda_simple(maskname, band, "+str(calibWith)+", waveops, longslit=longslit, smooth=True)") self.waveName = "lambda_solution_"+str(Wavelength.filelist_to_wavename(waveFiles, self.band, self.maskName,"")) else: # we have no arcs. For the time being, we can try with sky lines but this only works with long2pos specphot print "#####################################################################################################" print "WARNING: There are no arc calibration files" print " The pipeline will try to use sky lines but this only works if the observation is long enough" print " and if you are only using long2pos. It will NOT work on long2pos_specphot" print " Please contact the MosfireDRP team to obtain a standard wavelength solution" print "#####################################################################################################" self.addLine("obsfiles = obsfiles_posAnarrow + obsfiles_posCnarrow") self.addLine("Wavelength.imcombine(obsfiles, maskname, band, waveops)") self.addLine("Wavelength.fit_lambda_interactively(maskname, band, obsfiles ,waveops,longslit=longslit, bypass=bypassflag)") self.addLine("Wavelength.fit_lambda(maskname, band, obsfiles,obsfiles ,waveops,longslit=longslit)") self.addLine("Wavelength.apply_lambda_simple(maskname, band, obsfiles, waveops, longslit=longslit, smooth=True)") files = IO.list_file_to_strings(self.offsetFiles) self.waveName = "lambda_solution_"+str(Wavelength.filelist_to_wavename(files, self.band, self.maskName,"")) self.addLine("") self.addLine("Wavelength_file = '"+str(self.waveName)+"'") self.addLine("Wavelength.bary_corr(obsfiles, Wavelength_file, maskname, band, waveops)") self.addLine("")
def find_longslit_edges(data, header, bs, options, edgeThreshold=450, longslit=None): y = 2034 DY = 44.25 toc = 0 ssl = bs.ssl slits = [] top = [0., np.float(Options.npix)] start_slit_num = int(bs.msl[0]['Slit_Number']) - 1 if start_slit_num > 0: y -= DY * start_slit_num # if the mask is a long slit, the default y value will be wrong. Set instead to be the middle if bs.long_slit: try: y = longslit["yrange"][1] except: error( "Longslit reduction mode is specified, but the row position has not been specified. Defaulting to " + str(y)) print "Longslit reduction mode is specified, but the row position has not been specified. Defaulting to " + str( y) # Count and check that the # of objects in the SSL matches that of the MSL # This is purely a safety check numslits = np.zeros(len(ssl)) for i in xrange(len(ssl)): slit = ssl[i] M = np.where(slit["Target_Name"] == bs.msl["Target_in_Slit"]) numslits[i] = len(M[0]) numslits = np.array(numslits) info("Number of slits allocated for this longslit: " + str(np.sum(numslits))) # now begin steps outline above results = [] result = {} result["Target_Name"] = ssl[0]["Target_Name"] # 1 Defines a polynomial of degree 0, which is a constant, with the value of the top of the slit result["top"] = np.poly1d([longslit["yrange"][1]]) topfun = np.poly1d([longslit["yrange"][1] ]) # this is a constant funtion with c=top of the slit botfun = np.poly1d([ longslit["yrange"][0] ]) # this is a constant funtion with c=bottom of the slit # xposs_top_this = [10 110 210 .... 1810 1910] xposs_top = np.arange(10, 2000, 100) xposs_bot = np.arange(10, 2000, 100) # yposs_top_this = [1104 1104 ... 1104 1104], it's the constant polynomium calculated at the X positions yposs_top = topfun(xposs_top) yposs_bot = botfun(xposs_bot) ''' Deal with the current slit ''' target = 0 hpps = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(target + 1)[0], header, bs) ok = np.where((xposs_top > hpps[0]) & (xposs_top < hpps[1])) xposs_bot = xposs_bot[ok] yposs_bot = yposs_bot[ok] xposs_top = xposs_top[ok] yposs_top = yposs_top[ok] if len(xposs_bot) == 0: error("The slit edges specifications appear to be incorrect.") raise Exception( "The slit edges specifications appear to be incorrect.") # bot is the polynomium that defines the shape of the bottom of the slit. In this case, we set it to a constant. bot = botfun.c.copy() top = topfun.c.copy() #4 result = {} result["Target_Name"] = ssl[target]["Target_Name"] result["xposs_top"] = xposs_top result["yposs_top"] = yposs_top result["xposs_bot"] = xposs_bot result["yposs_bot"] = yposs_bot result["top"] = np.poly1d(top) result["bottom"] = np.poly1d(bot) result["hpps"] = hpps result["ok"] = ok results.append(result) results.append({"version": options["version"]}) return results
def find_longslit_edges(data, header, bs, options, edgeThreshold=450,longslit=None): y = 2034 DY = 44.25 toc = 0 ssl = bs.ssl slits = [] top = [0., np.float(Options.npix)] start_slit_num = int(bs.msl[0]['Slit_Number'])-1 if start_slit_num > 0: y -= DY * start_slit_num # if the mask is a long slit, the default y value will be wrong. Set instead to be the middle if bs.long_slit: try: y=longslit["yrange"][1] except: error("Longslit reduction mode is specified, but the row position has not been specified. Defaulting to "+str(y)) print "Longslit reduction mode is specified, but the row position has not been specified. Defaulting to "+str(y) # Count and check that the # of objects in the SSL matches that of the MSL # This is purely a safety check numslits = np.zeros(len(ssl)) for i in xrange(len(ssl)): slit = ssl[i] M = np.where(slit["Target_Name"] == bs.msl["Target_in_Slit"]) numslits[i] = len(M[0]) numslits = np.array(numslits) info("Number of slits allocated for this longslit: "+str(np.sum(numslits))) # now begin steps outline above results = [] result = {} result["Target_Name"] = ssl[0]["Target_Name"] # 1 Defines a polynomial of degree 0, which is a constant, with the value of the top of the slit result["top"] = np.poly1d([longslit["yrange"][1]]) topfun = np.poly1d([longslit["yrange"][1]]) # this is a constant funtion with c=top of the slit botfun = np.poly1d([longslit["yrange"][0]]) # this is a constant funtion with c=bottom of the slit # xposs_top_this = [10 110 210 .... 1810 1910] xposs_top = np.arange(10,2000,100) xposs_bot = np.arange(10,2000,100) # yposs_top_this = [1104 1104 ... 1104 1104], it's the constant polynomium calculated at the X positions yposs_top = topfun(xposs_top) yposs_bot = botfun(xposs_bot) ''' Deal with the current slit ''' target=0 hpps = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(target+1)[0], header, bs) ok = np.where((xposs_top > hpps[0]) & (xposs_top < hpps[1])) xposs_bot = xposs_bot[ok] yposs_bot = yposs_bot[ok] xposs_top = xposs_top[ok] yposs_top = yposs_top[ok] if len(xposs_bot) == 0: error ("The slit edges specifications appear to be incorrect.") raise Exception("The slit edges specifications appear to be incorrect.") # bot is the polynomium that defines the shape of the bottom of the slit. In this case, we set it to a constant. bot = botfun.c.copy() top = topfun.c.copy() #4 result = {} result["Target_Name"] = ssl[target]["Target_Name"] result["xposs_top"] = xposs_top result["yposs_top"] = yposs_top result["xposs_bot"] = xposs_bot result["yposs_bot"] = yposs_bot result["top"] = np.poly1d(top) result["bottom"] = np.poly1d(bot) result["hpps"] = hpps result["ok"] = ok results.append(result) results.append({"version": options["version"]}) return results
def write_outputs(solutions, itime, header, maskname, band_name, plan, options): sky_sub_out = np.zeros((2048, 2048), dtype=np.float) sky_model_out = np.zeros((2048, 2048), dtype=np.float) p0 = plan[0].replace("'", "p") p1 = plan[1].replace("'", "p") suffix = "%s-%s" % (p0,p1) xroi = slice(0,2048) for sol in solutions: if not sol["ok"]: continue yroi = slice(sol["bottom"], sol["top"]) sky_sub_out[yroi, xroi] = sol["output"] sky_model_out[yroi, xroi] = sol["model"] header['BUNIT'] = 'SECOND' IO.writefits(itime, maskname, "itime_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True, lossy_compress=True) header['BUNIT'] = 'ELECTRONS/SECOND' IO.writefits(data, maskname, "sub_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True, lossy_compress=True) header['BUNIT'] = 'ELECTRONS/SECOND' IO.writefits(sky_sub_out, maskname, "bsub_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True) header['BUNIT'] = 'ELECTRONS' IO.writefits(Var, maskname, "var_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True, lossy_compress=True) header['BUNIT'] = 'ELECTRONS/SECOND' IO.writefits(sky_model_out, maskname, "bmod_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True, lossy_compress=True) '''Now create rectified solutions''' dlam = Wavelength.grating_results(band) hpp = np.array(Filters.hpp[band]) ll_fid = np.arange(hpp[0], hpp[1], dlam) nspec = len(ll_fid) rectified = np.zeros((2048, nspec), dtype=np.float32) rectified_var = np.zeros((2048, nspec), dtype=np.float32) rectified_itime = np.zeros((2048, nspec), dtype=np.float32) from scipy.interpolate import interp1d for i in xrange(2048): ll = lam[1][i,:] ss = sky_sub_out[i,:] ok = np.isfinite(ll) & np.isfinite(ss) & (ll < hpp[1]) & (ll > hpp[0]) if len(np.where(ok)[0]) < 100: continue f = interp1d(ll[ok], ss[ok], bounds_error=False) rectified[i,:] = f(ll_fid) f = interp1d(ll, Var[i,:], bounds_error=False) rectified_var[i,:] = f(ll_fid) f = interp1d(ll, itime[i,:], bounds_error=False) rectified_itime[i,:] = f(ll_fid) header["wat0_001"] = "system=world" header["wat1_001"] = "type=linear" header["wat2_001"] = "type=linear" header["dispaxis"] = 1 header["dclog1"] = "Transform" header["dc-flag"] = 0 header["type1"] = "AWAV" header["cunit1"] = "Angstrom" header["crval1"] = (ll_fid[0], "Starting wavelength Angstrom") header["crval2"] = 0 header["crpix1"] = 1 header["crpix2"] = 1 header["cdelt1"] = 1 header["cdelt2"] = 1 header["cname1"] = "angstrom" header["cname2"] = "pixel" header["cd1_1"] = (dlam, "Angstrom/pixel") header["cd1_2"] = 0 header["cd2_1"] = 0 header["cd2_2"] = (1, "pixel/pixel") IO.writefits(rectified_itime, maskname, "%s_rectified_itime_%s_%s.fits" % (maskname, band_name, suffix), options, header=header, overwrite=True, lossy_compress=True) IO.writefits(rectified, maskname, "%s_rectified_%s_%s.fits" % (maskname, band_name, suffix), options, header=header, overwrite=True, lossy_compress=True) IO.writefits(rectified_var, maskname, "%s_rectified_var_%s_%s.fits" % (maskname, band_name, suffix), options, header=header, overwrite=True, lossy_compress=True) IO.writefits(rectified*rectified_itime/np.sqrt(rectified_var), maskname, "%s_rectified_sn_%s_%s.fits" % (maskname, band_name, suffix), options, header=header, overwrite=True, lossy_compress=True)
def printWavelengthFit(self): if self.type is 'longslit' or self.type is 'long2pos': addLongSlit = ",longslit=longslit" else: addLongSlit = "" if self.type is 'slitmask' or self.type is 'longslit': self.useNeon = False self.useArgon = False # determine is Argon and Neon files contain data for K bands if self.isEmpty('Ar.txt') is False and self.band is 'K': self.useArgon = True if self.isEmpty('Ne.txt') is False and self.band is 'K': self.useNeon = True self.addLine( "Wavelength.imcombine(obsfiles, maskname, band, waveops)") if self.useArgon: self.addLine( "Wavelength.imcombine('Ar.txt', maskname, band, waveops)") if self.useNeon: self.addLine( "Wavelength.imcombine('Ne.txt', maskname, band, waveops)") self.addLine( "Wavelength.fit_lambda_interactively(maskname, band, obsfiles,waveops" + addLongSlit + ", noninteractive=noninteractiveflag)") if self.useArgon: self.addLine( "Wavelength.apply_interactive(maskname, band, waveops, apply=obsfiles, to='Ar.txt', argon=True)" ) if self.useNeon: self.addLine( "Wavelength.apply_interactive(maskname, band, waveops, apply=obsfiles, to='Ne.txt', neon=True)" ) self.addLine( "Wavelength.fit_lambda(maskname, band, obsfiles, obsfiles,waveops" + addLongSlit + ")") if self.useArgon and self.useNeon: self.addLine( "Wavelength.fit_lambda(maskname, band, 'Ne.txt', 'Ne.txt',waveops, wavenames2='Ar.txt'" + addLongSlit + ")") if self.useArgon and not self.useNeon: self.addLine( "Wavelength.fit_lambda(maskname, band, 'Ar.txt', 'Ar.txt',waveops" + addLongSlit + ")") if self.useNeon and not self.useArgon: self.addLine( "Wavelength.fit_lambda(maskname, band, 'Ne.txt', 'Ne.txt',waveops" + addLongSlit + ")") if self.useNeon or self.useArgon: self.addLine("LROI = [[21000,22800]]*1") if self.useNeon: self.addLine( "LROIs = Wavelength.check_wavelength_roi(maskname, band, obsfiles, 'Ne.txt', LROI, waveops)" ) if self.useArgon and not self.useNeon: self.addLine( "LROIs = Wavelength.check_wavelength_roi(maskname, band, obsfiles, 'Ar.txt', LROI, waveops)" ) self.addLine( "Wavelength.apply_lambda_simple(maskname, band, obsfiles, waveops" + addLongSlit + ")") if self.useArgon and self.useNeon: self.addLine( "Wavelength.apply_lambda_sky_and_arc(maskname, band, obsfiles, 'Ne.txt', LROIs, waveops)" ) if self.useArgon and not self.useNeon: self.addLine( "Wavelength.apply_lambda_sky_and_arc(maskname, band, obsfiles, 'Ar.txt', LROIs, waveops)" ) if self.useNeon and not self.useArgon: self.addLine( "Wavelength.apply_lambda_sky_and_arc(maskname, band, obsfiles, 'Ne.txt', LROIs, waveops)" ) # determine waveleng name files = IO.list_file_to_strings(self.offsetFiles) if self.useNeon: neon_files = IO.list_file_to_strings('Ne.txt') self.waveName = "merged_lambda_solution_" + str( Wavelength.filelist_to_wavename( files, self.band, self.maskName, "")).rstrip(".fits") + "_and_" + str( Wavelength.filelist_to_wavename( neon_files, self.band, self.maskName, "")) elif self.useArgon and not self.useNeon: argon_files = IO.list_file_to_strings('Ar.txt') self.waveName = "merged_lambda_solution_" + str( Wavelength.filelist_to_wavename( files, self.band, self.maskName, "")).rstrip(".fits") + "_and_" + str( Wavelength.filelist_to_wavename( argon_files, self.band, self.maskName, "")) else: self.waveName = "lambda_solution_" + str( Wavelength.filelist_to_wavename(files, self.band, self.maskName, "")) if self.type is 'long2pos' or self.type is 'long2pos_specphot': calibWith = "" if self.isEmpty('Ar.txt') is False: self.addLine("argon = ['Ar.txt']") calibWith = "argon" waveFiles = IO.list_file_to_strings('Ar.txt') if self.isEmpty('Ne.txt') is False: self.addLine("neon = ['Ne.txt']") calibWith = "neon" waveFiles = IO.list_file_to_strings('Ne.txt') if calibWith: # we have either Argon, or Neon, or both, so we can use arcs for the reduction self.addLine("Wavelength.imcombine(" + str(calibWith) + ", maskname, band, waveops)") self.addLine( "Wavelength.fit_lambda_interactively(maskname, band, " + str(calibWith) + ",waveops,longslit=longslit, " + str(calibWith) + "=True, noninteractive=noninteractiveflag)") self.addLine("Wavelength.fit_lambda(maskname, band, " + str(calibWith) + "," + str(calibWith) + ",waveops,longslit=longslit)") self.addLine( "Wavelength.apply_lambda_simple(maskname, band, " + str(calibWith) + ", waveops, longslit=longslit, smooth=True)") self.waveName = "lambda_solution_" + str( Wavelength.filelist_to_wavename(waveFiles, self.band, self.maskName, "")) else: # we have no arcs. For the time being, we can try with sky lines but this only works with long2pos specphot print "#####################################################################################################" print "WARNING: There are no arc calibration files" print " The pipeline will try to use sky lines but this only works if the observation is long enough" print " and if you are only using long2pos. It will NOT work on long2pos_specphot" print " Please contact the MosfireDRP team to obtain a standard wavelength solution" print "#####################################################################################################" self.addLine( "obsfiles = obsfiles_posAnarrow + obsfiles_posCnarrow") self.addLine( "Wavelength.imcombine(obsfiles, maskname, band, waveops)") self.addLine( "Wavelength.fit_lambda_interactively(maskname, band, obsfiles ,waveops,longslit=longslit, noninteractive=noninteractiveflag)" ) self.addLine( "Wavelength.fit_lambda(maskname, band, obsfiles,obsfiles ,waveops,longslit=longslit)" ) self.addLine( "Wavelength.apply_lambda_simple(maskname, band, obsfiles, waveops, longslit=longslit, smooth=True)" ) files = IO.list_file_to_strings(self.offsetFiles) self.waveName = "lambda_solution_" + str( Wavelength.filelist_to_wavename(files, self.band, self.maskName, "")) self.addLine("") self.addLine("Wavelength_file = '" + str(self.waveName) + "'") self.addLine("")
pixs[0] = pixs[0][ind] betas[0] = betas[0][ind] all_pixs = np.concatenate(pixs) all_betas = np.concatenate(betas) pars = [1500, 20, 100000, 10000] pars.extend(np.zeros(len(pixs))) pars = np.array(pars) parinfo = [] for par in pars: parinfo.append({"fixed": 0, "value": par}) pl.ion() y = Wavelength.beta_model(pars, pixs) parinfo[0]["fixed"] = 1 parinfo[1]["fixed"] = 1 parinfo[2]["fixed"] = 1 parinfo[3]["fixed"] = 1 merit_fun = Fit.mpfit_residuals(Wavelength.beta_model) lsf = Fit.mpfit_do(merit_fun, pixs, all_betas, parinfo) parinfo = [] for param in lsf.params: parinfo.append({"fixed": 0, "value": param}) lsf = Fit.mpfit_do(merit_fun, pixs, all_betas, parinfo) print lsf pl.figure(2)
def go(maskname, band, filenames, wavefile, wavoptions, longoptions, use_flat=False): ''' The go command is the main entry point into this module. Inputs: maskname: String of the mask name band: String of 'Y', 'J', 'H', or 'K' filenames: List of filenames to reduce wavefile: String of path to FITS file with the wavelength solution wavoptions: The Wavelength Options dictionary longoptions: Dictionary containing: {'yrange': The pixel range to extract over 'row_position': The row to solve the initial wavelength solution on} use_flat: Boolean False [default] means to use no flat field Boolean True means to divide by the pixelflat ''' wavename = Wavelength.filelist_to_wavename(filenames, band, maskname, wavoptions).rstrip(".fits") print "Wavefile: {0}".format(wavefile) lamhdr, lamdat = IO.readfits(wavefile) positions = [] objname = None for listfile in filenames: fnames = IO.list_file_to_strings(listfile) if len(fnames) != 1: raise Exception("I currently expect only one file per position. Remove multiple entries and try again") header, data, bs = IO.readmosfits(fnames[0], wavoptions) if objname is None: objname = header["object"] if objname != header["object"]: print ("Trying to combine longslit stack of object {0} " "with object {1}".format(objname, header["object"])) print("{0:18s} {1:30s} {2:2s} {3:4.1f}".format(file, header["object"], header["frameid"], header["yoffset"])) positions.append([fnames[0], header, data, bs]) print("{0:2g} nod positions found. Producing stacked difference" \ " image.".format(len(positions))) for i in xrange(len(positions)-1): A = positions[i] B = positions[i+1] print("----------- -----".format(A,B)) dname, varname = imdiff(A, B, maskname, band, header, wavoptions) if use_flat: apply_flat(dname, maskname, band) apply_flat(varname, maskname, band) rectify(dname, lamdat, A, B, maskname, band, wavoptions, longoptions) rectify(varname, lamdat, A, B, maskname, band, wavoptions, longoptions) print dname dname, vname = imdiff(B, A, maskname, band, header, wavoptions) if use_flat: apply_flat(dname, maskname, band) apply_flat(vname, maskname, band) rectify(dname, lamdat, B, A, maskname, band, wavoptions, longoptions) rectify(vname, lamdat, B, A, maskname, band, wavoptions, longoptions) if False: fname = os.path.join(path, wavename + ".fits") B = IO.readfits(fname) B = [fname, B[0], B[1]] for i in xrange(len(positions)): A = positions[i] imdiff(A, B, maskname, band, wavoptions) rectify(path, dname, lamdat, A, B, maskname, band, wavoptions, longoptions) imdiff(B, A, maskname, band, wavoptions) rectify(path, dname, lamdat, B, A, maskname, band, wavoptions, longoptions)
def go(maskname, band, filenames, wavefile, wavoptions, longoptions, use_flat=False): ''' The go command is the main entry point into this module. Inputs: maskname: String of the mask name band: String of 'Y', 'J', 'H', or 'K' filenames: List of filenames to reduce wavefile: String of path to FITS file with the wavelength solution wavoptions: The Wavelength Options dictionary longoptions: Dictionary containing: {'yrange': The pixel range to extract over 'row_position': The row to solve the initial wavelength solution on} use_flat: Boolean False [default] means to use no flat field Boolean True means to divide by the pixelflat ''' wavename = Wavelength.filelist_to_wavename(filenames, band, maskname, wavoptions).rstrip(".fits") print "Wavefile: {0}".format(wavefile) lamhdr, lamdat = IO.readfits(wavefile) positions = [] objname = None for listfile in filenames: fnames = IO.list_file_to_strings(listfile) if len(fnames) != 1: raise Exception( "I currently expect only one file per position. Remove multiple entries and try again" ) header, data, bs = IO.readmosfits(fnames[0], wavoptions) if objname is None: objname = header["object"] if objname != header["object"]: print( "Trying to combine longslit stack of object {0} " "with object {1}".format(objname, header["object"])) print("{0:18s} {1:30s} {2:2s} {3:4.1f}".format(file, header["object"], header["frameid"], header["yoffset"])) positions.append([fnames[0], header, data, bs]) print("{0:2g} nod positions found. Producing stacked difference" \ " image.".format(len(positions))) for i in xrange(len(positions) - 1): A = positions[i] B = positions[i + 1] print("----------- -----".format(A, B)) dname, varname = imdiff(A, B, maskname, band, header, wavoptions) if use_flat: apply_flat(dname, maskname, band) apply_flat(varname, maskname, band) rectify(dname, lamdat, A, B, maskname, band, wavoptions, longoptions) rectify(varname, lamdat, A, B, maskname, band, wavoptions, longoptions) print dname dname, vname = imdiff(B, A, maskname, band, header, wavoptions) if use_flat: apply_flat(dname, maskname, band) apply_flat(vname, maskname, band) rectify(dname, lamdat, B, A, maskname, band, wavoptions, longoptions) rectify(vname, lamdat, B, A, maskname, band, wavoptions, longoptions) if False: fname = os.path.join(path, wavename + ".fits") B = IO.readfits(fname) B = [fname, B[0], B[1]] for i in xrange(len(positions)): A = positions[i] imdiff(A, B, maskname, band, wavoptions) rectify(path, dname, lamdat, A, B, maskname, band, wavoptions, longoptions) imdiff(B, A, maskname, band, wavoptions) rectify(path, dname, lamdat, B, A, maskname, band, wavoptions, longoptions)
def handle_rectification(maskname, in_files, wavename, band_pass, files, options, commissioning_shift=3.0, target='default'): '''Handle slit rectification and coaddition. Args: maskname: The mask name string in_files: List of stacked spectra in electron per second. Will look like ['electrons_Offset_1.5.txt.fits', 'electrons_Offset_-1.5.txt.fits'] wavename: path (relative or full) to the wavelength stack file, string band_pass: Band pass name, string barset_file: Path to a mosfire fits file containing the full set of FITS extensions for the barset. It can be any file in the list of science files. Returns: None Writes files: [maskname]_[band]_[object name]_eps.fits -- The rectified, background subtracted, stacked eps spectrum [maskname]_[band]_[object name]_sig.fits -- Rectified, background subtracted, stacked weight spectrum (STD/itime) [maskname]_[band]_[object_name]_itime.fits Rectified, CRR stacked integration time spectrum [maskname]_[band]_[object_name]_snrs.fits Rectified signal to noise spectrum ''' global edges, dats, vars, itimes, shifts, lambdas, band, fidl, all_shifts band = band_pass dlambda = Wavelength.grating_results(band) hpp = Filters.hpp[band] fidl = np.arange(hpp[0], hpp[1], dlambda) lambdas = IO.readfits(wavename, options) if np.any(lambdas[1].data < 0) or np.any(lambdas[1].data > 29000): info("***********WARNING ***********") info("The file {0} may not be a wavelength file.".format(wavename)) info("Check before proceeding.") info("***********WARNING ***********") edges, meta = IO.load_edges(maskname, band, options) shifts = [] posnames = [] postoshift = {} for file in in_files: info(":: "+str(file)) II = IO.read_drpfits(maskname, file, options) off = np.array((II[0]["decoff"], II[0]["raoff"]),dtype=np.float64) if "yoffset" in II[0]: off = -II[0]["yoffset"] else: # Deal with data taken during commissioning if II[0]["frameid"] == 'A': off = 0.0 else: off = commissioning_shift try: off0 except: off0 = off shift = off - off0 shifts.append(shift) posnames.append(II[0]["frameid"]) postoshift[II[0]['frameid']] = shift info("Position {0} shift: {1:2.2f} as".format(off, shift)) # this is to deal with cases in which we want to rectify one single file if len(set(posnames)) is 1: plans = [['A']] else: plans = Background.guess_plan_from_positions(set(posnames)) all_shifts = [] for plan in plans: to_append = [] for pos in plan: to_append.append(postoshift[pos]) all_shifts.append(to_append) # Reverse the elements in all_shifts to deal with an inversion all_shifts.reverse() theBPM = IO.badpixelmask() all_solutions = [] cntr = 0 if target is 'default': outname = maskname else: outname = target for plan in plans: if len(plan) is 1: p0 = 'A' p1 = 'B' else: p0 = plan[0].replace("'", "p") p1 = plan[1].replace("'", "p") suffix = "%s-%s" % (p0,p1) info("Handling plan %s" % suffix) fname = "bsub_{0}_{1}_{2}.fits".format(outname,band,suffix) EPS = IO.read_drpfits(maskname, fname, options) EPS[1] = np.ma.masked_array(EPS[1], theBPM, fill_value=0) fname = "var_{0}_{1}_{2}.fits".format(outname, band, suffix) VAR = IO.read_drpfits(maskname, fname, options) VAR[1] = np.ma.masked_array(VAR[1], theBPM, fill_value=np.inf) fname = "itime_{0}_{1}_{2}.fits".format(outname, band, suffix) ITIME = IO.read_drpfits(maskname, fname, options) ITIME[1] = np.ma.masked_array(ITIME[1], theBPM, fill_value=0) dats = EPS vars = VAR itimes = ITIME EPS[0]["ORIGFILE"] = fname tock = time.time() sols = range(len(edges)-1,-1,-1) shifts = all_shifts[cntr] cntr += 1 p = Pool() solutions = p.map(handle_rectification_helper, sols) p.close() all_solutions.append(solutions) tick = time.time() info("-----> Mask took %i. Writing to disk." % (tick-tock)) output = np.zeros((1, len(fidl))) snrs = np.zeros((1, len(fidl))) sdout= np.zeros((1, len(fidl))) itout= np.zeros((1, len(fidl))) # the barset [bs] is used for determining object position files = IO.list_file_to_strings(files) info("Using "+str(files[0])+" for slit configuration.") x, x, bs = IO.readmosfits(files[0], options) for i_slit in xrange(len(solutions)): solution = all_solutions[0][i_slit] header = EPS[0].copy() obj = header['OBJECT'] target_name = bs.ssl[-(i_slit+1)]['Target_Name'] header['OBJECT'] = target_name pixel_dist = np.float(bs.ssl[-(i_slit+1)]['Target_to_center_of_slit_distance'])/0.18 pixel_dist -= solution['offset'] ll = solution["lambda"] header["wat0_001"] = "system=world" header["wat1_001"] = "wtype=linear" header["wat2_001"] = "wtype=linear" header["dispaxis"] = 1 header["dclog1"] = "Transform" header["dc-flag"] = 0 header["ctype1"] = "AWAV" header["cunit1"] = "Angstrom" header["crval1"] = ll[0] header["crval2"] = -solution["eps_img"].shape[0]/2 - pixel_dist header["crpix1"] = 1 header["crpix2"] = 1 #remove redundant CDELTi due to wavelength issues with ds9 #see: https://github.com/Keck-DataReductionPipelines/MosfireDRP/issues/44 #header["cdelt1"] = 1 #header["cdelt2"] = 1 header["cname1"] = "angstrom" header["cname2"] = "pixel" header["cd1_1"] = ll[1]-ll[0] header["cd1_2"] = 0 header["cd2_1"] = 0 header["cd2_2"] = 1 try: header["BARYCORR"]= (lambdas[0]['BARYCORR'],lambdas[0].comments['BARYCORR']) except KeyError: warning( "Barycentric corrections not applied to the wavelength solution") pass S = output.shape img = solution["eps_img"] std = solution["sd_img"] tms = solution["itime_img"] for i_solution in xrange(1,len(all_solutions)): info("Combining solution %i" %i_solution) solution = all_solutions[i_solution][i_slit] img += solution["eps_img"] std += solution["sd_img"] tms += solution["itime_img"] #print "adding in quadrature" output = np.append(output, img, 0) output = np.append(output, np.nan*np.zeros((3,S[1])), 0) snrs = np.append(snrs, img*tms/std, 0) snrs = np.append(snrs, np.nan*np.zeros((3,S[1])), 0) sdout = np.append(sdout, std, 0) sdout = np.append(sdout, np.nan*np.zeros((3,S[1])), 0) itout = np.append(itout, tms, 0) itout = np.append(itout, np.nan*np.zeros((3,S[1])), 0) header['bunit'] = ('electron/second', 'electron power') IO.writefits(img, maskname, "{0}_{1}_{2}_eps.fits".format(outname, band, target_name), options, overwrite=True, header=header, lossy_compress=False) header['bunit'] = ('electron/second', 'sigma/itime') IO.writefits(std/tms, maskname, "{0}_{1}_{2}_sig.fits".format(outname, band, target_name), options, overwrite=True, header=header, lossy_compress=False) header['bunit'] = ('second', 'exposure time') IO.writefits(tms, maskname, "{0}_{1}_{2}_itime.fits".format(outname, band, target_name), options, overwrite=True, header=header, lossy_compress=False) header['bunit'] = ('', 'SNR') IO.writefits(img*tms/std, maskname, "{0}_{1}_{2}_snrs.fits".format(outname, band, target_name), options, overwrite=True, header=header, lossy_compress=False) header = EPS[0].copy() header["wat0_001"] = "system=world" header["wat1_001"] = "wtype=linear" header["wat2_001"] = "wtype=linear" header["dispaxis"] = 1 header["dclog1"] = "Transform" header["dc-flag"] = 0 header["ctype1"] = "AWAV" header["cunit1"] = ("Angstrom", 'Start wavelength') header["crval1"] = ll[0] header["crval2"] = 1 header["crpix1"] = 1 header["crpix2"] = 1 #remove redundant CDELTi due to wavelength issues with ds9 #see: https://github.com/Keck-DataReductionPipelines/MosfireDRP/issues/44 #header["cdelt1"] = 1 #header["cdelt2"] = 1 header["cname1"] = "angstrom" header["cname2"] = "pixel" header["cd1_1"] = (ll[1]-ll[0], 'Angstrom/pixel') header["cd1_2"] = 0 header["cd2_1"] = 0 header["cd2_2"] = 1 try: header["BARYCORR"]= (lambdas[0]['BARYCORR'],lambdas[0].comments['BARYCORR']) except KeyError: warning( "Barycentric corrections not applied to the wavelength solution") pass header["bunit"] = "ELECTRONS/SECOND" info("############ Final reduced file: {0}_{1}_eps.fits".format(outname,band)) IO.writefits(output, maskname, "{0}_{1}_eps.fits".format(outname, band), options, overwrite=True, header=header, lossy_compress=False) header["bunit"] = "" IO.writefits(snrs, maskname, "{0}_{1}_snrs.fits".format(outname, band), options, overwrite=True, header=header, lossy_compress=False) header["bunit"] = "ELECTRONS/SECOND" IO.writefits(sdout/itout, maskname, "{0}_{1}_sig.fits".format(outname, band), options, overwrite=True, header=header, lossy_compress=False) header["bunit"] = "SECOND" IO.writefits(itout, maskname, "{0}_{1}_itime.fits".format(outname, band), options, overwrite=True, header=header, lossy_compress=False)
def write_outputs(solutions, itime, header, maskname, band_name, plan, options): sky_sub_out = np.zeros((2048, 2048), dtype=np.float) sky_model_out = np.zeros((2048, 2048), dtype=np.float) p0 = plan[0].replace("'", "p") p1 = plan[1].replace("'", "p") suffix = "%s-%s" % (p0, p1) xroi = slice(0, 2048) for sol in solutions: if not sol["ok"]: continue yroi = slice(sol["bottom"], sol["top"]) sky_sub_out[yroi, xroi] = sol["output"] sky_model_out[yroi, xroi] = sol["model"] header['BUNIT'] = 'SECOND' IO.writefits(itime, maskname, "itime_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True, lossy_compress=True) header['BUNIT'] = 'ELECTRONS/SECOND' IO.writefits(data, maskname, "sub_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True, lossy_compress=True) header['BUNIT'] = 'ELECTRONS/SECOND' IO.writefits(sky_sub_out, maskname, "bsub_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True) header['BUNIT'] = 'ELECTRONS' IO.writefits(Var, maskname, "var_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True, lossy_compress=True) header['BUNIT'] = 'ELECTRONS/SECOND' IO.writefits(sky_model_out, maskname, "bmod_%s_%s_%s.fits" % (maskname, band, suffix), options, header=header, overwrite=True, lossy_compress=True) '''Now create rectified solutions''' dlam = Wavelength.grating_results(band) hpp = np.array(Filters.hpp[band]) ll_fid = np.arange(hpp[0], hpp[1], dlam) nspec = len(ll_fid) rectified = np.zeros((2048, nspec), dtype=np.float32) rectified_var = np.zeros((2048, nspec), dtype=np.float32) rectified_itime = np.zeros((2048, nspec), dtype=np.float32) from scipy.interpolate import interp1d for i in xrange(2048): ll = lam[1][i, :] ss = sky_sub_out[i, :] ok = np.isfinite(ll) & np.isfinite(ss) & (ll < hpp[1]) & (ll > hpp[0]) if len(np.where(ok)[0]) < 100: continue f = interp1d(ll[ok], ss[ok], bounds_error=False) rectified[i, :] = f(ll_fid) f = interp1d(ll, Var[i, :], bounds_error=False) rectified_var[i, :] = f(ll_fid) f = interp1d(ll, itime[i, :], bounds_error=False) rectified_itime[i, :] = f(ll_fid) header["wat0_001"] = "system=world" header["wat1_001"] = "type=linear" header["wat2_001"] = "type=linear" header["dispaxis"] = 1 header["dclog1"] = "Transform" header["dc-flag"] = 0 header["type1"] = "AWAV" header["cunit1"] = "Angstrom" header["crval1"] = (ll_fid[0], "Starting wavelength Angstrom") header["crval2"] = 0 header["crpix1"] = 1 header["crpix2"] = 1 header["cdelt1"] = 1 header["cdelt2"] = 1 header["cname1"] = "angstrom" header["cname2"] = "pixel" header["cd1_1"] = (dlam, "Angstrom/pixel") header["cd1_2"] = 0 header["cd2_1"] = 0 header["cd2_2"] = (1, "pixel/pixel") IO.writefits(rectified_itime, maskname, "%s_rectified_itime_%s_%s.fits" % (maskname, band_name, suffix), options, header=header, overwrite=True, lossy_compress=True) IO.writefits(rectified, maskname, "%s_rectified_%s_%s.fits" % (maskname, band_name, suffix), options, header=header, overwrite=True, lossy_compress=True) IO.writefits(rectified_var, maskname, "%s_rectified_var_%s_%s.fits" % (maskname, band_name, suffix), options, header=header, overwrite=True, lossy_compress=True) IO.writefits(rectified * rectified_itime / np.sqrt(rectified_var), maskname, "%s_rectified_sn_%s_%s.fits" % (maskname, band_name, suffix), options, header=header, overwrite=True, lossy_compress=True)
flatops = Options.flat waveops = Options.wavelength #Driver file automatically generated on Sat Jul 25 17:46:43 2015 #For questions and comments, email [email protected], submit a ticket on the ticketing system, or contact Luca Rizzi @ WMKO maskname = 'maskname' band = 'band' #Set bypass to True to autofit wavelenth solution instead of manually fitting. bypassflag=False obsfiles=['Offset_1.25.txt','Offset_-1.25.txt'] Flats.handle_flats('Flat.txt', maskname, band, flatops,lampOffList='FlatThermal.txt') Wavelength.imcombine(obsfiles, maskname, band, waveops) # if you have Ar Wavelength.imcombine('Ar.txt', maskname, band, waveops) # if you have Ne Wavelength.imcombine('Ne.txt', maskname, band, waveops) Wavelength.fit_lambda_interactively(maskname, band, obsfiles,waveops, bypass=bypassflag) Wavelength.apply_interactive(maskname, band, waveops, apply=obsfiles, to='Ar.txt', argon=True) Wavelength.apply_interactive(maskname, band, waveops, apply=obsfiles, to='Ne.txt', neon=True) Wavelength.fit_lambda(maskname, band, obsfiles, obsfiles,waveops) Wavelength.fit_lambda(maskname, band, 'Ne.txt', 'Ne.txt',waveops, wavenames2='Ar.txt') LROI = [[21000,22800]]*1 LROIs = Wavelength.check_wavelength_roi(maskname, band, obsfiles, 'Ne.txt', LROI, waveops) Wavelength.apply_lambda_simple(maskname, band, obsfiles, waveops)
def handle_rectification(maskname, in_files, wavename, band_pass, barset_file, options, commissioning_shift=3.0): '''Handle slit rectification and coaddition. Args: maskname: The mask name string in_files: List of stacked spectra in electron per second. Will look like ['electrons_Offset_1.5.txt.fits', 'electrons_Offset_-1.5.txt.fits'] wavename: path (relative or full) to the wavelength stack file, string band_pass: Band pass name, string barset_file: Path to a mosfire fits file containing the full set of FITS extensions for the barset. It can be any file in the list of science files. Returns: None Writes files: [maskname]_[band]_[object name]_eps.fits -- The rectified, background subtracted, stacked eps spectrum [maskname]_[band]_[object name]_sig.fits -- Rectified, background subtracted, stacked weight spectrum (STD/itime) [maskname]_[band]_[object_name]_itime.fits Rectified, CRR stacked integration time spectrum [maskname]_[band]_[object_name]_snrs.fits Rectified signal to noise spectrum ''' global edges, dats, vars, itimes, shifts, lambdas, band, fidl, all_shifts band = band_pass dlambda = Wavelength.grating_results(band) hpp = Filters.hpp[band] fidl = np.arange(hpp[0], hpp[1], dlambda) lambdas = IO.readfits(wavename, options) if np.any(lambdas[1].data < 0) or np.any(lambdas[1].data > 29000): print "***********WARNING ***********" print "The file {0} may not be a wavelength file.".format(wavename) print "Check before proceeding." print "***********WARNING ***********" edges, meta = IO.load_edges(maskname, band, options) shifts = [] posnames = [] postoshift = {} for file in in_files: print ":: ", file II = IO.read_drpfits(maskname, file, options) off = np.array((II[0]["decoff"], II[0]["raoff"]),dtype=np.float64) if "yoffset" in II[0]: off = -II[0]["yoffset"] else: # Deal with data taken during commissioning if II[0]["frameid"] == 'A': off = 0.0 else: off = commissioning_shift try: off0 except: off0 = off shift = off - off0 shifts.append(shift) posnames.append(II[0]["frameid"]) postoshift[II[0]['frameid']] = shift print "Position {0} shift: {1:2.2f} as".format(off, shift) plans = Background.guess_plan_from_positions(set(posnames)) all_shifts = [] for plan in plans: to_append = [] for pos in plan: to_append.append(postoshift[pos]) all_shifts.append(to_append) # Reverse the elements in all_shifts to deal with an inversion all_shifts.reverse() theBPM = IO.badpixelmask() all_solutions = [] cntr = 0 for plan in plans: p0 = plan[0].replace("'", "p") p1 = plan[1].replace("'", "p") suffix = "%s-%s" % (p0,p1) print "Handling plan %s" % suffix fname = "bsub_{0}_{1}_{2}.fits".format(maskname,band,suffix) EPS = IO.read_drpfits(maskname, fname, options) EPS[1] = np.ma.masked_array(EPS[1], theBPM, fill_value=0) fname = "var_{0}_{1}_{2}.fits".format(maskname, band, suffix) VAR = IO.read_drpfits(maskname, fname, options) VAR[1] = np.ma.masked_array(VAR[1], theBPM, fill_value=np.inf) fname = "itime_{0}_{1}_{2}.fits".format(maskname, band, suffix) ITIME = IO.read_drpfits(maskname, fname, options) ITIME[1] = np.ma.masked_array(ITIME[1], theBPM, fill_value=0) dats = EPS vars = VAR itimes = ITIME EPS[0]["ORIGFILE"] = fname tock = time.time() sols = range(len(edges)-1,-1,-1) shifts = all_shifts[cntr] cntr += 1 p = Pool() solutions = p.map(handle_rectification_helper, sols) #solutions = map(handle_rectification_helper, [15]) p.close() all_solutions.append(solutions) tick = time.time() print "-----> Mask took %i. Writing to disk." % (tick-tock) output = np.zeros((1, len(fidl))) snrs = np.zeros((1, len(fidl))) sdout= np.zeros((1, len(fidl))) itout= np.zeros((1, len(fidl))) # the barset [bs] is used for determining object position x, x, bs = IO.readmosfits(barset_file, options) for i_slit in xrange(len(solutions)): solution = all_solutions[0][i_slit] header = EPS[0].copy() obj = header['OBJECT'] target_name = bs.ssl[-(i_slit+1)]['Target_Name'] header['OBJECT'] = target_name pixel_dist = np.float(bs.ssl[-(i_slit+1)]['Target_to_center_of_slit_distance'])/0.18 pixel_dist -= solution['offset'] ll = solution["lambda"] header["wat0_001"] = "system=world" header["wat1_001"] = "wtype=linear" header["wat2_001"] = "wtype=linear" header["dispaxis"] = 1 header["dclog1"] = "Transform" header["dc-flag"] = 0 header["ctype1"] = "AWAV" header["cunit1"] = "Angstrom" header["crval1"] = ll[0] header["crval2"] = -solution["eps_img"].shape[0]/2 - pixel_dist header["crpix1"] = 1 header["crpix2"] = 1 header["cdelt1"] = 1 header["cdelt2"] = 1 header["cname1"] = "angstrom" header["cname2"] = "pixel" header["cd1_1"] = ll[1]-ll[0] header["cd1_2"] = 0 header["cd2_1"] = 0 header["cd2_2"] = 1 S = output.shape img = solution["eps_img"] std = solution["sd_img"] tms = solution["itime_img"] for i_solution in xrange(1,len(all_solutions)): print "Combining solution %i" %i_solution solution = all_solutions[i_solution][i_slit] img += solution["eps_img"] std += solution["sd_img"] tms += solution["itime_img"] output = np.append(output, img, 0) output = np.append(output, np.nan*np.zeros((3,S[1])), 0) snrs = np.append(snrs, img*tms/std, 0) snrs = np.append(snrs, np.nan*np.zeros((3,S[1])), 0) sdout = np.append(sdout, std, 0) sdout = np.append(sdout, np.nan*np.zeros((3,S[1])), 0) itout = np.append(itout, tms, 0) itout = np.append(itout, np.nan*np.zeros((3,S[1])), 0) header['bunit'] = ('electron/second', 'electron power') IO.writefits(img, maskname, "{0}_{1}_{2}_eps.fits".format(maskname, band, target_name), options, overwrite=True, header=header, lossy_compress=False) header['bunit'] = ('electron/second', 'sigma/itime') IO.writefits(std/tms, maskname, "{0}_{1}_{2}_sig.fits".format(maskname, band, target_name), options, overwrite=True, header=header, lossy_compress=False) header['bunit'] = ('second', 'exposure time') IO.writefits(tms, maskname, "{0}_{1}_{2}_itime.fits".format(maskname, band, target_name), options, overwrite=True, header=header, lossy_compress=False) header['bunit'] = ('', 'SNR') IO.writefits(img*tms/std, maskname, "{0}_{1}_{2}_snrs.fits".format(maskname, band, target_name), options, overwrite=True, header=header, lossy_compress=False) header = EPS[0].copy() header["wat0_001"] = "system=world" header["wat1_001"] = "wtype=linear" header["wat2_001"] = "wtype=linear" header["dispaxis"] = 1 header["dclog1"] = "Transform" header["dc-flag"] = 0 header["ctype1"] = "AWAV" header["cunit1"] = ("Angstrom", 'Start wavelength') header["crval1"] = ll[0] header["crval2"] = 1 header["crpix1"] = 1 header["crpix2"] = 1 header["cdelt1"] = 1 header["cdelt2"] = 1 header["cname1"] = "angstrom" header["cname2"] = "pixel" header["cd1_1"] = (ll[1]-ll[0], 'Angstrom/pixel') header["cd1_2"] = 0 header["cd2_1"] = 0 header["cd2_2"] = 1 header["bunit"] = "ELECTRONS/SECOND" IO.writefits(output, maskname, "{0}_{1}_eps.fits".format(maskname, band), options, overwrite=True, header=header, lossy_compress=False) header["bunit"] = "" IO.writefits(snrs, maskname, "{0}_{1}_snrs.fits".format(maskname, band), options, overwrite=True, header=header, lossy_compress=False) header["bunit"] = "ELECTRONS/SECOND" IO.writefits(sdout/itout, maskname, "{0}_{1}_sig.fits".format(maskname, band), options, overwrite=True, header=header, lossy_compress=False) header["bunit"] = "SECOND" IO.writefits(itout, maskname, "{0}_{1}_itime.fits".format(maskname, band), options, overwrite=True, header=header, lossy_compress=False)
#For questions and comments, email [email protected], submit a ticket on the ticketing system, or contact Luca Rizzi @ WMKO maskname = 'LONGSLIT-3x0.7' band = 'H' #Set bypass to True to autofit wavelenth solution instead of manually fitting. bypassflag=False # modify the target name to match your observations obsfiles=['Offset_5_HIP17971.txt','Offset_-5_HIP17971.txt'] target="HIP17971" # modify the yrange to match the size of your longslit # row position is the extraction line used for the initial wavelength solution. It should be away from your target longslit = {'yrange':[968,1100],'row_position':1034,'mode':'longslit'} Flats.handle_flats('Flat.txt', maskname, band, flatops,longslit=longslit) Wavelength.imcombine(obsfiles, maskname, band, waveops) Wavelength.fit_lambda_interactively(maskname, band, obsfiles,waveops,longslit=longslit, bypass=bypassflag) Wavelength.fit_lambda(maskname, band, obsfiles, obsfiles,waveops,longslit=longslit) Wavelength.apply_lambda_simple(maskname, band, obsfiles, waveops,longslit=longslit) # make sure you use the file generated on the previous step Wavelength_file = 'lambda_solution_wave_stack_H_m121227_0162-0311.fits' Background.handle_background(obsfiles,Wavelength_file,maskname,band,waveops,target=target) redfiles = ["eps_" + file + ".fits" for file in obsfiles] Rectify.handle_rectification(maskname, redfiles,Wavelength_file,band,obsfiles,waveops, target=target)
fs = ['m120406_0291.fits'] maskname = 'NGC5053' options = Options.wavelength path = os.path.join(options["outdir"], maskname) if not os.path.exists(path): raise Exception("Output directory '%s' does not exist. This " "directory should exist." % path) if False: for fname in fs: fp = os.path.join(path, fname) mfits = IO.readmosfits(fp) header, data, bs = mfits Wavelength.plot_mask_solution_ds9(fname, maskname, options) Wavelength.fit_lambda(mfits, fname, maskname, options) Wavelength.apply_lambda(mfits, fname, maskname, options) Wavelength.plot_data_quality(maskname, fname, options) Wavelength.plot_sky_spectra(maskname, fname, options) Wavelength.plot_mask_fits(maskname, fname, options) if True: for fname in fs: pass
def rename_files(wavenames, maskname, band, wavops): lamname = Wavelength.filelist_to_wavename(wavenames[0], band, maskname, wavops).rstrip(".fits") suffix = lamname.lstrip("wave_stack_%s_" % band) path = os.path.join(wavops["outdir"], maskname) fnames = ["rectified_%s%s.fits", "rectified_ivar_%s%s.fits", "rectified_sn_%s%s.fits"] for fname in fnames: try: a = get_path(os.path.join(path, fname % (band, "_" + suffix))) b = os.path.join(path, fname % (band, "")) + gz(a) os.rename(a, b) except: print "Ignoring renaming of: ", fname pass edges = IO.load_edges(maskname, band, wavops) n_slits = len(edges[0]) for i in xrange(1, n_slits+1): S = "S%2.2i" % (i) a = get_path(os.path.join(path, "eps_%s_%s_%s.fits" % (band, suffix, S))) a_h = pf.open(a)[0].header obj = a_h['object'] b = os.path.join(path, "%s_%s_%s_eps.fits" % (maskname, band, obj)) + \ gz(a) os.rename(a,b) a = get_path(os.path.join(path, "ivar_%s_%s_%s.fits" % (band, suffix, S))) a_h = pf.open(a)[0].header obj = a_h['object'] b = os.path.join(path, "%s_%s_%s_ivar.fits" % (maskname, band, obj)) + \ gz(a) os.rename(a,b) a = get_path(os.path.join(path, "eps_%s_%s_%s.fits" % (maskname, suffix, band))) b = os.path.join(path, "%s_%s_eps.fits" % (maskname, band)) + gz(a) os.rename(a,b) a = get_path(os.path.join(path, "snrs_%s_%s_%s.fits" % (maskname, suffix, band))) b = os.path.join(path, "%s_%s_snrs.fits" % (maskname, band)) + gz(a) os.rename(a, b) a = get_path(os.path.join(path, "ivars_%s_%s_%s.fits" % (maskname, suffix, band))) b = os.path.join(path, "%s_%s_ivars.fits" % (maskname, band)) + gz(a) os.rename(a, b)
] target_posAwide = "HIP85871_7.25_POSA_WIDE" IO.fix_long2pos_headers(obsfiles_posAwide) # Note: for long2pos, the row position is ignored, and the middle point of the slit is used longslit = { 'yrange': [[1062, 1188], [887, 1010]], 'row_position': 0, 'mode': 'long2pos' } Flats.handle_flats('Flat.txt', maskname, band, flatops, longslit=longslit) # in this case, we are using the argon lines. # replace this with neon=['Ne.txt'] if you prefer to use Ne, and edit the following lines accordingly argon = ['Ar.txt'] Wavelength.imcombine(argon, maskname, band, waveops) Wavelength.fit_lambda_interactively(maskname, band, argon, waveops, longslit=longslit, argon=True, bypass=bypassflag) Wavelength.fit_lambda(maskname, band, argon, argon, waveops, longslit=longslit) Wavelength.apply_lambda_simple(maskname, band, argon, waveops, longslit=longslit, smooth=True)
# these are the wide slits, comment out if you are not using specphot obsfiles_posCwide = ["Offset_-14_HIP85871_7.25_PosC.txt", "Offset_-7_HIP85871_7.25_PosC.txt"] target_posCwide = "HIP85871_7.25_POSC_WIDE" IO.fix_long2pos_headers(obsfiles_posCwide) obsfiles_posAwide = ["Offset_14_HIP85871_7.25_PosA.txt", "Offset_21_HIP85871_7.25_PosA.txt"] target_posAwide = "HIP85871_7.25_POSA_WIDE" IO.fix_long2pos_headers(obsfiles_posAwide) # Note: for long2pos, the row position is ignored, and the middle point of the slit is used longslit = {"yrange": [[1062, 1188], [887, 1010]], "row_position": 0, "mode": "long2pos"} Flats.handle_flats("Flat.txt", maskname, band, flatops, longslit=longslit) # in this case, we are using the argon lines. # replace this with neon=['Ne.txt'] if you prefer to use Ne, and edit the following lines accordingly argon = ["Ar.txt"] Wavelength.imcombine(argon, maskname, band, waveops) Wavelength.fit_lambda_interactively(maskname, band, argon, waveops, longslit=longslit, argon=True, bypass=bypassflag) Wavelength.fit_lambda(maskname, band, argon, argon, waveops, longslit=longslit) Wavelength.apply_lambda_simple(maskname, band, argon, waveops, longslit=longslit, smooth=True) # make sure you use the correct wavelength file generated before Wavelength_file = "lambda_solution_wave_stack_H_m150428_0091-0091.fits" # narrow Background.handle_background(obsfiles_posAnarrow, Wavelength_file, maskname, band, waveops, target=target_posAnarrow) Background.handle_background(obsfiles_posCnarrow, Wavelength_file, maskname, band, waveops, target=target_posCnarrow) # wide Background.handle_background(obsfiles_posAwide, Wavelength_file, maskname, band, waveops, target=target_posAwide) Background.handle_background(obsfiles_posCwide, Wavelength_file, maskname, band, waveops, target=target_posCwide) # narrow
def find_and_fit_edges(data, header, bs, options,edgeThreshold=450): ''' Given a flat field image, find_and_fit_edges determines the position of all slits. The function works by starting with a guess at the location for a slit edge in the spatial direction(options["first-slit-edge"]). Starting from the guess, find_edge_pair works out in either direction, measuring the position of the (e.g.) bottom of slit 1 and top of slit 2: ------ pixel y value = 2048 Slit 1 data ------ (bottom) deadband ------ (top) Slit N pixel data .... ------- (bottom) pixel = 0 --------------------------------> Spectral direction 1. At the top of the flat, the slit edge is defined to be a pixel value 2. The code guesses the position of the bottom of the slit, and runs find_edge_pair to measure slit edge locations. 3. A low-order polynomial is fit to the edge locations with fit_edge_poly 4. The top and bottom of the current slit, is stored into the result list. 5. The top of the next slit is stored temporarily for the next iteration of the for loop. 6. At the bottom of the flat, the slit edge is defined to be pixel 4. options: options["edge-order"] -- The order of the polynomial [pixels] edge. options["edge-fit-width"] -- The length [pixels] of the edge to fit over ''' # TODO: move hardcoded values into Options.py # y is the location to start y = 2034 DY = 44.25 toc = 0 ssl = bs.ssl slits = [] top = [0., np.float(Options.npix)] start_slit_num = int(bs.msl[0]['Slit_Number'])-1 if start_slit_num > 0: y -= DY * start_slit_num # Count and check that the # of objects in the SSL matches that of the MSL # This is purely a safety check numslits = np.zeros(len(ssl)) for i in xrange(len(ssl)): slit = ssl[i] M = np.where(slit["Target_Name"] == bs.msl["Target_in_Slit"]) numslits[i] = len(M[0]) numslits = np.array(numslits) if (np.sum(numslits) != CSU.numslits) and (not bs.long_slit) and (not bs.long2pos_slit) and (not bs.long2pos_slit_specphot): error ("The number of allocated CSU slits (%i) does not match " " the number of possible slits (%i)." % (np.sum(numslits), CSU.numslits)) raise Exception("The number of allocated CSU slits (%i) does not match " " the number of possible slits (%i)." % (np.sum(numslits), CSU.numslits)) # if the mask is a long slit, the default y value will be wrong. Set instead to be the middle if bs.long_slit: y = 1104 # now begin steps outline above results = [] result = {} result["Target_Name"] = ssl[0]["Target_Name"] # 1 result["top"] = np.poly1d([y]) ''' Nomenclature here is confusing: ----- Edge -- Top of current slit, bottom of prev slit . o ' Data ===== Data .;.;' Data ----- Edge -- Bottom of current slit, top of next slit ''' topfun = np.poly1d([y]) xposs_top_this = np.arange(10,2000,100) yposs_top_this = topfun(xposs_top_this) for target in xrange(len(ssl)): y -= DY * numslits[target] y = max(y, 1) info("%2.2i] Finding Slit Edges for %s ending at %4.0i. Slit " "composed of %i CSU slits" % ( target, ssl[target]["Target_Name"], y, numslits[target])) ''' First deal with the current slit ''' hpps = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(target+1)[0], header, bs) if y == 1: xposs_bot = [1024] xposs_bot_missing = [] yposs_bot = [4.25] botfun = np.poly1d(yposs_bot) ok = np.where((xposs_bot > hpps[0]) & (xposs_bot < hpps[1])) else: (xposs_top_next, xposs_top_next_missing, yposs_top_next, xposs_bot, xposs_bot_missing, yposs_bot, scatter_bot_this) = find_edge_pair( data, y, options["edge-fit-width"],edgeThreshold=edgeThreshold) ok = np.where((xposs_bot > hpps[0]) & (xposs_bot < hpps[1])) ok2 = np.where((xposs_bot_missing > hpps[0]) & (xposs_bot_missing < hpps[1])) xposs_bot = xposs_bot[ok] xposs_bot_missing = xposs_bot_missing[ok2] yposs_bot = yposs_bot[ok] if len(xposs_bot) == 0: botfun = np.poly1d(y-DY) else: (botfun, bot_res, botsd, botok) = fit_edge_poly(xposs_bot, xposs_bot_missing, yposs_bot, options["edge-order"]) bot = botfun.c.copy() top = topfun.c.copy() #4 result = {} result["Target_Name"] = ssl[target]["Target_Name"] result["xposs_top"] = xposs_top_this result["yposs_top"] = yposs_top_this result["xposs_bot"] = xposs_bot result["yposs_bot"] = yposs_bot result["top"] = np.poly1d(top) result["bottom"] = np.poly1d(bot) result["hpps"] = hpps result["ok"] = ok results.append(result) #5 if y == 1: break next = target + 2 if next > len(ssl): next = len(ssl) hpps_next = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(next)[0], header, bs) ok = np.where((xposs_top_next > hpps_next[0]) & (xposs_top_next < hpps_next[1])) ok2 = np.where((xposs_top_next_missing > hpps_next[0]) & (xposs_top_next_missing < hpps_next[1])) xposs_top_next = xposs_top_next[ok] xposs_top_next_missing = xposs_top_next_missing[ok2] yposs_top_next = yposs_top_next[ok] if len(xposs_top_next) == 0: topfun = np.poly1d(y) else: (topfun, topres, topsd, ok) = fit_edge_poly(xposs_top_next, xposs_top_next_missing, yposs_top_next, options["edge-order"]) xposs_top_this = xposs_top_next xposs_top_this_missing = xposs_top_next_missing yposs_top_this = yposs_top_next results.append({"version": options["version"]}) return results
import pyfits as pf np.seterr(all='ignore') flatops = Options.flat waveops = Options.wavelength #Driver file automatically generated on Sat Jul 25 17:33:42 2015 #For questions and comments, email [email protected], submit a ticket on the ticketing system, or contact Luca Rizzi @ WMKO maskname = 'maskname' band = 'band' #Set noninteractive to True to autofit wavelenth solution instead of manually fitting. noninteractiveflag=False obsfiles=['Offset_1.25.txt','Offset_-1.25.txt'] Flats.handle_flats('Flat.txt', maskname, band, flatops) Wavelength.imcombine(obsfiles, maskname, band, waveops) Wavelength.fit_lambda_interactively(maskname, band, obsfiles,waveops, noninteractive=noninteractiveflag) Wavelength.fit_lambda(maskname, band, obsfiles, obsfiles,waveops) Wavelength.apply_lambda_simple(maskname, band, obsfiles, waveops) # modify this variable to point to the correct wavelength file created on the previous step Wavelength_file = 'lambda_solution_wave_stack_H_m141130_0323-0338.fits' Background.handle_background(obsfiles,Wavelength_file,maskname,band,waveops) redfiles = ["eps_" + file + ".fits" for file in obsfiles] Rectify.handle_rectification(maskname, redfiles,Wavelength_file,band,obsfiles,waveops)
def find_and_fit_edges(data, header, bs, options, edgeThreshold=450): ''' Given a flat field image, find_and_fit_edges determines the position of all slits. The function works by starting with a guess at the location for a slit edge in the spatial direction(options["first-slit-edge"]). Starting from the guess, find_edge_pair works out in either direction, measuring the position of the (e.g.) bottom of slit 1 and top of slit 2: ------ pixel y value = 2048 Slit 1 data ------ (bottom) deadband ------ (top) Slit N pixel data .... ------- (bottom) pixel = 0 --------------------------------> Spectral direction 1. At the top of the flat, the slit edge is defined to be a pixel value 2. The code guesses the position of the bottom of the slit, and runs find_edge_pair to measure slit edge locations. 3. A low-order polynomial is fit to the edge locations with fit_edge_poly 4. The top and bottom of the current slit, is stored into the result list. 5. The top of the next slit is stored temporarily for the next iteration of the for loop. 6. At the bottom of the flat, the slit edge is defined to be pixel 4. options: options["edge-order"] -- The order of the polynomial [pixels] edge. options["edge-fit-width"] -- The length [pixels] of the edge to fit over ''' # TODO: move hardcoded values into Options.py # y is the location to start y = 2034 DY = 44.25 toc = 0 ssl = bs.ssl slits = [] top = [0., np.float(Options.npix)] start_slit_num = int(bs.msl[0]['Slit_Number']) - 1 if start_slit_num > 0: y -= DY * start_slit_num # Count and check that the # of objects in the SSL matches that of the MSL # This is purely a safety check numslits = np.zeros(len(ssl)) for i in xrange(len(ssl)): slit = ssl[i] M = np.where(slit["Target_Name"] == bs.msl["Target_in_Slit"]) numslits[i] = len(M[0]) numslits = np.array(numslits) if (np.sum(numslits) != CSU.numslits) and (not bs.long_slit) and ( not bs.long2pos_slit) and (not bs.long2pos_slit_specphot): error("The number of allocated CSU slits (%i) does not match " " the number of possible slits (%i)." % (np.sum(numslits), CSU.numslits)) raise Exception( "The number of allocated CSU slits (%i) does not match " " the number of possible slits (%i)." % (np.sum(numslits), CSU.numslits)) # if the mask is a long slit, the default y value will be wrong. Set instead to be the middle if bs.long_slit: y = 1104 # now begin steps outline above results = [] result = {} result["Target_Name"] = ssl[0]["Target_Name"] # 1 result["top"] = np.poly1d([y]) ''' Nomenclature here is confusing: ----- Edge -- Top of current slit, bottom of prev slit . o ' Data ===== Data .;.;' Data ----- Edge -- Bottom of current slit, top of next slit ''' topfun = np.poly1d([y]) xposs_top_this = np.arange(10, 2000, 100) yposs_top_this = topfun(xposs_top_this) for target in xrange(len(ssl)): y -= DY * numslits[target] y = max(y, 1) info("%2.2i] Finding Slit Edges for %s ending at %4.0i. Slit " "composed of %i CSU slits" % (target, ssl[target]["Target_Name"], y, numslits[target])) ''' First deal with the current slit ''' hpps = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(target + 1)[0], header, bs) if y == 1: xposs_bot = [1024] xposs_bot_missing = [] yposs_bot = [4.25] botfun = np.poly1d(yposs_bot) ok = np.where((xposs_bot > hpps[0]) & (xposs_bot < hpps[1])) else: (xposs_top_next, xposs_top_next_missing, yposs_top_next, xposs_bot, xposs_bot_missing, yposs_bot, scatter_bot_this) = find_edge_pair(data, y, options["edge-fit-width"], edgeThreshold=edgeThreshold) ok = np.where((xposs_bot > hpps[0]) & (xposs_bot < hpps[1])) ok2 = np.where((xposs_bot_missing > hpps[0]) & (xposs_bot_missing < hpps[1])) xposs_bot = xposs_bot[ok] xposs_bot_missing = xposs_bot_missing[ok2] yposs_bot = yposs_bot[ok] if len(xposs_bot) == 0: botfun = np.poly1d(y - DY) else: (botfun, bot_res, botsd, botok) = fit_edge_poly(xposs_bot, xposs_bot_missing, yposs_bot, options["edge-order"]) bot = botfun.c.copy() top = topfun.c.copy() #4 result = {} result["Target_Name"] = ssl[target]["Target_Name"] result["xposs_top"] = xposs_top_this result["yposs_top"] = yposs_top_this result["xposs_bot"] = xposs_bot result["yposs_bot"] = yposs_bot result["top"] = np.poly1d(top) result["bottom"] = np.poly1d(bot) result["hpps"] = hpps result["ok"] = ok results.append(result) #5 if y == 1: break next = target + 2 if next > len(ssl): next = len(ssl) hpps_next = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(next)[0], header, bs) ok = np.where((xposs_top_next > hpps_next[0]) & (xposs_top_next < hpps_next[1])) ok2 = np.where((xposs_top_next_missing > hpps_next[0]) & (xposs_top_next_missing < hpps_next[1])) xposs_top_next = xposs_top_next[ok] xposs_top_next_missing = xposs_top_next_missing[ok2] yposs_top_next = yposs_top_next[ok] if len(xposs_top_next) == 0: topfun = np.poly1d(y) else: (topfun, topres, topsd, ok) = fit_edge_poly(xposs_top_next, xposs_top_next_missing, yposs_top_next, options["edge-order"]) xposs_top_this = xposs_top_next xposs_top_this_missing = xposs_top_next_missing yposs_top_this = yposs_top_next results.append({"version": options["version"]}) return results
As1 = ["m120604_%4.4i.fits" % i for i in range(608,648,2)] Bs1 = ["m120604_%4.4i.fits" % i for i in range(609,648,2)] wavenames1 = As1[:] ; wavenames1.extend(Bs1) As2 = ["m120604_%4.4i.fits" % i for i in range(591,604,2)] Bs2 = ["m120604_%4.4i.fits" % i for i in range(592,604,2)] wavenames2 = As2[:] ; wavenames2.extend(Bs2) # Change the bad pixel mask path # Options.path_bpm = "/scr2/mosfire/badpixels/badpix_18may2012.fits" # Change if False to if True when you want to execute that step # On interactive step, make sure you attempt to quit&save after fitting one # slit! if False: Flats.handle_flats(flatnames, maskname, band, flatops) if False: Wavelength.imcombine(wavenames1, maskname, band, wavlops) if False: Wavelength.imcombine(wavenames2, maskname, band, wavlops) # only one interactive fit is needed if False: Wavelength.fit_lambda_interactively(maskname, band, wavenames1, wavlops) # mask band to fit guess options if False: Wavelength.fit_lambda(maskname, band, wavenames1, wavenames1, wavlops) if False: Wavelength.fit_lambda(maskname, band, wavenames2, wavenames1, wavlops) if False: Wavelength.apply_lambda_simple(maskname, band, wavenames1, wavlops) if False: Wavelength.apply_lambda_simple(maskname, band, wavenames2, wavlops) As = As1[:] Bs = Bs1[:]