def get_image_datatab(ra, dec, width): fitsurl = geturl(ra, dec, size=int(width * 240), filters="i", format="fits") fh = fits.open(fitsurl[0]) fhead = fh[0].header wcs = WCS(fhead) fim = fh[0].data # replace NaN values with zero for display fim[numpy.isnan(fim)] = 0.0 # set contrast to something reasonable transform = AsinhStretch() + PercentileInterval(90) bfim = transform(fim) #query PS1 catalog datatab = panstarrs_query_pos(ra, dec, width) #query the table with positions and aperture pre-defined positions = SkyCoord(ra=datatab['raMean'], dec=datatab['decMean'], unit='deg') aper = SkyCircularAperture(positions, 0.5 * u.arcsec) pix_aperture = aper.to_pixel(wcs) #plot fig = plt.figure() fig.add_subplot(111, projection=wcs) #norm = ImageNormalize(stretch=SqrtStretch()) plt.imshow(bfim, cmap='Greys', origin='lower') pix_aperture.plot(color='blue', lw=0.5, alpha=0.5) plt.xlabel('RA') plt.ylabel('Dec') image = plt.savefig('test_run.jpg', dpi=1000) fits.writeto('test_run.fits', fim, fhead, overwrite=True) ascii.write(datatab, 'test_run.csv', format='csv', fast_writer=False) return datatab
def aperature_f(field, band, aper_rad=2., annu_in=3., annu_out=6.): hdu = fits.open("final/coadd_c%s_%s.fits" % (field, band)) pos_filename = os.path.join('final', 'test%s_%s.fits' % (field, 'i')) if not os.path.isfile(pos_filename): print 'sextracting the i band position for %s' % field pos_filename = sex_band(field, 'i') t7 = Table.read(pos_filename) positions = SkyCoord(t7['XWIN_WORLD'], t7['YWIN_WORLD'], frame='icrs') apertures = SkyCircularAperture(positions, r=aper_rad * u.arcsec) annulus_apertures = SkyCircularAnnulus(positions, r_in=annu_in * u.arcsec, r_out=annu_out * u.arcsec) apers = [apertures, annulus_apertures] phot_table = aperture_photometry(hdu[0], apers) phot_table2 = phot_table[np.isfinite(phot_table['aperture_sum_0'])] phot_table3 = phot_table2[np.where(phot_table2['aperture_sum_0'] > 0)] snr = phot_table3['aperture_sum_0'] / (np.sqrt( phot_table3['aperture_sum_0'])) phot_table3['snr'] = snr for name in phot_table3.colnames[1:]: phot_table3.rename_column(name, name + '_%s' % band) return phot_table3
def center_flux(self, *args, **kwargs): """ calculate the flux in the center if the mask is "annulus" or "circle" :return: the flux in the center :rtype: float """ if self._mask.shape == "annulus": pos = self._mask.position wcs = self.header inner = self._mask.rin center_mask = (SkyCircularAperture( pos, inner * u.arcsec).to_pixel(wcs).to_mask("center")) data = center_mask.multiply(self.data) data = data[center_mask.data > 0] return self._calc_flux(data, *args, **kwargs) elif self._mask.shape == "circle": data = self._mask.mask.multiply(self.data) data = data[self._mask.mask.data > 0] return self._calc_flux(data, *args, **kwargs)
def photometry(): filters = ['I', 'B', 'V', 'R'] #filter names for f in filters: All_data = Table(names=('Count', 'Error', 'Time')) file = open('photometry_' + str(sn_name) + str(f) + '.txt', 'w') super_lotis_path = '/Users/zeynepyaseminkalender/Documents/MyFiles_Pyhton/SuperLOTIS_final' date_search_path = os.path.join(super_lotis_path, '13*') search_str = os.path.join(date_search_path, str(sn_name) + str(f) + '.fits') for name in glob(search_str): date = extract_date_from_fullpath(name) final_date = convert_time(date) with fits.open(name) as analysis: z = .086 r = 1 * u.kpc / cosmo.kpc_comoving_per_arcmin(z) cordinate = SkyCoord('01:48:08.66 +37:33:29.22', unit=(u.hourangle, u.deg)) aperture = SkyCircularAperture(cordinate, r) exp_time = analysis[0].header['EXPTIME'] # error calculation data_error = np.sqrt(analysis[0].data * exp_time) / exp_time tbl = Table(aperture_photometry(analysis[0], aperture, error=data_error), names=('Count', 'Count_Error', 'x_center', 'y_center', 'center_input')) tbl.keep_columns(['Count', 'Count_Error']) count = tbl[0]['Count'] error = tbl[0]['Count_Error'] All_data.add_row((count, error, final_date)) print >> file, All_data file.close() plot(filters)
def Skyaperture_agn(coor,num,survey,data_dict, path, aperture = None): #data_dict = the dictionary {g:{}, i:{}...} data_arr, hdr_arr, wcs_arr = arrays(num,survey, path) n = len(data_arr) # = 5 bands radius = 1.5 #for sdss we havn't determined a radius yet so we'll work with a fixed one arr=np.zeros(n) for j in range(n): miss = data_arr[j] == np.array([-99]) if miss.all(): arr[j] = -99 else: try: if survey == Survey.ps1: radius = find_rad(data_dict[bands_ps1[j]],j, survey, aperture) position = SkyCoord(coor[0] , coor[1] , unit='deg', frame='icrs') aper = SkyCircularAperture(position, radius*u.arcsec) phot_table = aperture_photometry(data_arr[j], aper, wcs=wcs_arr[j]) phot_table['aperture_sum'].info.format = '%.8g' value = phot_table['aperture_sum'][0] #value in nanomaggy if (survey == Survey.ps1): if aperture == Aperture.fillfac: value = value/data_dict[bands_ps1[j]]['ApFillFac'] #when using const radius else: value = value/0.9375 #when usinf psf as radius arr[j] = value #value = 3.631*(10**(-29))*value #value in erg/sec*cm^2*Hz except: print("wasn't able to perform sky apeture to AGN "+str(num)) return arr
def create_example_frame(self, plot=True, figsize=(13, 13)): fits_files = list(self.datadir.glob('MCT*fits')) assert len(fits_files) > 0, 'No example frame fits-files found.' f = fits_files[0] f1 = pf.open(f) f2 = pf.open(f.with_suffix('.wcs')) h1 = f1[0].header.copy() h1.append(('COMMENT', '*********************')) h1.append(('COMMENT', ' WCS ')) h1.append(('COMMENT', '*********************')) h1.extend(f2[0].header, unique=True, bottom=True) f1[0].header = h1 filter = h1['filter'] f1.writeto(self._dres.joinpath( f'{self.ticname}_20{self.date}_MuSCAT2_{filter}_frame.fits'), overwrite=True) if plot: wcs = WCS(f1[0].header) data = f1[0].data.astype('d') norm = simple_norm(data, stretch='log') fig = figure(figsize=figsize, constrained_layout=True) ax = fig.add_subplot(111, projection=wcs) ax.imshow(data, origin='image', norm=norm, cmap=cm.gray_r) apts = SkyCircularAperture( self.phs[0].centroids_sky, float(self.phs[0]._flux.aperture[self.lpf.aid]) * u.pixel) apts.to_pixel(wcs).plot(color='w')
def test_photutils_sky_no_wcs(self): from photutils import SkyCircularAperture my_aper_sky = SkyCircularAperture(self.sky, 0.5 * u.arcsec) with pytest.warns(UserWarning, match='data has no valid WCS'): self.imviz.load_static_regions({'my_aper_sky_2': my_aper_sky}) self.verify_region_loaded('my_aper_sky_2', count=0) assert self.imviz.get_interactive_regions() == {}
def test_photutils_sky_has_wcs(self): from photutils import SkyCircularAperture sky = SkyCoord(ra=337.5202808, dec=-20.833333059999998, unit='deg') my_aper_sky = SkyCircularAperture(sky, 0.5 * u.arcsec) self.imviz.load_static_regions({'my_aper_sky_1': my_aper_sky}) self.verify_region_loaded('my_aper_sky_1') assert self.imviz.get_interactive_regions() == {}
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 photometry(): filters = ['I', 'B', 'V', 'R'] #filter names # create a table here for Photometry results photo_table = Table(names=('Residuals', 'Error', 'Time')) Photometry = open('photometry_' + str(sn_name) + '.txt', 'w') for f in filters: #create a txt file where the Photometry Results table will be saved #join the two paths given above search_str = os.path.join(date_search_path, str(sn_name) + str(f) + '.fits') #names will be the supernova fits files for different filters for name in glob(search_str): with fits.open(name) as analysis: N = analysis[0].header[ 'NCOMBINE'] # number of images stacked in the fit file final_date = convert_time( analysis) # The Time series must be MJD #Position of Supernova as coordinate, aperture is calculated with the coordinate cordinate = SkyCoord('01:48:08.66 +37:33:29.22', unit=(u.hourangle, u.deg)) #coordinates = SkyCoord('01:48:08.66 +37:33:29.22',unit = (u.hourangle, u.deg)) #exp_time= analysis[0].header['EXPTIME'] #data_error = np.sqrt(N*analysis[0].data) aperture = SkyCircularAperture(cordinate, r=5 * u.arcsec) annulus_apertures = SkyCircularAnnulus(cordinate, r_in=6 * u.arcsec, r_out=8 * u.arcsec) aperture_area = np.pi * 3**2 annulus_area = np.pi * (8**2 - 6**2) rawflux_table = aperture_photometry(analysis[0], aperture) bkgflux_table = aperture_photometry(analysis[0], annulus_apertures) residual_sum = rawflux_table[0]['aperture_sum'] - bkgflux_table[ 0]['aperture_sum'] * aperture_area / annulus_area error = np.sqrt(np.abs(residual_sum) * N) photo_table.add_row((residual_sum, error, final_date)) print "***** Photometry Results without Calibration ****" print photo_table print >> Photometry, photo_table Photometry.close() calibration(N)
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 simpleapphot(fileName, pos, r, rI, rO, frame='image'): '''Performs simple circular aperture photometry with local bg subtraction ''' # Check Type of pos first if not isinstance(pos, np.ndarray): pos = np.array(pos) if pos.ndim == 1: pos = pos.reshape((-1, 2)) # Create Aperture frame = frame.lower() if frame == 'image': # Create the Aperatures cirAps = CircularAperture(pos, r) annAps = CircularAnnulus(pos, rI, rO) elif frame == 'fk5': # Create Sky Apertures pos = SkyCoord(frame=frame, ra=pos[:, 0] * u.deg, dec=pos[:, 1] * u.deg) cirAps = SkyCircularAperture(pos, r * u.arcsec) annAps = SkyCircularAnnulus(pos, rI * u.arcsec, rO * u.arcsec) else: raise ValueError('Unsupported coordinate system.') # Load in the files and do photometry hdu = fits.open(fileName) cirPhotTab = aperture_photometry(hdu, cirAps) annPhotTab = aperture_photometry(hdu, annAps) if frame == 'fk5': cirAps = cirAps.to_pixel(WCS(header=hdu['SCI'].header)) annAps = annAps.to_pixel(WCS(header=hdu['SCI'].header)) hdu.close() # Get Photometry as ndarray phot = cirPhotTab['aperture_sum'].data - \ (cirAps.area()/annAps.area())*annPhotTab['aperture_sum'].data return phot
def photometry(fits_file, radius): if os.path.isfile(fits_file): hdulist = fits.open(fits_file) ra = hdulist[0].header["RA"] dec = hdulist[0].header["DEC"] wcs = WCS(fits_file) coords = [ra, dec] w = wcs.all_world2pix(ra, dec, 1) r = radius * u.kpc aperture = SkyCircularAperture(w, r * u.arcsec) exp_time = hdulist[0].header["EXPTIME"] photo_error = np.sqrt(hdulist[0].data / exp_time) photo_error = np.sqrt(hdulist[0].data / exp_time) phot_table = aperture_photometry(hdulist[0], aperture, error=photo_error) else: print("it is not a fit file")
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 }
def measure_light_in_circle(self, positions, radius, sky_coords=False): positions = np.asarray(positions) if sky_coords: wcs = self.wcs positions = SkyCoord(positions, unit='deg') apertures = SkyCircularAperture(positions, radius * u.arcsec) else: wcs = None positions -= 1 apertures = CircularAperture(positions, radius) light = {} for b in ['red', 'green', 'blue']: data = getattr(self, b + '_data') phot = aperture_photometry(data, apertures, wcs=wcs) light[b] = np.array(phot['aperture_sum']) return light['red'], light['green'], light['blue']
def set_apertures(catalog, limit=16, r=10, r_in=15.5, r_out=25): ''' From Anna Marini: get a catalog and set apertures and annulus for photometry. ''' radec = catalog['ra', 'dec', 'phot_g_mean_mag'] mask = radec['phot_g_mean_mag'] < limit radec = radec[mask] positions = SkyCoord(radec['ra'], radec['dec'], frame='fk5', unit=(u.deg, u.deg)) aperture = SkyCircularAperture(positions, r=r * u.arcsec) annulus = SkyCircularAnnulus(positions, r_in=r_in * u.arcsec, r_out=r_out * u.arcsec) apers = [aperture, annulus] return apers
def extractSpectra(fitsfile, pos, radius, axes=[0, 1, 2], smth=False, freqsmth=0, verbose=False, restfreq=115.27120, z=0.01): apertures = SkyCircularAperture(pos, r=radius * aunits.arcsec) w = WCS(fitsfile).celestial pix_aperture = apertures.to_pixel(w) header = f.open(fitsfile)[0].header cube = np.squeeze(f.open(fitsfile)[0].data).transpose(axes) df, dx, dy = np.shape(cube) if dx != dy: print('warning : image is not square, may need a transpose') mask = pix_aperture.to_mask()[0] image = mask.to_image(shape=((dx, dy))).astype('bool') freqs = np.linspace(header['CRVAL4'], header['CRVAL4'] + header['CDELT4'] * header['NAXIS4'], header['NAXIS4']) vels = Freq2Vel(x0=freqs / 1e9, z=z, restfreq=restfreq) if smth: cube = ndimage.gaussian_filter(cube, sigma=[freqsmth, 0, 0], mode='reflect')[::freqsmth, :, :] freqs = freqs[::freqsmth] vels = vels[::freqsmth] spec = np.mean(cube[:, image], axis=(1)) if verbose: print('assuming NAXIS 4 is the frequency one') return vels, freqs, spec
radec_deg[j1] = [ra_deg[j1], dec_deg[j1]] # print(j1,j2,radec_deg[j1]) ra_hhmmss[j1] = df_refstar['RefStarRA_hhmmss'][j2] dec_ddmmss[j1] = df_refstar['RefStarDEC_ddmmss'][j2] # print(i,j1,radec_deg[j1],ra_hhmmss[j1],dec_ddmmss[j1]) rmag[j1] = df_refstar['Rmag'][j2] rmag_err[j1] = df_refstar['Rmag_err'][j2] r_circle[j1] = df_refstar['R_circle_as'][j2] r_inner[j1] = df_refstar['R_inner_as'][j2] r_outer[j1] = df_refstar['R_outer_as'][j2] # position= SkyCoord(ra_deg[j1],dec_deg[j1],unit=(u.hourangle,u.deg),frame='icrs') position = SkyCoord(ra_deg[j1], dec_deg[j1], unit=(u.deg), frame='icrs') # print(position) r_circle_as = r_circle[j1] * u.arcsec # print(r_circle_as) aperture[j1] = SkyCircularAperture(position, r=r_circle_as) # print(aperture[j1]) r_inner_as = r_inner[j1] * u.arcsec r_outer_as = r_outer[j1] * u.arcsec aper_annu[j1] = SkyCircularAnnulus(position, r_inner_as, r_outer_as) # print(aper_annu[j1]) # print(aper_annu[j1].r_in) # print(aper_annu[j1].r_out) # refstarID[j1]=df_refstar['RefStarID'][j2] # refstarRA_deg[j1]=df_refstar['RefStarRA_deg'][j2] # refstarDEC_deg[j1]=df_refstar['RefStarDEC_deg'][j2] # print(refstarID[j1]) # print(refstarRA_deg[j1] # print(refstarDEC_deg[j1])
def extract_photometry(ccddata, catalog, catalog_coords, target, image_path=None, aperture_radius=2. * u.arcsec, bg_radius_in=None, bg_radius_out=None): apertures = SkyCircularAperture(catalog_coords, aperture_radius) if bg_radius_in is not None and bg_radius_out is not None: apertures = [ apertures, SkyCircularAnnulus(catalog_coords, bg_radius_in, bg_radius_out) ] photometry = aperture_photometry(ccddata, apertures) target_row = photometry[target][0] if target_row['xcenter'].value < 0. or target_row['xcenter'].value > ccddata.shape[1] or \ target_row['ycenter'].value < 0. or target_row['ycenter'].value > ccddata.shape[0]: logging.error( 'target not contained in the image (or coordinate solution is bad)' ) return if 'aperture_sum_1' in photometry.colnames: flux = photometry['aperture_sum_0'] - photometry['aperture_sum_1'] dflux = (photometry['aperture_sum_err_0']**2. + photometry['aperture_sum_err_1']**2.)**0.5 else: flux = photometry['aperture_sum'] dflux = photometry['aperture_sum_err'] photometry['aperture_mag'] = u.Magnitude(flux / ccddata.meta['exptime']) photometry['aperture_mag_err'] = 2.5 / np.log(10.) * dflux / flux photometry = hstack([catalog, photometry]) photometry['zeropoint'] = photometry['catalog_mag'] - photometry[ 'aperture_mag'].value zeropoints = photometry['zeropoint'][~target].filled(np.nan) zp = np.nanmedian(zeropoints) zperr = mad_std( zeropoints, ignore_nan=True) / np.isfinite(zeropoints).sum()**0.5 # std error target_row = photometry[target][0] mag = target_row['aperture_mag'].value + zp dmag = (target_row['aperture_mag_err'].value**2. + zperr**2.)**0.5 with open(lc_file, 'a') as f: f.write( f'{ccddata.meta["MJD-OBS"]:11.5f} {mag:6.3f} {dmag:5.3f} {zp:6.3f} {zperr:5.3f} {ccddata.meta["FILTER"]:>6s} ' f'{ccddata.meta["TELESCOP"]:>16s} {ccddata.meta["filename"]:>22s}\n' ) if image_path is not None: ax = plt.axes() mark = ',' if np.isfinite( photometry['aperture_mag']).sum() > 1000 else '.' ax.plot(photometry['aperture_mag'], photometry['catalog_mag'], ls='none', marker=mark, zorder=1, label='calibration stars') ax.plot(mag - zp, mag, ls='none', marker='*', zorder=3, label='target') yfit = np.array([21., 13.]) xfit = yfit - zp ax.plot(xfit, yfit, label=f'$Z = {zp:.2f}$ mag', zorder=2) ax.set_xlabel('Instrumental Magnitude') ax.set_ylabel('AB Magnitude') ax.legend() plt.savefig(image_path, overwrite=True) plt.savefig('latest_cal.pdf', overwrite=True) plt.close() plt.figure(figsize=(6., 6.)) imshow_norm(ccddata.data, interval=ZScaleInterval()) plt.axis('off') plt.axis('tight') plt.tight_layout(pad=0.) if isinstance(apertures, list): for aperture in apertures: aperture.to_pixel(ccddata.wcs).plot(color='r', lw=1) else: apertures.to_pixel(ccddata.wcs).plot(color='r', lw=1) image_filename = ccddata.meta['filename'].replace('.fz', '').replace( '.fits', '.png') plt.savefig(os.path.join(image_dir, image_filename), overwrite=True) plt.savefig('latest_image.png', overwrite=True) plt.close()
def flux(nddata, tbl, zeroPoint, gain, radius): """ Derive the flux and the magnitude within circular aperture Parameters ---------- nddata: numpy array Numpy array where is saved the data and the sky coordinates wcs. tbl: table Table where the first column is the id, the second the ra coordinate, the third is dec coordinate and the four the skycoordinate. zeroPoint: float Zero point of your image gain: float The gain of your image radius: float The radius of your circle in arcsec to derive the flux Return ------ Table with id, skycoord, flux, flux error, magnitude, magnitude error """ # By convention, sextractor if gain == 0.: gain = 1000000000000000000000000000. result = tbl['id', 'skycoord'] result['flux'] = float(np.size(tbl)) result['flux_err'] = float(np.size(tbl)) for i in range(np.size(tbl)): # Recover the position for each object position = tbl['skycoord'][i] if hdr['NAXIS1'] >= 50 and hdr['NAXIS2'] >= 50: # size of the background map sizeBkg = 50 # cut the mosaic in stamp to the wcs coordinate of your objects cutout = Cutout2D(nddata.data, position, (sizeBkg, sizeBkg), wcs=nddata.wcs) # Recover new data and wcs of the stamp data = cutout.data wcs = cutout.wcs else: # size of the background map sizeBkg = min(hdr['NAXIS1'], hdr['NAXIS2']) # Keep data and wcs of the initial image data = nddata.data wcs = nddata.wcs ######################### ####### Background ###### ######################### # Mask sources mask = make_source_mask(data, snr=1, npixels=3, dilate_size=3) # Derive the background and the rms image bkg = Background2D( data, int(sizeBkg / 10), filter_size=1, sigma_clip=None, bkg_estimator=SExtractorBackground(SigmaClip(sigma=2.5)), bkgrms_estimator=StdBackgroundRMS(SigmaClip(sigma=2.5)), exclude_percentile=60, mask=mask) ########################### ###### Aperture Flux ###### ########################### nddataStamp = NDData(data=data - bkg.background, wcs=wcs) # Calculate the total error error = calc_total_error(cutout.data, bkg.background_rms, gain) # Define a cicularAperture in the wcs position of your objects apertures = SkyCircularAperture(position, r=radius * u.arcsec) # Derive the flux and error flux phot_table = aperture_photometry(nddataStamp, apertures, error=error) phot_table['aperture_sum'].info.format = '%.8g' phot_table['aperture_sum_err'].info.format = '%.8g' # Recover data result['flux'][i] = phot_table['aperture_sum'][0] result['flux_err'][i] = phot_table['aperture_sum_err'][0] ########################### ######## Magnitude ######## ########################### # convert flux into magnitude result['mag'] = -2.5 * np.log10(result['flux']) + zeroPoint # convert flux error into magnitude error result['mag_err'] = 1.0857 * (result['flux_err'] / result['flux']) return result
def PDF(cutout): """ Create a pdf file with the plot of your objects in different filters Parameters ---------- cutout: list array of images N filt x N sources """ # create the pdf pdfOut = PdfPages(dirpath + 'stampPDF.pdf') # it's a sum to derive the good number of stamp p = 0 # Placement of the Id sizeId = cutout[0][0].shape # while p < np.size(cutout[0]) - 1: print(p) if np.size(cutout[0]) - p > 10: fig, axs = plt.subplots(10, len(cutout), figsize=(8.3, 11.7)) else: fig, axs = plt.subplots(np.size(cutout[0]) - p, len(cutout), figsize=(8.3, 11.7)) # Loop over the 10 sources to be include in one PDF page for k in range(10): # id of object axs[k, 0].text(-sizeId[0], sizeId[0] / 2, tbl['id'][p]) # Loop over the filters for j in range(len(cutout)): # Display the image mappa = axs[k, j].imshow(cutout[j][p].data, cmap='afmhot', origin='lower', interpolation='nearest') axs[k, j].set_title(filters[j], fontsize=5, pad=2.5) axs[k, j].get_xaxis().set_visible(False) axs[k, j].get_yaxis().set_visible(False) # Plot circular aperture at the coordinate of your object apertures = SkyCircularAperture(tbl['skycoord'][p], r=1.5 * u.arcsec) aperturesPix = apertures.to_pixel(cutout[j][p].wcs) aperturesPix.plot(color='cyan', ax=axs[k, j], lw=1, alpha=0.5) # DS9 zscale zrange = zscale.zscale(cutout[j][p].data) mappa.set_clim(zrange) # it's a sum to derive the good number of stamp if p < np.size(cutout[0]) - 1: p = p + 1 else: break # save the page plt.savefig(pdfOut, format='pdf') pdfOut.close() return
data = fits.open(fitsimage)[item].data data = np.squeeze(data) data_masked = np.ma.masked_invalid(data) return wcs, data_masked ############################################################ # main program ### Draw different regions. position = SkyCoord(dec=0.8309 * u.degree, ra=204.9906 * u.degree, frame='icrs') apertures['center']['sky'] = SkyCircularAperture(position, r=3 * u.arcsec) apertures['ring around center']['sky'] = SkyCircularAnnulus(position, r_in=3 * u.arcsec, r_out=7 * u.arcsec) position = SkyCoord(dec=0.8349 * u.degree, ra=204.9930 * u.degree, frame='icrs') apertures['northarm']['sky'] = SkyEllipticalAperture(position, a=15 * u.arcsec, b=7 * u.arcsec, theta=340 * u.degree) position = SkyCoord(dec=0.8275 * u.degree, ra=204.9884 * u.degree, frame='icrs') apertures['southarm']['sky'] = SkyEllipticalAperture(position, a=10 * u.arcsec,
def sb_at_frb(host, cut_dat: np.ndarray, cut_err: np.ndarray, wcs: WCS, fwhm=3., physical=False, min_uncert=2): """ Measure the surface brightness at an FRB location in a host galaxy Args: host (Host object): host galaxy object from frb repo cut_dat (np.ndarray): data (data from astorpy 2D Cutout object) cut_err (np.ndarray): inverse variance of data (from astropy 2D Cutout object) wcs (WCS): WCS for the cutout fwhm (float, optional): FWHM of the PSF of the image in either pixels or kpc. Defaults to 3 [pix]. physical (bool, optional): If True, FWHM is in kpc. Defaults to False. min_uncert (int, optional): Minimum localization unceratainty for the FRB, in pixels. Defaults to 2. Returns: tuple: sb_average, sb_average_err [counts/sqarcsec] """ # Generate the x,y grid of coordiantes x = np.arange(np.shape(cut_dat)[0]) y = np.arange(np.shape(cut_dat)[1]) xx, yy = np.meshgrid(x, y) coords = wcs_utils.pixel_to_skycoord(xx, yy, wcs) xfrb, yfrb = wcs_utils.skycoord_to_pixel(host.frb.coord, wcs) plate_scale = coords[0, 0].separation(coords[0, 1]).to('arcsec').value # Calculate total a, b uncertainty (FRB frame) uncerta, uncertb = host.calc_tot_uncert() # Put in pixel space uncerta /= plate_scale uncertb /= plate_scale # Set a minimum threshold uncerta = max(uncerta, min_uncert) uncertb = max(uncertb, min_uncert) # check if in ellipse -- pixel space! theta = host.frb.eellipse['theta'] in_ellipse = ( (xx - xfrb.item()) * np.cos(theta) + (yy - yfrb.item()) * np.sin(theta))**2 / (uncerta**2) + ( (xx - xfrb.item()) * np.sin(theta) - (yy - yfrb.item()) * np.cos(theta))**2 / (uncertb**2) <= 1 idx = np.where(in_ellipse) xval = xx[idx] yval = yy[idx] # x, y gal on the tilted grid (same for frb coords) xp = yval * np.cos(theta) - xval * np.sin(theta) yp = xval * np.cos(theta) + yval * np.sin(theta) xpfrb = yfrb.item() * np.cos(theta) - xfrb.item() * np.sin(theta) ypfrb = xfrb.item() * np.cos(theta) + yfrb.item() * np.sin(theta) # convert fwhm from pixels to arcsec or kpc to arcsec if physical: fwhm_as = fwhm * units.kpc * defs.frb_cosmo.arcsec_per_kpc_proper( host.z) else: fwhm_as = fwhm * plate_scale * units.arcsec # Aperture photometry at every pixel in the ellipse photom = [] photom_var = [] for i in np.arange(np.shape(idx)[1]): aper = SkyCircularAperture(coords[idx[0][i], idx[1][i]], fwhm_as) apermap = aper.to_pixel(wcs) # aperture photometry for psf-size within the galaxy photo_frb = aperture_photometry(cut_dat, apermap) photo_err = aperture_photometry(1 / cut_err, apermap) photom.append(photo_frb['aperture_sum'][0]) photom_var.append(photo_err['aperture_sum'][0]) # ff prob distribution p_ff = np.exp(-(xp - xpfrb)**2 / (2 * uncerta**2)) * np.exp(-(yp - ypfrb)**2 / (2 * uncertb**2)) f_weight = (photom / (np.pi * fwhm_as.value**2)) * p_ff # weighted photometry fvar_weight = (photom_var / (np.pi * fwhm_as.value**2)) * p_ff # weighted sigma weight_avg = np.sum(f_weight) / np.sum(p_ff) # per unit area (arcsec^2) # Errors weight_var_avg = np.sum(fvar_weight) / np.sum(p_ff) weight_err_avg = np.sqrt(weight_var_avg) return weight_avg, weight_err_avg
def main(file, right_ascension, declination, redshift, Rout_Mpc): science = fits.open(file) # open the science image header = science[0].header # define the header, in order to get the WCS image = science[0].data # create the image that will be used science.close() world_cs = WCS(header) RA = Angle(right_ascension, u.deg) # the RA, Dec for this cluster Dec = Angle(declination, u.deg) Rout = Rout_Mpc * u.Mpc # the Rout_Mpc for this cluster D_A = cosmo.angular_diameter_distance(redshift) R_max = Angle(Rout / D_A * u.rad) # maximum radius in radians position = SkyCoord(ra=RA, dec=Dec, distance=D_A) aperture = SkyCircularAperture(position, r=R_max) phot_table = aperture_photometry(image, aperture, wcs=world_cs) total_counts_per_second = phot_table['aperture_sum'][0] exposure_time = header['EXPOSURE'] # exposure time in seconds minimum_necessary_counts = 20000 if (total_counts_per_second * exposure_time) < minimum_necessary_counts: with open('insufficient.txt', 'w') as file: file.write("Actual counts: " + str(total_counts_per_second * exposure_time)) return "skip" else: roi_sky = ('# Region file format: DS9 version 4.1\n' + 'global width=1\n' + 'fk5\n') roi_sky += ("circle(" + RA.to_string(unit=u.hour, sep=':') + "," + Dec.to_string(unit=u.degree, sep=':') + "," + str(R_max.to(u.arcsec).value) + '")\n') box_sky = ('# Region file format: DS9 version 4.1\n' + 'global width=1\n' + 'fk5\n') box_sky += ("box(" + RA.to_string(unit=u.hour, sep=':') + "," + Dec.to_string(unit=u.degree, sep=':') + "," + str(4 * R_max.to(u.arcsec).value) + '"' + "," + str(4 * R_max.to(u.arcsec).value) + '",360)\n') with open('roi_sky.reg', 'w') as file: file.write(roi_sky) # create the roi_sky.reg file for further use with open('box_sky.reg', 'w') as file: file.write(box_sky) # save square region with l=w=2*R_max # http://cxc.harvard.edu/ciao/ahelp/dmmakereg.html subprocess.run("punlearn dmmakereg", shell=True) subprocess.run("dmmakereg 'region(roi_sky.reg)' roi_phys.reg " + "kernel=ascii wcsfile=merged_2/broad_flux.img", shell=True) # take the roi_sky.reg file and create a # CIAO physical roi_phys.reg file subprocess.run("dmmakereg 'region(box_sky.reg)' box_phys.reg " + "kernel=ascii wcsfile=merged_2/broad_flux.img", shell=True) # take the box_sky.reg file and create a # CIAO physical box_phys.reg file return "sufficient"
# fitsimage=imageDir+'12CO10/NGC5258_12CO10_uvrange_pbcor_cube_masked.fits' fitsimage = ratioDir + 'NGC5258_12CO10_combine_contsub_uvrange_smooth_masked_pbcor_mom0.fits' wcs = fits_import(fitsimage)[0] data10_masked = fits_import(fitsimage)[1] # 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)
print(idx_fitsheader) print(fits_ori) print(fits_ori[idx_fitsheader]) n_idx = len(idx_fitsheader) Rmag0 = np.array([0.] * n_idx) #sys.exit(0) r_circle = 12. r_circle_as = r_circle * u.arcsec r_inner = 22. r_outer = 32. r_inner_as = r_inner * u.arcsec r_outer_as = r_outer * u.arcsec aperture = SkyCircularAperture(positions, r_circle_as) #print(aperture) r_as = aperture.r print('r_as =', r_as) k = 0 for i in idx_fitsheader: print('-----------------------') print('idx', i, ') ID =', ID[i], ', #', k) fits_root = fits_ori[i].split('.', -1)[0].split('_calib', -1)[0] fits_calib = fits_root + '_calib.fits' print(fits_calib) #print(fits_root) #print(fits_calib) #print(fits_ori) # sys.exit(0)
def qphot(data, coord, rad, skyradin, skyradout, wcs=None, calfctr=None, skycoord=None, unit='Jy', error=None, filter=None): if is_pix_coord(coord): coord = [np.float(coord[0]), np.float(coord[1])] aperture = CircularAperture(coord, r=rad) else: coord = SkyCoord(' '.join(coord), unit=(u.hourangle, u.deg), frame='icrs') aperture = SkyCircularAperture(coord, r=rad * u.arcsec) if skycoord: if is_pix_coord(skycoord): scoord = [np.float(skycoord[0]), np.float(skycoord[1])] annulus = CircularAnnulus(scoord, skyradin, skyradout) else: scoord = SkyCoord(' '.join(skycoord), unit=(u.hourangle, u.deg), frame='icrs') annulus = SkyCircularAnnulus(scoord, skyradin * u.arcsec, skyradout * u.arcsec) else: if isinstance(coord, SkyCoord): annulus = SkyCircularAnnulus(coord, skyradin * u.arcsec, skyradout * u.arcsec) else: annulus = CircularAnnulus(coord, skyradin, skyradout) #mask out nans or negative mask = np.logical_or(np.isnan(data), data < 0.) apflux = aperture_photometry(data, aperture, wcs=wcs, error=error, mask=mask) skyflux = aperture_photometry(data, annulus, wcs=wcs, error=error, mask=mask) phot_table = hstack([apflux, skyflux], table_names=['src', 'sky']) #calculate mean local background in annulus if isinstance(annulus, SkyCircularAnnulus): sky_area = annulus.to_pixel(wcs).area() else: sky_area = annulus.area() if isinstance(aperture, SkyCircularAperture): src_area = aperture.to_pixel(wcs).area() else: src_area = aperture.area() sky_mean = phot_table['aperture_sum_sky'] / sky_area sky_sum = sky_mean * src_area final_sum = phot_table['aperture_sum_src'] - sky_sum phot_table['residual_aperture_sum'] = final_sum phot_table['residual_aperture_sum'].unit = unit phot_table['aperture_area_sky'] = sky_area phot_table['aperture_area_src'] = src_area phot_table['aperture_mean_sky'] = sky_mean phot_table['aperture_mean_sky'].unit = unit phot_table['aperture_rad_src'] = rad phot_table['aperture_irad_sky'] = skyradin phot_table['aperture_orad_sky'] = skyradout phot_table['aperture_area_sky'].unit = u.pix**2 phot_table['aperture_area_src'].unit = u.pix**2 if error is not None: src_err = phot_table['aperture_sum_err_src'] sky_err = phot_table['aperture_sum_err_sky'] src_var = src_err / phot_table['residual_aperture_sum'] sky_var = sky_err / sky_sum color_err = 0. # 10 percent photoerr color_var = color_err * phot_table['residual_aperture_sum'] phot_table['residual_aperture_err'] = np.sqrt(src_var**2 + sky_var**2 + color_var**2) else: color_err = 0.07 # 7 percent photoerr color_var = color_err * sky_sum phot_table.add_column( Column([color_var for x in phot_table], name='residual_aperture_err')) phot_table.remove_columns( ['xcenter_src', 'ycenter_src', 'xcenter_sky', 'ycenter_sky']) if 'center_input' in phot_table.colnames: phot_table.remove_columns('center_input') if 'center_input_src' in phot_table.colnames: phot_table.remove_columns('center_input_src') if 'center_input_sky' in phot_table.colnames: phot_table.remove_columns('center_input_sky') if isinstance(coord, SkyCoord): phot_table['xcen'], phot_table['ycen'] = wcs2pix(coord, wcs) phot_table['ra'], phot_table['dec'] = coord.to_string('hmsdms', sep=':').split() else: phot_table['xcen'] = coord[0] phot_table['ycen'] = coord[1] if skycoord: if isinstance(scoord, SkyCoord): phot_table['xcensky'], phot_table['ycensky'] = wcs2pix(scoord, wcs) phot_table['rasky'], phot_table['decsky'] = scoord.to_string( 'hmsdms', sep=':').split() else: phot_table['xcensky'] = scoord[0] phot_table['ycensky'] = scoord[1] if wcs: if 'ra' not in phot_table.colnames: ra, dec = pix2wcs(coord, wcs) phot_table['ra'] = ra phot_table['dec'] = dec if skycoord: if 'rasky' not in phot_table.colnames: skyra, skydec = pix2wcs(scoord, wcs) phot_table['rasky'] = skyra phot_table['decsky'] = skydec if calfctr: flux = phot_table['residual_aperture_sum'] / calfctr phot_table.add_column(Column(flux, name='ap_flux', unit=unit)) #if error is not None: fluxerr = phot_table['residual_aperture_err'] / calfctr phot_table.add_column(Column(fluxerr, name='ap_err', unit=unit)) if filter: phot_table['filter'] = str(filter) return phot_table
from regions import read_ds9 fitsimage = imageDir + 'mass_map.fits' hdr = fits.open(fitsimage)[0].header wcs = fits_import(fitsimage)[0] mass = fits_import(fitsimage)[1] # file=regionDir+'stellar_total.reg' # whole_star=read_ds9(file)[0] # wholestar_pix=whole_star.to_pixel(wcs) # whole_masked=Apmask_convert(wholestar_pix, mass) # SM=np.ma.sum(whole_masked)*(480*0.3)**2 radius = 17.53 # SDSS petrosian radius for NGC 5257 in arcsec. center = position aperture_whole = SkyCircularAperture(center, radius * u.arcsec) aperture_whole_pix = aperture_whole.to_pixel(wcs=wcs) aperture_whole_masked = Apmask_convert(aperture_whole_pix, mass) SM = np.ma.sum(aperture_whole_masked) * (480 * 0.3)**2 fig = plt.figure() plt.imshow(mass, origin='lower') aperture_whole_pix.plot(color='red') #### check total stellar mass flux_36 = 19448.31 * 1e6 / (4.25e10) * 0.3**2 flux_45 = 13959 * 1e6 / (4.25e10) * 0.3**2 Mstar_total = mass_calc(flux_36, flux_45)
# # find the shape to measure the flux # wcs=fits_import(fitsimage)[0] # data=fits_import(fitsimage)[1] # flux measured from original image via casa. flux_33GHz = 2.16e-3 error = 1.1e-5 / 3.4e-4 * flux_33GHz # compare to the smoothed image filename = imageDir + 'NGC5258_33GHz_pbcor_smooth.fits' wcs_33GHz = fits_import(filename)[0] data_33GHz = fits_import(filename)[1] ra = (13 * u.degree + 39 * u.arcmin + 57.14 * u.arcsec) * 15 dec = 49 * u.arcmin + 44.309 * u.arcsec position = SkyCoord(dec=dec, ra=ra, frame='icrs') southarm_sky = SkyCircularAperture(positions=position, r=3 * ratio * u.arcsec) southarm_pix = southarm_sky.to_pixel(wcs_33GHz) flux = aperture_photometry(data_33GHz, apertures=southarm_pix)['aperture_sum'][0] flux = float(flux / (beamarea / pixsize)) freq = 33 SFR_33GHz = sfr_radio(flux_33GHz, freq, d) df['region']['33GHz'] = 'south' df['flux']['33GHz'] = flux_33GHz df['SFR']['33GHz'] = SFR_33GHz df['uncertainty']['33GHz'] = error / flux_33GHz * SFR_33GHz fig = plt.figure() plt.imshow(data_33GHz, origin='lower')
def calc_radial_profile(fitsfile, center, rstart, rend, rstep, verbose=False, detmaskfile=None, plot=True): """ Utility function to calculate the radial profile from an image `fitsfile` at a `center` """ # if (not os.path.isfile(fitsfile)): print(f"ERROR. FITS file {fitsfile} not found. Cannot continue.") return None # qhdu = fits.open(fitsfile) wcs = WCS(qhdu[0].header) # # if detmaskfile is provided then will use it for detector mask # doMask = False if (detmaskfile != None): if (not os.path.isfile(detmaskfile)): print(f"Warning. Detector mask file {detmaskfile} not found. Will not use detector mask!") doMask = False else: det = fits.open(detmaskfile) detmask = det['MASK'] # need the WCS wcs_det = WCS(detmask.header) doMask = True # if (not isinstance(center, SkyCoord)): print(f"ERROR: the input radial profile centre is not SkyCoord object. Cannot continue.") return None # j = 0 rx = rstart counts = [] counts_err = [] rmid = [] # emtpy = False while rx < rend: r0 = rstart + rstep * j rx = rstart + rstep * (j + 1) # the mid point, can be better the mid area point rmid.append((r0.value + rx.value) / 2.0) if (j == 0): xap = SkyCircularAperture(center, rx) photo = aperture_photometry(qhdu[0].data, xap, wcs=wcs) if (doMask): masked = aperture_photometry(detmask.data, xap, wcs=wcs_det) else: xap = SkyCircularAnnulus(center, r0, rx) photo = aperture_photometry(qhdu[0].data, xap, wcs=wcs) if (doMask): masked = aperture_photometry(detmask.data, xap, wcs=wcs_det) # ap_area = xap.to_pixel(wcs).area good_area = ap_area if (doMask): good_area = masked['aperture_sum'][0] # compare the two annuli areas: with and without bad pixels if (verbose): print( f"Annulus: {r0:.2f},{rx:.2f},geometric area: {ap_area:.1f} pixels,non-masked area {good_area:.1f} pixels, ratio: {ap_area / good_area:.2f}") # taking into account the masked pixels if (good_area == 0.0): counts.append(float('nan')) counts_err.append(float('nan')) else: counts.append(photo['aperture_sum'][0] / good_area) counts_err.append(np.sqrt(photo['aperture_sum'][0]) / good_area) j += 1 # # convert the results in numpy arrays # rmid = np.array(rmid) counts = np.array(counts) counts_err = np.array(counts_err) # # convert per pixel to per arcsec^2 pix_area = utils.proj_plane_pixel_area(wcs) * 3600.0 * 3600.0 # in arcsec^2 counts = counts / pix_area counts_err = counts_err / pix_area # if (plot): fig, ax = plt.subplots(figsize=(10, 8)) ax.errorbar(rmid, counts, xerr=rstep.value / 2.0, yerr=counts_err) ax.set_xscale('linear') ax.set_yscale('log') ax.set_xlabel('Radial distance (arcsec)') ax.set_ylabel(r'Counts/arcsec$^2$') ax.grid() ax.set_title(f"Radial profile"); qhdu.close() if (doMask): det.close() return rmid, counts, counts_err