def get_optical_psf(expid, aos=False): # set up objects. make sure I get the right mesh digestor = Digestor() PSF_Evaluator = Moment_Evaluator() mesh_name = "Science-20121120s1-v20i2_All" PSF_Interpolator = Mesh_Interpolator(mesh_name=mesh_name, directory=mesh_directory) # This will be our main wavefront WF = DECAM_Model_Wavefront(PSF_Interpolator=PSF_Interpolator) # load up data expid_path = "{0:08d}/{1:08d}".format(expid - expid % 1000, expid) data_directory = base_directory + expid_path files = sorted(glob(data_directory + "/*{0}".format("_selpsfcat.fits"))) # load up all the data from an exposure. Unfortunately, pandas is stupid and # can't handle the vignet format, so we don't load those up # note that you CAN load them up by passing "do_exclude=True", which then # returns a second variable containing the vignets and aperture fluxes and # errors # data has certain columns removed, needed for processing. # unfortunately I need full_data's vignettes and other info for later steps # TODO optimize this cuz this is clearly wasteful # I'm loading an HDUlist in 2 places, but overhauling the digestor to load it once would be a challenge data = digestor.digest_fits(files[0], do_exclude=False) metaHDUList = [fits.open(files[0])] # list of HDULists #META for file in files[1:]: tmpData = digestor.digest_fits(file, do_exclude=False) data = data.append(tmpData) metaHDUList.append(fits.open(file)) fit_i = jamierod_results.loc[expid] misalignment = { "z04d": fit_i["z04d"], "z04x": fit_i["z04x"], "z04y": fit_i["z04y"], "z05d": fit_i["z05d"], "z05x": fit_i["z05x"], "z05y": fit_i["z05y"], "z06d": fit_i["z06d"], "z06x": fit_i["z06x"], "z06y": fit_i["z06y"], "z07d": fit_i["z07d"], "z07x": fit_i["z07x"], "z07y": fit_i["z07y"], "z08d": fit_i["z08d"], "z08x": fit_i["z08x"], "z08y": fit_i["z08y"], "z09d": fit_i["z09d"], "z09x": fit_i["z09x"], "z09y": fit_i["z09y"], "z10d": fit_i["z10d"], "z10x": fit_i["z10x"], "z10y": fit_i["z10y"], "rzero": fit_i["rzero"], } # print(misalignment['rzero']) # rzero needs to be adjusted to be smaller than the stars! x = 0.3 / 0.14 # 4 misalignment["rzero"] = 1 / (1 / misalignment["rzero"] - x) # print(misalignment['rzero']) # print(.14*x ) data["rzero"] = misalignment["rzero"] optPSFStamps, model = WF.draw_psf(data, misalignment=misalignment) # optPSFStamps is a numpy data cube # full_data is data frame including vignettes of the stars return optPSFStamps, metaHDUList
def stamp_collector(expid, Nmax=0, rzero=None, snr_max=400, snr_min=90): results = np.load(jamierod_dir + '/params/params_{0:08d}.npy'.format(expid)).item() keys = sorted([key for key in results.keys() if ('error' not in key and 'fix' not in key and 'limit' not in key)]) misalignment = {key: results[key] for key in keys} params = {'expid': expid, 'misalignment': misalignment, # jamie's params: 'mesh_directory': '/nfs/slac/g/ki/ki22/roodman/ComboMeshesv20', 'mesh_name': 'Science-20121120s1-v20i2_All', } params_default = {'snr_key': 'SNR_WIN', 'snr_max': snr_max, 'snr_min': snr_min, 'data_name': '_selpsfcat.fits', 'num_bins': 4 } params_default.update(param_default_kils(expid)) params_default.update(params) params = params_default fits_files = glob(params['data_directory'] + '/*{0}'.format(params['data_name'])) dig = Digestor() model, data_stamps = dig.digest_fits(fits_files[0], do_exclude=True) data_stamps = data_stamps['VIGNET'] for fits_file in fits_files[1:]: model_i, data_stamps_i = dig.digest_fits(fits_file, do_exclude=True) model = model.append(model_i, ignore_index=True) data_stamps = np.vstack((data_stamps, data_stamps_i['VIGNET'])) if params['snr_key'] in model.columns: conds = ((model[params['snr_key']] > params['snr_min']) & (model[params['snr_key']] < params['snr_max'])) data_stamps = data_stamps[conds.values] model = model[conds] if Nmax > 0: # cut out Nmax objects rows = np.random.choice(len(model), Nmax, replace=False) model = model.iloc[rows] data_stamps = data_stamps[rows] # set data_stamps to be float64 like the model stamps data_stamps = data_stamps.astype(np.float64) if type(rzero) == type(None): model['rzero'] = results['rzero'] else: model['rzero'] = rzero # get the PSF_Interpolator PSF_Interpolator = Mesh_Interpolator(mesh_name=params['mesh_name'], directory=params['mesh_directory']) WF = DECAM_Model_Wavefront(PSF_Interpolator=PSF_Interpolator, num_bins=params['num_bins'], model=model) def plane(rzero, z04d, z04x, z04y, z05d, z05x, z05y, z06d, z06x, z06y, z07d, z07x, z07y, z08d, z08x, z08y, z09d, z09x, z09y, z10d, z10x, z10y, z11d, z11x, z11y, dz, dx, dy, xt, yt, e0, e1, e2, delta1, delta2, zeta1, zeta2, **kwargs): wf_misalignment = {'z04d': z04d, 'z04x': z04x, 'z04y': z04y, 'z05d': z05d, 'z05x': z05x, 'z05y': z05y, 'z06d': z06d, 'z06x': z06x, 'z06y': z06y, 'z07d': z07d, 'z07x': z07x, 'z07y': z07y, 'z08d': z08d, 'z08x': z08x, 'z08y': z08y, 'z09d': z09d, 'z09x': z09x, 'z09y': z09y, 'z10d': z10d, 'z10x': z10x, 'z10y': z10y, 'z11d': z11d, 'z11x': z11x, 'z11y': z11y, 'dz': dz, 'dx': dx, 'dy': dy, 'xt': xt, 'yt': yt} return wf_misalignment wf_misalignment = plane(**misalignment) # get evaluated PSFs stamps, eval_data = WF.draw_psf(WF.data, force_interpolation=True, misalignment=wf_misalignment) # apply shear to stamps directly! evaluated_psfs = WF.evaluate_psf(stamps, misalignment=wf_misalignment) # make sure evaluated_psfs has the right index evaluated_psfs.index = eval_data.index # combine the results from PSF_Evaluator with your input data combined_df = evaluated_psfs.combine_first(eval_data) # TODO: Deal with constant jitter terms! Currently the results are off and seem to be off related to the overall magnitude... ## # add dc factors ## # combined_df['e0'] += results['e0'] ## # combined_df['e1'] += results['e1'] ## # combined_df['e2'] += results['e2'] ## # combined_df['delta1'] += results['delta1'] ## # combined_df['delta2'] += results['delta2'] ## # combined_df['zeta1'] += results['zeta1'] ## # combined_df['zeta2'] += results['zeta2'] ## e1 = results['e1'] * 5 # empirical correction? ## e2 = results['e2'] * 5 ## Mx = combined_df['Mx'].values ## My = combined_df['My'].values ## esq = e1 * e1 + e2 * e2 ## if esq < 1e-8: ## A = 1 + esq / 8 + e1 * (0.5 + esq * 3 / 16) ## B = 1 + esq / 8 - e1 * (0.5 + esq * 3 / 16) ## C = e2 * (0.5 + esq * 3 / 16) ## else: ## temp = np.sqrt(1 - esq) ## cc = np.sqrt(0.5 * (1 + 1 / temp)) ## temp = cc * (1 - temp) / esq ## C = temp * e2 ## temp *= e1 ## A = cc + temp ## B = cc - temp ## matrix = np.array([[A, C], [C, B]]) ## matrix /= A * B - C * C ## offsetsx = -Mx * (A + C - 1) ## offsetsy = -My * (C + B - 1) ## # apply transformation ## stamps_transformed = [] ## for stamp, offsetx, offsety in zip(stamps, offsetsx, offsetsy): ## stamps_transformed_i = affine_transform(stamp, matrix, (offsetx, offsety)) ## stamps_transformed.append(stamps_transformed_i) ## stamps_transformed = np.array(stamps_transformed) ## evaluated_psfs = WF.evaluate_psf(stamps_transformed, misalignment=wf_misalignment) ## # make sure evaluated_psfs has the right index ## evaluated_psfs.index = eval_data.index ## # combine the results from PSF_Evaluator with your input data ## combined_df_trans = evaluated_psfs.combine_first(eval_data) ## e1 = combined_df['e1'] ## e2 = combined_df['e2'] ## e1_t = combined_df_trans['e1'] ## e2_t = combined_df_trans['e2'] ## print((e1 - e1_t) / (results['e1'])) ## print((e2 - e2_t) / (results['e2'])) return combined_df, stamps, data_stamps