def runall(prefixes,cat): for prefix in prefixes: images=glob.glob(prefix) iraf.imgets(images[0],'FILTER') filter=str(iraf.imgets.value) for im in images: runsextractor(im) t=im.split('.') if cat < 0.1: out='sdssmatch-'+str(t[0]) refcat='sdsscoords.dat' s='cat '+out+' >> sdssmatch'+filter plotsdsspos(im) if cat > .1: out='2massmatch-'+str(t[0]) refcat='2masscoords.dat' s='cat '+out+' >> 2massmatch'+filter plot2masspos(im) #iraf.xyxymatch(input='testxy.cat',reference='sdsscoords.dat',output=out,tolerance=20.,refpoints='refpoints',interactive='yes') iraf.xyxymatch(input='testxy.cat',reference=refcat,output=out,tolerance=10.,refpoints='refpoints',interactive='no') os.system(s) infile='sdssmatch'+filter infile='2massmatch'+filter iraf.geomap(input=infile,database='PiscesBok',transform=filter,xmin=1.,xmax=1024,ymin=1.,ymax=1024.)
def source_match(self): ''' Uses iraf.xyxymatch to match sources between images. ''' countlist = glob.glob(self.root + '/*counts.fits') sourcelist = glob.glob(self.root + '/*sources.dat') refimage = sourcelist[0] for image, source in zip(countlist, sourcelist): iraf.xyxymatch(input=source, reference=refimage, \ output=image[:-12] + '_match.dat', \ tolerance=self.tolerance, verbose='no')
def twomassmatch(): twomassRA, twomassDec, mag, lineno, octRA, octDec, octlineno, octflux, chipno = [], [], [], [], [], [], [], [], [] global bandline, indexjhk with open('2mass.txt', 'r') as f: lines = f.readlines() i = 1 for x in lines: line = x.split() if x.startswith('#') == False and x.split()[21][indexjhk] == '0' \ and x.split()[23] == '0' and x.split()[24] == '0' \ and (x.split()[18][indexjhk] == 'A' or x.split()[18][indexjhk] == 'B'): twomassRA.append(float(line[0]) * 1000) twomassDec.append(float(line[1]) * 1000) mag.append("#" + line[bandline]) lineno.append("#" + str(i)) i += 1 ascii.write([twomassRA, twomassDec, mag, lineno], '2mass_RADec.txt', names=('#RA', 'Dec', 'Mag', 'Line number'), overwrite=True) with open('oct_total.txt', 'r') as f: lines = f.readlines() for x in lines: line = x.split(' ') octRA.append(float(line[len(line) - 3]) * 1000) octDec.append(float(line[len(line) - 2]) * 1000) octlineno.append(line[0]) octflux.append(line[convergeap]) chipno.append(line[len(line) - 1]) ascii.write([octRA, octDec, octlineno, chipno, octflux], 'Oct_RADec.txt', names=('#RA', 'Dec', 'line', 'chip', 'flux'), overwrite=True) iraf.xyxymatch(input='Oct_RADec.txt', reference='2mass_RADec.txt', output="2mass_Oct_matched.txt", tolerance=3, verbose="no", xref=0, yref=0, xin=0, yin=0)
def get_align_to_subaru(sci='M0416_Ks_c1_mp_avg.fits', wht='M0416_Ks_c1_mp_exp.fits', field='', clean=True, toler=3, verbose=False, fitgeometry='shift', shift_max=20, rms_max=1.1, rot_max=2, rot_only=True, THRESH=2, align_data=None): """ Align HAWK-I images to the FF Subaru astrometric reference catalogs """ #sci='M0416_Ks_c1_mp_avg.fits'; wht='M0416_Ks_c1_mp_exp.fits' ### Make object catalog se = threedhst.sex.SExtractor() se.aXeParams() se.copyConvFile() se.overwrite = True se.options['CHECKIMAGE_TYPE'] = 'NONE' if wht is None: se.options['WEIGHT_TYPE'] = 'NONE' else: se.options['WEIGHT_TYPE'] = 'MAP_WEIGHT' se.options['WEIGHT_IMAGE'] = wht se.options['FILTER'] = 'Y' se.options['DETECT_THRESH'] = '%d' % (THRESH) se.options['ANALYSIS_THRESH'] = '%d' % (THRESH) se.options['MAG_ZEROPOINT'] = '26.0' #### Run SExtractor on direct and alignment images ## direct image se.options['CATALOG_NAME'] = 'direct.cat' status = se.sextractImage(sci) threedhst.sex.sexcatRegions('direct.cat', 'direct.reg', format=2) directCat = threedhst.sex.mySexCat('direct.cat') #### Get the X/Y coords of the reference catalog #head = pyfits.getheader(sci, 0) #wcs = pywcs.WCS(head) if 'M0416' in sci: ra_list, dec_list, mag = np.loadtxt( os.getenv('HAWKI') + '/FrontierFields/HST/hlsp_frontier_subaru_suprimecam_macs0416-astrom_R_v1_cat.txt', unpack=True) if ('c4' in sci): ra_list, dec_list, mag = np.loadtxt( os.getenv('HAWKI') + '/FrontierFields/HST/M0416/macs0416_f814w_radec.cat', unpack=True) # if 'M0717' in sci: ra_list, dec_list, mag = np.loadtxt('subaru.radec', unpack=True) if ('M1149' in sci) | (field == 'M1149'): ra_list, dec_list, mag = np.loadtxt( '/Users/brammer/Research/VLT/HAWKI/MACS1149/hlsp_frontier_subaru_suprimecam_macs1149-astrom_R_v1_cat.txt', unpack=True) if 'A2744' in sci: ra_list, dec_list, mag = np.loadtxt( os.getenv('HAWKI') + '/FrontierFields/HST/hlsp_frontier_subaru_suprimecam_abell2744-astrom_i_v1_cat.txt', unpack=True) if ('c1' in sci) | ('c4' in sci): ra_list, dec_list, mag = np.loadtxt( os.getenv('HAWKI') + '/FrontierFields/HST/abell2744_f814w_radec.cat', unpack=True) if align_data is not None: ra_list, dec_list, mag = align_data im = pyfits.open(sci) print sci sh = im[0].shape head = im[0].header head['CUNIT1'] = 'deg' head['CUNIT2'] = 'deg' wcs = pywcs.WCS(head) x_image, y_image = wcs.wcs_sky2pix(ra_list, dec_list, 1) try: x_image, y_image = wcs.wcs_sky2pix(ra_list, dec_list, 1) except: x_image, y_image = wcs.wcs_world2pix(ra_list, dec_list, 1) ok = (x_image > 0) & (y_image > 0) & (x_image < sh[1]) & (y_image < sh[1]) x_image, y_image = x_image[ok], y_image[ok] fpr = open('align.reg', 'w') fpr.write('image\n') for i in range(ok.sum()): fpr.write('circle(%.6f, %.6f,0.3") # color=magenta\n' % (x_image[i], y_image[i])) fpr.close() # x_image, y_image = [], [] # # for ra, dec in zip(ra_list, dec_list): # x, y = wcs.wcs_sky2pix([[ra, dec]], 1)[0] # if (x > 0) & (y > 0) & (x < sh[1]) & (y < sh[1]): # x_image.append(x) # y_image.append(y) alignCat = catIO.EmptyCat() alignCat['X_IMAGE'] = np.array(x_image) alignCat['Y_IMAGE'] = np.array(y_image) xshift = 0 yshift = 0 rot = 0 scale = 1. xrms = 2 yrms = 2 NITER = 5 IT = 0 while (IT < NITER): IT = IT + 1 #### Get x,y coordinates of detected objects ## direct image fp = open('direct.xy', 'w') for i in range(len(directCat.X_IMAGE)): fp.write('%s %s\n' % (directCat.X_IMAGE[i], directCat.Y_IMAGE[i])) fp.close() ## alignment image fp = open('align.xy', 'w') for i in range(len(alignCat.X_IMAGE)): fp.write('%s %s\n' % (np.float(alignCat.X_IMAGE[i]) + xshift, np.float(alignCat.Y_IMAGE[i]) + yshift)) fp.close() iraf.flpr() iraf.flpr() iraf.flpr() #### iraf.xyxymatch to find matches between the two catalogs pow = toler * 1. try: os.remove('align.match') except: pass status1 = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**pow, separation=0, verbose=iraf.yes, Stdout=1) nmatch = 0 while status1[-1].startswith('0') | (nmatch < 10) | (float( status1[-3].split()[1]) > 40): pow += 1 os.remove('align.match') status1 = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**pow, separation=0, verbose=iraf.yes, Stdout=1) # nmatch = 0 for line in open('align.match').xreadlines(): nmatch += 1 if verbose: for line in status1: print line #### Compute shifts with iraf.geomap iraf.flpr() iraf.flpr() iraf.flpr() try: os.remove("align.map") except: pass status2 = iraf.geomap(input="align.match", database="align.map", fitgeometry=fitgeometry, interactive=iraf.no, xmin=iraf.INDEF, xmax=iraf.INDEF, ymin=iraf.INDEF, ymax=iraf.INDEF, maxiter=10, reject=2.0, Stdout=1) if verbose: for line in status2: print line #fp = open(root+'.iraf.log','a') #fp.writelines(status1) #fp.writelines(status2) #fp.close() #### Parse geomap.output fp = open("align.map", "r") for line in fp.readlines(): spl = line.split() if spl[0].startswith('xshift'): xshift += float(spl[1]) if spl[0].startswith('yshift'): yshift += float(spl[1]) if spl[0].startswith('xrotation'): rot = float(spl[1]) if spl[0].startswith('xmag'): scale = float(spl[1]) if spl[0].startswith('xrms'): xrms = float(spl[1]) if spl[0].startswith('yrms'): yrms = float(spl[1]) fp.close() #os.system('wc align.match') print 'Shift iteration #%d, xshift=%f, yshift=%f, rot=%f, scl=%f (rms: %5.2f,%5.2f)' % ( IT, xshift, yshift, rot, scale, xrms, yrms) os.system( 'cat align.match | grep -v "\#" | grep [0-9] | awk \'{print "circle(", $1, ",", $2, ",4) # color=green"}\' > d.reg' ) os.system( 'cat align.match | grep -v "\#" | grep [0-9] | awk \'{print "circle(", $3, ",", $4, ",4) # color=magenta"}\' > a.reg' ) shutil.copy('align.map', sci.replace('.fits', '.align.map')) shutil.copy('align.match', sci.replace('.fits', '.align.match')) #### Cleanup if clean: rmfiles = [ 'align.cat', 'align.map', 'align.match', 'align.reg', 'align.xy', 'direct.cat', 'direct.reg', 'direct.xy' ] for file in rmfiles: try: os.remove(file) except: pass fp = open(sci.replace('.fits', '.align.info'), 'w') fp.write('# image xshift yshift rot scale xrms yrms\n') fp.write('%s %.3f %.3f %.4f %.4f %.3f %.3f\n' % (sci, xshift, yshift, rot, scale, xrms, yrms)) if (np.abs(xshift) > shift_max) | (np.abs(yshift) > shift_max) | ( xrms > rms_max) | (yrms > rms_max): print 'Shifts out of allowed range. Run again with increased shift_max to accept.' #return xshift, yshift, rot, scale, xrms, yrms ## Add a small shift that should come out easily with another ## shift iteration xshift, yshift, rot, scale, xrms, yrms = 2, 2, 0, 1.0, -99, -99 for file in [sci, wht]: if ('r' in fitgeometry) & rot_only: xshift, yshift = 0, 0 #apply_offsets(file, [[xshift, yshift, rot, scale]]) from drizzlepac import updatehdr updatehdr.updatewcs_with_shift(file, sci, wcsname='DRZWCS', rot=rot, scale=scale, xsh=xshift, ysh=yshift, fit=None, xrms=xrms, yrms=yrms, verbose=False, force=True, sciext=0) if '_dr' in sci: im = pyfits.open(sci) h = im[0].header for i in range(h['NDRIZIM']): flt_str = h['D%03dDATA' % (i + 1)] if 'sci,2' in flt_str: continue # flt_im = flt_str.split('[')[0] ext = int(flt_str.split('[')[1][:-1].split(',')[1]) updatehdr.updatewcs_with_shift(flt_im, sci, wcsname='GTWEAK', rot=rot, scale=scale, xsh=xshift, ysh=yshift, fit=None, xrms=xrms, yrms=yrms, verbose=False, force=True, sciext='SCI') # im = pyfits.open(file, mode='update') # wcs = pywcs.WCS(im[0].header) # wcs.rotateCD(-rot) # wcs.wcs.cd /= scale # # # im[0].header['CRPIX1'] += xshift # im[0].header['CRPIX2'] += yshift # # # for i in [0,1]: # for j in [0,1]: # im[0].header['CD%d_%d' %(i+1, j+1)] = wcs.wcs.cd[i,j] # # # im.flush() return xshift, yshift, rot, scale, xrms, yrms
def matchOctSept(): global liststars, masteroctlines, masterseptlines septxlist, septylist, septmatchlinelist, octmatchlinelist, septcatlinelist, octcatlinelist, oct_total, octlineno, \ septlineno, octxlist, octylist = [], [], [], [], [], [], [], [], [], [], [] # create list of acceptable sources in september with open(septextracted[0], "r") as f: lines = f.readlines() RAs, Decs = [], [] for x in lines: line = x.split(' ') if (not x.startswith("N")) and int(line[3]) == 0 \ and uppersept > float(line[1]) > lowersept and uppersept > float(line[2]) > lowersept: septxlist.append(line[1]) septylist.append(line[2]) septlineno.append('#%s' % line[0]) RAs.append('#%s' % line[5]) Decs.append('#%s' % line[6]) with open((userdata + 'match1.xml'), 'w') as f: for y in range(len(septxlist)): f.write('circle(%s,%s,%s)' % (septxlist[y], septylist[y], 30) + '\n') septxy = ((sept + 'xysept_full.txt')) ascii.write([septxlist, septylist, septlineno, RAs, Decs], septxy, names=('#x', 'y', 'line no.', 'RA', 'Dec'), overwrite=True) for num in range(len(octclean)): octfile = octclean[num] with open(octfile, "r") as f: lines = f.readlines() for x in lines: line = x.split(' ') if int(line[3]) == 0: octxlist.append(line[1]) octylist.append(line[2]) octlineno.append('#%s' % line[0]) octxy = oct + 'c%s_xyoct_full.txt' % (num + 1) ascii.write([octxlist, octylist, octlineno], octxy, names=('#x', 'y', 'line no.'), overwrite=True) del octxlist[:], octylist[:], octlineno[:] str_out = 'c%s_oct_sept_match.txt' % (num + 1) refpnt = (reference + '%sref.txt' % (num + 1)) iraf.xyxymatch(input=(sept + 'xysept_full.txt'), reference=octxy, output=str_out, xmag=1.0, ymag=1.0, refpoints=refpnt, matching="tolerance", tolerance=3, verbose="no") with open(str_out, "r") as f: lines = f.readlines() for x in lines: x = x.strip() if not x or x.startswith('#'): continue septmatchlinelist.append(int(x.split()[5]) - 1) octmatchlinelist.append(int(x.split()[4]) - 1) if len(septmatchlinelist) != len( set(septmatchlinelist)) or len(octmatchlinelist) != len( set(octmatchlinelist)): print "Error: tweak xyxymatch parameters so that a coordinate in one set of data isn't matched to " \ "multiple coordinates in the other" print num sys.exit() with open((sept + 'xysept_full.txt'), 'r') as fs: tempsept, tempoct = np.array(septmatchlinelist), np.array( octmatchlinelist) with open(octxy, 'r') as f: lines = fs.readlines() linesoct = f.readlines() i = 1 for x in lines: line = x.split('#') if x.startswith("#"): continue elif i in septmatchlinelist: septcatlinelist.append(int(line[1])) masterseptlines[num].append(int(line[1])) RA.append(float(line[2])) Dec.append(float(line[3])) p = linesoct[octmatchlinelist[np.where( tempsept == i)[0][0]]].split('#') octcatlinelist.append(int(p[1])) masteroctlines[num].append(int(p[1])) i += 1 temptotal = [] with open(octfile, 'r') as f: tempoct = np.array(octcatlinelist) lines = f.readlines() for x in lines: z = int(x.split(' ')[0]) if x.startswith("#"): continue elif z in octcatlinelist: a = np.where(tempoct == z)[0][0] temptotal.append('%s %s %s %s\n' % (x.rstrip('\n'), RA[a], Dec[a], (num + 1))) for item in range(len(temptotal)): if int(temptotal[item].split(' ')[0]) in liststars[num]: oct_total.append(temptotal[item]) del septmatchlinelist[:], octmatchlinelist[:], septcatlinelist[:], octcatlinelist[:], RA[:], Dec[:], temptotal[:] with open('oct_total.txt', 'w') as f: for item in oct_total: f.write('%s' % item)
def stacking(cllist,zpofflist,ref,zprefoff=0.0,stackname='stack',shiftsize=400): """ """ #Reset the IRAF tasks used in this routine. iraf.unlearn('imcalc') iraf.unlearn('imcombine') iraf.unlearn('imreplace') iraf.unlearn('xyxymatch') iraf.unlearn('geomap') iraf.unlearn('geotran') iraf.unlearn('imcopy') #Find reference image in reference directory. Check to make #sure that it is actually the image and not the mask file! #Grab the mask for adding to the mask list now. (refimg,refmask,expmap)=classify(ref+'/tu*.fits') zpref=pf.open(refimg)[0].header['MAGZERO'] # zprefoff=NewfirmZPoffset[ref.split('/')[-1]] zprefoff=float(zprefoff) #Get 2MASS PSC positions for reference cluster image. catalog=get2masspsc(refimg) foo=file_check(ref+'/2mass_ref_stars.cdt',delete=True) foo=open(ref+'/2mass_ref_stars.cdt','w') for y in catalog: data=y.split() foo.write(data[6]+'\t'+data[7]+'\n') foo.close() #Create lists for files to be input into the stacking routine. foo=file_check('matchlist',delete=True) foo=file_check('scalelist',delete=True) foo=file_check('shiftlist',delete=True) foo=file_check('masklist',delete=True) foo=file_check('shiftmask',delete=True) foo=file_check('expmaplist',delete=True) (matchlist,scalelist,shiftlist,masklist, shiftmask,finalmasks,stacklist,stackmask, finalmasks2,expmaplist,shiftexp,expmaplist2)=(open('matchlist','w'),open('scalelist','w'), open('shiftlist','w'),open('masklist','w'), open('shiftmask','w'),open('finalmasks','w'), open('stacklist','w'),open('stackmask','w'), open('finalmasks2','w'),open('expmaplist','w'), open('shiftexp','w'),open('expmaplist2','w')) (xsize,ysize)=(np.array([]),np.array([])) #Step through all of the input cluster directories. i=0 for x in cllist: #Find the image, mask, and exposure map files. Get zeropoints and #scale image to the reference image. scaleimg=x+'/scaled_to_'+ref.split('/')[-1]+'.fits' foo=file_check(scaleimg,delete=True) (img,mask,expmap)=classify(x+'/tu*.fits') imgzp=pf.open(img)[0].header['MAGZERO'] (xs,ys)=(pf.open(img)[0].header['NAXIS1'],pf.open(img)[0].header['NAXIS2']) (xsize,ysize)=(np.append(xsize,xs),np.append(ysize,ys)) imgzpoff=float(zpofflist[i]) # imgzpoff=NewfirmZPoffset[x.split('/')[-1]] scale=scalecounts(imgzp+imgzpoff,zpref+zprefoff) iraf.imcalc(img,scaleimg,'im1*'+str(scale)) #Get X,Y pixel positions of 2MASS sources from the 2MASS PSC #in the image. Use these to compute shifts relative to the #reference image using IRAF task geomap. foo=file_check(x+'/2mass_ref_stars.cdt',delete=True) foo=open(x+'/2mass_ref_stars.cdt','w') catalog=get2masspsc(scaleimg) for y in catalog: data=y.split() foo.write(data[6]+'\t'+data[7]+'\n') foo.close() #Match the 2MASS PSC positions with stars in the reference #image using xyxymatch. The matched source list is then fed #into geomap to get the X and Y shifts. foo=file_check(x+'/2mass_matched.cdt',delete=True) iraf.xyxymatch(x+'/2mass_ref_stars.cdt',ref+'/2mass_ref_stars.cdt', x+'/2mass_matched.cdt','200.0',verbose='no') #Append all of the names of the files for the input and output filename #lists to be passed to IRAF tasks further down the line. matchlist.write(x+'/2mass_matched.cdt\n') scalelist.write(scaleimg+'\n') foo=file_check(x+'/scaled_and_shifted.fits',delete=True) shiftlist.write(x+'/scaled_and_shifted.fits['+str(shiftsize)+':'+\ str(int(np.max(xsize))+shiftsize)+','+str(shiftsize)+':'+\ str(int(np.max(ysize))+shiftsize)+']\n') stacklist.write(x+'/scaled_and_shifted.fits\n') file_check(x+'/mask_tmp.fits',delete=True) file_check(x+'/expmap_tmp.fits',delete=True) iraf.imarith(mask+'[1]','*',1000.0,x+'/mask_tmp.fits',pixtype='real') iraf.imarith(expmap+'[1]','*',1.0,x+'/expmap_tmp.fits',pixtype='real') offset=2.558435 file_check(x+'/mask_tmp2.fits',delete=True) iraf.imcalc(x+'/mask_tmp.fits',x+'/mask_tmp2.fits','im1+'+str(offset)) os.remove(x+'/mask_tmp.fits') masklist.write(x+'/mask_tmp2.fits\n') file_check(x+'/mask_shift.fits',delete=True) shiftmask.write(x+'/mask_shift.fits['+str(shiftsize)+':'+\ str(int(np.max(xsize))+shiftsize)+','+str(shiftsize)+':'+\ str(int(np.max(ysize))+shiftsize)+']\n') stackmask.write(x+'/mask_shift.fits\n') finalmasks.write(x+'/mask_final.fits\n') finalmasks2.write(x+'/mask_final.fits[0]\n') expmaplist.write(x+'/expmap_tmp.fits[0]\n') shiftexp.write(x+'/expmap_shift.fits['+str(shiftsize)+':'+\ str(int(np.max(xsize))+shiftsize)+','+str(shiftsize)+':'+\ str(int(np.max(ysize))+shiftsize)+']\n') expmaplist2.write(x+'/expmap_shift.fits\n') i += 1 #Close all of the input and output filename lists to be passed to IRAF tasks. matchlist.close() scalelist.close() stacklist.close() masklist.close() shiftmask.close() finalmasks.close() shiftlist.close() stackmask.close() finalmasks2.close() expmaplist.close() expmaplist2.close() shiftexp.close() #Get the shifts between all input files (including the reference) and the #reference image itself. foo=file_check('shift.db',delete=True) iraf.geomap('@matchlist','shift.db',1.0,np.max(xsize), 1.0,np.max(ysize),fitgeometry='shift',interactive='no', maxiter=2,function='legendre',verbose='no') #Shift the input images (including the reference) and associated mask files #to a common pixel grid. Add some padding around the individual frames (-99 #in the images, 1 in the bad pixel masks) to ensure that the images will #combine properly. (maxx,maxy)=(np.max(xsize)+shiftsize+100.0,np.max(ysize)+shiftsize+100.0) iraf.geotran('@scalelist','@shiftlist','shift.db','@matchlist',geometry='linear', boundary='constant',nlines=maxy,ncols=maxx,constant=-99.0) iraf.geotran('@masklist','@shiftmask','shift.db','@matchlist',geometry='linear', boundary='constant',nlines=maxy,ncols=maxx,constant=1000.0, nxblock=10000,nyblock=10000) iraf.geotran('@expmaplist','@shiftexp','shift.db','@matchlist',geometry='linear', boundary='constant',nlines=maxy,ncols=maxx,constant=0.) for x in cllist: file_check(x+'/mask_final.fits',delete=True) shutil.copy(x+'/mask_shift.fits',x+'/mask_final.fits') iraf.hedit(x+'/scaled_and_shifted.fits[0]','BPM',x+'/mask_final.fits[0]', add='yes',update='yes',verify='no') iraf.imreplace('@finalmasks2',0,upper=offset) iraf.imreplace('@finalmasks2',1,lower=offset) file_check(stackname,delete=True) file_check(stackname[:-5]+'_mask.pl',delete=True) file_check(stackname[:-5]+'_expmap.fits',delete=True) iraf.imcombine('@stacklist',stackname,bpmasks=stackname[:-5]+'_bpm', masktype='goodval',reject='none',mclip='yes',lthresh='INDEF',hthresh='INDEF', hsigma=10.0,lsigma='INDEF',nrejmasks=stackname[:-5]+'_nrej', sigmas=stackname[:-5]+'_sigma',grow=2.5,nkeep=1,blank=-99.0,gain=8.0,rdnoise=35.0) iraf.imcombine('@expmaplist2',stackname[:-5]+'_expmap.fits',combine='sum') hdu=pf.open(stackname,mode='update') hdu[0].header['BPM']=stackname.split('/')[-1][:-5]+'_mask.pl' hdu[0].header['MAGZERO']=zpref+zprefoff hdu.close() #Fix the WCS information in the stacked image. copyhead(stackname,refimg,offset=shiftsize) applywcs(stackname,stackname[:-5]+'_wcs.fits') trash=['matchlist','scalelist','shiftlist','masklist','shiftmask','finalmasks', 'shift.db','stacklist','finalmasks2','stackmask','tmp_wcs.fits','expmaplist', 'expmaplist2','shiftexp'] for x in trash: os.remove(x)
def cat_im_match(xref, yref, xin, yin, septol, **kwargs): '''Written by Gregory Rudnick 9 January 2018 PURPOSE: Take two lists of x and y coordinates in the same units and match them within some tolerance. Plot the differences in each coordinate. INPUT PARAMETERS: xref, yref: the reference coordinates in pixels. Numpy arrays. xin, yin: the input coordinates in pixels. If performing coordinate transforms, these would be the ones to be transformed. Numpy arrays septol: the maximum separation allowed for a match. Units are pixels OPTIONAL KEYWORD PARAMETERS icfile: The filename with the input reference coordinates for xyxymatch. These need to be created by hand from the images matchfile: a name of the file that will contain the reference and input coordinates. Suitable for geomap input. Default is 'xyxy_out.txt' OUTPUT arrays containing row-matched (x,y) coordinates of the reference and input coordinates that fall with septol ''' # #loop through all coordiantes and find closest match. This is an # #N^2 process. I can make it faster later. # #initialize distance coordinate # dist = np.full(xref.size, 1.e6) # #initialize array with indices of closest match # imatch = np.zeros(xref.size, dtype=np.int8) # for iref,valref in enumerate(xref): # for iin,valin in enumerate(xin): # #print("hi",iref,iin,xref[iref],xin[iin],yref[iref],yin[iin]) # disttest = np.sqrt( (xref[iref] - xin[iin])**2 +(yref[iref] - yin[iin])**2) # #find the closest reference point to each input point # if disttest < dist[iref]: # #print(disttest,iref,iin) # dist[iref] = disttest # imatch[iref] = iin # #select close matches, where I assume septol is in pixels, just like the input catalog # iclose = np.where(dist < septol) # #convert tuple to pure array # iclose=iclose[0] #generate input files for xyxymatch from reference coordinates xyxy_refin = 'xyxymatch_refcoords.txt' fo = open(xyxy_refin, "w") for i, val in enumerate(xref): #print(i,iclose[i]) #print(raref[iclose[i]],decref[iclose[i]],rain[idx[iclose[i]]],decin[idx[iclose[i]]]) fo.write('{} {}\n'.format(xref[i], yref[i])) fo.close() xyxy_inin = 'xyxymatch_incoords.txt' fo = open(xyxy_inin, "w") for i, val in enumerate(xin): fo.write('{} {}\n'.format(xin[i], yin[i])) fo.close() #set xyxymatch output name if keyword is given xyxy_out = 'xyxy_match.txt' #remove geotran output file if it already exists if os.path.isfile(xyxy_out) is True: cmdstr = 'rm ' + xyxy_out os.system(cmdstr) #run xyxymatch and include a set of reference points if given as input if 'icfile' in kwargs.keys(): iraf.xyxymatch(xyxy_inin, xyxy_refin, xyxy_out, septol, refpoints=kwargs['icfile'], \ xcolumn=1,ycolumn=2,xrcolumn=1,yrcolumn=2,matching="tolerance") else: iraf.xyxymatch(xyxy_inin, xyxy_refin, xyxy_out, septol, refpoints="", \ xcolumn=1,ycolumn=2,xrcolumn=1,yrcolumn=2,matching="tolerance") #read in xyxymatch output to get coordinate limits and to return #ordered matched coordinates xyxy_cat = ascii.read(xyxy_out) xref_m = np.array(xyxy_cat['col1']) yref_m = np.array(xyxy_cat['col2']) xin_m = np.array(xyxy_cat['col3']) yin_m = np.array(xyxy_cat['col4']) #write files only if "matchfile" keyword is set #this reformat of the xyxymatch code is just so that my other routines work keys = sorted(kwargs.keys()) for kw in keys: if kw == 'matchfile': #print(kwargs[kw]) #open file for writing and write a header fo = open(kwargs[kw], "w") fo.write("# xref yref xin yin\n") for i, val in enumerate(xref_m): #print(i,iclose[i]) #print(raref[iclose[i]],decref[iclose[i]],rain[idx[iclose[i]]],decin[idx[iclose[i]]]) fo.write('{} {} {} {}\n'.format(xref_m[i], yref_m[i], xin_m[i], yin_m[i])) fo.close() #store the limits of the coordinates lims = { 'xmax': np.amax(xref_m), 'xmin': np.amin(xref_m), 'ymax': np.amax(yref_m), 'ymin': np.amin(yref_m) } #return all matches within the tolerance return xref_m, yref_m, xin_m, yin_m, lims
def align_direct_to_reference(verbose=True, n_iter=20, drizzled_image=True): """ Use iraf software geomap to get shift solutions between images. n_iter = number of times to iterate over the alignment routines drizzled_image = boolean to distinguish between a drizzled image used for alignment, in which case the shifts must be transferred back to oiginal flt. """ ### get the root name: root = wfc3_grism.options['ROOT_DIRECT'] ### get the alignment image which has been produced ### with run_sregister_to_cutout_CANDELS_region() align_image = '%s_align_reference.fits' %(root) ### now run SExtractor on the direct and refereance ### images to build up 2 catalogs: se = wfc3_grism.sex.SExtractor() se.aXeParams() se.copyConvFile() se.overwrite = True se.options['CHECKIMAGE_TYPE'] = 'NONE' se.options['FILTER'] = 'Y' se.options['DETECT_THRESH'] = '%.1f' % wfc3_grism.options['ALIGN_DETECT_THRESH'] se.options['ANALYSIS_THRESH'] = '3' se.options['MAG_ZEROPOINT'] = '%.2f' % wfc3_grism.options['MAG_ZEROPOINT'] se.options['DETECT_MINAREA'] = '%.1f' % wfc3_grism.options['ALIGN_DETECT_MINAREA'] ### generate the direct image catalog: se.options['CATALOG_NAME'] = 'direct.cat' iraf.imcopy('%s_drz.fits[SCI]' %(root), "SCI.fits", verbose=False) ## if not using drizzled image for alignment done't include ### a weight image: if drizzled_image: se.options['WEIGHT_TYPE'] = 'MAP_WEIGHT' se.options['WEIGHT_IMAGE'] = 'WHT.fits' iraf.imcopy('%s_drz.fits[WHT]' %(root), "WHT.fits", verbose=False) else: se.options['WEIGHT_TYPE'] = 'NONE' se.options['WEIGHT_IMAGE'] = 'WHT.fits' status = se.sextractImage('SCI.fits') ### generate the alignment image catalog: se.options['CATALOG_NAME'] = 'align.cat' se.options['WEIGHT_TYPE'] = 'NONE' se.options['WEIGHT_IMAGE'] = 'WHT.fits' status = se.sextractImage(align_image) ### Read the catalogs direct_cat = wfc3_grism.sex.mySexCat('direct.cat') align_cat = wfc3_grism.sex.mySexCat('align.cat') ### initialize x,y shift parameters so can be ### updated with each iteration, the x,y shifts ### will converge twoard an optimal value over the ### iterations: xshift = 0 yshift = 0 rot = 0 scale = 1. ### empty line in the output to make things clearer: print "" ### now loop through the process until xrms and yrms both < 0.5 ### or run out of number of iterations: xrms, yrms = 100, 100 toler = wfc3_grism.options['ALIGN_TOLERANCE'] iteration = 0 max_iter = wfc3_grism.options['ALIGN_ITERATIONS'] while ((xrms > 0.1) | (yrms > 0.1)) & (iteration <= max_iter): print "Running matching algorithm on iteration #%d" %(iteration) ### Get x,y coordinates of detected objects direct image fp = open('direct.xy','w') for i in range(len(direct_cat.X_IMAGE)): fp.write('%-15s%-15s\n' %(direct_cat.X_IMAGE[i],direct_cat.Y_IMAGE[i])) fp.close() ### Get x,y coordinates of detected objects alignment image fp = open('align.xy','w') for i in range(len(align_cat.X_IMAGE)): fp.write('%-15s%-15s\n' %(np.float(align_cat.X_IMAGE[i])+xshift, np.float(align_cat.Y_IMAGE[i])+yshift)) fp.close() ### iraf flpr() wfc3_grism.utils.iraf_flpr() ### remove previous solution: if iteration > 0: os.remove('align.match') ### get the alignment catalog: status = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**toler, separation=0, verbose=True, Stdout=1) ### iraf flpr() wfc3_grism.utils.iraf_flpr() ### now get shifts with geomap: if iteration > 0: os.remove('align.map') iraf.geomap(input="align.match", database="align.map", fitgeometry="shift", interactive=False, xmin=iraf.INDEF, xmax=iraf.INDEF, ymin=iraf.INDEF, ymax=iraf.INDEF, maxiter = 10, reject = 2.0, Stdout=1) ### get the output from geomap: fp = open("align.map", "r") for line in fp.readlines(): spl = line.split() if spl[0].startswith('xshift'): xshift += float(spl[1]) if spl[0].startswith('yshift'): yshift += float(spl[1]) if spl[0].startswith('xrotation'): rot = float(spl[1]) if spl[0].startswith('xmag'): scale = float(spl[1]) if spl[0].startswith('xrms'): xrms = float(spl[1]) if spl[0].startswith('yrms'): yrms = float(spl[1]) fp.close() ### update iteration counter: iteration += 1 toler += 1 print 'Shift iteration #%d, xshift=%f, yshift=%f, rot=%f, scl=%f (rms: %5.2f,%5.2f)' %(iteration, xshift, yshift, rot, scale, xrms, yrms) ### copy the final align.map for posterity: shutil.copy('align.map', '%s_align.map' %(root)) ## cleanup from the alignment process: remvfiles = ['SCI.fits','WHT.fits','align.cat', 'align.map','align.match','align.reg','align.xy', 'direct.cat','direct.reg','direct.xy', 'drz_sci.fits','drz_wht.fits','bg.fits', 'imxymatch.1', 'sex_stderr', 'wfc3_grism_auto.sex', 'wfc3_grism_auto.param', 'default.nnw', 'default.conv'] for file in remvfiles: try: os.remove(file) except: pass if drizzled_image: #### shifts measured in drz frame. Translate to the flt frame: drz = fits.open('%s_drz.fits' %(root)) #### Get reference angle from first image in the ASN file: asn = wfc3_grism.utils.ASNFile('%s_asn.fits' %(root)) alpha = (180. - fits.getheader(asn.exposures[0]+'_flt.fits', 1)['PA_APER']) / 360. * 2 * np.pi ### Get the drizzle scale from the MultiDrizzle '.run' file: for line in open('%s.run' %(root),'r'): if line.startswith('drizzle.scale'): drizzle_scale = line.split()[2] print drizzle_scale ### get the equivalent shifts in the FLT frames: xsh = (xshift*np.cos(alpha) - yshift*np.sin(alpha))*np.float(drizzle_scale) ysh = (xshift*np.sin(alpha) + yshift*np.cos(alpha))*np.float(drizzle_scale) print 'Final shift:', xsh, ysh, drz[1].header['PA_APER'] else: xsh = xshift ysh = yshift fp = open('%s_align.info' %(root),'w') fp.write('%s %8.3f %8.3f %8.3f\n' %(align_image, xsh, ysh, rot)) fp.close() #### Read the shiftfile if drizzled_image: shiftF = ShiftFile('%s_initial_shifts.txt' %(root)) shiftF.xshift = list(np.array(shiftF.xshift)-xsh) shiftF.yshift = list(np.array(shiftF.yshift)-ysh) shiftF.rotate = list((np.array(shiftF.rotate)+rot) % 360) shiftF.scale = list(np.array(shiftF.scale)*scale) shiftF.write('%s_final_shifts.txt' %(root)) else: ### use the default shift file in wfc3_grism data folder: shiftF = ShiftFile('/disk1/fc/FIGS/wfc3_grism/data/default_shift_file.txt') ### add the reference image as needed by multidrizzle: shiftF.headerlines[1] = '# refimage: %s \n' %(align_image) #### Apply the alignment shifts to the shiftfile shiftF.xshift = [np.array(xsh)] shiftF.yshift = [np.array(ysh)] shiftF.rotate = [np.array(rot) % 360] shiftF.scale = [np.array(scale)] shiftF.write('%s_final_shifts.txt' %(root))
def align_to_reference(ROOT_DIRECT, ALIGN_IMAGE, fitgeometry="shift", clean=True, verbose=False, ALIGN_EXTENSION=0, toler=3, skip_swarp=False, align_sdss_ds9=False, catalog=None): """ xshift, yshift, rot, scale, xrms, yrms = align_to_reference() """ import os import glob import shutil from pyraf import iraf from iraf import stsdas, dither import threedhst from threedhst import catIO no = iraf.no yes = iraf.yes INDEF = iraf.INDEF #### Clean slate rmfiles = [ 'SCI.fits', 'WHT.fits', 'align.cat', 'direct.cat' 'align.map', 'align.match', 'align.reg', 'align.xy', 'direct.reg', 'direct.xy', 'ds9_align.tsv' ] for file in rmfiles: try: os.remove(file) except: pass if catalog is not None: align_sdss_ds9 = True #### Get only images that overlap from the ALIGN_IMAGE list if not align_sdss_ds9: align_img_list = find_align_images_that_overlap( ROOT_DIRECT + '_drz.fits', ALIGN_IMAGE, ALIGN_EXTENSION=ALIGN_EXTENSION) if not align_img_list: print 'threedhst.shifts.align_to_reference: no alignment images overlap.' return 0, 0 #### Use swarp to combine the alignment images to the same image #### dimensions as the direct mosaic if (not skip_swarp) & (not align_sdss_ds9): try: os.remove(ROOT_DIRECT + '_align.fits') except: pass matchImagePixels(input=align_img_list, matchImage=ROOT_DIRECT + '_drz.fits', output=ROOT_DIRECT + '_align.fits', match_extension=1, input_extension=ALIGN_EXTENSION) #### Run SExtractor on the direct image, with the WHT #### extension as a weight image se = threedhst.sex.SExtractor() se.aXeParams() se.copyConvFile() se.overwrite = True se.options['CHECKIMAGE_TYPE'] = 'NONE' se.options['WEIGHT_TYPE'] = 'MAP_WEIGHT' se.options['WEIGHT_IMAGE'] = 'WHT.fits' se.options['FILTER'] = 'Y' ## Detect thresholds (default = 1.5) THRESH = 10 if align_sdss_ds9: if 'Vizier' not in REFERENCE_CATALOG: THRESH = 20 se.options['DETECT_THRESH'] = '%d' % (THRESH) se.options['ANALYSIS_THRESH'] = '%d' % (THRESH) se.options['MAG_ZEROPOINT'] = str(threedhst.options['MAG_ZEROPOINT']) #### Run SExtractor on direct and alignment images ## direct image se.options['CATALOG_NAME'] = 'direct.cat' iraf.imcopy(ROOT_DIRECT + '_drz.fits[1]', "SCI.fits") iraf.imcopy(ROOT_DIRECT + '_drz.fits[2]', "WHT.fits") status = se.sextractImage('SCI.fits') ## Read the catalog directCat = threedhst.sex.mySexCat('direct.cat') if align_sdss_ds9: ### Use ds9 SDSS catalog to refine alignment import threedhst.dq import pywcs import threedhst.catIO as catIO wcs = pywcs.WCS(pyfits.getheader('SCI.fits', 0)) #wcs = pywcs.WCS(pyfits.getheader('Q0821+3107-F140W_drz.fits', 1)) if 'Vizier' in REFERENCE_CATALOG: #### Use (unstable) astroquery Vizier search #### CFHTLS-Deep: 'Vizier.II/317' VIZIER_CAT = REFERENCE_CATALOG.split('Vizier.')[1] print 'Align to Vizier catalog: http://vizier.u-strasbg.fr/viz-bin/VizieR?-source=%s' % ( VIZIER_CAT) import astroquery if astroquery.__version__ < '0.0.dev1078': from astroquery import vizier query = {} query["-source"] = VIZIER_CAT #query["-out"] = ["_r", "CFHTLS", "rmag"] query["-out"] = ["_RAJ2000", "_DEJ2000"] ### Just RA/Dec. #### Center position and query radius r0, d0 = wcs.wcs_pix2sky([[wcs.naxis1 / 2., wcs.naxis2 / 2.]], 1)[0] rll, dll = wcs.wcs_pix2sky([[0, 0]], 1)[0] corner_radius = np.sqrt( (r0 - rll)**2 * np.cos(d0 / 360. * 2 * np.pi)**2 + (d0 - dll)**2) * 60. * 1.5 h = query["-c"] = "%.6f %.6f" % (r0, d0) query["-c.rm"] = "%.3f" % (corner_radius ) ### xxx check image size #### Run the query vt = vizier.vizquery(query) else: #### Newer astroquery from astroquery.vizier import Vizier import astropy.coordinates as coord import astropy.units as u Vizier.ROW_LIMIT = -1 r0, d0 = wcs.wcs_pix2sky([[wcs.naxis1 / 2., wcs.naxis2 / 2.]], 1)[0] rll, dll = wcs.wcs_pix2sky([[0, 0]], 1)[0] corner_radius = np.sqrt( (r0 - rll)**2 * np.cos(d0 / 360. * 2 * np.pi)**2 + (d0 - dll)**2) * 60. * 1.5 # c = coord.ICRSCoordinates(ra=r0, dec=d0, unit=(u.deg, u.deg)) #### something with astropy.coordinates # c.icrs.ra.degree = c.icrs.ra.degrees # c.icrs.dec.degree = c.icrs.dec.degrees # vt = Vizier.query_region(c, width=u.Quantity( corner_radius, u.arcminute), catalog=[VIZIER_CAT])[0] #### Make a region file ra_list, dec_list = vt['RAJ2000'], vt['DEJ2000'] print 'Vizier, found %d objects.' % (len(ra_list)) fp = open('%s.vizier.reg' % (ROOT_DIRECT), 'w') fp.write('# %s, r=%.1f\'\nfk5\n' % (VIZIER_CAT, corner_radius)) for ra, dec in zip(ra_list, dec_list): fp.write('circle(%.6f, %.6f, 0.5")\n' % (ra, dec)) # fp.close() else: #### Use DS9 catalog ds9 = threedhst.dq.myDS9() ds9.set('file SCI.fits') #ds9.set('file Q0821+3107-F140W_drz.fits') ds9.set('catalog %s' % (REFERENCE_CATALOG)) ### Can't find XPA access point for "copy to regions" ds9.set('catalog export tsv ds9_align.tsv') lines = open('ds9_align.tsv').readlines() ra_list, dec_list = [], [] for line in lines[1:]: spl = line.split() ra, dec = float(spl[0]), float(spl[1]) ra_list.append(ra) dec_list.append(dec) # del (ds9) x_image, y_image = [], [] for ra, dec in zip(ra_list, dec_list): x, y = wcs.wcs_sky2pix([[ra, dec]], 1)[0] x_image.append(x) y_image.append(y) alignCat = catIO.EmptyCat() alignCat['X_IMAGE'] = np.array(x_image) alignCat['Y_IMAGE'] = np.array(y_image) else: ## alignment image se.options['CATALOG_NAME'] = 'align.cat' status = se.sextractImage(ROOT_DIRECT + '_align.fits') alignCat = threedhst.sex.mySexCat('align.cat') xshift = 0 yshift = 0 rot = 0 scale = 1. xrms = 2 yrms = 2 NITER = 5 IT = 0 while (IT < NITER): IT = IT + 1 #### Get x,y coordinates of detected objects ## direct image fp = open('direct.xy', 'w') for i in range(len(directCat.X_IMAGE)): fp.write('%s %s\n' % (directCat.X_IMAGE[i], directCat.Y_IMAGE[i])) fp.close() ## alignment image fp = open('align.xy', 'w') for i in range(len(alignCat.X_IMAGE)): fp.write('%s %s\n' % (np.float(alignCat.X_IMAGE[i]) + xshift, np.float(alignCat.Y_IMAGE[i]) + yshift)) fp.close() iraf.flpr() iraf.flpr() iraf.flpr() #### iraf.xyxymatch to find matches between the two catalogs pow = toler * 1. try: os.remove('align.match') except: pass status1 = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**pow, separation=0, verbose=yes, Stdout=1) nmatch = 0 while status1[-1].startswith('0') | (nmatch < 10): pow += 1 os.remove('align.match') status1 = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**pow, separation=0, verbose=yes, Stdout=1) # nmatch = 0 for line in open('align.match').xreadlines(): nmatch += 1 if verbose: for line in status1: print line #### Compute shifts with iraf.geomap iraf.flpr() iraf.flpr() iraf.flpr() try: os.remove("align.map") except: pass status2 = iraf.geomap(input="align.match", database="align.map", fitgeometry=fitgeometry, interactive=no, xmin=INDEF, xmax=INDEF, ymin=INDEF, ymax=INDEF, maxiter=10, reject=2.0, Stdout=1) if verbose: for line in status2: print line #fp = open(root+'.iraf.log','a') #fp.writelines(status1) #fp.writelines(status2) #fp.close() #### Parse geomap.output fp = open("align.map", "r") for line in fp.readlines(): spl = line.split() if spl[0].startswith('xshift'): xshift += float(spl[1]) if spl[0].startswith('yshift'): yshift += float(spl[1]) if spl[0].startswith('xrotation'): rot = float(spl[1]) if spl[0].startswith('xmag'): scale = float(spl[1]) if spl[0].startswith('xrms'): xrms = float(spl[1]) if spl[0].startswith('yrms'): yrms = float(spl[1]) fp.close() #os.system('wc align.match') print 'Shift iteration #%d, xshift=%f, yshift=%f, rot=%f, scl=%f (rms: %5.2f,%5.2f)' % ( IT, xshift, yshift, rot, scale, xrms, yrms) im = pyfits.open('SCI.fits') shutil.copy('align.map', ROOT_DIRECT + '_align.map') shutil.copy('align.match', ROOT_DIRECT + '_align.match') #### Cleanup if clean: rmfiles = [ 'SCI.fits', 'WHT.fits', 'align.cat', 'align.map', 'align.match', 'align.reg', 'align.xy', 'direct.cat', 'direct.reg', 'direct.xy', 'drz_sci.fits', 'drz_wht.fits', 'bg.fits' ] for file in rmfiles: try: os.remove(file) except: pass return xshift, yshift, rot, scale, xrms, yrms
def plot_shifts(ROOT_DIRECT, ALIGN_IMAGE, clean=True, verbose=True, ALIGN_EXTENSION=0, toler=3, skip_swarp=False, threshold=7, force=False, drz=True, WEIGHT_IMAGE=None): """ Run SExtractor on two images and match the objects to plot the shifts between them. ALIGN_IMAGE is a string that may contain wildcards, and the function will use `align_img_list` to find ALIGN_IMAGEs """ import glob from pyraf import iraf from iraf import stsdas, dither no = iraf.no yes = iraf.yes INDEF = iraf.INDEF if os.path.exists(ROOT_DIRECT + '_align.fits') & (not force): if verbose: print 'Image %s_align.fits exists. Skipping SWarp.' % ( ROOT_DIRECT) skip_swarp = True if not skip_swarp: if drz: align_img_list = find_align_images_that_overlap( ROOT_DIRECT + '_drz.fits', ALIGN_IMAGE, ALIGN_EXTENSION=ALIGN_EXTENSION) else: align_img_list = glob.glob(ALIGN_IMAGE) if not align_img_list: print 'threedhst.shifts.align_to_reference: no alignment images overlap.' return 0, 0 # try: os.remove(ROOT_DIRECT + '_align.fits') except: pass if drz: matchImagePixels(input=align_img_list, matchImage=ROOT_DIRECT + '_drz.fits', output=ROOT_DIRECT + '_align.fits', match_extension=1, input_extension=ALIGN_EXTENSION) ALIGN_FITS = ROOT_DIRECT + '_align.fits' else: ALIGN_FITS = os.path.basename( ROOT_DIRECT.split('.fits')[0]) + '_align.fits' matchImagePixels(input=align_img_list, matchImage=ROOT_DIRECT, output=ALIGN_FITS, match_extension=0, input_extension=ALIGN_EXTENSION) se = threedhst.sex.SExtractor() se.aXeParams() se.copyConvFile() se.overwrite = True se.options['CHECKIMAGE_TYPE'] = 'NONE' se.options['WEIGHT_TYPE'] = 'MAP_WEIGHT' if drz: se.options['WEIGHT_IMAGE'] = ROOT_DIRECT + '_drz.fits[1]' else: if WEIGHT_IMAGE: se.options['WEIGHT_IMAGE'] = WEIGHT_IMAGE else: se.options['WEIGHT_TYPE'] = 'NONE' se.options['WEIGHT_IMAGE'] = 'NONE' se.options['FILTER'] = 'Y' ## Detect thresholds (default = 1.5) se.options['DETECT_THRESH'] = '%f' % (threshold) se.options['ANALYSIS_THRESH'] = '%f' % (threshold) se.options['MAG_ZEROPOINT'] = str(threedhst.options['MAG_ZEROPOINT']) #### Run SExtractor on direct and alignment images ## direct image se.options['CATALOG_NAME'] = 'direct.cat' if drz: status = se.sextractImage(ROOT_DIRECT + '_drz.fits[0]') INPUT_IMAGE = ROOT_DIRECT + '_drz.fits' else: status = se.sextractImage(ROOT_DIRECT) INPUT_IMAGE = ROOT_DIRECT ## alignment image se.options['CATALOG_NAME'] = 'align.cat' se.options['WEIGHT_TYPE'] = 'NONE' status = se.sextractImage(ALIGN_FITS) ## Read the catalogs directCat = threedhst.sex.mySexCat('direct.cat') alignCat = threedhst.sex.mySexCat('align.cat') xshift = 0 yshift = 0 rot = 0 scale = 1. xrms = 2 yrms = 2 NITER = 5 IT = 0 while (IT < NITER): IT = IT + 1 #### Get x,y coordinates of detected objects ## direct image fp = open('direct.xy', 'w') for i in range(len(directCat.X_IMAGE)): fp.write('%s %s\n' % (directCat.X_IMAGE[i], directCat.Y_IMAGE[i])) fp.close() ## alignment image fp = open('align.xy', 'w') for i in range(len(alignCat.X_IMAGE)): fp.write('%s %s\n' % (np.float(alignCat.X_IMAGE[i]) + xshift, np.float(alignCat.Y_IMAGE[i]) + yshift)) fp.close() iraf.flpr() iraf.flpr() iraf.flpr() #### iraf.xyxymatch to find matches between the two catalogs pow = toler * 1. try: os.remove('align.match') except: pass status1 = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**pow, separation=0, verbose=yes, Stdout=1) while status1[-1].startswith('0'): pow += 1 os.remove('align.match') status1 = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**pow, separation=0, verbose=yes, Stdout=1) #### Images are aligned, plot the offsets dx, dy, ax, ay, di, ai = np.loadtxt('align.match', unpack=True) ddx, ddy = dx - ax, dy - ay keep = (np.abs(ddx) < 15) & (np.abs(ddy) < 15) for i in range(5): sx, sy = threedhst.utils.biweight( ddx[keep], both=True), threedhst.utils.biweight(ddy[keep], both=True) keep = keep & (np.abs(ddx - sx[0]) < 5 * sx[1]) & (np.abs(ddy - sy[0]) < 5 * sy[1]) if USE_PLOT_GUI: fig = plt.figure(figsize=[8, 4], dpi=100) else: fig = Figure(figsize=[8, 4], dpi=100) fig.subplots_adjust(wspace=0.28, hspace=0.0, left=0.08, bottom=0.14, right=0.98, top=0.98) ax = fig.add_subplot(121) ax.plot(ddx, ddy, marker='o', linestyle='None', color='black', alpha=0.4, ms=2, zorder=-1) ax.errorbar(sx[0], sy[0], sx[1], sy[1], marker='o', ms=0.1, color='white', linewidth=3, zorder=100) ax.errorbar(sx[0], sy[0], sx[1], sy[1], marker='o', ms=0.1, color='red', linewidth=2, zorder=500) ax.grid(alpha=0.5) dwin = 5 * np.max([sx[1], sy[1]]) ax.set_xlim(sx[0] - dwin, sx[0] + dwin) ax.set_ylim(sy[0] - dwin, sy[0] + dwin) ax.set_xlabel(r'$\Delta x$ [pix]') ax.set_ylabel(r'$\Delta y$ [pix]') ax.text(0.5, 0.95, os.path.basename(INPUT_IMAGE), fontsize=9, horizontalalignment='center', transform=ax.transAxes) ax.text(0.5, 0.9, os.path.basename(ALIGN_IMAGE), fontsize=9, horizontalalignment='center', transform=ax.transAxes) ax.text(0.5, 0.1, r'$\Delta x, \Delta y = %.2f \pm %.2f, %.2f \pm %.2f)$' % (sx[0], sx[1], sy[0], sy[1]), fontsize=11, horizontalalignment='center', transform=ax.transAxes) ax = fig.add_subplot(122) ax.plot(dx[keep], dy[keep], marker='o', ms=1, linestyle='None', color='black', alpha=0.1) ax.quiver(dx[keep], dy[keep], ddx[keep], ddy[keep], alpha=0.5, angles='xy', headlength=1, headwidth=1, scale=30. / (dx.max() - dx.min()), units='x', minlength=1) aa = np.array([1, 1]) ax.quiver(dx[keep].mean() * aa, dy[keep].max() * 0.95 * aa, 1 * aa, 0 * aa, alpha=0.9, angles='xy', headlength=0, headwidth=1, scale=30. / (dx.max() - dx.min()), units='x', color='red') ax.set_xlabel(r'$x$ [pix]') ax.set_ylabel(r'$y$ [pix]') if USE_PLOT_GUI: fig.savefig(os.path.basename(ROOT_DIRECT.split('.fits')[0]) + '_align.pdf', dpi=100, transparent=False) else: canvas = FigureCanvasAgg(fig) canvas.print_figure(os.path.basename(ROOT_DIRECT.split('.fits')[0]) + '_align.pdf', dpi=100, transparent=False) if clean: rmfiles = [ 'SCI.fits', 'WHT.fits', 'align.cat', 'align.map', 'align.match', 'align.reg', 'align.xy', 'direct.cat', 'direct.reg', 'direct.xy', 'drz_sci.fits', 'drz_wht.fits', 'bg.fits' ] for file in rmfiles: try: os.remove(file) except: pass
def get_align_to_subaru(sci='M0416_Ks_c1_mp_avg.fits', wht='M0416_Ks_c1_mp_exp.fits', field='', clean=True, toler=3, verbose=False, fitgeometry='shift', shift_max=20, rms_max=1.1, rot_max=2, rot_only=True, THRESH=2, align_data=None): """ Align HAWK-I images to the FF Subaru astrometric reference catalogs """ #sci='M0416_Ks_c1_mp_avg.fits'; wht='M0416_Ks_c1_mp_exp.fits' ### Make object catalog se = threedhst.sex.SExtractor() se.aXeParams() se.copyConvFile() se.overwrite = True se.options['CHECKIMAGE_TYPE'] = 'NONE' if wht is None: se.options['WEIGHT_TYPE'] = 'NONE' else: se.options['WEIGHT_TYPE'] = 'MAP_WEIGHT' se.options['WEIGHT_IMAGE'] = wht se.options['FILTER'] = 'Y' se.options['DETECT_THRESH'] = '%d' %(THRESH) se.options['ANALYSIS_THRESH'] = '%d' %(THRESH) se.options['MAG_ZEROPOINT'] = '26.0' #### Run SExtractor on direct and alignment images ## direct image se.options['CATALOG_NAME'] = 'direct.cat' status = se.sextractImage(sci) threedhst.sex.sexcatRegions('direct.cat', 'direct.reg', format=2) directCat = threedhst.sex.mySexCat('direct.cat') #### Get the X/Y coords of the reference catalog #head = pyfits.getheader(sci, 0) #wcs = pywcs.WCS(head) if 'M0416' in sci: ra_list, dec_list, mag = np.loadtxt(os.getenv('HAWKI')+'/FrontierFields/HST/hlsp_frontier_subaru_suprimecam_macs0416-astrom_R_v1_cat.txt', unpack=True) if ('c4' in sci): ra_list, dec_list, mag = np.loadtxt(os.getenv('HAWKI')+'/FrontierFields/HST/M0416/macs0416_f814w_radec.cat', unpack=True) # if 'M0717' in sci: ra_list, dec_list, mag = np.loadtxt('subaru.radec', unpack=True) if ('M1149' in sci) | (field == 'M1149'): ra_list, dec_list, mag = np.loadtxt('/Users/brammer/Research/VLT/HAWKI/MACS1149/hlsp_frontier_subaru_suprimecam_macs1149-astrom_R_v1_cat.txt', unpack=True) if 'A2744' in sci: ra_list, dec_list, mag = np.loadtxt(os.getenv('HAWKI')+'/FrontierFields/HST/hlsp_frontier_subaru_suprimecam_abell2744-astrom_i_v1_cat.txt', unpack=True) if ('c1' in sci) | ('c4' in sci): ra_list, dec_list, mag = np.loadtxt(os.getenv('HAWKI')+'/FrontierFields/HST/abell2744_f814w_radec.cat', unpack=True) if align_data is not None: ra_list, dec_list, mag = align_data im = pyfits.open(sci) print sci sh = im[0].shape head = im[0].header head['CUNIT1'] = 'deg'; head['CUNIT2'] = 'deg' wcs = pywcs.WCS(head) x_image, y_image = wcs.wcs_sky2pix(ra_list, dec_list, 1) try: x_image, y_image = wcs.wcs_sky2pix(ra_list, dec_list, 1) except: x_image, y_image = wcs.wcs_world2pix(ra_list, dec_list, 1) ok = (x_image > 0) & (y_image > 0) & (x_image < sh[1]) & (y_image < sh[1]) x_image, y_image = x_image[ok], y_image[ok] fpr = open('align.reg','w') fpr.write('image\n') for i in range(ok.sum()): fpr.write('circle(%.6f, %.6f,0.3") # color=magenta\n' %(x_image[i], y_image[i])) fpr.close() # x_image, y_image = [], [] # # for ra, dec in zip(ra_list, dec_list): # x, y = wcs.wcs_sky2pix([[ra, dec]], 1)[0] # if (x > 0) & (y > 0) & (x < sh[1]) & (y < sh[1]): # x_image.append(x) # y_image.append(y) alignCat = catIO.EmptyCat() alignCat['X_IMAGE'] = np.array(x_image) alignCat['Y_IMAGE'] = np.array(y_image) xshift = 0 yshift = 0 rot = 0 scale = 1. xrms = 2 yrms = 2 NITER = 5 IT = 0 while (IT < NITER): IT = IT+1 #### Get x,y coordinates of detected objects ## direct image fp = open('direct.xy','w') for i in range(len(directCat.X_IMAGE)): fp.write('%s %s\n' %(directCat.X_IMAGE[i],directCat.Y_IMAGE[i])) fp.close() ## alignment image fp = open('align.xy','w') for i in range(len(alignCat.X_IMAGE)): fp.write('%s %s\n' %(np.float(alignCat.X_IMAGE[i])+xshift, np.float(alignCat.Y_IMAGE[i])+yshift)) fp.close() iraf.flpr() iraf.flpr() iraf.flpr() #### iraf.xyxymatch to find matches between the two catalogs pow = toler*1. try: os.remove('align.match') except: pass status1 = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**pow, separation=0, verbose=iraf.yes, Stdout=1) nmatch = 0 while status1[-1].startswith('0') | (nmatch < 10) | (float(status1[-3].split()[1]) > 40): pow+=1 os.remove('align.match') status1 = iraf.xyxymatch(input="direct.xy", reference="align.xy", output="align.match", tolerance=2**pow, separation=0, verbose=iraf.yes, Stdout=1) # nmatch = 0 for line in open('align.match').xreadlines( ): nmatch += 1 if verbose: for line in status1: print line #### Compute shifts with iraf.geomap iraf.flpr() iraf.flpr() iraf.flpr() try: os.remove("align.map") except: pass status2 = iraf.geomap(input="align.match", database="align.map", fitgeometry=fitgeometry, interactive=iraf.no, xmin=iraf.INDEF, xmax=iraf.INDEF, ymin=iraf.INDEF, ymax=iraf.INDEF, maxiter = 10, reject = 2.0, Stdout=1) if verbose: for line in status2: print line #fp = open(root+'.iraf.log','a') #fp.writelines(status1) #fp.writelines(status2) #fp.close() #### Parse geomap.output fp = open("align.map","r") for line in fp.readlines(): spl = line.split() if spl[0].startswith('xshift'): xshift += float(spl[1]) if spl[0].startswith('yshift'): yshift += float(spl[1]) if spl[0].startswith('xrotation'): rot = float(spl[1]) if spl[0].startswith('xmag'): scale = float(spl[1]) if spl[0].startswith('xrms'): xrms = float(spl[1]) if spl[0].startswith('yrms'): yrms = float(spl[1]) fp.close() #os.system('wc align.match') print 'Shift iteration #%d, xshift=%f, yshift=%f, rot=%f, scl=%f (rms: %5.2f,%5.2f)' %(IT, xshift, yshift, rot, scale, xrms, yrms) os.system('cat align.match | grep -v "\#" | grep [0-9] | awk \'{print "circle(", $1, ",", $2, ",4) # color=green"}\' > d.reg') os.system('cat align.match | grep -v "\#" | grep [0-9] | awk \'{print "circle(", $3, ",", $4, ",4) # color=magenta"}\' > a.reg') shutil.copy('align.map', sci.replace('.fits', '.align.map')) shutil.copy('align.match', sci.replace('.fits', '.align.match')) #### Cleanup if clean: rmfiles = ['align.cat', 'align.map','align.match','align.reg','align.xy', 'direct.cat','direct.reg','direct.xy'] for file in rmfiles: try: os.remove(file) except: pass fp = open(sci.replace('.fits', '.align.info'), 'w') fp.write('# image xshift yshift rot scale xrms yrms\n') fp.write('%s %.3f %.3f %.4f %.4f %.3f %.3f\n' %(sci, xshift, yshift, rot, scale, xrms, yrms)) if (np.abs(xshift) > shift_max) | (np.abs(yshift) > shift_max) | (xrms > rms_max) | (yrms > rms_max): print 'Shifts out of allowed range. Run again with increased shift_max to accept.' #return xshift, yshift, rot, scale, xrms, yrms ## Add a small shift that should come out easily with another ## shift iteration xshift, yshift, rot, scale, xrms, yrms = 2,2,0,1.0,-99,-99 for file in [sci, wht]: if ('r' in fitgeometry) & rot_only: xshift, yshift = 0, 0 #apply_offsets(file, [[xshift, yshift, rot, scale]]) from drizzlepac import updatehdr updatehdr.updatewcs_with_shift(file, sci, wcsname='DRZWCS', rot=rot,scale=scale, xsh=xshift, ysh=yshift, fit=None, xrms=xrms, yrms = yrms, verbose=False, force=True, sciext=0) if '_dr' in sci: im = pyfits.open(sci) h = im[0].header for i in range(h['NDRIZIM']): flt_str = h['D%03dDATA' %(i+1)] if 'sci,2' in flt_str: continue # flt_im = flt_str.split('[')[0] ext = int(flt_str.split('[')[1][:-1].split(',')[1]) updatehdr.updatewcs_with_shift(flt_im, sci, wcsname='GTWEAK', rot=rot, scale=scale, xsh=xshift, ysh=yshift, fit=None, xrms=xrms, yrms = yrms, verbose=False, force=True, sciext='SCI') # im = pyfits.open(file, mode='update') # wcs = pywcs.WCS(im[0].header) # wcs.rotateCD(-rot) # wcs.wcs.cd /= scale # # # im[0].header['CRPIX1'] += xshift # im[0].header['CRPIX2'] += yshift # # # for i in [0,1]: # for j in [0,1]: # im[0].header['CD%d_%d' %(i+1, j+1)] = wcs.wcs.cd[i,j] # # # im.flush() return xshift, yshift, rot, scale, xrms, yrms
def align_to_reference( ROOT_DIRECT, ALIGN_IMAGE, fitgeometry="shift", clean=True, verbose=False, ALIGN_EXTENSION=0, toler=3, skip_swarp=False, align_sdss_ds9=False, catalog=None, ): """ xshift, yshift, rot, scale, xrms, yrms = align_to_reference() """ import os import glob import shutil from pyraf import iraf from iraf import stsdas, dither import threedhst from threedhst import catIO no = iraf.no yes = iraf.yes INDEF = iraf.INDEF #### Clean slate rmfiles = [ "SCI.fits", "WHT.fits", "align.cat", "direct.cat" "align.map", "align.match", "align.reg", "align.xy", "direct.reg", "direct.xy", "ds9_align.tsv", ] for file in rmfiles: try: os.remove(file) except: pass if catalog is not None: align_sdss_ds9 = True #### Get only images that overlap from the ALIGN_IMAGE list if not align_sdss_ds9: align_img_list = find_align_images_that_overlap( ROOT_DIRECT + "_drz.fits", ALIGN_IMAGE, ALIGN_EXTENSION=ALIGN_EXTENSION ) if not align_img_list: print "threedhst.shifts.align_to_reference: no alignment images overlap." return 0, 0 #### Use swarp to combine the alignment images to the same image #### dimensions as the direct mosaic if (not skip_swarp) & (not align_sdss_ds9): try: os.remove(ROOT_DIRECT + "_align.fits") except: pass matchImagePixels( input=align_img_list, matchImage=ROOT_DIRECT + "_drz.fits", output=ROOT_DIRECT + "_align.fits", match_extension=1, input_extension=ALIGN_EXTENSION, ) #### Run SExtractor on the direct image, with the WHT #### extension as a weight image se = threedhst.sex.SExtractor() se.aXeParams() se.copyConvFile() se.overwrite = True se.options["CHECKIMAGE_TYPE"] = "NONE" se.options["WEIGHT_TYPE"] = "MAP_WEIGHT" se.options["WEIGHT_IMAGE"] = "WHT.fits" se.options["FILTER"] = "Y" ## Detect thresholds (default = 1.5) THRESH = 10 if align_sdss_ds9: if "Vizier" not in REFERENCE_CATALOG: THRESH = 20 se.options["DETECT_THRESH"] = "%d" % (THRESH) se.options["ANALYSIS_THRESH"] = "%d" % (THRESH) se.options["MAG_ZEROPOINT"] = str(threedhst.options["MAG_ZEROPOINT"]) #### Run SExtractor on direct and alignment images ## direct image se.options["CATALOG_NAME"] = "direct.cat" iraf.imcopy(ROOT_DIRECT + "_drz.fits[1]", "SCI.fits") iraf.imcopy(ROOT_DIRECT + "_drz.fits[2]", "WHT.fits") status = se.sextractImage("SCI.fits") ## Read the catalog directCat = threedhst.sex.mySexCat("direct.cat") if align_sdss_ds9: ### Use ds9 SDSS catalog to refine alignment import threedhst.dq import pywcs import threedhst.catIO as catIO wcs = pywcs.WCS(pyfits.getheader("SCI.fits", 0)) # wcs = pywcs.WCS(pyfits.getheader('Q0821+3107-F140W_drz.fits', 1)) if "Vizier" in REFERENCE_CATALOG: #### Use (unstable) astroquery Vizier search #### CFHTLS-Deep: 'Vizier.II/317' VIZIER_CAT = REFERENCE_CATALOG.split("Vizier.")[1] print "Align to Vizier catalog: http://vizier.u-strasbg.fr/viz-bin/VizieR?-source=%s" % (VIZIER_CAT) import astroquery if astroquery.__version__ < "0.0.dev1078": from astroquery import vizier query = {} query["-source"] = VIZIER_CAT # query["-out"] = ["_r", "CFHTLS", "rmag"] query["-out"] = ["_RAJ2000", "_DEJ2000"] ### Just RA/Dec. #### Center position and query radius r0, d0 = wcs.wcs_pix2sky([[wcs.naxis1 / 2.0, wcs.naxis2 / 2.0]], 1)[0] rll, dll = wcs.wcs_pix2sky([[0, 0]], 1)[0] corner_radius = ( np.sqrt((r0 - rll) ** 2 * np.cos(d0 / 360.0 * 2 * np.pi) ** 2 + (d0 - dll) ** 2) * 60.0 * 1.5 ) h = query["-c"] = "%.6f %.6f" % (r0, d0) query["-c.rm"] = "%.3f" % (corner_radius) ### xxx check image size #### Run the query vt = vizier.vizquery(query) else: #### Newer astroquery from astroquery.vizier import Vizier import astropy.coordinates as coord import astropy.units as u Vizier.ROW_LIMIT = -1 r0, d0 = wcs.wcs_pix2sky([[wcs.naxis1 / 2.0, wcs.naxis2 / 2.0]], 1)[0] rll, dll = wcs.wcs_pix2sky([[0, 0]], 1)[0] corner_radius = ( np.sqrt((r0 - rll) ** 2 * np.cos(d0 / 360.0 * 2 * np.pi) ** 2 + (d0 - dll) ** 2) * 60.0 * 1.5 ) # c = coord.ICRSCoordinates(ra=r0, dec=d0, unit=(u.deg, u.deg)) #### something with astropy.coordinates # c.icrs.ra.degree = c.icrs.ra.degrees # c.icrs.dec.degree = c.icrs.dec.degrees # vt = Vizier.query_region(c, width=u.Quantity(corner_radius, u.arcminute), catalog=[VIZIER_CAT])[0] #### Make a region file ra_list, dec_list = vt["RAJ2000"], vt["DEJ2000"] print "Vizier, found %d objects." % (len(ra_list)) fp = open("%s.vizier.reg" % (ROOT_DIRECT), "w") fp.write("# %s, r=%.1f'\nfk5\n" % (VIZIER_CAT, corner_radius)) for ra, dec in zip(ra_list, dec_list): fp.write('circle(%.6f, %.6f, 0.5")\n' % (ra, dec)) # fp.close() else: #### Use DS9 catalog ds9 = threedhst.dq.myDS9() ds9.set("file SCI.fits") # ds9.set('file Q0821+3107-F140W_drz.fits') ds9.set("catalog %s" % (REFERENCE_CATALOG)) ### Can't find XPA access point for "copy to regions" ds9.set("catalog export tsv ds9_align.tsv") lines = open("ds9_align.tsv").readlines() ra_list, dec_list = [], [] for line in lines[1:]: spl = line.split() ra, dec = float(spl[0]), float(spl[1]) ra_list.append(ra) dec_list.append(dec) # del (ds9) x_image, y_image = [], [] for ra, dec in zip(ra_list, dec_list): x, y = wcs.wcs_sky2pix([[ra, dec]], 1)[0] x_image.append(x) y_image.append(y) alignCat = catIO.EmptyCat() alignCat["X_IMAGE"] = np.array(x_image) alignCat["Y_IMAGE"] = np.array(y_image) else: ## alignment image se.options["CATALOG_NAME"] = "align.cat" status = se.sextractImage(ROOT_DIRECT + "_align.fits") alignCat = threedhst.sex.mySexCat("align.cat") xshift = 0 yshift = 0 rot = 0 scale = 1.0 xrms = 2 yrms = 2 NITER = 5 IT = 0 while IT < NITER: IT = IT + 1 #### Get x,y coordinates of detected objects ## direct image fp = open("direct.xy", "w") for i in range(len(directCat.X_IMAGE)): fp.write("%s %s\n" % (directCat.X_IMAGE[i], directCat.Y_IMAGE[i])) fp.close() ## alignment image fp = open("align.xy", "w") for i in range(len(alignCat.X_IMAGE)): fp.write("%s %s\n" % (np.float(alignCat.X_IMAGE[i]) + xshift, np.float(alignCat.Y_IMAGE[i]) + yshift)) fp.close() iraf.flpr() iraf.flpr() iraf.flpr() #### iraf.xyxymatch to find matches between the two catalogs pow = toler * 1.0 try: os.remove("align.match") except: pass status1 = iraf.xyxymatch( input="direct.xy", reference="align.xy", output="align.match", tolerance=2 ** pow, separation=0, verbose=yes, Stdout=1, ) nmatch = 0 while status1[-1].startswith("0") | (nmatch < 10): pow += 1 os.remove("align.match") status1 = iraf.xyxymatch( input="direct.xy", reference="align.xy", output="align.match", tolerance=2 ** pow, separation=0, verbose=yes, Stdout=1, ) # nmatch = 0 for line in open("align.match").xreadlines(): nmatch += 1 if verbose: for line in status1: print line #### Compute shifts with iraf.geomap iraf.flpr() iraf.flpr() iraf.flpr() try: os.remove("align.map") except: pass status2 = iraf.geomap( input="align.match", database="align.map", fitgeometry=fitgeometry, interactive=no, xmin=INDEF, xmax=INDEF, ymin=INDEF, ymax=INDEF, maxiter=10, reject=2.0, Stdout=1, ) if verbose: for line in status2: print line # fp = open(root+'.iraf.log','a') # fp.writelines(status1) # fp.writelines(status2) # fp.close() #### Parse geomap.output fp = open("align.map", "r") for line in fp.readlines(): spl = line.split() if spl[0].startswith("xshift"): xshift += float(spl[1]) if spl[0].startswith("yshift"): yshift += float(spl[1]) if spl[0].startswith("xrotation"): rot = float(spl[1]) if spl[0].startswith("xmag"): scale = float(spl[1]) if spl[0].startswith("xrms"): xrms = float(spl[1]) if spl[0].startswith("yrms"): yrms = float(spl[1]) fp.close() # os.system('wc align.match') print "Shift iteration #%d, xshift=%f, yshift=%f, rot=%f, scl=%f (rms: %5.2f,%5.2f)" % ( IT, xshift, yshift, rot, scale, xrms, yrms, ) im = pyfits.open("SCI.fits") shutil.copy("align.map", ROOT_DIRECT + "_align.map") shutil.copy("align.match", ROOT_DIRECT + "_align.match") #### Cleanup if clean: rmfiles = [ "SCI.fits", "WHT.fits", "align.cat", "align.map", "align.match", "align.reg", "align.xy", "direct.cat", "direct.reg", "direct.xy", "drz_sci.fits", "drz_wht.fits", "bg.fits", ] for file in rmfiles: try: os.remove(file) except: pass return xshift, yshift, rot, scale, xrms, yrms
def plot_shifts( ROOT_DIRECT, ALIGN_IMAGE, clean=True, verbose=True, ALIGN_EXTENSION=0, toler=3, skip_swarp=False, threshold=7, force=False, drz=True, WEIGHT_IMAGE=None, ): """ Run SExtractor on two images and match the objects to plot the shifts between them. ALIGN_IMAGE is a string that may contain wildcards, and the function will use `align_img_list` to find ALIGN_IMAGEs """ import glob from pyraf import iraf from iraf import stsdas, dither no = iraf.no yes = iraf.yes INDEF = iraf.INDEF if os.path.exists(ROOT_DIRECT + "_align.fits") & (not force): if verbose: print "Image %s_align.fits exists. Skipping SWarp." % (ROOT_DIRECT) skip_swarp = True if not skip_swarp: if drz: align_img_list = find_align_images_that_overlap( ROOT_DIRECT + "_drz.fits", ALIGN_IMAGE, ALIGN_EXTENSION=ALIGN_EXTENSION ) else: align_img_list = glob.glob(ALIGN_IMAGE) if not align_img_list: print "threedhst.shifts.align_to_reference: no alignment images overlap." return 0, 0 # try: os.remove(ROOT_DIRECT + "_align.fits") except: pass if drz: matchImagePixels( input=align_img_list, matchImage=ROOT_DIRECT + "_drz.fits", output=ROOT_DIRECT + "_align.fits", match_extension=1, input_extension=ALIGN_EXTENSION, ) ALIGN_FITS = ROOT_DIRECT + "_align.fits" else: ALIGN_FITS = os.path.basename(ROOT_DIRECT.split(".fits")[0]) + "_align.fits" matchImagePixels( input=align_img_list, matchImage=ROOT_DIRECT, output=ALIGN_FITS, match_extension=0, input_extension=ALIGN_EXTENSION, ) se = threedhst.sex.SExtractor() se.aXeParams() se.copyConvFile() se.overwrite = True se.options["CHECKIMAGE_TYPE"] = "NONE" se.options["WEIGHT_TYPE"] = "MAP_WEIGHT" if drz: se.options["WEIGHT_IMAGE"] = ROOT_DIRECT + "_drz.fits[1]" else: if WEIGHT_IMAGE: se.options["WEIGHT_IMAGE"] = WEIGHT_IMAGE else: se.options["WEIGHT_TYPE"] = "NONE" se.options["WEIGHT_IMAGE"] = "NONE" se.options["FILTER"] = "Y" ## Detect thresholds (default = 1.5) se.options["DETECT_THRESH"] = "%f" % (threshold) se.options["ANALYSIS_THRESH"] = "%f" % (threshold) se.options["MAG_ZEROPOINT"] = str(threedhst.options["MAG_ZEROPOINT"]) #### Run SExtractor on direct and alignment images ## direct image se.options["CATALOG_NAME"] = "direct.cat" if drz: status = se.sextractImage(ROOT_DIRECT + "_drz.fits[0]") INPUT_IMAGE = ROOT_DIRECT + "_drz.fits" else: status = se.sextractImage(ROOT_DIRECT) INPUT_IMAGE = ROOT_DIRECT ## alignment image se.options["CATALOG_NAME"] = "align.cat" se.options["WEIGHT_TYPE"] = "NONE" status = se.sextractImage(ALIGN_FITS) ## Read the catalogs directCat = threedhst.sex.mySexCat("direct.cat") alignCat = threedhst.sex.mySexCat("align.cat") xshift = 0 yshift = 0 rot = 0 scale = 1.0 xrms = 2 yrms = 2 NITER = 5 IT = 0 while IT < NITER: IT = IT + 1 #### Get x,y coordinates of detected objects ## direct image fp = open("direct.xy", "w") for i in range(len(directCat.X_IMAGE)): fp.write("%s %s\n" % (directCat.X_IMAGE[i], directCat.Y_IMAGE[i])) fp.close() ## alignment image fp = open("align.xy", "w") for i in range(len(alignCat.X_IMAGE)): fp.write("%s %s\n" % (np.float(alignCat.X_IMAGE[i]) + xshift, np.float(alignCat.Y_IMAGE[i]) + yshift)) fp.close() iraf.flpr() iraf.flpr() iraf.flpr() #### iraf.xyxymatch to find matches between the two catalogs pow = toler * 1.0 try: os.remove("align.match") except: pass status1 = iraf.xyxymatch( input="direct.xy", reference="align.xy", output="align.match", tolerance=2 ** pow, separation=0, verbose=yes, Stdout=1, ) while status1[-1].startswith("0"): pow += 1 os.remove("align.match") status1 = iraf.xyxymatch( input="direct.xy", reference="align.xy", output="align.match", tolerance=2 ** pow, separation=0, verbose=yes, Stdout=1, ) #### Images are aligned, plot the offsets dx, dy, ax, ay, di, ai = np.loadtxt("align.match", unpack=True) ddx, ddy = dx - ax, dy - ay keep = (np.abs(ddx) < 15) & (np.abs(ddy) < 15) for i in range(5): sx, sy = threedhst.utils.biweight(ddx[keep], both=True), threedhst.utils.biweight(ddy[keep], both=True) keep = keep & (np.abs(ddx - sx[0]) < 5 * sx[1]) & (np.abs(ddy - sy[0]) < 5 * sy[1]) if USE_PLOT_GUI: fig = plt.figure(figsize=[8, 4], dpi=100) else: fig = Figure(figsize=[8, 4], dpi=100) fig.subplots_adjust(wspace=0.28, hspace=0.0, left=0.08, bottom=0.14, right=0.98, top=0.98) ax = fig.add_subplot(121) ax.plot(ddx, ddy, marker="o", linestyle="None", color="black", alpha=0.4, ms=2, zorder=-1) ax.errorbar(sx[0], sy[0], sx[1], sy[1], marker="o", ms=0.1, color="white", linewidth=3, zorder=100) ax.errorbar(sx[0], sy[0], sx[1], sy[1], marker="o", ms=0.1, color="red", linewidth=2, zorder=500) ax.grid(alpha=0.5) dwin = 5 * np.max([sx[1], sy[1]]) ax.set_xlim(sx[0] - dwin, sx[0] + dwin) ax.set_ylim(sy[0] - dwin, sy[0] + dwin) ax.set_xlabel(r"$\Delta x$ [pix]") ax.set_ylabel(r"$\Delta y$ [pix]") ax.text(0.5, 0.95, os.path.basename(INPUT_IMAGE), fontsize=9, horizontalalignment="center", transform=ax.transAxes) ax.text(0.5, 0.9, os.path.basename(ALIGN_IMAGE), fontsize=9, horizontalalignment="center", transform=ax.transAxes) ax.text( 0.5, 0.1, r"$\Delta x, \Delta y = %.2f \pm %.2f, %.2f \pm %.2f)$" % (sx[0], sx[1], sy[0], sy[1]), fontsize=11, horizontalalignment="center", transform=ax.transAxes, ) ax = fig.add_subplot(122) ax.plot(dx[keep], dy[keep], marker="o", ms=1, linestyle="None", color="black", alpha=0.1) ax.quiver( dx[keep], dy[keep], ddx[keep], ddy[keep], alpha=0.5, angles="xy", headlength=1, headwidth=1, scale=30.0 / (dx.max() - dx.min()), units="x", minlength=1, ) aa = np.array([1, 1]) ax.quiver( dx[keep].mean() * aa, dy[keep].max() * 0.95 * aa, 1 * aa, 0 * aa, alpha=0.9, angles="xy", headlength=0, headwidth=1, scale=30.0 / (dx.max() - dx.min()), units="x", color="red", ) ax.set_xlabel(r"$x$ [pix]") ax.set_ylabel(r"$y$ [pix]") if USE_PLOT_GUI: fig.savefig(os.path.basename(ROOT_DIRECT.split(".fits")[0]) + "_align.pdf", dpi=100, transparent=False) else: canvas = FigureCanvasAgg(fig) canvas.print_figure(os.path.basename(ROOT_DIRECT.split(".fits")[0]) + "_align.pdf", dpi=100, transparent=False) if clean: rmfiles = [ "SCI.fits", "WHT.fits", "align.cat", "align.map", "align.match", "align.reg", "align.xy", "direct.cat", "direct.reg", "direct.xy", "drz_sci.fits", "drz_wht.fits", "bg.fits", ] for file in rmfiles: try: os.remove(file) except: pass
def alignimages(im1, im2): runsex = 1 #run sextractor to get object catalogs auto = 0. t = im1.split('.') prefixim1 = t[0] t = prefixim1.split('pre') fieldid = t[0] #saves cl1018 or whatever as fieldid t = im2.split('.') prefixim2 = t[0] filexy1 = prefixim1 + '-xy.cat' filexy2 = prefixim2 + '-xy.cat' print "aligning images for ", fieldid if runsex > 0: runsextractor(im1, auto) infile = open('test.cat', 'r') #keep only sources w/in useable field outfile = open(filexy1, 'w') for line in infile: #keep only targets w/in 500 pixels of center if line.find('#') > -1: continue t = line.split() out = '%8.4f %8.4f \n' % (float(t[10]), float(t[11])) outfile.write(out) infile.close() outfile.close() print "running sextractor on ", im2 runsextractor(im2, auto) infile = open('test.cat', 'r') #keep only sources w/in useable field outfile = open(filexy2, 'w') for line in infile: #keep only targets w/in 500 pixels of center if line.find('#') > -1: continue t = line.split() out = '%8.4f %8.4f \n' % (float(t[10]), float(t[11])) outfile.write(out) infile.close() outfile.close() match = fieldid + '-match' dbase = fieldid + '-match-geomap' iraf.display(im1, 1, fill='yes') iraf.display(im2, 2, fill='yes') reffile = fieldid + 'refpoints' #make these individually. First line w/3points in gmos image (x1 y1 x2 y2 x3 y3). 2nd line w/same points in ediscs I-band flag = raw_input("Should we create a refpoints file (0=no, 1=yes)?\n") flag = int(flag) if flag > 0.1: s = 'cp cl1018refpoints ' + reffile os.system(s) print "open ", reffile, " in emacs, delete 2 lines" print "Enter x1 y1 x2 y2 x3 y3 for ref image (gmos)" print "Enter x1 y1 x2 y2 x3 y3 for 2nd image (vlt)" iraf.imexam() iraf.xyxymatch(filexy2, filexy1, match, tolerance=15, refpoints=reffile, matching='tolerance', interactive='no') iraf.imgets(image=im1, param='i_naxis1') t = iraf.imgets.value im1xmax = (float(t)) iraf.imgets(image=im1, param='i_naxis2') t = iraf.imgets.value im1ymax = (float(t)) iraf.geomap(input=match, database=dbase, function='polynomial', xmin=1, xmax=im1xmax, ymin=1, ymax=im1ymax, xxorder=4, xyorder=4, yyorder=4, yxorder=4, transform='gmos', interactive='yes') transformim = 1 if transformim > 0: outim2 = 'g' + im2 iraf.geotran(im2, output=outim2, database=dbase, transform='gmos') iraf.display(im2, 1, fill='yes') iraf.display(outim2, 2, fill='yes') iraf.display(im1, 3, fill='yes')