def _remove_background(self, mask=None): """ Background removal. It models the background using a median estimator, rejects flux values with sigma clipping. It modiffies the attributes `flux` and `flux_2d`. The background model are stored in the `background_model` attribute. Parameters ---------- mask : numpy.ndarray of booleans Mask to reject pixels containing sources. Default None. """ # model background for all cadences self.background_model = np.array( [ Background2D( flux_2d, mask=mask, box_size=(64, 50), filter_size=15, exclude_percentile=20, sigma_clip=SigmaClip(sigma=3.0, maxiters=5), bkg_estimator=MedianBackground(), interpolator=BkgZoomInterpolator(order=3), ).background for flux_2d in self.flux_2d ] ) # substract background self.flux_2d -= self.background_model # flatten flix image self.flux = self.flux_2d.reshape(self.flux_2d.shape[0], -1) return
def _model_bkg(self, data, mask=None): """ BkgZoomInterpolator: This class generates full-sized background and background RMS images from lower-resolution mesh images using the `~scipy.ndimage.zoom` (spline) interpolator. Parameters ---------- data : numpy.ndarray Data arra with the pixel flux values. mask : numpy.ndarray Boolean array to mask pixels with sources. Returns ------- background : numpy.ndarray Data array with background model """ model = Background2D( data, mask=mask, box_size=(64, 50), filter_size=15, exclude_percentile=20, sigma_clip=SigmaClip(sigma=3.0, maxiters=5), bkg_estimator=MedianBackground(), interpolator=BkgZoomInterpolator(order=3), ) return model.background
def background_2D(image, sigma, iters, box_size, filter_size, plt_grid): """2D background estimation. This function creates a 2D background estimate by dividing the image into a grid, defined by box_size. Args: image(array, required): This is the image data sigma(float, required): Sigma level iters(int, required): Number of iterations box_size(int, required): Defines the box dimesions, in pixels filter_size(int, required): Defines the filter reach in pixels plt_grid(boolean): Overplot grid on image Returns: bkg(array): 2D background level bkgrms(array): RMS background """ sigma_clip = SigmaClip(sigma=sigma, iters=iters) mask = (image == 0) bkg_estimator = MedianBackground() bkg = Background2D(image, box_size=box_size, filter_size=filter_size, sigma_clip=sigma_clip, bkg_estimator=bkg_estimator, mask=mask, edge_method=u'pad') # print('Background Median: ' + str(bkg.background_median)) # print('Background RMS median: ' + str(bkg.background_rms_median)) if plt_grid is True: plt.imshow(bkg.background, origin='lower', cmap='Greys') bkg.plot_meshes(outlines=True, color='#1f77b4') bkgrms = bkg.background_rms return bkg, bkgrms
def __init__(self, window_size=15, img_shape=None): from astropy.stats import SigmaClip from photutils import Background2D, MedianBackground self.sigma_clip = SigmaClip(sigma=3., iters=10) self.bkg_estimator = MedianBackground() self.B2D = Background2D
def bkg_subtraction(time, flux, scope="tpf", sigma=3): """Subtracts background flux from target pixel file. Parameters ---------- scope : string, "tpf" or "postcard" If `tpf`, will use data from the target pixel file only to estimate and remove the background. If `postcard`, will use data from the entire postcard region to estimate and remove the background. sigma : float The standard deviation cut used to determine which pixels are representative of the background in each cadence. """ tpf_flux_bkg = [] sigma_clip = SigmaClip(sigma=sigma) # bkg = MMMBackground(sigma_clip=sigma_clip) bkg = SExtractorBackground(sigma_clip=sigma_clip) bkg_MMM = MMMBackground(sigma_clip=sigma_clip) bkg_ModeEstimator = ModeEstimatorBackground(median_factor=3., mean_factor=2., sigma_clip=sigma_clip) bkg_Mean = MeanBackground(sigma_clip) bkg_Median = MedianBackground(sigma_clip) bkg_SExtractor = SExtractorBackground(sigma_clip) bkg_MMM_value = bkg_MMM.calc_background(flux[0]) bkg_ModeEstimator_value = bkg_ModeEstimator.calc_background(flux[0]) bkg_Mean_value = bkg_Mean.calc_background(flux[0]) bkg_Median_value = bkg_Median.calc_background(flux[0]) bkg_SExtractor_value = bkg_SExtractor.calc_background(flux[0]) print("MMM Background = {}".format(bkg_MMM_value)) print("ModeEstimator Background = {}".format(bkg_ModeEstimator_value)) print("Mean Background = {}".format(bkg_Mean_value)) print("Median Background = {}".format(bkg_Median_value)) print("SExtractor Background = {}".format(bkg_SExtractor_value)) for i in range(len(time)): bkg_value = bkg.calc_background(flux[i]) tpf_flux_bkg.append(bkg_value) tpf_flux_bkg = np.array(tpf_flux_bkg) return tpf_flux_bkg
def test_recovered_flux_aperture(science_image): with fits.open(science_image) as hdul: header = hdul[0].header wcs = WCS(header) footprint = wcs.calc_footprint() # realize fakes randomly throughout the footprint rx = rng.uniform(size=N_FAKE) ry = rng.uniform(size=N_FAKE) # keep things bright mag = rng.uniform(low=15, high=18, size=N_FAKE) minra, mindec = footprint.min(axis=0) maxra, maxdec = footprint.max(axis=0) coord = SkyCoord(minra + (maxra - minra) * rx, mindec + (maxdec - mindec) * ry, unit='deg') fakes.inject_psf(science_image, mag, coord) with fits.open(science_image) as hdul: data = hdul[-2].data header = hdul[0].header table = hdul[-1].data # subtract off the background sigma_clip = SigmaClip(sigma=3.0) bkg = MedianBackground(sigma_clip) bkg_val = bkg.calc_background(data) bkgsub = data - bkg_val APERTURE_RADIUS = 3 * u.pixel for row in table: ra, dec, mag = row['fake_ra'], row['fake_dec'], row['fake_mag'] coord = SkyCoord(ra, dec, unit='deg') apertures = photutils.SkyCircularAperture(coord, r=APERTURE_RADIUS) phot_table = photutils.aperture_photometry(bkgsub, apertures, wcs=wcs) flux = phot_table['aperture_sum'][0] assert abs(-2.5 * np.log10(flux) + header['MAGZP'] + header['APCOR4'] - mag) < 0.05
def background_reduction(List): Raw_Image_Data = [] Reduced_Image_Data = [] Bkg = [] Bkg_Sigma = [] Median = [] Std = [] Norm = ImageNormalize(stretch=SqrtStretch()) for i in range(len(List)): Image_File = get_pkg_data_filename(f'RAW_DATA/{List[i]}') crmask, Raw_Image_Data_1 = astroscrappy.detect_cosmics( fits.getdata(Image_File, ext=0)) Raw_Image_Data.append(Raw_Image_Data_1) Mask = (Raw_Image_Data_1 == 0) Sigma_Clip = SigmaClip(sigma=3.0) Bkg_Estimator = MedianBackground() Bkg_ta = Background2D(Raw_Image_Data_1, (25, 25), filter_size=(3, 3), sigma_clip=Sigma_Clip, bkg_estimator=Bkg_Estimator, mask=Mask) Bkg.append(Bkg_ta) Bkg_Sigma_ta = mad_std(Raw_Image_Data_1) Bkg_Sigma.append(Bkg_Sigma_ta) Mean, Median_ta, Std_ta = sigma_clipped_stats(Raw_Image_Data_1, sigma=3.0) Median.append(Median_ta) Std.append(Std_ta) Reduced_Image_Data_to_append = Raw_Image_Data_1 - Bkg_ta.background Reduced_Image_Data.append(Reduced_Image_Data_to_append) #plt.figure() #plt.imshow(Raw_Image_Data_1, cmap = 'gray', origin = 'lower', interpolation = 'bicubic', norm = Norm, vmin = 100, vmax = 1000) #plt.colorbar() #plt.figure() #plt.imshow(Bkg_ta.background, origin='lower', cmap='gray', interpolation = 'bicubic') #plt.colorbar() #plt.figure() #plt.imshow(Reduced_Image_Data_to_append, norm = Norm, origin = 'lower', cmap = 'gray', interpolation = 'bicubic', vmin = 1, vmax = 1000) #plt.colorbar() #plt.show() return Raw_Image_Data, Reduced_Image_Data, Bkg, Bkg_Sigma, Median, Std
def _get_background(self, image, tile_size=32): sigma_clip = SigmaClip(sigma=3., iters=3) bkg_estimator = MedianBackground() bkg = Background2D(image, tile_size, filter_size=3, sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) return bkg.background
def doSubtractBackground(self, rgb): sigma_clip = SigmaClip(sigma=3.0) bkg_estimator = MedianBackground() for j in range(3): bkg = Background2D(rgb[j], (50, 50), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) #print("Bkg median: %7.4f, RMS median: %7.4f" % (bkg.background_median, bkg.background_rms_median)) rgb[j] -= bkg.background imshow(bkg.background, origin='lower', cmap='Greys_r')
async def __call__(self, image: Image) -> Image: """Find stars in given image and append catalog. Args: image: Image to find stars in. Returns: Image with attached catalog. """ from astropy.stats import SigmaClip, sigma_clipped_stats from photutils import Background2D, MedianBackground, DAOStarFinder # get data if image.data is None: log.warning("No data found in image.") return image data = image.data.astype(float).copy() # estimate background sigma_clip = SigmaClip(sigma=self.bkg_sigma) bkg_estimator = MedianBackground() bkg = Background2D( data, self.bkg_box_size, filter_size=self.bkg_filter_size, sigma_clip=sigma_clip, bkg_estimator=bkg_estimator, mask=image.mask, ) data -= bkg.background # do statistics mean, median, std = sigma_clipped_stats(data, sigma=3.0) # find stars daofind = DAOStarFinder(fwhm=self.fwhm, threshold=self.threshold * std) loop = asyncio.get_running_loop() sources = await loop.run_in_executor(None, daofind, data - median) # rename columns sources.rename_column("xcentroid", "x") sources.rename_column("ycentroid", "y") # match fits conventions sources["x"] += 1 sources["y"] += 1 # pick columns for catalog cat = sources["x", "y", "flux", "peak"] # copy image, set catalog and return it img = image.copy() img.catalog = cat return img
def calc_background_rms(fits): image = fits[0].data sigma_clip = SigmaClip(sigma=3.) bkg_estimator = MedianBackground() bkg = Background2D(image, (50, 50), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) rms = np.sqrt((bkg.background**2).mean()) return rms
def get_sky_background(img, verbose=True): from astropy.stats import SigmaClip from photutils import Background2D, MedianBackground sigma_clip = SigmaClip(sigma=3.) bkg = Background2D(img, (100, 100), filter_size=(5, 5), sigma_clip=sigma_clip, bkg_estimator=MedianBackground()) if verbose: print('Sky background median = {:.3f}, rms = {:.3f} ADU.'.format( bkg.background_median, bkg.background_rms_median)) return bkg
def bkg(data, SNR=5, box_size=30, filter_size=3): ''' Применение медианного фильтра к изображению. ''' sigma_clip = SigmaClip(sigma=SNR) bkg_estimator = MedianBackground() bkg = Background2D(data, (box_size, box_size), filter_size=(filter_size, filter_size), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) #hdu = fits.PrimaryHDU() mean_bkg = np.mean(bkg.background) fits.writeto('background.fits', bkg.background, overwrite=True) return data - bkg.background, mean_bkg
def bkg_estimation(filename, box=(20, 20), filter_size=(3, 3), bkg_estimator='SExtractor', sigma=3., sigma_lower=None, sigma_upper=None, maxiters=10, outLevel=1): imagelist = np.atleast_1d(filename) for ima in imagelist: print("\nEstimate background in %s" % ima) root = os.path.splitext(ima)[0] hdulist = fits.open(ima) data = hdulist[0].data sigma_clip = SigmaClip(sigma=sigma, sigma_lower=sigma_lower, sigma_upper=sigma_upper, maxiters=maxiters) if bkg_estimator == 'SExtractor': bkg_estimator = SExtractorBackground() elif bkg_estimator == 'MMM': bkg_estimator = MMMBackground() elif bkg_estimator == 'ModeEstimator': bkg_estimator = ModeEstimatorBackground() elif bkg_estimator == 'Median': bkg_estimator = MedianBackground() elif bkg_estimator == 'Mean': bkg_estimator = MeanBackground() bkg = Background2D( data, box, filter_size=filter_size, sigma_clip=sigma_clip, bkg_estimator=bkg_estimator, ) # Create image with background substracted hdulist[0].data = data - bkg.background hdulist.writeto(ima, overwrite=True) if outLevel == 2: # Create image with 2D background bkg_file = root + "_bkg_map.fits" hdulist[0].data = bkg.background hdulist.writeto(bkg_file, overwrite=True)
def _remove_background(self): # Get background map and subtract. sigma_clip = SigmaClip(sigma=3., iters=10) bkg_estimator = MedianBackground() self._bkg = Background2D(self.raw_image, (self.bkg_box_size, self.bkg_box_size), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) self.background_map = self._bkg.background self.image = self.raw_image - self.background_map self._med = self._bkg.background_median self._std = self._bkg.background_rms_median
def subtractFitsBackground(fitsFileName): if exists(fitsFileName): hdul = fits.open(fitsFileName, mode='update') data = hdul[0].data sigma_clip = SigmaClip(sigma=3.0) bkg_estimator = MedianBackground() bkg = Background2D(data, (50, 50), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) #print("Bkg median: %7.4f, RMS median: %7.4f" % (bkg.background_median, bkg.background_rms_median)) data -= bkg.background hdul.flush() hdul.close()
def _background2d(self): """ Estimate the 2D background and background RMS noise in an image. Parameters ---------- box_size : int or array_like (int) The box size along each axis. If ``box_size`` is a scalar then a square box of size ``box_size`` will be used. If ``box_size`` has two elements, they should be in ``(ny, nx)`` order. coverage_mask : bool ndarray Returns ------- background : `photutils.background.Background2D` A Background2D object containing the 2D background and background RMS noise estimates. """ sigma_clip = SigmaClip(sigma=3.) bkg_estimator = MedianBackground() filter_size = (3, 3) try: bkg = Background2D(self.data, self.box_size, filter_size=filter_size, mask=self.mask, sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) except ValueError: # use the entire unmasked array bkg = Background2D(self.data, self.data.shape, filter_size=filter_size, mask=self.mask, sigma_clip=sigma_clip, bkg_estimator=bkg_estimator, exclude_percentile=100.) log.info('Background could not be estimated in meshes. ' 'Using the entire unmasked array for background ' f'estimation: bkg_boxsize={self.data.shape}.') # apply the coverage mask bkg.background *= np.logical_not(self.mask) bkg.background_rms *= np.logical_not(self.mask) return bkg
def bkg_sub(img, mask, sigma=5, bkg_estimator='median', box=(10, 2), filter_size=(1, 1)): """ Completes a step for fitting a 2D background model. Parameters ---------- img : np.ndarray Single exposure frame. mask : np.ndarray Mask to remove the orders. sigma : float, optional Sigma to remove above. Default is 5. bkg_estimator : str, optional Which type of 2D background model to use. Default is `median`. box : tuple, optional Box size by which to smooth over. Default is (10,2) --> prioritizes smoothing by column. filter_size : tuple, optional The window size of the 2D filter to apply to the low-resolution background map. Default is (1,1). Returns ------- background : np.ndarray The modeled background image. """ sigma_clip = SigmaClip(sigma=sigma) if bkg_estimator.lower() == 'mmmbackground': bkg = MMMBackground() elif bkg_estimator.lower() == 'median': bkg = MedianBackground() b = Background2D(img, box, filter_size=filter_size, bkg_estimator=bkg, sigma_clip=sigma_clip, fill_value=0.0, mask=mask) return b.background
def return_backgrounds(image, mask, mskimg_fname, saveBackground=True): rms_fname = mskimg_fname.replace('mskimg', 'rmsimg') if os.path.exists(rms_fname): with fits.open(rms_fname) as f: rms = f[0].data else: bkg = Background2D(image, (10, 10), mask=mask, filter_size=1, bkg_estimator=MedianBackground(sigma_clip=None), bkgrms_estimator=StdBackgroundRMS(sigma_clip=None)) rms = bkg.background_rms.astype(np.float32) if saveBackground: create_fits(rms_fname, rms) return rms
def bkg_subs(image, box, snr=2, npixels=5, dilate_size=15): """Substrackt the background of an image. Sources are idenfified first and masked, then the background is estimated as the (sigma-clipped) median. """ # get data from file data = fits.getdata(image) # create mask nan_mask = np.isnan(data) source_mask = make_source_mask(data, snr=snr, npixels=npixels, dilate_size=dilate_size) mask = np.logical_or(nan_mask, source_mask) bkg_estimator = MedianBackground() bkg = Background2D(data, box, filter_size=1, bkg_estimator=bkg_estimator, mask=mask) return data - bkg.background
def find_centroid(data): """ find the centroid again after the image was rotated """ sigma_clip = SigmaClip(sigma=3., iters=10) bkg_estimator = MedianBackground() bkg = Background2D(data, (25, 25), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) threshold = bkg.background + (3. * bkg.background_rms) sigma = 2.0 * gaussian_fwhm_to_sigma # FWHM = 2. kernel = Gaussian2DKernel(sigma, x_size=3, y_size=3) kernel.normalize() segm = detect_sources(data, threshold, npixels=5, filter_kernel=kernel) props = source_properties(data, segm) tbl = properties_table(props) my_min = 100000. x_shape = np.float(data.shape[0]) y_shape = np.float(data.shape[1]) r = 3. # approximate isophotal extent apertures = [] for prop in props: position = (prop.xcentroid.value, prop.ycentroid.value) #print(position) a = prop.semimajor_axis_sigma.value * r b = prop.semiminor_axis_sigma.value * r theta = prop.orientation.value apertures.append(EllipticalAperture(position, a, b, theta=theta)) my_dist = np.sqrt((prop.xcentroid.value - x_shape / 2.)**2 + (prop.ycentroid.value - y_shape / 2.)**2) if (my_dist < my_min): my_label = prop.id - 1 my_min = my_dist mytheta = props[my_label].orientation.value mysize = np.int(np.round(r * props[my_label].semimajor_axis_sigma.value)) my_x = props[my_label].xcentroid.value my_y = props[my_label].ycentroid.value return my_x, my_y, mytheta, mysize
def get_kernel(image, stars_cata, plot=False): print len(stars_cata) hal_size = 10 print hal_size stamps = [] for k in range(len(stars_cata)): print '\tStar position: %f, %f' % (stars_cata['X_IMAGE'][k], stars_cata['Y_IMAGE'][k]) print '\tStar size : ', stars_cata['FWHM_IMAGE'][k] col_pix = int(stars_cata['X_IMAGE'][k]) row_pix = int(stars_cata['Y_IMAGE'][k]) stamp = image[row_pix - hal_size: row_pix + hal_size + 1, col_pix - hal_size: col_pix + hal_size + 1].copy() stamp_bkg = image[row_pix - hal_size * 2: row_pix + hal_size * 2, col_pix - hal_size * 2: col_pix + hal_size * 2].copy() # background sigma_clip = SigmaClip(sigma=3., iters=2) bkg_estimator = MedianBackground() bkg = Background2D(stamp_bkg, (hal_size * 2, hal_size * 2), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) stamp = stamp - bkg.background[hal_size: hal_size * 3 + 1, hal_size: hal_size * 3 + 1] # stamp[stamp < 0] = 0 stamp /= stamp.sum() print '\tStar sum :', stamp.sum() # plt.imshow(norm_stamp, cmap='viridis', interpolation='nearest') # plt.colorbar() # plt.show() stamps.append(stamp) stamps = np.array(stamps) kernel = np.median(stamps, axis=0) kernel /= kernel.sum() print '\tPSF sum :', kernel.sum() if plot: plt.imshow(kernel, cmap='viridis', interpolation='nearest') plt.colorbar() plt.show() return kernel
def psf_photometry(img, filename): warnings.filterwarnings('ignore', category=UserWarning, append=True) sigma_clip = SigmaClip(sigma=3., iters=10) bkgrms = MADStdBackgroundRMS() bkg_estimator = MedianBackground() bkgimg = Background2D(img, (10, 10), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) sigma_psf = 3 daofind = DAOStarFinder(fwhm=3.0, threshold=5. * mad_std(img)) daogroup = DAOGroup(2.0 * sigma_psf * gaussian_sigma_to_fwhm) fitter = LevMarLSQFitter() psf_model = IntegratedGaussianPRF(sigma=sigma_psf) photometry = IterativelySubtractedPSFPhotometry( finder=daofind, group_maker=daogroup, bkg_estimator=bkg_estimator, psf_model=psf_model, fitter=LevMarLSQFitter(), niters=100, fitshape=(11, 11)) #photometry = DAOPhotPSFPhotometry psftab = photometry(image=img).to_pandas() psftab = psftab.rename(columns={ 'flux_fit': 'PSF_FLUX', 'flux_unc': 'PSF_FLUX_ERR' }) psftab = psftab.apply(pd.to_numeric, errors='ignore') #psftab['STAR_FLUX'] = psftab['APERTURE_FLUX'] - psftab['BKG_FLUX'] #psftab['STAR_FLUX_ERR'] = np.sqrt(phot['APERTURE_FLUX_ERR']**2 + phot['BKG_FLUX_ERR']**2) #psftab['VEGAMAG'] = vegazpt - 2.5 * np.log10(phot['STAR_FLUX']) #psftab['VEGAMAG_UNC'] = 1.0857 * psftab['STAR_FLUX_ERR'] / psftab['STAR_FLUX'] psftab.to_csv('psf_table_' + str(shortfile) + '.csv') residual_image = photometry.get_residual_image() shortfile = filename.split('.fits')[0] plt.imshow(residual_image, cmap='gray_r') plt.savefig('resimg_' + str(shortfile) + '.jpg') return result_tab.reset_index()
def get_photometry(image, mask=None, gain=4., pos=(dx_stamp, dx_stamp), radii=10.): sigma_clip = SigmaClip(sigma=3., iters=2) bkg_estimator = MedianBackground() bkg = Background2D(image, (10, 10), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) print '\tBackground stats: %f, %f' % (bkg.background_median, bkg.background_rms_median) data = image - bkg.background # bkg_err = np.random.normal(bkg.background_median, # bkg.background_rms_median, image.shape) if False: plt.imshow(data, cmap='viridis', interpolation='nearest') plt.colorbar() plt.show() # error = calc_total_error(image, bkg_err, gain) back_mean, back_median, back_std = sigma_clipped_stats(data, mask, sigma=3, iters=3, cenfunc=np.median) print '\tBackground stats: %f, %f' % (back_median, back_std) tbl = find_peaks(data, np.minimum(back_std, bkg.background_rms_median) * 3, box_size=5, subpixel=True) print tbl tree_XY = cKDTree(np.array([tbl['x_peak'], tbl['y_peak']]).T) dist, indx = tree_XY.query(pos, k=1, distance_upper_bound=5) if np.isinf(dist): print '\tNo source found in the asked position...' return None position = [tbl[indx]['x_centroid'], tbl[indx]['y_centroid']] print '\tObject position: ', position apertures = [CircularAperture(position, r=r) for r in radii] phot_table = aperture_photometry(data, apertures, mask=mask, method='subpixel', subpixels=5) for k, r in enumerate(radii): area = np.pi * r ** 2 phot_table['aperture_flx_err_%i' % k] = np.sqrt(area * bkg.background_rms_median ** 2 + phot_table['aperture_sum_%i' % k] / gain) phot_table.remove_columns(['xcenter', 'ycenter']) phot_table['xcenter'] = position[0] phot_table['ycenter'] = position[1] return phot_table
def bg_2d(data, box_size=50): sigma_clip = SigmaClip(sigma=3.) bkg_estimator = MedianBackground() bkg = Background2D(data, (box_size, box_size), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) # plt.ion() # fig, ax = plt.subplots(nrows=1, ncols=3, sharex=True, sharey=True, figsize=(16,7)) # avg, med, std = sigma_clipped_stats(data) # ax[0].imshow(data, origin='lower', vmin=med, vmax=med+3*std) # ax[1].imshow(bkg.background, origin='lower', vmin=med, vmax=med+3*std) # avg, med, std = sigma_clipped_stats(data-bkg.background) # ax[2].imshow(data-bkg.background, origin='lower', vmin=med, vmax=med+3*std) # plt.tight_layout() # pdb.set_trace() return data - bkg.background
def extract_sources(img, fwhm=2.0, threshold=None, source_box=7, sharp=None, output=None, plot=False, vmax=None): """Use photutils to find sources in image based on segmentation.""" if threshold is None: bkg_estimator = MedianBackground() bkg = Background2D(img, (50, 50), filter_size=(3, 3), bkg_estimator=bkg_estimator) threshold = bkg.background + (3. * bkg.background_rms) sigma = fwhm * gaussian_fwhm_to_sigma kernel = Gaussian2DKernel(sigma, x_size=source_box, y_size=source_box) kernel.normalize() segm = detect_sources(img, threshold, npixels=source_box, filter_kernel=kernel) cat = source_properties(img, segm) print("Total Number of detected sources: {}".format(len(cat))) if sharp: # Remove sources that do not fall within specified sharpness limit newcat = photutils.segmentation.properties.SourceCatalog([]) for obj in cat: src_peak = (obj.max_value - (obj.source_sum/obj.area.value)) kern_peak = (kernel*obj.source_sum).array.max() sharpness = src_peak/kern_peak if sharpness < sharp[0] or sharpness > sharp[1]: newcat._data.append(obj) else: newcat = cat print("Final Number of selected sources: {}".format(len(newcat))) if output: tbl = newcat.to_table() tbl['xcentroid'].info.format = '.10f' # optional format tbl['ycentroid'].info.format = '.10f' tbl['cxy'].info.format = '.10f' tbl['cyy'].info.format = '.10f' tbl.write(output, format='ascii.ecsv') if plot: norm = None if vmax is None: norm = ImageNormalize(stretch=SqrtStretch()) fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 8)) ax1.imshow(img, origin='lower', cmap='Greys_r', norm=norm, vmax=vmax) ax2.imshow(segm, origin='lower', cmap=segm.cmap(random_state=12345)) return newcat, segm
def model_bkg(data, mask=None): """ BkgZoomInterpolator: This class generates full-sized background and background RMS images from lower-resolution mesh images using the `~scipy.ndimage.zoom` (spline) interpolator. """ model = Background2D( data, mask=mask, box_size=(64, 50), filter_size=15, exclude_percentile=20, sigma_clip=SigmaClip(sigma=3.0, maxiters=5), bkg_estimator=MedianBackground(), interpolator=BkgZoomInterpolator(order=3), ) return model.background
def aper_phot(img_data,positions, r = 10., r_in = 14., r_out = 18,bkg_sub=False,plot=False): """ :params: r: Aperture Radius :params: r_in: annulus aperture inside radius :params: r_out: annulus aperture outside radius :params: bkg_sub: True if background subtraction is needed :params: plot: True to plot :out: phot_table: Table with the values of the aperture photometry """ #Background subtraction if bkg_sub == True: sigma_clip = SigmaClip(sigma=3., iters=10) bkg_estimator = MedianBackground() bkg = Background2D(img_data, (50, 50), filter_size=(3, 3),sigma_clip=sigma_clip, bkg_estimator=bkg_estimator) data_sub = img_data - bkg.background else: data_sub = img_data #Aperture Photometry using a circular aperture and a circular annulus apertures = CircularAperture(positions, r=r) annulus_apertures = CircularAnnulus(positions,r_in = r_in,r_out = r_out) apers = [apertures,annulus_apertures] phot_table = aperture_photometry(data_sub, apers) bkg_mean = phot_table['aperture_sum_1'] / annulus_apertures.area() bkg_sum = bkg_mean * apertures.area() final_sum = phot_table['aperture_sum_0'] - bkg_sum phot_table['residual_aperture_sum'] = final_sum positions = np.array(positions) if plot == True: #Ploting norm = ImageNormalize(data_sub, interval=ZScaleInterval(),stretch=LinearStretch()) plt.imshow(data_sub, cmap='Greys', origin='lower',norm=norm) apertures.plot(color='blue', lw=1.5, alpha=0.5) annulus_apertures.plot(color='green',lw=1.5,alpha=0.5) plt.plot(positions[:,0],positions[:,1], ls='none', color = 'red', marker='.', ms=10, lw=1.5) plt.xlim(0, data_sub.shape[1]-1) plt.ylim(0, data_sub.shape[0]-1) plt.show() return phot_table
def estimate(image, sigma=3.0, sigma_clip_iters=10, mesh_size=(75, 75), filter_size=(5, 5), mask_value=None): mask = (image == mask_value) sigma_clip = SigmaClip(sigma=sigma, iters=sigma_clip_iters) bkg_estimator = MedianBackground() bkg = Background2D(image, mesh_size, filter_size=filter_size, sigma_clip=sigma_clip, bkg_estimator=bkg_estimator, mask=mask) return bkg.background_median, bkg.background_rms_median, bkg, mask
def bkgstd(im_data, mask): """Estimate the RMS standard deviation of the background in the `im_data` image. Arguments --------- im_data : array_like Image data mask : array_like Mask to apply to image Returns ------- np.ndarray RMS standard deviation of the background image """ # use crude image segmentation to find sources above SNR=3, build a # source mask, and estimate the background RMS source_mask = make_source_mask(im_data, snr=3, npixels=5, dilate_size=15, mask=mask) # combine the bad pixel mask and source mask rough_mask = np.logical_or(mask, source_mask) # estimate the background standard deviation try: sigma_clip = SigmaClip(sigma=3, maxiters=5) # sigma clipping except TypeError: # in old astropy, "maxiters" was "iters" sigma_clip = SigmaClip(sigma=3, iters=5) try: bkg = Background2D(im_data, (50,50), filter_size=(5,5), sigma_clip=sigma_clip, bkg_estimator=MedianBackground(), mask=rough_mask) except ValueError: e = sys.exc_info() print("\nWhile attempting background estimation on the "+ "science image, the following error was raised: "+ f"\n{str(e[0])}\n{str(e[1])}\n--> exiting.") return return bkg.background_rms