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')
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
            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)
Ejemplo n.º 13
0
    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')