def is_on_target(image): ''' Add as a parameter whether the image is on target or not. ''' import coordinates_conversor as cc ra, dec = cc.hour2deg(fitsutils.get_par(image, 'OBJRA'), fitsutils.get_par(image, 'OBJDEC')) impf = fits.open(image) w = wcs.WCS(impf[0].header) filt = fitsutils.get_par(image, "FILTER") #pra, pdec = wcs.wcs_sky2pix(np.array([ra, dec], ndmin=2), 1)[0] pra, pdec = get_xy_coords(image, ra,dec) shape = impf[0].data.shape if (pra > 0) and (pra < shape[0]) and (pdec > 0) and (pdec < shape[1]): fitsutils.update_par(image, "ONTARGET", 1) return True else: fitsutils.update_par(image, "ONTARGET", 0) return False
def __combine_guiders(ifu_dic, abspath, outdir): ''' Receives an IFU dictionary with the images that need a solved guider. ''' rc = np.array(glob.glob(abspath + "/rc*fits")) rcjd = np.array([fitsutils.get_par(r, "JD") for r in rc]) imtypes = np.array([fitsutils.get_par(r, "IMGTYPE").upper() for r in rc]) objnames = np.array([fitsutils.get_par(r, "OBJECT").upper() for r in rc]) ras = np.array([cc.getDegRaString(fitsutils.get_par(r, "RA")) for r in rc]) decs = np.array( [cc.getDegDecString(fitsutils.get_par(r, "DEC")) for r in rc]) for ifu_i in ifu_dic.keys(): name, jd_ini, jd_end, rad, decd, exptime = ifu_dic[ifu_i] #guiders = rc[(imtypes=="GUIDER") * (rcjd >= ifu_dic[ifu_i][1]) * (rcjd <= ifu_dic[ifu_i][2]) ] mymask = (rcjd >= jd_ini) * (rcjd <= jd_end) *\ (np.abs(ras - rad)*np.cos(np.deg2rad(decd))<0.5/60 ) * (np.abs(decs - decd)<0.5/60 ) guiders = rc[mymask] im = imtypes[mymask] names = objnames[mymask] print("For image %s on object %s with exptime %d found guiders:\n %s" % (ifu_i, name, exptime, zip(names, im))) out = os.path.join(outdir, "guider_" + os.path.basename(ifu_i)) create_masterguide(guiders, out=out) fitsutils.update_par(out, "IFU_IMG", os.path.basename(ifu_i))
def clean_cosmic(f): ''' From lacosmic. ''' import cosmics out = f.replace('.fits', '_clean.fits') #If it does already exist, just return the name. if (os.path.isfile(out)): return out #Otherwise, run the cosmic ray rejection based on LA Cosmic. g = fitsutils.get_par(f, "GAIN") if (fitsutils.has_par(f, "RDNOISE")): rn = fitsutils.get_par(f, "RDNOISE") else: rn = 20 array, header = cosmics.fromfits(f) try: c = cosmics.cosmicsimage(array, gain=g, readnoise=rn, sigclip = 8.0, sigfrac = 0.3, satlevel = 64000.0) c.run(maxiter = 3) out = f.replace('.fits', '_clean.fits') cosmics.tofits(out, c.cleanarray, header) fitsutils.update_par(out, "CRREJ", 1) #os.remove(f) except: pass return out
def correct_files(dirname): cmd = "gethead OBJECT *fits | grep -v -i calib | grep PTF | grep -v -E \"\[A|\[B|findi\" | grep ifu | awk '{print $1}' > update_science" subprocess.all(cmd, shell=True) filelist = os.path.join(dirname, "update_science") for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "OBJDEC", fitsutils.get_par(f, "DEC")) for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "OBJRA", fitsutils.get_par(f, "RA")) for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par( f, "FILTER", fitsutils.get_par(f, "OBJECT").split()[0].replace("]", "").replace( "[", "")) for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "NAME", fitsutils.get_par(f, "OBJECT").split()[1]) for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "IMGTYPE", "SCIENCE")
def is_on_target(image): ''' Add as a parameter whether the image is on target or not. ''' import coordinates_conversor as cc ra, dec = cc.hour2deg(fitsutils.get_par(image, 'OBJRA'), fitsutils.get_par(image, 'OBJDEC')) impf = fits.open(image) w = wcs.WCS(impf[0].header) filt = fitsutils.get_par(image, "FILTER") #pra, pdec = wcs.wcs_sky2pix(np.array([ra, dec], ndmin=2), 1)[0] pra, pdec = get_xy_coords(image, ra, dec) shape = impf[0].data.shape if (pra > 0) and (pra < shape[0]) and (pdec > 0) and (pdec < shape[1]): fitsutils.update_par(image, "ONTARGET", 1) return True else: fitsutils.update_par(image, "ONTARGET", 0) return False
def correct_files(dirname): cmd = "gethead OBJECT *fits | grep -v -i calib | grep PTF | grep -v -E \"\[A|\[B|findi\" | grep ifu | awk '{print $1}' > update_science" subprocess.all(cmd, shell=True) filelist = os.path.join(dirname, "update_science") for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "OBJDEC", fitsutils.get_par(f, "DEC")) for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "OBJRA", fitsutils.get_par(f, "RA")) for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "FILTER", fitsutils.get_par(f, "OBJECT").split()[0].replace("]","").replace("[", "")) for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "NAME", fitsutils.get_par(f, "OBJECT").split()[1]) for f in np.genfromtxt(filelist, dtype=None): fitsutils.update_par(f, "IMGTYPE", "SCIENCE")
def slice_rc(img): ''' Slices the Rainbow Camera into 4 different images and adds the 'filter' keyword in the fits file. ''' fname = os.path.basename(img) fdir = os.path.dirname(img) # Running IRAF iraf.noao(_doprint=0) corners = { "g": [1, 910, 1, 900], "i": [1, 910, 1060, 2045], "r": [1040, 2045, 1015, 2045], "u": [1030, 2045, 1, 900] } filenames = [] for i, b in enumerate(corners.keys()): logger.info("Slicing for filter %s" % b) name = fname.replace(".fits", "_%s.fits" % b) #Clean first if (os.path.isfile(name)): os.remove(name) iraf.imcopy( "%s[%d:%d,%d:%d]" % (img, corners[b][0], corners[b][1], corners[b][2], corners[b][3]), name) fitsutils.update_par(name, 'filter', b) is_on_target(name) filenames.append(name) return filenames
def clean_cosmic(f): ''' From lacosmic. ''' import cosmics out = f.replace('.fits', '_clean.fits') #If it does already exist, just return the name. if (os.path.isfile(out)): return out #Otherwise, run the cosmic ray rejection based on LA Cosmic. g = fitsutils.get_par(f, "GAIN") if (fitsutils.has_par(f, "RDNOISE")): rn = fitsutils.get_par(f, "RDNOISE") else: rn = 20 array, header = cosmics.fromfits(f) try: c = cosmics.cosmicsimage(array, gain=g, readnoise=rn, sigclip=8.0, sigfrac=0.3, satlevel=64000.0) c.run(maxiter=3) out = f.replace('.fits', '_clean.fits') cosmics.tofits(out, c.cleanarray, header) fitsutils.update_par(out, "CRREJ", 1) #os.remove(f) except: pass return out
def slice_rc(img): ''' Slices the Rainbow Camera into 4 different images and adds the 'filter' keyword in the fits file. ''' fname = os.path.basename(img) fdir = os.path.dirname(img) # Running IRAF iraf.noao(_doprint=0) '''f = pf.open(img) h = f[0].header i = f[0].data[1000:-1,0:920] g = f[0].data[0:910,0:900] r = f[0].data[1035:2046, 1050:2046] u = f[0].data[0:910,1050:2046]''' corners = { "i" : [1, 910, 1, 900], "g" : [1, 910, 1060, 2045], "r" : [1040, 2045, 1015, 2045], "u" : [1030, 2045, 1, 900] } filenames = [] for i, b in enumerate(corners.keys()): name = fname.replace(".fits", "_%s.fits"%b) iraf.imcopy("%s[%d:%d,%d:%d]"%(img, corners[b][0], corners[b][1], corners[b][2], corners[b][3]), name) fitsutils.update_par(name, 'filter', b) filenames.append(name) return filenames
def slice_rc(img): ''' Slices the Rainbow Camera into 4 different images and adds the 'filter' keyword in the fits file. ''' fname = os.path.basename(img) fdir = os.path.dirname(img) # Running IRAF iraf.noao(_doprint=0) corners = { "g" : [1, 910, 1, 900], "i" : [1, 910, 1060, 2045], "r" : [1040, 2045, 1015, 2045], "u" : [1030, 2045, 1, 900] } filenames = [] for i, b in enumerate(corners.keys()): logger.info( "Slicing for filter %s"% b) name = fname.replace(".fits", "_%s.fits"%b) #Clean first if (os.path.isfile(name)): os.remove(name) iraf.imcopy("%s[%d:%d,%d:%d]"%(img, corners[b][0], corners[b][1], corners[b][2], corners[b][3]), name) fitsutils.update_par(name, 'filter', b) is_on_target(name) filenames.append(name) return filenames
def reset_zp(directory): """ Resets the zeropoint keyword to if the result is interpolated. """ files = glob.glob(directory + "/*fits") for f in files: if fitsutils.get_par(f, "ZPCAT") == "SDSSinterpolated": fitsutils.update_par(f, "IQZEROPT", 0) fitsutils.update_par(f, "ZEROPT", 0) fitsutils.update_par(f, "ZEROPTU", 0)
def reduce_image(img, flatdir=None, biasdir=None, cosmic=True, astrometry=True, channel='rc', target_dir='reduced'): ''' Applies Flat field and bias calibrations to the image. Steps: 1. - Solve astrometry on the entire image. 2. - Compute master bias and de-bias the image. 3. - Separate the image into 4 filters. 4. - Compute flat field for each filter and apply flat fielding on the image. 5. - Computes cosmic ray rejectionon the entire image. 6. - Compute zeropoint for each image and store in a log file. 7. - Plot zeropoint for the night. ''' print "Reducing image ", img objectname = fitsutils.get_par(img, "OBJECT").replace(" ", "").replace("]","").replace("[", "") print "For object", objectname #Change to image directory mydir = os.path.dirname(img) if mydir=="": mydir = "." mydir = os.path.abspath(mydir) os.chdir(mydir) #Create destination directory if (not os.path.isdir(target_dir)): os.makedirs(target_dir) #Rename to the image name only img = os.path.basename(img) if (astrometry): print "Solving astometry for the whole image..." img = solve_astrometry(img) astro = "a_" else: astro = "" #Compute BIAS if (biasdir == None or biasdir==""): biasdir = "." create_masterbias(biasdir) bias_slow = os.path.join(biasdir, "Bias_%s_%s.fits"%(channel, 'slow')) bias_fast = os.path.join(biasdir, "Bias_%s_%s.fits"%(channel, 'fast')) # Running IRAF to DE-BIAS iraf.noao(_doprint=0) iraf.imred(_doprint=0) iraf.ccdred(_doprint=0) #Compute flat field if (flatdir == None or flatdir==""): flatdir = "." create_masterflat(flatdir, biasdir) #New names for the object. debiased = "b_" + astro + img print "Creating debiased file, ",debiased if (not os.path.isfile(bias_slow) or not os.path.isfile(bias_fast)): print "Master bias not found!" return #Debias if (fitsutils.get_par(img, "ADCSPEED")==2): iraf.imarith(img, "-", bias_fast, debiased) fitsutils.update_par(debiased, "BIASFILE", bias_fast) fitsutils.update_par(debiased, "RDNOISE", 20.) else: iraf.imarith(img, "-", bias_slow, debiased) fitsutils.update_par(debiased, "BIASFILE", bias_slow) fitsutils.update_par(debiased, "RDNOISE", 4.) #Set negative counts to zero hdu = pf.open(debiased) header = hdu[0].header hdu[0].data[hdu[0].data<0] = 0 hdu.writeto(debiased, clobber=True) #Slicing the image for flats slice_names = slice_rc(debiased) #Remove un-sliced image os.remove(debiased) # DE-flat each filter and store under object name for i, debiased_f in enumerate(slice_names): b = fitsutils.get_par(debiased_f, 'filter') deflatted = "f_b_" + astro + objectname + "_%s.fits"%b #Flat to be used for that filter flat = os.path.join(flatdir, "Flat_%s_%s_norm.fits"%(channel, b)) if (not os.path.isfile(flat)): print "Master flat not found in", flat return #Cleans the deflatted file if exists if (os.path.isfile(deflatted)): os.remove(deflatted) iraf.imarith(debiased_f, "/", flat, deflatted) #Removes the de-biased file os.remove(debiased_f) print "Updating header with original filename and flat field used." fitsutils.update_par(deflatted, "ORIGFILE", img) fitsutils.update_par(deflatted, "FLATFILE", flat) slice_names[i] = deflatted if (cosmic): print "Correcting for cosmic rays..." # Correct for cosmics each filter for i, deflatted in enumerate(slice_names): cclean = "c_" +name clean_cosmic(os.path.join(os.path.abspath(mydir), deflatted), cclean) slice_names[i] = cclean #Moving files to the target directory for name in slice_names: if (os.path.isfile(name)): shutil.move(name, os.path.join(target_dir, name))
def find_zeropoint_noid(ref_stars, image, plot=True, plotdir="."): """ Finds the zeropoint by comparig the magnitude of the stars measured in the image, vs. the magnitude of the stars from the reference catalogue. band: band for which we want to measure the zeropoint. col_band: band for the colour term we want to use. returns the zeropoint, the colour term and the standard deviation in the zeropoint from all the measured stars. """ logger.info("Finding the optimum ZP fit...") logger.info("Reference stars used: %s" % ref_stars) r = np.genfromtxt(ref_stars, delimiter=" ", dtype=None, names=True) imapp = os.path.join(os.path.join(os.path.dirname(image), "photometry"), os.path.basename(image) + ".app.mag") # imapp = os.path.join(os.path.dirname(image), os.path.basename(image) + ".app.mag") my = np.genfromtxt( imapp, comments="#", dtype=[ ("id", "<f4"), ("image", "|S20"), ("X", "<f4"), ("Y", "<f4"), ("Xshift", "<f4"), ("Yshift", "<f4"), ("fwhm", "<f4"), ("ph_mag", "<f4"), ("stdev", "<f4"), ("fit_mag", "<f4"), ("fiterr", "<f4"), ], ) """try: except: my = np.genfromtxt(imapp, comments="#", dtype=[("id","<f4"), ("X","<f4"), ("Y","<f4"),("Xshift","<f4"), ("Yshift","<f4"),("fwhm","<f4"), ("ph_mag","<f4"), ("stdev","<f4"), ("fit_mag","<f4"), ("fiterr","<f4")]) """ if my.size < 2: my = np.array([my]) if r.size < 2: r = np.array([r]) coldic = {"u": "g", "g": "r", "r": "i", "i": "z", "z": "i", "U": "B", "B": "V", "V": "R", "R": "I", "I": "R"} band = fitsutils.get_par(image, "filter") col_band = coldic[band] mask_valid1 = ( np.array(my["fwhm"] < 9000) * np.array(my["ph_mag"] < 9000) * np.array(~np.isnan(r[band])) * np.array(~np.isnan(my["fit_mag"])) ) N = len(r) r = r[mask_valid1] my = my[mask_valid1] if len(my) == 0: logger.warn("Warning, no reliable measurements for file %s. Returning 0,0,0." % image) return 0, 0, 0 my["fiterr"][np.isnan(my["fiterr"])] = 100 ids = np.arange(N) + 1 ids = ids[mask_valid1] coefs, residuals, rank, singular_values, rcond = np.polyfit( r[band] - r[col_band], r[band] - my["fit_mag"], w=1.0 / np.maximum(0.1, np.sqrt(my["fiterr"] ** 2 + r["d" + band] ** 2)), deg=1, full=True, ) p = np.poly1d(coefs) logger.info("Coefficients for 1 deg polynomial fit to the zeropoint: %s" % coefs) logger.info("%s - %s = %.3f, %.3f" % (band, col_band, p[0], p[1])) pred = p(r[band] - r[col_band]) measured = r[band] - my["fit_mag"] mad = stats.funcs.median_absolute_deviation(pred - measured) print "MAD1", mad if len(r) > 4: mask = np.abs(pred - measured) / mad < 3 r = r[mask] my = my[mask] ids = ids[mask] coefs, residuals, rank, singular_values, rcond = np.polyfit( r[band] - r[col_band], r[band] - my["fit_mag"], w=1.0 / np.maximum(0.2, np.sqrt(my["fiterr"] ** 2 + r["d" + band] ** 2)), deg=1, full=True, ) logger.info("Coefficients for 1 deg polynomial fit to the zeropoint: %s. After outlier rejection." % coefs) p = np.poly1d(coefs) pred = p(r[band] - r[col_band]) measured = r[band] - my["fit_mag"] mad = stats.funcs.median_absolute_deviation(pred - measured) print "MAD2", mad if plot: print "Plotting..." plt.errorbar( r[band] - r[col_band], r[band] - my["fit_mag"], yerr=np.sqrt(my["fiterr"] ** 2 + r["d" + band] ** 2), marker="o", ls="None", ) for i, myid in enumerate(ids): plt.text(r[band][i] - r[col_band][i] + 0.01, r[band][i] - my["fit_mag"][i] + 0.01, str(myid)) x = np.linspace(np.min(r[band] - r[col_band]), np.max(r[band] - r[col_band]), 100) plt.plot(x, p(x)) plt.title("Best fit ZP: %.2f colour term: %.2f MAD: %.2f" % (p[0], p[1], mad)) plt.xlabel("{:} - {:}".format(band, col_band)) plt.ylabel("ZP") plt.savefig( os.path.join(plotdir, os.path.basename(image).replace(".fits", ".zp.png").replace(".new", ".zp.png")) ) plt.clf() logger.info("%s - %s = %.3f, %.3f" % (band, col_band, p[0], p[1])) pred = p(r[band] - r[col_band]) measured = r[band] - my["fit_mag"] fitsutils.update_par(image, "ZP", np.round(p[0], 3)) fitsutils.update_par(image, "COLTERM", np.round(p[1], 3)) fitsutils.update_par(image, "ZPERR", np.round(mad, 3)) # np.std(pred - measured)) return np.round(p[0], 3), np.round(p[1], 3), np.round(mad, 3)
def get_app_phot_target(image, plot=False, store=True, wcsin="logical", fwhm=2, box=4, ra=None, dec=None): ''' coords: files: wcsin: can be "world", "logic" ''' # Load packages; splot is in the onedspec package, which is in noao. # The special keyword _doprint=0 turns off displaying the tasks # when loading a package. with warnings.catch_warnings(): warnings.simplefilter("ignore") fxn() iraf.noao(_doprint=0) iraf.digiphot(_doprint=0) iraf.apphot(_doprint=0) iraf.unlearn("apphot") impf = pf.open(image) wcs = pywcs.WCS(impf[0].header) #Check that actually the object is within this frame. if (ra is None or dec is None): if (fitsutils.has_par(image, "OBJRA") and fitsutils.has_par(image, "OBJRA")): ra, dec = cc.hour2deg(fitsutils.get_par(image, 'OBJRA'), fitsutils.get_par(image, 'OBJDEC')) else: ra, dec = cc.hour2deg(fitsutils.get_par(image, 'RA'), fitsutils.get_par(image, 'DEC')) pra, pdec = get_xy_coords(image, ra, dec) else: if(wcsin == "logical"): pra, pdec = ra, dec else: #Using new method to derive the X, Y pixel coordinates, as pywcs does not seem to be working well. pra, pdec = get_xy_coords(image, ra, dec) #pra, pdec = wcs.wcs_sky2pix(ra, dec, 1) #pra, pdec = wcs.wcs_sky2pix(np.array([ra, dec], ndmin=2), 1)[0] shape = impf[0].data.shape if (pra > 0) and (pra < shape[0]) and (pdec > 0) and (pdec < shape[1]): pass else: print image, "ERROR! Object coordinates are outside this frame. Skipping any aperture photometry!!" print pra, pdec, shape return imdir = os.path.dirname(image) imname = os.path.basename(image) plotdir = os.path.join(imdir, "photometry") if not os.path.isdir(plotdir): os.makedirs(plotdir) out_name = os.path.join(plotdir, imname + ".seq.mag") clean_name = os.path.join(plotdir, imname + ".objapp.mag") fwhm_value = fwhm nsrc, fwhm_value, ellip = sextractor.get_image_pars(image) if np.isnan(fwhm_value): fwhm_value=99 fitsutils.update_par(image, 'FWHM', fwhm_value) if (fitsutils.has_par(image, 'AIRMASS')): airmass_value = fitsutils.get_par(image, 'AIRMASS') else: airmass_value = 1.3 exptime = fitsutils.get_par(image, 'EXPTIME') gain = fitsutils.get_par(image, 'GAIN') #print "FWHM", fwhm_value aperture_rad = math.ceil(float(fwhm_value)*3) # Set aperture radius to three times the PSF radius sky_rad= math.ceil(aperture_rad*4) #print aperture_rad, sky_rad print "Saving coodinates for the object in pixels",pra,pdec coords = "/tmp/coords.dat" np.savetxt("/tmp/coords.dat", np.array([[pra, pdec]]), fmt="%.4f %.4f") if (plot): zmin, zmax = zscale.zscale(impf[0].data) im = plt.imshow(impf[0].data, vmin=zmin, vmax=zmax, origin="bottom") plt.scatter(pra, pdec, marker="o", s=100, facecolor="none") plt.savefig(os.path.join(plotdir, imname+".png")) plt.clf() if os.path.isfile(out_name): os.remove(out_name) if os.path.isfile(clean_name): os.remove(clean_name) iraf.noao.digiphot.apphot.qphot(image = image,\ cbox = box ,\ annulus = sky_rad ,\ dannulus = 15. ,\ aperture = str(aperture_rad),\ coords = coords ,\ output = out_name ,\ plotfile = "" ,\ zmag = 0. ,\ exposure = "exptime" ,\ airmass = "airmass" ,\ filter = "filter" ,\ obstime = "DATE" ,\ epadu = gain ,\ interactive = "no" ,\ radplots = "yes" ,\ verbose = "no" ,\ graphics = "stdgraph" ,\ display = "stdimage" ,\ icommands = "" ,\ wcsin = "logical", wcsout = "logical", gcommands = "") #iraf.noao.digiphot.apphot.phot(image=image, cbox=5., annulus=12.4, dannulus=10., salgori = "centroid", aperture=9.3,wcsin="world",wcsout="tv", interac = "no", coords=coords, output=out_name) iraf.txdump(out_name, "id,image,xcenter,ycenter,xshift,yshift,fwhm,msky,stdev,mag,merr", "yes", Stdout=clean_name) ma = np.genfromtxt(clean_name, comments="#", dtype=[("id","<f4"), ("image","|S20"), ("X","<f4"), ("Y","<f4"), ("Xshift","<f4"), ("Yshift","<f4"),("fwhm","<f4"), ("ph_mag","<f4"), ("stdev","<f4"), ("fit_mag","<f4"), ("fiterr","<f4")]) if (ma.size > 0): if (ma.size==1): ma = np.array([ma]) m = ma[~np.isnan(ma["fit_mag"])] else: print "Only one object found!" m = np.array([ma]) insmag = np.round(ma['fit_mag'][0] , 3) insmagerr = np.round(ma['fiterr'][0], 3) if (fitsutils.has_par(image, "ZEROPT")): mag = insmag + float(fitsutils.get_par(image, "ZEROPT")) magerr = np.sqrt(insmagerr**2+ float(fitsutils.get_par(image, "ZEROPTU"))**2) if np.isnan(mag): mag, magerr = 0, 0 insmag, insmagerr = 0,0 fitsutils.update_par(image, "INSMAG", "%.3f"%insmag ) fitsutils.update_par(image, "INSMAGER", "%.3f"%insmagerr) fitsutils.update_par(image, "APPMAG", np.round(mag, 3) ) fitsutils.update_par(image, "APPMAGER", np.round(magerr, 3)) if (plot): X = int(ma["X"][0]) Y = int(ma["Y"][0]) pra = int(pra) pdec = int(pdec) plt.scatter(X, Y, marker="o", s=100, facecolor="none", edgecolor="red") plt.colorbar(im) plt.savefig(os.path.join(plotdir, imname+".png")) plt.clf() zmin, zmax = zscale.zscale(impf[0].data.T[X-50:X+50,Y-50:Y+50].T) im = plt.imshow(impf[0].data.T[pra-50:pra+50,pdec-50:pdec+50].T, vmin=zmin, vmax=zmax, interpolation="none", origin="bottom", extent=(-50,50,-50,50)) c1 = plt.Circle( (pra-X, pdec-Y), edgecolor="k", facecolor="none", radius=aperture_rad, label="Initial position") c11 = plt.Circle( (pra-X, pdec-Y), edgecolor="k", facecolor="none", radius=sky_rad) c2 = plt.Circle( (0, 0), edgecolor="orange", facecolor="none", radius=aperture_rad, label="Adjusted centroid") c22 = plt.Circle( (0, 0), edgecolor="orange", facecolor="none", radius=sky_rad) plt.gca().add_artist(c1) plt.gca().add_artist(c11) plt.gca().add_artist(c2) plt.gca().add_artist(c22) plt.colorbar(im) myhandles = [] markers = ["o", "o"] labels = ["Initial position", "Adjusted centroid"] cols = ["k", "orange"] for i in np.arange(len(markers)): myhandles.append(mlines.Line2D([], [], mec=cols[i], mfc="none", marker=markers[i], ls="None", markersize=10, label=labels[i])) plt.legend(handles=myhandles, loc="lower left", labelspacing=0.3, fontsize=11, numpoints=1, frameon=False, ncol=5, bbox_to_anchor=(0.0, 0.00), fancybox=False, shadow=True) plt.title("MIN: %.0f MAX: %.0f"%(np.nanmin(impf[0].data.T[X-50:X+50,Y-50:Y+50]), np.nanmax(impf[0].data.T[X-50:X+50,Y-50:Y+50]))) plt.savefig(os.path.join(plotdir, imname+"_zoom.png")) plt.clf()
def extract_star_sequence(imfile, band, plot=True, survey="sdss", debug=False, refstars=None, plotdir="."): """ Given a fits image: imfile and a the name of the band which we want to extract the sources from, it saves the extracted sources into '/tmp/sdss_cat_det.txt' file. If the band does not match the bands in the survey, a change is performed to adapt to the new band. If plotting activated, plots the USNOB1 field of stars on top of the star field image. Red circles are stars identified from the catalogue in the correct magnitude range. Yellow circles are stars that are isolated. """ survey = str.lower(survey) minmag = 15 maxmag = 21.0 f = pf.open(imfile) wcs = pywcs.WCS(f[0].header) img = f[0].data img[img < 0] = 0 ra, dec = wcs.wcs_pix2sky(np.array([img.shape[0] / 2, img.shape[1] / 2], ndmin=2), 1)[0] ra0, dec0 = wcs.wcs_pix2sky(np.array([img.shape[0], img.shape[1]], ndmin=2), 1)[0] sr = 2 * np.abs(dec - dec0) logger.info("%.4f %.4f %.4f" % (ra, dec, sr)) if not refstars is None: shutil.copy(refstars, "/tmp/tmp_sdss_%s.cat" % creationdate) catalog = np.genfromtxt("/tmp/tmp_sdss_%s.cat" % creationdate, names=True, dtype=None, delimiter=",") cat_ra = catalog["ra"] cat_dec = catalog["dec"] try: mag = catalog["R"] except: mag = catalog["r"] elif str.lower(survey) == "usnob1": # ra, dec = coordinates_conversor.hour2deg(f[0].header['RA'], f[0].header['DEC']) # SEDM FoV is 6.5 arcmin, due to uncertainties in the position, 4 arcmin radius assumed. # Download USNO-B1 catalog for the position catalog_url = "http://www.nofs.navy.mil/cgi-bin/vo_cone.cgi?CAT=USNO-B1&RA=%.5f&DEC=%.5f&SR=%.4f&VERB=1" % ( ra, dec, sr, ) logger.info("Downloading USNO-B1 catalog...") urllib.urlretrieve(catalog_url, "/tmp/tmp_%s.cat" % creationdate) # Read RA, Dec and magnitude from XML format USNO catalog catalog = parse_single_table("/tmp/tmp_%s.cat" % creationdate) cat_ra = catalog.array["RA"].data cat_dec = catalog.array["DEC"].data cat_R1mag = catalog.array["R1"].data cat_R2mag = catalog.array["R2"].data cat_B1mag = catalog.array["B1"].data cat_B2mag = catalog.array["B2"].data cat_I2mag = catalog.array["I2"].data cat_R1mag[cat_R1mag == 0] = np.nan cat_R2mag[cat_R2mag == 0] = np.nan cat_B1mag[cat_B1mag == 0] = np.nan cat_B2mag[cat_B2mag == 0] = np.nan cat_I2mag[cat_I2mag == 0] = np.nan Bmag = np.nanmean(np.array([cat_B1mag, cat_B2mag]), axis=0) Rmag = np.nanmean(np.array([cat_R1mag, cat_R2mag]), axis=0) Imag = cat_I2mag mag = Rmag elif survey == "apass": # Download USNO-B1 catalog for the position catalog_url = "https://www.aavso.org/cgi-bin/apass_download.pl?ra=%.5f&dec=%.5f&radius=%.4f8&outtype=1" % ( ra, dec, sr, ) print "Downloading APASS catalog..." urllib.urlretrieve(catalog_url, "/tmp/tmp_apass_%s.cat" % creationdate) catalog = np.genfromtxt("/tmp/tmp_apass_%s.cat" % creationdate, delimiter=",", names=True) if np.ndim(catalog) == 0: return False cat_ra = catalog["radeg"] cat_dec = catalog["decdeg"] mag = catalog["Sloan_r"] elif survey == "sdss": minmag = 15 maxmag = 21.5 catalog_url = ( "http://skyserver.sdss.org/dr9/en/tools/search/x_radial.asp?ra=%.5f&dec=%.5f&check_type=type&type=6&radius=%.4f&check_u=u&min_u=%.2f&max_u=%.2f&check_g=g&min_g=%.2f&max_g=%.2f&check_r=r&min_r=%.2f&max_r=%.2f&check_i=i&min_i=%.2f&max_i=%.2f&check_z=z&min_z=%.2f&max_z=%.2f&entries=top&topnum=500&format=csv" % (ra, dec, sr * 60, minmag, maxmag, minmag, maxmag, minmag, maxmag, minmag, maxmag, minmag, maxmag) ) logger.info("Downloading SDSS catalog...") logger.info("%s" % catalog_url) urllib.urlretrieve(catalog_url, "/tmp/tmp_sdss_%s.cat" % creationdate) catalog = np.genfromtxt("/tmp/tmp_sdss_%s.cat" % creationdate, delimiter=",", names=True) if np.ndim(catalog) == 0: return False try: cat_ra = np.array(catalog["ra"], ndmin=1) cat_dec = np.array(catalog["dec"], ndmin=1) if band in catalog.dtype.names: print "SDSS filter detected" mag = np.array(catalog[band], ndmin=1) elif band in ["U", "B", "V", "R", "I", "Z"]: print "Johnson filter detected." john = transformations.sdss2johnson( "/tmp/tmp_sdss_%s.cat" % creationdate, savefile="/tmp/tmp_sdss_%s.cat" % creationdate ) mag = john[band] catalog = np.genfromtxt("/tmp/tmp_sdss_%s.cat" % creationdate, dtype=None, names=True, delimiter=",") else: print "Unknown band!!", band except IOError: logger.error("Problems with SDSS image %s" % band) return False except ValueError: logger.error("Problems with the catalogue for the image") return False # Convert ra, dec position of all stars to pixels. star_pix = np.array([0, 0]) for i in range(len(cat_ra)): # Get pixel coordinates of USNO stars s = wcs.wcs_sky2pix(np.array([cat_ra[i], cat_dec[i]], ndmin=2), 1)[0] star_pix = np.row_stack((star_pix, s)) star_pix = star_pix[1:] pix2ang = 0.394 rad = math.ceil(25.0 / pix2ang) # Select only the stars within the image. mask = ( (star_pix[:, 0] > -rad) * (star_pix[:, 0] < img.shape[1] + rad) * (star_pix[:, 1] > -rad) * (star_pix[:, 1] < img.shape[0] + rad) ) if band == "u": mask = mask * (mag < 19) # Select only stars isolated in a radius of ~12 arcsec. mask2 = np.array(are_isolated(cat_ra[mask], cat_dec[mask], 15.0)) if len(mask2) == 0: logger.error("No good stars left") return False # Select only stars that are within the proper magnitude range mask3 = (mag[mask][mask2] < maxmag) * (mag[mask][mask2] > minmag) mask3 = ( mask3 * (star_pix[:, 0][mask][mask2] > rad) * (star_pix[:, 0][mask][mask2] < img.shape[1] - rad) * (star_pix[:, 1][mask][mask2] > rad) * (star_pix[:, 1][mask][mask2] < img.shape[0] - rad) ) if survey == "usnob1": output = np.column_stack( ( star_pix[:, 0][mask][mask2][mask3], star_pix[:, 0][mask][mask2][mask3], cat_ra[mask][mask2][mask3], cat_dec[mask][mask2][mask3], Bmag[mask][mask2][mask3], Rmag[mask][mask2][mask3], Imag[mask][mask2][mask3], ) ) np.savetxt("/tmp/usnob1_cat.txt", output, fmt="%.5f %.5f %.5f %.5f %.5f %.5f %.5f", header="#X Y ra dec B R I") print "Saved to", "/tmp/usnob1_cat.txt" elif survey == "apass": if not np.any(mask2) and not np.any(mask3): print star_pix print "No stars left...", mask, mask2, mask3 return else: print catalog[mask][mask2][mask3] catalog = catalog[mask][mask2][mask3] s = star_pix[mask][mask2][mask3] z = np.zeros(len(s), dtype=[("x", "f8"), ("y", "f8")]) z["x"] = s[:, 0] z["y"] = s[:, 1] for n in catalog.dtype.names: z = rfn.append_fields(z, names=n, data=catalog[n], usemask=False) fmt = "%.5f" for i in range(len(z[0]) - 1): fmt += " %.5f" np.savetxt( "/tmp/apass_cat.txt", z, fmt=fmt, header="x y radeg raerr decdeg decerr number_of_Obs V dV B dB g dg r dr i di", ) print "Saved to", "/tmp/apass_cat.txt" elif survey == "sdss": if (not np.any(mask) and not np.any(mask2) and not np.any(mask3)) or len(catalog[mask][mask2][mask3]) == 0: print star_pix print "No stars left...", mask, mask2, mask3 return False else: catalog = catalog[mask][mask2][mask3] s = star_pix[mask][mask2][mask3] print "left %d stars" % (len(catalog)), catalog.dtype.names z = np.zeros(len(s), dtype=[("x", "f8"), ("y", "f8")]) z["x"] = s[:, 0] z["y"] = s[:, 1] header = "x y " for n in catalog.dtype.names: if n in [ "objid", "ra", "dec", "u", "g", "r", "i", "z", "Err_u", "Err_g", "Err_r", "Err_i", "Err_z", ] or n in ["id", "ra", "dec", "U", "B", "V", "R", "I", "dU", "dB", "dV", "dR", "dI"]: z = rfn.append_fields(z, names=n, data=catalog[n], usemask=False) header += n.replace("Err_", "d") + " " fmt = "%.5f" for i in range(len(z[0]) - 1): fmt += " %.5f" np.savetxt("/tmp/sdss_cat_%s.txt" % creationdate, z, fmt=fmt, header=header) logger.info("Saved catalogue stars to %s" % ("/tmp/sdss_cat_%s.txt" % creationdate)) # Find FWHM for this image out = find_fwhm(imfile, star_pix[:, 1][mask][mask2][mask3], star_pix[:, 0][mask][mask2][mask3], plot=debug) mask_valid_fwhm = (out["detected"]) * (out["e"] > 0.6) * ~np.isnan(out["fwhm"] * (out["fwhm"] < 30)) if ((np.count_nonzero(mask_valid_fwhm) < 3) and (fitsutils.get_par(imfile, "FILTER") != "u")) or ( (np.count_nonzero(mask_valid_fwhm) < 2) and (fitsutils.get_par(imfile, "FILTER") == "u") ): logger.error( "ERROR with FWHM!! Too few points for a valid estimation. %d" % np.count_nonzero(mask_valid_fwhm) + ") points" ) logger.error("%s %s" % (out["detected"], out["fwhm"])) return False outd = out[mask_valid_fwhm] logger.info( "Average FWHM %.3f arcsec, %.3f pixels" % (np.median(outd["fwhm"]), np.median(outd["fwhm"]) * pix2ang) ) fwhm = np.percentile(outd["fwhm"], 40) fitsutils.update_par(imfile, "FWHM", np.round(fwhm, 3)) if band in "ugriz": header = "x y objid ra dec u g r i z du dg dr di dz" elif band in "UBVRI": header = "x y objid ra dec U B V R I dU dB dV dR dI" np.savetxt("/tmp/sdss_cat_det_%s.txt" % creationdate, z[mask_valid_fwhm], fmt=fmt, header=header) print "Saved to", "/tmp/sdss_cat_det_%s.txt" % creationdate # Plot results img = img - np.nanmin(img) zmin, zmax = zscale.zscale(img) logger.info( "Found %d stars in %s. " % (len(cat_dec), survey) + "%d of them within the FoV. " % len(cat_ra[mask]) + "%d of them are isolated." % len(cat_ra[mask][mask2]) + "%d of them with suitable magnitudes. " % len(cat_ra[mask][mask2][mask3]) + "%d of them with detected stars." % np.count_nonzero(mask_valid_fwhm) ) if plot: im = plt.imshow( img, aspect="equal", origin="lower", cmap=matplotlib.cm.gray_r, interpolation="none", vmin=zmin, vmax=zmax ) if len(star_pix[:, 0][mask]) > 0: plt.scatter( star_pix[:, 0][mask], star_pix[:, 1][mask], marker="o", s=np.minimum(150, 10000 * (10.0 / mag[mask][mask2]) ** 9), edgecolor="red", facecolor="none", label="catalogue", ) if len(star_pix[:, 0][mask][mask2]) > 0: plt.scatter( star_pix[:, 0][mask][mask2], star_pix[:, 1][mask][mask2], marker="o", s=20, edgecolor="yellow", facecolor="none", label="isolated", ) if len(star_pix[:, 0][mask][mask2][mask3]) > 0: plt.scatter( star_pix[:, 0][mask][mask2][mask3], star_pix[:, 1][mask][mask2][mask3], marker="o", s=200, edgecolor="green", facecolor="none", label="wihtin farme and mag", ) selected = star_pix[:, :][mask][mask2][mask3][mask_valid_fwhm] if len(selected) > 0: plt.scatter(selected[:, 0], selected[:, 1], marker="o", s=400, edgecolor="blue", facecolor="none") for i in np.arange(len(selected)): plt.text(selected[i, 0] + 10, selected[i, 1] + 10, i + 1) plt.legend(loc="best", frameon=False, framealpha=0.9) plt.savefig( os.path.join( plotdir, os.path.basename(imfile).replace(".fits", ".seqstars.png").replace(".new", ".seqstars.png") ) ) logger.info("Saved stars to %s" % imfile.replace(".fits", ".seqstars.png")) plt.clf() return True
def get_app_phot_target(image, ra=None, dec=None, plot=True, store=True, wcsin="logical", fwhm=None, box=15, arcsecpix=0.394, app=2): ''' coords: files: wcsin: can be "world", "logic" fwhm: in arcsec ''' # Load packages; splot is in the onedspec package, which is in noao. # The special keyword _doprint=0 turns off displaying the tasks # when loading a package. with warnings.catch_warnings(): warnings.simplefilter("ignore") fxn() iraf.noao(_doprint=0) iraf.digiphot(_doprint=0) iraf.apphot(_doprint=0) iraf.unlearn("apphot") impf = pf.open(image) wcs = WCS(impf[0].header) #Check that actually the object is within this frame. if (ra is None or dec is None): if (fitsutils.has_par(image, "OBJRA") and fitsutils.has_par(image, "OBJRA")): ra, dec = cc.hour2deg(fitsutils.get_par(image, 'OBJRA'), fitsutils.get_par(image, 'OBJDEC')) else: ra, dec = cc.hour2deg(fitsutils.get_par(image, 'RA'), fitsutils.get_par(image, 'DEC')) print "Assuming ra=%.5f, dec=%.5f"%(ra, dec) pra, pdec = get_xy_coords(image, ra, dec) else: if("logic" in wcsin): pra, pdec = ra, dec else: #Using new method to derive the X, Y pixel coordinates, as wcs module does not seem to be working well. try: #pra, pdec = wcs.wcs_sky2pix(ra, dec, 1) #print "Retrieved the pixel number" pra, pdec = get_xy_coords(image, ra, dec) except IndexError: print "Error with astrometry.net. trying the rudimentary method." pra, pdec = wcs.wcs_sky2pix(ra, dec, 1) #pra, pdec = wcs.wcs_sky2pix(np.array([ra, dec], ndmin=2), 1)[0] shape = impf[0].data.shape if (pra > 0) and (pra < shape[0]) and (pdec > 0) and (pdec < shape[1]): pass else: print image, "ERROR! Object coordinates are outside this frame. Skipping any aperture photometry!!" print pra, pdec, shape return imdir = os.path.dirname(image) imname = os.path.basename(image) plotdir = os.path.join(imdir, "photometry") if not os.path.isdir(plotdir): os.makedirs(plotdir) out_name = os.path.join(plotdir, imname + ".seq.mag") clean_name = os.path.join(plotdir, imname + ".objapp.mag") if (not fwhm is None): fwhm_value = fwhm elif (fitsutils.has_par(image, 'FWHM')): fwhm_value = fitsutils.get_par(image, 'FWHM') else: #Put some default value for Palomar fwhm_value=1.5 if (wcsin == 'logical'): fwhm_value = fwhm_value / arcsecpix if (fitsutils.has_par(image, 'AIRMASS')): airmass_value = fitsutils.get_par(image, 'AIRMASS') else: airmass_value = 1.3 if (not fitsutils.has_par(image, "EXPTIME")): if (fitsutils.has_par(image, "ITIME") and fitsutils.has_par(image, "COADDS")): exptime = fitsutils.get_par(image, "ITIME")*fitsutils.get_par(image, "COADDS") fitsutils.update_par(image, "EXPTIME", exptime) exptime = fitsutils.get_par(image, 'EXPTIME') gain = fitsutils.get_par(image, 'GAIN') #print "FWHM", fwhm_value aperture_rad = math.ceil(float(fwhm_value)*app) # Set aperture radius to two times the PSF radius sky_rad= math.ceil(aperture_rad*app*2) #print aperture_rad, sky_rad print "Saving coodinates for the object in pixels",pra,pdec coords = "/tmp/coords.dat" np.savetxt("/tmp/coords.dat", np.array([[pra, pdec]]), fmt="%.4f %.4f") if os.path.isfile(out_name): os.remove(out_name) if os.path.isfile(clean_name): os.remove(clean_name) iraf.noao.digiphot.apphot.qphot(image = image,\ cbox = box ,\ annulus = sky_rad ,\ dannulus = 20. ,\ aperture = str(aperture_rad),\ coords = coords ,\ output = out_name ,\ plotfile = "" ,\ zmag = 0. ,\ exposure = "exptime" ,\ airmass = "airmass" ,\ filter = "filter" ,\ obstime = "DATE" ,\ epadu = gain ,\ interactive = "no" ,\ radplots = "yes" ,\ verbose = "no" ,\ graphics = "stdgraph" ,\ display = "stdimage" ,\ icommands = "" ,\ wcsin = "logical", wcsout = "logical", gcommands = "") #iraf.noao.digiphot.apphot.phot(image=image, cbox=5., annulus=12.4, dannulus=10., salgori = "centroid", aperture=9.3,wcsin="world",wcsout="tv", interac = "no", coords=coords, output=out_name) iraf.txdump(out_name, "id,image,xcenter,ycenter,xshift,yshift,fwhm,msky,stdev,cier,rapert,sum,area,nsky,flux,itime,mag,merr", "yes", Stdout=clean_name) ma = np.genfromtxt(clean_name, comments="#", dtype=[("id","<f4"), ("image","|S20"), ("X","<f4"), ("Y","<f4"), ("Xshift","<f4"), ("Yshift","<f4"),("fwhm","<f4"), ("msky","<f4"), \ ("stdev","<f4"), ("flags", np.int), ("rapert", "<f4"), ("sum", "<f4"), ("area", "<f4"), ("nsky","<f4") , ("flux", "<f4"), ("itime", "<f4"), ("fit_mag","<f4"), ("fiterr","<f4")]) if (ma.size > 0): ma = np.array([ma]) m = ma[~np.isnan(ma["fit_mag"])] else: print "Only one object found!" m = np.array([ma]) insmag = np.round(ma['fit_mag'][0] , 3) insmagerr = np.round(ma['fiterr'][0], 3) if (fitsutils.has_par(image, "ZEROPT") and fitsutils.has_par(image, "ZEROPTU")): mag = insmag + float(fitsutils.get_par(image, "ZEROPT")) magerr = np.sqrt(insmagerr**2+ float(fitsutils.get_par(image, "ZEROPTU"))**2) else: mag = 0 magerr = 0 if np.isnan(mag): mag, magerr = 0, 0 insmag, insmagerr = 0,0 fitsutils.update_par(image, "INSMAG", "%.3f"%insmag ) fitsutils.update_par(image, "INSMAGER", "%.3f"%insmagerr) fitsutils.update_par(image, "APPMAG", np.round(mag, 3) ) fitsutils.update_par(image, "APPMAGER", np.round(magerr, 3)) if (plot): #zmin, zmax = zscale.zscale(impf[0].data.T[pra-50:pra+50,pdec-50:pdec+50]) #zmin, zmax = zscale.zscale(impf[0].data) #im = plt.imshow(impf[0].data, vmin=zmin, vmax=zmax, origin="bottom") print np.percentile(impf[0].data, 5), np.percentile(impf[0].data, 95) impf[0].data[np.isnan(impf[0].data)] = np.nanmedian(impf[0].data) print np.percentile(impf[0].data, 5), np.percentile(impf[0].data, 95) im = plt.imshow(impf[0].data, vmin=np.percentile(impf[0].data, 5), vmax=np.percentile(impf[0].data, 95), origin="bottom") X = int(ma["X"][0]) Y = int(ma["Y"][0]) pra = int(pra) pdec = int(pdec) plt.scatter(X, Y, marker="o", s=100, facecolor="none", edgecolor="red") plt.colorbar(im) plt.savefig(os.path.join(plotdir, imname+".png"), dpi=200) plt.clf() zmin, zmax = zscale.zscale(impf[0].data.T[X-50:X+50,Y-50:Y+50].T) im = plt.imshow(impf[0].data.T[pra-50:pra+50,pdec-50:pdec+50].T, vmin=zmin, vmax=zmax, interpolation="none", origin="bottom", extent=(-50,50,-50,50)) c1 = plt.Circle( (pra-X, pdec-Y), edgecolor="k", facecolor="none", radius=aperture_rad, label="Initial position") c11 = plt.Circle( (pra-X, pdec-Y), edgecolor="k", facecolor="none", radius=sky_rad) c2 = plt.Circle( (0, 0), edgecolor="orange", facecolor="none", radius=aperture_rad, label="Adjusted centroid") c22 = plt.Circle( (0, 0), edgecolor="orange", facecolor="none", radius=sky_rad) plt.gca().add_artist(c1) plt.gca().add_artist(c11) plt.gca().add_artist(c2) plt.gca().add_artist(c22) plt.colorbar(im) myhandles = [] markers = ["o", "o"] labels = ["Initial position", "Adjusted centroid"] cols = ["k", "orange"] for i in np.arange(len(markers)): myhandles.append(mlines.Line2D([], [], mec=cols[i], mfc="none", marker=markers[i], ls="None", markersize=10, label=labels[i])) plt.legend(handles=myhandles, loc="lower left", labelspacing=0.3, fontsize=11, numpoints=1, frameon=False, ncol=5, bbox_to_anchor=(0.0, 0.00), fancybox=False, shadow=True) plt.title("MIN: %.0f MAX: %.0f"%(np.nanmin(impf[0].data.T[X-50:X+50,Y-50:Y+50]), np.nanmax(impf[0].data.T[X-50:X+50,Y-50:Y+50]))) plt.savefig(os.path.join(plotdir, imname+"_zoom.png")) plt.clf()
def reduce_image(image, flatdir=None, biasdir=None, cosmic=False, astrometry=True, channel='rc', target_dir='reduced', overwrite=False): ''' Applies Flat field and bias calibrations to the image. Steps: 1. - Solve astrometry on the entire image. 2. - Computes cosmic ray rejectionon the entire image. 3. - Compute master bias (if it does not exist) and de-bias the image. 4. - Separate the image into 4 filters. 5. - Compute flat field for each filter (if it does not exist) and apply flat fielding on the image. 6. - Compute the image zeropoint. ''' logger.info("Reducing image %s" % image) print "Reducing image ", image image = os.path.abspath(image) imname = os.path.basename(image).replace(".fits", "") try: objectname = fitsutils.get_par(image, "NAME").replace( " ", "") + "_" + fitsutils.get_par(image, "FILTER") except: logger.error("ERROR, image " + image + " does not have a NAME or a FILTER!!!") return print "For object", objectname logger.info("For object %s" % objectname) #Change to image directory mydir = os.path.dirname(image) if mydir == "": mydir = "." mydir = os.path.abspath(mydir) os.chdir(mydir) #Create destination directory if (not os.path.isdir(target_dir)): os.makedirs(target_dir) #If we don't want to overwrite the already extracted images, we check wether they exist. if (not overwrite): existing = True for band in ['u', 'g', 'r', 'i']: destfile = os.path.join( target_dir, imname + "_f_b_a_%s_%s_0.fits" % (objectname, band)) logger.info( "Looking if file %s exists: %s"%( destfile, \ (os.path.isfile(destfile) ) ) ) existing = existing and (os.path.isfile(destfile)) if existing: return [] #Initialize the basic parameters. init_header_reduced(image) astro = "" if (astrometry): logger.info("Solving astometry for the whole image...") img = solve_astrometry(image) if (os.path.isfile(img)): astro = "a_" fitsutils.update_par(img, "IQWCS", 1) else: logger.error("ASTROMETRY DID NOT SOLVE ON IMAGE %s" % image) img = image #Update noise parameters needed for cosmic reection if (fitsutils.get_par(img, "ADCSPEED") == 2): fitsutils.update_par(img, "RDNOISE", 20.) else: fitsutils.update_par(img, "RDNOISE", 4.) if (cosmic): logger.info("Correcting for cosmic rays...") # Correct for cosmics each filter cleanimg = clean_cosmic(os.path.join(os.path.abspath(mydir), img)) img = cleanimg #Compute BIAS if (biasdir is None or biasdir == ""): biasdir = "." create_masterbias(biasdir) bias_slow = os.path.join(biasdir, "Bias_%s_%s.fits" % (channel, 'slow')) bias_fast = os.path.join(biasdir, "Bias_%s_%s.fits" % (channel, 'fast')) # Running IRAF to DE-BIAS iraf.noao(_doprint=0) iraf.imred(_doprint=0) iraf.ccdred(_doprint=0) #Compute flat field if (flatdir is None or flatdir == ""): flatdir = "." create_masterflat(flatdir, biasdir) #New names for the object. debiased = os.path.join(os.path.dirname(img), "b_" + os.path.basename(img)) logger.info("Creating debiased file, %s" % debiased) if ( (fitsutils.get_par(img, "ADCSPEED")==0.1 and not os.path.isfile(bias_slow)) \ or (fitsutils.get_par(img, "ADCSPEED")==2 and not os.path.isfile(bias_fast)) ): logger.warn( "Master bias not found! Tryting to copy from reference folder...") copy_ref_calib(mydir, "Bias") if ( (fitsutils.get_par(img, "ADCSPEED")==0.1 and not os.path.isfile(bias_slow)) \ or (fitsutils.get_par(img, "ADCSPEED")==2 and not os.path.isfile(bias_fast)) ): logger.error("Bias not found in reference folder") return #Clean first if (os.path.isfile(debiased)): os.remove(debiased) #Debias if (fitsutils.get_par(img, "ADCSPEED") == 2): iraf.imarith(img, "-", bias_fast, debiased) fitsutils.update_par(debiased, "BIASFILE", bias_fast) fitsutils.update_par(debiased, "RDNOISE", 20.) else: iraf.imarith(img, "-", bias_slow, debiased) fitsutils.update_par(debiased, "BIASFILE", bias_slow) fitsutils.update_par(debiased, "RDNOISE", 4.) #Set negative counts to zero hdu = fits.open(debiased) header = hdu[0].header hdu[0].data[hdu[0].data < 0] = 0 hdu.writeto(debiased, clobber=True) #Slicing the image for flats slice_names = slice_rc(debiased) print "Creating sliced files, ", slice_names #Remove un-sliced image os.remove(debiased) # DE-flat each filter and store under object name for i, debiased_f in enumerate(slice_names): b = fitsutils.get_par(debiased_f, 'filter') deflatted = os.path.join( os.path.dirname(image), target_dir, imname + "_f_b_" + astro + objectname + "_%s.fits" % b) #Flat to be used for that filter flat = os.path.join(flatdir, "Flat_%s_%s_norm.fits" % (channel, b)) if (not os.path.isfile(flat)): logger.warn("Master flat not found in %s" % flat) copy_ref_calib(mydir, "Flat") continue else: logger.info("Using flat %s" % flat) #Cleans the deflatted file if exists if (os.path.isfile(deflatted)): os.remove(deflatted) if (os.path.isfile(debiased_f) and os.path.isfile(flat)): logger.info("Storing de-flatted %s as %s" % (debiased_f, deflatted)) time.sleep(1) iraf.imarith(debiased_f, "/", flat, deflatted) else: logger.error( "SOMETHING IS WRONG. Error when dividing %s by the flat field %s!" % (debiased_f, flat)) #Removes the de-biased file os.remove(debiased_f) logger.info( "Updating header with original filename and flat field used.") fitsutils.update_par(deflatted, "ORIGFILE", os.path.basename(image)) fitsutils.update_par(deflatted, "FLATFILE", flat) slice_names[i] = deflatted #Moving files to the target directory for image in slice_names: bkg = get_median_bkg(image) fitsutils.update_par(image, "SKYBKG", bkg) #Get basic statistics for the image nsrc, fwhm, ellip, bkg = sextractor.get_image_pars(image) plot_image(image) logger.info( "Sextractor statistics: nscr %d, fwhm (arcsec) %.2f, ellipticity %.2f" % (nsrc, fwhm, ellip)) print "Sextractor statistics: nscr %d, fwhm (arcsec) %.2f, ellipticity %.2f" % ( nsrc, fwhm, ellip) dic = { "FWHM": np.round(fwhm, 3), "FWHMPIX": np.round(fwhm / 0.394, 3), "NSRC": nsrc, "ELLIP": np.round(ellip, 3) } #Update the seeing information from sextractor fitsutils.update_pars(image, dic) #Compute the zeropoints for image in slice_names: zeropoint.calibrate_zeropoint(image) return slice_names
def reduce_image(image, flatdir=None, biasdir=None, cosmic=False, astrometry=True, channel='rc', target_dir='reduced', overwrite=False): ''' Applies Flat field and bias calibrations to the image. Steps: 1. - Solve astrometry on the entire image. 2. - Computes cosmic ray rejectionon the entire image. 3. - Compute master bias (if it does not exist) and de-bias the image. 4. - Separate the image into 4 filters. 5. - Compute flat field for each filter (if it does not exist) and apply flat fielding on the image. 6. - Compute the image zeropoint. ''' logger.info("Reducing image %s"% image) print "Reducing image ", image image = os.path.abspath(image) imname = os.path.basename(image).replace(".fits", "") try: objectname = fitsutils.get_par(image, "NAME").replace(" ","")+"_"+fitsutils.get_par(image, "FILTER") except: logger.error( "ERROR, image "+ image + " does not have a NAME or a FILTER!!!") return print "For object", objectname logger.info( "For object %s"% objectname) #Change to image directory mydir = os.path.dirname(image) if mydir=="": mydir = "." mydir = os.path.abspath(mydir) os.chdir(mydir) #Create destination directory if (not os.path.isdir(target_dir)): os.makedirs(target_dir) #If we don't want to overwrite the already extracted images, we check wether they exist. if (not overwrite): existing = True for band in ['u', 'g', 'r', 'i']: destfile = os.path.join(target_dir, imname + "_f_b_a_%s_%s_0.fits"%(objectname, band)) logger.info( "Looking if file %s exists: %s"%( destfile, \ (os.path.isfile(destfile) ) ) ) existing = existing and (os.path.isfile( destfile ) ) if existing: return [] #Initialize the basic parameters. init_header_reduced(image) astro = "" if (astrometry): logger.info( "Solving astometry for the whole image...") img = solve_astrometry(image) if (os.path.isfile(img)): astro="a_" fitsutils.update_par(img, "IQWCS", 1) else: logger.error( "ASTROMETRY DID NOT SOLVE ON IMAGE %s"% image) img = image #Update noise parameters needed for cosmic reection if (fitsutils.get_par(img, "ADCSPEED")==2): fitsutils.update_par(img, "RDNOISE", 20.) else: fitsutils.update_par(img, "RDNOISE", 4.) if (cosmic): logger.info( "Correcting for cosmic rays...") # Correct for cosmics each filter cleanimg = clean_cosmic(os.path.join(os.path.abspath(mydir), img)) img = cleanimg #Get basic statistics for the image nsrc, fwhm, ellip, bkg = sextractor.get_image_pars(img) logger.info( "Sextractor statistics: nscr %d, fwhm (pixel) %.2f, ellipticity %.2f"% (nsrc, fwhm, ellip)) print "Sextractor statistics: nscr %d, fwhm (pixel) %.2f, ellipticity %.2f"% (nsrc, fwhm, ellip) dic = {"SEEPIX": fwhm/0.394, "NSRC":nsrc, "ELLIP":ellip} #Update the seeing information from sextractor fitsutils.update_pars(img, dic) #Compute BIAS if (biasdir is None or biasdir==""): biasdir = "." create_masterbias(biasdir) bias_slow = os.path.join(biasdir, "Bias_%s_%s.fits"%(channel, 'slow')) bias_fast = os.path.join(biasdir, "Bias_%s_%s.fits"%(channel, 'fast')) # Running IRAF to DE-BIAS iraf.noao(_doprint=0) iraf.imred(_doprint=0) iraf.ccdred(_doprint=0) #Compute flat field if (flatdir is None or flatdir==""): flatdir = "." create_masterflat(flatdir, biasdir) #New names for the object. debiased = os.path.join(os.path.dirname(img), "b_" + os.path.basename(img)) logger.info( "Creating debiased file, %s"%debiased) if ( (fitsutils.get_par(img, "ADCSPEED")==0.1 and not os.path.isfile(bias_slow)) \ or (fitsutils.get_par(img, "ADCSPEED")==2 and not os.path.isfile(bias_fast)) ): logger.warn( "Master bias not found! Tryting to copy from reference folder...") copy_ref_calib(mydir, "Bias") if ( (fitsutils.get_par(img, "ADCSPEED")==0.1 and not os.path.isfile(bias_slow)) \ or (fitsutils.get_par(img, "ADCSPEED")==2 and not os.path.isfile(bias_fast)) ): logger.error( "Bias not found in reference folder") return #Clean first if (os.path.isfile(debiased)): os.remove(debiased) #Debias if (fitsutils.get_par(img, "ADCSPEED")==2): iraf.imarith(img, "-", bias_fast, debiased) fitsutils.update_par(debiased, "BIASFILE", bias_fast) fitsutils.update_par(debiased, "RDNOISE", 20.) else: iraf.imarith(img, "-", bias_slow, debiased) fitsutils.update_par(debiased, "BIASFILE", bias_slow) fitsutils.update_par(debiased, "RDNOISE", 4.) #Set negative counts to zero hdu = fits.open(debiased) header = hdu[0].header hdu[0].data[hdu[0].data<0] = 0 hdu.writeto(debiased, clobber=True) #Slicing the image for flats slice_names = slice_rc(debiased) print "Creating sliced files, ", slice_names #Remove un-sliced image os.remove(debiased) # DE-flat each filter and store under object name for i, debiased_f in enumerate(slice_names): b = fitsutils.get_par(debiased_f, 'filter') deflatted = os.path.join(os.path.dirname(image), target_dir, imname + "_f_b_" + astro + objectname + "_%s.fits"%b) #Flat to be used for that filter flat = os.path.join(flatdir, "Flat_%s_%s_norm.fits"%(channel, b)) if (not os.path.isfile(flat)): logger.warn( "Master flat not found in %s"% flat) copy_ref_calib(mydir, "Flat_%s_%s_norm"%(channel, b)) continue else: logger.info( "Using flat %s"%flat) #Cleans the deflatted file if exists if (os.path.isfile(deflatted)): os.remove(deflatted) if (os.path.isfile(debiased_f) and os.path.isfile(flat)): logger.info( "Storing de-flatted %s as %s"%(debiased_f, deflatted)) time.sleep(1) iraf.imarith(debiased_f, "/", flat, deflatted) else: logger.error( "SOMETHING IS WRONG. Error when dividing %s by the flat field %s!"%(debiased_f, flat)) #Removes the de-biased file os.remove(debiased_f) logger.info( "Updating header with original filename and flat field used.") fitsutils.update_par(deflatted, "ORIGFILE", os.path.basename(image)) fitsutils.update_par(deflatted, "FLATFILE", flat) slice_names[i] = deflatted #Moving files to the target directory for image in slice_names: bkg = get_median_bkg(image) fitsutils.update_par(image, "SKYBKG", bkg) #shutil.move(name, newname) #Compute the zeropoints for image in slice_names: zeropoint.calibrate_zeropoint(image) return slice_names
def create_superflat(imdir, filters=["u", "g", "r", "i"]): #Locate images for each filter imlist = glob.glob("rc*fits") #Run sextractor to locate bright sources sexfiles = sextractor.run_sex(imlist, overwrite=False) maskfiles = [] for i, im in enumerate(imlist): #Create a mask and store it int he mask directory maskfile = mask_stars(im, sexfiles[i]) maskfiles.append(maskfile) fitsutils.update_par(im, "BPM", os.path.relpath(maskfile)) for filt in filters: fimlist = [ im for im in imlist if fitsutils.get_par(im, "FILTER") == filt ] fmasklist = [ im for im in maskfiles if fitsutils.get_par(im, "FILTER") == filt ] if len(fimlist) == 0: continue fsfile = "lflat_%s" % filt msfile = "lmask_%s" % filt np.savetxt(fsfile, np.array(fimlist), fmt="%s") np.savetxt(msfile, np.array(fmasklist), fmt="%s") '''masklist = [] for m in fmasklist: hdulist = fits.open(m) data = hdulist[0].data masklist.append(data) masklist = np.array(masklist) hdu = fits.PrimaryHDU(masklist) hdulist = fits.HDUList([hdu]) hdulist.writeto("mastermask_%s.fits"%filt)''' # Running IRAF iraf.noao(_doprint=0) iraf.imred(_doprint=0) iraf.ccdred(_doprint=0) iraf.imarith("@" + fsfile, "*", "@" + msfile, "m_@" + fsfile) #Combine flats iraf.imcombine(input = "m_@"+fsfile, \ output = "superflat_%s.fits"%filt, \ combine = "median",\ scale = "mode", \ masktype="badvalue",\ maskvalue = 0) iraf.imstat("superflat_%s.fits" % filt, fields="image,npix,mean,stddev,min,max,mode", Stdout="Flat_stats") time.sleep(0.1) st = np.genfromtxt("Flat_stats", names=True, dtype=None) #Normalize flats iraf.imarith("superflat_%s.fits" % filt, "/", st["MODE"], "superflat_%s_norm.fits" % filt)
def solve_astrometry(img, outimage=None, radius=3, with_pix=True, overwrite=False, tweak=3): ''' img: fits image where astrometry should be solved. outimage: name for the astrometry solved image. If none is provided, the name will be "a_"img. radius: radius of uncertainty on astrometric position in image. with_pix: if we want to include the constraint on the pixel size for the RCCam. overwrite: wether the astrometrically solved image should go on top of the old one. tewak: parameter for astrometry.net ''' from astropy.wcs import InconsistentAxisTypesError img = os.path.abspath(img) ra = fitsutils.get_par(img, 'RA') dec = fitsutils.get_par(img, 'DEC') #logger.info( "Solving astrometry on field with (ra,dec)=%s %s"%(ra, dec)) astro = os.path.join(os.path.dirname(img), "a_" + os.path.basename(img)) #If astrometry exists, we don't run it again. if (os.path.isfile(astro) and not overwrite): return astro #Store a temporary file with the multiplication of the mask mask = "mask.fits" cmd = "solve-field --ra %s --dec %s --radius %.4f -p --new-fits %s \ -W none -B none -P none -M none -R none -S none -t %d --overwrite %s " % ( ra, dec, radius, astro, tweak, img) if (with_pix): cmd = cmd + " --scale-units arcsecperpix --scale-low 0.375 --scale-high 0.4" #logger.info( cmd) subprocess.call(cmd, shell=True) #Cleaning after astrometry.net if (os.path.isfile(img.replace(".fits", ".axy"))): os.remove(img.replace(".fits", ".axy")) if (os.path.isfile(img.replace(".fits", "-indx.xyls"))): os.remove(img.replace(".fits", "-indx.xyls")) if (os.path.isfile("none")): os.remove("none") if os.path.isfile(astro): try: is_on_target(img) except InconsistentAxisTypesError as e: fitsutils.update_par(img, "ONTARGET", 0) print "Error detected with WCS when reading file %s. \n %s" % (img, e) if (not outimage is None and overwrite and os.path.isfile(astro)): shutil.move(astro, outimage) return outimage elif (outimage is None and overwrite and os.path.isfile(astro)): shutil.move(astro, img) return img else: return astro
def extract_star_sequence(imfile, band, plot=True, survey='apass', debug=False, refstars=None): ''' Plots the USNOB1 field of stars on top of the star field image. Red circles are stars identified from the catalogue in the correct magnitude range. Yellow circles are stars that are isolated. ''' survey = str.lower(survey) f = pf.open(imfile) wcs = pywcs.WCS(f[0].header) img = f[0].data img[img<0] = 0 ra, dec = wcs.wcs_pix2sky(np.array([img.shape[0]/2, img.shape[1]/2], ndmin=2), 1)[0] sr = 5.5/60 print ra,dec if not refstars is None: shutil.copy(refstars, "/tmp/tmp_sdss.cat") catalog = np.genfromtxt("/tmp/tmp_sdss.cat", names=True, dtype=None, delimiter=",") cat_ra = catalog["ra"] cat_dec = catalog["dec"] mag = catalog["R"] elif str.lower(survey) =='usnob1': #ra, dec = coordinates_conversor.hour2deg(f[0].header['RA'], f[0].header['DEC']) #SEDM FoV is 6.5 arcmin, due to uncertainties in the position, 4 arcmin radius assumed. # Download USNO-B1 catalog for the position catalog_url = 'http://www.nofs.navy.mil/cgi-bin/vo_cone.cgi?CAT=USNO-B1&RA=%.5f&DEC=%.5f&SR=%.4f&VERB=1' % (ra, dec, sr) print "Downloading USNO-B1 catalog..." urllib.urlretrieve(catalog_url, '/tmp/tmp.cat') # Read RA, Dec and magnitude from XML format USNO catalog catalog = parse_single_table("/tmp/tmp.cat") cat_ra = catalog.array['RA'].data cat_dec = catalog.array['DEC'].data cat_R1mag = catalog.array['R1'].data cat_R2mag = catalog.array['R2'].data cat_B1mag = catalog.array['B1'].data cat_B2mag = catalog.array['B2'].data cat_I2mag = catalog.array['I2'].data cat_R1mag[cat_R1mag==0] = np.nan cat_R2mag[cat_R2mag==0] = np.nan cat_B1mag[cat_B1mag==0] = np.nan cat_B2mag[cat_B2mag==0] = np.nan cat_I2mag[cat_I2mag==0] = np.nan Bmag = np.nanmean(np.array([cat_B1mag, cat_B2mag]), axis=0) Rmag = np.nanmean(np.array([cat_R1mag, cat_R2mag]), axis=0) Imag = cat_I2mag mag = Rmag elif survey == "apass": # Download USNO-B1 catalog for the position catalog_url = 'https://www.aavso.org/cgi-bin/apass_download.pl?ra=%.5f&dec=%.5f&radius=%.4f8&outtype=1' % (ra, dec, sr) print "Downloading APASS catalog..." urllib.urlretrieve(catalog_url, '/tmp/tmp_apass.cat') catalog = np.genfromtxt("/tmp/tmp_apass.cat", delimiter=",", names=True) cat_ra = catalog['radeg'] cat_dec = catalog['decdeg'] mag = catalog['Sloan_r'] elif (survey=='sdss'): minmag = 0 maxmag = 21.0 catalog_url='http://skyserver.sdss.org/dr7/en/tools/search/x_radial.asp?ra=%.5f&dec=%.5f&check_type=type&type=6\ &radius=%.4f&check_u=u&min_u=%.2f&max_u=%.2f&check_g=g&min_g=%.2f&max_g=%.2f&check_r=r&min_r=%.2f&max_r=%.2f&check_i=i&min_i=%.2f&max_i=%.2f&check_z=z&min_z=%.2f&max_z=%.2f&entries=top&topnum=500&format=csv'%(ra, dec, sr*60,minmag,maxmag,minmag,maxmag,minmag,maxmag,minmag,maxmag,minmag,maxmag) print "Downloading SDSS catalog..." print catalog_url urllib.urlretrieve(catalog_url, '/tmp/tmp_sdss.cat') catalog = np.genfromtxt("/tmp/tmp_sdss.cat", delimiter=",", names=True) try: cat_ra = catalog['ra'] cat_dec = catalog['dec'] mag = catalog[band] except: print "Problems with SDSS image", band return False #Convert ra, dec position of all stars to pixels. star_pix = np.array([0,0]) for i in range(len(cat_ra)): # Get pixel coordinates of USNO stars s = wcs.wcs_sky2pix(np.array([cat_ra[i], cat_dec[i]], ndmin=2), 1)[0] star_pix = np.row_stack((star_pix, s)) star_pix = star_pix[1:] pix2ang = 0.394 rad = math.ceil(25./pix2ang) #Select only the stars within the image. mask = (star_pix[:,0]>-rad) * (star_pix[:,0]<img.shape[1]+rad)*(star_pix[:,1]>-rad) * (star_pix[:,1]<img.shape[0]+rad) if (band == 'u'): mask = mask * (mag < 19) #Select only stars isolated in a radius of ~12 arcsec. mask2 = np.array(are_isolated(cat_ra[mask], cat_dec[mask], 30.)) #Select only stars that are within the proper magnitude range mask3 = (mag[mask][mask2] < 20.) * (mag[mask][mask2] > 12) mask3 = mask3 * (star_pix[:,0][mask][mask2]>rad) * (star_pix[:,0][mask][mask2]<img.shape[1]-rad)*(star_pix[:,1][mask][mask2]>rad) * (star_pix[:,1][mask][mask2]<img.shape[0]-rad) if (survey=='usnob1'): output = np.column_stack((star_pix[:,0][mask][mask2][mask3], star_pix[:,0][mask][mask2][mask3], \ cat_ra[mask][mask2][mask3], cat_dec[mask][mask2][mask3], Bmag[mask][mask2][mask3], Rmag[mask][mask2][mask3], Imag[mask][mask2][mask3])) np.savetxt('/tmp/usnob1_cat.txt', output, fmt="%.5f %.5f %.5f %.5f %.5f %.5f %.5f", header='#X Y ra dec B R I') print "Saved to", '/tmp/usnob1_cat.txt' elif (survey=='apass'): if not np.any(mask2) and not np.any(mask3): print star_pix print "No stars left...", mask, mask2, mask3 return else: print catalog[mask][mask2][mask3] catalog = catalog[mask][mask2][mask3] s = star_pix[mask][mask2][mask3] z = np.zeros(len(s), dtype=[('x','f8'), ('y', 'f8')]) z['x'] = s[:,0] z['y'] = s[:,1] for n in catalog.dtype.names: z = rfn.append_fields(z, names=n, data=catalog[n], usemask=False) fmt = "%.5f" for i in range(len(z[0])-1): fmt += " %.5f" np.savetxt('/tmp/apass_cat.txt', z, fmt=fmt, \ header='x y radeg raerr decdeg decerr number_of_Obs V dV B dB g dg r dr i di') print "Saved to", '/tmp/apass_cat.txt' elif survey=='sdss': if not np.any(mask) and not np.any(mask2) and not np.any(mask3): print star_pix print "No stars left...", mask, mask2, mask3 else: catalog = catalog[mask][mask2][mask3] s = star_pix[mask][mask2][mask3] z = np.zeros(len(s), dtype=[('x','f8'), ('y', 'f8')]) z['x'] = s[:,0] z['y'] = s[:,1] for n in catalog.dtype.names: z = rfn.append_fields(z, names=n, data=catalog[n], usemask=False) fmt = "%.5f" for i in range(len(z[0])-1): fmt += " %.5f" np.savetxt('/tmp/sdss_cat.txt', z, fmt=fmt, \ header='x y objid run rerun camcol field obj type ra dec u g r i z du dg dr di dz') print "Saved to", '/tmp/sdss_cat.txt' #Find FWHM for this image out = find_fwhm(imfile, star_pix[:,1][mask][mask2][mask3], star_pix[:,0][mask][mask2][mask3], plot=debug) mask_valid_fwhm = (out['detected']) * (out['e']>0.7) * ~np.isnan(out['fwhm']* (out['fwhm'] < 30)) if (np.count_nonzero(mask_valid_fwhm) < 3): print "ERROR with FWHM!! Too few points for a valid estimation." return False outd = out[mask_valid_fwhm] print 'Average FWHM',np.median(outd['fwhm']), 'arcsec', np.median(outd['fwhm'])*pix2ang, 'pixels' fwhm = np.median(outd['fwhm']) fitsutils.update_par(imfile,'FWHM',fwhm) np.savetxt('/tmp/sdss_cat_det.txt', z[mask_valid_fwhm], fmt=fmt, \ header='x y objid run rerun camcol field obj type ra dec u g r i z du dg dr di dz') print "Saved to", '/tmp/sdss_cat_det.txt' #Plot results img = img - np.nanmin(img) zmin, zmax = zscale.zscale(img) print "Found %d stars in %s. "%(len(cat_dec), survey), \ "%d of them within the FoV. "%len(cat_ra[mask]),\ "%d of them are isolated."%len(cat_ra[mask][mask2]),\ "%d of them with suitable magnitudes. "%len(cat_ra[mask][mask2][mask3]),\ "%d of them with detected stars."%np.count_nonzero(mask_valid_fwhm) if (plot): im = plt.imshow(img, aspect="equal", origin="lower", cmap=matplotlib.cm.gray_r, interpolation="none", vmin=zmin, vmax=zmax) if (len(star_pix[:,0][mask]) >0): plt.scatter(star_pix[:,0][mask], star_pix[:,1][mask], marker="o", s=np.minimum(150, 10000*(10./mag[mask][mask2])**9), edgecolor="red", facecolor="none") if (len(star_pix[:,0][mask][mask2]) >0): plt.scatter(star_pix[:,0][mask][mask2], star_pix[:,1][mask][mask2], marker="o", s=20, edgecolor="yellow", facecolor="none") if (len(star_pix[:,0][mask][mask2][mask3]) >0): plt.scatter(star_pix[:,0][mask][mask2][mask3], star_pix[:,1][mask][mask2][mask3], marker="o", s=200, edgecolor="green", facecolor="none") selected = star_pix[:,:][mask][mask2][mask3][mask_valid_fwhm] if (len(selected) >0): plt.scatter(selected[:,0], selected[:,1], marker="o", \ s=400, edgecolor="blue", facecolor="none") for i in np.arange(len(selected)): plt.text(selected[i,0]+10, selected[i,1]+10, i+1) plt.savefig(imfile.replace('.fits', '.seqstars.png')) print "Saved stars to ",imfile.replace('.fits', '.seqstars.png') plt.clf() return True
def create_superflat(imdir, filters=["u", "g", "r", "i"]): #Locate images for each filter imlist = glob.glob("rc*fits") #Run sextractor to locate bright sources sexfiles = sextractor.run_sex(imlist, overwrite=False) maskfiles = [] for i, im in enumerate(imlist): #Create a mask and store it int he mask directory maskfile = mask_stars(im, sexfiles[i]) maskfiles.append(maskfile) fitsutils.update_par(im, "BPM", os.path.relpath(maskfile)) for filt in filters: fimlist = [im for im in imlist if fitsutils.get_par(im, "FILTER") == filt] fmasklist = [im for im in maskfiles if fitsutils.get_par(im, "FILTER") == filt] if len(fimlist) == 0: continue fsfile ="lflat_%s"%filt msfile = "lmask_%s"%filt np.savetxt(fsfile, np.array(fimlist), fmt="%s") np.savetxt(msfile, np.array(fmasklist), fmt="%s") '''masklist = [] for m in fmasklist: hdulist = fits.open(m) data = hdulist[0].data masklist.append(data) masklist = np.array(masklist) hdu = fits.PrimaryHDU(masklist) hdulist = fits.HDUList([hdu]) hdulist.writeto("mastermask_%s.fits"%filt)''' # Running IRAF iraf.noao(_doprint=0) iraf.imred(_doprint=0) iraf.ccdred(_doprint=0) iraf.imarith("@"+fsfile, "*", "@"+msfile, "m_@"+fsfile) #Combine flats iraf.imcombine(input = "m_@"+fsfile, \ output = "superflat_%s.fits"%filt, \ combine = "median",\ scale = "mode", \ masktype="badvalue",\ maskvalue = 0) iraf.imstat("superflat_%s.fits"%filt, fields="image,npix,mean,stddev,min,max,mode", Stdout="Flat_stats") time.sleep(0.1) st = np.genfromtxt("Flat_stats", names=True, dtype=None) #Normalize flats iraf.imarith("superflat_%s.fits"%filt, "/", st["MODE"], "superflat_%s_norm.fits"%filt)