Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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])
Ejemplo n.º 4
0
    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')
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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])
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
    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')
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
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)