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 _aperture_convolve_img(orig_img, aperture_radius, apkwargs={ 'method': 'subpixel', 'subpixels': 4 }): """ Perform aperture photometry on every pixel in a 2-D image Input: orig_img: Npix x Npix image aperture_radius: radius of the circular aperture Returns: phot_img: image of the aperture photometry on every non-nan pixel """ phot_img = np.zeros(orig_img.shape) nanpix = np.where(np.isnan(orig_img)) notnanpix = np.where(~np.isnan(orig_img)) orig_shape = orig_img.shape img = orig_img.copy() # let's not modify the original cube img[nanpix] = 0.0 # put an aperture on every non-nan pixel img_apertures = CircularAperture(positions=zip(*notnanpix[::-1]), r=aperture_radius) img_phot = aperture_photometry(img, img_apertures, **apkwargs) # set up to calculate the flattened indices ncols = np.ones_like(img_phot['ycenter']) * img.shape[-1] flattened_ind = lambda n, row, col: n * row + col ind = np.array(map(flattened_ind, ncols, img_phot['ycenter'], img_phot['xcenter']), dtype=np.int) phot_img = np.ravel(phot_img) # map the photometry to the cube phot_img[ind] = img_phot['aperture_sum'] phot_img = phot_img.reshape(orig_shape) # re-assign the nan pixels phot_img[nanpix] = np.nan return phot_img
def run(self) -> None: """ Run method of the module. Computes the flux within a circular aperture for each frame and saves the values in the database. Returns ------- NoneType None """ def _photometry(image, aperture): # https://photutils.readthedocs.io/en/stable/overview.html # In Photutils, pixel coordinates are zero-indexed, meaning that (x, y) = (0, 0) # corresponds to the center of the lowest, leftmost array element. This means that # the value of data[0, 0] is taken as the value over the range -0.5 < x <= 0.5, # -0.5 < y <= 0.5. Note that this is the same coordinate system as used by PynPoint. return aperture_photometry(image, aperture, method='exact')['aperture_sum'] pixscale = self.m_image_in_port.get_attribute('PIXSCALE') self.m_radius /= pixscale if self.m_position is None: self.m_position = center_subpixel(self.m_image_in_port[0, ]) # Position in CircularAperture is defined as (x, y) aperture = CircularAperture((self.m_position[1], self.m_position[0]), self.m_radius) self.apply_function_to_images(_photometry, self.m_image_in_port, self.m_phot_out_port, 'Running AperturePhotometryModule', func_args=(aperture, )) history = f'radius [arcsec] = {self.m_radius*pixscale:.3f}' self.m_phot_out_port.copy_attributes(self.m_image_in_port) self.m_phot_out_port.add_history('AperturePhotometryModule', history) self.m_phot_out_port.close_port()
def plot(self, scale='log'): apertures = CircularAperture([self.locx, self.locy], r=self.r) z = self.copy() z -= np.nanmedian(z) if scale == 'log': z = np.log10(self) z = ma.masked_invalid(z) z.mask = z.mask | (z < 0) z.fill_value = 0 z = z.filled() imshow2(z) if self.pixels is not None: for i, pos in enumerate(self.pixels): r, c = pos plt.text(c, r, i, va='center', ha='center', color='Orange') apertures.plot(color='Lime', lw=1.5, alpha=0.5) plt.xlabel('Column (pixels)') plt.ylabel('Row (pixels)')
def circular_aperture_img(pattern): for filename in pattern: header = get_fits_header(filename) wcs = WCS(header) c = img_coords(pattern) loc = c['loc'] e = dict(); e['data'] = get_fits_data(filename) e['positions'] = np.transpose(loc) e['apertures'] = CircularAperture(e['positions'], r=6.8) e['annulus_aperture'] = CircularAnnulus(e['positions'], r_in=10, r_out=15) phot_table = aperture_photometry(e['data'], e['apertures']) for col in phot_table.colnames: phot_table[col].info.format = '%.8g' bkg_mean = phot_table['aperture_sum'] / e['annulus_aperture'].area bkg_sum = bkg_mean * e['apertures'].area final_sum = phot_table['aperture_sum'] - bkg_sum phot_table['residual_aperture_sum'] = final_sum print(phot_table) ## print(phot_table[29]) #GJ3470 location return(e)
def mag(image, x, y, radius=3.89245, returnflux=False, returntable=False): ''' Compute instrument magnitudes of one object. Defaults are set to CLIO 3.9um optimal. Parameters: ----------- image : 2d array science image x,y : flt x and y pixel location of center of star radius : flt pixel radius for aperture. Default = 3.89, approx 1/2 L/D for CLIO 3.9um r_in, r_out : flt inside and outside radius for background annulus. Default = 10,12 returnflux : bool if true, return the instrument mag and the raw flux value. returntable : bool if true, return the entire photometry table. Returns: -------- flt instrument magnitudes of source flt signal to noise ratio ''' from photutils import CircularAperture, CircularAnnulus, aperture_photometry # Position of star: positions = [(x, y)] # Get sum of all pixel values within radius of center: aperture = CircularAperture(positions, r=radius) # Do photometry on star: phot_table = aperture_photometry(image, aperture) m = (-2.5) * np.log10(phot_table['aperture_sum'][0]) if returnflux: return m, phot_table['aperture_sum'][0] if returntable: phot_table['Mag'] = m return m, phot_table return m
def set_apertures(self, stars_coords, fwhm): self.annulus_apertures = CircularAnnulus( stars_coords, r_in=self.annulus_inner_radius * fwhm, r_out=self.annulus_outer_radius * fwhm, ) if callable(self.annulus_apertures.area): self.annulus_area = self.annulus_apertures.area() else: self.annulus_area = self.annulus_apertures.area self.circular_apertures = [CircularAperture(stars_coords, r=fwhm*aperture) for aperture in self.apertures] # Unresolved buf; sometimes circular_apertures.area is a method, sometimes a float if callable(self.circular_apertures[0].area): self.circular_apertures_area = [ca.area() for ca in self.circular_apertures] else: self.circular_apertures_area = [ca.area for ca in self.circular_apertures] self.annulus_masks = self.annulus_apertures.to_mask(method="center") self.n_stars = len(stars_coords)
def aperture(self, positions, bkg=None, radius=3.): from astropy.table import Table # flux, eflux = [], [] apertures = CircularAperture(positions, r=radius) if bkg is None: bkg, bkg_counts, bkg_mean = self.annulus_background(positions, radius=radius) phot_table = aperture_photometry(self.data, apertures, error=bkg) # for i in range(len(positions)): # flux.append(phot_table['aperture_sum'][i]) # eflux.append(phot_table['aperture_sum_err'][i]) # frames = [pd.DataFrame(flux).T, pd.DataFrame(eflux).T] # data_flux = pd.concat(frames,axis=1) # data_flux.columns = ['flux','eflux'] return Table(phot_table)
def circleApp(x, y, r, img_data): numAps = 20 maxR = 1.5 myPhot = list() myRs = list() myCounts = list() myCountsNoBack = list() positions = [(x, y)] # print positions print r print(maxR * r) myBackAp = CircularAnnulus(positions, r_in=maxR * r, r_out=(maxR + 0.5) * r) # / numAps) myBackPhot = aperture_photometry(img_data, myBackAp) print myBackPhot['aperture_sum'][0] myBackRate = myBackPhot['aperture_sum'][0] / myBackAp.area( ) # (math.pi * (((maxR + 0.5) * r) ** 2 - (maxR * r) ** 2)) print myBackRate for j in range(numAps): curR = maxR * r * (j + 1) / numAps aperture = CircularAperture(positions, r=curR) myRs.append(curR) # maxR*(j+1.0)/numAps myPhot.append(aperture_photometry(img_data, aperture, method="exact")) tmp = myPhot[j] myCounts.append( tmp['aperture_sum'][0] - (myBackRate * aperture.area())) # math.pi * (curR) ** 2)) myCountsNoBack.append(tmp['aperture_sum'][0]) yerr = np.sqrt(myCountsNoBack) / myCountsNoBack[ numAps - 1] # don't use subtract background return myRs, myCountsNoBack, yerr
def get_single_cube_spot_photometry(cube, spot_positions): """ Do aperture photometry on the spots. Will need to be careful about aperture size for future comparison Input: cube: Nchan x Npix x Npix data cube to do photometry spot_positions: Nspot x Nchan x 2 spot positions for apertures scaling_factors: Nchan array for scaling apertures with wavelength Output: spot_phot: Nspot x Nchan array of spot photometry and spot errors """ nchan = cube.shape[0] apsize = P1640params.aperture_refchan photometry = [] # need scaling factors to scale aperture scaling_factors = get_single_cube_scaling_factors(spot_positions).mean(axis=0) for chan in range(nchan): positions = [i[::-1] for i in spot_positions[:,chan,:]] # need to reverse row, col apertures = CircularAperture(positions = positions, r = apsize*scaling_factors[chan]) photometry.append(aperture_photometry(cube[chan], apertures)) spot_phot = np.array([i['aperture_sum'] for i in photometry]).T return spot_phot
def show_stars(self, data, sources): """ Convenience method for plotting the identified sources Parameters ---------- data : FITS data to plot sources : Sources found in the FITS data Returns ------- """ fig, ax = plt.subplots(nrows=1, ncols=1) norm = ImageNormalize(data, stretch=LinearStretch(), interval=ZScaleInterval()) im = ax.imshow(data, norm=norm, cmap='gray') # Make apertures apertures = CircularAperture( (sources['xcentroid'], sources['ycentroid']), r=3) apertures.plot(color='red', lw=1.5, alpha=0.75) plt.show()
def photometryimg(positions, img, i): positionslist = positions.tolist() aperture = CircularAperture(positionslist, r=5) #2*FWHM annulus_aperture = CircularAnnulus(positionslist, r_in=7, r_out=9)#4-5*FWHM+2*FWHM apers = [aperture, annulus_aperture] displayimage(img, 1, i) ###画图1 aperture.plot(color='blue', lw=0.5) annulus_aperture.plot(color='red', lw=0.2) plt.pause(0.001) plt.clf() phot_table = aperture_photometry(img, apers) bkg_mean = phot_table['aperture_sum_1'] / annulus_aperture.area bkg_sum = bkg_mean * aperture.area final_sum = phot_table['aperture_sum_0'] - bkg_sum phot_table['residual_aperture_sum'] = final_sum posflux = np.column_stack((positions, phot_table['residual_aperture_sum'])) #return posflux magstar = 25 - 2.5*np.log10(abs(final_sum/1)) return posflux,magstar
def showStars(image): stars = findStars(image) # take just the 5 brightest objects stars.sort('flux') stars.reverse() list = stars[:3] positions = zip(list['xcentroid'], list['ycentroid']) apertures = CircularAperture(positions, r=6) annuli = CircularAnnulus(positions, r_in=18, r_out=24) phot_table = aperture_photometry(image, [apertures, annuli]) plt.clf() plt.imshow(image, cmap='gray', norm=LogNorm()) annuli.plot(color='green', lw=1, alpha=0.75) apertures.plot(color='blue', lw=1, alpha=0.75) plt.savefig('%s.png' % path, dpi=300) print list print phot_table
def set_target(self, position, radius, name=None): """ Configure the target object\'s position, aperture radius, and name. Arguments: position: tuple of len 2, x and y coordinates of target. radius: int, aperture radius in pixels. name: optional, str, name of the target object Example: set_target((1108.81, 1015.97), 8, "Lx Ser") """ if type(position) == tuple and len(position) == 2: self.target_pos = position self.target_aperture = CircularAperture(position, r=radius) if type(name) == str: self.target_name = name self.target = [] #running this function resets the aperture photometry values of target. else: print("Position must be provided as a tuple of len 2.\nExample: (1108.81, 1015.97)") return
def save_source_plot(mdy, cap_fname, sources, im_data, ref=False, basedir=base_path): os.makedirs(os.path.join(basedir, log_path, mdy), exist_ok=True) positions = (sources['xcentroid'], sources['ycentroid']) apertures = CircularAperture(positions, r=4.) norm = ImageNormalize(stretch=SqrtStretch()) plt.figure() apertures.plot(color='blue', lw=1.5, alpha=0.5) plt.imshow(im_data, cmap='Greys', origin='lower', norm=norm) prefix, num, obj_name = parse_fits_name(cap_fname) if ref: plot_fpath = os.path.join( basedir, log_path, mdy, prefix + '.' + num + '.' + obj_name + '.ref.png') else: plot_fpath = os.path.join(basedir, log_path, mdy, prefix + '.' + num + '.' + obj_name + '.png') plt.savefig(plot_fpath) plt.close()
def measure_profile(image, step, reso=1.5, maxtheta=180): profile, profile_unc = [], [] center = len(image) / 2. - 0.5 steppix = step / reso inner_aper = CircularAperture([center, center], steppix) profile.append( float( aperture_photometry(image, inner_aper)['aperture_sum'] / inner_aper.area)) i = 1 while step * i < maxtheta: new_aper = CircularAnnulus([center, center], steppix * i, steppix * (i + 1)) profile.append( float( aperture_photometry(image, new_aper)['aperture_sum'] / new_aper.area)) i += 1 return np.array(profile)
def create_aperture(aperture): """ Function to create a circular or elliptical aperture. Parameters ---------- aperture : dict Dictionary with the aperture properties. The aperture 'type' can be 'circular' or 'elliptical' (str). Both types of apertures require a position, 'pos_x' and 'pos_y' (float), where the aperture is placed. The circular aperture requires a 'radius' (in pixels, float) and the elliptical aperture requires a 'semimajor' and 'semiminor' axis (in pixels, float), and an 'angle' (deg). The rotation angle in degrees of the semimajor axis from the positive x axis. The rotation angle increases counterclockwise. Returns ------- photutils.aperture.circle.CircularAperture or photutils.aperture.circle.EllipticalAperture Aperture object. """ if aperture['type'] == "circular": phot_ap = CircularAperture((aperture['pos_x'], aperture['pos_y']), aperture['radius']) elif aperture['type'] == "elliptical": phot_ap = EllipticalAperture((aperture['pos_x'], aperture['pos_y']), aperture['semimajor'], aperture['semiminor'], math.radians(aperture['angle'])) else: raise ValueError("Aperture type not recognized.") return phot_ap
def CircleMaskPhometry(data, location, index=2): Mimgdata = np.copy(data) Mlocatin = np.copy(location) Mapeture = CircularAperture(Mlocatin, r=6) Mannuals = CircularAnnulus(Mlocatin, r_in=8., r_out=11.) Eannuals_masks = Mannuals.to_mask(method='center') bkg_median = [] for mask in Eannuals_masks: Eannuals_data = mask.multiply(Mimgdata) Eannulus_data_1d = Eannuals_data[mask.data > 0] meandata, median_sigclip, _ = sigma_clipped_stats(Eannulus_data_1d) bkg_median.append(median_sigclip) bkg_median = np.array(bkg_median) phot = aperture_photometry(Mimgdata, Mapeture) phot['annulus_median'] = bkg_median phot['aper_bkg'] = bkg_median * Mapeture.area phot['aper_sum_bkgsub'] = phot['aperture_sum'] - phot['aper_bkg'] Mpositionflux = np.transpose( (phot['xcenter'], phot['ycenter'], phot['aper_sum_bkgsub'])) displayimage(Mimgdata, 3, index) Mapeture.plot(color='blue', lw=0.5) Mannuals.plot(color='red', lw=0.2) plt.pause(0.001) plt.clf() #Mannulus_data = Eannuals_masks[0].multiply(Mimgdata) #displayimage(Mannulus_data,3,index+1) flux_sum = phot['aper_sum_bkgsub'] magstar = 25 - 2.5 * np.log10(abs(flux_sum / 1)) return Mpositionflux, magstar
def calculate_sky_background(img, images_info, return_table=False): nskyap = 10000 xlen, ylen = img.shape nanmask = pd.isnull(img) xnpos = np.random.uniform(low=1, high=xlen, size=nskyap) ynpos = np.random.uniform(low=1, high=ylen, size=nskyap) xynpos = list(zip(xnpos, ynpos)) ap = 0.4 / images_info.loc[0, 'PIXSCALE'] napers = CircularAperture(xynpos, r=ap) noise_table = aperture_photometry(img, napers, mask=nanmask, method='exact') for col in noise_table.colnames: noise_table[col].info.format = '%.8g' # for consistent table output noise_table = Table(noise_table).to_pandas() noise_table['aperture_area'] = napers.area #Sigma Clip image to avoid stars b1 = sigma_clip(noise_table['aperture_sum'] ) #, masked=False, axis=0) #default = 3 sigma a1 = b1.data[~b1.mask] a2 = b1.mask a2 = np.array([not x for x in a2]) sigclip_skyflux = noise_table['aperture_sum'] * a2 bkgflux = np.average(a1) #rmean bkgfluxerr = np.nanstd(a1) #rstd print('background flux = ' + str(bkgflux)) print('background flux error = ' + str(bkgfluxerr)) if return_table: return noise_table else: return [bkgflux, bkgfluxerr]
def recalc_fluxes(): ''' Nesta função o raio tem que vir pelo javascript pois ele é mudado num widget do bokeh ''' req = request.get_json() data = pd.DataFrame(dict( x=req['x'], y=req['y'], flux=req['flux'], banda=req['banda'] )) r = req['r'] session.modifeid = True session['r'] = r # Salva o novo raio print(session['pathname']+'data.json') with open(session['pathname']+'data.json') as f: dirdata = json.load(f) dirdata['r'] = r with open(session['pathname']+'data.json','w') as f: json.dump(dirdata,f) for banda in data['banda']: fname = banda.split(':')[1] img = fits.getdata(session['pathname']+fname) aperture = CircularAperture(data[['x','y']][data['banda']==banda], r) fluxes = aperture_photometry(img,aperture) data['flux'][data['banda']==banda] = fluxes['aperture_sum'] res = make_response(data.to_json(),200) return res
def run(self): """ Run method of the module. Calculates the counts for each frames and saves the values in the database. :return: None """ def _photometry(image, aperture): photo = aperture_photometry(image, aperture, method='exact') return photo['aperture_sum'] self.m_phot_out_port.del_all_data() self.m_phot_out_port.del_all_attributes() pixscale = self.m_image_in_port.get_attribute("PIXSCALE") self.m_radius /= pixscale size = self.m_image_in_port.get_shape()[1] if self.m_position is None: self.m_position = (size / 2., size / 2.) # Position in CircularAperture is defined as (x, y) aperture = CircularAperture(self.m_position, self.m_radius) self.apply_function_to_images(_photometry, self.m_image_in_port, self.m_phot_out_port, "Running AperturePhotometryModule...", func_args=(aperture, )) self.m_phot_out_port.copy_attributes_from_input_port( self.m_image_in_port) self.m_phot_out_port.add_history_information( "AperturePhotometryModule", "radius = " + str(self.m_radius * pixscale)) self.m_phot_out_port.close_port()
def run_counting(self): if self.images: self.find_sources_in_all_images() self.do_aperture_flux_measurement_in_all_images() print( "Choose the reference star on image that popped on the screen!" ) print( "Use left mouse button. If you made a mistake simply click on correct star." ) print("Close the window or hit Enter to proceed...\n") image = self.images[0] positions = self.sources_positions[0] object_aperture = CircularAperture(positions, self.aperture_radius) background_annulus = CircularAnnulus(positions, self._irad_annulus, self._orad_annulus) self.ax.imshow(image, norm=colors.PowerNorm(gamma=0.5), cmap='PuBu_r') object_aperture.plot(color='white', lw=1) background_annulus.plot(color='white', lw=1) self.interactive = True plt.show() # Continue when image is closed threshold_flux = self.fluxes_in_all_images[0][ self.reference_star_idx] counts = self.count_stars(threshold_flux) for f, c in zip(self.file_names, counts): print("{:5d} counts in central circle of image : {}".format( c, f)) print("\nAverage number of stars in central circle = {:.1f}\n". format(np.mean(counts)))
def check_adjustments(self): if self.images: print("Current adjustments are:\n") print("Aperture radius = {} pix".format(self.aperture_radius)) print("FWHM = {} pix".format(self.fwhm)) print("Threshold = {:.2f}\n".format(self.threshold)) #------------------------------------------------------------------- image = self.images[0] positions = None if len(self.images) == len(self.sources_positions): positions = self.sources_positions[0] else: positions = self.get_positions(image) # ------------------------------------------------------------------ object_aperture = CircularAperture(positions, self.aperture_radius) background_annulus = CircularAnnulus(positions, self._irad_annulus, self._orad_annulus) self.ax.imshow(image, norm=colors.PowerNorm(gamma=0.5), cmap='PuBu_r') object_aperture.plot(color='white', lw=1) background_annulus.plot(color='white', lw=1) self.interactive = False plt.show()
def updateCoords(self, frame, x, y, gauss=False): x = int(x) y = int(y) if gauss: try: # plt.figure() # plt.imshow(frame.imdata[y-2*w:y+2*w, x-2*w:x+2*w], cmap='gray') # plt.title('Gaussian fitting space') # plt.show() gaussian = fit_2dgaussian(frame.imdata[y-w:y+w, x-w:x+w]) x += gaussian.x_mean.value - w y += gaussian.y_mean.value - w except ValueError: print( '({}, {}: [{}:{}, {}:{}]'.format( self.x[frame], self.y[frame], y-w, y+w, x-w, x+w ) ) self.apertures[frame] = CircularAperture([x, y], self.r) self.annuli[frame] = CircularAnnulus( [x, y], self.r+self.d_d, self.r+self.d_d+self.d_a ) self.x[frame] = x self.y[frame] = y
def set_aperture_properties(self): """ Calculate the aperture photometry. The values are set as dynamic attributes. """ apertures = [ CircularAperture(self.xypos, radius) for radius in self.aperture_params['aperture_radii'] ] aper_phot = aperture_photometry(self.model.data, apertures, error=self.error) for i, aperture in enumerate(apertures): flux_col = f'aperture_sum_{i}' flux_err_col = f'aperture_sum_err_{i}' # subtract the local background measured in the annulus aper_phot[flux_col] -= (self.aper_bkg_flux * aperture.area) flux = aper_phot[flux_col] flux_err = aper_phot[flux_err_col] abmag, abmag_err = self.convert_flux_to_abmag(flux, flux_err) vegamag = abmag - self.abvega_offset vegamag_err = abmag_err idx0 = 2 * i idx1 = (2 * i) + 1 setattr(self, self.aperture_flux_colnames[idx0], flux) setattr(self, self.aperture_flux_colnames[idx1], flux_err) setattr(self, self.aperture_abmag_colnames[idx0], abmag) setattr(self, self.aperture_abmag_colnames[idx1], abmag_err) setattr(self, self.aperture_vegamag_colnames[idx0], vegamag) setattr(self, self.aperture_vegamag_colnames[idx1], vegamag_err)
def run(self): """ Run method of the module. Computes the flux within a circular aperture for each frame and saves the values in the database. Returns ------- NoneType None """ def _photometry(image, aperture): return aperture_photometry(image, aperture, method='exact')['aperture_sum'] self.m_phot_out_port.del_all_data() self.m_phot_out_port.del_all_attributes() pixscale = self.m_image_in_port.get_attribute("PIXSCALE") self.m_radius /= pixscale if self.m_position is None: self.m_position = center_subpixel(self.m_image_in_port[0, ]) # Position in CircularAperture is defined as (x, y) aperture = CircularAperture(self.m_position, self.m_radius) self.apply_function_to_images(_photometry, self.m_image_in_port, self.m_phot_out_port, "Running AperturePhotometryModule...", func_args=(aperture, )) history = "radius [arcsec] = {:.3f}".format(self.m_radius*pixscale) self.m_phot_out_port.copy_attributes(self.m_image_in_port) self.m_phot_out_port.add_history("AperturePhotometryModule", history) self.m_phot_out_port.close_port()
def circle_aperture_pix(filename, position, r_end=7, plot=True): #Opening FITS, getting data and header ima = Image(os.getcwd() + '/DATA/' + filename + '.fits') hdr = ima.data_header data = ima.data.copy() #Galaxy center position and position for apertures center = (hdr['CRPIX1'], hdr['CRPIX2']) position = position + center #Defining radius for circular apertures radius = 50 * np.arange(1, r_end) aperture = [CircularAperture(position, r=i) for i in radius] if plot == True: #Plot galaxy image with apertures fig, ax = plt.subplots() ima.data[ima.data < 0] = 0 ima.plot(ax, scale='log', vmin=0, vmax=0.9 * np.amax(ima.data), colorbar='v') for i in range(len(aperture)): aperture[i].plot(ax, color='white', lw=2) ax.set_title(r'Original image - NGC 3614') #plt.savefig('Image_apertures', dpi = 200) #Table with apertures data (flux sum) phot_table = aperture_photometry(data, aperture) for col in phot_table.colnames: phot_table[col].info.format = '%.8g' print(phot_table) return data, position, aperture
def compute_fwhm_enclosed(imgs, xc, yc, minrad=0.01, maxrad=15.0): peak_pix = wcs_to_pix_np((xc, yc)) peak = imgs[tuple(peak_pix)] rad = np.logspace(np.log10(minrad), np.log10(maxrad), num=100) flux = np.zeros_like(rad) positions = [(xc, yc)] for idr, r in enumerate(rad): ca = CircularAperture(positions, r) m = aperture_photometry(imgs, ca) flux[idr] = m['aperture_sum'][0] idx = flux.argmax() rmodel = rad[:idx+1] fmodel = flux[:idx+1] fmax = fmodel[-1] res_d = fit_fwhm_enclosed_direct(peak, rad, flux) res_g = fit_fwhm_enclosed_grow(fmax, rmodel, fmodel) return res_d, res_g
def run_aperture_photometry(ifile, hdu, coo_tab, back, backrms, aperture, PAMcorr=True): """Runs photutils.aperture_photometry on an observation, for a single circular aperture size. Subtracts the (given) sky level from the aperture.""" header = hdu[0].header exptime = header['EXPTIME'] filterr = header['FILTER'] data = hdu[0].data xc = coo_tab['xcentroid'][0] yc = coo_tab['ycentroid'][0] apertures = CircularAperture((coo_tab['xcentroid'], coo_tab['ycentroid']), r=aperture) phot_table = aperture_photometry(data - back, apertures) flux = phot_table['aperture_sum'][0] mag = -2.5 * np.log10(flux / exptime) + get_wfc3_zeropoint(filterr) subarray_amp = sub_amp() subarray = header['APERTURE'] chip, amp = subarray_amp[subarray] epdau = get_UVIS_gain(amp) mag_err, flux_err = calculate_mag_errs(flux, mag, aperture, back, backrms, epdau) return (flux, flux_err, mag, mag_err)
def find_pinholes_irregular(fname, freference, sname, fdarkff, fdark, fff, files, size, threshold, fwhm, fitshape, MAX_CONTROL_POINTS, PIXEL_TOL, range_psf, sigma=2., oversampling=4, maxiters=3, MIN_MATCHES_FRACTION=0.8, NUM_NEAREST_NEIGHBORS=5): """Finds and fits irregularly spread pinhole positions with a ePSF in a FITS image. Then matches them to the reference positions. Parameters ---------- fname : str Folder name of the input fits files. freference : str File name of the reference positions (txt file). sname : str Folder name of the returned found and matched pinhole positions (txt files). fdarkff : string Location of the dark images for the flat field images. fdark : string Location of the dark images for the raw images. fff : string Location of the flat field images. files : (1, 2)-shaped int array File range to create a median image size : int Rectangular size of the ePSF. Size must be an odd number. threshold : float The absolute image value above which to select sources. fwhm : float The full-width half-maximum (FWHM) of the major axis of the Gaussian kernel in units of pixels. fitshape : int or length-2 array-like Rectangular shape around the center of a star which will be used to collect the data to do the fitting. Can be an integer to be the same along both axes. E.g., 5 is the same as (5, 5), which means to fit only at the following relative pixel positions: [-2, -1, 0, 1, 2]. Each element of fitshape must be an odd number. MAX_CONTROL_POINTS : int The maximum control points (stars) to use to build the invariants. PIXEL_TOL : int The pixel distance tolerance to assume two invariant points are the same. range_psf : (1, 4)-shaped int array Position range to compute epsf [xmin,xmax,ymin,ymax] sigma : float Number of standard deviations used to perform sigma clip with a astropy.stats.SigmaClip object. oversampling : int or tuple of two int The oversampling factor(s) of the ePSF relative to the input stars along the x and y axes. The oversampling can either be a single float or a tuple of two floats of the form (x_oversamp, y_oversamp). If oversampling is a scalar then the oversampling will be the same for both the x and y axes. maxiters : int The maximum number of iterations to perform. MIN_MATCHES_FRACTION : float (0,1] The minimum fraction of triangle matches to accept a transformation. If the minimum fraction yields more than 10 triangles, 10 is used instead. NUM_NEAREST_NEIGHBORS : int The number of nearest neighbors of a given star (including itself) to construct the triangle invariants. Returns ------- s_list : (N,2)-shaped array Found and matched positions of the pinholes. t_list : (N,2)-shaped array Matched reference grid positions. """ #Load the sample of fits images entries = os.listdir(fname) data_col = np.array([fits.getdata(fname + '/' + entries[files[0]], ext=0)]) for k in range(files[0] + 1, files[1] + 1): data_col = np.append(data_col, [fits.getdata(fname + '/' + entries[k], ext=0)], axis=0) #Data reduction: Darc current + Flatfield data_col = data_correction(data_col, fdarkff, fdark, fff) #Claculate median image data_full = np.median(data_col, axis=0) pos_full = np.array([[0, 0]]) data = data_full[range_psf[2]:range_psf[3], range_psf[0]:range_psf[1]] #Find peaks in data peaks_tbl = find_peaks(data, threshold=threshold) peaks_tbl['peak_value'].info.format = '%.8g' #Load data around found peaks hsize = (size - 1) / 2 x = peaks_tbl['x_peak'] y = peaks_tbl['y_peak'] mask = ((x > hsize) & (x < (data.shape[1] - 1 - hsize)) & (y > hsize) & (y < (data.shape[0] - 1 - hsize))) stars_tbl = Table() stars_tbl['x'] = x[mask] stars_tbl['y'] = y[mask] #Calculate mean, median, std mean_val, median_val, std_val = sigma_clipped_stats(data, sigma=sigma) data = data - median_val #Find pinholes and create ePSF nddata = NDData(data=data) stars = extract_stars(nddata, stars_tbl, size=size) epsf_builder = EPSFBuilder(oversampling=oversampling, maxiters=maxiters, progress_bar=False) epsf, fitted_stars = epsf_builder(stars) #Use ePSF to find precise locations of pinholes daofind = DAOPhotPSFPhotometry(crit_separation=30, threshold=threshold, fwhm=fwhm, psf_model=epsf, fitshape=fitshape, aperture_radius=12, niters=1) #Get positions sources = daofind(data_full) for col in sources.colnames: sources[col].info.format = '%.8g' pos = np.transpose((sources['x_fit'], sources['y_fit'])) pos_full = np.append(pos_full, pos, axis=0) pos_full = pos_full[1:] #Plot found pinholes apertures = CircularAperture(pos_full, r=10) norm = ImageNormalize(stretch=SqrtStretch()) #Plot found pinholes fig, ax = plt.subplots() ax.set_title('Pinhole Positions') ax.set(xlabel='x [pixel]', ylabel='y [pixel]') ax.imshow(data_full, cmap='Greys', origin='lower', norm=norm) apertures.plot(color='blue', lw=1.5, alpha=0.5) ax.legend(['#pinholes = ' + str(len(pos_full[:, 0]))], loc='lower left', prop={'size': 12}) plt.show() #Sort positions by matching with reference grid positions_sort = pos_full ref_positions = np.genfromtxt(freference, skip_header=0) transf, (s_list, t_list) = find_transform(positions_sort, ref_positions, MAX_CONTROL_POINTS, PIXEL_TOL, MIN_MATCHES_FRACTION, NUM_NEAREST_NEIGHBORS) text = np.array([s_list[:, 0], s_list[:, 1], t_list[:, 0], t_list[:, 1]]) text_trans = np.zeros((len(s_list[:, 0]), 4)) #Transpose text matrix for k in range(0, 4): for l in range(0, len(s_list[:, 0])): text_trans[l][k] = text[k][l] #Save data as txt file np.savetxt(sname + '.txt', text_trans, fmt='%1.9E', delimiter='\t', comments='', header='x-measured y-measured x-reference y-reference') return s_list, t_list