def call_fit_mtf(imageRoot, dataDir='/u/jlu/data/w51/10aug14/combo/', starsSuffix='_0.8_stf.lis', resolvedSources=None, maskSize=150, xcenter=None, ycenter=None, clip=0.02, weights=None, outDir='./'): """ weights - {None, 'std', 0.1} where the last can be any scale factor. None = no weighting, or same as constant weights. 'std' = use 1 / standard deviation of averaged 1D power spectrum. <frac> = use 1 / (any scale factor * 'std') """ ############################## # H-band wide image ############################## imageFile = dataDir + imageRoot + '.fits' img, hdr = pyfits.getdata(imageFile, header=True) wavelength = hdr['CENWAVE'] * 1e-6 focallength = mtf.Fvalues[hdr['CAMNAME'].strip()] pupil = hdr['PMSNAME'] # Mask resolved sources if resolvedSources != None: print 'MTF: Masking %d resolved sources' % len(resolvedSources) img = mask_image(imageFile, resolvedSources, maskSize=maskSize) gcutil.rmall([outDir + imageRoot + '_masked.fits']) pyfits.writeto(outDir + imageRoot + '_masked.fits', img) print 'MTF: Set initial guesses for parameters' #definitions of starting parameters [from fitmtf_keck.pro] # # wave=1.65d-6 # wavelength in meters # F=557.0 # effective focal length of Keck AO (narrow) # D=10.99 # primary's diameter in meters # pupil=0.266 # central obscuration # pupil='largehex' # NIRC2 pupil-stop # Apix=27d-6 # width of detector's pixel in meters # L0=20. # outer scale of turbulence in meters # sigma=.56 # Infl Func width on primary in meters # w=1.3 # Influence Function height # Delta=0 # wavefront measurement error # Cmult=10. # multiplicative constant # N=1d-2 # additive noise floor constant # r0=0.5 # wavelength specific fried parameter in meters startp = { 'wave': wavelength, 'D': 10.99, 'F': focallength, 'Apix': 27e-6, 'pupil': pupil, 'r0': 0.5, 'L0': 30.0, 'cmult': 1.0, 'N': 1e-5, 'w': 1.3, 'delta': 0.0, 'sigma': 0.56, } # Load up the starfinder results for this image print 'MTF: Read in preliminary starlist.' stfLis = dataDir + 'starfinder/' + imageRoot + starsSuffix table = asciidata.open(stfLis) name = table[0].tonumpy() mag = table[1].tonumpy() x = table[3].tonumpy() y = table[4].tonumpy() flux = 10**((mag[0] - mag) / 2.5) # Create sources array (delta functions * flux) for the stars. print 'MTF: Creating 2D source array' sources = np.zeros(img.shape, dtype=float) sources[np.array(y, dtype=int), np.array(x, dtype=int)] = flux # If this is a wide camera image, trim down to the central 512x512 # in order to limit the impact of anisoplanatism. if hdr['CAMNAME'].strip() == 'wide': # Make image square new_size = (np.array(img.shape) / 2.0).min() xlo = xcenter - (new_size / 2) xhi = xcenter + (new_size / 2) ylo = ycenter - (new_size / 2) yhi = ycenter + (new_size / 2) img = img[ylo:yhi, xlo:xhi] sources = sources[ylo:yhi, xlo:xhi] py.figure(2) py.clf() py.imshow(np.log10(img)) py.draw() py.figure(1) print 'MTF: Calling getmtf' foo = mtf.get_mtf(img, startp, sources=sources) nu = foo[0] power = foo[1] error = foo[2] pspec_sources = foo[3] weightMsg = 'Weighting by 1 / STD of azimuthal average power spectrum' # Defuault, assume weight = 'std' and just use the # standard deviation of azimuthal average of the power spectrum. if weights == None: weightMsg = 'Unweighted' # we will be working in log space, so need to 0.1 instead of 1.0 to # avoid dividing by log(1.0) = 0. error = np.ones(len(error)) * 0.1 if (type(weights) == float) and (weights <= 1) and (weights > 0): weightMsg = 'Weighting by 1 / power * scaleFactor of %.3f' % weights error = power * weights print weightMsg # Fit the power spectrum print 'MTF: Fitting the power spectrum (round 1)' fit = mtf.fitmtf_keck(nu, power, error, pspec_sources, startParams=startp, relStep=0.2, clip=clip) print 'MTF: Fitting the power spectrum (round 2)' fit = mtf.fitmtf_keck(nu, power, error, pspec_sources, startParams=fit.params, relStep=0.02, clip=clip) pspec_fit = mtf.mtffunc_keck(fit.params, nu=nu, sources=pspec_sources) mtfOut = mtf.mtffunc_keck(fit.params, nu=nu) print 'Calculating PSF' # PSF psf2d, psf1d = mtf.mtf2psf(fit.params, 2.0) print 'Calculating EE ' # Encircled Energy pix = np.arange(100, dtype=float) ee = mtf.mtf2ee(fit.params, pix) print 'Calculating Strehl' # Strehl sr = mtf.strehl(fit.params) # Make some output objects p_obs = objects.DataHolder() p_obs.nu = nu p_obs.pspec = power p_obs.pspec_error = error p_obs.pspec_sources = pspec_sources p_fit = objects.DataHolder() p_fit.all_params = fit.params p_fit.all_errors = fit.perror p_fit.fit_params = fit.fit_params p_fit.fit_covar = fit.fit_covar p_fit.fit_stat = fit.fit_stat p_fit.pspec_fit = pspec_fit p_fit.mtf_system = mtfOut p_fit.mtf_perfect = fit.tperf p_fit.psf1d = psf1d p_fit.psf2d = psf2d p_fit.strehl = sr p_fit.encircled_energy = ee # Save output to a pickle file outfile = open(outDir + imageRoot + '_mtf.pickle', 'w') pickle.dump(p_obs, outfile) pickle.dump(p_fit, outfile) outfile.close()
def plotWithHST(rotateFITS=True): # Load up the OSIRIS image cubeFile = datadir + cuberoot + '_img.fits' cube, cubehdr = pyfits.getdata(cubeFile, header=True) paCube = cubehdr['PA_SPEC'] scaleCube = 0.05 # Load up the NIRC2 image kFile = '/u/jlu/data/m31/05jul/combo/m31_05jul_kp.fits' # kFile = '/u/jlu/data/m31/09sep/combo/mag09sep_m31_kp.fits' k, khdr = pyfits.getdata(kFile, header=True) m31K = np.array([751.986, 716.989]) paK = 0.0 scaleK = 0.00995 f330Root = '/u/jlu/data/m31/hst/m31_acshrc_f330w_j9am01030' f435Root = '/u/jlu/data/m31/hst/m31_acshrc_f435w_j9am01010' f555Root = '/u/jlu/data/m31/hst/m31_wfpc2pc1_f555w_u2lg020at' f814Root = '/u/jlu/data/m31/hst/m31_wfpc2pc1_f814w_u2lg020bt' ########## # Rotate all the HST images to PA=0, scale=NIRC2 ########## if rotateFITS == True: # Load up the HST ACS image (330 nm) f330File = f330Root + '.fits' f330FileRot = f330Root + '_rot.fits' f330, f330hdr = pyfits.getdata(f330File, 1, header=True) m31F330 = np.array([547.0, 623.2]) paF330 = f330hdr['ORIENTAT'] scaleF330 = 0.025 # Load up the HST ACS image (435 nm) f435File = f435Root + '.fits' f435FileRot = f435Root + '_rot.fits' f435, f435hdr = pyfits.getdata(f435File, 1, header=True) m31F435 = np.array([546.9, 623.5]) paF435 = f435hdr['ORIENTAT'] scaleF435 = 0.025 # Load up the HST ACS image (555 nm) f555File = f555Root + '.fits' f555FileRot = f555Root + '_rot.fits' f555, f555hdr = pyfits.getdata(f555File, 1, header=True) m31F555 = np.array([973.0, 961.0]) paF555 = f555hdr['ORIENTAT'] scaleF555 = 0.1 # Load up the HST ACS image (814 nm) f814File = f814Root + '.fits' f814FileRot = f814Root + '_rot.fits' f814, f814hdr = pyfits.getdata(f814File, 1, header=True) m31F814 = np.array([975.0, 962.0]) paF814 = f814hdr['ORIENTAT'] scaleF814 = 0.1 print('scaleK = ', scaleK) print('scaleF330 = ', scaleF330) print('scaleF435 = ', scaleF435) print('scaleF555 = ', scaleF555) print('scaleF814 = ', scaleF814) print('paK = ', paK) print('paF330 = ', paF330) print('paF435 = ', paF435) print('paF555 = ', paF555) print('paF814 = ', paF814) gcutil.rmall([f330FileRot, f435FileRot, f555FileRot, f814FileRot]) from pyraf import iraf as ir ir.unlearn('imlintran') ir.imlintran.boundary = 'constant' ir.imlintran.constant = 0 ir.imlintran.interpolant = 'spline3' ir.imlintran.fluxconserve = 'yes' # 330 ir.imlintran.xin = m31F330[0] ir.imlintran.yin = m31F330[1] ir.imlintran.xout = m31K[0] ir.imlintran.yout = m31K[1] ir.imlintran.ncols = k.shape[1] ir.imlintran.nlines = k.shape[0] ir.imlintran(f330File + '[1]', f330FileRot, paF330, paF330, scaleK / scaleF330, scaleK / scaleF330) # 435 ir.imlintran.xin = m31F435[0] ir.imlintran.yin = m31F435[1] ir.imlintran.xout = m31K[0] ir.imlintran.yout = m31K[1] ir.imlintran.ncols = k.shape[1] ir.imlintran.nlines = k.shape[0] ir.imlintran(f435File + '[1]', f435FileRot, paF435, paF435, scaleK / scaleF435, scaleK / scaleF435) # 555 ir.imlintran.xin = m31F555[0] ir.imlintran.yin = m31F555[1] ir.imlintran.xout = m31K[0] ir.imlintran.yout = m31K[1] ir.imlintran.ncols = k.shape[1] ir.imlintran.nlines = k.shape[0] ir.imlintran(f555File + '[1]', f555FileRot, paF555, paF555, scaleK / scaleF555, scaleK / scaleF555) # 814 ir.imlintran.xin = m31F814[0] ir.imlintran.yin = m31F814[1] ir.imlintran.xout = m31K[0] ir.imlintran.yout = m31K[1] ir.imlintran.ncols = k.shape[1] ir.imlintran.nlines = k.shape[0] ir.imlintran(f814File + '[1]', f814FileRot, paF814, paF814, scaleK / scaleF814, scaleK / scaleF814) f330 = pyfits.getdata(f330Root + '_rot.fits') f435 = pyfits.getdata(f435Root + '_rot.fits') img = np.zeros((k.shape[0], k.shape[1], 3), dtype=float) img[:, :, 0] = img_scale.linear(k, scale_min=300, scale_max=2400) img[:, :, 1] = img_scale.linear(f435, scale_min=0.45, scale_max=1.8) img[:, :, 2] = img_scale.linear(f330, scale_min=0, scale_max=0.16) # Axes xaxis = (np.arange(img.shape[0], dtype=float) - m31K[0]) * 0.00995 yaxis = (np.arange(img.shape[1], dtype=float) - m31K[1]) * 0.00995 py.clf() py.imshow(img, aspect='equal', extent=[xaxis[0], xaxis[-1], yaxis[0], yaxis[-1]]) #py.plot([m31K[0]], [m31K[1]], 'ko') #py.axis([625, 825, 650, 850]) py.plot([0], [0], 'k+') py.axis([-1.5, 1.5, -1.5, 1.5]) py.xlabel('X Offset from M31* (arcsec)') py.ylabel('Y Offset from M31* (arcsec)') py.title('Blue = F330W, Green = F435W, Red = Kband') py.savefig(workdir + 'plots/hst_nirc2_rgb.png') py.show()
def mtf_play(imageRoot, dataDir='/u/jlu/data/w51/09jun26/combo/', starsSuffix='_0.8_stf.lis', resolvedSources=None, maskSize=150): import pidly idl = pidly.IDL() ############################## # H-band wide image ############################## imageFile = dataDir + imageRoot + '.fits' img, hdr = pyfits.getdata(imageFile, header=True) wavelength = hdr['CENWAVE'] * 1e-6 # Mask resolved sources if resolvedSources != None: print 'MTF: Masking %d resolved sources' % len(resolvedSources) img = mask_image(imageFile, resolvedSources, maskSize=maskSize) gcutil.rmall([imageRoot + '_masked.fits']) pyfits.writeto(imageRoot + '_masked.fits', img) # Load up the image print 'MTF: Load the science image.' idl('im = readfits("' + imageRoot + '_masked.fits")') print 'MTF: Set initial guesses for parameters' #definitions of starting parameters [from fitmtf_keck.pro] # # lambda=1.65d-6 # wavelength in meters # F=557.0 # effective focal length of Keck AO (narrow) # D=10.99 # primary's diameter in meters # pupil=0.266 # central obscuration # pupil='largehex' # NIRC2 pupil-stop # Apix=27d-6 # width of detector's pixel in meters # L0=20. # outer scale of turbulence in meters # sigma=.56 # Infl Func width on primary in meters # w=1.3 # Influence Function height # Delta=0 # wavefront measurement error # Cmult=10. # multiplicative constant # N=1d-2 # additive noise floor constant # r0=0.5 # wavelength specific fried parameter in meters idl('startp = {lambda:' + str(wavelength) + ', ' + 'D:10.99, F:139.9, APIX:27e-6, ' + 'pupil:"largehex", L0:30.0, SIGMA:0.56, ' + 'W:1.3, Delta:0.0, Cmult:1.0, N:1e-5, R0:0.5}') # Load up the starfinder results for this image print 'MTF: Read in preliminary starlist.' stfLis = dataDir + 'starfinder/' + imageRoot + starsSuffix idl('readcol, "' + stfLis + '", name, mag, time, x, y, ' + 'snr, corr, frames, fwhm, format="(A,F,F,F,F,F,F,F,F)"') idl('flux = 10^((mag[0] - mag)/2.5)') # Create sources array (delta functions * flux) for the stars. print 'MTF: Creating 2D source array' idl('sources = im') idl('sources[*] = 0.') idl('sources[x, y] = flux') mtfData = imageRoot + '_mtfdata.save' mtfFit = imageRoot + '_mtffit.save' print 'MTF: Calling getmtf' idl('getmtf, im, startp, nu, power, error, spdist, deltas=sources') idl('save, nu, power, error, spdist, filename="'+mtfData+'"') # Fit the power spectrum print 'MTF: Fitting the power spectrum (round 1)' idl('print, startp') idl('fitmtf_keck, "'+mtfData+'", params, perror, ' + 'start=startp, relstep=0.2')
def mosaic_kp(): """ Make a mosaic of our NIRC2 data on W51, one per filter. """ hepochs = ['09jun26', '09jun26', '09jun26', '09jun26'] kepochs = ['09jun10', '09jun10', '09jun10', '09jun26'] lepochs = ['09jun26', '09jun26', '09jun26', '09jun26'] cooStarsH = ['f1_psf0', 'f2_psf0', 'f3_psf0', 'f4_psf0'] cooStarsK = ['f1_psf0', 'f2_psf0', 'f3_psf0', 'f4_psf0'] cooStarsL = ['f1_psf1', 'f2_psf0', 'f3_psf2', 'f4_psf1'] cooStarsH = ['E4-1', 'E8-1', 'N5-1', 'W6-2'] cooStarsK = ['E4-1', 'E8-1', 'N5-1', 'W6-2'] cooStarsL = ['S0-1', 'E8-1', 'W7-1', 'W9-1'] scaleMinH = [0, 0, 0, 0] scaleMinK = [0, 0, 0, 0] scaleMinL = [1000, 1100, 1200, 1250] scaleMaxH = [6000, 6000, 5000, 6000] scaleMaxK = [6500, 6500, 6500, 5500] scaleMaxL = [1600, 1300, 1400, 1600] img = np.zeros((2400, 2400, 3), dtype=float) imgH = np.zeros((2400, 2400), dtype=float) imgK = np.zeros((2400, 2400), dtype=float) imgL = np.zeros((2400, 2400), dtype=float) origin = np.array([1200.0, 1200.0]) labelFile = '/u/jlu/data/w51/source_list/w51a_label.dat' labels = starTables.Labels(labelFile=labelFile) dataRoot = '/u/jlu/data/w51/' py.clf() foo = range(len(hepochs)) for ii in foo[::-1]: # for ii in range(1): rootH = '%s/%s/combo/mag%s_w51a_f%d_h' % \ (dataRoot, hepochs[ii], hepochs[ii], ii+1) rootK = '%s/%s/combo/mag%s_w51a_f%d_kp' % \ (dataRoot, kepochs[ii], kepochs[ii], ii+1) rootL = '%s/%s/combo/mag%s_w51a_f%d_lp' % \ (dataRoot, lepochs[ii], lepochs[ii], ii+1) # Load up the images h, hhdr = pyfits.getdata(rootH + '.fits', header=True) k, khdr = pyfits.getdata(rootK + '.fits', header=True) l, lhdr = pyfits.getdata(rootL + '.fits', header=True) hint = hhdr['ITIME'] * hhdr['COADDS'] kint = khdr['ITIME'] * khdr['COADDS'] lint = lhdr['ITIME'] * lhdr['COADDS'] # Make the arrays into the largest size. h_new = np.zeros((img.shape[0], img.shape[1]), dtype=float) k_new = np.zeros((img.shape[0], img.shape[1]), dtype=float) l_new = np.zeros((img.shape[0], img.shape[1]), dtype=float) h_new[0:h.shape[0], 0:h.shape[1]] = h k_new[0:k.shape[0], 0:k.shape[1]] = k l_new[0:l.shape[0], 0:l.shape[1]] = l # Load up the coo stars tmpH = open(rootH + '.coo').readline().split() cooH = np.array([float(tmpH[0]), float(tmpH[1])]) tmpK = open(rootK + '.coo').readline().split() cooK = np.array([float(tmpK[0]), float(tmpK[1])]) tmpL = open(rootL + '.coo').readline().split() cooL = np.array([float(tmpL[0]), float(tmpL[1])]) # Get the coordinates of each coo star in arcsec. idxH = np.where(labels.name == cooStarsH[ii])[0][0] idxK = np.where(labels.name == cooStarsK[ii])[0][0] idxL = np.where(labels.name == cooStarsL[ii])[0][0] asecH = np.array([labels.x[idxH], labels.y[idxH]]) asecK = np.array([labels.x[idxK], labels.y[idxK]]) asecL = np.array([labels.x[idxL], labels.y[idxL]]) scale = np.array([-0.00995, 0.00995]) # Now figure out the necessary shifts originH = cooH - asecH/scale originK = cooK - asecK/scale originL = cooL - asecL/scale # Shift the J and H images to be lined up with K-band shiftL = origin - originL shiftK = origin - originK shiftH = origin - originH l = interp.shift(l_new, shiftL[::-1]) k = interp.shift(k_new, shiftK[::-1]) h = interp.shift(h_new, shiftH[::-1]) print shiftH print shiftL xx, yy = np.meshgrid(np.arange(img.shape[0]), np.arange(img.shape[1])) idx = np.where((h >= 1) & (k >= 1) & (l >= 1)) # Trim off the bottom 10 rows where there is data ymin = yy[idx[0], idx[1]].min() ydx = np.where(yy[idx[0],idx[1]] > (ymin+10))[0] idx = (idx[0][ydx], idx[1][ydx]) img[idx[0],idx[1],0] = img_scale.log(l[idx[0],idx[1]], scale_min=scaleMinL[ii], scale_max=scaleMaxL[ii]) img[idx[0],idx[1],1] = img_scale.log(k[idx[0], idx[1]], scale_min=scaleMinK[ii], scale_max=scaleMaxK[ii]) img[idx[0],idx[1],2] = img_scale.log(h[idx[0], idx[1]], scale_min=scaleMinH[ii], scale_max=scaleMaxH[ii]) imgH[idx[0], idx[1]] = h[idx[0], idx[1]] / hint imgK[idx[0], idx[1]] = k[idx[0], idx[1]] / kint imgL[idx[0], idx[1]] = l[idx[0], idx[1]] / lint # Fix scaling of first image. if ii == 0: imgK[idx[0], idx[1]] -= 0.4 # Save on memory l = None k = None h = None l_new = None k_new = None h_new = None # Define the axes xaxis = np.arange(-0.5, img.shape[1]+0.5, 1) xaxis = ((xaxis - origin[0]) * scale[0]) yaxis = np.arange(-0.5, img.shape[0]+0.5, 1) yaxis = ((yaxis - origin[1]) * scale[1]) extent = [xaxis[0], xaxis[-1], yaxis[0], yaxis[-1]] # py.figure(1) # py.imshow(img[:,:,0], extent=extent, cmap=py.cm.gray) # py.axis('equal') py.figure(2) py.imshow(img[:,:,1], extent=extent, cmap=py.cm.gray) py.axis('equal') # py.figure(3) # py.imshow(img[:,:,2], extent=extent, cmap=py.cm.gray) # py.axis('equal') foo = raw_input('Continue?') gcutil.rmall(['w51a_h_mosaic.fits', 'w51a_k_mosaic.fits', 'w51a_l_mosaic.fits']) pyfits.writeto('w51a_h_mosaic.fits', imgH) pyfits.writeto('w51a_k_mosaic.fits', imgK) pyfits.writeto('w51a_l_mosaic.fits', imgL)
def plotLabelAndAlign(alignRoot, polyRoot, magCut=25, labelFile='label.dat', showStars=True): label = starTables.Labels(labelFile) label.take(np.where(label.mag < magCut)[0]) t = 2005.580 x_lab = label.x + label.vx * (t - label.t0) / 10**3 y_lab = label.y + label.vy * (t - label.t0) / 10**3 n_lab = label.ourName use = label.useToAlign # Now read in the align stuff s = starset.StarSet(alignRoot) s.loadPolyfit(polyRoot, accel=0) mag = s.getArray('mag') idx = np.where(mag < magCut)[0] s.stars = [s.stars[ii] for ii in idx] n_aln = np.array(s.getArray('name')) mag = s.getArray('mag') x0 = s.getArray('fitXv.p') * -1.0 y0 = s.getArray('fitYv.p') x0err = s.getArray('fitXv.perr') y0err = s.getArray('fitYv.perr') vx = s.getArray('fitXv.v') * -1.0 vy = s.getArray('fitYv.v') vxerr = s.getArray('fitXv.verr') vyerr = s.getArray('fitYv.verr') t0x = s.getArray('fitXv.t0') t0y = s.getArray('fitYv.t0') r = np.hypot(x0, y0) x_aln = x0 + vx * (t - t0x) y_aln = y0 + vy * (t - t0y) # Fix x0err, y0err to some minimum value idx = np.where(x0err < 0.0001)[0] x0err[idx] = 0.0001 idx = np.where(y0err < 0.0001)[0] y0err[idx] = 0.0001 # First lets update the 16 sources since they are used # to align label.dat to the reference epoch (crude I know) names16 = [ 'irs16C', 'irs16NW', 'irs16CC', 'irs16NE', 'irs16SW', 'irs16SW-E', 'irs33N', 'irs33E' ] for nn in range(len(names16)): idx = np.where(n_aln == names16[nn])[0] for rr in idx: print '%-11s %4.1f %6.3f %6.3f %7.4f %7.4f %8.3f %8.3f %7.3f %7.3f %8.3f 1 %5.3f' % \ (n_aln[rr], mag[rr], x0[rr], y0[rr], x0err[rr], y0err[rr], vx[rr]*10**3, vy[rr]*10**3, vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], r[rr]) # Image imageFile = '/u/ghezgroup/data/gc/' imageFile += '06maylgs1/combo/mag06maylgs1_dp_msc_kp.fits' im = pyfits.getdata(imageFile) imgsize = (im.shape)[0] # pixel position (0,0) is at upper left xpix = np.arange(0, im.shape[0], dtype=float) ypix = np.arange(0, im.shape[1], dtype=float) sgra = [1422.6, 1543.8] scale_jpg = 0.00994 xim = (xpix - sgra[0]) * scale_jpg * -1.0 yim = (ypix - sgra[1]) * scale_jpg # Lets also make some coordinates for compass rose and scale bar xrose = np.array([-15.5, -15.5]) yrose = np.array([15.5, 15.5]) xroseLen = np.array([20.0, 0.0]) yroseLen = np.array([0.0, 20.0]) py.clf() py.close(1) py.close(2) def drawImage(xlo, xhi, ylo, yhi): py.figure(2, figsize=(9, 9)) py.grid(True) py.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95) py.imshow(np.log10(im), extent=[xim[0], xim[-1], yim[0], yim[-1]], aspect='equal', vmin=2.0, vmax=4.0, cmap=py.cm.gray) py.xlabel('X Offset from Sgr A* (arcsec)') py.ylabel('Y Offset from Sgr A* (arcsec)') py.title('UCLA/Keck Galactic Center Group', fontsize=20, fontweight='bold') thePlot = py.gca() # Plot label.dat points py.plot(x_lab, y_lab, 'rs') for ii in range(len(x_lab)): py.text(x_lab[ii], y_lab[ii], n_lab[ii], color='red', fontsize=10) # Plot align points py.plot(x_aln, y_aln, 'bo') for ii in range(len(x_aln)): py.text(x_aln[ii], y_aln[ii], n_aln[ii], color='blue', fontsize=10) py.axis([xlo, xhi, ylo, yhi]) # We can do some matching here to help us out. drawImage(15, -15, -15, 15) if showStars: fmt = '%-11s %4.1f %9.5f %9.5f %8.5f %8.5f %8.3f %8.3f %7.3f %7.3f %8.3f %1d %5.3f\n' gcutil.rmall(['label_updated.dat']) out = open('label_updated.dat', 'w') out.write( '#Name K x y xerr yerr vx vy vxerr vyerr t0 use? r2d\n' ) out.write( '#() (mag) (asec) (asec) (asec) (asec) (mas/yr) (mas/yr) (mas/yr) (mas/yr) (year) () (asec)\n' ) foo = raw_input('Continue?') for ss in range(len(x_lab)): update = 0 idx = np.where(n_aln == n_lab[ss])[0] # The rest of the code allows us to find stars that were not matched # between the old label and new absolute alignment. # This will write out the new info from absolute alignment to a new # label_updated.dat file for just those stars that weren't matched properly, # but still need to run updateLabelInfoWithAbsRefs() to update the info # for stars that were matched. if len(idx) == 0: dr = np.hypot(x_aln - x_lab[ss], y_aln - y_lab[ss]) rdx = np.where(dr < 0.2)[0] if len(rdx) > 0: xlo = x_lab[ss] + 0.2 xhi = x_lab[ss] - 0.2 ylo = y_lab[ss] - 0.2 yhi = y_lab[ss] + 0.2 py.axis([xlo, xhi, ylo, yhi]) print 'Did not find a match for %s (K=%4.1f x=%7.3f y = %7.3f):' % \ (n_lab[ss], label.mag[ss], x_lab[ss], y_lab[ss]) for rr in rdx: print fmt % \ (n_aln[rr], mag[rr], x0[rr], y0[rr], x0err[rr], y0err[rr], vx[rr]*10**3, vy[rr]*10**3, vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], use[ss], r[rr]) # if the starname in align has the same ending as the name in # label.dat, it's likely the same star (e.g. '1S9-87' and 'S9-87'; # Note that this is the naming used in mosaicked star list analysis) if n_aln[rr].endswith(n_lab[ss]): # do a check that these stars have similar magnitudes if np.abs(label.mag[ss] - mag[rr]) <= 0.5: update = 1 # replace the whole line in label_updated.dat out.write(fmt % \ (n_lab[ss], mag[rr], x0[rr], y0[rr], x0err[rr], y0err[rr], vx[rr]*10**3, vy[rr]*10**3, vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], use[ss], r[rr])) continue else: foo = raw_input( 'Similar names, but magnitudes are off. Check star %s manually and decide whether or not to replace it in label_updated.dat when this program completes. Hit enter to continue.' % n_aln[rr]) # Or the star just wasn't matched with any star in the old label.dat file # and was given an arbitrary name elif (('star' in n_aln[rr]) | ('ep' in n_aln[rr])): print 'Manually check and update this star if needed:' print 'Name in label: %s' % n_lab[ss] print 'Name in new alignment: %s' % n_aln[rr] if len(rdx) > 1: print 'CAUTION: There are other nearby stars, including:' for ii in range(len(rdx)): print n_aln[rdx[ii]] update = raw_input( 'Update with %s velocity? (enter 1 for yes; 0 for no) ' % n_aln[rr]) update = int(update) if update == 1: out.write(fmt % \ (n_lab[ss], mag[rr], x0[rr], y0[rr], x0err[rr], y0err[rr], vx[rr]*10**3, vy[rr]*10**3, vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], use[ss], r[rr])) # check magnitude offset #if np.abs(label.mag[ss] - mag[rr]) <= 0.5: # update = 1 # # replace the whole line in label_updated.dat # out.write(fmt % \ # (n_lab[ss], mag[rr], x0[rr], y0[rr], x0err[rr], # y0err[rr], vx[rr]*10**3, vy[rr]*10**3, # vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], 1, r[rr])) if update == 0: # just re-write what was in label.dat, and later run # updateLabelInfoWithAbsRefs() to update matched stars with the new # absolute alignment out.write(fmt % \ (label.ourName[ss], label.mag[ss], label.x[ss], label.y[ss], label.xerr[ss], label.yerr[ss], label.vx[ss], label.vy[ss], label.vxerr[ss], label.vyerr[ss], label.t0[ss], use[ss], label.r[ss])) out.close()
def call_fit_mtf(imageRoot, dataDir='/u/jlu/data/w51/09jun26/combo/', starsSuffix='_0.8_stf.lis', resolvedSources=None, maskSize=150, xcenter=None, ycenter=None, clip=0.02, weights=None, outDir='./'): """ weights - {None, 'std', 0.1} where the last can be any scale factor. None = no weighting, or same as constant weights. 'std' = use 1 / standard deviation of averaged 1D power spectrum. <frac> = use 1 / (any scale factor * 'std') """ ############################## # H-band wide image ############################## imageFile = dataDir + imageRoot + '.fits' img, hdr = pyfits.getdata(imageFile, header=True) wavelength = hdr['CENWAVE'] * 1e-6 focallength = mtf.Fvalues[hdr['CAMNAME'].strip()] pupil = hdr['PMSNAME'] # Mask resolved sources if resolvedSources != None: print 'MTF: Masking %d resolved sources' % len(resolvedSources) img = mask_image(imageFile, resolvedSources, maskSize=maskSize) gcutil.rmall([outDir + imageRoot + '_masked.fits']) pyfits.writeto(outDir + imageRoot + '_masked.fits', img) print 'MTF: Set initial guesses for parameters' #definitions of starting parameters [from fitmtf_keck.pro] # # wave=1.65d-6 # wavelength in meters # F=557.0 # effective focal length of Keck AO (narrow) # D=10.99 # primary's diameter in meters # pupil=0.266 # central obscuration # pupil='largehex' # NIRC2 pupil-stop # Apix=27d-6 # width of detector's pixel in meters # L0=20. # outer scale of turbulence in meters # sigma=.56 # Infl Func width on primary in meters # w=1.3 # Influence Function height # Delta=0 # wavefront measurement error # Cmult=10. # multiplicative constant # N=1d-2 # additive noise floor constant # r0=0.5 # wavelength specific fried parameter in meters startp = {'wave': wavelength, 'D': 10.99, 'F': focallength, 'Apix': 27e-6, 'pupil': pupil, 'r0': 0.5, 'L0': 30.0, 'cmult': 1.0, 'N': 1e-5, 'w': 1.3, 'delta': 0.0, 'sigma': 0.56,} # Load up the starfinder results for this image print 'MTF: Read in preliminary starlist.' stfLis = dataDir + 'starfinder/' + imageRoot + starsSuffix table = asciidata.open(stfLis) name = table[0].tonumpy() mag = table[1].tonumpy() x = table[3].tonumpy() y = table[4].tonumpy() flux = 10**((mag[0] - mag)/2.5) # Create sources array (delta functions * flux) for the stars. print 'MTF: Creating 2D source array' sources = np.zeros(img.shape, dtype=float) sources[np.array(y, dtype=int), np.array(x, dtype=int)] = flux # If this is a wide camera image, trim down to the central 512x512 # in order to limit the impact of anisoplanatism. if hdr['CAMNAME'].strip() == 'wide': # Make image square new_size = (np.array(img.shape) / 2.0).min() xlo = xcenter - (new_size/2) xhi = xcenter + (new_size/2) ylo = ycenter - (new_size/2) yhi = ycenter + (new_size/2) img = img[ylo:yhi, xlo:xhi] sources = sources[ylo:yhi, xlo:xhi] py.figure(2) py.clf() py.imshow(np.log10(img)) py.draw() py.figure(1) print 'MTF: Calling getmtf' foo = mtf.get_mtf(img, startp, sources=sources) nu = foo[0] power = foo[1] error = foo[2] pspec_sources = foo[3] weightMsg = 'Weighting by 1 / STD of azimuthal average power spectrum' # Defuault, assume weight = 'std' and just use the # standard deviation of azimuthal average of the power spectrum. if weights == None: weightMsg = 'Unweighted' error = np.ones(len(error)) if (type(weights) == float) and (weights <= 1) and (weights > 0): weightMsg = 'Weighting by 1 / power * scaleFactor of %.3f' % weights error = power * weights print weightMsg # Fit the power spectrum print 'MTF: Fitting the power spectrum (round 1)' fit = mtf.fitmtf_keck(nu, power, error, pspec_sources, startParams=startp, relStep=0.2, clip=clip) print 'MTF: Fitting the power spectrum (round 2)' fit = mtf.fitmtf_keck(nu, power, error, pspec_sources, startParams=fit.params, relStep=0.02, clip=clip) pspec_fit = mtf.mtffunc_keck(fit.params, nu=nu, sources=pspec_sources) mtfOut = mtf.mtffunc_keck(fit.params, nu=nu) print 'Calculating PSF' # PSF psf2d, psf1d = mtf.mtf2psf(fit.params, 2.0) print 'Calculating EE ' # Encircled Energy pix = np.arange(100, dtype=float) ee = mtf.mtf2ee(fit.params, pix) print 'Calculating Strehl' # Strehl sr = mtf.strehl(fit.params) # Make some output objects p_obs = objects.DataHolder() p_obs.nu = nu p_obs.pspec = power p_obs.pspec_error = error p_obs.pspec_sources = pspec_sources p_fit = objects.DataHolder() p_fit.all_params = fit.params p_fit.all_errors = fit.perror p_fit.fit_params = fit.fit_params p_fit.fit_covar = fit.fit_covar p_fit.fit_stat = fit.fit_stat p_fit.pspec_fit = pspec_fit p_fit.mtf_system = mtfOut p_fit.mtf_perfect = fit.tperf p_fit.psf1d = psf1d p_fit.psf2d = psf2d p_fit.strehl = sr p_fit.encircled_energy = ee # Save output to a pickle file outfile = open(outDir + imageRoot + '_mtf.pickle', 'w') pickle.dump(p_obs, outfile) pickle.dump(p_fit, outfile) outfile.close()
def gc_ast_err_vs_snr(n_init=0, n_sims=10): """ Analyze how starfinder astrometric error changes with signal-to-noise ratio. Do this by planting known GC stars on a simulated sky background and readnoise/dark current image. Then try to recover the stars with starfinder and measure the astrometric errors. """ workDir = '/u/jlu/work/gc/ao_performance/ast_err_vs_snr/gc/' sky, dc, noise, gain = image_noise_properites() # IN e- background = (sky + dc) # in e- imgCount = 150 # The total number of individual exposures that went # into this image. print '' print 'SIMULATED IMAGE PROPERTIES:' print ' assuming %d science exposures' % imgCount print ' constant = %.1f DN (%.1f e-)' % (background/gain, background) print ' additional noise approximated with gaussian' print ' sigma = %.1f DN (%.1f e-)' % (noise/gain, noise) # Start with the background that Starfinder fit... it is smoothed. img = pyfits.getdata('mag10maylgs_kp_back.fits') img += background * gain # Noise from read out and sky subtraction (in e-) otherNoise = stats.norm.rvs(scale=noise, size=img.shape) # We are going to plant stars on this image using one of our # own PSFs. Each star we plant has to have photon noise from # itself as well. psf, hdr = pyfits.getdata('mag10maylgs_kp_psf.fits', header=True) # Repair the PSF so we don't have negative values idx1 = np.where(psf <= 0) idx2 = np.where(psf > 0) psf[idx1] = psf[idx2].min() # Read in the GC starlist gcstars = starTables.StarfinderList('mag10maylgs_kp_rms.lis', hasErrors=True) allIDLroots = [] for nn in range(n_init, n_init+n_sims): # Create a new image newImage = img.copy() # Now plant the stars for ii in range(len(gcstars.x)): mag = gcstars.mag[ii] flux = gcstars.counts[ii] # We need to add photon noise to the PSF. # Scale up the PSF temporarily since poisson() only # returns integers. tmp = psf * flux * gain # set flux=1 since we already scaled it. starPlant.addStar(newImage, tmp, gcstars.x[ii]+1.0, gcstars.y[ii]+1.0, 1.0) # Planted positions are actually rounded to the nearest # pixel to avoid interpolation noise.... do the same in the # input star list. gcstars.x[ii] = round(gcstars.x[ii]) gcstars.y[ii] = round(gcstars.y[ii]) # Fix negative pixels idx = np.where(newImage < 0) newImage[idx] = 0 # Now add noise to the image, compensate for large number of exposures newImage = stats.poisson.rvs((newImage * imgCount).tolist()) newImage = np.array(newImage, dtype=float) # necessary for starfinder newImage /= imgCount newImage += otherNoise # Subtract off sky/dark newImage -= background # Convert back to DN newImage /= gain # Save the new image, and copy over all the necessary files. suffix = str(nn).zfill(4) fitsFile = 'sim_img_%s.fits' % suffix psfFile = 'sim_img_%s_psf.fits' % suffix backFile = 'sim_img_%s_back.fits' % suffix cooFile = 'sim_img_%s.coo' % suffix lisFile = 'sim_orig_%s.lis' % suffix print 'Writing ', fitsFile gcutil.rmall([fitsFile]) pyfits.writeto(fitsFile, newImage, hdr, output_verify='silentfix') shutil.copyfile('mag10maylgs_kp_psf.fits', psfFile) shutil.copyfile('mag10maylgs_kp_back.fits', backFile) shutil.copyfile('mag10maylgs_kp.coo', cooFile) gcstars.saveToFile(lisFile) # Write out a starfinder batch file idlRoot = 'idl_sim_img_%s' % suffix _batch = open(idlRoot + '.batch', 'w') _batch.write("find_stf, ") _batch.write("'" + fitsFile + "', 0.8, /trimfake\n") _batch.write("exit\n") _batch.close() gcutil.rmall([idlRoot + '.log']) allIDLroots.append(idlRoot) for root in allIDLroots: print 'idl < %s.batch >& %s.log' % (root, root)
def plotLabelAndAlign(alignRoot, polyRoot, magCut=25, labelFile='label.dat', showStars=True): label = starTables.Labels(labelFile) label.take(np.where(label.mag < magCut)[0]) t = 2005.580 x_lab = label.x + label.vx * (t - label.t0) / 10**3 y_lab = label.y + label.vy * (t - label.t0) / 10**3 n_lab = label.ourName use = label.useToAlign # Now read in the align stuff s = starset.StarSet(alignRoot) s.loadPolyfit(polyRoot, accel=0) mag = s.getArray('mag') idx = np.where(mag < magCut)[0] s.stars = [s.stars[ii] for ii in idx] n_aln = np.array(s.getArray('name')) mag = s.getArray('mag') x0 = s.getArray('fitXv.p') * -1.0 y0 = s.getArray('fitYv.p') x0err = s.getArray('fitXv.perr') y0err = s.getArray('fitYv.perr') vx = s.getArray('fitXv.v') * -1.0 vy = s.getArray('fitYv.v') vxerr = s.getArray('fitXv.verr') vyerr = s.getArray('fitYv.verr') t0x = s.getArray('fitXv.t0') t0y = s.getArray('fitYv.t0') r = np.hypot(x0, y0) x_aln = x0 + vx * (t - t0x) y_aln = y0 + vy * (t - t0y) # Fix x0err, y0err to some minimum value idx = np.where(x0err < 0.0001)[0] x0err[idx] = 0.0001 idx = np.where(y0err < 0.0001)[0] y0err[idx] = 0.0001 # First lets update the 16 sources since they are used # to align label.dat to the reference epoch (crude I know) names16 = ['irs16C', 'irs16NW', 'irs16CC', 'irs16NE', 'irs16SW', 'irs16SW-E', 'irs33N', 'irs33E'] for nn in range(len(names16)): idx = np.where(n_aln == names16[nn])[0] for rr in idx: print '%-11s %4.1f %6.3f %6.3f %7.4f %7.4f %8.3f %8.3f %7.3f %7.3f %8.3f 1 %5.3f' % \ (n_aln[rr], mag[rr], x0[rr], y0[rr], x0err[rr], y0err[rr], vx[rr]*10**3, vy[rr]*10**3, vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], r[rr]) # Image imageFile = '/u/ghezgroup/data/gc/' imageFile += '06maylgs1/combo/mag06maylgs1_dp_msc_kp.fits' im = pyfits.getdata(imageFile) imgsize = (im.shape)[0] # pixel position (0,0) is at upper left xpix = np.arange(0, im.shape[0], dtype=float) ypix = np.arange(0, im.shape[1], dtype=float) sgra = [1422.6, 1543.8] scale_jpg = 0.00994 xim = (xpix - sgra[0]) * scale_jpg * -1.0 yim = (ypix - sgra[1]) * scale_jpg # Lets also make some coordinates for compass rose and scale bar xrose = np.array([-15.5, -15.5]) yrose = np.array([15.5, 15.5]) xroseLen = np.array([20.0, 0.0]) yroseLen = np.array([0.0, 20.0]) py.clf() py.close(1) py.close(2) def drawImage(xlo, xhi, ylo, yhi): py.figure(2, figsize=(9, 9)) py.grid(True) py.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95) py.imshow(np.log10(im), extent=[xim[0], xim[-1], yim[0], yim[-1]], aspect='equal', vmin=2.0, vmax=4.0, cmap=py.cm.gray) py.xlabel('X Offset from Sgr A* (arcsec)') py.ylabel('Y Offset from Sgr A* (arcsec)') py.title('UCLA/Keck Galactic Center Group', fontsize=20, fontweight='bold') thePlot = py.gca() # Plot label.dat points py.plot(x_lab, y_lab, 'rs') for ii in range(len(x_lab)): py.text(x_lab[ii], y_lab[ii], n_lab[ii], color='red', fontsize=10) # Plot align points py.plot(x_aln, y_aln, 'bo') for ii in range(len(x_aln)): py.text(x_aln[ii], y_aln[ii], n_aln[ii], color='blue', fontsize=10) py.axis([xlo, xhi, ylo, yhi]) # We can do some matching here to help us out. drawImage(15, -15, -15, 15) if showStars: fmt = '%-11s %4.1f %9.5f %9.5f %8.5f %8.5f %8.3f %8.3f %7.3f %7.3f %8.3f %1d %5.3f\n' gcutil.rmall(['label_updated.dat']) out = open('label_updated.dat','w') out.write('#Name K x y xerr yerr vx vy vxerr vyerr t0 use? r2d\n') out.write('#() (mag) (asec) (asec) (asec) (asec) (mas/yr) (mas/yr) (mas/yr) (mas/yr) (year) () (asec)\n') foo = raw_input('Continue?') for ss in range(len(x_lab)): update = 0 idx = np.where(n_aln == n_lab[ss])[0] # The rest of the code allows us to find stars that were not matched # between the old label and new absolute alignment. # This will write out the new info from absolute alignment to a new # label_updated.dat file for just those stars that weren't matched properly, # but still need to run updateLabelInfoWithAbsRefs() to update the info # for stars that were matched. if len(idx) == 0: dr = np.hypot(x_aln - x_lab[ss], y_aln - y_lab[ss]) rdx = np.where(dr < 0.2)[0] if len(rdx) > 0: xlo = x_lab[ss] + 0.2 xhi = x_lab[ss] - 0.2 ylo = y_lab[ss] - 0.2 yhi = y_lab[ss] + 0.2 py.axis([xlo, xhi, ylo, yhi]) print 'Did not find a match for %s (K=%4.1f x=%7.3f y = %7.3f):' % \ (n_lab[ss], label.mag[ss], x_lab[ss], y_lab[ss]) for rr in rdx: print fmt % \ (n_aln[rr], mag[rr], x0[rr], y0[rr], x0err[rr], y0err[rr], vx[rr]*10**3, vy[rr]*10**3, vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], use[ss], r[rr]) # if the starname in align has the same ending as the name in # label.dat, it's likely the same star (e.g. '1S9-87' and 'S9-87'; # Note that this is the naming used in mosaicked star list analysis) if n_aln[rr].endswith(n_lab[ss]): # do a check that these stars have similar magnitudes if np.abs(label.mag[ss] - mag[rr]) <= 0.5: update = 1 # replace the whole line in label_updated.dat out.write(fmt % \ (n_lab[ss], mag[rr], x0[rr], y0[rr], x0err[rr], y0err[rr], vx[rr]*10**3, vy[rr]*10**3, vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], use[ss], r[rr])) continue else: foo = raw_input('Similar names, but magnitudes are off. Check star %s manually and decide whether or not to replace it in label_updated.dat when this program completes. Hit enter to continue.' % n_aln[rr]) # Or the star just wasn't matched with any star in the old label.dat file # and was given an arbitrary name elif (('star' in n_aln[rr]) | ('ep' in n_aln[rr])): print 'Manually check and update this star if needed:' print 'Name in label: %s' % n_lab[ss] print 'Name in new alignment: %s' % n_aln[rr] if len(rdx) > 1: print 'CAUTION: There are other nearby stars, including:' for ii in range(len(rdx)): print n_aln[rdx[ii]] update = raw_input('Update with %s velocity? (enter 1 for yes; 0 for no) ' % n_aln[rr]) update = int(update) if update == 1: out.write(fmt % \ (n_lab[ss], mag[rr], x0[rr], y0[rr], x0err[rr], y0err[rr], vx[rr]*10**3, vy[rr]*10**3, vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], use[ss], r[rr])) # check magnitude offset #if np.abs(label.mag[ss] - mag[rr]) <= 0.5: # update = 1 # # replace the whole line in label_updated.dat # out.write(fmt % \ # (n_lab[ss], mag[rr], x0[rr], y0[rr], x0err[rr], # y0err[rr], vx[rr]*10**3, vy[rr]*10**3, # vxerr[rr]*10**3, vyerr[rr]*10**3, t0x[rr], 1, r[rr])) if update == 0: # just re-write what was in label.dat, and later run # updateLabelInfoWithAbsRefs() to update matched stars with the new # absolute alignment out.write(fmt % \ (label.ourName[ss], label.mag[ss], label.x[ss], label.y[ss], label.xerr[ss], label.yerr[ss], label.vx[ss], label.vy[ss], label.vxerr[ss], label.vyerr[ss], label.t0[ss], use[ss], label.r[ss])) out.close()
def plotWithHST(rotateFITS=True): # Load up the OSIRIS image cubeFile = datadir + cuberoot + "_img.fits" cube, cubehdr = pyfits.getdata(cubeFile, header=True) paCube = cubehdr["PA_SPEC"] scaleCube = 0.05 # Load up the NIRC2 image kFile = "/u/jlu/data/m31/05jul/combo/m31_05jul_kp.fits" # kFile = '/u/jlu/data/m31/09sep/combo/mag09sep_m31_kp.fits' k, khdr = pyfits.getdata(kFile, header=True) m31K = np.array([751.986, 716.989]) paK = 0.0 scaleK = 0.00995 f330Root = "/u/jlu/data/m31/hst/m31_acshrc_f330w_j9am01030" f435Root = "/u/jlu/data/m31/hst/m31_acshrc_f435w_j9am01010" f555Root = "/u/jlu/data/m31/hst/m31_wfpc2pc1_f555w_u2lg020at" f814Root = "/u/jlu/data/m31/hst/m31_wfpc2pc1_f814w_u2lg020bt" ########## # Rotate all the HST images to PA=0, scale=NIRC2 ########## if rotateFITS == True: # Load up the HST ACS image (330 nm) f330File = f330Root + ".fits" f330FileRot = f330Root + "_rot.fits" f330, f330hdr = pyfits.getdata(f330File, 1, header=True) m31F330 = np.array([547.0, 623.2]) paF330 = f330hdr["ORIENTAT"] scaleF330 = 0.025 # Load up the HST ACS image (435 nm) f435File = f435Root + ".fits" f435FileRot = f435Root + "_rot.fits" f435, f435hdr = pyfits.getdata(f435File, 1, header=True) m31F435 = np.array([546.9, 623.5]) paF435 = f435hdr["ORIENTAT"] scaleF435 = 0.025 # Load up the HST ACS image (555 nm) f555File = f555Root + ".fits" f555FileRot = f555Root + "_rot.fits" f555, f555hdr = pyfits.getdata(f555File, 1, header=True) m31F555 = np.array([973.0, 961.0]) paF555 = f555hdr["ORIENTAT"] scaleF555 = 0.1 # Load up the HST ACS image (814 nm) f814File = f814Root + ".fits" f814FileRot = f814Root + "_rot.fits" f814, f814hdr = pyfits.getdata(f814File, 1, header=True) m31F814 = np.array([975.0, 962.0]) paF814 = f814hdr["ORIENTAT"] scaleF814 = 0.1 print "scaleK = ", scaleK print "scaleF330 = ", scaleF330 print "scaleF435 = ", scaleF435 print "scaleF555 = ", scaleF555 print "scaleF814 = ", scaleF814 print "paK = ", paK print "paF330 = ", paF330 print "paF435 = ", paF435 print "paF555 = ", paF555 print "paF814 = ", paF814 gcutil.rmall([f330FileRot, f435FileRot, f555FileRot, f814FileRot]) from pyraf import iraf as ir ir.unlearn("imlintran") ir.imlintran.boundary = "constant" ir.imlintran.constant = 0 ir.imlintran.interpolant = "spline3" ir.imlintran.fluxconserve = "yes" # 330 ir.imlintran.xin = m31F330[0] ir.imlintran.yin = m31F330[1] ir.imlintran.xout = m31K[0] ir.imlintran.yout = m31K[1] ir.imlintran.ncols = k.shape[1] ir.imlintran.nlines = k.shape[0] ir.imlintran(f330File + "[1]", f330FileRot, paF330, paF330, scaleK / scaleF330, scaleK / scaleF330) # 435 ir.imlintran.xin = m31F435[0] ir.imlintran.yin = m31F435[1] ir.imlintran.xout = m31K[0] ir.imlintran.yout = m31K[1] ir.imlintran.ncols = k.shape[1] ir.imlintran.nlines = k.shape[0] ir.imlintran(f435File + "[1]", f435FileRot, paF435, paF435, scaleK / scaleF435, scaleK / scaleF435) # 555 ir.imlintran.xin = m31F555[0] ir.imlintran.yin = m31F555[1] ir.imlintran.xout = m31K[0] ir.imlintran.yout = m31K[1] ir.imlintran.ncols = k.shape[1] ir.imlintran.nlines = k.shape[0] ir.imlintran(f555File + "[1]", f555FileRot, paF555, paF555, scaleK / scaleF555, scaleK / scaleF555) # 814 ir.imlintran.xin = m31F814[0] ir.imlintran.yin = m31F814[1] ir.imlintran.xout = m31K[0] ir.imlintran.yout = m31K[1] ir.imlintran.ncols = k.shape[1] ir.imlintran.nlines = k.shape[0] ir.imlintran(f814File + "[1]", f814FileRot, paF814, paF814, scaleK / scaleF814, scaleK / scaleF814) f330 = pyfits.getdata(f330Root + "_rot.fits") f435 = pyfits.getdata(f435Root + "_rot.fits") img = np.zeros((k.shape[0], k.shape[1], 3), dtype=float) img[:, :, 0] = img_scale.linear(k, scale_min=300, scale_max=2400) img[:, :, 1] = img_scale.linear(f435, scale_min=0.45, scale_max=1.8) img[:, :, 2] = img_scale.linear(f330, scale_min=0, scale_max=0.16) # Axes xaxis = (np.arange(img.shape[0], dtype=float) - m31K[0]) * 0.00995 yaxis = (np.arange(img.shape[1], dtype=float) - m31K[1]) * 0.00995 py.clf() py.imshow(img, aspect="equal", extent=[xaxis[0], xaxis[-1], yaxis[0], yaxis[-1]]) # py.plot([m31K[0]], [m31K[1]], 'ko') # py.axis([625, 825, 650, 850]) py.plot([0], [0], "k+") py.axis([-1.5, 1.5, -1.5, 1.5]) py.xlabel("X Offset from M31* (arcsec)") py.ylabel("Y Offset from M31* (arcsec)") py.title("Blue = F330W, Green = F435W, Red = Kband") py.savefig(workdir + "plots/hst_nirc2_rgb.png") py.show()
def ast_err_vs_snr(n_init=0, n_sims=1000): """ Analyze how starfinder astrometric error changes with signal-to-noise ratio. Do this by planting stars on a simulated sky background and readnoise/dark current image. Then try to recover the stars with starfinder and measure the astrometric errors. """ sky, dc, noise, gain = image_noise_properites() # IN e- background = (sky + dc) # in e- imgCount = 150 # The total number of individual exposures that went # into this image. print '' print 'SIMULATED IMAGE PROPERTIES:' print ' assuming %d science exposures' % imgCount print ' constant = %.1f DN (%.1f e-)' % (background/gain, background) print ' additional noise approximated with gaussian' print ' sigma = %.1f DN (%.1f e-)' % (noise/gain, noise) img = np.zeros((1024, 1024), dtype=float) img += background # Noise from read out and sky subtraction (in e-) otherNoise = stats.norm.rvs(scale=noise, size=(1024,1024)) # We are going to plant stars on this image using one of our # own PSFs. Each star we plant has to have photon noise from # itself as well. psf, hdr = pyfits.getdata('mag10maylgs_kp_psf.fits', header=True) # Repair the PSF so we don't have negative values idx1 = np.where(psf <= 0) idx2 = np.where(psf > 0) psf[idx1] = psf[idx2].min() # Seperate the PSFs by 2" since this is the Starfinder box size. step = 200 # in pixels # Pulled these numbers from the calibrated starlists for 10maylgs. mag0 = 9.782 flux0 = 20522900.000 # Randomly select from a distribution of magnitudes. magMin = 9.0 magMax = 22.0 # Number of samples (stars planted) #numStars = 100 stopN = n_sims + n_init allIDLroots = [] nn = n_init while nn <= stopN: # Create a new image newImage = img.copy() brightCoords = None brightMag = 1000 # Make a new starlist with the input info. newStars = starTables.StarfinderList(None, hasErrors=False) # Now plant the stars for xx in range(step, img.shape[1]-step, step): for yy in range(step, img.shape[0]-step, step): mag = np.random.uniform(magMin, magMax) flux = flux0 * 10**(-0.4 * (mag - mag0)) # We need to add photon noise to the PSF. # Scale up the PSF temporarily since poisson() only # returns integers. tmp = psf * flux * gain #print '%4s x = %4d y = %4d mag = %5.2f flux = %.2f' % \ # (nn, xx, yy, mag, flux) newName = 'sim_%s' % str(nn).zfill(4) # set flux=1 since we already scaled it. starPlant.addStar(newImage, tmp, xx, yy, 1.0) newStars.append(newName, mag, xx-1, yy-1, counts=flux, epoch=2010.342) # Updare our record of the brightest star in the image. if mag < brightMag: brightMag = mag brightCoords = [xx, yy] nn += 1 # Fix negative pixels idx = np.where(newImage < 0) newImage[idx] = 0 # Now add noise to the image, compensate for large number of exposures newImage = stats.poisson.rvs((newImage * imgCount).tolist()) newImage = np.array(newImage, dtype=float) # necessary for starfinder newImage /= imgCount newImage += otherNoise # Subtract off sky/dark newImage -= background # Convert back to DN newImage /= gain # Make a background image. img_back = np.zeros((1024, 1024), dtype=float) # Save the new image, and copy over all the necessary files. suffix = str(nn).zfill(4) fitsFile = 'sim_img_%s.fits' % suffix psfFile = 'sim_img_%s_psf.fits' % suffix backFile = 'sim_img_%s_back.fits' % suffix cooFile = 'sim_img_%s.coo' % suffix lisFile = 'sim_orig_%s.lis' % suffix print 'Writing ', fitsFile gcutil.rmall([fitsFile, backFile]) pyfits.writeto(fitsFile, newImage, hdr, output_verify='silentfix') pyfits.writeto(backFile, img_back, hdr, output_verify='silentfix') # Resort the starlist so the brightest star is at the top mdx = newStars.mag.argsort() newStars.name = newStars.name[mdx] newStars.mag = newStars.mag[mdx] newStars.epoch = newStars.epoch[mdx] newStars.x = newStars.x[mdx] newStars.y = newStars.y[mdx] newStars.snr = newStars.snr[mdx] newStars.corr = newStars.corr[mdx] newStars.nframes = newStars.nframes[mdx] newStars.counts = newStars.counts[mdx] newStars.saveToFile(lisFile) shutil.copyfile('mag10maylgs_kp_psf.fits', psfFile) _coo = open(cooFile, 'w') _coo.write('%.2f %.2f\n' % (brightCoords[0], brightCoords[1])) _coo.close() # Write out a starfinder batch file idlRoot = 'idl_sim_img_%s' % suffix _batch = open(idlRoot + '.batch', 'w') _batch.write("find_stf, ") _batch.write("'" + fitsFile + "', 0.8, /trimfake\n") _batch.write("exit\n") _batch.close() gcutil.rmall([idlRoot + '.log']) allIDLroots.append(idlRoot) for root in allIDLroots: print 'idl < %s.batch >& %s.log' % (root, root)
def makeData(self, remakeImages=True, stepPerRun=2, stepFinal=0.5, magMin=None, magMax=None, magStep=0.25, magBins=None, xyinit=None): """ Make data with artificial stars added. Copy over all the necessary files to be able to re-run starfinder. remakeImages (def=True) - remake all the fits files and starlists. If False, then just ste some variables. psfBoxSize - The size of the PSF in arcsec. stepPerRun - The seperation between planted stars per Starfinder run in arcseconds. The default is 2 which is the PSF box size (so no overlap). stepFinal - The final seperation between artificial stars when considering the sum of all grids (arcsec). magMin - The minimum magnitude of stars to simulate. If None, then use the minimum magnitude of stars in the data itself. magMax - The maximum magnitude of stars to simulate.If None, then use the maximum magnitude of stars in the data itself. magStep - The step size of the magnitude bins. Default = 0.25. """ self.fitsFile = self.imageRoot + '.fits' self.psfFile = self.imageRoot + '_psf.fits' self.backFile = self.imageRoot + '_back.fits' self.maxFile = self.imageRoot + '.max' self.cooFile = self.imageRoot + '.coo' # Generate a list of sources to be planted in the image. This # should be done one magnitude bin at a time. pixelScale = 0.01 # arcsec/pixel stepPerRun /= pixelScale stepFinal /= pixelScale # Number of iterations per magnitude bin (in each direction) stepCountPerSide = round(stepPerRun / stepFinal) # Read in the image and starlist img, hdr = pyfits.getdata(self.fitsFile, header=True) psf = pyfits.getdata(self.psfFile) stars = starTables.StarfinderList(self.starlist, hasErrors=False) # Get the mag to flux scale factor (e.g. zeropoints). flux0 = stars.counts[0] / 10**(-0.4 * stars.mag[0]) xsize = img.shape[1] ysize = img.shape[0] if magMin == None: magMin = stars.mag.min()+0.1 if magMax == None: magMax = stars.mag.max() self.magMin = magMin self.magMax = magMax self.magStep = magStep magBins = np.arange(magMin, magMax, magStep) if xyinit == None: xyinit = np.array([stepFinal, stepFinal]) self.xyinit = xyinit newStarCount = 0 newFitsFiles = [] newStarlists = [] for mag in magBins: flux = flux0 * 10**(-0.4 * mag) for ii in range(stepCountPerSide): xinit_this_run = xyinit[0] + ii*stepFinal x1d = np.arange(xinit_this_run, xsize, stepPerRun) for kk in range(stepCountPerSide): yinit_this_run = xyinit[1] + kk*stepFinal y1d = np.arange(yinit_this_run, ysize, stepPerRun) # For each "run" we are going to make a new # fits file, a new starlist (copy of the old one but # with artificial stars added), and copy over # the PSF, background, coo, and max files for # running starfinder. newImageRoot = 'sim_img_%.2f_%d_%d' % (mag, ii, kk) newFitsFile = newImageRoot + '.fits' newStarlist = 'sim_orig_%.2f_%d_%d.lis' % (mag, ii, kk) if remakeImages: gcutil.rmall([newFitsFile, newStarlist]) newImage = np.zeros((ysize, xsize), dtype=float) newStars = starTables.StarfinderList(self.starlist, hasErrors=False) for x in x1d: for y in y1d: x = int(round(x)) y = int(round(y)) newName = 'sim_%d' % newStarCount newStarCount += 1 addStar(newImage, psf, x, y, flux) newStars.append(newName, mag, x-1, y-1, counts=flux) newImage += img # Save off the image pyfits.writeto(newFitsFile, newImage, hdr, output_verify='silentfix') # Copy over the PSF and background files shutil.copyfile(self.psfFile, newImageRoot + '_psf.fits') shutil.copyfile(self.backFile, newImageRoot + '_back.fits') shutil.copyfile(self.maxFile, newImageRoot + '.max') shutil.copyfile(self.cooFile, newImageRoot + '.coo') # Save off the starlist newStars.saveToFile(newStarlist) print 'Made simulated image: ', newFitsFile newFitsFiles.append(newFitsFile) newStarlists.append(newStarlist) self.newFitsFiles = newFitsFiles self.newStarlists = newStarlists
def mosaic_kp(): """ Make a mosaic of our NIRC2 data on W51, one per filter. """ hepochs = ['09jun26', '09jun26', '09jun26', '09jun26'] kepochs = ['09jun10', '09jun10', '09jun10', '09jun26'] lepochs = ['09jun26', '09jun26', '09jun26', '09jun26'] cooStarsH = ['f1_psf0', 'f2_psf0', 'f3_psf0', 'f4_psf0'] cooStarsK = ['f1_psf0', 'f2_psf0', 'f3_psf0', 'f4_psf0'] cooStarsL = ['f1_psf1', 'f2_psf0', 'f3_psf2', 'f4_psf1'] cooStarsH = ['E4-1', 'E8-1', 'N5-1', 'W6-2'] cooStarsK = ['E4-1', 'E8-1', 'N5-1', 'W6-2'] cooStarsL = ['S0-1', 'E8-1', 'W7-1', 'W9-1'] scaleMinH = [0, 0, 0, 0] scaleMinK = [0, 0, 0, 0] scaleMinL = [1000, 1100, 1200, 1250] scaleMaxH = [6000, 6000, 5000, 6000] scaleMaxK = [6500, 6500, 6500, 5500] scaleMaxL = [1600, 1300, 1400, 1600] img = np.zeros((2400, 2400, 3), dtype=float) imgH = np.zeros((2400, 2400), dtype=float) imgK = np.zeros((2400, 2400), dtype=float) imgL = np.zeros((2400, 2400), dtype=float) origin = np.array([1200.0, 1200.0]) labelFile = '/u/jlu/data/w51/source_list/w51a_label.dat' labels = starTables.Labels(labelFile=labelFile) dataRoot = '/u/jlu/data/w51/' py.clf() foo = range(len(hepochs)) for ii in foo[::-1]: # for ii in range(1): rootH = '%s/%s/combo/mag%s_w51a_f%d_h' % \ (dataRoot, hepochs[ii], hepochs[ii], ii+1) rootK = '%s/%s/combo/mag%s_w51a_f%d_kp' % \ (dataRoot, kepochs[ii], kepochs[ii], ii+1) rootL = '%s/%s/combo/mag%s_w51a_f%d_lp' % \ (dataRoot, lepochs[ii], lepochs[ii], ii+1) # Load up the images h, hhdr = pyfits.getdata(rootH + '.fits', header=True) k, khdr = pyfits.getdata(rootK + '.fits', header=True) l, lhdr = pyfits.getdata(rootL + '.fits', header=True) hint = hhdr['ITIME'] * hhdr['COADDS'] kint = khdr['ITIME'] * khdr['COADDS'] lint = lhdr['ITIME'] * lhdr['COADDS'] # Make the arrays into the largest size. h_new = np.zeros((img.shape[0], img.shape[1]), dtype=float) k_new = np.zeros((img.shape[0], img.shape[1]), dtype=float) l_new = np.zeros((img.shape[0], img.shape[1]), dtype=float) h_new[0:h.shape[0], 0:h.shape[1]] = h k_new[0:k.shape[0], 0:k.shape[1]] = k l_new[0:l.shape[0], 0:l.shape[1]] = l # Load up the coo stars tmpH = open(rootH + '.coo').readline().split() cooH = np.array([float(tmpH[0]), float(tmpH[1])]) tmpK = open(rootK + '.coo').readline().split() cooK = np.array([float(tmpK[0]), float(tmpK[1])]) tmpL = open(rootL + '.coo').readline().split() cooL = np.array([float(tmpL[0]), float(tmpL[1])]) # Get the coordinates of each coo star in arcsec. idxH = np.where(labels.name == cooStarsH[ii])[0][0] idxK = np.where(labels.name == cooStarsK[ii])[0][0] idxL = np.where(labels.name == cooStarsL[ii])[0][0] asecH = np.array([labels.x[idxH], labels.y[idxH]]) asecK = np.array([labels.x[idxK], labels.y[idxK]]) asecL = np.array([labels.x[idxL], labels.y[idxL]]) scale = np.array([-0.00995, 0.00995]) # Now figure out the necessary shifts originH = cooH - asecH / scale originK = cooK - asecK / scale originL = cooL - asecL / scale # Shift the J and H images to be lined up with K-band shiftL = origin - originL shiftK = origin - originK shiftH = origin - originH l = interp.shift(l_new, shiftL[::-1]) k = interp.shift(k_new, shiftK[::-1]) h = interp.shift(h_new, shiftH[::-1]) print shiftH print shiftL xx, yy = np.meshgrid(np.arange(img.shape[0]), np.arange(img.shape[1])) idx = np.where((h >= 1) & (k >= 1) & (l >= 1)) # Trim off the bottom 10 rows where there is data ymin = yy[idx[0], idx[1]].min() ydx = np.where(yy[idx[0], idx[1]] > (ymin + 10))[0] idx = (idx[0][ydx], idx[1][ydx]) img[idx[0], idx[1], 0] = img_scale.log(l[idx[0], idx[1]], scale_min=scaleMinL[ii], scale_max=scaleMaxL[ii]) img[idx[0], idx[1], 1] = img_scale.log(k[idx[0], idx[1]], scale_min=scaleMinK[ii], scale_max=scaleMaxK[ii]) img[idx[0], idx[1], 2] = img_scale.log(h[idx[0], idx[1]], scale_min=scaleMinH[ii], scale_max=scaleMaxH[ii]) imgH[idx[0], idx[1]] = h[idx[0], idx[1]] / hint imgK[idx[0], idx[1]] = k[idx[0], idx[1]] / kint imgL[idx[0], idx[1]] = l[idx[0], idx[1]] / lint # Fix scaling of first image. if ii == 0: imgK[idx[0], idx[1]] -= 0.4 # Save on memory l = None k = None h = None l_new = None k_new = None h_new = None # Define the axes xaxis = np.arange(-0.5, img.shape[1] + 0.5, 1) xaxis = ((xaxis - origin[0]) * scale[0]) yaxis = np.arange(-0.5, img.shape[0] + 0.5, 1) yaxis = ((yaxis - origin[1]) * scale[1]) extent = [xaxis[0], xaxis[-1], yaxis[0], yaxis[-1]] # py.figure(1) # py.imshow(img[:,:,0], extent=extent, cmap=py.cm.gray) # py.axis('equal') py.figure(2) py.imshow(img[:, :, 1], extent=extent, cmap=py.cm.gray) py.axis('equal') # py.figure(3) # py.imshow(img[:,:,2], extent=extent, cmap=py.cm.gray) # py.axis('equal') foo = raw_input('Continue?') gcutil.rmall( ['w51a_h_mosaic.fits', 'w51a_k_mosaic.fits', 'w51a_l_mosaic.fits']) pyfits.writeto('w51a_h_mosaic.fits', imgH) pyfits.writeto('w51a_k_mosaic.fits', imgK) pyfits.writeto('w51a_l_mosaic.fits', imgL)
def lgsAnimate(redoAlign=False, redoImages=False): dataRoot = '/u/ghezgroup/data/gc/' imgRoots = ['05jullgs', '06maylgs1', '06junlgs', '06jullgs', '07maylgs', '07auglgs', '08maylgs1', '08jullgs', '09maylgs', '10maylgs', '10jullgs1', '10auglgs1', '11maylgs', '11auglgs'] refEpoch = '08maylgs' workRoot = '/u/ghezgroup/public_html/gc/images/media/image_anim/' alignRoot = workRoot + 'align/align' if (redoAlign): # Copy over the starlists for epoch in imgRoots: lisFile = 'mag' + epoch + '_kp_rms.lis' copyFrom = dataRoot + epoch + '/combo/starfinder/' + lisFile copyTo = workRoot + 'lis/' shutil.copy(copyFrom, copyTo) lisFile = 'mag' + epoch + '_kp_rms_named.lis' copyFrom = dataRoot + epoch + '/combo/starfinder/' + lisFile copyTo = workRoot + 'lis/' shutil.copy(copyFrom, copyTo) # Align os.chdir(workRoot + 'align/') alignList = open(alignRoot + '.list', 'w') for epoch in imgRoots: lisFile = 'mag' + epoch + '_kp_rms.lis' alignList.write('../lis/' + lisFile + ' 9') if (epoch == refEpoch): alignList.write(' ref') alignList.write('\n') alignList.close() alignCmd = 'java align -a 2 -p ' alignCmd += '-N /u/ghezgroup/data/gc/source_list/label.dat ' #alignCmd += '-N /u/ghezgroup/data/gc/source_list/label_new.dat ' alignCmd += '-o /u/ghezgroup/data/gc/source_list/orbits.dat ' alignCmd += 'align.list' os.system(alignCmd) absCmd = 'java align_absolute ' absCmd += '-abs /u/ghezgroup/data/gc/source_list/absolute_refs.dat ' absCmd += 'align align_abs' os.system(absCmd) os.chdir(workRoot) s = starset.StarSet(alignRoot+'_abs') names = s.getArray('name') idx = names.index('SgrA') sgraxOrig = s.stars[idx].getArrayAllEpochs('xorig') sgrayOrig = s.stars[idx].getArrayAllEpochs('yorig') sgrax = s.stars[idx].getArrayAllEpochs('xpix') sgray = s.stars[idx].getArrayAllEpochs('ypix') print 'sgraxOrig = ', sgraxOrig print 'sgrax = ', sgrax print 'sgrayOrig = ', sgrayOrig print 'sgray = ', sgray # Tweak 05jullgs Sgr A* position, since it was not detected print print 'Tweaking 05jullgs Sgr A* position, since it was not named in the starlist' sgraxOrig[0] = 525.9 sgrayOrig[0] = 643.9 sgrax[0] = 0.0 sgray[0] = 0.0 print 'Update code with positions of Sgr A*' foo = raw_input('Continue? ') if (foo == 'q' or foo == 'Q'): return # Tweaks to Sgr A*'s positions (in arcseconds) # more negative goes to the right dx = array([-0.017, -0.002, -0.003, -0.005, 0.001, 0.00, 0.002, 0.001, 0.002, 0.001, 0.00, 0.00, 0.001, 0.00]) dy = array([ 0.005, 0.00, 0.00, 0.00, 0.001, 0.00, 0.00, -0.003, 0.00, 0.00, 0.000, 0.00, 0.000, 0.00]) # Color Ranges for Images - Log Scale vmin = array([2.48, 2.51, 2.45, 2.48, 2.50, 2.55, 2.50, 2.50, 2.50, 2.55, 2.53, 2.53, 2.53, 2.45]) vmax = array([3.45, 3.32, 3.38, 3.35, 3.40, 3.25, 3.3, 3.35, 3.3, 3.30, 3.30, 3.30, 3.30, 3.45]) # Image plate scale scale = 0.00995 if (len(imgRoots) != len(sgrax)): print 'Problem... images and align do not match. Compare to align.list' print imgRoots from gcreduce import gcutil import nirc2 if (redoImages): # Need to rotate images from pyraf import iraf as ir ir.unlearn('rotate') ir.rotate.boundary = 'constant' ir.rotate.constant = 0 ir.rotate.interpolant = 'spline3' # Need to plot images pylab.clf() for i in range(len(imgRoots)): imgIn = dataRoot + imgRoots[i] + '/combo/mag' + imgRoots[i] + '_kp.fits' imgOut = 'images/mag' + imgRoots[i] + '_rot.fits' hdr = pyfits.getheader(imgIn) phi = nirc2.getPA(hdr) if (redoImages): gcutil.rmall([imgOut]) ir.rotate.xin = sgraxOrig[i]+1 ir.rotate.yin = sgrayOrig[i]+1 ir.rotate.xout = (sgrax[i]/scale)+512+1 ir.rotate.yout = (sgray[i]/scale)+512+1 ir.rotate(imgIn, imgOut, phi) img = pyfits.getdata(imgOut) xax = arange(0, img.shape[1]) yax = arange(0, img.shape[0]) xax = (xax - 512.) * -scale + dx[i] yax = (yax - 512.) * scale + dy[i] # With labels and borders pylab.figure(1) pylab.clf() pylab.figure(figsize=(7,7)) pylab.imshow(log10(img), extent=[xax[0], xax[-1], yax[0], yax[-1]], vmin=vmin[i], vmax=vmax[i],origin='lowerleft') pylab.plot([0], [0], 'k+') #pylab.axis([0.5, -0.5, -0.5, 0.5]) #pylab.axis([0.8, -0.8, -0.8, 0.8]) #pylab.axis([3, -3, -3, 3]) pylab.axis([1, -1, -1, 1]) pylab.xlabel('RA Offset from Sgr A* (arcsec)') pylab.ylabel('Dec Offset from Sgr A* (arcsec)') pylab.title(imgRoots[i]) pylab.savefig('frame%d.png' % i) pylab.close(1) # No labels and borders pylab.figure(2) pylab.clf() pylab.figure(figsize=(6,6)) pylab.subplots_adjust(left=0, right=1, bottom=0, top=1) pylab.imshow(log10(img), extent=[xax[0], xax[-1], yax[0], yax[-1]], vmin=vmin[i], vmax=vmax[i],origin='lowerleft') pylab.plot([0], [0], 'k+') pylab.axis([0.5, -0.5, -0.5, 0.5]) pylab.axis('off') pylab.title(imgRoots[i]) pylab.savefig('frame%d_noborder.png' % i) pylab.close(2)
def gc_ast_err_vs_snr(n_init=0, n_sims=10): """ Analyze how starfinder astrometric error changes with signal-to-noise ratio. Do this by planting known GC stars on a simulated sky background and readnoise/dark current image. Then try to recover the stars with starfinder and measure the astrometric errors. """ workDir = '/u/jlu/work/gc/ao_performance/ast_err_vs_snr/gc/' sky, dc, noise, gain = image_noise_properites() # IN e- background = (sky + dc) # in e- imgCount = 150 # The total number of individual exposures that went # into this image. print '' print 'SIMULATED IMAGE PROPERTIES:' print ' assuming %d science exposures' % imgCount print ' constant = %.1f DN (%.1f e-)' % (background / gain, background) print ' additional noise approximated with gaussian' print ' sigma = %.1f DN (%.1f e-)' % (noise / gain, noise) # Start with the background that Starfinder fit... it is smoothed. img = pyfits.getdata('mag10maylgs_kp_back.fits') img += background * gain # Noise from read out and sky subtraction (in e-) otherNoise = stats.norm.rvs(scale=noise, size=img.shape) # We are going to plant stars on this image using one of our # own PSFs. Each star we plant has to have photon noise from # itself as well. psf, hdr = pyfits.getdata('mag10maylgs_kp_psf.fits', header=True) # Repair the PSF so we don't have negative values idx1 = np.where(psf <= 0) idx2 = np.where(psf > 0) psf[idx1] = psf[idx2].min() # Read in the GC starlist gcstars = starTables.StarfinderList('mag10maylgs_kp_rms.lis', hasErrors=True) allIDLroots = [] for nn in range(n_init, n_init + n_sims): # Create a new image newImage = img.copy() # Now plant the stars for ii in range(len(gcstars.x)): mag = gcstars.mag[ii] flux = gcstars.counts[ii] # We need to add photon noise to the PSF. # Scale up the PSF temporarily since poisson() only # returns integers. tmp = psf * flux * gain # set flux=1 since we already scaled it. starPlant.addStar(newImage, tmp, gcstars.x[ii] + 1.0, gcstars.y[ii] + 1.0, 1.0) # Planted positions are actually rounded to the nearest # pixel to avoid interpolation noise.... do the same in the # input star list. gcstars.x[ii] = round(gcstars.x[ii]) gcstars.y[ii] = round(gcstars.y[ii]) # Fix negative pixels idx = np.where(newImage < 0) newImage[idx] = 0 # Now add noise to the image, compensate for large number of exposures newImage = stats.poisson.rvs((newImage * imgCount).tolist()) newImage = np.array(newImage, dtype=float) # necessary for starfinder newImage /= imgCount newImage += otherNoise # Subtract off sky/dark newImage -= background # Convert back to DN newImage /= gain # Save the new image, and copy over all the necessary files. suffix = str(nn).zfill(4) fitsFile = 'sim_img_%s.fits' % suffix psfFile = 'sim_img_%s_psf.fits' % suffix backFile = 'sim_img_%s_back.fits' % suffix cooFile = 'sim_img_%s.coo' % suffix lisFile = 'sim_orig_%s.lis' % suffix print 'Writing ', fitsFile gcutil.rmall([fitsFile]) pyfits.writeto(fitsFile, newImage, hdr, output_verify='silentfix') shutil.copyfile('mag10maylgs_kp_psf.fits', psfFile) shutil.copyfile('mag10maylgs_kp_back.fits', backFile) shutil.copyfile('mag10maylgs_kp.coo', cooFile) gcstars.saveToFile(lisFile) # Write out a starfinder batch file idlRoot = 'idl_sim_img_%s' % suffix _batch = open(idlRoot + '.batch', 'w') _batch.write("find_stf, ") _batch.write("'" + fitsFile + "', 0.8, /trimfake\n") _batch.write("exit\n") _batch.close() gcutil.rmall([idlRoot + '.log']) allIDLroots.append(idlRoot) for root in allIDLroots: print 'idl < %s.batch >& %s.log' % (root, root)
def ast_err_vs_snr(n_init=0, n_sims=1000): """ Analyze how starfinder astrometric error changes with signal-to-noise ratio. Do this by planting stars on a simulated sky background and readnoise/dark current image. Then try to recover the stars with starfinder and measure the astrometric errors. """ sky, dc, noise, gain = image_noise_properites() # IN e- background = (sky + dc) # in e- imgCount = 150 # The total number of individual exposures that went # into this image. print '' print 'SIMULATED IMAGE PROPERTIES:' print ' assuming %d science exposures' % imgCount print ' constant = %.1f DN (%.1f e-)' % (background / gain, background) print ' additional noise approximated with gaussian' print ' sigma = %.1f DN (%.1f e-)' % (noise / gain, noise) img = np.zeros((1024, 1024), dtype=float) img += background # Noise from read out and sky subtraction (in e-) otherNoise = stats.norm.rvs(scale=noise, size=(1024, 1024)) # We are going to plant stars on this image using one of our # own PSFs. Each star we plant has to have photon noise from # itself as well. psf, hdr = pyfits.getdata('mag10maylgs_kp_psf.fits', header=True) # Repair the PSF so we don't have negative values idx1 = np.where(psf <= 0) idx2 = np.where(psf > 0) psf[idx1] = psf[idx2].min() # Seperate the PSFs by 2" since this is the Starfinder box size. step = 200 # in pixels # Pulled these numbers from the calibrated starlists for 10maylgs. mag0 = 9.782 flux0 = 20522900.000 # Randomly select from a distribution of magnitudes. magMin = 9.0 magMax = 22.0 # Number of samples (stars planted) #numStars = 100 stopN = n_sims + n_init allIDLroots = [] nn = n_init while nn <= stopN: # Create a new image newImage = img.copy() brightCoords = None brightMag = 1000 # Make a new starlist with the input info. newStars = starTables.StarfinderList(None, hasErrors=False) # Now plant the stars for xx in range(step, img.shape[1] - step, step): for yy in range(step, img.shape[0] - step, step): mag = np.random.uniform(magMin, magMax) flux = flux0 * 10**(-0.4 * (mag - mag0)) # We need to add photon noise to the PSF. # Scale up the PSF temporarily since poisson() only # returns integers. tmp = psf * flux * gain #print '%4s x = %4d y = %4d mag = %5.2f flux = %.2f' % \ # (nn, xx, yy, mag, flux) newName = 'sim_%s' % str(nn).zfill(4) # set flux=1 since we already scaled it. starPlant.addStar(newImage, tmp, xx, yy, 1.0) newStars.append(newName, mag, xx - 1, yy - 1, counts=flux, epoch=2010.342) # Updare our record of the brightest star in the image. if mag < brightMag: brightMag = mag brightCoords = [xx, yy] nn += 1 # Fix negative pixels idx = np.where(newImage < 0) newImage[idx] = 0 # Now add noise to the image, compensate for large number of exposures newImage = stats.poisson.rvs((newImage * imgCount).tolist()) newImage = np.array(newImage, dtype=float) # necessary for starfinder newImage /= imgCount newImage += otherNoise # Subtract off sky/dark newImage -= background # Convert back to DN newImage /= gain # Make a background image. img_back = np.zeros((1024, 1024), dtype=float) # Save the new image, and copy over all the necessary files. suffix = str(nn).zfill(4) fitsFile = 'sim_img_%s.fits' % suffix psfFile = 'sim_img_%s_psf.fits' % suffix backFile = 'sim_img_%s_back.fits' % suffix cooFile = 'sim_img_%s.coo' % suffix lisFile = 'sim_orig_%s.lis' % suffix print 'Writing ', fitsFile gcutil.rmall([fitsFile, backFile]) pyfits.writeto(fitsFile, newImage, hdr, output_verify='silentfix') pyfits.writeto(backFile, img_back, hdr, output_verify='silentfix') # Resort the starlist so the brightest star is at the top mdx = newStars.mag.argsort() newStars.name = newStars.name[mdx] newStars.mag = newStars.mag[mdx] newStars.epoch = newStars.epoch[mdx] newStars.x = newStars.x[mdx] newStars.y = newStars.y[mdx] newStars.snr = newStars.snr[mdx] newStars.corr = newStars.corr[mdx] newStars.nframes = newStars.nframes[mdx] newStars.counts = newStars.counts[mdx] newStars.saveToFile(lisFile) shutil.copyfile('mag10maylgs_kp_psf.fits', psfFile) _coo = open(cooFile, 'w') _coo.write('%.2f %.2f\n' % (brightCoords[0], brightCoords[1])) _coo.close() # Write out a starfinder batch file idlRoot = 'idl_sim_img_%s' % suffix _batch = open(idlRoot + '.batch', 'w') _batch.write("find_stf, ") _batch.write("'" + fitsFile + "', 0.8, /trimfake\n") _batch.write("exit\n") _batch.close() gcutil.rmall([idlRoot + '.log']) allIDLroots.append(idlRoot) for root in allIDLroots: print 'idl < %s.batch >& %s.log' % (root, root)