def makeFirstRefList(self, labelFile, scale=0.00995): """ Read in a label.dat file specificed in <labelFile> and convert it into a starfinder *_rms.lis file. Coordinates in label.dat are assumed to be in arcseconds and they will be converted to NIRC2 narrow pixels using <scale>. Sgr A* will be centered at x=2000, y=2000 in the output list. labelFile - (string) The name of the label.dat file. scale - (float) The pixels scale in arcsec/pixel. """ labels = starTables.Labels(labelFile=labelFile) starlist = starTables.StarfinderList(None, hasErrors=True) # We need to pull out the date of this epoch. Pull this from the # first image starlist in the mosaic. firstList = self.dataDir + self.images[0] + '_rms.lis' tmpList = starTables.StarfinderList(firstList) date = tmpList.epoch[0] # Trim label list to only stars with use? != 0 idx = np.where(labels.useToAlign == 1)[0] labels.take(idx) # Convert label velocities to arcsec/yr instead of mas/yr labels.vx /= 1000.0 labels.vy /= 1000.0 labels.vxerr /= 1000.0 labels.vyerr /= 1000.0 starlist.name = labels.name starlist.mag = labels.mag starlist.epoch = np.zeros(len(labels.name), dtype=float) starlist.epoch += date dt = date - labels.t0 starlist.x = ((labels.x + labels.vx * dt) / -scale) + 2000.0 starlist.y = ((labels.y + labels.vy * dt) / scale) + 2000.0 starlist.xerr = np.sqrt(labels.xerr**2 + (labels.vxerr * dt)**2) starlist.xerr /= scale starlist.yerr = np.sqrt(labels.yerr**2 + (labels.vyerr * dt)**2) starlist.yerr /= scale starlist.snr = np.ones(len(labels.name)) starlist.corr = np.ones(len(labels.name)) starlist.nframes = np.ones(len(labels.name)) starlist.counts = np.ones(len(labels.name)) outFile = self.lisDir + labelFile.split('/')[-1] outFile = outFile.replace('.dat', '_rms.lis') print 'Saving to %s' % outFile starlist.saveToFile(outFile)
def add_distErr_to_lis(self): """ For every single *_rms.lis file, modify the error columns to include distortion errors and distortion residuals. """ for ii in range(len(self.images)): # read in this field's star list starlist = self.lisDir + self.images[ii] + '_rms.lis' lis = starTables.StarfinderList(starlist, hasErrors=True) lis.xerr = np.hypot(lis.xerr, self.addErrX) lis.yerr = np.hypot(lis.yerr, self.addErrY) outlist = starlist.replace('rms', 'rms_dist') lis.saveToFile(outlist)
def name_new_stars(self, oldNames): mosaicRoot = 'mag' + self.epoch +'_'+ self.mosaic +'_'+ self.filter starlist = self.tableDir + mosaicRoot + '_rms_named_abs_xwest.lis' labelNewFile = self.tableDir+'/label_new.dat' labels = starTables.Labels(labelFile=labelNewFile) list = starTables.StarfinderList(starlist, hasErrors=True) # Go through the existing named sources and figure out the highest # star index number. highestIndex = {} for ii in range(len(labels.name)): name = labels.name[ii] if name.startswith('S') and '-' in name: parts = name.split('-') radius = int(parts[0].replace('S', '')) index = int(parts[1]) if highestIndex.has_key(radius): if index > highestIndex[radius]: highestIndex[radius] = index else: highestIndex[radius] = index # Work with the starlist list.x *= -1.0 list.r = np.hypot(list.x, list.y) for ii in range(len(oldNames)): idx = np.where(list.name == oldNames[ii])[0] rBin = int(math.floor( list.r[idx] )) highestIndex[rBin] += 1 newName = 'S%d-%d' % (rBin, highestIndex[rBin]) print '%-11s %4.1f %8.4f %8.4f %8.4f %8.4f 0.000 0.000 0.000 0.000 %8.3f 0 %6.3f' % \ (newName, list.mag[idx], list.x[idx], list.y[idx], list.xerr[idx], list.yerr[idx], list.epoch[idx], list.r[idx])
def convertToAbsolute(self): """ Make a sham starlist in arcseconds with +x to the west. This is for Tuan's data analysis. """ mosaicRoot = 'mag' + self.epoch +'_'+ self.mosaic +'_'+ self.filter starlist = self.tableDir + mosaicRoot + '_rms_named.lis' lis = starTables.StarfinderList(starlist, hasErrors=True) labels = starTables.Labels() # Convert the coordinates to arcseconds xpix = lis.x ypix = lis.y xpixerr = lis.xerr ypixerr = lis.yerr # Find 16C in both lists lis16C = np.where(lis.name == 'irs16C') lab16C = np.where(labels.name == 'irs16C') scale = 0.00995 x = (xpix - xpix[lis16C]) * scale * -1.0 x += labels.x[lab16C] x *= -1.0 y = (ypix - ypix[lis16C]) * scale y += labels.y[lab16C] xe = xpixerr * scale ye = ypixerr * scale lis.x = x lis.y = y lis.xerr = xe lis.yerr = ye lis.saveToFile(starlist.replace('.lis', '_abs_xwest.lis')) shutil.copyfile(self.tableDir + mosaicRoot + '_rms_named_abs_xwest.lis', self.dataDir + mosaicRoot + '_rms_named_abs_xwest.lis')
def shiftToTopOfList(oldList, newList, starnames, withErr=True): print 'Shifting to top', starnames print ' old: %s' % (oldList) print ' new: %s' % (newList) # Star List _ref = starTables.StarfinderList(oldList, hasErrors=withErr) first = [] rest = np.ones(len(_ref.name), dtype=bool) for ss in range(len(starnames)): idx = np.where(_ref.name == starnames[ss])[0] if len(idx) is 0: print 'Failed to find %s in %s' % (starnames[ss], oldList) print 'HERE2' first.append(idx[0]) rest[idx[0]] = False rest = np.where(rest == True)[0] indices = np.append(first, rest) _ref.name = _ref.name[indices] _ref.mag = _ref.mag[indices] _ref.epoch = _ref.epoch[indices] _ref.x = _ref.x[indices] _ref.y = _ref.y[indices] _ref.snr = _ref.snr[indices] _ref.corr = _ref.corr[indices] _ref.nframes = _ref.nframes[indices] _ref.counts = _ref.counts[indices] if withErr: _ref.xerr = _ref.xerr[indices] _ref.yerr = _ref.yerr[indices] _ref.saveToFile(newList)
def findOverlapStars(mosaicRoot, mosaicStars, cleanRoot1, cleanStars1, cleanRoot2, cleanStars2): """ Take two cleaned images from a maser mosaic and use the combined mosaic (with starfinder run on it) to identify the set of stars that are in both cleaned images. These stars in the overlap region can be used to align the two individual cleaned frames. """ # Read in the shifts file and extract shifts for the two frames shiftsFile = mosaicRoot + '.shifts' print(shiftsFile) shiftsTable = asciidata.open(shiftsFile) cleanFiles = shiftsTable[0]._data xshifts = shiftsTable[1].tonumpy() yshifts = shiftsTable[2].tonumpy() idx1 = -1 idx2 = -1 for cc in range(len(cleanFiles)): if cleanRoot1 in cleanFiles[cc]: idx1 = cc if cleanRoot2 in cleanFiles[cc]: idx2 = cc print(idx1, idx2, cleanFiles[idx1], cleanFiles[idx2]) xshift1 = xshifts[idx1] xshift2 = xshifts[idx2] yshift1 = yshifts[idx1] yshift2 = yshifts[idx2] print('Shifts:') print(cleanFiles[idx1], xshift1, yshift1) print(cleanFiles[idx2], xshift2, yshift2) # Read in the mosaic fits file to get the size of the mosaic. # Then define coordinates for the mosaic fitsFile = mosaicRoot + '.fits' fitsImg = pyfits.getdata(fitsFile) mosaicSize = fitsImg.shape print('Mosaic Size: ', mosaicSize) (ym, xm) = np.meshgrid(np.arange(mosaicSize[0]), np.arange(mosaicSize[1])) mosaicHalfX = mosaicSize[1] / 2.0 mosaicHalfY = mosaicSize[0] / 2.0 # Define coordinates for the cleaned frames and shift accordingly. (y1orig, x1orig) = np.meshgrid(np.arange(1024), np.arange(1024)) (y2orig, x2orig) = np.meshgrid(np.arange(1024), np.arange(1024)) cleanHalf = 512.0 x1 = ((x1orig - cleanHalf) + xshift1) + mosaicHalfX y1 = ((y1orig - cleanHalf) + yshift1) + mosaicHalfY x2 = ((x2orig - cleanHalf) + xshift2) + mosaicHalfX y2 = ((y2orig - cleanHalf) + yshift2) + mosaicHalfY box1x = np.array([x1.min(), x1.max(), x1.max(), x1.min(), x1.min()]) box1y = np.array([y1.min(), y1.min(), y1.max(), y1.max(), y1.min()]) box2x = np.array([x2.min(), x2.max(), x2.max(), x2.min(), x2.min()]) box2y = np.array([y2.min(), y2.min(), y2.max(), y2.max(), y2.min()]) overlap = np.where((x1 >= x2.min()) & (x1 <= x2.max()) & (y1 >= y2.min()) & (y1 <= y2.max())) xo = x1[overlap] yo = y1[overlap] xo_min = xo.min() xo_max = xo.max() yo_min = yo.min() yo_max = yo.max() print('Overlap Range:') print(xo_min, xo_max, yo_min, yo_max) box3x = np.array([xo_min, xo_max, xo_max, xo_min, xo_min]) box3y = np.array([yo_min, yo_min, yo_max, yo_max, yo_min]) # Read in the two cleaned star lists and the mosaic list stars1 = starTables.StarfinderList(cleanStars1) stars2 = starTables.StarfinderList(cleanStars2) starsM = starTables.StarfinderList(mosaicStars) # Extract stars from the mosaic list in the overlap region. idx = np.where((starsM.x >= xo_min) & (starsM.x <= xo_max) & (starsM.y >= yo_min) & (starsM.y <= yo_max))[0] # Trim out named sources idxNamed = [] for ii in idx: if not starsM.name[ii].startswith('star'): idxNamed.append(ii) # Loop through and find matching sources (by name) idxIn1 = [] idxIn2 = [] for ii in idxNamed: try: match1 = stars1.name.index(starsM.name[ii]) match2 = stars2.name.index(starsM.name[ii]) except ValueError: continue idxIn1.append(match1) idxIn2.append(match2) print(stars1.name[match1], stars2.name[match2])
def plotStarfinderList( starList, hasErrors=True, magCut=18, cooStarList='16C', cooStarLabels='irs16C', scaleList=0.00995, scaleImg=0.00995, image='/u/ghezgroup/data/gc/06maylgs1/combo/mag06maylgs1_dp_msc_kp.fits' ): """ Plot the specified image and overlay the photo_calib.dat sources on top. Coordinates are converted from pixels to arcsec using the coo star and assuming that the angle of the image is 0. This code assumes coordinates are NIRC2 narrow pixels coordaintes. You can modify this by changing the scale. But +x must be to the west in the starlist. """ # Load up the photometric calibraters table. lis = starTables.StarfinderList(starList, hasErrors=hasErrors) labels = starTables.Labels() # Find the coo star in the starlist and in the labels ii1 = np.where(lis.name == cooStarList)[0] ii2 = np.where(labels.name == cooStarLabels)[0] dt = lis.epoch[0] - labels.t0 labels.x += (labels.vx / 10**3) * dt labels.y += (labels.vy / 10**3) * dt # Convert the pixels in the starlist into arcsec x = ((lis.x - lis.x[ii1]) * -scaleList) + labels.x[ii2] y = ((lis.y - lis.y[ii1]) * scaleList) + labels.y[ii2] im = pyfits.getdata(image) 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) # Read in the image coo file # Coo star pixel coordinates _coo = open(image.replace('.fits', '.coo'), 'r') coordsTmp = _coo.readline().split() coords = [float(coo) for coo in coordsTmp] print 'Coordinates for %s:' % cooStarLabels print ' [%10.4f, %10.4f] pixels' % (coords[0], coords[1]) print ' [%10.4f, %10.4f] arcsec' % (labels.x[ii2], labels.y[ii2]) sgrax = coords[0] - (labels.x[ii2] / -scaleImg) sgray = coords[1] - (labels.y[ii2] / scaleImg) sgra = [sgrax, sgray] # Image coordinates (in arcsec) xim = (xpix - sgra[0]) * -scaleImg yim = (ypix - sgra[1]) * scaleImg py.clf() py.close(2) py.figure(2, figsize=(6, 4.5)) 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=1.9, vmax=6.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() py.axis([15, -15, -15, 15]) idx = (np.where((lis.mag < magCut) & (x > xim.min()) & (x < xim.max()) & (y > yim.min()) & (y < yim.max())))[0] py.plot(x[idx], y[idx], 'r+', color='orange') for ii in idx: py.text(x[ii], y[ii], lis.name[ii], color='orange', fontsize=10)
def makeNamedStarlist(self): """ We would like to make a named starlist. We do this with a trick... just align a dummy starlist to our *rms.lis and pass in label.dat to align. """ mosaicRoot = 'mag' + self.epoch +'_'+ self.mosaic +'_'+ self.filter starlist = self.tableDir + mosaicRoot + '_rms_dist.lis' dumblist = self.lisDir + self.images[0] + '_rms_dist.lis' # This is shorter newList1 = self.lisDir + mosaicRoot + '_align_label.lis' newList2 = self.lisDir + self.images[0] + '_align_label.lis' # Match sources at the top shiftToTopOfList(starlist, newList1, self.refStars[self.fields[0]]) shiftToTopOfList(dumblist, newList2, self.refStars[self.fields[0]]) # Get the align data type fitsFile = self.dataDir + '../%s.fits' % (self.images[0]) alignType = dataUtil.get_align_type(fitsFile, errors=True) alignRoot = self.alignDir + 'align_label' _list = open(alignRoot + '.list', 'w') _list.write('%s %d ref\n' % (newList1, alignType)) _list.write('%s %d\n' % (newList2, alignType)) _list.close() cmd = 'java align -v -p -a 2 -R 1 ' cmd += '-N /g/lu/data/orion/source_list/label.dat ' cmd += '-r %s %s.list' % (alignRoot, alignRoot) print cmd os.system(cmd) # This will be our new starlist list = starTables.StarfinderList(None, hasErrors=True) # Make a new starlist out of the resulting align output s = starset.StarSet(alignRoot) # Trim out all stars only detected in the dummy epoch. mag = s.getArrayFromEpoch(0, 'mag') idx = np.where(mag != 0)[0] newStars = [] for ii in idx: newStars.append(s.stars[ii]) s.stars = newStars # Pull the data from the aligned epoch list.name = np.array(s.getArray('name')) list.epoch = np.zeros(len(s.stars), dtype=float) + s.years[0] list.mag = s.getArrayFromEpoch(0, 'mag') list.x = s.getArrayFromEpoch(0, 'xpix') list.y = s.getArrayFromEpoch(0, 'ypix') list.xerr = s.getArrayFromEpoch(0, 'xpixerr_p') list.yerr = s.getArrayFromEpoch(0, 'ypixerr_p') list.snr = s.getArrayFromEpoch(0, 'snr') list.corr = s.getArrayFromEpoch(0, 'corr') list.nframes = s.getArrayFromEpoch(0, 'nframes') list.counts = s.getArrayFromEpoch(0, 'fwhm') list.saveToFile(starlist.replace('rms_dist', 'rms_named')) shutil.copyfile(self.tableDir + mosaicRoot + '_rms_named.lis', self.dataDir + mosaicRoot + '_rms_named.lis')
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 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)