def measure_fluxes_gaussfit_allsrcs(data, img, data_name, name_start=27, name_end=-21, ref_name='B3'): cat = Table.read(data) RA_name = 'gauss_x_' + ref_name ind = np.where(np.isnan(cat[RA_name]) == False) cat = cat[ind] col_names = fnmatch.filter(cat.colnames, 'ap_flux_r*') col_names = [cn[8:] for cn in col_names] fl = fits.open(img) header = fl[0].header img_data = fl[0].data.squeeze() mywcs = WCS(header).celestial beam = radio_beam.Beam.from_fits_header(header) pixel_scale = np.abs( mywcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg ppbeam = (beam.sr / (pixel_scale**2)).decompose().value save_dir = '/lustre/aoc/students/jotter/gauss_diags/diff_imgs/' + ref_name + '/' + data_name + '/' if not os.path.exists(save_dir): os.makedirs(save_dir) reg_file = '/users/jotter/summer_research_2018/final_regs/misc_regs/' + data_name + '_reg_file_' + ref_name + '_apflux.reg' with open(reg_file, 'w') as fh: fh.write("fk5\n") for ind in range(len(cat)): fh.write( 'ellipse({x_cen}, {y_cen}, {maj}, {minr}, {ang}) #text={{{ID}}}\n' .format(x_cen=cat['gauss_x_' + ref_name][ind], y_cen=cat['gauss_y_' + ref_name][ind], maj=(cat['FWHM_major_' + ref_name][ind] * u.arcsec.to(u.degree)), minr=(cat['FWHM_minor_' + ref_name][ind] * u.arcsec.to(u.degree)), ang=cat['position_angle_' + ref_name][ind], ID=str(cat['D_ID'][ind]))) rad = Angle(1, 'arcsecond') #radius for region list regs = [] for ind in range(len(cat)): reg = regions.CircleSkyRegion(center=SkyCoord( cat['gauss_x_' + ref_name][ind] * u.degree, cat['gauss_y_' + ref_name][ind] * u.degree), radius=rad, meta={'text': str(cat['D_ID'][ind])}) reg_pix = reg.to_pixel(mywcs) if reg_pix.center.x > 0 and reg_pix.center.x < len(img_data[0]): if reg_pix.center.y > 0 and reg_pix.center.y < len(img_data): if np.isnan(img_data[int(reg_pix.center.x), int(reg_pix.center.y)]) == False: regs.append(reg) cat_r = Angle(0.5, 'arcsecond') #radius in gaussian fitting gauss_cat = gaussfit_catalog( img, regs, cat_r, savepath=save_dir) #output is nested dictionary structure gauss_fit_tab = Table( names=('D_ID', 'FWHM_major_' + data_name, 'major_err_' + data_name, 'FWHM_minor_' + data_name, 'minor_err_' + data_name, 'pa_' + data_name, 'pa_err_' + data_name, 'g_amplitude_' + data_name, 'amp_err_' + data_name), dtype=('i4', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8')) for key in gauss_cat: gauss_fit_tab.add_row( (key, gauss_cat[key]['fwhm_major'], gauss_cat[key]['e_fwhm_major'], gauss_cat[key]['fwhm_minor'], gauss_cat[key]['e_fwhm_minor'], gauss_cat[key]['pa'], gauss_cat[key]['e_pa'], gauss_cat[key]['amplitude'], gauss_cat[key]['e_amplitude'])) #fill table ap_flux_arr = [] circ_flux_arr = [] ap_flux_err_arr = [] circ_flux_err_arr = [] bg_median_arr = [] bg_ap_arr = [] bg_circ_arr = [] RA = [] DEC = [] RA_err = [] DEC_err = [] for row in range(len(cat)): gauss_ind = np.where(gauss_fit_tab['D_ID'] == cat['D_ID'][row])[0] if len(gauss_ind) > 0: pix_major_fwhm = ( (cat['FWHM_major_' + ref_name][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() pix_minor_fwhm = ( (cat['FWHM_minor_' + ref_name][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() center_coord = SkyCoord(cat['gauss_x_' + ref_name][row], cat['gauss_y_' + ref_name][row], frame='icrs', unit=(u.deg, u.deg)) center_coord_pix = center_coord.to_pixel(mywcs) center_coord_pix_reg = regions.PixCoord(center_coord_pix[0], center_coord_pix[1]) position_angle = cat['position_angle_' + ref_name][row] * u.deg ellipse_reg = regions.EllipsePixelRegion(center_coord_pix_reg, pix_major_fwhm * 2., pix_minor_fwhm * 2., angle=position_angle) size = pix_major_fwhm * 2.1 ap_mask = ellipse_reg.to_mask() cutout_mask = ap_mask.cutout(img_data) aperture_flux = np.sum(cutout_mask[ap_mask.data == 1]) / ppbeam npix = len(cutout_mask[ap_mask.data == 1]) ap_flux_arr.append(aperture_flux) #now creating annulus around source to measure background and ap flux error annulus_width = 15 annulus_radius = 0.1 * u.arcsecond annulus_radius_pix = (annulus_radius.to(u.degree) / pixel_scale).decompose() # Cutout section of the image we care about, to speed up computation time size = 2.5 * annulus_radius cutout = Cutout2D(img_data, center_coord_pix, size, mywcs, mode='partial') #cutout of outer circle cutout_center = regions.PixCoord(cutout.center_cutout[0], cutout.center_cutout[1]) # Define the aperture regions needed for SNR innerann_reg = regions.CirclePixelRegion(cutout_center, annulus_radius_pix) outerann_reg = regions.CirclePixelRegion( cutout_center, annulus_radius_pix + annulus_width) # Make masks from aperture regions annulus_mask = mask(outerann_reg, cutout) - mask( innerann_reg, cutout) # Calculate the SNR and aperture flux sums pixels_in_annulus = cutout.data[annulus_mask.astype( 'bool')] #pixels within annulus bg_rms = rms(pixels_in_annulus) ap_bg_rms = bg_rms / np.sqrt( npix / ppbeam) #rms/sqrt(npix/ppbeam) - rms error per beam bg_median = np.median(pixels_in_annulus) pix_bg = bg_median * npix / ppbeam ap_flux_err_arr.append(ap_bg_rms) bg_median_arr.append(bg_median) bg_ap_arr.append(pix_bg) #now measure circle flux: radius = 0.1 * u.arcsecond radius_pix = annulus_radius_pix circle_reg = regions.CirclePixelRegion(center_coord_pix_reg, radius_pix) circ_ap_mask = circle_reg.to_mask() circ_cutout_mask = circ_ap_mask.cutout(img_data) cutout_mask = ap_mask.cutout(img_data) circ_aperture_flux = np.sum( circ_cutout_mask[circ_ap_mask.data == 1]) / ppbeam circ_npix = len(circ_cutout_mask[circ_ap_mask.data == 1]) circ_bg_rms = bg_rms / np.sqrt(circ_npix / ppbeam) circ_flux_arr.append(circ_aperture_flux) circ_flux_err_arr.append(circ_bg_rms) bg_circ_arr.append(bg_median * circ_npix / ppbeam) RA.append(cat['gauss_x_' + ref_name][row]) DEC.append(cat['gauss_y_' + ref_name][row]) RA_err.append(cat['x_err_' + ref_name][row]) DEC_err.append(cat['y_err_' + ref_name][row]) cols = [ 'ap_flux_', 'ap_flux_err_', 'bg_median_', 'bg_ap_', 'circ_flux_', 'circ_flux_err_', 'bg_circ_' ] arrs = [ ap_flux_arr, ap_flux_err_arr, bg_median_arr, bg_ap_arr, circ_flux_arr, circ_flux_err_arr, bg_circ_arr ] cols2 = ['RA_', 'DEC_', 'RA_err_', 'DEC_err_'] #seperate bc different naming arrs2 = [RA, DEC, RA_err, DEC_err] for j in range(len(cols)): gauss_fit_tab[cols[j] + data_name] = arrs[j] for c in range(len(cols2)): gauss_fit_tab[cols2[c] + ref_name] = arrs2[c] gauss_fit_tab.write('/lustre/aoc/students/jotter/dendro_catalogs/' + data_name + '_500klplus_allsrcs_catalog_' + ref_name + '_ref.txt', format='ascii', overwrite=True)
def measure_fluxes_gaussfit(data, directory, data_name, name_start=27, name_end=-21, ref_name='B6'): #This function takes a directory full of images and adds them all to a catalog with flux measurements and fits gaussians. 'data' is the catalog to get positions from, 'ref_name' is the name of the reference data (for positions), 'directory' is the directory with all the new images. cat = Table.read(data) RA_names = ['gauss_x_B3', 'gauss_x_B6', 'gauss_x_B7_hr'] inds = [] for fn in RA_names: ind = np.where(np.isnan(cat[fn]) == False) inds.append(ind) detected = reduce( np.intersect1d, inds ) #sources detected in B3, B6, B7 - only make measurements on these sources cat = cat[detected] imgs = glob.glob(directory + '*r-2.clean0.1mJy.500klplus.deepmask*') img_names = [img[len(directory) + name_start:name_end] for img in imgs] col_names = fnmatch.filter(cat.colnames, 'ap_flux_r*') col_names = [cn[8:] for cn in col_names] for j, img in enumerate(imgs): name = img_names[j] if len(name) > 54: name = name[0:53] if name not in col_names: fl = fits.open(img) header = fl[0].header try: img_data = fl[0].data.squeeze() except TypeError: print("error! img: " + img) continue mywcs = WCS(header).celestial beam = radio_beam.Beam.from_fits_header(header) pixel_scale = np.abs( mywcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg ppbeam = (beam.sr / (pixel_scale**2)).decompose().value save_dir = '/lustre/aoc/students/jotter/gauss_diags/diff_imgs/' + ref_name + '/' + name + '/' if not os.path.exists(save_dir): os.makedirs(save_dir) reg_file = '/users/jotter/summer_research_2018/final_regs/' + name + '_reg_file_B6_apflux.reg' with open(reg_file, 'w') as fh: fh.write("fk5\n") for ind in range(len(cat)): fh.write( 'ellipse({x_cen}, {y_cen}, {maj}, {minr}, {ang}) #text={{{ID}}}\n' .format(x_cen=cat['gauss_x_' + ref_name][ind], y_cen=cat['gauss_y_' + ref_name][ind], maj=(cat['FWHM_major_' + ref_name][ind] * u.arcsec.to(u.degree)), minr=(cat['FWHM_minor_' + ref_name][ind] * u.arcsec.to(u.degree)), ang=cat['position_angle_' + ref_name][ind], ID=str(cat['D_ID'][ind]))) rad = Angle(1, 'arcsecond') #radius for region list regs = [] for ind in range(len(cat)): reg = regions.CircleSkyRegion(center=SkyCoord( cat['gauss_x_' + ref_name][ind] * u.degree, cat['gauss_y_' + ref_name][ind] * u.degree), radius=rad, meta={ 'text': str(cat['D_ID'][ind]) }) reg_pix = reg.to_pixel(mywcs) if reg_pix.center.x > 0 and reg_pix.center.x < len( img_data[0]): if reg_pix.center.y > 0 and reg_pix.center.y < len( img_data): regs.append(reg) cat_r = Angle(0.5, 'arcsecond') #radius in gaussian fitting gauss_cat = gaussfit_catalog( img, regs, cat_r, savepath=save_dir) #output is nested dictionary structure gauss_fit_tab = Table( names=('D_ID', 'FWHM_major_' + name, 'major_err_' + name, 'FWHM_minor_' + name, 'minor_err_' + name, 'pa_' + name, 'pa_err_' + name, 'g_amplitude_' + name, 'amp_err_' + name), dtype=('i4', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8')) for key in gauss_cat: gauss_fit_tab.add_row( (key, gauss_cat[key]['fwhm_major'], gauss_cat[key]['e_fwhm_major'], gauss_cat[key]['fwhm_minor'], gauss_cat[key]['e_fwhm_minor'], gauss_cat[key]['pa'], gauss_cat[key]['e_pa'], gauss_cat[key]['amplitude'], gauss_cat[key]['e_amplitude'])) #fill table cat = join(cat, gauss_fit_tab, keys='D_ID', join_type='left') ap_flux_arr = [] circ_flux_arr = [] ap_flux_err_arr = [] circ_flux_err_arr = [] bg_median_arr = [] bg_ap_arr = [] bg_circ_arr = [] for row in range(len(cat)): pix_major_fwhm = ((cat['FWHM_major_' + ref_name][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() pix_minor_fwhm = ((cat['FWHM_minor_' + ref_name][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() center_coord = SkyCoord(cat['gauss_x_' + ref_name][row], cat['gauss_y_' + ref_name][row], frame='icrs', unit=(u.deg, u.deg)) center_coord_pix = center_coord.to_pixel(mywcs) center_coord_pix_reg = regions.PixCoord( center_coord_pix[0], center_coord_pix[1]) position_angle = cat['position_angle_' + ref_name][row] * u.deg print(center_coord_pix_reg, pix_major_fwhm, pix_minor_fwhm) ellipse_reg = regions.EllipsePixelRegion(center_coord_pix_reg, pix_major_fwhm * 2., pix_minor_fwhm * 2., angle=position_angle) size = pix_major_fwhm * 2.1 ap_mask = ellipse_reg.to_mask() cutout_mask = ap_mask.cutout(img_data) aperture_flux = np.sum(cutout_mask[ap_mask.data == 1]) / ppbeam npix = len(cutout_mask[ap_mask.data == 1]) ap_flux_arr.append(aperture_flux) #now creating annulus around source to measure background and ap flux error annulus_width = 15 annulus_radius = 0.1 * u.arcsecond annulus_radius_pix = (annulus_radius.to(u.degree) / pixel_scale).decompose() # Cutout section of the image we care about, to speed up computation time size = 2.5 * annulus_radius cutout = Cutout2D(img_data, center_coord_pix, size, mywcs, mode='partial') #cutout of outer circle cutout_center = regions.PixCoord(cutout.center_cutout[0], cutout.center_cutout[1]) # Define the aperture regions needed for SNR innerann_reg = regions.CirclePixelRegion( cutout_center, annulus_radius_pix) outerann_reg = regions.CirclePixelRegion( cutout_center, annulus_radius_pix + annulus_width) # Make masks from aperture regions annulus_mask = mask(outerann_reg, cutout) - mask( innerann_reg, cutout) # Calculate the SNR and aperture flux sums pixels_in_annulus = cutout.data[annulus_mask.astype( 'bool')] #pixels within annulus bg_rms = rms(pixels_in_annulus) ap_bg_rms = bg_rms / np.sqrt( npix / ppbeam) #rms/sqrt(npix/ppbeam) - rms error per beam bg_median = np.median(pixels_in_annulus) pix_bg = bg_median * npix / ppbeam ap_flux_err_arr.append(ap_bg_rms) bg_median_arr.append(bg_median) bg_ap_arr.append(pix_bg) #now measure circle flux: radius = 0.1 * u.arcsecond radius_pix = annulus_radius_pix circle_reg = regions.CirclePixelRegion(center_coord_pix_reg, radius_pix) circ_ap_mask = circle_reg.to_mask() circ_cutout_mask = circ_ap_mask.cutout(img_data) cutout_mask = ap_mask.cutout(img_data) circ_aperture_flux = np.sum( circ_cutout_mask[circ_ap_mask.data == 1]) / ppbeam circ_npix = len(circ_cutout_mask[circ_ap_mask.data == 1]) circ_bg_rms = bg_rms / np.sqrt(circ_npix / ppbeam) circ_flux_arr.append(circ_aperture_flux) circ_flux_err_arr.append(circ_bg_rms) bg_circ_arr.append(bg_median * circ_npix / ppbeam) cols = [ 'ap_flux_', 'ap_flux_err_', 'bg_median_', 'bg_ap_', 'circ_flux_', 'circ_flux_err_', 'bg_circ_' ] arrs = [ ap_flux_arr, ap_flux_err_arr, bg_median_arr, bg_ap_arr, circ_flux_arr, circ_flux_err_arr, bg_circ_arr ] for j in range(len(cols)): cat[cols[j] + name] = arrs[j] cat.write('/lustre/aoc/students/jotter/dendro_catalogs/' + data_name + '_500klplus_allsrcs_catalog_' + ref_name + '_ref.txt', format='ascii', overwrite=True)
def gauss_sizes_imgs(srcID, band, images, directory, name_start=27, name_end=-21): #This function takes a list of image names and adds them all to a catalog with gaussian sizes. 'data' is the catalog to get positions from, 'srcID' is the D_ID of the desired source, 'band' is the band of data, 'images' is the list of image names, 'directory' is the directory where these images are. data = '/lustre/aoc/students/jotter/dendro_catalogs/master_500klplus_B3_ref.fits' cat = Table.read(data) ind = np.where(cat['D_ID'] == srcID)[0][0] img_names = [img[name_start:name_end] for img in images] print(img_names) table_names = [] #because maybe not all images in img_namse get used img_fwhm_maj = [] #at the end combine these lists into a table img_fwhm_maj_err = [] img_fwhm_min = [] img_fwhm_min_err = [] img_pa = [] img_pa_err = [] for j, img in enumerate(images): #loop through images and measure fwhms name = img_names[j] if len(name) > 54: name = name[0:53] fl = fits.open(directory + img) header = fl[0].header try: img_data = fl[0].data.squeeze() except TypeError: print("error! img: " + img) continue mywcs = WCS(header).celestial beam = radio_beam.Beam.from_fits_header(header) pixel_scale = np.abs( mywcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg ppbeam = (beam.sr / (pixel_scale**2)).decompose().value save_dir = '/lustre/aoc/students/jotter/gauss_diags/diff_imgs/src_' + str( srcID) + '/' + band + '/' + name if not os.path.exists(save_dir): os.makedirs(save_dir) rad = Angle(1, 'arcsecond') #radius for region list regs = [] reg = regions.CircleSkyRegion(center=SkyCoord( cat['RA_B3'][ind] * u.degree, cat['DEC_B3'][ind] * u.degree), radius=rad, meta={'text': str(cat['D_ID'][ind])}) reg_pix = reg.to_pixel(mywcs) if reg_pix.center.x > 0 and reg_pix.center.x < len(img_data[0]): if reg_pix.center.y > 0 and reg_pix.center.y < len(img_data): regs.append(reg) cat_r = Angle(0.5, 'arcsecond') #radius in gaussian fitting gauss_cat = gaussfit_catalog( directory + img, regs, cat_r, savepath=save_dir) #output is nested dictionary structure table_names.append(name) img_fwhm_maj.append(gauss_cat[str(srcID)]['fwhm_major'].value) img_fwhm_maj_err.append(gauss_cat[str(srcID)]['e_fwhm_major'].value) img_fwhm_min.append(gauss_cat[str(srcID)]['fwhm_minor'].value) img_fwhm_min_err.append(gauss_cat[str(srcID)]['e_fwhm_minor'].value) img_pa.append(gauss_cat[str(srcID)]['pa'].value) img_pa_err.append(gauss_cat[str(srcID)]['e_pa'].value) table = Table((table_names, img_fwhm_maj, img_fwhm_maj_err, img_fwhm_min, img_fwhm_min_err, img_pa, img_pa_err), names=('img_name', 'fwhm_maj', 'fwhm_maj_err', 'fwhm_min', 'fwhm_min_err', 'pa', 'pa_err')) table['fwhm_maj'].unit = 'arcsec' table['fwhm_maj_err'].unit = 'arcsec' table['fwhm_min'].unit = 'arcsec' table['fwhm_min_err'].unit = 'arcsec' table.write('/lustre/aoc/students/jotter/dendro_catalogs/src' + str(srcID) + '_img_sizes' + band + '.fits', overwrite=True)
def measure_fluxes(data, ref_name, img, name): #This function is to add another image to an already made catalog using positions from a different image. 'data' is the catalog to add measurements to, 'ref_name' is the name of the reference data set (where the positions are from), 'img' is the new image, and 'name' is the name of 'img' cat = Table.read(data) fl = fits.open(img) header = fl[0].header img_data = fl[0].data.squeeze() mywcs = WCS(header).celestial rad = Angle(1, 'arcsecond') #radius for region list rad_deg = rad.to(u.degree) #generate region list regs = [] reg_file = '/users/jotter/summer_research_2018/final_regs/' + name + '_reg_file_circle.reg' with open(reg_file, 'w') as fh: fh.write("fk5\n") for ind in range(len(cat)): reg = regions.CircleSkyRegion(center=SkyCoord( cat['gauss_x_' + ref_name][ind] * u.degree, cat['gauss_y_' + ref_name][ind] * u.degree), radius=rad, meta={'text': str(cat['D_ID'][ind])}) reg_pix = reg.to_pixel(mywcs) if reg_pix.center.x > 0 and reg_pix.center.x < len(img_data[0]): if reg_pix.center.y > 0 and reg_pix.center.y < len(img_data): regs.append(reg) fh.write( 'circle({x_cen}, {y_cen}, {radius}) #text={{{ID}}}\n'. format(x_cen=reg.center.ra.value, y_cen=reg.center.dec.value, radius=0.1 * rad_deg.value, ID=str(cat['D_ID'][ind]))) cat_r = Angle(0.3, 'arcsecond') #radius in gaussian fitting gauss_cat = gaussfit_catalog( img, regs, cat_r, savepath='/lustre/aoc/students/jotter/gauss_diags/leaves/' + name) #output is nested dictionary structure gauss_fit_tab = Table( names=('D_ID', '_idx_' + name, 'gauss_x_' + name, 'x_err_' + name, 'gauss_y_' + name, 'y_err_' + name, 'FWHM_major_' + name, 'major_err_' + name, 'FWHM_minor_' + name, 'minor_err_' + name, 'position_angle_' + name, 'position_angle_err_' + name, 'peak_flux_' + name, 'gauss_amplitude_' + name, 'amplitude_err_' + name, 'ap_flux_' + name, 'ap_flux_err_' + name, 'fit_goodness_' + name), dtype=('i4', 'i4', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'U10')) #turn into astropy table for key in gauss_cat: gauss_fit_tab.add_row( (key, key, gauss_cat[key]['center_x'], gauss_cat[key]['e_center_x'], gauss_cat[key]['center_y'], gauss_cat[key]['e_center_y'], gauss_cat[key]['fwhm_major'], gauss_cat[key]['e_fwhm_major'], gauss_cat[key]['fwhm_minor'], gauss_cat[key]['e_fwhm_minor'], gauss_cat[key]['pa'], gauss_cat[key]['e_pa'], gauss_cat[key]['peak'], gauss_cat[key]['amplitude'], gauss_cat[key]['e_amplitude'], np.nan, np.nan, 'none')) #fill table beam = radio_beam.Beam.from_fits_header(header) pixel_scale = np.abs( mywcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg ppbeam = (beam.sr / (pixel_scale**2)).decompose().value for row in range(len(gauss_fit_tab)): pix_major_fwhm = ((gauss_fit_tab['FWHM_major_' + name][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() pix_minor_fwhm = ((gauss_fit_tab['FWHM_minor_' + name][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() cutout_center = SkyCoord(gauss_fit_tab['gauss_x_' + name][row], gauss_fit_tab['gauss_y_' + name][row], frame='icrs', unit=(u.deg, u.deg)) cutout_center_pix = cutout_center.to_pixel(mywcs) cutout_center_pix = regions.PixCoord(cutout_center_pix[0], cutout_center_pix[1]) position_angle = gauss_fit_tab['position_angle_' + name][row] * u.deg ellipse_reg = regions.EllipsePixelRegion(cutout_center_pix, pix_major_fwhm * 2., pix_minor_fwhm * 2., angle=position_angle) size = pix_major_fwhm * 2.1 ap_mask = ellipse_reg.to_mask() cutout_mask = ap_mask.cutout(img_data) aperture_flux = np.sum(cutout_mask[ap_mask.data == 1]) / ppbeam gauss_fit_tab['ap_flux_' + name][row] = aperture_flux gauss_fit_tab.write('/lustre/aoc/students/jotter/dendro_catalogs/' + name + '_dendro_catalog_ref_' + ref_name + '.fits', format='fits', overwrite=True)
def create_catalog(param_file): params = ascii.read(param_file) for row in range(len(params)): name = params['name'][ row] #contains parameters for dendrogram catalog creation min_val = params['min_value'][row] min_del = params['min_delta'][row] n_pix = params['n_pix'][row] img = params['file_name'][row] reg_fname = '/home/jotter/nrao/images/dendro_regions/' + name + '_reg_file.reg' dendro, cat = compute_regions(min_val, min_del, n_pix, img, reg_fname) cat['flux_err_' + name] = np.zeros(len(cat)) if params['pbcorr'][ row] != 'True': #if the image is not pb corrected, measure flux from pb corrected image img = params['pbcorr'][row] cont_file = fits.open(img) header = cont_file[0].header mywcs = WCS(header).celestial data = cont_file[0].data.squeeze() beam = radio_beam.Beam.from_fits_header(header) pixel_scale = np.abs( mywcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg ppbeam = (beam.sr / (pixel_scale**2)).decompose().value cat.rename_column('_idx', '_idx_' + name) #next, measure centroids with gaussian fitting rad = Angle(1, 'arcsecond') #radius for region list regs = [] for ind, leaf in enumerate( dendro.all_structures): #.leaves #generate region list regs.append( regions.CircleSkyRegion( center=SkyCoord(cat['x_cen'][ind] * u.degree, cat['y_cen'][ind] * u.degree), radius=rad, meta={'text': str(cat['_idx_' + name][ind])})) print(len(regs)) #if name == 'B6': #regs.append(regions.CircleSkyRegion(center=SkyCoord(83.81138026377482*u.degree, -5.374951161716349*u.degree), radius=rad, meta={'text':'54'}))#manually appending a source not picked up by dendrogram cat_r = Angle(0.3, 'arcsecond') #radius in gaussian fitting gauss_cat = gaussfit_catalog( img, regs, cat_r, savepath='/home/jotter/nrao/gauss_diags/leaves/' + name) #output is nested dictionary structure gauss_fit_tab = Table( names=('_idx_' + name, 'gauss_x_' + name, 'x_err_' + name, 'gauss_y_' + name, 'y_err_' + name, 'FWHM_major_' + name, 'major_err_' + name, 'FWHM_minor_' + name, 'minor_err_' + name, 'position_angle_' + name, 'position_angle_err_' + name, 'peak_flux_' + name, 'gauss_amplitude_' + name, 'amplitude_err_' + name, 'ap_flux_' + name, 'ap_flux_err_' + name, 'fit_goodness_' + name), dtype=('i4', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'U10')) #turn into astropy table for key in gauss_cat: gauss_fit_tab.add_row( (key, gauss_cat[key]['center_x'], gauss_cat[key]['e_center_x'], gauss_cat[key]['center_y'], gauss_cat[key]['e_center_y'], gauss_cat[key]['fwhm_major'], gauss_cat[key]['e_fwhm_major'], gauss_cat[key]['fwhm_minor'], gauss_cat[key]['e_fwhm_minor'], gauss_cat[key]['pa'], gauss_cat[key]['e_pa'], gauss_cat[key]['peak'], gauss_cat[key]['amplitude'], gauss_cat[key]['e_amplitude'], np.nan, np.nan, 'none')) #fill table for row in range(len(gauss_fit_tab)): pix_major_fwhm = ((gauss_fit_tab['FWHM_major_' + name][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() pix_minor_fwhm = ((gauss_fit_tab['FWHM_minor_' + name][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() cutout_center = SkyCoord(gauss_fit_tab['gauss_x_' + name][row], gauss_fit_tab['gauss_y_' + name][row], frame='icrs', unit=(u.deg, u.deg)) cutout_center_pix = cutout_center.to_pixel(mywcs) cutout_center_pix = regions.PixCoord(cutout_center_pix[0], cutout_center_pix[1]) position_angle = gauss_fit_tab['position_angle_' + name][row] * u.deg ellipse_reg = regions.EllipsePixelRegion(cutout_center_pix, pix_major_fwhm * 2., pix_minor_fwhm * 2., angle=position_angle) size = pix_major_fwhm * 2.1 ap_mask = ellipse_reg.to_mask() cutout_mask = ap_mask.cutout(data) aperture_flux = np.sum(cutout_mask[ap_mask.data == 1]) / ppbeam gauss_fit_tab['ap_flux_' + name][row] = aperture_flux #NOTE: aperture flux error and background fluxes will get filled in after running `snr_rejection.py` full_cat = join(cat, gauss_fit_tab, keys='_idx_' + name, join_type='outer' ) #joining the gaussian centroid data with the rest full_cat.write('/home/jotter/nrao/tables/dendro_catalogs/' + name + '_dendro_catalog_leaves.fits', format='fits', overwrite=True)
B3_pixel_scale = np.abs(wcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg B3_kernel = B3beam.as_kernel(B3_pixel_scale) convolved_img = convolve_fft(fake_img, B3_kernel) new_fl[0].data = convolved_img new_fl.writeto('/users/jotter/summer_research_2018/fake_conv_img.fits', overwrite=True) loc = wcs.wcs_pix2world(500, 500, 1) reg = regions.CircleSkyRegion(center=SkyCoord(loc[0], loc[1], unit='deg'), radius=0.5 * u.arcsec, meta={'text': 'test'}) reg_pix = reg.to_pixel(wcs) gaussfit = gaussfit_catalog( '/users/jotter/summer_research_2018/fake_conv_img.fits', [reg], Angle(0.5, 'arcsecond'), savepath='/users/jotter/summer_research_2018/') source_size = Beam(major=gaussfit['test']['fwhm_major'], minor=gaussfit['test']['fwhm_minor'], pa=(gaussfit['test']['pa'].value - 90) * u.degree) try: deconv_size = source_size.deconvolve(B3beam) print('gaussfit deconv major: ' + str(gaussfit['test']['deconv_fwjm_major']) + ' minor: ' + str(gaussfit['test']['deconv_fwhm_minor']) + ' deconv - 90 degrees major: ' + str(deconv_size.major.value) + ' minor: ' + str(deconv_size.minor.value)) except ValueError: print('could not be deconvolved')
def b6b7_catalog(B6_img, B6_name, B7_img, B7_name, cat_name, nonconv_B6_img=None, nonconv_B7_img=None): #creates catalog from one image in each band #B3_names, B6_names, B7_names only used for gaussian diag directory names ref_data_name = '/home/jotter/nrao/summer_research_2018/tables/ref_catalog_may21.fits' ref_data = Table.read(ref_data_name) ref_arrs = [ref_data['B6_detect'], ref_data['B7_detect']] band_imgs = [B6_img, B7_img] band_names = ['B6', 'B7'] band_img_names = [B6_name, B7_name] band_tables = [] for b in range(len(band_imgs)): #first loop through different bands name = band_names[b] img_name = band_img_names[b] img = band_imgs[b] fl = fits.open(img) header = fl[0].header img_data = fl[0].data.squeeze() img_wcs = WCS(header).celestial beam = radio_beam.Beam.from_fits_header(header) pixel_scale = np.abs(img_wcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg ppbeam = (beam.sr/(pixel_scale**2)).decompose().value if name == 'B6' and nonconv_B6_img is not None: fl = fits.open(nonconv_B6_img) header = fl[0].header nonconv_beam = radio_beam.Beam.from_fits_header(header) ppbeam = (nonconv_beam.sr/(pixel_scale**2)).decompose().value if name == 'B7' and nonconv_B7_img is not None: fl = fits.open(nonconv_B7_img) header = fl[0].header nonconv_beam = radio_beam.Beam.from_fits_header(header) ppbeam = (nonconv_beam.sr/(pixel_scale**2)).decompose().value #now get ready to fit gaussians #start by setting up save directory for images gauss_save_dir = '/home/jotter/nrao/gauss_diags_may21/'+img_name+'/' if not os.path.exists(gauss_save_dir): os.makedirs(gauss_save_dir) #now make region list rad = Angle(1, 'arcsecond') #radius used in region list regs = [] src_inds = np.where(ref_arrs[b] == True)[0] print(len(src_inds)) for ind in src_inds: reg = regions.CircleSkyRegion(center=SkyCoord(ref_data['RA_B3'][ind]*u.degree, ref_data['DEC_B3'][ind]*u.degree), radius=rad, meta={'text':str(ref_data['B3_Seq'][ind])}) reg_pix = reg.to_pixel(img_wcs) if reg_pix.center.x > 0 and reg_pix.center.x < len(img_data[0]): if reg_pix.center.y > 0 and reg_pix.center.y < len(img_data): if np.isnan(img_data[int(reg_pix.center.x), int(reg_pix.center.y)]) == False: regs.append(reg) cat_r = Angle(0.5, 'arcsecond')/2 #radius for gaussian fitting print('ok') gauss_cat = gaussfit_catalog(img, regs, cat_r, savepath=gauss_save_dir, max_offset_in_beams = 1, max_radius_in_beams = 5) #table does not have all columns yet, add others later img_table = Table(names=('Seq_B3', 'fwhm_maj_'+name, 'fwhm_maj_err_'+name, 'fwhm_min_'+name, 'fwhm_min_err_'+name, 'pa_'+name, 'pa_err_'+name, 'gauss_amp_'+name, 'gauss_amp_err_'+name,'RA_'+name,'RA_err_'+name, 'DEC_'+name, 'DEC_err_'+name, ), dtype=('i4', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8')) for key in gauss_cat: img_table.add_row((key, gauss_cat[key]['fwhm_major'], gauss_cat[key]['e_fwhm_major'], gauss_cat[key]['fwhm_minor'], gauss_cat[key]['e_fwhm_minor'], gauss_cat[key]['pa'], gauss_cat[key]['e_pa'], gauss_cat[key]['amplitude'], gauss_cat[key]['e_amplitude'], gauss_cat[key]['center_x'], gauss_cat[key]['e_center_x'], gauss_cat[key]['center_y'], gauss_cat[key]['e_center_y'])) #now measure deconvovled sizes and aperture flux measurements for each source ap_flux_arr = [] ap_flux_err_arr = [] fwhm_maj_deconv_arr = [] fwhm_maj_deconv_err_arr = [] fwhm_min_deconv_arr = [] fwhm_min_deconv_err_arr = [] pa_deconv_arr = [] pa_deconv_err_arr = [] snr_arr = [] rms_arr = [] for row in range(len(img_table)): #now loop through sources in reference data and make measurements ref_ind = np.where(ref_data['B3_Seq'] == img_table['Seq_B3'][row])[0] if len(ref_ind > 0): #now measuring deconvolved sizes measured_source_size = radio_beam.Beam(major=img_table['fwhm_maj_'+name][row]*u.arcsec, minor=img_table['fwhm_min_'+name][row]*u.arcsec, pa=(img_table['pa_'+name][row]-90)*u.degree) try: deconv_size = measured_source_size.deconvolve(beam) fwhm_maj_deconv_arr.append(deconv_size.major.value) fwhm_min_deconv_arr.append(deconv_size.minor.value) fwhm_maj_deconv_err_arr.append(img_table['fwhm_maj_err_'+name][row]) #same error as non deconvolved fwhm_min_deconv_err_arr.append(img_table['fwhm_min_err_'+name][row]) pa_deconv_arr.append(deconv_size.pa.to(u.deg).value) pa_deconv_err_arr.append(img_table['pa_err_'+name][row]) except ValueError: fwhm_maj_deconv_arr.append(np.nan) fwhm_min_deconv_arr.append(np.nan) fwhm_maj_deconv_err_arr.append(np.nan) fwhm_min_deconv_err_arr.append(np.nan) pa_deconv_arr.append(np.nan) pa_deconv_err_arr.append(np.nan) pix_major_fwhm = ((img_table['fwhm_maj_'+name][row]*u.arcsec).to(u.degree)/pixel_scale).decompose() pix_minor_fwhm = ((img_table['fwhm_min_'+name][row]*u.arcsec).to(u.degree)/pixel_scale).decompose() center_coord = SkyCoord(img_table['RA_'+name][row], img_table['DEC_'+name][row], frame='icrs', unit=(u.deg, u.deg)) center_coord_pix = center_coord.to_pixel(img_wcs) center_coord_pix_reg = regions.PixCoord(center_coord_pix[0], center_coord_pix[1]) pos_ang = (img_table['pa_'+name][row]-90)*u.deg #must subtract 90 to be consistent ellipse_reg = regions.EllipsePixelRegion(center_coord_pix_reg, pix_major_fwhm.value*2, pix_minor_fwhm.value*2, angle=pos_ang) ap_mask = ellipse_reg.to_mask() cutout_mask = ap_mask.cutout(img_data) aperture_flux = np.nansum(cutout_mask[ap_mask.data==1])/ppbeam npix = len(cutout_mask[ap_mask.data==1]) #now make annulus for measuring background and error annulus_width = 15 #pixels annulus_radius = img_table['fwhm_maj_'+name][row]*u.arcsecond#+0.05*u.arcsecond annulus_radius_pix = (annulus_radius.to(u.degree)/pixel_scale).decompose() #cutout image cutout = Cutout2D(img_data, center_coord_pix, annulus_radius*2.5, img_wcs, mode='partial') cutout_center = regions.PixCoord(cutout.center_cutout[0], cutout.center_cutout[1]) #define aperture regions for SNR innerann_reg = regions.CirclePixelRegion(cutout_center, annulus_radius_pix.value) outerann_reg = regions.CirclePixelRegion(cutout_center, annulus_radius_pix.value+annulus_width) #Make masks from aperture regions annulus_mask = mask(outerann_reg, cutout) - mask(innerann_reg, cutout) # Calculate the SNR and aperture flux sums pixels_in_annulus = cutout.data[annulus_mask.astype('bool')] bg_rms = median_abs_deviation(pixels_in_annulus) print(img_table['Seq_B3'][row]) print('BG RMS: %f' % (bg_rms)) ap_bg_rms = bg_rms/np.sqrt(npix/ppbeam) #rms/sqrt(npix/ppbeam) - rms error per beam bg_median = np.nanmedian(pixels_in_annulus) pix_bg = bg_median*npix/ppbeam ap_flux_bgcorrect = aperture_flux - pix_bg ap_flux_correct = ap_flux_bgcorrect + ap_flux_bgcorrect*(1 - special.erf(2*np.sqrt(np.log(2)))) #flux correction for summing within 2*fwhm ap_flux_err_arr.append(ap_bg_rms) ap_flux_arr.append(ap_flux_correct) snr_arr.append(img_table['gauss_amp_'+name][row]/bg_rms) rms_arr.append(bg_rms) cols = ['ap_flux_'+name, 'ap_flux_err_'+name, 'fwhm_maj_deconv_'+name, 'fwhm_maj_deconv_err_'+name, 'fwhm_min_deconv_'+name, 'fwhm_min_deconv_err_'+name, 'pa_deconv_'+name, 'pa_deconv_err_'+name, 'SNR_'+name, 'RMS_'+name] arrs = [ap_flux_arr, ap_flux_err_arr, fwhm_maj_deconv_arr, fwhm_maj_deconv_err_arr, fwhm_min_deconv_arr, fwhm_min_deconv_err_arr, pa_deconv_arr, pa_deconv_err_arr, snr_arr, rms_arr] for c in range(len(cols)): img_table.add_column(Column(np.array(arrs[c])), name=cols[c]) img_table.add_column(Column(np.array(fwhm_maj_deconv_arr)/np.array(fwhm_min_deconv_arr)), name='ar_deconv_'+name) band_tables.append(img_table) #list of tables for each image B6B7 = join(band_tables[0], band_tables[1], keys='Seq_B3', join_type='outer') B6B7.write('/home/jotter/nrao/summer_research_2018/tables/'+cat_name+'.fits', overwrite=True)
for regfn, contfn, name in ( ('Meier2015NGC253Positions-Updated.reg', 'NGC253-H2COJ32K02_H2COJ32K0_moment0_widthscale1.0_sncut2.0_widthcutscale1.0.fits', 'NGC253-H2COJ32K02-H2COJ32K0GaussFit'), #('Meier2015NGC253Positions-Updated.reg', 'NGC253-H2COJ32K02_H2COJ32K210_moment0_widthscale1.0_sncut2.0_widthcutscale1.0.fits', 'NGC253-H2COJ32K02-H2COJ32K210GaussFit'), #('Meier2015NGC253Positions-Updated.reg', 'NGC253-H2COJ54K1_H2COJ54K1_moment0_widthscale1.0_sncut2.0_widthcutscale1.0.fits', 'NGC253-H2COJ54K1-H2COJ54K1GaussFit'), #('Meier2015NGC253Positions-Updated.reg', 'NGC253-H2COJ54K23_H2COJ54K321_moment0_widthscale1.0_sncut2.0_widthcutscale1.0.fits', 'NGC253-H2COJ54K23-H2COJ54K321GaussFit'), ): regs = regions.read_ds9(regfn) # contfn = 'gaussfit/'+contfn fit_data = gaussfit_catalog( contfn, regs, radius=1.0 * u.arcsec, prefix=name + "_", max_radius_in_beams=5, max_offset_in_beams=2, #raise_for_failure=True, savepath='gaussfit') tbl = data_to_table(fit_data) tbl.rename_column("chi2/n", "chi2_n") tbl.write("gaussian_fit_table_{0}.ipac".format(name), format='ascii.ipac', overwrite=True)
def fit_source(srcID, img, img_name, band, fit_bg=False, bg_stddev_x=30, bg_stddev_y=30, bg_mean_x=0, bg_mean_y=0, zoom=1, max_offset_in_beams=1, max_radius_in_beams=5, nonconv_img=None, mask_size=1.5): #this function fits a given source, and the background #srcID : int #name of source to fit in catalogs #img : fits file #fits file with source to fit #img_name : str #name of image for the directory where the fit plots will go #band : str #band of image to fit ('B3', 'B6', or 'B7') #fit_bg : bool #if False, do not fit background gaussian #bg_stddev_x : float #eyeballed estimate of stddev of the background source in pixels #bg_stddev_y : float #same as above in y direction #bg_mean_x/y : float #pixels away from center (origin) in x/y direction for background gaussian mean guess #zoom : float #amount of zoom, values greater than 1 are zoom ins #ref_data_name = '/home/jotter/nrao/summer_research_2018/tables/dendro_ref_catalog_edited.fits' ref_data_name = '/home/jotter/nrao/summer_research_2018/tables/ref_catalog_may21_b7.fits' #ref_data_name = '/lustre/cv/observers/cv-12578/orion_disks/summer_research_2018/tables/ref_catalog_may21.fits' ref_data = Table.read(ref_data_name) fl = fits.open(img) header = fl[0].header img_data = fl[0].data.squeeze() img_wcs = WCS(header).celestial beam = radio_beam.Beam.from_fits_header(header) pixel_scale = np.abs( img_wcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg ppbeam = (beam.sr / (pixel_scale**2)).decompose().value if nonconv_img is not None: flnonconv = fits.open(nonconv_img) nonconv_header = flnonconv[0].header nonconv_beam = radio_beam.Beam.from_fits_header(nonconv_header) ppbeam = (nonconv_beam.sr / (pixel_scale**2)).decompose().value #now get ready to fit gaussians #start by setting up save directory for images gauss_save_dir = '/home/jotter/nrao/gauss_diags_may21/fitbg/' + img_name + '/' #gauss_save_dir = f'/lustre/cv/observers/cv-12578/orion_disks/gauss_diags_may21/{img_name}/' print('saving plots to ' + gauss_save_dir) if not os.path.exists(gauss_save_dir): os.makedirs(gauss_save_dir) #now make region rad = Angle(1, 'arcsecond') #radius used in region list #src_ind = np.where(ref_data['D_ID']==srcID)[0] src_ind = np.where(ref_data['B3_Seq'] == srcID)[0] ra = ref_data['RA_B3'][src_ind].data[0] dec = ref_data['DEC_B3'][src_ind].data[0] center_reg = SkyCoord(ra, dec, unit='deg', frame='icrs') reg = regions.CircleSkyRegion( center=center_reg, radius=1 * u.arcsecond, meta={ 'text': str(ref_data['B3_Seq'][src_ind].data[0]) + '_xstddev_' + str(bg_stddev_x) + '_ystddev_' + str(bg_stddev_y) }) region_list = [] #valid_inds = np.where(np.isnan(ref_data[band+'_detect']) == False)[0] for ind in range(len(ref_data)): #valid_inds: if ref_data['B3_Seq'][ind] == srcID: continue ra_i = ref_data['RA_B3'][ind] dec_i = ref_data['DEC_B3'][ind] region_i = regions.CircleSkyRegion(center=SkyCoord(ra_i, dec_i, unit='deg', frame='icrs'), radius=1 * u.arcsecond) region_list.append(region_i) #print(region_list) #print(reg) cat_r = Angle(0.5, 'arcsecond') / zoom #radius for gaussian fitting if fit_bg == True: gauss_cat, fitim_bg = bg_gaussfit( img, reg, region_list, cat_r, bg_stddev_x=bg_stddev_x, bg_stddev_y=bg_stddev_y, bg_mean_x=bg_mean_x, bg_mean_y=bg_mean_y, savepath=gauss_save_dir, max_offset_in_beams=max_offset_in_beams, max_offset_in_beams_bg=10, max_radius_in_beams=max_radius_in_beams, mask_size=mask_size) #print('gauss_cat length ',len(gauss_cat)) #k = list(gauss_cat.keys())[0] #if gauss_cat[k]['success'] == False: # gauss_cat = gaussfit_cutoutim(img, fitim_bg, reg, region_list, cat_r, savepath=gauss_save_dir, max_offset_in_beams = max_offset_in_beams, max_radius_in_beams = max_radius_in_beams) # success = gauss_cat[k]['success'] # print(F'ALTERNATIVE FIT SUCCESS: {success}') else: gauss_cat = gaussfit_catalog(img, [reg], cat_r, savepath=gauss_save_dir, max_offset_in_beams=max_offset_in_beams, max_radius_in_beams=max_radius_in_beams) img_table = Table(names=('Seq', 'fwhm_maj_' + band, 'fwhm_maj_err_' + band, 'fwhm_min_' + band, 'fwhm_min_err_' + band, 'pa_' + band, 'pa_err_' + band, 'gauss_amp_' + band, 'gauss_amp_err_' + band, 'RA_' + band, 'RA_err_' + band, 'DEC_' + band, 'DEC_err_' + band), dtype=('i4', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8')) for key in gauss_cat: img_table.add_row( (srcID, gauss_cat[key]['fwhm_major'], gauss_cat[key]['e_fwhm_major'], gauss_cat[key]['fwhm_minor'], gauss_cat[key]['e_fwhm_minor'], gauss_cat[key]['pa'], gauss_cat[key]['e_pa'], gauss_cat[key]['amplitude'], gauss_cat[key]['e_amplitude'], gauss_cat[key]['center_x'], gauss_cat[key]['e_center_x'], gauss_cat[key]['center_y'], gauss_cat[key]['e_center_y'])) #now measure deconvovled sizes and aperture flux measurements for each source ap_flux_arr = [] ap_flux_err_arr = [] fwhm_maj_deconv_arr = [] fwhm_maj_deconv_err_arr = [] fwhm_min_deconv_arr = [] fwhm_min_deconv_err_arr = [] pa_deconv_arr = [] pa_deconv_err_arr = [] snr_arr = [] for row in range( len(img_table) ): #now loop through sources in reference data and make measurements ref_ind = np.where(ref_data['B3_Seq'] == img_table['Seq'][row])[0] if True == True: #len(ref_ind > 0): measured_source_size = radio_beam.Beam( major=img_table['fwhm_maj_' + band][row] * u.arcsec, minor=img_table['fwhm_min_' + band][row] * u.arcsec, pa=(img_table['pa_' + band][row] - 90) * u.deg) try: deconv_size = measured_source_size.deconvolve(beam) fwhm_maj_deconv_arr.append(deconv_size.major.value) fwhm_min_deconv_arr.append(deconv_size.minor.value) fwhm_maj_deconv_err_arr.append(img_table['fwhm_maj_err_' + band][row]) fwhm_min_deconv_err_arr.append(img_table['fwhm_min_err_' + band][row]) pa_deconv_arr.append(deconv_size.pa.value) pa_deconv_err_arr.append(img_table['pa_err_' + band][row]) except ValueError: fwhm_maj_deconv_arr.append(np.nan) fwhm_min_deconv_arr.append(np.nan) fwhm_maj_deconv_err_arr.append(np.nan) fwhm_min_deconv_err_arr.append(np.nan) pa_deconv_arr.append(np.nan) pa_deconv_err_arr.append(np.nan) pix_major_fwhm = ( (img_table['fwhm_maj_' + band][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() pix_minor_fwhm = ( (img_table['fwhm_min_' + band][row] * u.arcsec).to(u.degree) / pixel_scale).decompose() center_coord = SkyCoord(img_table['RA_' + band][row], img_table['DEC_' + band][row], frame='icrs', unit=(u.deg, u.deg)) center_coord_pix = center_coord.to_pixel(img_wcs) center_coord_pix_reg = regions.PixCoord(center_coord_pix[0], center_coord_pix[1]) pos_ang = (img_table['pa_' + band][row] - 90) * u.deg ellipse_reg = regions.EllipsePixelRegion(center_coord_pix_reg, pix_major_fwhm.value * 2, pix_minor_fwhm.value * 2, angle=pos_ang) size = pix_major_fwhm * 2.1 ap_mask = ellipse_reg.to_mask() cutout_mask = ap_mask.cutout(img_data) aperture_flux = np.nansum(cutout_mask[ap_mask.data == 1]) / ppbeam npix = len(cutout_mask[ap_mask.data == 1]) #now make annulus for measuring background and error annulus_width = 15 #pixels annulus_radius = img_table[ 'fwhm_maj_' + band][row] * u.arcsecond #0.1*u.arcsecond annulus_radius_pix = (annulus_radius.to(u.degree) / pixel_scale).decompose() #cutout image cutout = Cutout2D(img_data, center_coord_pix, annulus_radius * 2.5, img_wcs, mode='partial') cutout_center = regions.PixCoord(cutout.center_cutout[0], cutout.center_cutout[1]) #define aperture regions for SNR innerann_reg = regions.CirclePixelRegion(cutout_center, annulus_radius_pix.value) outerann_reg = regions.CirclePixelRegion( cutout_center, annulus_radius_pix.value + annulus_width) #Make masks from aperture regions annulus_mask = mask(outerann_reg, cutout) - mask( innerann_reg, cutout) # Calculate the SNR and aperture flux sums pixels_in_annulus = cutout.data[annulus_mask.astype( 'bool')] #pixels within annulus bg_rms = median_abs_deviation(pixels_in_annulus) ap_bg_rms = bg_rms / np.sqrt( npix / ppbeam) #rms/sqrt(npix/ppbeam) - rms error per beam bg_median = np.median(pixels_in_annulus) pix_bg = bg_median * npix / ppbeam #flux corrections ap_flux_bgcorrect = aperture_flux - pix_bg ap_flux_correct = ap_flux_bgcorrect + ap_flux_bgcorrect * ( 1 - special.erf(2 * np.sqrt(np.log(2))) ) #flux correction for summing within 2*fwhm print( f'Background: {pix_bg}, Gauss amp: {img_table["gauss_amp_"+band][row]}' ) print(f'peak pixel: {np.nanmax(cutout_mask[ap_mask.data==1])}') ap_flux_err_arr.append(ap_bg_rms) ap_flux_arr.append(ap_flux_correct) snr_arr.append(img_table['gauss_amp_' + band][row] / bg_rms) cols = [ 'ap_flux_' + band, 'ap_flux_err_' + band, 'fwhm_maj_deconv_' + band, 'fwhm_maj_deconv_err_' + band, 'fwhm_min_deconv_' + band, 'fwhm_min_deconv_err_' + band, 'pa_deconv_' + band, 'pa_deconv_err_' + band, 'SNR_' + band ] arrs = [ ap_flux_arr, ap_flux_err_arr, fwhm_maj_deconv_arr, fwhm_maj_deconv_err_arr, fwhm_min_deconv_arr, fwhm_min_deconv_err_arr, pa_deconv_arr, pa_deconv_err_arr, snr_arr ] for c in range(len(cols)): img_table.add_column(Column(np.array(arrs[c])), name=cols[c]) img_table.add_column(Column(img_table['fwhm_maj_deconv_' + band] / img_table['fwhm_min_deconv_' + band]), name='ar_deconv_' + band) return img_table
warnings.filterwarnings('ignore', category=wcs.FITSFixedWarning, append=True) w51north_vla = (paths.dpath( 'W51_North_QbandAarray_cont_spws_continuum_cal_clean_2terms_robust0_wproj_selfcal9.image.tt0.pbcor.fits' )) w51north_alma = (paths.dpath('alma/W51n.cont.image.allEB.fits')) regs = regions.read_ds9(paths.rpath('w51north_protostars.reg')) reg = [r for r in regs if r.meta['text'] == '{1}'][0] fit_vla = gaussfit_catalog(w51north_vla, [ regions.PointSkyRegion(coordinates.SkyCoord( '19:23:40.117 +14:31:05.779', frame='fk5', unit=(u.hour, u.deg)), meta={'text': '1'}) ], radius=0.2 * u.arcsec, max_offset_in_beams=4, max_radius_in_beams=1.2, savepath='./', prefix='vla_source1_fit')['1'] fit_alma = gaussfit_catalog(w51north_alma, [reg], radius=0.1 * u.arcsec, savepath='./', prefix='alma_source1_fit')['1'] coord_vla = coordinates.SkyCoord(fit_vla['center_x'], fit_vla['center_y']) coord_alma = coordinates.SkyCoord(fit_alma['center_x'], fit_alma['center_y']) offset = (coord_vla.separation(coord_alma).to(u.arcsec)) print(offset) assert (offset > 0.005 * u.arcsec) and (offset < 0.006 * u.arcsec)
header['BMIN'] = 9/3600. # HACK - try setting the PA to be 45deg-ish to force # Gaussfit to rotate header['BPA'] = 45.12 fh.writeto(fn, overwrite=True) diagnostics_dir = '/Volumes/external/mgps/gaussfit_diagnostics/' prefix = regname+"_" if not os.path.exists(diagnostics_dir): diagnostics_dir = None prefix = '' gfit_dat = gaussfit_catalog(fn, reglist, radius=30*u.arcsec, max_radius_in_beams=3, max_offset_in_beams=0.5, savepath=diagnostics_dir, prefix=prefix, #debug=True, ) gfit_tbl = gaussfits_to_table(gfit_dat) # IPAC compatibility gfit_tbl.rename_column("chi2/n", "chi2_n") gfit_tbl.rename_column("Name", "SourceName") merge_tbl = join(catalog, gfit_tbl, join_type='left', keys='SourceName') extended = merge_tbl['fwhm_major'].quantity > 14*u.arcsec compact = merge_tbl['fwhm_major'].quantity < 14*u.arcsec
] columns = [ Column(name=k, data=[ fit_data[entry][k].value if hasattr( fit_data[entry][k], 'value') else fit_data[entry][k] for entry in names ], unit=(fit_data[names[0]][k].unit if hasattr( fit_data[names[0]][k], 'unit') else None)) for k in colnames ] return Table([namecol] + columns) if __name__ == "__main__": regs = regions.read_ds9(paths.rpath('cores_with_names.reg')) from files import contfilename as contfnpath fit_data = gaussfit_catalog(contfnpath, regs, savepath=paths.fpath('gaussfits')) tbl = data_to_table(fit_data) tbl.rename_column("chi2/n", "chi2_n") tbl.write(paths.tpath("gaussian_fit_table.ipac"), format='ascii.ipac', overwrite=True)
for regfn, contfn, name in ( ('w51north_protostars.reg', 'W51n_cont_uniform.image.tt0.pbcor.fits', 'NorthUniform'), ('w51north_protostars.reg', 'W51n.cont.image.allEB.fits', 'NorthRobust'), ('w51e_protostars.reg', 'W51e2_cont_uniform.image.tt0.pbcor.fits', 'W51eUniform'), ('w51e_protostars.reg', 'W51e2_cont_briggs.image.fits', 'W51eRobust'), ): regs = regions.read_ds9(paths.rpath(regfn)) contfn = paths.dpath('longbaseline/' + contfn) fit_data = gaussfit_catalog( contfn, regs, radius=0.1 * u.arcsec, prefix=name + "_", max_radius_in_beams=5, max_offset_in_beams=2, savepath=paths.fpath('longbaseline/gaussfits')) tbl = data_to_table(fit_data) tbl.rename_column("chi2/n", "chi2_n") tbl.write(paths.tpath("gaussian_fit_table_{0}.ipac".format(name)), format='ascii.ipac', overwrite=True)
fit_data[entry][k], 'value') else fit_data[entry][k] for entry in names ], unit=(fit_data[names[0]][k].unit if hasattr( fit_data[names[0]][k], 'unit') else None)) for k in colnames ] return Table([namecol] + columns) if __name__ == "__main__": regs = regions.read_ds9(rpath('contsource_approxlocations.reg')) from files import band4cont fit_data = gaussfit_catalog(band4cont, regs, savepath=fpath('gaussfits')) tbl = data_to_table(fit_data) tbl.rename_column("chi2/n", "chi2_n") tbl.write(tpath("gaussian_fit_table.ipac"), format='ascii.ipac', overwrite=True) with open(rpath('contsource_locations.reg'), 'w') as fh: fh.write("fk5\n") for reg in regs: ii = reg.meta['text'].strip("{}") crd = coordinates.SkyCoord(fit_data[str(ii)]['center_x'], fit_data[str(ii)]['center_y'], frame='fk5')