def mosaicDistortionErrors(rootDir, ep, mosaicRoot, mosaicStarlist, addResid=True, distResid=0.11): """ Read in a maser mosaic and it's associated *.shifts file and calculate the distortion error contribution to each pixel in the maser mosaic. This is done by using the NIRC2 single frame distortion error maps (X and Y) located here: /u/ghezgroup/code/python/gcreduce/nirc2dist_xerr.fits /u/ghezgroup/code/python/gcreduce/nirc2dist_yerr.fits For each independent dither position (where independent excludes any frame within 30 pixels of another frame), the distortion error map is shifted to the appropriate location in the final moasic and added in quadrature as sqrt( err1^2 + err2^2 + ... + errN^2 ) / sqrt(N). The resulting distortion error maps for the mosaics are saved to FITS files with the name: <mosaicRoot>_xdisterr.fits <mosaicRoot>_ydisterr.fits Finally, <mosaicStarlist> is the existing positional errors are added in quadrature to the distortion error at the nearest pixel for each star. The final starlist is saved off to the following file in the same directory as the input list: <mosaicStarlist_root>_rms_dist.lis Inputs: mosaicRoot - The root name of the maser mosaic fits file (e.g. 'mag08maylgs1_msr_kp') mosaicStarlist - The full name of a maser starlist with positional errors (e.g. 'starfinder/mag08maylgs1_msr_kp_0.8_rms.lis') addResid - Set to True to add residual distortion error (0.11 pix) in quadrature to the centroiding and distortion errors distResid - Value of residual distortion in pixels, to be added to centroid and distortion errors in quadrature (def=0.11 pix). """ # Read in the shifts file shiftsFile = mosaicRoot + '.shifts' print(shiftsFile) shiftsTable = asciidata.open(shiftsFile) singleFiles = shiftsTable[0]._data xshifts = shiftsTable[1].tonumpy() yshifts = shiftsTable[2].tonumpy() # Read in the mosaic fits file to get the size of the mosaic. # Then define coordinates for the mosaic. fitsFile = mosaicRoot + '.fits' fitsImg, fitsHdr = pyfits.getdata(fitsFile, header=True) mosaicSize = fitsImg.shape # Make the final distortion error map. # Also keep the number of frames that contributes to each pixel. xdistErrMap = np.zeros((mosaicSize[0], mosaicSize[1]), dtype=float) ydistErrMap = np.zeros((mosaicSize[0], mosaicSize[1]), dtype=float) distErrCnt = np.zeros((mosaicSize[0], mosaicSize[1]), dtype=int) # Read in the distortion errors map errorRoot = '/u/ghezgroup/code/python/gcreduce/nirc2dist' xerrOrig = pyfits.getdata(errorRoot + '_xerr.fits') yerrOrig = pyfits.getdata(errorRoot + '_yerr.fits') # Get the half-way points for both the mosaic and the single frame. # For zero-shift, the center of the single frame lies at the center of # the mosaic. mosaicHalfX = mosaicSize[1] / 2.0 mosaicHalfY = mosaicSize[0] / 2.0 singleHalfX = xerrOrig.shape[1] / 2.0 singleHalfY = xerrOrig.shape[0] / 2.0 print('Mosaic Size: ', mosaicSize) print('Mosaic Half: ', mosaicHalfX, mosaicHalfY) print('Single Half: ', singleHalfX, singleHalfY) # Loop through the individual frames and add them in # quadrature to the final distortion error map. Remember that we # can only do this for independent dither positions. We will # consider independent dither positions to be those that are # more than 30 pixel distant from any other ones. xshiftsUsed = np.array([]) yshiftsUsed = np.array([]) allowedSep = 30.0 # pixels for ii in range(len(singleFiles)): # Check to see if we should count this single file as # a new "independent" position by comparing to all # shifts used so far. sep = np.hypot(xshifts[ii] - xshiftsUsed, yshifts[ii] - yshiftsUsed) idx = np.where(sep < allowedSep)[0] # If used before, skip if (len(idx) > 0): continue # This is a new independent dither position xshiftsUsed = np.append(xshiftsUsed, xshifts[ii]) yshiftsUsed = np.append(yshiftsUsed, yshifts[ii]) # Calculate the stop and start indices in the maser mosaic xlo = round(mosaicHalfX + xshifts[ii] - singleHalfX) xhi = round(mosaicHalfX + xshifts[ii] + singleHalfX) ylo = round(mosaicHalfY + yshifts[ii] - singleHalfY) yhi = round(mosaicHalfY + yshifts[ii] + singleHalfY) print(singleFiles[ii], xshifts[ii], yshifts[ii]) print(' xrange = [%4d:%4d] yrange = [%4d:%4d]' % (xlo, xhi, ylo, yhi)) xdistErrMap[ylo:yhi,xlo:xhi] += xerrOrig**2 ydistErrMap[ylo:yhi,xlo:xhi] += yerrOrig**2 distErrCnt[ylo:yhi,xlo:xhi] += 1.0 idx = np.where(distErrCnt != 0) xdistErrMap[idx] = np.sqrt(xdistErrMap[idx] / distErrCnt[idx]) ydistErrMap[idx] = np.sqrt(ydistErrMap[idx] / distErrCnt[idx]) # Save these to a FITS file xfits = pyfits.PrimaryHDU(xdistErrMap) gcutil.rmall([mosaicRoot + '_xdisterr.fits', mosaicRoot + '_ydisterr.fits']) pyfits.writeto(mosaicRoot + '_xdisterr.fits', xdistErrMap) pyfits.writeto(mosaicRoot + '_ydisterr.fits', ydistErrMap) ########## # # Read in starlist and apply distortion errors. # ########## starlist = asciidata.open(mosaicStarlist) # Check that this starlist properly has error columns if starlist.nrows < 11: print('Starlist does not have error columns: %s' % mosaicStarlist) # Now for each star, add the distortion errors in quadrature for rr in range(starlist.nrows): xpix = round(starlist[3][rr]) ypix = round(starlist[4][rr]) if addResid: xerr = math.sqrt(starlist[5][rr]**2 + xdistErrMap[ypix,xpix]**2 + \ distResid**2) yerr = math.sqrt(starlist[6][rr]**2 + ydistErrMap[ypix,xpix]**2 + \ distResid**2) else: xerr = math.sqrt(starlist[5][rr]**2 + xdistErrMap[ypix,xpix]**2) yerr = math.sqrt(starlist[6][rr]**2 + ydistErrMap[ypix,xpix]**2) starlist[5][rr] = xerr starlist[6][rr] = yerr # Reformat the columns so they get printed out nicely starlist[0].reformat('%-13s ') starlist[1].reformat('%6.3f ') starlist[2].reformat('%8.3f') starlist[3].reformat('%9.3f ') starlist[4].reformat('%9.3f ') starlist[5].reformat('%6.3f') starlist[6].reformat('%6.3f') starlist[7].reformat('%11.4f') starlist[8].reformat('%5.2f') starlist[9].reformat('%5d') starlist[10].reformat('%8.4f') # Write out the new starlist outroot = mosaicStarlist.replace('rms', 'rms_dist') starlist.writeto(outroot)
def lgsAnimate(redoImages=False): dataRoot = "/u/ghezgroup/data/gc/" imgRoots = ["05jullgs", "06maylgs1", "06junlgs", "06jullgs", "07maylgs", "07auglgs", "08maylgs1"] workRoot = "/u/ghezgroup/public_html/gc/images/media/image_anim/" alignRoot = workRoot + "align/align" s = starset.StarSet(alignRoot) 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 print sgrax print sgrayOrig print sgray sgrax = array([602.831, 600.688, 600.9547, 601.239, 601.118, 601.5432, 600.7679]) sgray = array([689.024, 686.918, 687.0692, 686.7293, 686.971, 686.8857, 687.4686]) # Color Ranges for Images - Log Scale vmin = array([2.55, 2.52, 2.45, 2.48, 2.5, 2.55, 2.5]) vmax = array([3.4, 3.33, 3.38, 3.35, 3.4, 3.25, 3.25]) # Image plate scale scale = 0.00996 if len(imgRoots) != len(sgrax): print "Problem... images and align do not match. Compare to align.list" print imgRoots import gcutil, 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" trans = objects.Transform() trans.loadFromAbsolute(root=workRoot, align="align/align.trans", idx=i) trans.linearToSpherical(override=False) hdr = pyfits.getheader(imgIn) # phi = nirc2.getPA(hdr) phi = math.degrees(trans.angle) if phi != 0: phi *= -1 if redoImages: gcutil.rmall([imgOut]) ir.rotate.xin = sgraxOrig[i] ir.rotate.yin = sgrayOrig[i] ir.rotate.xout = sgrax[i] ir.rotate.yout = sgray[i] ir.rotate(imgIn, imgOut, phi) img = pyfits.getdata(imgOut) xax = arange(0, img.shape[0]) yax = arange(0, img.shape[1]) xax = (xax - sgrax[1]) * -scale yax = (yax - sgray[1]) * scale pylab.imshow(log10(img), extent=[xax[0], xax[-1], yax[0], yax[-1]], vmin=vmin[i], vmax=vmax[i]) 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.xlabel("RA Offset from Sgr A* (arcsec)") pylab.ylabel("RA Offset from Sgr A* (arcsec)") pylab.title(imgRoots[i]) pylab.savefig("frame%d.png" % i)
def lgsAnimate(redoImages=False): dataRoot = '/u/ghezgroup/data/gc/' imgRoots = [ '05jullgs', '06maylgs1', '06junlgs', '06jullgs', '07maylgs', '07auglgs', '08maylgs1' ] workRoot = '/u/ghezgroup/public_html/gc/images/media/image_anim/' alignRoot = workRoot + 'align/align' s = starset.StarSet(alignRoot) 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 print sgrax print sgrayOrig print sgray sgrax = array( [602.831, 600.688, 600.9547, 601.239, 601.118, 601.5432, 600.7679]) sgray = array( [689.024, 686.918, 687.0692, 686.7293, 686.971, 686.8857, 687.4686]) # Color Ranges for Images - Log Scale vmin = array([2.55, 2.52, 2.45, 2.48, 2.5, 2.55, 2.5]) vmax = array([3.4, 3.33, 3.38, 3.35, 3.4, 3.25, 3.25]) # Image plate scale scale = 0.00996 if (len(imgRoots) != len(sgrax)): print 'Problem... images and align do not match. Compare to align.list' print imgRoots import gcutil, 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' trans = objects.Transform() trans.loadFromAbsolute(root=workRoot, align='align/align.trans', idx=i) trans.linearToSpherical(override=False) hdr = pyfits.getheader(imgIn) #phi = nirc2.getPA(hdr) phi = math.degrees(trans.angle) if (phi != 0): phi *= -1 if (redoImages): gcutil.rmall([imgOut]) ir.rotate.xin = sgraxOrig[i] ir.rotate.yin = sgrayOrig[i] ir.rotate.xout = sgrax[i] ir.rotate.yout = sgray[i] ir.rotate(imgIn, imgOut, phi) img = pyfits.getdata(imgOut) xax = arange(0, img.shape[0]) yax = arange(0, img.shape[1]) xax = (xax - sgrax[1]) * -scale yax = (yax - sgray[1]) * scale pylab.imshow(log10(img), extent=[xax[0], xax[-1], yax[0], yax[-1]], vmin=vmin[i], vmax=vmax[i]) 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.xlabel('RA Offset from Sgr A* (arcsec)') pylab.ylabel('RA Offset from Sgr A* (arcsec)') pylab.title(imgRoots[i]) pylab.savefig('frame%d.png' % i)