def compareW(PSF,sig,accd,cx,cy): x1, y1 = centroid_com(PSF) x2, y2 = centroid_1dg(PSF) x3, y3 = centroid_2dg(PSF) errx1=cx-1-x1 erry1=cy-1-y1 errx2=cx-1-x2 erry2=cy-1-y2 errx3=cx-1-x3 erry3=cy-1-y3 err1=((errx1)**2+(erry1)**2)**0.5 err2=((errx2)**2+(erry2)**2)**0.5 err3=((errx3)**2+(erry3)**2)**0.5 # print("%.2e,%.2e,%.2e,%.2e,%.2e,%.2e," % ( errx1,erry1,errx2,erry2,errx3,erry3)) # Weighted Weight=GaussianFunc(sig,accd,cx,cy) PSFW=PSF*Weight x1, y1 = centroid_com(PSFW) x2, y2 = centroid_1dg(PSFW) x3, y3 = centroid_2dg(PSFW) errx12=cx-1-x1 erry12=cy-1-y1 errx22=cx-1-x2 erry22=cy-1-y2 errx32=cx-1-x3 erry32=cy-1-y3 err12=((errx12)**2+(erry12)**2)**0.5 err22=((errx22)**2+(erry22)**2)**0.5 err32=((errx32)**2+(erry32)**2)**0.5 # print("%.2e,%.2e,%.2e,%.2e,%.2e,%.2e," % ( errx12,erry12,errx22,erry22,errx32,erry32)) return err1,err2,err3,err12,err22,err32
def Centroids(Stars, References, Trim=0, Plot=False): """ Calculate the centroid offsets for a set of reference stars. """ flags = np.zeros((Stars.shape[0])) centroids = np.zeros((Stars.shape[0], Stars.shape[1], 2)) for i in range(len(Stars)): star = Stars[i] lc = np.nansum(star, axis=(1, 2)) lc[lc == 0] = np.nan lc = lc / np.nanmedian(lc) bads = np.nansum(lc > 1.2) if bads >= 10: flags[i] = 1 for j in range(len(star)): if Trim == 0: c = centroid_com(star[j]) ref = centroid_com(References[i]) else: c = centroid_com(star[j, Trim:-Trim, Trim:-Trim]) ref = centroid_com(References[i, Trim:-Trim, Trim:-Trim]) c = c - ref centroids[i, j] = c if Plot: Plot_centroids(centroids[i], star, i) return centroids, flags
def get_centroids(fluxes, centroid_shift=None, method='abs_distance', check_outliers=False, showfig=False): ''' fluxes: array, 3D fluxes method: str, (1) absolute distance (2) sklearn.ensemble centroid_shift: int, maximum shift in pixels; if larger then mask is flagged check_outliers: bool, ''' xcen, ycen = [],[] mask = np.zeros(len(fluxes)) if check_outliers: stacked = np.nansum(fluxes, axis=0) Xc, Yc = centroid_com(stacked) for idx,img in enumerate(fluxes): x,y = centroid_com(img) if check_outliers: if centroid_shift is not None: #shift = int(round(centroid_shift)) shift = float(centroid_shift) if abs(Xc-x) > shift or abs(Yc-y) > shift: mask[idx] = 1 else: raise ValueError('`centroid_shift` not defined') else: pass xcen.append(x) ycen.append(y) #convert 0,1 into bool mask = np.array(mask, dtype=bool) if method == 'ensemble': X = np.c_[xcen,ycen] mask = IsolationForest(max_features=2, contamination=0.01).fit(X).predict(X) #output is 1 or -1, convert to bool mask = np.array([True if bool(i == 1.0) else False for i in mask]) xcen, ycen = np.array(xcen),np.array(ycen) if showfig: if method == 'ensemble': pl.scatter(xcen, ycen, c=mask, cmap='RdBu') else: pl.plot(xcen,ycen,'bo',label='good data') pl.plot(xcen[mask],ycen[mask],'ro',label='bad data') pl.legend() return (xcen,ycen), mask
def center(s_post, member_indices): mem = gcat[member_indices] """ Member Galaxy Locations """ mempix = convpix(mem, w) x = mempix[:, 0] y = mempix[:, 1] """ Configuring Pixel Space""" init_x, init_y = w.wcs_world2pix(s_post[0], s_post[1], 1) # initial estimate to draw box wid_arcsec = 302 # 5'x 5' area around s-post pix_scale = 0.8627 # "/pixel ---> 0.000239 deg/pixel wid_pixels = int(wid_arcsec / pix_scale) # ~350x350 pixels xmin = int(init_x - (wid_pixels / 2.0)) # boundaries xmax = int(init_x + (wid_pixels / 2.0)) ymin = int(init_y - (wid_pixels / 2.0)) ymax = int(init_y + (wid_pixels / 2.0)) """ 2D-Histogram & Smoothing """ binstep = 10 # 10 pixel ~ 8.62 " wght = np.asarray( gcat[member_indices]['fch1']) # weights: irac ch1[3.6 um] flux xedges = np.arange(xmin, xmax + binstep, binstep) yedges = np.arange(ymin, ymax + binstep, binstep) h, xedges, yedges = np.histogram2d(x, y, bins=(xedges, yedges), weights=wght) size = int(round( (np.shape(h)[0]) / 4.0)) # kernel size : at least ~ 4 times smaller stdev_ker = size / 3.0 # size = 3-sigma gauss_kernel = Gaussian2DKernel(stddev=stdev_ker, x_size=size, y_size=size) # kernel smoothed_data_gauss = convolve_fft(h.T, gauss_kernel) # convolution/smoothing """ Finds Peak """ x_org, y_org = (xedges[0] + xedges[1]) / 2.0, ( yedges[0] + yedges[1]) / 2.0 # origin of bin-coordinate fp_m = find_peaks(smoothed_data_gauss, 0, npeaks=1) # 1 peak with max value xbin_peak, ybin_peak = fp_m['x_peak'][0], fp_m['y_peak'][ 0] # x, y positions of the peak x_p, y_p = (x_org + xbin_peak * binstep), ( y_org + ybin_peak * binstep) # conversion to pixel coordinates peak = (x_p, y_p) ra_p, dec_p = w.wcs_pix2world(peak[0], peak[1], 1) peak_fk5 = (ra_p, dec_p) """ Centroid from Image Moments """ cen_pos = centroid_com(smoothed_data_gauss) cenx, ceny = (x_org + cen_pos[0] * binstep), (y_org + cen_pos[1] * binstep) ra_c, dec_c = w.wcs_pix2world(cenx, ceny, 1) centre = (ra_c, dec_c) return centre, peak_fk5
def plot_image(): std = np.std(stamp[stamp == stamp]) x1, y1 = centroid_com(stamp) x2, y2 = centroid_1dg(stamp) x3, y3 = centroid_2dg(stamp) return [((x1 - dx + xcen), (x2 - dx + xcen), (x3 - dx + xcen)), ((y1 - dy + ycen), (y2 - dy + ycen), (y3 - dy + ycen))]
def plot_aper_mask(fluxes,rad,aper_shape,contrast=0.1,epic=None): stacked = np.nansum(fluxes,axis=0) mask = make_mask(fluxes, rad = rad, shape=aper_shape) y,x = centroid_com(stacked) fig, ax = pl.subplots(1,1) interval = ZScaleInterval(contrast=contrast) zmin,zmax = interval.get_limits(stacked) cb = ax.imshow(stacked, origin='bottom', interpolation=None) ax.imshow(mask, alpha=0.3) if aper_shape == 'round': circ = pl.Circle((x,y),rad,color='w',alpha=0.2,lw=5,label='r={}'.format(rad)) ax.add_artist(circ) ax.plot(x,y,'r+',ms=20, lw=10,label='centroid') pl.colorbar(cb, ax=ax) pl.xlabel('X') pl.ylabel('Y') pl.legend() if epic is not None: pl.title('EPIC {}'.format(epic)) pl.show() return fig
def psfpy(data): x1, y1 = centroid_com(data) x2, y2 = centroid_1dg(data) x3, y3 = centroid_2dg(data) # print(data) # print(x1,y1,x2,y2,x3,y3) # mean, median, std = sigma_clipped_stats(data, sigma=3.0, iters=5) # data -= median # subtract background cat = data_properties(data) # print (cat) #列输出 columns = [ 'id', 'xcentroid', 'ycentroid', 'semimajor_axis_sigma', 'semiminor_axis_sigma', 'orientation', 'cxx', 'cyy', 'cxy', 'eccentricity' ] tbl = cat.to_table(columns=columns) tbl['cxy'].info.format = '.10f' eccef = float(tbl['eccentricity']) str1 = str(tbl['semimajor_axis_sigma']) semimajorf = str1.split("[")[1].split("]")[0] str1 = str(tbl['semiminor_axis_sigma']) semiminorf = str1.split("[")[1].split("]")[0] str1 = str(tbl['orientation']) orientationf = str1.split("[")[1].split("]")[0] str1 = str(tbl['cxx']) cxxf = str1.split("[")[1].split("]")[0] str1 = str(tbl['cxy']) cxyf = str1.split("[")[1].split("]")[0] str1 = str(tbl['cyy']) cyyf = str1.split("[")[1].split("]")[0] return (x1, y1, x2, y2, x3, y3, semimajorf, semiminorf, eccef, orientationf, cxxf, cxyf, cyyf)
def plot_image(posx, posy, count, prevstds): #We have to redefine the stamp every time, otherwise the program doesn't woek stamp = data[i][int(round(posy - dy)):int(round(posy + dy)), int(round(posx - dx)):int(round(posx + dx))] #this is just to keep track of how much recursing we do count = count + 1 std = np.std(stamp[stamp == stamp]) x1, y1 = centroid_com(stamp) x2, y2 = centroid_1dg(stamp) x3, y3 = centroid_2dg(stamp) xavg = np.average([x2, x3]) yavg = np.average([y2, y3]) xstd = np.std([x2, x3]) ystd = np.std([y2, y3]) #xavg = np.average([x1,x2,x3]) #yavg = np.average([y1,y2,y3]) #xstd = np.std([x1,x2,x3]) #ystd = np.std([y1,y2,y3]) #print(count, posx-dx+xavg, posy-dy+yavg, xstd, ystd) # RECURSION BITCH limit 100 times, while either std is higher than our 0.1 threshold # and as long as the std is getting smaller if (xstd + ystd > prevstds[0] + prevstds[1]): return posx, posy, prevstds[0]**(-2), prevstds[1]**(-2), count - 1 if count < 100 and (xstd > 0.1 or ystd > 0.1) and (xstd <= prevstds[0] and ystd <= prevstds[1]): return plot_image(posx - dx + xavg, posy - dy + yavg, count, [xstd, ystd]) else: return posx - dx + xavg, posy - dy + yavg, 1 / (xstd**2), 1 / ( ystd**2), count
def Select_Target(self, image, x, y, box): X = [] Y = [] #delete previous circles for elem in self.redcircle: self.canvas.delete(elem) D = image[int(y) - box:int(y) + box, int(x) - box:int(x) + box] xn, yn = centroid_com(D - numpy.median(D)) xn = xn + int(x) - box yn = yn + int(y) - box print('Center of the target: x = {} y = {}'.format(xn, yn)) X.append(xn) Y.append(yn) NX = X[0] - 22 NY = Y[0] D = image[int(NY) - box:int(NY) + box, int(NX) - box:int(NX) + box] xn, yn = centroid_com(D - numpy.median(D)) xn = xn + int(NX) - box yn = yn + int(NY) - box X.append(xn) Y.append(yn) for xe, ye in zip(X, Y): self.redcircle.append( self.canvas.create_oval(xe * self.zoom - 10, ye * self.zoom - 10, xe * self.zoom + 10, ye * self.zoom + 10, outline='blue', width=2)) self.redcircle.append( self.canvas.create_oval(xe * self.zoom - 1, ye * self.zoom - 1, xe * self.zoom + 1, ye * self.zoom + 1, outline='red', width=2)) self.Tx[self.index] = X self.Ty[self.index] = Y
def psf_norm_2d(array, fwhm, size, threshold, mask_core, full_output, verbose): """ 2d case """ if size is not None: if size < array.shape[0]: psfs = frame_crop(array, size, force=True, verbose=False) else: psfs = array.copy() else: psfs = array.copy() # we check if the psf is centered and fix it if needed cy, cx = frame_center(psfs, verbose=False) xcom, ycom = photutils.centroid_com(psfs) if not (np.allclose(cy, ycom, atol=1e-2) or np.allclose(cx, xcom, atol=1e-2)): # first we find the centroid and put it in the center of the array centry, centrx = fit_2d(psfs) shiftx, shifty = centrx - cx, centry - cy psfs = frame_shift(array, -shifty, -shiftx, imlib=imlib, interpolation=interpolation) if size is not None: psfs = frame_crop(psfs, size, force=True, verbose=False) for _ in range(2): centry, centrx = fit_2d(psfs) cy, cx = frame_center(psfs, verbose=False) shiftx, shifty = centrx - cx, centry - cy psfs = frame_shift(psfs, -shifty, -shiftx, imlib=imlib, interpolation=interpolation) # we check whether the flux is normalized and fix it if needed fwhm_aper = photutils.CircularAperture((frame_center(psfs)), fwhm/2) fwhm_aper_phot = photutils.aperture_photometry(psfs, fwhm_aper, method='exact') fwhm_flux = np.array(fwhm_aper_phot['aperture_sum']) if fwhm_flux > 1.1 or fwhm_flux < 0.9: psf_norm_array = psfs / np.array(fwhm_aper_phot['aperture_sum']) else: psf_norm_array = psfs if threshold is not None: psf_norm_array[np.where(psf_norm_array < threshold)] = 0 if mask_core is not None: psf_norm_array = get_circle(psf_norm_array, radius=mask_core) if verbose: print("Flux in 1xFWHM aperture: {:.3f}".format(fwhm_flux[0])) if full_output: return psf_norm_array, fwhm_flux, fwhm else: return psf_norm_array
def centroid(a): top=19 bot=12 a = ma.masked_invalid(a) #a=sigma_clip(a, sigma=7, iters=1) a=a[bot:top+1, bot:top+1] a2=np.multiply(a,a) beta_np=np.sum(a)**2/np.sum(a2) xcg, ycg = centroid_2dg(a)+bot xc, yc = centroid_com(a)+bot return xc,yc, xcg, ycg
def get_planicentre(img, rad, iterations=1, croppix=400, Debug=False, endcrop=10): croppedimg = img for i in range(iterations): imgcent = centroid_com(croppedimg) if Debug: print(imgcent) plt.figure(figsize=(5, 5)) im5 = plt.imshow(croppedimg, cmap=col) plt.axhline(imgcent[0], color=xcol) plt.axvline(imgcent[1], color=xcol) plt.title('Partial Image ' + str(i)) plt.colorbar(im5) plt.show() croppedimg = croppedimg[(int(imgcent[1] - croppix)):(int(imgcent[1] + croppix)), (int(imgcent[0] - croppix)):(int(imgcent[0] + croppix))] croppedimg = image.exp_despike(croppedimg, nsigma=1) croppix = croppix / 3 planicentre1 = centroid_com(croppedimg) DiscImg = croppedimg[(int(planicentre1[1]) - (int(rad) + endcrop)):(int(planicentre1[1]) + (int(rad) + endcrop)), (int(planicentre1[0]) - (int(rad) + endcrop)):int(planicentre1[0]) + ((int(rad) + endcrop))] planicentre2 = get_disc(DiscImg, r0=rad) return DiscImg, planicentre2
def plot_image(): std = np.std(stamp[stamp==stamp]) plt.imshow(stamp, interpolation='nearest', origin = 'lower', vmin = -1.*std, vmax = 3.*std, cmap='bone') plt.tick_params(axis='both', which='major', labelsize=8) circle0 = plt.Circle((dx,dy),0.1) x1, y1 = centroid_com(stamp) circle1 = plt.Circle((x1,y1),0.1,color='r') ax.add_artist(circle1) x2, y2 = centroid_1dg(stamp) circle2 = plt.Circle((x2,y2),0.1,color='b') ax.add_artist(circle2) x3, y3 = centroid_2dg(stamp) circle3 = plt.Circle((x3,y3),0.1,color='g') ax.add_artist(circle3) return ((x1, y1),(x2, y2),(x3, y3))
def get_centroid(image, method='com'): ''' centroid_com(): Calculates the object 'center of mass' from 2D image moments. centroid_1dg(): Calculates the centroid by fitting 1D Gaussians to the marginal x and y distributions of the data. centroid_2dg(): Calculates the centroid by fitting a 2D Gaussian to the 2D distribution of the data. Default is centroid_2dg. ''' if method == 'com': x, y = centroid_com(image) elif method == '1d_gaussian': x, y = centroid_1dg(image) else: #default x, y = centroid_2dg(image) return (x, y)
def make_mask(fluxes, rad=None, cutoff_limit=1.0, shape='round', epic=None, showfig=False): ''' create mask given 3D (t x h x w) fluxes ''' #stack images stacked = np.nansum(fluxes,axis=0) #get centroid of stacked image x,y = centroid_com(stacked) xx,yy = int(round(x)), int(round(y)) mask = np.zeros_like(stacked) if shape == 'square': if rad is not None: if stacked.size > (2*rad)**2: assert ValueError('mask size bigger than tpf cutout') for i in np.arange(-rad,rad,1): for j in np.arange(-rad,rad,1): mask[xx+i,yy+j] = 1 else: raise ValueError('rad: aperture radius not defined') elif shape == 'irregular': mask = find_aperture(fluxes, cutoff_limit=1.0) elif shape == 'round' or shape == 'cirle': #default: round if rad is not None: if stacked.size > (2*rad)**2: assert ValueError('mask size bigger than tpf cutout') for i in range(stacked.shape[0]): for j in range(stacked.shape[1]): if np.sqrt((xx-i)**2+(yy-j)**2)<=rad: mask[i,j] = 1 else: raise ValueError('rad: aperture radius not defined') else: # no mask; use all pixels mask = np.ones_like(stacked) if showfig: fig = plot_aper_mask(fluxes,rad,aper_shape=shape,contrast=0.1,epic=epic) return np.array(mask,dtype=bool)
def plot_image(posx,posy, count, prevstds): stamp = data[int(round(posy-dy)):int(round(posy+dy)), int(round(posx-dx)):int(round(posx+dx))] count = count +1 std = np.std(stamp[stamp==stamp]) x1, y1 = centroid_com(stamp) x2, y2 = centroid_1dg(stamp) x3, y3 = centroid_2dg(stamp) xavg = np.average([x1,x2,x3]) yavg = np.average([y1,y2,y3]) xstd = np.std([x1,x2,x3]) ystd = np.std([y1,y2,y3]) # RECURSION BITCH if count < 100 and (xstd > 0.1 or ystd > 0.1) and (xstd <= prevstds[0] and ystd <= prevstds[1]): print(count, posx-dx+xavg, posy-dy+yavg, xstd, ystd) return plot_image(posx-dx+xavg, posy-dy+yavg, count, [xstd,ystd]) else: return posx-dx+xavg, posy-dy+yavg, 1/(xstd**2), 1/(ystd**2), count
def get_centroid(image, method='com'): ''' centroid_com(): Calculates the object “center of mass” from 2D image moments. centroid_1dg(): Calculates the centroid by fitting 1D Gaussians to the marginal x and y distributions of the data. centroid_2dg(): Calculates the centroid by fitting a 2D Gaussian to the 2D distribution of the data. Default is com. ''' if method == 'com': x, y = centroid_com(image) return (x, y) elif method == '1d_gaussian': x, y = centroid_1dg(image) return (x, y) elif method == '2d_gaussian': #bug: takes too much time; fit may be unsuccessful x, y = centroid_2dg(image) return (x, y) else: print('invalid centroiding algorithm') sys.exit()
def recenter(image, pos, window_size=5, method="1dg"): """ Recenter each star in each frame of the image cube before performing aperture photometry to take care of slight misalignments between frames because of atmospheric turbulence and tracking/pointing errors. Parameters ---------- image : numpy array 2D image pos : list List of (x,y) tuples for star positions window_size : int Window size in which to fit the gaussian to the star to calculate new center method : string Method used to find center of the star. Options are 1d Gaussian fit, 2d gaussian fit or com (center of mass) Returns ------- xcen, ycen : float Source x and y centers """ pos = np.asarray(pos) ny, nx = image.shape window_size = int(window_size) nstars = pos.shape[0] star_pos = np.zeros([nstars, 2], dtype=np.float32) for i in range(nstars): x, y = pos[i][0], pos[i][1] xmin, xmax = int(x) - int(window_size / 2), int(x) + int( window_size / 2) + 1 ymin, ymax = int(y) - int(window_size / 2), int(y) + int( window_size / 2) + 1 if xmin < 0: xmin = 0 if ymin < 0: ymin = 0 if xmax > nx: xmax = nx if ymax > ny: ymax = ny if method == "1dg": xcen, ycen = centroid_1dg(image[ymin:ymax, xmin:xmax]) elif method == "2dg": xcen, ycen = centroid_2dg(image[ymin:ymax, xmin:xmax]) elif method == "com": xcen, ycen = centroid_com(image[ymin:ymax, xmin:xmax]) if (np.abs(xmin + xcen - x)) > 3. or (np.abs(ymin + ycen - y)) > 3.: star_pos[i, 0] = x star_pos[i, 1] = y else: star_pos[i, 0] = xmin + xcen star_pos[i, 1] = ymin + ycen return star_pos
def find_center(image, center_guess, cutout_size=30, max_iters=10): """ Find the centroid of a star from an initial guess of its position. Originally written to find star from a mouse click. Parameters ---------- image : numpy array or CCDData Image containing the star. center_guess : array or tuple The position, in pixels, of the initial guess for the position of the star. The coordinates should be horizontal first, then vertical, i.e. opposite the usual Python convention for a numpy array. cutout_size : int, optional The default width of the cutout to use for finding the star. max_iters : int, optional Maximum number of iterations to go through in finding the center. """ pad = cutout_size // 2 x, y = center_guess # Keep track of iterations cnt = 0 # Grab the cutout... sub_data = image[y - pad:y + pad, x - pad:x + pad] # - med # ...do stats on it... _, sub_med, _ = sigma_clipped_stats(sub_data) # sub_med = 0 # ...and centroid. x_cm, y_cm = centroid_com(sub_data - sub_med) # Translate centroid back to original image (maybe use Cutout2D instead) cen = np.array([x_cm + x - pad, y_cm + y - pad]) # ceno is the "original" center guess, set it to something nonsensical here ceno = np.array([-100, -100]) while (cnt <= max_iters and (np.abs(np.array([x_cm, y_cm]) - pad).max() > 3 or np.abs(cen - ceno).max() > 0.1)): # Update x, y positions for subsetting x = int(np.floor(x_cm)) + x - pad y = int(np.floor(y_cm)) + y - pad sub_data = image[y - pad:y + pad, x - pad:x + pad] # - med _, sub_med, _ = sigma_clipped_stats(sub_data) # sub_med = 0 mask = (sub_data - sub_med) < 0 x_cm, y_cm = centroid_com(sub_data - sub_med, mask=mask) ceno = cen cen = np.array([x_cm + x - pad, y_cm + y - pad]) if not np.all(~np.isnan(cen)): raise RuntimeError('Centroid finding failed, ' 'previous was {}, current is {}'.format( ceno, cen)) cnt += 1 return cen
def plot_image(): std = np.std(stamp[stamp == stamp]) x1, y1 = centroid_com(stamp) x2, y2 = centroid_1dg(stamp) x3, y3 = centroid_2dg(stamp) return np.array([[x1, x2, x3], [y1, y2, y3]])
def center(iter_no, s_post, member_indices, apr, plotmap): mem = gcat[ member_indices] # gcat = The galaxy catalog of which the overdensities are being computed. """ Member Galaxy Locations in Pixel Space """ galpix = convpix(mem, w) x = galpix[:, 0] y = galpix[:, 1] """ Configuring Pixel Space""" init_x, init_y = w.wcs_world2pix(s_post[0], s_post[1], 0) # initial estimate to draw box PIX_SCALE = imagefile[0].header[ 'CDELT2'] * 3600.0 # "/pixel ---> 0.000239 deg/pixel, IRAC/bootes if apr <= 2.0: wid_arcsec = 302 # ~5'x5' region around the signpost elif 2.0 < apr <= 5.0: wid_arcsec = 716.5 # ~12'x12' else: wid_arcsec = 898 # ~15'x15' wid_pixels = int(wid_arcsec / PIX_SCALE) # ~350x350 pixels/ 830x830 /1040x1040 xmin, xmax = int(init_x - (wid_pixels / 2.0)), int( init_x + (wid_pixels / 2.0)) # boundaries ymin, ymax = int(init_y - (wid_pixels / 2.0)), int(init_y + (wid_pixels / 2.0)) """ 2D-Histogram & Smoothing """ binstep = 5.0 # 10 pixel ~ 8.62 " wght = np.asarray( gcat[member_indices]['ch2_flux']) # weights: irac ch2[4.5 um] flux xedges = np.arange(xmin, xmax + binstep, binstep) yedges = np.arange(ymin, ymax + binstep, binstep) h, xedges, yedges = np.histogram2d(x, y, bins=(xedges, yedges), weights=wght) xmid = [(xedges[ik] + xedges[ik + 1]) / 2.0 for ik in range(len(xedges) - 1)] ymid = [(yedges[ij] + yedges[ij + 1]) / 2.0 for ij in range(len(yedges) - 1)] size = int(round((np.shape(h)[0]) / 4.0)) # kernel size : at least ~ 4 times smaller stdev_ker = size / 4.0 # size = 4-sigma gauss_kernel = Gaussian2DKernel(x_stddev=stdev_ker, y_stddev=stdev_ker, x_size=size, y_size=size) # kernel smoothed_data_gauss = convolve_fft( h.T, gauss_kernel) # convolution/smoothing max_sm_val = max(smoothed_data_gauss.flatten()) """ Finds Peak """ x_org, y_org = (xedges[0] + xedges[1]) / 2.0, ( yedges[0] + yedges[1]) / 2.0 # origin of bin-coordinate fp_m = find_peaks(smoothed_data_gauss, 0, npeaks=1) # 1 peak with max value xbin_peak, ybin_peak = fp_m['x_peak'][0], fp_m['y_peak'][ 0] # x, y positions of the peak x_p, y_p = (x_org + xbin_peak * binstep), ( y_org + ybin_peak * binstep) # conversion to pixel coordinates peak_pix = (x_p, y_p) ra_p, dec_p = w.wcs_pix2world(peak_pix[0], peak_pix[1], 0) peak_fk5 = (ra_p, dec_p) """ Centroid from Image Moments """ cen_pos = centroid_com(smoothed_data_gauss) cenx, ceny = (x_org + cen_pos[0] * binstep), (y_org + cen_pos[1] * binstep) ra_c, dec_c = w.wcs_pix2world(cenx, ceny, 0) centre = (ra_c, dec_c) """ Plots """ if plotmap == 'ON': fgm = plt.figure() ax = fgm.add_subplot(111) # ax_b.imshow(smoothed_data_gauss, extent=[xmin, xmax, ymin, ymax], cmap='jet') cntf = ax.contourf( xmid, ymid, smoothed_data_gauss, cmap='Blues', levels=[lt for lt in np.arange(0.10, max_sm_val + 0.02, 0.02)]) ax.scatter(x, y, marker='o', color='red', s=5) ax.scatter(cenx, ceny, marker='s') ax.scatter(x_p, y_p, marker='^') ax.scatter(init_x, init_y, marker='o', color='lime') fgm.colorbar(cntf) fgm.savefig(catdir + 'clump_plots/' + str(iter_no) + '_map.png', format='png', dpi=100) plt.close(fgm) return centre, peak_fk5
def fit_2dmoffat(array, crop=False, cent=None, cropsize=15, fwhm=4, threshold=False, sigfactor=6, full_output=True, debug=True): """ Fitting a 2D Moffat to the 2D distribution of the data. Parameters ---------- array : numpy ndarray Input frame with a single PSF. crop : bool, optional If True an square sub image will be cropped. cent : tuple of int, optional X,Y integer position of source in the array for extracting the subimage. If None the center of the frame is used for cropping the subframe (the PSF is assumed to be ~ at the center of the frame). cropsize : int, optional Size of the subimage. fwhm : float, optional Initial values for the FWHM of the fitted 2d Moffat, in px. threshold : bool, optional If True the background pixels (estimated using sigma clipped statistics) will be replaced by small random Gaussian noise. sigfactor : int, optional The background pixels will be thresholded before fitting a 2d Moffat to the data using sigma clipped statistics. All values smaller than (MEDIAN + sigfactor*STDDEV) will be replaced by small random Gaussian noise. full_output : bool, optional If False it returns just the centroid, if True also returns the FWHM in X and Y (in pixels), the amplitude and the rotation angle. debug : bool, optional If True, the function prints out parameters of the fit and plots the data, model and residuals. Returns ------- mean_y : float Source centroid y position on input array from fitting. mean_x : float Source centroid x position on input array from fitting. If ``full_output`` is True it returns a Pandas dataframe containing the following columns: 'alpha': Float value. Alpha parameter. 'amplitude' : Float value. Moffat Amplitude. 'centroid_x' : Float value. X coordinate of the centroid. 'centroid_y' : Float value. Y coordinate of the centroid. 'fwhm' : Float value. FHWM [px]. 'gamma' : Float value. Gamma parameter. """ check_array(array, dim=2, msg='array') if crop: if cent is None: ceny, cenx = frame_center(array) else: cenx, ceny = cent imside = array.shape[0] psf_subimage, suby, subx = get_square(array, min(cropsize, imside), ceny, cenx, position=True) else: psf_subimage = array.copy() if threshold: _, clipmed, clipstd = sigma_clipped_stats(psf_subimage, sigma=2) indi = np.where(psf_subimage <= clipmed + sigfactor * clipstd) subimnoise = np.random.randn(psf_subimage.shape[0], psf_subimage.shape[1]) * clipstd psf_subimage[indi] = subimnoise[indi] # Creating the 2D Moffat model init_amplitude = np.ptp(psf_subimage) xcom, ycom = photutils.centroid_com(psf_subimage) moffat = models.Moffat2D(amplitude=init_amplitude, x_0=xcom, y_0=ycom, gamma=fwhm / 2., alpha=1) # Levenberg-Marquardt algorithm fitter = fitting.LevMarLSQFitter() y, x = np.indices(psf_subimage.shape) fit = fitter(moffat, x, y, psf_subimage) if crop: mean_y = fit.y_0.value + suby mean_x = fit.x_0.value + subx else: mean_y = fit.y_0.value mean_x = fit.x_0.value fwhm = fit.fwhm amplitude = fit.amplitude.value alpha = fit.alpha.value gamma = fit.gamma.value if debug: if threshold: label = ('Subimage thresholded', 'Model', 'Residuals') else: label = ('Subimage', 'Model', 'Residuals') plot_frames((psf_subimage, fit(x, y), psf_subimage - fit(x, y)), grid=True, grid_spacing=1, label=label) print('FWHM =', fwhm) print('centroid y =', mean_y) print('centroid x =', mean_x) print('centroid y subim =', fit.y_0.value) print('centroid x subim =', fit.x_0.value, '\n') print('amplitude =', amplitude) print('alpha =', alpha) print('gamma =', gamma) # compute uncertainties if fitter.fit_info['param_cov'] is not None: perr = np.sqrt(np.diag(fitter.fit_info['param_cov'])) amplitude_err, mean_x_err, mean_y_err, gamma_err, alpha_err = perr fwhm_err = 2 * gamma_err else: amplitude_err, mean_x_err, mean_y_err = None, None, None gamma_err, alpha_err, fwhm_err = None, None, None if full_output: return pd.DataFrame( { 'centroid_y': mean_y, 'centroid_x': mean_x, 'fwhm': fwhm, 'alpha': alpha, 'gamma': gamma, 'amplitude': amplitude, 'centroid_y_err': mean_y_err, 'centroid_x_err': mean_x_err, 'fwhm_err': fwhm_err, 'alpha_err': alpha_err, 'gamma_err': gamma_err, 'amplitude_err': amplitude_err }, index=[0]) else: return mean_y, mean_x
def fit_2dairydisk(array, crop=False, cent=None, cropsize=15, fwhm=4, threshold=False, sigfactor=6, full_output=False, debug=False): """ Fitting a 2D Moffat to the 2D distribution of the data. Parameters ---------- array : array_like Input frame with a single PSF. crop : bool, optional If True an square sub image will be cropped. cent : tuple of int, optional X,Y integer position of source in the array for extracting the subimage. If None the center of the frame is used for cropping the subframe (the PSF is assumed to be ~ at the center of the frame). cropsize : int, optional Size of the subimage. fwhm : float, optional Initial values for the FWHM of the fitted 2d Moffat, in px. threshold : bool, optional If True the background pixels (estimated using sigma clipped statistics) will be replaced by small random Gaussian noise. sigfactor : int, optional The background pixels will be thresholded before fitting a 2d Moffat to the data using sigma clipped statistics. All values smaller than (MEDIAN + sigfactor*STDDEV) will be replaced by small random Gaussian noise. full_output : bool, optional If False it returns just the centroid, if True also returns the FWHM in X and Y (in pixels), the amplitude and the rotation angle. debug : bool, optional If True, the function prints out parameters of the fit and plots the data, model and residuals. Returns ------- mean_y : float Source centroid y position on input array from fitting. mean_x : float Source centroid x position on input array from fitting. If ``full_output`` is True it returns a Pandas dataframe containing the following columns: 'alpha': Float value. Alpha parameter. 'amplitude' : Float value. Moffat Amplitude. 'centroid_x' : Float value. X coordinate of the centroid. 'centroid_y' : Float value. Y coordinate of the centroid. 'fwhm' : Float value. FHWM [px]. 'gamma' : Float value. Gamma parameter. """ if array.ndim != 2: raise TypeError('Input array is not a frame or 2d array') if crop: if cent is None: ceny, cenx = frame_center(array) else: cenx, ceny = cent imside = array.shape[0] psf_subimage, suby, subx = get_square(array, min(cropsize, imside), ceny, cenx, position=True) else: psf_subimage = array.copy() if threshold: _, clipmed, clipstd = sigma_clipped_stats(psf_subimage, sigma=2) indi = np.where(psf_subimage <= clipmed + sigfactor * clipstd) subimnoise = np.random.randn(psf_subimage.shape[0], psf_subimage.shape[1]) * clipstd psf_subimage[indi] = subimnoise[indi] # Creating the 2d Airy disk model init_amplitude = np.ptp(psf_subimage) xcom, ycom = photutils.centroid_com(psf_subimage) diam_1st_zero = (fwhm * 2.44) / 1.028 airy = models.AiryDisk2D(amplitude=init_amplitude, x_0=xcom, y_0=ycom, radius=diam_1st_zero / 2.) # Levenberg-Marquardt algorithm fitter = fitting.LevMarLSQFitter() y, x = np.indices(psf_subimage.shape) fit = fitter(airy, x, y, psf_subimage) if crop: mean_y = fit.y_0.value + suby mean_x = fit.x_0.value + subx else: mean_y = fit.y_0.value mean_x = fit.x_0.value amplitude = fit.amplitude.value radius = fit.radius.value fwhm = ((radius * 1.028) / 2.44) * 2 if debug: if threshold: msg = ['Subimage thresholded', 'Model', 'Residuals'] else: msg = ['Subimage', 'Model', 'Residuals'] pp_subplots(psf_subimage, fit(x, y), psf_subimage - fit(x, y), grid=True, gridspacing=1, label=msg) print('FWHM =', fwhm) print('centroid y =', mean_y) print('centroid x =', mean_x) print('centroid y subim =', fit.y_0.value) print('centroid x subim =', fit.x_0.value, '\n') print('amplitude =', amplitude) print('radius =', radius) if full_output: return pd.DataFrame( { 'centroid_y': mean_y, 'centroid_x': mean_x, 'fwhm': fwhm, 'radius': radius, 'amplitude': amplitude }, index=[0]) else: return mean_y, mean_x
def fit_2dgaussian(array, crop=False, cent=None, cropsize=15, fwhmx=4, fwhmy=4, theta=0, threshold=False, sigfactor=6, full_output=False, debug=False): """ Fitting a 2D Gaussian to the 2D distribution of the data. Parameters ---------- array : array_like Input frame with a single PSF. crop : bool, optional If True an square sub image will be cropped. cent : tuple of int, optional X,Y integer position of source in the array for extracting the subimage. If None the center of the frame is used for cropping the subframe (the PSF is assumed to be ~ at the center of the frame). cropsize : int, optional Size of the subimage. fwhmx, fwhmy : float, optional Initial values for the standard deviation of the fitted Gaussian, in px. theta : float, optional Angle of inclination of the 2d Gaussian counting from the positive X axis. threshold : bool, optional If True the background pixels (estimated using sigma clipped statistics) will be replaced by small random Gaussian noise. sigfactor : int, optional The background pixels will be thresholded before fitting a 2d Gaussian to the data using sigma clipped statistics. All values smaller than (MEDIAN + sigfactor*STDDEV) will be replaced by small random Gaussian noise. full_output : bool, optional If False it returns just the centroid, if True also returns the FWHM in X and Y (in pixels), the amplitude and the rotation angle. debug : bool, optional If True, the function prints out parameters of the fit and plots the data, model and residuals. Returns ------- mean_y : float Source centroid y position on input array from fitting. mean_x : float Source centroid x position on input array from fitting. If ``full_output`` is True it returns a Pandas dataframe containing the following columns: 'amplitude' : Float value. Amplitude of the Gaussian. 'centroid_x' : Float value. X coordinate of the centroid. 'centroid_y' : Float value. Y coordinate of the centroid. 'fwhm_x' : Float value. FHWM in X [px]. 'fwhm_y' : Float value. FHWM in Y [px]. 'theta' : Float value. Rotation angle. """ if array.ndim != 2: raise TypeError('Input array is not a frame or 2d array') if crop: if cent is None: ceny, cenx = frame_center(array) else: cenx, ceny = cent imside = array.shape[0] psf_subimage, suby, subx = get_square(array, min(cropsize, imside), ceny, cenx, position=True) else: psf_subimage = array.copy() if threshold: _, clipmed, clipstd = sigma_clipped_stats(psf_subimage, sigma=2) indi = np.where(psf_subimage <= clipmed + sigfactor * clipstd) subimnoise = np.random.randn(psf_subimage.shape[0], psf_subimage.shape[1]) * clipstd psf_subimage[indi] = subimnoise[indi] # Creating the 2D Gaussian model init_amplitude = np.ptp(psf_subimage) xcom, ycom = photutils.centroid_com(psf_subimage) gauss = models.Gaussian2D(amplitude=init_amplitude, theta=theta, x_mean=xcom, y_mean=ycom, x_stddev=fwhmx * gaussian_fwhm_to_sigma, y_stddev=fwhmy * gaussian_fwhm_to_sigma) # Levenberg-Marquardt algorithm fitter = fitting.LevMarLSQFitter() y, x = np.indices(psf_subimage.shape) fit = fitter(gauss, x, y, psf_subimage) if crop: mean_y = fit.y_mean.value + suby mean_x = fit.x_mean.value + subx else: mean_y = fit.y_mean.value mean_x = fit.x_mean.value fwhm_y = fit.y_stddev.value * gaussian_sigma_to_fwhm fwhm_x = fit.x_stddev.value * gaussian_sigma_to_fwhm amplitude = fit.amplitude.value theta = np.rad2deg(fit.theta.value) if debug: if threshold: msg = ['Subimage thresholded', 'Model', 'Residuals'] else: msg = ['Subimage', 'Model', 'Residuals'] pp_subplots(psf_subimage, fit(x, y), psf_subimage - fit(x, y), grid=True, gridspacing=1, label=msg) print('FWHM_y =', fwhm_y) print('FWHM_x =', fwhm_x, '\n') print('centroid y =', mean_y) print('centroid x =', mean_x) print('centroid y subim =', fit.y_mean.value) print('centroid x subim =', fit.x_mean.value, '\n') print('amplitude =', amplitude) print('theta =', theta) if full_output: return pd.DataFrame( { 'centroid_y': mean_y, 'centroid_x': mean_x, 'fwhm_y': fwhm_y, 'fwhm_x': fwhm_x, 'amplitude': amplitude, 'theta': theta }, index=[0]) else: return mean_y, mean_x
def center(s_post, member_cat, image_wcs, apr, dog, itr_no): mem = member_cat mempix = convpix(mem, image_wcs) # member objects in pixel coordinates x_pixels, y_pixels = mempix[:, 0], mempix[:, 1] init_x, init_y = image_wcs.wcs_world2pix(s_post[0], s_post[1], 0) # initial estimate to draw box dogx, dogy = image_wcs.wcs_world2pix(dog[0], dog[1], 0) # DOG location in pixel space pix_scale = 0.000239631 * 3600. # "/pixel IRAC-Ch2/SDWFS survey if apr <= 2.0: wid_arcsec = 200.0 # ~6'x6' region around the DOG elif 2.0 < apr <= 5.0: wid_arcsec = 716.5 # ~12'x12' else: wid_arcsec = 898.0 # ~15'x15' wid_pixels = int( wid_arcsec / pix_scale ) # ~350x350 pixels/~830x830 /~1040x1040 depending on aperture. xmin, xmax = int(dogx - (wid_pixels / 2.0)), int( dogx + (wid_pixels / 2.0)) # boundaries ymin, ymax = int(dogy - (wid_pixels / 2.0)), int( dogy + (wid_pixels / 2.0)) # boundaries # 2D-histogram resol = 5 # (input in arcsec -- > degrees) resol is the grid resolution for histogram. binstep = int(resol / pix_scale) # of image pixels in one bin bnsx = list(np.arange(xmin, xmax + binstep, binstep)) # bin-edges in X direction bnsy = list(np.arange(ymin, ymax + binstep, binstep)) # bin-edges in Y direction nx_bins, ny_bins = len(bnsx), len(bnsy) # number of bins in the histogram wght = np.asarray(mem['fch2']) # weights: irac ch2[4.5 um] flux h, xedges, yedges = np.histogram2d(x_pixels, y_pixels, bins=[bnsx, bnsy], weights=wght) mesh_pixels = np.meshgrid(xedges, yedges) mesh_wcs = image_wcs.wcs_pix2world(mesh_pixels[0], mesh_pixels[1], 0) # Smoothing size = int(round( (np.shape(h)[0]) / 4.0)) # kernel size : at least ~ 4 times smaller stdev_ker = size / 4.0 # size = 4-sigma gauss_kernel = Gaussian2DKernel(x_stddev=stdev_ker, y_stddev=stdev_ker, x_size=size, y_size=size) # kernel smoothed_data_gauss = convolve_fft(h.T, gauss_kernel) # convolution/smoothing # Centroid of the image moments x_org, y_org = (xedges[0] + xedges[1]) / 2.0, ( yedges[0] + yedges[1]) / 2.0 # origin of bin-coordinate cen_pos = centroid_com(smoothed_data_gauss) cenx, ceny = (x_org + cen_pos[0] * binstep), (y_org + cen_pos[1] * binstep) centre = image_wcs.wcs_pix2world(cenx, ceny, 0) dist_to_dog = sky_sep(s_post, dog) print(round(dist_to_dog, 2)) """ Plotting """ fig = plt.figure(figsize=(5, 5), dpi=300, tight_layout=True) ax = fig.add_subplot(111, projection=image_wcs) max_sm_val = max(smoothed_data_gauss.flatten()) ax.contourf( mesh_wcs[0][1:, :-1], mesh_wcs[1][:-1, :-1], smoothed_data_gauss, interpolation="nearest", origin='lower', cmap='viridis', extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]], levels=[lt for lt in np.arange(-0.10, max_sm_val + 0.30, 0.20)], transform=ax.get_transform('icrs')) ax.scatter(mem['ra'], mem['dec'], marker='o', s=50, transform=ax.get_transform('icrs'), facecolor='red', edgecolor='none', alpha=1., zorder=4, label='Member Galaxies') circ = Circle((init_x, init_y), (apr * 60) / pix_scale, edgecolor='w', facecolor='none', lw=2.0, ls='--') ax.add_patch(circ) ax.plot(centre[0], centre[1], marker='x', color='k', fillstyle='none', ls='', ms=15, label='Centroid', mew=2.0, transform=ax.get_transform('icrs')) ax.plot(dog[0], dog[1], marker='o', color='lime', fillstyle='full', ls='', ms=8, label='DOG', mew=4.0, transform=ax.get_transform('icrs')) ax.text(dog[0] - 0.002, dog[1] - 0.019, r'$\mathrm{{Richness~={val}}}$'.format(val=len(mem)), transform=ax.get_transform('icrs'), fontsize=20, color='w') ax.text(dog[0] - 0.01, dog[1] - 0.015, r'$\mathrm{{Iteration~={val2}}}$'.format(val2=itr_no + 1), transform=ax.get_transform('icrs'), fontsize=15, color='w') # Accessories ax.set_xlim(xmin, xmax - binstep) ax.set_ylim(ymin, ymax - binstep) ax.coords[0].set_ticks_position('b') ax.coords[0].set_ticklabel_position('b') ax.coords[0].set_axislabel_position('b') ax.coords[1].set_ticks_position('l_dict') ax.coords[1].set_ticklabel_position('l_dict') ax.coords[1].set_axislabel_position('l_dict') ax.coords[0].set_ticks( np.arange(mesh_wcs[0][-1][-1], mesh_wcs[0][-1][0] + 0.02, 0.02) * units.degree) ax.coords[0].set_ticklabel(fontsize=10) ax.coords[0].set_major_formatter('d.dd') ax.coords[0].set_axislabel(r'$\mathrm{R.A.(J2000)}$', fontsize=13) ax.coords[1].set_ticks( np.arange(mesh_wcs[1][:, 0][0], mesh_wcs[1][:, 0][-1] + 0.02, 0.02) * units.degree) ax.coords[1].set_ticklabel(fontsize=10.0) ax.coords[1].set_major_formatter('d.dd') ax.coords[1].set_axislabel(r'$\mathrm{Dec.(J2000)}$', fontsize=13) ax.legend(loc='best', fontsize=10) plt.axis('off') fig.show() fig.savefig(anim_dir + 'itr' + str(itr_no + 1) + '.png', format='png') plt.close(fig) return centre
def get_centroid_cutout(self, x, y, box_size=30, method="howell", dao_fwhm=10., dao_SNR=100., plot=False, plot_full=False, stretch=None): """ Perform centroiding on a cutout window. INPUT: x - a touple y - box_size - the total box size in pixels method - the centroiding method to use for cutout. This can be "centroid_2dg" "centroid_com" "daofind" OUTPUT: centroid positions EXAMPLE: PM = PhotoMetry(filenames[0]) PM.perform_photometry() print(PM.get_centroid_cutout(234.227204448,25.6594515323,method="daofind",plot=True)) print(PM.get_centroid_cutout(234.227204448,25.6594515323,method="centroid_com",plot=True)) print(PM.get_centroid_cutout(234.227204448,25.6594515323,method="centroid_2dg",plot=True)) print(PM.get_centroid_cutout(234.227204448,25.6594515323,method="daofind",box_size=50,stretch="HistEqStretch")) print(PM.get_centroid_cutout(234.227204448,25.6594515323,method="centroid_com",plot=True,box_size=50)) print(PM.get_centroid_cutout(234.227204448,25.6594515323,method="centroid_2dg",plot=True,box_size=50)) """ int_x = int(round(x)) int_y = int(round(y)) postage_stamp = photutils.utils.cutouts.cutout_footprint( self.data, (int_x, int_y), box_size) # Only interested in the image data [1] is the mask postage_stamp = np.array(postage_stamp[0]) #plt.imshow(postage_stamp) #print(postage_stamp) if method == "centroid_2dg": x_stamp_centroid, y_stamp_centroid = photutils.centroid_com( postage_stamp) elif method == "centroid_com": x_stamp_centroid, y_stamp_centroid = photutils.centroid_2dg( postage_stamp) elif method == "daofind": daofind = DAOStarFinder(fwhm=dao_fwhm, threshold=dao_SNR * self.bkg_sigma) sources = daofind(postage_stamp) positions = (sources['xcentroid'], sources['ycentroid']) x_stamp_centroid, y_stamp_centroid = float(positions[0]), float( positions[1]) elif method == "howell": x_stamp_centroid, y_stamp_centroid = self.howell_center( postage_stamp) else: print( "Error: method must be 'daofind', centroid_2dg', 'centroid_com' or 'howell'" ) pass x_centroid = x_stamp_centroid + int_x - box_size / 2. y_centroid = y_stamp_centroid + int_y - box_size / 2. if plot: fig, ax = plt.subplots() if stretch: norm = gkastro.stretch_data(postage_stamp, method=stretch) else: norm = None ax.imshow(postage_stamp, origin="lower", extent=[ int_x - box_size / 2., int_x + box_size / 2., int_y - box_size / 2., int_y + box_size / 2. ], interpolation="none", norm=norm) ax.set_xlim(int_x - box_size / 2., int_x + box_size / 2.) ax.set_ylim(int_y - box_size / 2., int_y + box_size / 2.) ax.set_xlabel("X pixel") ax.set_ylabel("Y pixel") ax.plot(x_centroid, y_centroid, color='#1f77b4', marker="+", ms=30, mew=2) if plot_full: fig, ax = plt.subplots() ax.imshow(self.data, origin="lower") ax.plot(x_centroid, y_centroid, color='#1f77b4', marker="+", ms=30, mew=2) return x_centroid, y_centroid
def show_event(viewer, event, datax, datay): i = iw._viewer.get_image() data = i.get_data() pad = 15 x = int(np.floor(event.data_x)) y = int(np.floor(event.data_y)) cnt = 0 sub_data = data[y - pad:y + pad, x - pad:x + pad] #- med _, sub_med, _ = sigma_clipped_stats(sub_data) #sub_med = 0 foo, moo = centroid_com(sub_data - sub_med) cenx = foo + x - pad ceny = moo + y - pad cen = np.array([foo + x - pad, moo + y - pad]) ceno = np.array([-100, -100]) while cnt <= 10 and (np.abs(np.array([foo, moo]) - pad).max() >3 or np.abs(cen - ceno).max() > 0.1): # print(cnt, foo, moo) x = int(np.floor(foo)) + x - pad y = int(np.floor(moo)) + y - pad sub_data = data[y - pad:y + pad, x - pad:x + pad] #- med _, sub_med, _ = sigma_clipped_stats(sub_data) #sub_med = 0 mask = (sub_data - sub_med) < 0 foo, moo = centroid_com(sub_data - sub_med, mask=mask) ceno = cen cen = np.array([foo + x - pad, moo + y - pad]) # print(cen) # print(cen - ceno) cnt += 1 iw.add_markers(Table(data=[[cen[0]], [cen[1]]], names=['x', 'y'])) #print(foo, moo) yd, xd = np.indices((sub_data.shape)) r = np.sqrt((xd - foo)**2 + (yd - moo)**2) r_exact = r.copy() r = r.astype(np.int) tbin = np.bincount(r.ravel(), sub_data.ravel()) rbin = np.bincount(r.ravel(), r_exact.ravel()) nr = np.bincount(r.ravel()) radialprofile = tbin / nr ravg = rbin / nr adjust_max = radialprofile.max() - sub_med scaled_profile = (radialprofile - sub_med) / adjust_max scaled_exact_counts = (sub_data - sub_med) / adjust_max out.clear_output(wait=True) with out: # print(dir(event)) #print(event.data_x, event.data_y) plt.clf() #sub_med += med seeing_plot(r_exact, scaled_exact_counts, ravg, scaled_profile, 5, 'Some Image Name', file_name='some_name', gap=6, annulus_width=13) plt.show() out2.clear_output(wait=True) with out2: tbin2 = np.bincount(r.ravel(), (sub_data - sub_med).ravel()) counts = np.cumsum(tbin2) mag_diff = -2.5 * np.log10(counts/counts.max()) plt.plot(range(len(radialprofile)), counts) plt.xlim(0, 20) #plt.ylim(0.2, 0) plt.grid() sub_blot = sub_data.copy() sub_blot[10:30, 10:30] = np.nan sub_std = np.nanstd(sub_blot) plt.title('Net counts in aperture std {:.2f} med {:.2f}'.format(sub_std, sub_med)) sub_pois = (sub_data - sub_med) e_sky = np.sqrt(sub_med) rn = 10 sub_noise_sq = np.sqrt(sub_pois ** 2 + sub_std ** 2) ** 2 nbin = np.sqrt(np.bincount(r.ravel(), (sub_noise_sq).ravel())) plt.xlabel('Aperture radius') plt.show() out3.clear_output(wait=True) with out3: poisson = np.sqrt(np.cumsum(tbin2)) error = np.sqrt(poisson ** 2 + np.cumsum(nr) * (e_sky ** 2 + rn ** 2)) snr = np.cumsum(tbin2) / error snr_max = snr[:20].max() plt.plot(range(len(radialprofile)), snr) plt.title('Signal to noise ratio {}'.format(snr.max())) plt.xlim(0, 20) #plt.ylim(0, 2) plt.xlabel('Aperture radius') plt.grid() plt.show()
# For the individual image cutouts fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(8, 4), sharey=True) # The actual work for j, star in enumerate(stars): crad = int(cutoutsize/2.) scutout = tdata[star[1]-crad:star[1]+crad, star[0]-crad:star[0]+crad] im = ax[j].imshow(scutout, interpolation='none', origin='lower', norm=norm, vmin=0, vmax=200) # Actually calculate the centroid cen = centroid_com(scutout) # cen = centroid_2dg(scutout) cxseries[j, i] = cen[0] cyseries[j, i] = cen[1] # Plot the centroid on the image ax[j].scatter(cen[0], cen[1], color='green') print("\t\tStar%d: %f,%f" % (j, cen[0], cen[1])) # cbar = fig.colorbar(im, pad=0.05, orientation='vertical') if dnps is True: units = "DN/sec" else: units = "DN"
def center(s_post, gal_cat, image_wcs, search_box_width): # centroid of the gal_cat # search box width = width of the search box around the signpost in arcmin. (5' x 5' BOX) # image_wcs = WCS of the image where objects are detected. # Search box PIX_SCALE = 0.000239631 * 3600 # arcsec/pixel ; 0.000239631 degrees/pixel for IRAC-ch2 (SDWFS Survey) wid_arcsec = search_box_width * 60 # arcsec wid_pixels = int(wid_arcsec / PIX_SCALE) # in pixels init_x, init_y = image_wcs.wcs_world2pix( s_post[0], s_post[1], 0) # initial center estimate to draw box xmin, xmax = int(init_x - (wid_pixels / 2.0)), int( init_x + (wid_pixels / 2.0)) # boundaries ymin, ymax = int(init_y - (wid_pixels / 2.0)), int( init_y + (wid_pixels / 2.0)) # boundaries # Galaxy catalog in image pixel coordinates galpix = convpix(gal_cat, image_wcs) # objects in pixel coordinates x_pixels, y_pixels = galpix[:, 0], galpix[:, 1] # 2D-histogram on the grid in the search box binstep = 5.0 # pixels, grid resolution wght = np.asarray(gal_cat['ch2']) # weights: irac ch2[4.5 um] flux, uJy xedges, yedges = np.arange(xmin, xmax + binstep, binstep), np.arange(ymin, ymax + binstep, binstep) h, xedges, yedges = np.histogram2d(x_pixels, y_pixels, bins=(xedges, yedges), weights=wght) # Smoothing the 2D histogram of the galaxies in the search box size = int(round( (np.shape(h)[0]) / 4.0)) # kernel size : at least ~ 4 times smaller stdev_ker = size / 4.0 # size = 4-sigma gauss_kernel = Gaussian2DKernel(x_stddev=stdev_ker, y_stddev=stdev_ker, x_size=size, y_size=size) # kernel smoothed_data_gauss = convolve_fft(h.T, gauss_kernel) # convolution/smoothing # Peak of the histogram x_org, y_org = (xedges[0] + xedges[1]) / 2.0, ( yedges[0] + yedges[1]) / 2.0 # origin of bin-coordinate fp_m = find_peaks(smoothed_data_gauss, 0, npeaks=1) # 1 peak with max value xbin_peak, ybin_peak = fp_m['x_peak'][0], fp_m['y_peak'][ 0] # x, y positions of the peak x_p, y_p = (x_org + xbin_peak * binstep), ( y_org + ybin_peak * binstep) # conversion to pixel coordinates peak_fk5 = image_wcs.wcs_pix2world(x_p, y_p, 0) # Centroid of the image moments cen_pos = centroid_com(smoothed_data_gauss) cenx, ceny = (x_org + cen_pos[0] * binstep), (y_org + cen_pos[1] * binstep) centre = image_wcs.wcs_pix2world(cenx, ceny, 0) return centre, peak_fk5
# Set the approximate star coordinates of reference star chosen estimated_star_x = [998,998,958] estimated_star_y = [1161,1121,1121] actual_star_x = [0,0,0] # dummy values actual_star_y = [0,0,0] for i in range(len(sciList)): HDUList = fits.open(procList[i], ignore_missing_end=True) procData = HDUList[0].data HDUList.close() (x0, x1) = (estimated_star_x[i]-20, estimated_star_x[i]+20) #create smaller area to cover the star (y0, y1) = (estimated_star_y[i]-20, estimated_star_y[i]+20) cutout = procData[y0:y1,x0:x1] mean, median, std = sigma_clipped_stats(cutout) cx, cy = photutils.centroid_com(cutout-median) #find the center position of the star actual_star_x[i] = cx+x0 #fill in actual calculated locations of star center from above actual_star_y[i] = cy+y0 print('Image %s unshifted ref location:' % (i+1), actual_star_x[i], actual_star_y[i], '\n') #offset images to match centroid locations #default crop region xmin, xmax = 50, 2050 ymin, ymax = 150, 2150 alignedImages = np.zeros((ymax-ymin, xmax-xmin, len(sciList))) #create empty array the size of [y pix, x pix, # images] #calcualte the offset for each image and apply it then add to 3D array for i in range(len(sciList)): xoffset = int(round(actual_star_x[i]-actual_star_x[0])) yoffset = int(round(actual_star_y[i]-actual_star_y[0]))