def measure_aper_flux(hdu, aper): # create mask (set True for where you want to mask) im_mask = im == 0 # define circular aperture and annulus aperture for background subtraction aper = SkyCircularAperture(coords, r=radius) aper_annulus = SkyCircularAnnulus(coords, annulus[0], annulus[1]) mask = aper_annulus.to_pixel(w).to_mask(method="center").data annulus_data = aper_annulus.to_pixel(w).to_mask( method="center").multiply(im) annulus_data_1d = annulus_data[mask > 0] annulus_mask = aper_annulus.to_pixel(w).to_mask( method="center").multiply(im_mask) annulus_mask_1d = annulus_mask[mask > 0] # determine fractional fiber coverage apcor_im = aper.to_pixel(w).to_mask( method="center").multiply(im_mask) / aper.to_pixel(w).to_mask( method="center").multiply(np.ones_like(im)) apcor = np.sum(apcor_im == 0) / np.sum(np.isfinite(apcor_im)) # get median and standard deviation in background mean_sigclip, median_sigclip, stddev_sigclip = sigma_clipped_stats( annulus_data_1d, mask=annulus_mask_1d) bkg_median = median_sigclip * aper.to_pixel(w).area * apcor bkg_stddev = stddev_sigclip * aper.to_pixel(w).area * apcor phottable = aperture_photometry( hdu[0].data, [aper, aper_annulus], error=hdu[1].data, mask=im_mask, wcs=wcs.WCS(hdu[0].header), ) if np.abs(bkg_median) > 2 * bkg_stddev: flux = (phottable["aperture_sum_0"][0] - bkg_median) * u.Unit("10^-17 erg cm-2 s-1") else: flux = (phottable["aperture_sum_0"][0]) * u.Unit("10^-17 erg cm-2 s-1") flux_err = phottable["aperture_sum_err_0"][0] * u.Unit( "10^-17 erg cm-2 s-1") if plot: plt.subplot(111, projection=w) plt.imshow(im, vmin=0 * stddev_sigclip, vmax=3 * stddev_sigclip) aper.to_pixel(w).plot(color="white") # for SkyCircularAperture aper_annulus.to_pixel(w).plot(color="red", linestyle="dashed") plt.xlabel("RA") plt.ylabel("Dec") plt.colorbar() if plottitle is not None: plt.title(plottitle) return flux, flux_err, bkg_stddev * u.Unit("10^-17 erg cm-2 s-1"), apcor
def get_photometry_ingredients(fits_file, RAs, DECs, aperture_radii, annuli_inner_radii, annuli_outer_radii): # Get data, wcs data, h = fits.getdata(fits_file, header=True) w = WCS(h) # Define positions where aperture photometry will be performed positions = SkyCoord(ra=RAs, dec=DECs, unit='deg') # Create apertures at positions for photometry aperture_sky = [ SkyCircularAperture(positions, r=r) for r in aperture_radii ] # Turn apertures defined in sky coordinates into pixel coordinates aperture_pixel = [a_sky.to_pixel(wcs=w) for a_sky in aperture_sky] # Perform aperture photometry phot = aperture_photometry(data, aperture_pixel) # Get out Array of aperture sums and areas aperture_sums = [] aperture_areas = [] for ii in range(len(aperture_radii)): aperture_sums.append(phot['aperture_sum_' + str(ii)]) aperture_areas.append(aperture_pixel[ii].area) background_medians = [] # Get background medians for r_inner, r_outer in zip(annuli_inner_radii, annuli_outer_radii): # Define annulus aperture annulus_aperture_sky = SkyCircularAnnulus(positions, r_in=r_inner, r_out=r_outer) # Turn annulus defined in sky coordinates to pixel coordinates annulus_masks_pixel = annulus_aperture_sky.to_pixel(wcs=w) # Define annuli masks to get annuli values from data: annulus_masks = annulus_masks_pixel.to_mask(method='center') # Get median background value around each apperture position bkg_median = [] for mask in annulus_masks: annulus_data = mask.multiply(data) annulus_data_1d = annulus_data[mask.data > 0] _, median_sigclip, _ = sigma_clipped_stats(annulus_data_1d) bkg_median.append(median_sigclip) bkg_median = np.array(bkg_median) background_medians.append(bkg_median) return np.array(aperture_sums), np.array(aperture_areas), np.array( background_medians)
def ap_phot(inp_img, rad_ap, rad_sky_i, rad_sky_o, show_plot=True): # Define Aperture Pars =========== ap = SkyCircularAperture(inp_img['coords_sky'], r=rad_ap) # Roughly WISE4 PSF sky = SkyCircularAnnulus(inp_img['coords_sky'], r_in=rad_sky_i, r_out=rad_sky_o) ap_px = ap.to_pixel(wcs=inp_img['wcs']) sky_px = sky.to_pixel(wcs=inp_img['wcs']) # Perform Photometry ============= phot_dat = aperture_photometry(inp_img['data'], ap, wcs=inp_img['wcs']) phot_sky = aperture_photometry(inp_img['data'], sky, wcs=inp_img['wcs']) bkg_mean = phot_sky['aperture_sum'] / sky_px.area() phot_dat['Phot'] = phot_dat['aperture_sum'] - (bkg_mean * ap_px.area()) # Compute S/N ==================== sky_stats = sample_comp.get_photmask_stats(sky_px, inp_img=inp_img['data']) ap__stats = sample_comp.get_photmask_stats(ap_px, inp_img=inp_img['data']) phot_dat['SN'] = (ap__stats['max'] - sky_stats['mean']) / sky_stats['std'] for col in ['aperture_sum', 'Phot', 'SN']: phot_dat[col].format = '10.2f' if show_plot: fig = plt.figure(figsize=[7, 7]) ax = plt.subplot(111) img = ax.imshow(inp_img['data'], origin='lower', cmap='viridis') ap_px.plot() sky_px.plot(color='red') plt.show() return { 'phot_tab': phot_dat, 'phot_ap_px': ap_px, 'phot_sky_px': sky_px }
# phot_table = aperture_photometry(imdata, aperture,wcs=wcs) phot_table = aperture_photometry(imdata, aperture_pix) # print(phot_table) # print(phot_table.colnames) # print(phot_table['sky_center']) # print(phot_table['xcenter']) # print(phot_table['ycenter']) aper_sum = phot_table['aperture_sum'] phot_table[ 'aperture_sum'].info.format = '%.8g' # for consistent table output aper_annu = SkyCircularAnnulus(positions, r_inner_as, r_outer_as) # print(aper_annu) # print(aper_annu.r_in) # print(aper_annu.r_out) aper_annu_pix = aper_annu.to_pixel(wcs) # print(aper_annu_pix) r_in_annu_pix = aper_annu_pix.r_in r_out_annu_pix = aper_annu_pix.r_out # print(r_in_annu_pix,r_out_annu_pix) apper = [aperture_pix, aper_annu_pix] phot_annu_table = aperture_photometry(imdata, apper) # print(phot_annu_table) # print(phot_annu_table.colnames) aper_annu_sum0 = phot_annu_table['aperture_sum_0'] # print(aper_annu_sum0) aper_annu_sum1 = phot_annu_table['aperture_sum_1'] # print(aper_annu_sum1) bkg_mean = phot_annu_table['aperture_sum_1'] / aper_annu_pix.area # print(bkg_mean)
# import the channel used map. # fitsimage='NGC5258_12CO10_combine_uvrange_smooth_regrid21_nchan.fits' # chans=fits_import(fitsimage)[1] chans = 50 chans_10 = chans # define the aperture position = SkyCoord(dec=0.8309 * u.degree, ra=204.9906 * u.degree, frame='icrs') center_sky = SkyCircularAperture(position, r=3 * u.arcsec) center_pix = center_sky.to_pixel(wcs=wcs) apertures['center'] = center_pix ring_sky = SkyCircularAnnulus(position, r_in=3 * u.arcsec, r_out=7 * u.arcsec) ring_pix = ring_sky.to_pixel(wcs=wcs) apertures['ring'] = ring_pix position = SkyCoord(dec=0.8340 * u.degree, ra=204.9935 * u.degree, frame='icrs') northarm_sky = SkyEllipticalAperture(position, a=13 * u.arcsec, b=4 * u.arcsec, theta=185 * u.degree) northarm_pix = northarm_sky.to_pixel(wcs=wcs) apertures['northarm'] = northarm_pix position = SkyCoord(dec=0.8283 * u.degree, ra=204.9882 * u.degree, frame='icrs')
def app_phot(self, imagefile, ras, decs, fwhm, plot=False, save=False): ''' Computes the aperture photometry on the image, for the coordinates given. Parameters ---------- imagefile : str The name of the fits file with the image. ras : array Array of floats with the RA positions for which aperture photometry is needed. decs : array Array of floats with the DEC positions for which aperture photometry is needed. fwhm : float Average FWHM of the field used to compute the aperture. plot : boolean Shall the apertures be plotted in the plot directory? save : boolean Save the aperture measurement to a file. Returns ------- phot : QTable A table of the photometry with the following columns: 'id': The source ID. 'xcenter', 'ycenter': The x and y pixel coordinates of the input aperture center(s). 'celestial_center': 'aperture_sum': The sum of the values within the aperture. 'aperture_sum_err': The corresponding uncertainty in the 'aperture_sum' values. Returned only if the input error is not None. ''' data = fits.open(imagefile)[self.ext].data filt = fitsutils.get_par(imagefile, 'FILTER', self.ext) mjd = Time(fitsutils.get_par(imagefile, "DATE-OBS", ext=self.ext)).mjd zp = fitsutils.get_par(imagefile, 'ZP', self.ext) color = fitsutils.get_par(imagefile, 'COLOR', self.ext) kcoef = fitsutils.get_par(imagefile, 'KCOEF', self.ext) zperr = fitsutils.get_par(imagefile, 'ZPERR', self.ext) if zp is None: zp = 0 if zperr is None: zperr = 0 wcs = astropy.wcs.WCS(fits.open(imagefile)[self.ext].header) positions = SkyCoord(ras*u.deg, decs*u.deg, frame='icrs') # Set aperture radius to three times the fwhm radius aperture_rad = np.median(fwhm)*2* u.arcsec aperture = SkyCircularAperture(positions, r=aperture_rad) annulus_apertures = SkyCircularAnnulus(positions, r_in=aperture_rad*2, r_out=aperture_rad*4) #Convert to pixels pix_aperture = aperture.to_pixel(wcs) pix_annulus = annulus_apertures.to_pixel(wcs) pix_annulus_masks = pix_annulus.to_mask(method='center') #Plot apertures from astropy.visualization import simple_norm try: if np.ndim(ras) == 0: c = wcs.wcs_world2pix(np.array([[ras, decs]]), 0) else: c = wcs.wcs_world2pix(np.array([ras, decs]).T, 0) except ValueError: self.logger.error('The vectors of RAs, DECs could not be converted into pixels using the WCS!') self.logger.error(str(np.array([ras, decs]).T)) if plot: x = c[:,0] y = c[:,1] plt.figure(figsize=(10,10)) norm = simple_norm(data, 'sqrt', percent=99) plt.imshow(data, norm=norm) pix_aperture.plot(color='white', lw=2) pix_annulus.plot(color='red', lw=2) plt.xlim(x[0]-200, x[0]+200) plt.ylim(y[0]-200, y[0]+200) plt.title('Apertures for filter %s'%filt) plt.savefig(os.path.join(self._plotpath, "apertures_cutout_%s.png"%os.path.basename(imagefile))) plt.clf() #Divide each pixel in 5 subpixels to make apertures apers = [pix_aperture, pix_annulus] phot_table = aperture_photometry(data, apers, method='subpixel', subpixels=5) for col in phot_table.colnames: phot_table[col].info.format = '%.8g' # for consistent table output bkg_median = [] std_counts = [] for mask in pix_annulus_masks: annulus_data = mask.multiply(data) annulus_data_1d = annulus_data[mask.data > 0] _, median_sigclip, stdv_clip = sigma_clipped_stats(annulus_data_1d) bkg_median.append(median_sigclip) std_counts.append(stdv_clip) bkg_median = np.array(bkg_median) std_counts = np.array(std_counts) phot = aperture_photometry(data, pix_aperture) phot['annulus_median'] = bkg_median phot['annulus_std'] = std_counts phot['aper_bkg'] = bkg_median * pix_aperture.area() phot['aper_sum_bkgsub'] = phot['aperture_sum'] - phot['aper_bkg'] # Flux = Gain * Counts / Exptime. exptime = fitsutils.get_par(imagefile, 'EXPTIME', self.ext) gain = fitsutils.get_par(imagefile, self.gain_keyword, self.ext) flux = gain * phot['aper_sum_bkgsub'] / exptime inst_mag = -2.5*np.log10(flux) phot['flux'] = flux phot['inst_mag'] = inst_mag #Noise is the poisson noise of the source plus the background noise for the extracted area err = np.sqrt (flux + pix_aperture.area() * std_counts**2) #Transform pixels to magnitudes flux2 = gain * (phot['aper_sum_bkgsub']+err) / exptime inst_mag2 = -2.5*np.log10(flux2) errmag = np.abs(inst_mag2 - inst_mag) phot['err_counts'] = err phot['err_mag'] = errmag for col in phot.colnames: phot[col].info.format = '%.8g' # for consistent table output if save: appfile = os.path.join(self._photpath, fitsutils.get_par(imagefile, "OBJECT", self.ext)+".app.phot.txt") self.logger.info('Creating aperture photometry out file as %s'%appfile) #Save the photometry into a file if (not os.path.isfile(appfile)): with open(appfile, 'w') as f: f.write("mjd filter instr_mag zp zperr color kcoef mag magerr\n") with open(appfile, 'a') as f: self.logger.info('Adding aperture photometry to file %s'%appfile) f.write("%.3f %s %.4f %.4f %.4f %s %.4f %.4f %.4f\n"%(mjd, filt, phot['inst_mag'].data[0], \ zp, zperr, color, kcoef, phot['inst_mag'].data[0]+ zp, phot['err_mag'].data[0])) return phot
def plot_image(self, data, wcs, coords=None): """ convience function to plot data on a wcs projection Input: data - the data array wcs - the WCS object coords - the coordinates of the object for plotting (1x2 array, optional) """ # set up the plot fig, axs = plt.subplots(1, 1, figsize=(8, 8), subplot_kw={'projection': wcs}) # set up limits of the colour scale for plotting vmin = 1e-1 vmax = np.max(data) * 0.9 # plot axs.imshow(data, cmap='magma', interpolation='nearest', origin='lower', norm=LogNorm(vmin=vmin, vmax=vmax)) #axs.scatter(coords[0], coords[1], transform=axs.get_transform('fk5'), s=20000, lw=2, # edgecolor='white', facecolor='none') # define the apertures to plot (these are the same as in other functions) # SNR position = SkyCoord(self.ra_deg * u.degree, self.dec_deg * u.degree, frame='icrs') snr_aperture = SkyCircularAperture(position, r=self.radius * u.arcsec) snr_pix_aperture = snr_aperture.to_pixel(wcs) snr_pix_aperture.plot(color='white', lw=5, alpha=1.0) # BKG r = self.radius * u.arcsec r_in = r + (40. * u.arcsec) r_out = r + (100. * u.arcsec) bkg_ap = SkyCircularAnnulus(position, r_in=r_in, r_out=r_out) bkg_ap_pix = bkg_ap.to_pixel(wcs) bkg_ap_pix.plot(color='red', lw=3, ls='--', alpha=0.9) # MIRI Imager r = self.radius * u.arcsec r_in = r - (37. * u.arcsec) r_out = r + (37. * u.arcsec) arc_ap = SkyCircularAnnulus(position, r_in=r_in, r_out=r_out) arc_ap_pix = arc_ap.to_pixel(wcs) arc_ap_pix.plot(color='cyan', lw=3, ls=':', alpha=0.9) axs.set_facecolor('black') axs.coords.grid(True, color='white', ls='dotted') axs.coords[0].set_axislabel('Right Ascension (J2000)') axs.coords[1].set_axislabel('Declination (J2000)') # indicative MIRI FOV x = Angle(self.radius, u.arcsec) y = x.degree t3_pos = SkyCoord((self.ra_deg) * u.degree, (self.dec_deg + y) * u.degree, frame='icrs') ap3 = SkyRectangularAperture(t3_pos, 74 * u.arcsec, 113 * u.arcsec, 0 * u.degree) ap3_pix = ap3.to_pixel(wcs) ap3_pix.plot(color='yellow', lw=3, ls='-', alpha=0.9) axs.set_facecolor('black') axs.coords.grid(True, color='white', ls='dotted') axs.coords[0].set_axislabel('Right Ascension (J2000)') axs.coords[1].set_axislabel('Declination (J2000)') # display the plot plt.tight_layout() # save as a pdf plot_name = os.path.join( str(self.name), str(self.name) + '_' + str(self.wavelength) + '.pdf') try: os.remove(plot_name) except: pass fig.savefig(plot_name, dpi=200)