def __init__(self, data, dq, shifts, psf_model, parms, clip, kind, noise_model=None): assert kind in ['noise', 'nll'] psfs = render_psfs(psf_model, shifts, parms.patch_shape, parms.psf_grid, parms.k) if kind == 'noise': return self.get_noise_model(data, dq, shifts, psfs, parms, clip) if kind == 'nll': return self.get_nll(data, dq, shifts, psfs, parms, clip, noise_models)
def evaluate((data, dq, shifts, psf_model, parms, core)): """ Compute the scaled squared error and regularization under the current model. """ if core: patch_shape = parms.core_shape else: patch_shape = parms.patch_shape min_pixels = np.ceil(parms.min_frac * patch_shape[0] * patch_shape[1]) psfs = render_psfs(psf_model, shifts, patch_shape, parms.psf_grid, parms.k) if parms.return_parms: if parms.background == 'constant': fit_parms = np.zeros((data.shape[0], 2)) else: fit_parms = np.zeros((data.shape[0], 4)) masks = np.zeros_like(data, dtype=np.bool) nll = np.zeros_like(data) for i in range(data.shape[0]): fitparms, bkg, ind = fit_single_patch((data[i], psfs[i], dq[i], parms)) model = fitparms[0] * psfs[i] + bkg scaled = fitparms[0] * psfs[i] # chi-squared like term if (model[ind].size >= min_pixels): nll[i, ind] = eval_nll(data[i][ind], model[ind], parms) else: nll[i] = parms.max_nll if parms.plot_data: # get pre-clip nll ind = parms.flags.ravel() != 1 old_nll = np.zeros(patch_shape[0] * patch_shape[1]) old_nll[ind] = eval_nll(data[i][ind], parms.old_model[ind], parms) # plot the data plot_data(i, data[i], model, bkg, nll[i], old_nll, parms) if parms.return_parms: fit_parms[i] = fitparms masks[i] = ind if parms.return_parms: return nll, fit_parms, masks else: return nll
def shift_loss(shift, psf_model, datum, dq, parms): """ Evaluate the shift for a given patch. """ # Horrible hack for minimizers w/o bounds if np.any(np.abs(shift) > 0.5): return parms.max_nll # render the psf model for given shift psf = render_psfs(psf_model, shift[None, :], parms.core_shape, parms.psf_grid, parms.k) # the fit fit_parms, fit_vars, bkg, ind = fit_single_patch(datum, psf[0], dq, parms) model = fit_parms[0] * psf[0] + bkg return np.sum(patch_nll(datum[ind], model[ind], parms))
def one_datum_nll_diff((datum, shift, psf_model, old_nll, fitparms, mask, steps, parms)): """ Calculate the derivative for a single datum using forward differencing. """ # if not enough good pixels, discard patch min_pixels = np.ceil(parms.min_frac * datum.size) if datum[mask].size < min_pixels: return np.zeros_like(psf_model) # background model if parms.background == 'linear': N = np.sqrt(psf_model.size).astype(np.int) x, y = np.meshgrid(range(N), range(N)) A = np.vstack((np.ones_like(psf), np.ones_like(psf), x.ravel(), y.ravel())).T bkg = make_background(datum, A, fitparms, parms.background) elif parms.background == None: bkg = 0.0 else: bkg = fitparms[-1] # calculate the difference in nll, tweaking each psf parm. steps = parms.h * psf_model deriv = np.zeros_like(psf_model) for i in range(parms.psf_model_shape[0]): for j in range(parms.psf_model_shape[1]): temp_psf = psf_model.copy() temp_psf[i, j] += steps[i, j] psf = render_psfs(temp_psf, shift, parms.patch_shape, parms.psf_grid)[0] model = fitparms[0] * psf + bkg diff = eval_nll(datum[mask], model[mask], parms) - old_nll[mask] deriv[i, j] = np.sum(diff) / steps[i, j] return deriv
def fit_patches(data, dq, shifts, psf_model, parms, old_fit_parms=None): """ Fit the patches and return model components and nll. """ # initialize nll = np.zeros_like(data) masks = np.zeros_like(data, dtype=np.bool) if parms.background == None: fit_parms = np.zeros(data.shape[0]) elif parms.background == 'constant': fit_parms = np.zeros((data.shape[0], 2)) else: assert 0, 'no linear bkgs, need to implement uncertainties' fit_parms = np.zeros((data.shape[0], 4)) fit_vars = np.zeros_like(fit_parms) psfs = render_psfs(psf_model, shifts, parms.patch_shape, parms.psf_grid, parms.k) for i in range(data.shape[0]): dlt_nll = np.inf if old_fit_parms == None: fp, fv, bkg, ind = fit_single_patch(data[i], psfs[i], dq[i], parms) else: bkg = make_background(data[i], old_fit_parms[i], parms.background) model = old_fit_parms[i][0] * psfs[i] + bkg nm = parms.floor + parms.gain * np.abs(model) fp, fv, bkg, ind = fit_single_patch(data[i], psfs[i], dq[i], parms, var=nm) model = fp[0] * psfs[i] + bkg nm = parms.floor + parms.gain * np.abs(model) cur_nll = np.sum(patch_nll(data[i][ind], model[ind], parms)) cur_fp = fp cur_fv = fv while dlt_nll > parms.nll_tol: fp, fv, bkg, idx = fit_single_patch(data[i], psfs[i], dq[i], parms, var=nm) model = fp[0] * psfs[i] + bkg nm = parms.floor + parms.gain * np.abs(model) new_nll = np.sum(patch_nll(data[i][idx], model[idx], parms)) dlt_nll = cur_nll - new_nll if dlt_nll > 0: ind = idx cur_fp = fp cur_fv = fv cur_nll = new_nll assert cur_nll < parms.max_nll nll[i, ind] = cur_nll masks[i] = ind fit_parms[i] = cur_fp fit_vars[i] = cur_fv if parms.plot_data: # get pre-clip nll if parms.clip_parms == None: parms.old_model = model parms.old_bkg = bkg flags = dq[i].reshape(parms.patch_shape) flags[flags > 1] = 1 parms.flags = flags else: ind = parms.flags.ravel() != 1 old_nll = np.zeros(data.shape[1]) old_nll[ind] = patch_nll(data[i][ind], parms.old_model[ind], parms) # plot the data t = time.time() plot_data(i, data[i], model, bkg, nll[i], old_nll, parms) return fit_parms, fit_vars, nll, masks