def cdriver(method, data, guess, trim, radius, size, mask=None, uncd=None, fitbg=1, maskstar=True, expand=5.0, psf=None, psfctr=None): # Default mask: all good if mask is None: mask = np.ones(np.shape(data)) # Default uncertainties: flat image if uncd is None: uncd = np.ones(np.shape(data)) # Trim the image if requested if trim != 0: # Integer part of center cen = np.rint(guess) # Center in the trimed image loc = (trim, trim) # Do the trim: img, msk, err = ie.trimimage(data, cen, loc, mask=mask, uncd=uncd) else: cen = np.array([0,0]) loc = np.rint(guess) img, msk, err = data, mask, uncd # If all data is bad: if not np.any(msk): raise Exception('Bad Frame Exception!') weights = 1.0/np.abs(err) # Get the center with one of the methods: if method == 'fgc': foo, bar = g.fitgaussian(img, yxguess=loc, mask=msk, weights=weights, fitbg=fitbg, maskg=maskstar) #print(foo, bar) y, x = foo[2:4] yerr, xerr = bar[2:4] # Make trimming correction and return return ((y, x) + cen - trim), (yerr, xerr)
def spitzer_fit(data, mask, weights, psf, psfctr, scale, make, offsetrad=1.0, noffset=201): """ Routine wrapper for easy plug-in into POET pipeline. Fits a PSF in a data frame from Spitzer. Parameters: ----------- data: 2D ndarray Data image to fit the PSF. mask: 2D ndarray Mask of bad pixel values, same shape as data. Good pixels have value 1; bad pixels have value 0, and will not be considered in the fit. weights: 2D ndarray Weights for the minimization, for scientific data the weights should be 1/sqrt(variance). Same shape as data. psf: 2D ndimage The supersampled PSF image. psfctr: 2-elements tuple [y, x] y, x-position of the center of the PSF. scale: Scalar Ratio of the PSF and data pixel-scales. noffset: Scalar Radii around the guess position where to look for best fit. Returns: -------- bestfit: 4-elements tuple [y, x, starflux, skyflux] position and fluxes of the PSF that best fit the data. Modification History: --------------------- 2011-07-26 patricio First documented version. [email protected] """ # Initial flux guess: skyguess = np.median(data) starguess = np.sum(data - skyguess) fluxguess = [starguess, skyguess] # Use fit gaussian for a first YX guess: datashape = np.asarray(np.shape(data)) fit, err = g.fitgaussian(data, fitbg=1, yxguess=datashape // 2) yxguess = fit[2:4] # Obtain the position guess (depending on the make used): if make == 'bpf': # Scale to the PSF scale: yguess, xguess = np.around(scale * (yxguess + 0.5) - 0.5) elif make == 'ipf': # Guess with respect to the center of the image: yguess = yxguess[0] - np.shape(data)[0] / 2.0 - 0.5 xguess = yxguess[1] - np.shape(data)[1] / 2.0 - 0.5 # Array of shifs around our guess where to search: if make == 'bpf': noffset = int(2 * scale * offsetrad + 1) offset = np.arange(noffset) - noffset // 2 elif make == 'ipf': offset = offsetrad * np.linspace(-1.0, 1.0, noffset) yshift = yguess + offset xshift = xguess + offset shift = (yshift, xshift) # Do the fit: pos, bestp, chisq = psf_fit(data, fluxguess, psf, psfctr, scale, shift, mask=mask, weights=weights, make=make) # Return best fit: [y, x, starflux, skyflux] return (pos[0], pos[1], bestp[0], bestp[1])
def centerdriver(method, data, guess, trim, radius, size, mask=None, uncd=None, fitbg=1, maskstar=True, expand=5.0, psf=None, psfctr=None): """ Use the center method to find the center of a star in data, starting from position guess. Parameters: ----------- method: string Name of the centering method to use. data: 2D ndarray Array containing the star image. guess: 2 elements 1D array y, x initial guess position of the target. trim: integer Semi-length of the box around the target that will be trimmed. radius: float least asymmetry parameter. See err_fasym_c. size: float least asymmetry parameter. See err_fasym_c. mask: 2D ndarray A mask array of bad pixels. Same shape of data. uncd: 2D ndarray An array containing the uncertainty values of data. Same shape of data. Returns: -------- A y,x tuple (scalars) with the coordinates of center of the target in data. Example: -------- nica Modification History: --------------------- 23-11-2010 patricio Written by Patricio Cubillos [email protected] """ # Default mask: all good if mask is None: mask = np.ones(np.shape(data)) # Default uncertainties: flat image if uncd is None: uncd = np.ones(np.shape(data)) # Trim the image if requested if trim != 0: # Integer part of center cen = np.rint(guess) # Center in the trimed image loc = (trim, trim) # Do the trim: img, msk, err = ie.trimimage(data, cen, loc, mask=mask, uncd=uncd) else: cen = np.array([0, 0]) loc = np.rint(guess) img, msk, err = data, mask, uncd # If all data is bad: if not np.any(msk): raise Exception('Bad Frame Exception!') weights = 1.0 / np.abs(err) extra = [] # Get the center with one of the methods: if method == 'fgc': sy, sx, y, x = g.fitgaussian(img, yxguess=loc, mask=msk, weights=weights, fitbg=fitbg, maskg=maskstar)[0][0:4] extra = sy, sx #Gaussian 1-sigma half-widths elif method == 'col': y, x = ctr.col(img) elif method == 'lag': [y, x], asym = la.actr(img, loc, asym_rad=radius, asym_size=size, method='gaus') #y, x = ctr.actr(img, loc, asym_rad=radius, # asym_size=size, method='gaus') elif method == 'lac': [y, x], asym = la.actr(img, loc, asym_rad=radius, asym_size=size, method='col') elif method == 'bpf' or method == 'ipf': y, x, flux, sky = pf.spitzer_fit(img, msk, weights, psf, psfctr, expand, method) extra = flux, sky # Make trimming correction and return return ((y, x) + cen - trim), extra
def ctrgauss(data, guess=None, mask=None, indarr=None, trim=None): ''' Finds and records the stellar centroid of a set of images by fitting a two dimensional Gaussian function to the data. It does not find the average centroid, but instead records the centroid of each image in the supplied frame parameters array at the supplied indices. The frame parameters array is assumed to have the same number of rows as the number of frames in the data cube. Parameters ---------- data : ndarray (2D) The stellar image. guess : array_like The initial guess of the position of the star. Has the form (y, x) of the guess center. mask : ndarray (2D) The stellar image. indarr : array_like The indices of the x and y center columns of the frame parameters and the width index. Defaults to 4, 5, and 6 respectively. trim : Scalar (positive) If trim!=0, trims the image in a box of 2*trim pixels around the guess center. Must be !=0 for 'col' method. Returns ------- center : y, x The updated frame parameters array. Contains the centers of each star in each image and their average width. Revisions --------- 2010-06-23 Patricio E. Cubillos, UCF ([email protected]) Adapted to POET from Chris' routines. 2009-10-30 Christopher J. Campo, UCF ([email protected]) Initial version. ''' if guess is None: fitguess = ctrguess(data, mask, guess) guess = fitguess[1] # the pixel of the center roundguess = np.round(guess) # Trim the image around the star if requested if trim is not None: image = np.copy(data[roundguess[0] - trim:roundguess[0] + trim, roundguess[1] - trim:roundguess[1] + trim]) loc = (trim, trim) else: image = np.copy(data) loc = roundguess # Subtract the median to fit a gaussian. image -= np.median(image) fitguess = ((1.0, 1.0), loc, image[loc[0], loc[1]]) if indarr is None: indarr = np.indices(np.shape(image)) # print(np.shape(image)) # print(loc) # print(fitguess[2]) # print(np.shape(image), roundguess) # print(np.shape(indarr)) # Fit the gaussian: #(fw, fc, fh, err) = g.fitgaussian(image, indarr, guess=fitguess) p, err = g.fitgaussian(image, indarr, guess=fitguess) fw = p[0:2] fc = p[2:4] fh = p[4] #FINDME: Hack below to get denoise_cenetering.py working #foo = g.fitgaussian(image, indarr, guess=fitguess) #fc = foo[0][2:4] return (fc + roundguess - loc)
# Extracts 10 x 10 sub array centered on star. sub_y = 5 sub_x = 5 sub_array = np.copy(data_cube[first_frame, cy - sub_y: cy + sub_y +1, cx - sub_x: cx + sub_x + 1]) # Initializes tuple of data for fitgaussuan. guess = ((wid, wid), (sub_y, sub_x), ht) # Stores return values from called fitgaussian (fw, fc, fh, fe) = g.fitgaussian(sub_array, guess=guess) # Stores average width photometry[first_frame][5] = np.mean(fw) print(np.mean(fw)) # Adjusts the fitted centre coordinates back to the full array. # Stored accordingly. photometry[first_frame][3] = fc[0] + cy - sub_y photometry[first_frame][4] = fc[1] + cx - sub_x # Uses center of previous frame as guess for next frame to fit a 2D Gaussian
def profile_gauss(subdata, mask, threshold=10, guess=None, isplots=False): ''' ''' submask = np.copy(mask) ny, nx = np.shape(subdata) profile = np.zeros((ny, nx)) maxiter = ny for i in range(nx): nobadpixels = False iternum = 0 dataslice = np.copy(subdata[:,i]) #Do not want to alter original data # Set initial guess if none given guess = [ny/10.,np.argmax(dataslice),dataslice.max()] while (nobadpixels == False) and (iternum < maxiter): #if guess == None: #guess = g.old_gaussianguess(dataslice, np.arange(ny), mask=submask[:,i]) # Fit Gaussian to each column if sum(submask[:,i]) >= 3: params, err = g.fitgaussian(dataslice, np.arange(ny), mask=submask[:,i], fitbg=0, guess=guess) else: params = guess err = None # Create model model = g.gaussian(np.arange(ny), params[0], params[1], params[2]) if isplots == 7: plt.figure(3) plt.clf() plt.suptitle(str(i) + "," + str(iternum)) plt.plot(dataslice, 'ro') plt.plot(dataslice*submask[:,i], 'bo') plt.plot(model, 'g-') plt.pause(0.5) # Calculate residuals and number of sigma from the model residuals = submask[:,i]*(dataslice - model) if np.std(residuals) == 0: stdevs = np.zeros(residuals.shape) else: stdevs = np.abs(residuals) / np.std(residuals) # Find worst data point loc = np.argmax(stdevs) # Mask data point if > threshold if stdevs[loc] > threshold: # Check for bad fit, possibly due to a bad pixel if i > 0 and (err == None or abs(params[0]) < abs(0.2*guess[0])): #print(i, params) # Remove brightest pixel within region of fit loc = params[1]-3 + np.argmax(dataslice[params[1]-3:params[1]+4]) #print(loc) else: guess = abs(params) submask[loc,i] = 0 else: nobadpixels = True #exit while loop guess = abs(params) iternum += 1 profile[:,i] = model if iternum == maxiter: print('WARNING: Max number of iterations reached for dataslice ' + str(i)) # Enforce positivity profile[np.where(profile < 0)] = 0 # Normalize along spatial direction profile /= np.sum(profile, axis=0) return profile