def get_sky_from_annulus(self, r_in=3, r_out=5, units='arcsec'): """ Measure the sky flux with aperture photometry in an annulus. :param r_in, r_out: float inner, outer radius of the sky annulus :param units: 'arcsec' or 'pixels' units for the radii. :return: skyval : the measured average sky brightness per pixel. """ self.skyxy = [self.x_0, self.y_0] if units.lower()=='arcsec': r_in = r_in / self.pixscale r_out = r_out / self.pixscale elif not units.lower().startswith('pix'): raise RuntimeError('Unknown unit %s'%units) skyannulus = CircularAnnulus(self.skyxy, r_in=r_in, r_out=r_out) phot_table = aperture_photometry( self.imdat, skyannulus, error=None, mask=None, method=u'exact', subpixels=5, unit=None, wcs=None) skyvaltot = phot_table['aperture_sum'] self.skyannpix = [r_in, r_out] self.skyvalperpix = skyvaltot / skyannulus.area() # TODO: compute the error properly self.skyerr = 0.0 return
def _aper_local_background(self): """ Estimate the local background and error using a circular annulus aperture. The local backround is the sigma-clipped median value in the annulus. The background error is the standard error of the median, sqrt(pi / 2N) * std. """ bkg_aper = CircularAnnulus( self.xypos, self.aperture_params['bkg_aperture_inner_radius'], self.aperture_params['bkg_aperture_outer_radius']) bkg_aper_masks = bkg_aper.to_mask(method='center') sigclip = SigmaClip(sigma=3) nvalues = [] bkg_median = [] bkg_std = [] for mask in bkg_aper_masks: bkg_data = mask.multiply(self.model.data.value) bkg_data_1d = bkg_data[mask.data > 0] values = sigclip(bkg_data_1d, masked=False) nvalues.append(values.size) bkg_median.append(np.median(values)) bkg_std.append(np.std(values)) nvalues = np.array(nvalues) bkg_median = np.array(bkg_median) # standard error of the median bkg_median_err = np.sqrt(np.pi / (2. * nvalues)) * np.array(bkg_std) bkg_median <<= self.model.data.unit bkg_median_err <<= self.model.data.unit return bkg_median, bkg_median_err
def first_cc_val_neg(param, *args): center_x, center_y = param data = args[0] radius_size = args[1] ones = np.array([[1] * 600] * 600) center_ap = CircularAperture([center_x, center_y], radius_size) center_area = center_ap.area center_mask = center_ap.to_mask(method='exact') center_data = center_mask.multiply(data) center_weights = center_mask.multiply(ones) center_std = twoD_weighted_std(center_data, center_weights) center_val = (np.sum(center_data)) / center_area + 5 * center_std first_ap = CircularAnnulus([center_x, center_y], r_in=radius_size, r_out=2 * radius_size) first_area = first_ap.area first_mask = first_ap.to_mask(method='exact') first_data = first_mask.multiply(data) first_weights = first_mask.multiply(ones) first_std = twoD_weighted_std(first_data, first_weights) first_val = (np.sum(first_data)) / first_area + 5 * first_std result = (-2.5 * math.log(first_val / center_val, 10)) return -1 * (result)
def redoAperturePhotometry(catalog, imagedata, aperture, annulus_inner, annulus_outer): """ Recalculate the FLUX column off a fits / BANZAI CAT extension based on operature photometry. """ _logger.info("redoing aperture photometry") positions = [(catalog['x'][ii], catalog['y'][ii]) for ii in range(len(catalog['x']))] apertures = CircularAperture(positions, r=aperture) sky_apertures = CircularAnnulus(positions, r_in=annulus_inner, r_out=annulus_outer) sky_apertures_masks = sky_apertures.to_mask(method='center') bkg_median = [] for mask in sky_apertures_masks: annulus_data = mask.multiply(imagedata) 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) phottable = aperture_photometry(imagedata, [apertures, sky_apertures]) # plt.plot (phottable['aperture_sum_1'] / sky_apertures.area, phottable['aperture_sum_1'] / sky_apertures.area - bkg_median,'.') # plt.savefig ('sky.png') newflux = phottable['aperture_sum_0'] - bkg_median * apertures.area # oldmag = -2.5 * np.log10(catalog['FLUX']) # newmag = -2.5 * np.log10 (newflux) # _logger.info ( newmag - oldmag) # plt.plot (newmag, newmag - oldmag, '.') # plt.savefig("Comparison.png") catalog['FLUX'] = newflux
def aper_phot(image, mask, xc, yc, radii, rsky, debug): positions = [(xc, yc)] # Define apertures apertures = [CircularAperture(positions, r=r) for r in radii] if (debug == 1): # print("line ", lineno()," apertures : ", apertures) print("line ", lineno(), " aper_phot: positions: ", positions) print("line ", lineno(), " aper_phot: sky aperture ", rsky) # for rr in range(0,len(radii)): # print("line ", lineno(), " apertures[rr].r, apertures[rr].area :", apertures[rr].r, apertures[rr].area ) # Background, masking bad pixels annulus_aperture = CircularAnnulus(positions, r_in=rsky[0], r_out=rsky[1]) annulus_masks = annulus_aperture.to_mask(method='center') bkg_median = [] for anm in annulus_masks: annulus_data = anm.multiply(image) annulus_data_1d = annulus_data[anm.data > 0] if (debug == 1): print("line ", lineno(), " aper_phot: annulus_data_1d.shape ", annulus_data_1d.shape) # Remove NaNs, Infs annulus_data_1d = annulus_data_1d[np.isfinite(annulus_data_1d)] _, median_sigclip, _ = sigma_clipped_stats(annulus_data_1d) bkg_median.append(median_sigclip) if (debug == 1): print("line ", lineno(), " aper_phot: annulus_data_1d.shape ", annulus_data_1d.shape) print("line ", lineno(), " aper_phot: median sigclip", median_sigclip) if (debug == 1): print("line ", lineno(), " aper_phot: bkg_median ", bkg_median) phot_table = aperture_photometry(image, apertures, mask=mask) # junk = [] area_list = [] n = -1 for index in phot_table.colnames: if ('aperture_sum' in index): n = n + 1 array = phot_table[index].data[0] flux = array.tolist() bkg = apertures[n].area * bkg_median[0] junk.append(flux - bkg) area_list.append(apertures[n].area) apflux = np.array(junk) area = np.array(area_list) # (diff, encircled) = differential(apflux,area,True,False) return apflux, area
def get_one_contrast_and_SN(data, positions, fwhm, fwhm_flux): ''' Args: path : a string. The path of repository where the files are. positions : a list of tuple (x,y). The coordinates of companions. Return: flux : a np.array, 1 dimension. Store the list of each companion's flux. SN : a np.array, 1 dimension. Store the list of each companion's Signal to Noise ratio. ''' # flux aperture = CircularAperture(positions, r=2) annulus = CircularAnnulus(positions, r_in=4, r_out=6) # flux flux_companion = aperture_photometry(data, [aperture, annulus]) flux_companion['aperture_sum_0', 'aperture_sum_1'].info.format = '%.8g' flux = (flux_companion['aperture_sum_0'] / aperture.area) / fwhm_flux # SN ds9 = vip.Ds9Window() ds9.display(data) SN = vip.metrics.snr(data, source_xy=positions[0], fwhm=fwhm, plot=True) return flux[0], SN
def allreg_to_aperture(region): """Convert region object to aperture object.""" region_type = type(region).__name__ if "Pixel" in region_type: source_center = (region.center.x, region.center.y) if region_type == 'CirclePixelRegion': return CircularAperture(source_center, r=region.radius) elif region_type == "CircleAnnulusPixelRegion": return CircularAnnulus(source_center, r_in=region.inner_radius, r_out=region.outer_radius) elif region_type == "EllipsePixelRegion": # to be tested return EllipticalAperture(source_center, a=region.width, b=region.height, angle=region.angle) elif "Sky" in region_type: center = region.center.fk5 if region_type == "CircleSkyRegion": return SkyCircularAperture(center, r=region.radius) elif region_type == "EllipseSkyRegion": return SkyEllipticalAperture(center, a=region.width / 2, b=region.height / 2, angle=region.angle) elif region_type == "CircleAnnulusSkyRegion": return SkyCircularAnnulus(center, r_in=region.inner_radius, r_out=region.outer_radius) else: print("Error region not implemented") return None
def sky(self,method='sep',rin=None,rout=None): """ (Re)calculate the sky.""" # Remove the current best-fit model resid = self.image.data-self.modelim # remove model # SEP smoothly varying background if method=='sep': bw = np.maximum(int(self.nx/10),64) bh = np.maximum(int(self.ny/10),64) bkg = sep.Background(resid, mask=None, bw=bw, bh=bh, fw=3, fh=3) self.skyim = bkg.back() # Calculate sky value for each star # use center position self.starsky[:] = self.skyim[np.round(self.starycen).astype(int),np.round(self.starxcen).astype(int)] # Annulus aperture elif method=='annulus': if rin is None: rin = self.psf.fwhm()*1.5 if rout is None: rout = self.psf.fwhm()*2.5 positions = list(zip(self.starxcen,self.starycen)) annulus = CircularAnnulus(positions,r_in=rin,r_out=rout) for i in range(self.nstars): annulus_mask = annulus[i].to_mask(method='center') annulus_data = annulus_mask.multiply(resid,fill_value=np.nan) data = annulus_data[(annulus_mask.data>0) & np.isfinite(annulus_data)] mean_sigclip, median_sigclip, _ = sigma_clipped_stats(data,stdfunc=dln.mad) self.starsky[i] = mean_sigclip if hasattr(self,'skyim') is False: self.skyim = np.zeros(self.image.shape,float) if self.skyim is None: self.skyim = np.zeros(self.image.shape,float) self.skyim += np.median(self.starsky) else: raise ValueError("Sky method "+method+" not supported")
def get_contrast_and_SN(res_fake, res_real, positions, fwhm_for_snr, fwhm_flux, r_aperture, r_in_annulus, r_out_annulus): ''' Args: res_fake : a 2D np.array. The path of repository where the files are. res_real : a 2D np.array. The path of another repository where the files are, for calculating snr. positions : a list of tuple (x,y). The coordinates of companions. fwhm : a float. fwhm's diameter. fwhm_flux : a float. The flux of fwhm. Return: contrast : a np.array, 1 dimension. Store the list of each companion's flux. SN : a np.array, 1 dimension. Store the list of each companion's Signal to Noise ratio. ''' aperture = CircularAperture(positions, r=r_aperture) annulus = CircularAnnulus(positions, r_in=r_in_annulus, r_out=r_out_annulus) # contrast flux_companion = aperture_photometry(res_fake, [aperture, annulus]) flux_companion['aperture_sum_0', 'aperture_sum_1'].info.format = '%.8g' flux = flux_companion['aperture_sum_0'] contrast = (flux_companion['aperture_sum_0']) / fwhm_flux # SN SN = vip.metrics.snr(array=res_fake, source_xy=positions, fwhm=fwhm_for_snr, plot=False, array2=res_real, use2alone=True) return contrast.data[0], SN, flux.data[0]
def estimate_all_backgrounds(xs, ys, r_in, r_out, data, stat='aperture_mode'): """ Compute sky values around (xs, ys) in data with various parameters See photometry_tools.aperture_stats_tbl for more details. """ ans = CircularAnnulus(positions=zip(xs, ys), r_in=r_in, r_out=r_out) bg_ests = aperture_stats_tbl(apertures=ans, data=data, sigma_clip=True) return np.array(bg_ests[stat])
def get_contrast_and_SN(path, positions, fwhm, fwhm_flux, path_real): ''' Args: path : a string. The path of repository where the files are. positions : a list of tuple (x,y). The coordinates of companions. fwhm : a float. fwhm's diameter. fwhm_flux : a float. The flux of fwhm. path_real : a string. The path of another repository where the files are, for calculating snr. Return: contrast : a np.array, 1 dimension. Store the list of each companion's flux. SN : a np.array, 1 dimension. Store the list of each companion's Signal to Noise ratio. ''' files = os.listdir(path) files.sort() files_real = os.listdir(path_real) files_real.sort() l = len(files) flux = np.zeros(l) # contrast contrast = np.zeros(l) aperture = CircularAperture(positions, r=2) annulus = CircularAnnulus(positions, r_in=4, r_out=6) # SN SN = np.zeros(l) for i in range(l): file = path+'/'+files[i] print("file",i,"=", file) data = vip.fits.open_fits(file) # contrast flux_companion = aperture_photometry(data, [aperture, annulus]) flux_companion['aperture_sum_0','aperture_sum_1'].info.format = '%.8g' #bkg_mean = flux_companion['aperture_sum_1']/annulus.area #bkg_sum_in_companion = bkg_mean * aperture.area flux[i] = flux_companion['aperture_sum_0'] contrast[i] = (flux_companion['aperture_sum_0']/aperture.area)/fwhm_flux # SN lets_plot = False if i==2: lets_plot = True #ds9.display(data) file_real = path_real+'/'+files_real[i] print("array2 at ",i," =", file_real) data2 = vip.fits.open_fits(file_real) SN[i] = vip.metrics.snr(array=data, source_xy=positions, fwhm=fwhm, plot=lets_plot, array2 = data2, use2alone=True) return contrast, SN
def _aper_local_background(self): """ Estimate the local background and error using a circular annulus aperture. The local background is the sigma-clipped median value in the annulus. The background error is the standard error of the median, sqrt(pi / 2N) * std. """ bkg_aper = CircularAnnulus( self._xypos_finite, self.aperture_params['bkg_aperture_inner_radius'], self.aperture_params['bkg_aperture_outer_radius']) bkg_aper_masks = bkg_aper.to_mask(method='center') sigclip = SigmaClip(sigma=3.) with warnings.catch_warnings(): warnings.simplefilter('ignore', category=RuntimeWarning) warnings.simplefilter('ignore', category=AstropyUserWarning) nvalues = [] bkg_median = [] bkg_std = [] for mask in bkg_aper_masks: bkg_data = mask.get_values(self.model.data.value) values = sigclip(bkg_data, masked=False) nvalues.append(values.size) bkg_median.append(np.median(values)) bkg_std.append(np.std(values)) nvalues = np.array(nvalues) bkg_median = np.array(bkg_median) # standard error of the median bkg_median_err = (np.sqrt(np.pi / (2. * nvalues)) * np.array(bkg_std)) bkg_median <<= self.model.data.unit bkg_median_err <<= self.model.data.unit return bkg_median, bkg_median_err
def region_to_aperture(region, wcs=None): """Convert region object to photutils.aperture.aperture_photometry object. The wcs object is needed only if the input regions are in sky coordinates. Parameters ---------- region: regions.Region Output of read_ds9 method or str wcs: astropy.wcs.WCS A world coordinate system if the region in sky coordinates IS needed to convert it to pixels. """ if type(region) == str: region = read_ds9(region)[0] print(region) region_type = type(region).__name__ if "Pixel" in region_type: source_center = (region.center.x, region.center.y) if region_type == 'CirclePixelRegion': return CircularAperture(source_center, r=region.radius) elif region_type == "CircleAnnulusPixelRegion": return CircularAnnulus(source_center, r_in=region.inner_radius, r_out=region.outer_radius) elif region_type == "EllipsePixelRegion": # to be tested return EllipticalAperture(source_center, a=region.width, b=region.height, theta=region.angle) elif "Sky" in region_type: if wcs is None: print("Error, cannot obtain aperture without a wcs.") return None center = region.center.fk5 if region_type == "CircleSkyRegion": return SkyCircularAperture(center, r=region.radius).to_pixel(wcs) elif region_type == "CircleAnnulusSkyRegion": print("Region %s not implemented") elif region_type == "EllipseSkyRegion": return SkyEllipticalAperture(center, a=region.width, b=region.height, theta=region.angle).to_pixel(wcs) elif region_type == "CircleAnnulusSkyRegion": return SkyCircularAnnulus(center, r_in=region.inner_radius, r_out=region.outer_radius).to_pixel(wcs) else: print("Error region not implemented") return None
def get_SN(path, positions, fwhm): ''' Args: path : a string. The path of repository where the files are. positions : a list of tuple (x,y). The coordinates of companions. Return: flux : a np.array, 1 dimension. Store the list of each companion's flux. SN : a np.array, 1 dimension. Store the list of each companion's Signal to Noise ratio. ''' files = os.listdir(path) files.sort() l = len(files) # flux flux = np.zeros(l) aperture = CircularAperture(positions, r=2) annulus = CircularAnnulus(positions, r_in=4, r_out=6) # SN SN = np.zeros(l) for i in range(l): file = path + '/' + files[i] print("file", i, "=", file) data = vip.fits.open_fits(file) # flux flux_companion = aperture_photometry(data, [aperture, annulus]) flux_companion['aperture_sum_0', 'aperture_sum_1'].info.format = '%.8g' #bkg_mean = flux_companion['aperture_sum_1']/annulus.area #bkg_sum_in_companion = bkg_mean * aperture.area #flux[i] = flux_companion['aperture_sum_0'] - bkg_sum_in_companion flux[i] = (flux_companion['aperture_sum_0'] / aperture.area) # SN lets_plot = False if i == 2: lets_plot = True #ds9.display(data) SN[i] = vip.metrics.snr(data, source_xy=positions[0], fwhm=fwhm, plot=lets_plot) return flux, SN
def get_contrast_and_SN_only_real(res_real, positions, fwhm_for_snr, psf, r_aperture, r_in_annulus, r_out_annulus): ''' Args: res_real : a 2D np.array. The path of another repository where the files are, for calculating snr. positions : a list of tuple (x,y). The coordinates of companions. psf : a 2D np.array. The image of flux. fwhm_flux : a float. The flux of fwhm. r_aperture, r_in_annulus, r_out_annulus : see args. Return: contrast : a np.array, 1 dimension. Store the list of each companion's flux. SN : a np.array, 1 dimension. Store the list of each companion's Signal to Noise ratio. ''' aperture = CircularAperture(positions, r=r_aperture) annulus = CircularAnnulus(positions, r_in=r_in_annulus, r_out=r_out_annulus) # contrast flux_companion = aperture_photometry(res_real, [aperture, annulus]) flux_companion['aperture_sum_0', 'aperture_sum_1'].info.format = '%.8g' flux = flux_companion['aperture_sum_0'] x, y = psf.shape aperture_psf = CircularAperture((x // 2, y // 2), r=r_aperture) flux_psf = aperture_photometry(psf, aperture_psf) flux_psf['aperture_sum'].info.format = '%.8g' contrast = (flux_companion['aperture_sum_0']) / flux_psf['aperture_sum'] # SN SN = vip.metrics.snr(array=res_real, source_xy=positions, fwhm=fwhm_for_snr, plot=False) return contrast.data[0], SN, flux.data[0]
print("psfn =", psfn.shape, "psfn.ndim =", psfn.ndim) if nb_wl > 1: fwhm_bis = get_fwhm_from_psf(psf[1]) psfn_bis = vip.metrics.normalize_psf(psf[1], fwhm_bis, size=17) print("psfn =", psfn_bis.shape, "psfn.ndim =", psfn_bis.ndim) # pxscale of IRDIS pxscale = get_pxscale() # get flux level psf_nx, psf_ny = psf[wl_final].shape position = (psf_nx // 2, psf_ny // 2) aperture = CircularAperture(position, r=(diameter / 2)) annulus = CircularAnnulus(position, r_in=diameter, r_out=diameter * (3 / 2)) flux_psf = aperture_photometry(psf[wl_final], [aperture, annulus]) flux_psf['aperture_sum_0', 'aperture_sum_1'].info.format = '%.8g' flux_level = flux_psf['aperture_sum_0'][0] * contrast print(">> flux of psf in the same aperture is:", flux_psf['aperture_sum_0'][0], "contrast is:", contrast) print(">> flux_level =", flux_level) ################################ # Step-3 do the fake injection # ################################ # use vip to inject a fake companion science_cube_fake_comp = np.zeros((2, nb_science_frames, nx, ny)) science_cube_fake_comp[wl_final] = vip.metrics.cube_inject_companions(
print('\nPrint source locations:') sources['id', 'xcentroid', 'ycentroid'].pprint() #print out positions of sources print('\n') #%% perform aperture photometry # extract source postions from table; transpose is needed for proper orientation positions = np.transpose((sources['xcentroid'], sources['ycentroid'])) # define the aperture r_a = 3 * seeing apertures = CircularAperture(positions, r=r_a) # define the annulus r_in = r_a + 3 r_out = r_in + 15 annulus = CircularAnnulus(positions, r_in=r_in, r_out=r_out) # plot image with apertures y_or_n = input('Do you wish to display the image and appertures? ') if (y_or_n[0] == 'y') or (y_or_n[0] == 'Y'): plt.figure(1) plt.clf() # label the sources mylabels = sources['id'] for idx, txt in enumerate(mylabels): plt.annotate(txt, (positions[idx, 0], positions[idx, 1])) plt.imshow(np.log(imdata), cmap='Greys') apertures.plot(color='red', lw=1.5, alpha=0.5) annulus.plot(color='green', lw=1.5, alpha=0.5)
def extract_ifu(input_model, source_type, extract_params): """This function does the extraction. Parameters ---------- input_model : IFUCubeModel The input model. source_type : string "POINT" or "EXTENDED" extract_params : dict The extraction parameters for aperture photometry. Returns ------- ra, dec : float ra and dec are the right ascension and declination respectively at the nominal center of the image. wavelength : ndarray, 1-D The wavelength in micrometers at each plane of the IFU cube. temp_flux : ndarray, 1-D The sum of the data values in the extraction aperture minus the sum of the data values in the background region (scaled by the ratio of areas), for each plane. The data values are in units of surface brightness, so this value isn't really the flux, it's an intermediate value. Dividing by `npixels` (to compute the average) will give the value for the `surf_bright` (surface brightness) column, and multiplying by the solid angle of a pixel will give the flux for a point source. background : ndarray, 1-D For point source data, the background array is the count rate that was subtracted from the total source data values to get `temp_flux`. This background is determined for annulus region. For extended source data, the background array is the sigma clipped extracted region. npixels : ndarray, 1-D, float64 For each slice, this is the number of pixels that were added together to get `temp_flux`. dq : ndarray, 1-D, uint32 The data quality array. npixels_bkg : ndarray, 1-D, float64 For each slice, for point source data this is the number of pixels that were added together to get `temp_flux` for an annulus region or for extended source data it is the number of pixels used to determine the background radius_match : ndarray,1-D, float64 The size of the extract radius in pixels used at each wavelength of the IFU cube x_center, y_center : float The x and y center of the extraction region """ data = input_model.data weightmap = input_model.weightmap shape = data.shape if len(shape) != 3: log.error("Expected a 3-D IFU cube; dimension is %d.", len(shape)) raise RuntimeError("The IFU cube should be 3-D.") # We need to allocate temp_flux, background, npixels, and dq arrays # no matter what. We may need to divide by npixels, so the default # is 1 rather than 0. temp_flux = np.zeros(shape[0], dtype=np.float64) background = np.zeros(shape[0], dtype=np.float64) npixels = np.ones(shape[0], dtype=np.float64) npixels_bkg = np.ones(shape[0], dtype=np.float64) dq = np.zeros(shape[0], dtype=np.uint32) # For an extended target, the entire aperture will be extracted, so # it makes no sense to shift the extraction location. if source_type != "EXTENDED": ra_targ = input_model.meta.target.ra dec_targ = input_model.meta.target.dec locn = locn_from_wcs(input_model, ra_targ, dec_targ) if locn is None or np.isnan(locn[0]): log.warning("Couldn't determine pixel location from WCS, so " "source offset correction will not be applied.") x_center = float(shape[-1]) / 2. y_center = float(shape[-2]) / 2. else: (x_center, y_center) = locn log.info( "Using x_center = %g, y_center = %g, based on " "TARG_RA and TARG_DEC.", x_center, y_center) method = extract_params['method'] subpixels = extract_params['subpixels'] subtract_background = extract_params['subtract_background'] radius = None inner_bkg = None outer_bkg = None width = None height = None theta = None # pull wavelength plane out of input data. # using extract 1d wavelength, interpolate the radius, inner_bkg, outer_bkg to match input wavelength # find the wavelength array of the IFU cube x0 = float(shape[2]) / 2. y0 = float(shape[1]) / 2. (ra, dec, wavelength) = get_coordinates(input_model, x0, y0) # interpolate the extraction parameters to the wavelength of the IFU cube radius_match = None if source_type == 'POINT': wave_extract = extract_params['wavelength'].flatten() inner_bkg = extract_params['inner_bkg'].flatten() outer_bkg = extract_params['outer_bkg'].flatten() radius = extract_params['radius'].flatten() frad = interp1d(wave_extract, radius, bounds_error=False, fill_value="extrapolate") radius_match = frad(wavelength) # radius_match is in arc seconds - need to convert to pixels # the spatial scale is the same for all wavelengths do we only need to call compute_scale once. if locn is None: locn_use = (input_model.meta.wcsinfo.crval1, input_model.meta.wcsinfo.crval2, wavelength[0]) else: locn_use = (ra_targ, dec_targ, wavelength[0]) scale_degrees = compute_scale( input_model.meta.wcs, locn_use, disp_axis=input_model.meta.wcsinfo.dispersion_direction) scale_arcsec = scale_degrees * 3600.00 radius_match /= scale_arcsec finner = interp1d(wave_extract, inner_bkg, bounds_error=False, fill_value="extrapolate") inner_bkg_match = finner(wavelength) / scale_arcsec fouter = interp1d(wave_extract, outer_bkg, bounds_error=False, fill_value="extrapolate") outer_bkg_match = fouter(wavelength) / scale_arcsec elif source_type == 'EXTENDED': # Ignore any input parameters, and extract the whole image. width = float(shape[-1]) height = float(shape[-2]) x_center = width / 2. - 0.5 y_center = height / 2. - 0.5 theta = 0. subtract_background = False bkg_sigma_clip = extract_params['bkg_sigma_clip'] log.debug("IFU 1-D extraction parameters:") log.debug(" x_center = %s", str(x_center)) log.debug(" y_center = %s", str(y_center)) if source_type == 'POINT': log.debug(" method = %s", method) if method == "subpixel": log.debug(" subpixels = %s", str(subpixels)) else: log.debug(" width = %s", str(width)) log.debug(" height = %s", str(height)) log.debug(" theta = %s degrees", str(theta)) log.debug(" subtract_background = %s", str(subtract_background)) log.debug(" sigma clip value for background = %s", str(bkg_sigma_clip)) log.debug(" method = %s", method) if method == "subpixel": log.debug(" subpixels = %s", str(subpixels)) position = (x_center, y_center) # get aperture for extended it will not change with wavelength if source_type == 'EXTENDED': aperture = RectangularAperture(position, width, height, theta) annulus = None for k in range(shape[0]): # looping over wavelength inner_bkg = None outer_bkg = None if source_type == 'POINT': radius = radius_match[ k] # this radius has been converted to pixels aperture = CircularAperture(position, r=radius) inner_bkg = inner_bkg_match[k] outer_bkg = outer_bkg_match[k] if inner_bkg <= 0. or outer_bkg <= 0. or inner_bkg >= outer_bkg: log.debug("Turning background subtraction off, due to " "the values of inner_bkg and outer_bkg.") subtract_background = False if subtract_background and inner_bkg is not None and outer_bkg is not None: annulus = CircularAnnulus(position, r_in=inner_bkg, r_out=outer_bkg) else: annulus = None subtract_background_plane = subtract_background # Compute the area of the aperture and possibly also of the annulus. # for each wavelength bin (taking into account empty spaxels) normalization = 1. temp_weightmap = weightmap[k, :, :] temp_weightmap[temp_weightmap > 1] = 1 aperture_area = 0 annulus_area = 0 # aperture_photometry - using weight map phot_table = aperture_photometry(temp_weightmap, aperture, method=method, subpixels=subpixels) aperture_area = float(phot_table['aperture_sum'][0]) log.debug("aperture.area = %g; aperture_area = %g", aperture.area, aperture_area) if (aperture_area == 0 and aperture.area > 0): aperture_area = aperture.area if subtract_background and annulus is not None: # Compute the area of the annulus. phot_table = aperture_photometry(temp_weightmap, annulus, method=method, subpixels=subpixels) annulus_area = float(phot_table['aperture_sum'][0]) log.debug("annulus.area = %g; annulus_area = %g", annulus.area, annulus_area) if (annulus_area == 0 and annulus.area > 0): annulus_area = annulus.area if annulus_area > 0.: normalization = aperture_area / annulus_area else: log.warning("Background annulus has no area, so background " f"subtraction will be turned off. {k}") subtract_background_plane = False npixels[k] = aperture_area npixels_bkg[k] = 0.0 if annulus is not None: npixels_bkg[k] = annulus_area # aperture_photometry - using data phot_table = aperture_photometry(data[k, :, :], aperture, method=method, subpixels=subpixels) temp_flux[k] = float(phot_table['aperture_sum'][0]) # Point source type of data with defined annulus size if subtract_background_plane: bkg_table = aperture_photometry(data[k, :, :], annulus, method=method, subpixels=subpixels) background[k] = float(bkg_table['aperture_sum'][0]) temp_flux[k] = temp_flux[k] - background[k] * normalization # Extended source data - background determined from sigma clipping if source_type == 'EXTENDED': bkg_data = data[k, :, :] # pull out the data with coverage in IFU cube. We do not want to use # the edge data that is zero to define the statistics on clipping bkg_stat_data = bkg_data[temp_weightmap == 1] bkg_mean, _, bkg_stddev = stats.sigma_clipped_stats( bkg_stat_data, sigma=bkg_sigma_clip, maxiters=5) low = bkg_mean - bkg_sigma_clip * bkg_stddev high = bkg_mean + bkg_sigma_clip * bkg_stddev # set up the mask to flag data that should not be used in aperture photometry maskclip = np.logical_or(bkg_data < low, bkg_data > high) bkg_table = aperture_photometry(bkg_data, aperture, mask=maskclip, method=method, subpixels=subpixels) background[k] = float(bkg_table['aperture_sum'][0]) phot_table = aperture_photometry(temp_weightmap, aperture, mask=maskclip, method=method, subpixels=subpixels) npixels_bkg[k] = float(phot_table['aperture_sum'][0]) del temp_weightmap # done looping over wavelength bins # Check for NaNs in the wavelength array, flag them in the dq array, # and truncate the arrays if NaNs are found at endpoints (unless the # entire array is NaN). (wavelength, temp_flux, background, npixels, dq, npixels_bkg) = \ nans_in_wavelength(wavelength, temp_flux, background, npixels, dq, npixels_bkg) return (ra, dec, wavelength, temp_flux, background, npixels, dq, npixels_bkg, radius_match, x_center, y_center)
def ConCur(star_data, radius_size=1, center=None, background_method='astropy', find_hots=False, find_center=False): data = star_data.copy() background_mean, background_std = background_calc(data, background_method) x, y = np.indices((data.shape)) if not center: center = np.array([(x.max() - x.min()) / 2.0, (y.max() - y.min()) / 2.0]) if find_hots == True: hots = hot_pixels(data, center, background_mean, background_std) if find_center == True: center_vals = find_best_center(data, radius_size, center) center = np.array([center_vals[0], center_vals[1]]) radii = np.sqrt((x - center[0])**2 + (y - center[1])**2) radii = radii.astype(np.int) ones = np.array([[1] * len(data)] * len(data[0])) number_of_a = radii.max() / radius_size center_ap = CircularAperture([center[0], center[1]], radius_size) all_apers, all_apers_areas, all_masks = [center_ap], [center_ap.area], [ center_ap.to_mask(method='exact') ] all_data, all_weights = [all_masks[0].multiply(data) ], [all_masks[0].multiply(ones)] all_stds = [twoD_weighted_std(all_data[0], all_weights[0])] for j in range(int(number_of_a)): aper = CircularAnnulus([center[0], center[1]], r_in=(j * radius_size + radius_size), r_out=(j * radius_size + 2 * radius_size)) all_apers.append(aper) all_apers_areas.append(aper.area) mask = aper.to_mask(method='exact') all_masks.append(mask) mask_data = mask.multiply(data) mask_weight = mask.multiply(ones) all_data.append(mask_data) all_weights.append(mask_weight) all_stds.append(twoD_weighted_std(mask_data, mask_weight)) phot_table = aperture_photometry(data, all_apers) center_val = np.sum(all_data[0]) / all_apers_areas[0] + 5 * all_stds[0] delta_mags = [] for i in range(len(phot_table[0]) - 3): try: delta_mags.append(-2.5 * math.log((np.sum(all_data[i])/all_apers_areas[i] + \ 5*all_stds[i])/center_val,10)) except ValueError: print('annulus',i, 'relative flux equal to', (np.sum(all_data[i])/all_apers_areas[i] + \ 5*all_stds[i])/center_val, '...it is not included') delta_mags.append(np.NaN) arc_lengths = [] for i in range(len(delta_mags)): arc_lengths.append( (i * 0.033 + 0.033) * radius_size) #make sure center radius size is correct arc_lengths = np.array(arc_lengths) lim_arc_lengths = arc_lengths[arc_lengths < 10] delta_mags = delta_mags[:len(lim_arc_lengths)] delta_mags = np.array(delta_mags) if delta_mags[1] < 0: print('Warning: first annulus has negative relative flux of value,', '%.5f' % delta_mags[1], 'consider changing center or radius size') return (lim_arc_lengths, delta_mags, all_stds)
handles = (ap_patches[0],ann_patches[0]) plt.legend(loc=(0.17, 0.05), facecolor='#458989', labelcolor='white', handles=handles, prop={'weight':'bold', 'size':11}) plt.xlim(100,170) plt.ylim(200,256) #plt.savefig('./circle_ADI/ADI_32px_'+str(i)) plt.show() return res, SN if __name__ == "__main__": print("###### Start to process the data ######") start_time = datetime.datetime.now() positions = [(126.05284, 249.11)] aperture = CircularAperture(positions, r=2) annulus = CircularAnnulus(positions, r_in=4, r_out=6) # ADI data #ADI_res, ADI_SN = get_photometry("./ADI") #ADI_res, ADI_SN = get_photometry("./ADI_WITH_MASK") #ADI_res_32, ADI_SN_32 = get_photometry("./ADI_WITH_MASK_32") #print(ADI_res_32) # RDI data 1 target 2 ref stars #RDI_res_2_ref, RDI_2_SN = get_photometry("./RDI_ref_2_star") #print(RDI_res_2_ref) # RDI data 1 target 4 ref stars #RDI_res_4_ref, RDI_4_SN = get_photometry("./RDI_ref_4_star") #print(RDI_res_4_ref)
def tso_aperture_photometry(datamodel, xcenter, ycenter, radius, radius_inner, radius_outer): """ Create a photometric catalog for NIRCam TSO imaging observations. Parameters ---------- datamodel : `CubeModel` The input `CubeModel` of a NIRCam TSO imaging observation. xcenter, ycenter : float The ``x`` and ``y`` center of the aperture. radius : float The radius (in pixels) of the circular aperture. radius_inner, radius_outer : float The inner and outer radii (in pixels) of the circular-annulus aperture, used for local background estimation. Returns ------- catalog : `~astropy.table.QTable` An astropy QTable (Quantity Table) containing the source photometry. """ if not isinstance(datamodel, CubeModel): raise ValueError('The input data model must be a CubeModel.') # For the SUB64P subarray with the WLP8 pupil, the circular aperture # extends beyond the image and the circular annulus does not have any # overlap with the image. In that case, we simply sum all values # in the array and skip the background subtraction. sub64p_wlp8 = False if (datamodel.meta.instrument.pupil == 'WLP8' and datamodel.meta.subarray.name == 'SUB64P'): sub64p_wlp8 = True if not sub64p_wlp8: phot_aper = CircularAperture((xcenter, ycenter), r=radius) bkg_aper = CircularAnnulus((xcenter, ycenter), r_in=radius_inner, r_out=radius_outer) # convert the input data and errors from MJy/sr to Jy if datamodel.meta.bunit_data != 'MJy/sr': raise ValueError('data is expected to be in units of MJy/sr') factor = 1.e6 * datamodel.meta.photometry.pixelarea_steradians datamodel.data *= factor datamodel.err *= factor datamodel.meta.bunit_data = 'Jy' datamodel.meta.bunit_err = 'Jy' aperture_sum = [] aperture_sum_err = [] annulus_sum = [] annulus_sum_err = [] nimg = datamodel.data.shape[0] if sub64p_wlp8: info = ('Photometry measured as the sum of all values in the ' 'subarray. No background subtraction was performed.') for i in np.arange(nimg): aperture_sum.append(np.sum(datamodel.data[i, :, :])) aperture_sum_err.append(np.sqrt(np.sum(datamodel.err[i, :, :]**2))) else: info = ('Photometry measured in a circular aperture of r={0} ' 'pixels. Background calculated as the mean in a ' 'circular annulus with r_inner={1} pixels and ' 'r_outer={2} pixels.'.format(radius, radius_inner, radius_outer)) for i in np.arange(nimg): aper_sum, aper_sum_err = phot_aper.do_photometry( datamodel.data[i, :, :], error=datamodel.err[i, :, :]) ann_sum, ann_sum_err = bkg_aper.do_photometry( datamodel.data[i, :, :], error=datamodel.err[i, :, :]) aperture_sum.append(aper_sum[0]) aperture_sum_err.append(aper_sum_err[0]) annulus_sum.append(ann_sum[0]) annulus_sum_err.append(ann_sum_err[0]) aperture_sum = np.array(aperture_sum) aperture_sum_err = np.array(aperture_sum_err) annulus_sum = np.array(annulus_sum) annulus_sum_err = np.array(annulus_sum_err) # construct metadata for output table meta = OrderedDict() meta['instrument'] = datamodel.meta.instrument.name meta['detector'] = datamodel.meta.instrument.detector meta['channel'] = datamodel.meta.instrument.channel meta['subarray'] = datamodel.meta.subarray.name meta['filter'] = datamodel.meta.instrument.filter meta['pupil'] = datamodel.meta.instrument.pupil meta['target_name'] = datamodel.meta.target.catalog_name meta['xcenter'] = xcenter meta['ycenter'] = ycenter ra_icrs, dec_icrs = datamodel.meta.wcs(xcenter, ycenter) meta['ra_icrs'] = ra_icrs meta['dec_icrs'] = dec_icrs meta['apertures'] = info # initialize the output table tbl = QTable(meta=meta) # check for the INT_TIMES table extension if hasattr(datamodel, 'int_times') and datamodel.int_times is not None: nrows = len(datamodel.int_times) else: nrows = 0 log.warning("The INT_TIMES table in the input file is missing or " "empty.") # load the INT_TIMES table data if nrows > 0: shape = datamodel.data.shape if len(shape) == 2: num_integ = 1 else: # len(shape) == 3 num_integ = shape[0] int_start = datamodel.meta.exposure.integration_start if int_start is None: int_start = 1 log.warning(f"INTSTART not found; assuming a value of {int_start}") # Columns of integration numbers & times of integration from the # INT_TIMES table. int_num = datamodel.int_times['integration_number'] mid_utc = datamodel.int_times['int_mid_MJD_UTC'] offset = int_start - int_num[0] # both are one-indexed if offset < 0: log.warning("Range of integration numbers in science data extends " "outside the range in INT_TIMES table.") log.warning("Can't use INT_TIMES table.") del int_num, mid_utc nrows = 0 # flag as bad else: log.debug("Times are from the INT_TIMES table") time_arr = mid_utc[offset:offset + num_integ] int_times = Time(time_arr, format='mjd', scale='utc') # compute integration time stamps on the fly if nrows == 0: log.debug("Times computed from EXPSTART and EFFINTTM") dt = datamodel.meta.exposure.integration_time n_dt = (datamodel.meta.exposure.integration_end - datamodel.meta.exposure.integration_start + 1) dt_arr = (np.arange(1, 1 + n_dt) * dt - (dt / 2.)) int_dt = TimeDelta(dt_arr, format='sec') int_times = (Time(datamodel.meta.exposure.start_time, format='mjd') + int_dt) # populate table columns unit = u.Unit(datamodel.meta.bunit_data) tbl['MJD'] = int_times.mjd tbl['aperture_sum'] = aperture_sum << unit tbl['aperture_sum_err'] = aperture_sum_err << unit if not sub64p_wlp8: tbl['annulus_sum'] = annulus_sum << unit tbl['annulus_sum_err'] = annulus_sum_err << unit annulus_mean = annulus_sum / bkg_aper.area annulus_mean_err = annulus_sum_err / bkg_aper.area aperture_bkg = annulus_mean * phot_aper.area aperture_bkg_err = annulus_mean_err * phot_aper.area tbl['annulus_mean'] = annulus_mean << unit tbl['annulus_mean_err'] = annulus_mean_err << unit tbl['aperture_bkg'] = aperture_bkg << unit tbl['aperture_bkg_err'] = aperture_bkg_err << unit net_aperture_sum = aperture_sum - aperture_bkg net_aperture_sum_err = np.sqrt(aperture_sum_err**2 + aperture_bkg_err**2) tbl['net_aperture_sum'] = net_aperture_sum << unit tbl['net_aperture_sum_err'] = net_aperture_sum_err << unit else: colnames = [ 'annulus_sum', 'annulus_sum_err', 'annulus_mean', 'annulus_mean_err', 'aperture_bkg', 'aperture_bkg_err' ] for col in colnames: tbl[col] = np.full(nimg, np.nan) tbl['net_aperture_sum'] = aperture_sum << unit tbl['net_aperture_sum_err'] = aperture_sum_err << unit return tbl
def quick_sky_circ(ccd, pos, r_in=10, r_out=20): """ Estimate sky with crude presets """ from photutils.aperture import CircularAnnulus annulus = CircularAnnulus(pos, r_in=r_in, r_out=r_out) return sky_fit(ccd, annulus)
# 3. result of cADI data = origin_flux_companion( slice_frame(target_frames, len(target_frames[0, 0, 0]), scale), read_file(str(sys.argv[2]), "ROTATION")) data_bkg_mean = radial_data_mean(data[0]) c = plt.imshow(data_bkg_mean, interpolation='nearest', origin='lower') plt.colorbar(c) plt.title('backgraound flux of target science') plt.show() #hdu = fits.PrimaryHDU(res_cADI) #hdu.writeto("./GJ_667C_origin_rotated.fits") positions = [(126.05284, 249.11)] #positions = [(143.06025, 166.01939)] aperture = CircularAperture(positions, r=2) annulus = CircularAnnulus(positions, r_in=4, r_out=6) #data[0][1:,1:] = data[0][1:,1:] - data_bkg_mean flux_companion = aperture_photometry(data[0], [aperture, annulus]) bkg_mean = flux_companion['aperture_sum_1'] / annulus.area bkg_sum_in_companion = bkg_mean * aperture.area print(flux_companion) print("bkg_mean =", bkg_mean[0], "\naperture.area =", aperture.area, "\nannulus.area =", annulus.area) print("bkg_sum_in_companion =", bkg_sum_in_companion[0]) flux_companion_origin = flux_companion[ 'aperture_sum_0'] - bkg_sum_in_companion print("flux companion origin =", flux_companion_origin[0]) norm = simple_norm(data, 'sqrt', percent=99)