def make_completeness_table(loga_mag_file, matchup_files, filt_names=None): """ Read in the output of KS2 (post processed with xym2mat and xym2bar) and match it up with the input planted stars. Input --------- loga_mag_file : string The name of the LOGA_MAGS.INPUT.fits file (produced by remake_loga_input() matchup_files : list A list of matchup files that corresponds to the filters in the LOGA file. The matchup files are assumed to be in the same order as the LOGA magnitude columns. """ # Read files loga = atpy.Table(loga_mag_file) mat = [starlists.read_matchup(mat_file) for mat_file in matchup_files] # Figure out the number of filters... make sure the match in input/output num_filt = len(matchup_files) num_filt2 = len(loga.columns) - 3 if num_filt != num_filt2: print('Filter mismatch: {0} in input, {1} in output'.format()) return # First modify the column names in loga to reflect that these are # input values loga.rename_column('x', 'x_in') loga.rename_column('y', 'y_in') for ff in range(num_filt): print('Processing Filter #{0}'.format(ff+1)) if filt_names != None: filt = '_{0}'.format(filt_names[ff]) else: filt = '_{0}'.format(ff+1) # Rename the input magnitude columns old_col_name = 'm{0}'.format(ff+1) new_col_name = 'm_in' + filt loga.rename_column(old_col_name, new_col_name) # Add the new columns to the table for all of the output data. loga.add_column('x_out' + filt, mat[ff].x) loga.add_column('y_out' + filt, mat[ff].y) loga.add_column('m_out' + filt, mat[ff].m) loga.add_column('xe_out' + filt, mat[ff].xe) loga.add_column('ye_out' + filt, mat[ff].ye) loga.add_column('me_out' + filt, mat[ff].me) loga.table_name = '' outfile_name = os.path.dirname(loga_mag_file) + 'completeness_matched.fits' loga.write(outfile_name) return loga
def make_completeness_table(loga_mag_file, matchup_files, filt_names=None): """ Read in the output of KS2 (post processed with xym2mat and xym2bar) and match it up with the input planted stars. Input --------- loga_mag_file : string The name of the LOGA_MAGS.INPUT.fits file (produced by remake_loga_input() matchup_files : list A list of matchup files that corresponds to the filters in the LOGA file. The matchup files are assumed to be in the same order as the LOGA magnitude columns. """ # Read files loga = atpy.Table(loga_mag_file) mat = [starlists.read_matchup(mat_file) for mat_file in matchup_files] # Figure out the number of filters... make sure the match in input/output num_filt = len(matchup_files) num_filt2 = len(loga.columns) - 3 if num_filt != num_filt2: print('Filter mismatch: {0} in input, {1} in output'.format()) return # First modify the column names in loga to reflect that these are # input values loga.rename_column('x', 'x_in') loga.rename_column('y', 'y_in') for ff in range(num_filt): print('Processing Filter #{0}'.format(ff + 1)) if filt_names != None: filt = '_{0}'.format(filt_names[ff]) else: filt = '_{0}'.format(ff + 1) # Rename the input magnitude columns old_col_name = 'm{0}'.format(ff + 1) new_col_name = 'm_in' + filt loga.rename_column(old_col_name, new_col_name) # Add the new columns to the table for all of the output data. loga.add_column('x_out' + filt, mat[ff].x) loga.add_column('y_out' + filt, mat[ff].y) loga.add_column('m_out' + filt, mat[ff].m) loga.add_column('xe_out' + filt, mat[ff].xe) loga.add_column('ye_out' + filt, mat[ff].ye) loga.add_column('me_out' + filt, mat[ff].me) loga.table_name = '' outfile_name = os.path.dirname(loga_mag_file) + 'completeness_matched.fits' loga.write(outfile_name) return loga
def combine_in_out_ks2(ks2_input_file, matchup_files, suffixes=None): """ Read in a LOGA.INPUT file and the corresponding MATCHUP.XYMEEE files and cross-match them. They should already be the same length and the in same order. Inputs ------ ks2_input_file -- the LOGA.INPUT file matchup_files -- a list of MATCHUP.XYMEEE files Optional Inputs --------------- suffixes -- a list (same length as matchup_files) """ final = atpy.Table() final.table_name = '' # Read in the input ks2 file inp = atpy.Table('LOGA.INPUT', type='ascii') final.add_column('name', inp.col17) final.add_column('x_in', inp.col1) final.add_column('y_in', inp.col2) for ff in range(len(matchup_files)): if suffixes == None: suf = '_{0}'.format(ff + 1) else: suf = '_' + suffixes[ff] f_in = 'col{0}'.format(18 + 4 * ff) m_in = -2.5 * np.log10(inp[f_in]) final.add_column('m_in' + suf, m_in) match = starlists.read_matchup(matchup_files[ff]) if len(match) != len(final): print 'Problem reading ' + matchup_files[ ff] + ': incorrect file length' final.add_column('x_out' + suf, match.x) final.add_column('y_out' + suf, match.y) final.add_column('m_out' + suf, match.m) final.add_column('xe_out' + suf, match.xe) final.add_column('ye_out' + suf, match.ye) final.add_column('me_out' + suf, match.me) final.write('ks2_in_out_catalog.fits', overwrite=True)
def combine_in_out_ks2(ks2_input_file, matchup_files, suffixes=None): """ Read in a LOGA.INPUT file and the corresponding MATCHUP.XYMEEE files and cross-match them. They should already be the same length and the in same order. Inputs ------ ks2_input_file -- the LOGA.INPUT file matchup_files -- a list of MATCHUP.XYMEEE files Optional Inputs --------------- suffixes -- a list (same length as matchup_files) """ final = atpy.Table() final.table_name = "" # Read in the input ks2 file inp = atpy.Table("LOGA.INPUT", type="ascii") final.add_column("name", inp.col17) final.add_column("x_in", inp.col1) final.add_column("y_in", inp.col2) for ff in range(len(matchup_files)): if suffixes == None: suf = "_{0}".format(ff + 1) else: suf = "_" + suffixes[ff] f_in = "col{0}".format(18 + 4 * ff) m_in = -2.5 * np.log10(inp[f_in]) final.add_column("m_in" + suf, m_in) match = starlists.read_matchup(matchup_files[ff]) if len(match) != len(final): print "Problem reading " + matchup_files[ff] + ": incorrect file length" final.add_column("x_out" + suf, match.x) final.add_column("y_out" + suf, match.y) final.add_column("m_out" + suf, match.m) final.add_column("xe_out" + suf, match.xe) final.add_column("ye_out" + suf, match.ye) final.add_column("me_out" + suf, match.me) final.write("ks2_in_out_catalog.fits", overwrite=True)
def plot_vpd_across_field(nside=4, interact=False): """ Plot the VPD at different field positions so we can see if there are systematic discrepancies due to residual distortions. """ # Read in matched and aligned star lists from the *.ref5 analysis. # Recall these data sets are in the F814W reference frame with a 50 mas plate scale. t2005 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F814W.ref5') t2010 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F125W.ref5') scale = 50.0 # mas per pixel # Trim down to only those stars that are detected in both epochs. # Also make cuts on astrometric/photometric errors, etc. # We only want the well measured stars in this analysis. perrLim814 = 1.0 / scale perrLim125 = 4.0 / scale merrLim814 = 0.05 merrLim125 = 0.1 cond = ((t2005.m != 0) & (t2010.m != 0) & (t2005.xe < perrLim814) & (t2005.ye < perrLim814) & (t2010.xe < perrLim125) & (t2010.ye < perrLim125) & (t2005.me < merrLim814) & (t2010.me < merrLim125)) t2005 = t2005.where(cond) t2010 = t2010.where(cond) # Calculate proper motions dt = years['2010_F125W'] - years['2005_F814W'] dx = t2010.x - t2005.x dy = t2010.y - t2005.y pmx = dx * scale / dt pmy = dy * scale / dt pm = np.hypot(pmx, pmy) t2005.add_column('pmx', pmx) t2005.add_column('pmy', pmy) t2005.add_column('pm', pm) # Divide up the region into N x N boxes and plot up the VPD for each. xlo = math.floor(t2005.x.min()) xhi = math.ceil(t2005.x.max()) ylo = math.floor(t2005.y.min()) yhi = math.ceil(t2005.y.max()) xboxsize = round((xhi - xlo) / nside) yboxsize = round((yhi - ylo) / nside) # Setup colors jet = py.get_cmap('jet') cNorm = colors.Normalize(vmin=0, vmax=nside**2) colorMap = py.cm.ScalarMappable(norm=cNorm, cmap=jet) # Save the average proper motions in each box pmx = np.zeros((nside, nside), dtype=float) pmy = np.zeros((nside, nside), dtype=float) pmxe = np.zeros((nside, nside), dtype=float) pmye = np.zeros((nside, nside), dtype=float) xcen = np.zeros((nside, nside), dtype=float) ycen = np.zeros((nside, nside), dtype=float) pmCut = 1.0 # Calculate the global mean proper motion # Start by trimming down to a 1 mas/yr radius idx2 = np.where(pm < pmCut)[0] pmx_all = np.median(t2005.pmx[idx2]) pmy_all = np.median(t2005.pmy[idx2]) out = 'All X:{0:5.0f}-{1:5.0f} Y:{2:5.0f}-{3:5.0f} ' out += 'PMX:{4:5.2f} +/- {5:5.2f} PMY:{6:5.2f} +/- {7:5.2f} ' out += 'N:{8:5d}' print((out.format(xlo, xhi, ylo, yhi, pmx_all, 0.0, pmy_all, 0.0, len(idx2)))) # Make a global proper motion diagram of star with a proper motion within # 1 mas/yr. This is mainly to see systematic flows due to residual distortion. pmTot = np.hypot(t2005.pmx, t2005.pmy) clust = np.where(pmTot < pmCut)[0] py.clf() q = py.quiver(t2005.x[clust], t2005.y[clust], t2005.pmx[clust], t2005.pmy[clust], scale=18) py.quiverkey(q, 0.5, 0.98, 1, '1 mas/yr', color='red', labelcolor='red') py.xlabel('X Position (pixels)') py.ylabel('Y Position (pixels)') py.xlim(xlo, xhi) py.ylim(ylo, yhi) out = '{0}/plots/vec_proper_motion_all.png' py.savefig(out.format(workDir)) py.clf() for xx in range(nside): for yy in range(nside): xlo_box = xlo + xx * xboxsize ylo_box = ylo + yy * yboxsize xhi_box = xlo + (1 + xx) * xboxsize yhi_box = ylo + (1 + yy) * yboxsize idx = np.where((t2005.x > xlo_box) & (t2005.x <= xhi_box) & (t2005.y > ylo_box) & (t2005.y <= yhi_box))[0] if interact: color = colorMap.to_rgba(yy + xx * nside) lim = 5 py.plot(t2005.pmx[idx], t2005.pmy[idx], 'k.', ms=2, color=color) py.axis([-lim, lim, -lim, lim]) py.xlabel('X Proper Motion (mas/yr)') py.ylabel('Y Proper Motion (mas/yr)') # Lets get the mean and std-dev (iterative) for the box. # Start by trimming down to a 1 mas/yr circle. idx2 = np.where(t2005.pm[idx] < pmCut)[0] xmean = np.median(t2005.pmx[idx][idx2]) ymean = np.median(t2005.pmy[idx][idx2]) xstd = t2005.pmx[idx][idx2].std() ystd = t2005.pmy[idx][idx2].std() xmean_err = xstd / np.sqrt(len(idx2)) ymean_err = ystd / np.sqrt(len(idx2)) xcen[xx, yy] = xlo_box + (xboxsize / 2.0) ycen[xx, yy] = ylo_box + (yboxsize / 2.0) pmx[xx, yy] = xmean - pmx_all pmy[xx, yy] = ymean - pmx_all pmxe[xx, yy] = xmean_err pmye[xx, yy] = ymean_err out = 'Box X:{0:5.0f}-{1:5.0f} Y:{2:5.0f}-{3:5.0f} ' out += 'PMX:{4:5.2f} +/- {5:5.2f} PMY:{6:5.2f} +/- {7:5.2f} ' out += 'N:{8:5d} ' if interact: out += 'Continue?' input( out.format(xlo_box, xhi_box, ylo_box, yhi_box, xmean, xmean_err, ymean, ymean_err, len(idx2))) else: print((out.format(xlo_box, xhi_box, ylo_box, yhi_box, xmean, xmean_err, ymean, ymean_err, len(idx2)))) if interact: out = '{0}/plots/vpd_grid_nside{1}.png' py.savefig(out.format(workDir, nside)) py.clf() q = py.quiver(xcen, ycen, pmx, pmy) py.quiverkey(q, 0.5, 0.98, 0.1, '0.1 mas/yr', color='red', labelcolor='red') py.xlabel('X Position (pixels)') py.ylabel('Y Position (pixels)') py.xlim(xlo, xhi) py.ylim(ylo, yhi) for xx in range(nside + 1): py.axvline(xlo + xx * xboxsize, linestyle='--', color='grey') for yy in range(nside + 1): py.axhline(ylo + yy * yboxsize, linestyle='--', color='grey') out = '{0}/plots/vec_proper_motion_grid_nside{1}.png' py.savefig(out.format(workDir, nside)) py.clf() q = py.quiver(xcen, ycen, pmx / pmxe, pmy / pmye) py.quiverkey(q, 0.5, 0.98, 3, '3 sigma', color='red', labelcolor='red') py.xlabel('X Position (pixels)') py.ylabel('Y Position (pixels)') py.xlim(xlo, xhi) py.ylim(ylo, yhi) for xx in range(nside + 1): py.axvline(xlo + xx * xboxsize, linestyle='--', color='grey') for yy in range(nside + 1): py.axhline(ylo + yy * yboxsize, linestyle='--', color='grey') out = '{0}/plots/vec_proper_motion_grid_sig_nside{1}.png' py.savefig(out.format(workDir, nside))
def make_master_lists(): """ Trim the ref5 master lists for each filter down to just stars with proper motions within 1 mas/yr of the cluster motion. """ # Read in matched and aligned star lists from the *.ref5 analysis. # Recall these data sets are in the F814W reference frame with a 50 mas plate scale. t2005_814 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F814W.ref5') t2010_125 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F125W.ref5') t2010_139 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F139M.ref5') t2010_160 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F160W.ref5') scale = 50.0 # mas per pixel # Trim down to only those stars that are detected in both epochs. # Also make cuts on astrometric/photometric errors, etc. # We only want the well measured stars in this analysis. perrLim814 = 1.0 / scale perrLim125 = 4.0 / scale merrLim814 = 0.05 merrLim125 = 0.1 cond = ((t2005_814.m != 0) & (t2010_125.m != 0) & (t2010_139.m != 0) & (t2010_160.m != 0) & (t2005_814.xe < perrLim814) & (t2005_814.ye < perrLim814) & (t2010_125.xe < perrLim125) & (t2010_125.ye < perrLim125) & (t2010_139.xe < perrLim125) & (t2010_139.ye < perrLim125) & (t2010_160.xe < perrLim125) & (t2010_160.ye < perrLim125) & (t2005_814.me < merrLim814) & (t2010_125.me < merrLim125) & (t2010_139.me < merrLim125) & (t2010_160.me < merrLim125)) t2005_814 = t2005_814.where(cond) t2010_125 = t2010_125.where(cond) t2010_139 = t2010_139.where(cond) t2010_160 = t2010_160.where(cond) # Calculate proper motions dt = years['2010_F125W'] - years['2005_F814W'] dx = t2010_125.x - t2005_814.x dy = t2010_125.y - t2005_814.y pmx = dx * scale / dt pmy = dy * scale / dt pm = np.hypot(pmx, pmy) t2005_814.add_column('pmx', pmx) t2005_814.add_column('pmy', pmy) t2005_814.add_column('pm', pm) # Trim down to a 1 mas/yr radius pmCut = 1.0 idx2 = np.where(pm < pmCut)[0] t2005_814 = t2005_814.where(idx2) t2010_125 = t2010_125.where(idx2) t2010_139 = t2010_139.where(idx2) t2010_160 = t2010_160.where(idx2) _o814 = open(workDir + '02.PMA/MASTER.F814W.ref5', 'w') _o125 = open(workDir + '02.PMA/MASTER.F125W.ref5', 'w') _o139 = open(workDir + '02.PMA/MASTER.F139M.ref5', 'w') _o160 = open(workDir + '02.PMA/MASTER.F160W.ref5', 'w') ofmt = '{0:10.4f} {1:10.4f} {2:8.4f} {3:10.4f} {4:10.4f} {5:8.4f} {6}\n' for ii in range(len(t2005_814)): _o814.write( ofmt.format(t2005_814.x[ii], t2005_814.y[ii], t2005_814.m[ii], t2005_814.xe[ii], t2005_814.ye[ii], t2005_814.me[ii], t2005_814.name[ii])) _o125.write( ofmt.format(t2010_125.x[ii], t2010_125.y[ii], t2010_125.m[ii], t2010_125.xe[ii], t2010_125.ye[ii], t2010_125.me[ii], t2010_125.name[ii])) _o139.write( ofmt.format(t2010_139.x[ii], t2010_139.y[ii], t2010_139.m[ii], t2010_139.xe[ii], t2010_139.ye[ii], t2010_139.me[ii], t2010_139.name[ii])) _o160.write( ofmt.format(t2010_160.x[ii], t2010_160.y[ii], t2010_160.m[ii], t2010_160.xe[ii], t2010_160.ye[ii], t2010_160.me[ii], t2010_160.name[ii])) _o814.close() _o125.close() _o139.close() _o160.close()
def make_residuals_table_year_pos(year, filt, pos): year = str(year) dir_xym = year + '_' + filt + '_' + pos + '/01.XYM/' # Read in the matchup file with the final positions and errors. stars = starlists.read_matchup(dir_xym + 'MATCHUP.XYMEEE.ref1') # For each image, read in the raw pixel coordinates, the transformed # coordinates, and the residual offsets. N_images = len(imgs[year][filt][pos]) N_stars = len(stars) xraw = np.zeros([N_images, N_stars]) yraw = np.zeros([N_images, N_stars]) mraw = np.zeros([N_images, N_stars]) xt = np.zeros([N_images, N_stars]) yt = np.zeros([N_images, N_stars]) mt = np.zeros([N_images, N_stars]) dx = np.zeros([N_images, N_stars]) dy = np.zeros([N_images, N_stars]) for nn in range(N_images): print 'nn = ', nn dat = ascii.read('{0:s}LNK.{1:03d}'.format(dir_xym, nn+1)) xt[nn, :] = dat['col1'] yt[nn, :] = dat['col2'] mt[nn, :] = dat['col3'] xraw[nn, :] = dat['col4'] yraw[nn, :] = dat['col5'] mraw[nn, :] = dat['col6'] dx[nn, :] = dat['col7'] dy[nn, :] = dat['col8'] idx = np.where((stars['m']>-11) & (stars['m']<-6) & (stars['xe']<0.05) & (stars['ye']<0.05) & (stars['me']<0.1))[0] stars = stars[idx] xraw = xraw[:, idx] yraw = yraw[:, idx] mraw = mraw[:, idx] xt = xt[:, idx] yt = yt[:, idx] mt = mt[:, idx] dx = dx[:, idx] dy = dy[:, idx] xmean = xt.mean(axis=0) ymean = yt.mean(axis=0) mmean = mt.mean(axis=0) xstd = xt.std(axis=0) ystd = yt.std(axis=0) mstd = mt.std(axis=0) _out = open(dir_xym + 'resid_all_images.pickle', 'w') pickle.dump(stars, _out) pickle.dump(xmean, _out) pickle.dump(ymean, _out) pickle.dump(mmean, _out) pickle.dump(xstd, _out) pickle.dump(ystd, _out) pickle.dump(mstd, _out) pickle.dump(xraw, _out) pickle.dump(yraw, _out) pickle.dump(mraw, _out) pickle.dump(xt, _out) pickle.dump(yt, _out) pickle.dump(mt, _out) pickle.dump(dx, _out) pickle.dump(dy, _out) _out.close()
def make_residuals_table_year_2pos(year, filt, pos1, pos2): year = str(year) dir_xym = year + '_' + filt + '/01.XYM/' # Read in the matchup file with the final positions and errors. stars = starlists.read_matchup(dir_xym + 'MATCHUP.XYMEEE.ref4') # For each image, read in the raw pixel coordinates, the transformed # coordinates, and the residual offsets. N_images = len(imgs[year][filt][pos1]) N_stars = len(stars) pos1_idx = get_file_indices(year, filt, pos1) pos2_idx = get_file_indices(year, filt, pos2) pos_idx = np.array([pos1_idx, pos2_idx]) xraw = np.zeros([2, N_images, N_stars]) yraw = np.zeros([2, N_images, N_stars]) mraw = np.zeros([2, N_images, N_stars]) xt = np.zeros([2, N_images, N_stars]) yt = np.zeros([2, N_images, N_stars]) mt = np.zeros([2, N_images, N_stars]) dx = np.zeros([2, N_images, N_stars]) dy = np.zeros([2, N_images, N_stars]) detected = np.zeros([2, N_images, N_stars], dtype=bool) # Loop through images at each position for nn in range(N_images): # Loop through 2 different positions. for ii in range(2): print 'nn = ', nn, 'ii = ', ii dat = ascii.read('{0:s}LNK.{1:03d}'.format(dir_xym, pos_idx[ii, nn])) xt[ii, nn, :] = dat['col1'].data yt[ii, nn, :] = dat['col2'].data mt[ii, nn, :] = dat['col3'].data xraw[ii, nn, :] = dat['col4'].data yraw[ii, nn, :] = dat['col5'].data mraw[ii, nn, :] = dat['col6'].data dx[ii, nn, :] = dat['col7'].data dy[ii, nn, :] = dat['col8'].data idx = np.where(dat['col3'].data != 0)[0] detected[ii, nn, idx] = True # Trim the data down to those stars detected in ALL # the images (the overlaps) at these two positions. det_Nimg = detected.sum(axis=1).sum(axis=0) idx = np.where(det_Nimg == (2*N_images))[0] print 'Trim 1', len(idx) xt = xt[:, :, idx] yt = yt[:, :, idx] mt = mt[:, :, idx] xraw = xraw[:, :, idx] yraw = yraw[:, :, idx] mraw = mraw[:, :, idx] dx = dx[:, :, idx] dy = dy[:, :, idx] detected = detected[:, :, idx] stars = stars[idx] # Also trim on some quality metrics. idx2 = np.where((stars['m']>-11) & (stars['m']<-6) & (stars['xe']<0.05) & (stars['ye']<0.05) & (stars['me']<0.1))[0] print 'Trim 1', len(idx2) stars = stars[idx2] xraw = xraw[:, :, idx2] yraw = yraw[:, :, idx2] mraw = mraw[:, :, idx2] xt = xt[:, :, idx2] yt = yt[:, :, idx2] mt = mt[:, :, idx2] dx = dx[:, :, idx2] dy = dy[:, :, idx2] xmean_p = xt.mean(axis=1) ymean_p = yt.mean(axis=1) mmean_p = mt.mean(axis=1) xstd_p = xt.std(axis=1) ystd_p = yt.std(axis=1) mstd_p = mt.std(axis=1) xmean = xmean_p.mean(axis=0) ymean = ymean_p.mean(axis=0) mmean = mmean_p.mean(axis=0) _out = open(dir_xym + 'resid_' + pos1 + '_' + pos2 + '.pickle', 'w') pickle.dump(stars, _out) pickle.dump(xmean, _out) pickle.dump(ymean, _out) pickle.dump(mmean, _out) pickle.dump(xmean_p, _out) pickle.dump(ymean_p, _out) pickle.dump(mmean_p, _out) pickle.dump(xstd_p, _out) pickle.dump(ystd_p, _out) pickle.dump(mstd_p, _out) pickle.dump(xraw, _out) pickle.dump(yraw, _out) pickle.dump(mraw, _out) pickle.dump(xt, _out) pickle.dump(yt, _out) pickle.dump(mt, _out) pickle.dump(dx, _out) pickle.dump(dy, _out) _out.close()
def plot_vpd_across_field(nside=4, interact=False): """ Plot the VPD at different field positions so we can see if there are systematic discrepancies due to residual distortions. """ # Read in matched and aligned star lists from the *.ref5 analysis. # Recall these data sets are in the F814W reference frame with a 50 mas plate scale. t2005 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F814W.ref5') t2010 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F125W.ref5') scale = 50.0 # mas per pixel # Trim down to only those stars that are detected in both epochs. # Also make cuts on astrometric/photometric errors, etc. # We only want the well measured stars in this analysis. perrLim814 = 1.0 / scale perrLim125 = 4.0 / scale merrLim814 = 0.05 merrLim125 = 0.1 cond = ((t2005.m != 0) & (t2010.m != 0) & (t2005.xe < perrLim814) & (t2005.ye < perrLim814) & (t2010.xe < perrLim125) & (t2010.ye < perrLim125) & (t2005.me < merrLim814) & (t2010.me < merrLim125)) t2005 = t2005.where(cond) t2010 = t2010.where(cond) # Calculate proper motions dt = years['2010_F125W'] - years['2005_F814W'] dx = t2010.x - t2005.x dy = t2010.y - t2005.y pmx = dx * scale / dt pmy = dy * scale / dt pm = np.hypot(pmx, pmy) t2005.add_column('pmx', pmx) t2005.add_column('pmy', pmy) t2005.add_column('pm', pm) # Divide up the region into N x N boxes and plot up the VPD for each. xlo = math.floor(t2005.x.min()) xhi = math.ceil(t2005.x.max()) ylo = math.floor(t2005.y.min()) yhi = math.ceil(t2005.y.max()) xboxsize = round((xhi - xlo) / nside) yboxsize = round((yhi - ylo) / nside) # Setup colors jet = py.get_cmap('jet') cNorm = colors.Normalize(vmin=0, vmax=nside**2) colorMap = py.cm.ScalarMappable(norm=cNorm, cmap=jet) # Save the average proper motions in each box pmx = np.zeros((nside, nside), dtype=float) pmy = np.zeros((nside, nside), dtype=float) pmxe = np.zeros((nside, nside), dtype=float) pmye = np.zeros((nside, nside), dtype=float) xcen = np.zeros((nside, nside), dtype=float) ycen = np.zeros((nside, nside), dtype=float) pmCut = 1.0 # Calculate the global mean proper motion # Start by trimming down to a 1 mas/yr radius idx2 = np.where(pm < pmCut)[0] pmx_all = np.median( t2005.pmx[idx2] ) pmy_all = np.median( t2005.pmy[idx2] ) out = 'All X:{0:5.0f}-{1:5.0f} Y:{2:5.0f}-{3:5.0f} ' out += 'PMX:{4:5.2f} +/- {5:5.2f} PMY:{6:5.2f} +/- {7:5.2f} ' out += 'N:{8:5d}' print((out.format(xlo, xhi, ylo, yhi, pmx_all, 0.0, pmy_all, 0.0, len(idx2)))) # Make a global proper motion diagram of star with a proper motion within # 1 mas/yr. This is mainly to see systematic flows due to residual distortion. pmTot = np.hypot(t2005.pmx, t2005.pmy) clust = np.where(pmTot < pmCut)[0] py.clf() q = py.quiver(t2005.x[clust], t2005.y[clust], t2005.pmx[clust], t2005.pmy[clust], scale=18) py.quiverkey(q, 0.5, 0.98, 1, '1 mas/yr', color='red', labelcolor='red') py.xlabel('X Position (pixels)') py.ylabel('Y Position (pixels)') py.xlim(xlo, xhi) py.ylim(ylo, yhi) out = '{0}/plots/vec_proper_motion_all.png' py.savefig(out.format(workDir)) py.clf() for xx in range(nside): for yy in range(nside): xlo_box = xlo + xx * xboxsize ylo_box = ylo + yy * yboxsize xhi_box = xlo + (1+xx) * xboxsize yhi_box = ylo + (1+yy) * yboxsize idx = np.where((t2005.x > xlo_box) & (t2005.x <= xhi_box) & (t2005.y > ylo_box) & (t2005.y <= yhi_box))[0] if interact: color = colorMap.to_rgba(yy + xx * nside) lim = 5 py.plot(t2005.pmx[idx], t2005.pmy[idx], 'k.', ms=2, color=color) py.axis([-lim, lim, -lim, lim]) py.xlabel('X Proper Motion (mas/yr)') py.ylabel('Y Proper Motion (mas/yr)') # Lets get the mean and std-dev (iterative) for the box. # Start by trimming down to a 1 mas/yr circle. idx2 = np.where(t2005.pm[idx] < pmCut)[0] xmean = np.median( t2005.pmx[idx][idx2] ) ymean = np.median( t2005.pmy[idx][idx2] ) xstd = t2005.pmx[idx][idx2].std() ystd = t2005.pmy[idx][idx2].std() xmean_err = xstd / np.sqrt(len(idx2)) ymean_err = ystd / np.sqrt(len(idx2)) xcen[xx, yy] = xlo_box + (xboxsize / 2.0) ycen[xx, yy] = ylo_box + (yboxsize / 2.0) pmx[xx, yy] = xmean - pmx_all pmy[xx, yy] = ymean - pmx_all pmxe[xx, yy] = xmean_err pmye[xx, yy] = ymean_err out = 'Box X:{0:5.0f}-{1:5.0f} Y:{2:5.0f}-{3:5.0f} ' out += 'PMX:{4:5.2f} +/- {5:5.2f} PMY:{6:5.2f} +/- {7:5.2f} ' out += 'N:{8:5d} ' if interact: out += 'Continue?' input(out.format(xlo_box, xhi_box, ylo_box, yhi_box, xmean, xmean_err, ymean, ymean_err, len(idx2))) else: print((out.format(xlo_box, xhi_box, ylo_box, yhi_box, xmean, xmean_err, ymean, ymean_err, len(idx2)))) if interact: out = '{0}/plots/vpd_grid_nside{1}.png' py.savefig(out.format(workDir, nside)) py.clf() q = py.quiver(xcen, ycen, pmx, pmy) py.quiverkey(q, 0.5, 0.98, 0.1, '0.1 mas/yr', color='red', labelcolor='red') py.xlabel('X Position (pixels)') py.ylabel('Y Position (pixels)') py.xlim(xlo, xhi) py.ylim(ylo, yhi) for xx in range(nside+1): py.axvline(xlo + xx * xboxsize, linestyle='--', color='grey') for yy in range(nside+1): py.axhline(ylo + yy * yboxsize, linestyle='--', color='grey') out = '{0}/plots/vec_proper_motion_grid_nside{1}.png' py.savefig(out.format(workDir, nside)) py.clf() q = py.quiver(xcen, ycen, pmx/pmxe, pmy/pmye) py.quiverkey(q, 0.5, 0.98, 3, '3 sigma', color='red', labelcolor='red') py.xlabel('X Position (pixels)') py.ylabel('Y Position (pixels)') py.xlim(xlo, xhi) py.ylim(ylo, yhi) for xx in range(nside+1): py.axvline(xlo + xx * xboxsize, linestyle='--', color='grey') for yy in range(nside+1): py.axhline(ylo + yy * yboxsize, linestyle='--', color='grey') out = '{0}/plots/vec_proper_motion_grid_sig_nside{1}.png' py.savefig(out.format(workDir, nside))
def make_master_lists(): """ Trim the ref5 master lists for each filter down to just stars with proper motions within 1 mas/yr of the cluster motion. """ # Read in matched and aligned star lists from the *.ref5 analysis. # Recall these data sets are in the F814W reference frame with a 50 mas plate scale. t2005_814 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F814W.ref5') t2010_125 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F125W.ref5') t2010_139 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F139M.ref5') t2010_160 = starlists.read_matchup(workDir + '02.PMA/MATCHUP.XYMEEE.F160W.ref5') scale = 50.0 # mas per pixel # Trim down to only those stars that are detected in both epochs. # Also make cuts on astrometric/photometric errors, etc. # We only want the well measured stars in this analysis. perrLim814 = 1.0 / scale perrLim125 = 4.0 / scale merrLim814 = 0.05 merrLim125 = 0.1 cond = ((t2005_814.m != 0) & (t2010_125.m != 0) & (t2010_139.m != 0) & (t2010_160.m != 0) & (t2005_814.xe < perrLim814) & (t2005_814.ye < perrLim814) & (t2010_125.xe < perrLim125) & (t2010_125.ye < perrLim125) & (t2010_139.xe < perrLim125) & (t2010_139.ye < perrLim125) & (t2010_160.xe < perrLim125) & (t2010_160.ye < perrLim125) & (t2005_814.me < merrLim814) & (t2010_125.me < merrLim125) & (t2010_139.me < merrLim125) & (t2010_160.me < merrLim125)) t2005_814 = t2005_814.where(cond) t2010_125 = t2010_125.where(cond) t2010_139 = t2010_139.where(cond) t2010_160 = t2010_160.where(cond) # Calculate proper motions dt = years['2010_F125W'] - years['2005_F814W'] dx = t2010_125.x - t2005_814.x dy = t2010_125.y - t2005_814.y pmx = dx * scale / dt pmy = dy * scale / dt pm = np.hypot(pmx, pmy) t2005_814.add_column('pmx', pmx) t2005_814.add_column('pmy', pmy) t2005_814.add_column('pm', pm) # Trim down to a 1 mas/yr radius pmCut = 1.0 idx2 = np.where(pm < pmCut)[0] t2005_814 = t2005_814.where(idx2) t2010_125 = t2010_125.where(idx2) t2010_139 = t2010_139.where(idx2) t2010_160 = t2010_160.where(idx2) _o814 = open(workDir + '02.PMA/MASTER.F814W.ref5', 'w') _o125 = open(workDir + '02.PMA/MASTER.F125W.ref5', 'w') _o139 = open(workDir + '02.PMA/MASTER.F139M.ref5', 'w') _o160 = open(workDir + '02.PMA/MASTER.F160W.ref5', 'w') ofmt = '{0:10.4f} {1:10.4f} {2:8.4f} {3:10.4f} {4:10.4f} {5:8.4f} {6}\n' for ii in range(len(t2005_814)): _o814.write(ofmt.format(t2005_814.x[ii], t2005_814.y[ii], t2005_814.m[ii], t2005_814.xe[ii], t2005_814.ye[ii], t2005_814.me[ii], t2005_814.name[ii])) _o125.write(ofmt.format(t2010_125.x[ii], t2010_125.y[ii], t2010_125.m[ii], t2010_125.xe[ii], t2010_125.ye[ii], t2010_125.me[ii], t2010_125.name[ii])) _o139.write(ofmt.format(t2010_139.x[ii], t2010_139.y[ii], t2010_139.m[ii], t2010_139.xe[ii], t2010_139.ye[ii], t2010_139.me[ii], t2010_139.name[ii])) _o160.write(ofmt.format(t2010_160.x[ii], t2010_160.y[ii], t2010_160.m[ii], t2010_160.xe[ii], t2010_160.ye[ii], t2010_160.me[ii], t2010_160.name[ii])) _o814.close() _o125.close() _o139.close() _o160.close()
def matchup_ks2_pass1(ks2Catalog, ks2FilterIdx, matchupFile, outSuffix=None): """ Read in ks2 output and xym2mat files. Matchup to search for common sources. Return a table with all the measurements for comparison. """ # Load the KS2 star list # Should be LOGR_catalo.fits produced by jlu.hst.starlists.process_ks2_output() #ks2 = atpy.Table(ks2Root + '.FIND_AVG_UV1_F.fits') ks2 = atpy.Table(ks2Catalog) suffix = '_%d' % ks2FilterIdx # Trim down the KS2 list to just stuff well-measured in the filter of interest. keepIdx = np.where((ks2['x' + suffix] != -1000) & (ks2['m' + suffix] != 0) & (ks2['me' + suffix] < 1))[0] ks2 = ks2.rows(keepIdx) pass1 = starlists.read_matchup(matchupFile) keepIdx = np.where((pass1.x != -1000) & (pass1.m != 0) & (pass1.me < 1))[0] pass1 = pass1.rows(keepIdx) ##### # For each star in the matchup list (with a valid measurement), search the ks2 # data to find whether the star is measured. If it is, then compare the measurements # and unceratinties. ##### ks2Indices = np.zeros(len(pass1), dtype=int) ks2Indices += -1 # -1 indicates no match print 'Starting search for {0} stars'.format(len(pass1)) for ss in range(len(pass1)): if ss % 5000 == 0: print 'Reached star {0}'.format(ss) dr = np.hypot(pass1.x[ss] - ks2['x_0'], pass1.y[ss] - ks2['y_0']) rminIdx = dr.argmin() if dr[rminIdx] < 1: ks2Indices[ss] = rminIdx # Make a new table with x, y, m, xe, ye, me First in ks2, then in pass1. in_p1 = np.where(ks2Indices >= 0)[0] in_ks2 = ks2Indices[in_p1] stars = atpy.Table() stars.add_column('x_ks2', ks2['x' + suffix][in_ks2]) stars.add_column('y_ks2', ks2['y' + suffix][in_ks2]) stars.add_column('m_ks2', ks2['m' + suffix][in_ks2]) stars.add_column('xe_ks2', ks2['xe' + suffix][in_ks2]) stars.add_column('ye_ks2', ks2['ye' + suffix][in_ks2]) stars.add_column('me_ks2', ks2['me' + suffix][in_ks2]) stars.add_column('x_pass1', pass1['x'][in_p1]) stars.add_column('y_pass1', pass1['y'][in_p1]) stars.add_column('m_pass1', pass1['m'][in_p1]) stars.add_column('xe_pass1', pass1['xe'][in_p1]) stars.add_column('ye_pass1', pass1['ye'][in_p1]) stars.add_column('me_pass1', pass1['me'][in_p1]) stars.table_name = '' if outSuffix == None: outSuffix = 'f{0}'.format(ksFilterIdx) stars.write('stars_ks2_pass1_{0}.fits'.format(outSuffix), overwrite=True) # Just for kicks, also produce a table of stars that WERE NOT in ks2. # This table will have the same format as the pass1 list. stars_pass1_only = pass1.where(ks2Indices == -1) stars_pass1_only.table_name = '' stars_pass1_only.write('stars_pass1_only_{0}.fits'.format(outSuffix), overwrite=True)
def matchup_ks2_pass1(ks2Catalog, ks2FilterIdx, matchupFile, outSuffix=None): """ Read in ks2 output and xym2mat files. Matchup to search for common sources. Return a table with all the measurements for comparison. """ # Load the KS2 star list # Should be LOGR_catalo.fits produced by jlu.hst.starlists.process_ks2_output() #ks2 = atpy.Table(ks2Root + '.FIND_AVG_UV1_F.fits') ks2 = atpy.Table(ks2Catalog) suffix = '_%d' % ks2FilterIdx # Trim down the KS2 list to just stuff well-measured in the filter of interest. keepIdx = np.where((ks2['x'+suffix] != -1000) & (ks2['m'+suffix] != 0) & (ks2['me'+suffix] < 1))[0] ks2 = ks2.rows(keepIdx) pass1 = starlists.read_matchup(matchupFile) keepIdx = np.where((pass1.x != -1000) & (pass1.m != 0) & (pass1.me < 1))[0] pass1 = pass1.rows(keepIdx) ##### # For each star in the matchup list (with a valid measurement), search the ks2 # data to find whether the star is measured. If it is, then compare the measurements # and unceratinties. ##### ks2Indices = np.zeros(len(pass1), dtype=int) ks2Indices += -1 # -1 indicates no match print 'Starting search for {0} stars'.format(len(pass1)) for ss in range(len(pass1)): if ss % 5000 == 0: print 'Reached star {0}'.format(ss) dr = np.hypot( pass1.x[ss] - ks2['x_0'], pass1.y[ss] - ks2['y_0'] ) rminIdx = dr.argmin() if dr[rminIdx] < 1: ks2Indices[ss] = rminIdx # Make a new table with x, y, m, xe, ye, me First in ks2, then in pass1. in_p1 = np.where(ks2Indices >= 0)[0] in_ks2 = ks2Indices[in_p1] stars = atpy.Table() stars.add_column('x_ks2', ks2['x'+suffix][in_ks2]) stars.add_column('y_ks2', ks2['y'+suffix][in_ks2]) stars.add_column('m_ks2', ks2['m'+suffix][in_ks2]) stars.add_column('xe_ks2', ks2['xe'+suffix][in_ks2]) stars.add_column('ye_ks2', ks2['ye'+suffix][in_ks2]) stars.add_column('me_ks2', ks2['me'+suffix][in_ks2]) stars.add_column('x_pass1', pass1['x'][in_p1]) stars.add_column('y_pass1', pass1['y'][in_p1]) stars.add_column('m_pass1', pass1['m'][in_p1]) stars.add_column('xe_pass1', pass1['xe'][in_p1]) stars.add_column('ye_pass1', pass1['ye'][in_p1]) stars.add_column('me_pass1', pass1['me'][in_p1]) stars.table_name = '' if outSuffix == None: outSuffix = 'f{0}'.format(ksFilterIdx) stars.write('stars_ks2_pass1_{0}.fits'.format(outSuffix), overwrite=True) # Just for kicks, also produce a table of stars that WERE NOT in ks2. # This table will have the same format as the pass1 list. stars_pass1_only = pass1.where(ks2Indices == -1) stars_pass1_only.table_name = '' stars_pass1_only.write('stars_pass1_only_{0}.fits'.format(outSuffix), overwrite=True)