def fit_patches(self, data, dq, parms, clip, psfs, noise_models): """ Fit the data given the psf_model """ flags = np.zeros_like(data, dtype=np.int) fit_vars = np.zeros_like(data) fit_masks = np.ones_like(data, dtype=np.bool) for i in range(data.shape[0]): fp, fv, ind = self.fit_single_patch(data[i], dq[i], psfs[i], noise_models[i]) if i == 0: fit_parms = np.zeros(data.shape[0], fp.shape[1]) if clip: for j in range(parms.clip_iter): # define model and clip variance scaled_psf, bkg = self.construct_model_parts(fp[None, :], psfs) model = scaled_psf + bkg clip_var = parms.floor + parms.gain * np.abs(model) clip_var += parms.q * scaled_psf ** 2. # sigma clip chi = np.zeros_like(data) chi[ind] = np.abs(data[ind] - model[ind]) / np.sqrt(clip_var[ind]) condition = chi - parms.clip_tol condition = (condition > 0).reshape(parms.patch_shape) # redefine mask, grow and add to dq mask. ind = 1 - ind.reshape(parms.patch_shape) idx = grow_mask(condition) flags[i] = ind.copy() flags[i][idx] = 3 flags[i][condition] = 2 ind = np.ravel((ind == 0) & (idx == 0)) # refit fp, fv, ind = self.fit_single_patch(data[i], dq[i], psfs[i], noise_models[i], ind=ind) fit_vars[i] = fv fit_masks[i] = ind fit_parms[i] = fp return fit_parms, fit_vars, fit_masks
def fit_single_patch(data, psf, dq, parms, var=None): """ Fit a single patch, return the scale for the psf plus any background parameters. Takes in flattened arrays for data and psf. """ gain = parms.gain floor = parms.floor clip_parms = parms.clip_parms background = parms.background if var == None: var = np.ones_like(data) if background is None: A = np.atleast_2d(psf).T elif background == 'constant': A = np.vstack((psf, np.ones_like(psf))).T elif background == 'linear': N = np.sqrt(psf.size).astype(np.int) x, y = np.meshgrid(range(N), range(N)) A = np.vstack((psf, np.ones_like(psf), x.ravel(), y.ravel())).T else: assert False, 'Background model not supported: %s' % background ind = dq == 0 # fit the data using least squares rh = np.dot(A[ind, :].T, data[ind] / var[ind]) try: lh = np.linalg.inv(np.dot(A[ind, :].T, A[ind, :] / var[ind, None])) fit_parms = np.dot(lh, rh) except: fit_parms = np.zeros(A.shape[1]) bkg = make_background(data, fit_parms, background) # sigma clip if desired if (clip_parms is not None) & (np.any(fit_parms != 0)): Niter = clip_parms[0] assert Niter == 1, 'Multiple rounds of clipping not supported.' tol = clip_parms[1] for i in range(Niter): # define model and noise scaled_psf = psf * fit_parms[0] model = scaled_psf + bkg if parms.plot_data: parms.old_bkg = bkg parms.old_model = model model = model[ind] scaled_psf = scaled_psf[ind] var = floor + gain * np.abs(model) + (parms.q * scaled_psf) ** 2. # sigma clip chi = np.zeros_like(data) chi[ind] = np.abs(data[ind] - model) / np.sqrt(var) condition = chi - tol condition = (condition > 0).reshape(parms.patch_shape) # redefine mask, grow and add to dq mask. ind = 1 - ind.reshape(parms.patch_shape) idx = grow_mask(condition) if parms.plot_data: parms.flags = ind.copy() parms.flags[idx] = 3 parms.flags[condition] = 2 ind = np.ravel((ind == 0) & (idx == 0)) # refit rh = np.dot(A[ind, :].T, data[ind]) try: lh = np.linalg.inv(np.dot(A[ind, :].T, A[ind, :])) fit_parms = np.dot(lh, rh) except: fit_parms = np.zeros(A.shape[1]) bkg = make_background(data, fit_parms, background) fit_vars = np.diagonal(lh) return fit_parms, fit_vars, bkg, ind
def fig1(small=1.e-6): """ Figure showing examples of data patches """ Nexamples = 16 rows = 4 cols = 4 rsize = 4 csize = 4 shrink = 1. ws, hs = 0.0, 0.2 fs = 24 # load data and dq f = pf.open('../data/region/f160w_25_457_557_457_557_pixels.fits') d = f[0].data f.close() f = pf.open('../data/region/f160w_25_457_557_457_557_dq.fits') dq = f[0].data f.close() # toss data where dq is nonzero in center center_pixel = (d.shape[1] - 1 ) / 2 ind = dq[:, center_pixel] == 0 d = d[ind] dq = dq[ind] # sort by maxima mxs = d[:, center_pixel] ind = np.argsort(mxs) mxs = mxs[ind] d = d[ind] dq = dq[ind] # get 7 other random patches ind = [0, d.shape[0] - 1] count = 0 while True: new = np.random.randint(d.shape[0]) if new in ind: continue else: ind.append(new) if len(ind) == Nexamples: break # sort and reshape to 2D ind = np.array(ind) data = d[ind] dq = dq[ind] mxs = data[:, center_pixel] ind = np.argsort(mxs) patch_side_size = np.sqrt(data.shape[1]) # assumes square patches dq = dq[ind].reshape(Nexamples, patch_side_size, patch_side_size) data = data[ind].reshape(Nexamples, patch_side_size, patch_side_size) # the figure pl.gray() f = pl.figure(figsize=(rows * rsize, cols * csize)) pl.subplots_adjust(wspace=ws, hspace=hs) axes = [None] * cols for i in range(Nexamples): # patch pixels with dq != 0 bad_pix = np.where(dq[i] != 0) for j in range(bad_pix[0].size): ind = np.zeros_like(dq[i]) ind[bad_pix[0][j], bad_pix[1][j]] = 1 idx = grow_mask(ind) fix = np.median(data[i][idx]) data[i][bad_pix[0][j], bad_pix[1][j]] = fix mn = data[i].min() mx = data[i].max() kwargs = {'interpolation':'nearest', 'origin':'lower', 'norm':LogNorm(vmin=mn, vmax=mx)} ax = pl.subplot(rows, cols, i + 1) pl.imshow(data[i], **kwargs) ax.set_xticks([]) ax.set_yticks([]) pl.title('[%0.1f, %0.0f]' % (mn, mx), fontsize=fs) f.savefig('../plots/paper/fig1.png', bbox_inches='tight') pl.close(f)