def test_CRG_noise(args): """Test noise propagation in ChromaticRealGalaxy """ t0 = time.time() print("Constructing chromatic PSFs") in_PSF = galsim.ChromaticAiry(lam=700., diam=2.4) out_PSF = galsim.ChromaticAiry(lam=700., diam=1.2) print("Constructing filters and SEDs") waves = np.arange(550.0, 900.1, 10.0) visband = galsim.Bandpass(galsim.LookupTable(waves, np.ones_like(waves), interpolant='linear'), wave_type='nm') split_points = np.linspace(550.0, 900.0, args.Nim + 1, endpoint=True) bands = [ visband.truncate(blue_limit=blim, red_limit=rlim) for blim, rlim in zip(split_points[:-1], split_points[1:]) ] maxk = max([ out_PSF.evaluateAtWavelength(waves[0]).maxK(), out_PSF.evaluateAtWavelength(waves[-1]).maxK() ]) SEDs = [ galsim.SED(galsim.LookupTable(waves, waves**i, interpolant='linear'), flux_type='fphotons', wave_type='nm').withFlux(1.0, visband) for i in range(args.NSED) ] print("Constructing input noise correlation functions") rng = galsim.BaseDeviate(args.seed) in_xis = [ galsim.getCOSMOSNoise(cosmos_scale=args.in_scale, rng=rng).dilate(1 + i * 0.05).rotate( 5 * i * galsim.degrees) for i in range(args.Nim) ] print("Creating noise images") img_sets = [] for i in range(args.Ntrial): imgs = [] for j, xi in enumerate(in_xis): img = galsim.Image(args.in_Nx, args.in_Nx, scale=args.in_scale) img.addNoise(xi) imgs.append(img) img_sets.append(imgs) print("Constructing `ChromaticRealGalaxy`s") crgs = [] with ProgressBar(len(img_sets)) as bar: for imgs in img_sets: crgs.append( galsim.ChromaticRealGalaxy.makeFromImages(imgs, bands, in_PSF, in_xis, SEDs=SEDs, maxk=maxk)) bar.update() print("Convolving by output PSF") objs = [galsim.Convolve(crg, out_PSF) for crg in crgs] print("Drawing through output filter") out_imgs = [ obj.drawImage(visband, nx=args.out_Nx, ny=args.out_Nx, scale=args.out_scale, iimult=args.iimult) for obj in objs ] noise = objs[0].noise print("Measuring images' correlation functions") xi_obs = galsim.correlatednoise.CorrelatedNoise(out_imgs[0]) for img in out_imgs[1:]: xi_obs += galsim.correlatednoise.CorrelatedNoise(img) xi_obs /= args.Ntrial xi_obs_img = galsim.Image(args.out_Nx, args.out_Nx, scale=args.out_scale) xi_obs.drawImage(xi_obs_img) print("Observed image variance: ", xi_obs.getVariance()) print("Predicted image variance: ", noise.getVariance()) print("Predicted/Observed variance:", noise.getVariance() / xi_obs.getVariance()) print("Took {} seconds".format(time.time() - t0)) if args.plot: import matplotlib.pyplot as plt out_array = (np.arange(args.out_Nx) - args.out_Nx / 2) * args.out_scale out_extent = [ -args.out_Nx * args.out_scale / 2, args.out_Nx * args.out_scale / 2, -args.out_Nx * args.out_scale / 2, args.out_Nx * args.out_scale / 2 ] fig = plt.figure(figsize=(5, 5)) # Sample image ax = fig.add_subplot(111) ax.imshow(out_imgs[0].array, extent=out_extent) ax.set_title("sample output image") ax.set_xlabel("x") ax.set_ylabel("y") # ax.colorbar() fig.show() # 2D correlation functions fig = plt.figure(figsize=(10, 10)) ax1 = fig.add_subplot(221) noise_img = galsim.Image(args.out_Nx, args.out_Nx, scale=args.out_scale) noise.drawImage(noise_img) ax1.imshow(np.log10(np.abs(noise_img.array)), extent=out_extent) ax1.set_title("predicted covariance function") ax1.set_xlabel(r"$\Delta x$") ax1.set_ylabel(r"$\Delta y$") ax2 = fig.add_subplot(222) ax2.imshow(np.log10(np.abs(xi_obs_img.array)), extent=out_extent) ax2.set_title("observed covariance function") ax2.set_xlabel(r"$\Delta x$") ax2.set_ylabel(r"$\Delta y$") # 1D slide through correlation functions ax3 = fig.add_subplot(223) ax3.plot(out_array, noise_img.array[args.out_Nx / 2, :], label="prediction", color='red') ax3.plot(out_array, xi_obs_img.array[args.out_Nx / 2, :], label="observation", color='blue') ax3.legend(loc='best') ax3.set_xlabel(r"$\Delta x$") ax3.set_ylabel(r"$\xi$") ax4 = fig.add_subplot(224) ax4.plot(out_array, noise_img.array[args.out_Nx / 2, :], label="prediction", color='red') ax4.plot(out_array, xi_obs_img.array[args.out_Nx / 2, :], label="observation", color='blue') ax4.plot(out_array, -noise_img.array[args.out_Nx / 2, :], ls=':', color='red') ax4.plot(out_array, -xi_obs_img.array[args.out_Nx / 2, :], ls=':', color='blue') ax4.legend(loc='best') ax4.set_yscale('log') ax4.set_xlabel(r"$\Delta x$") ax4.set_ylabel(r"$\xi$") plt.tight_layout() plt.show()
def check_crg_noise(n_sed, n_im, n_trial, tol): print("Checking CRG noise for") print("n_sed = {}".format(n_sed)) print("n_im = {}".format(n_im)) print("n_trial = {}".format(n_trial)) print("Constructing chromatic PSFs") in_PSF = galsim.ChromaticAiry(lam=700., diam=2.4) out_PSF = galsim.ChromaticAiry(lam=700., diam=0.6) print("Constructing filters and SEDs") waves = np.arange(550.0, 900.1, 10.0) visband = galsim.Bandpass(galsim.LookupTable(waves, np.ones_like(waves), interpolant='linear'), wave_type='nm') split_points = np.linspace(550.0, 900.0, n_im + 1, endpoint=True) bands = [ visband.truncate(blue_limit=blim, red_limit=rlim) for blim, rlim in zip(split_points[:-1], split_points[1:]) ] maxk = max([ out_PSF.evaluateAtWavelength(waves[0]).maxk, out_PSF.evaluateAtWavelength(waves[-1]).maxk ]) SEDs = [ galsim.SED(galsim.LookupTable(waves, waves**i, interpolant='linear'), flux_type='fphotons', wave_type='nm').withFlux(1.0, visband) for i in range(n_sed) ] print("Constructing input noise correlation functions") rng = galsim.BaseDeviate(57721) in_xis = [ galsim.getCOSMOSNoise(cosmos_scale=0.03, rng=rng).dilate(1 + i * 0.05).rotate( 5 * i * galsim.degrees) for i in range(n_im) ] print("Creating noise images") img_sets = [] for i in range(n_trial): imgs = [] for xi in in_xis: img = galsim.Image(128, 128, scale=0.03) img.addNoise(xi) imgs.append(img) img_sets.append(imgs) print("Constructing `ChromaticRealGalaxy`s") crgs = [] for imgs in img_sets: crgs.append( galsim.ChromaticRealGalaxy.makeFromImages(imgs, bands, in_PSF, in_xis, SEDs=SEDs, maxk=maxk)) print("Convolving by output PSF") objs = [galsim.Convolve(crg, out_PSF) for crg in crgs] with assert_raises(galsim.GalSimError): noise = objs[0].noise # Invalid before drawImage is called print("Drawing through output filter") out_imgs = [ obj.drawImage(visband, nx=30, ny=30, scale=0.1) for obj in objs ] noise = objs[0].noise print("Measuring images' correlation functions") xi_obs = galsim.correlatednoise.CorrelatedNoise(out_imgs[0]) for img in out_imgs[1:]: xi_obs += galsim.correlatednoise.CorrelatedNoise(img) xi_obs /= n_trial xi_obs_img = galsim.Image(30, 30, scale=0.1) xi_obs.drawImage(xi_obs_img) noise_img = galsim.Image(30, 30, scale=0.1) noise.drawImage(noise_img) print("Predicted/Observed variance:", noise.getVariance() / xi_obs.getVariance()) print("Predicted/Observed xlag-1 covariance:", noise_img.array[14, 15] / xi_obs_img.array[14, 15]) print("Predicted/Observed ylag-1 covariance:", noise_img.array[15, 14] / xi_obs_img.array[15, 14]) # Just test that the covariances for nearest neighbor pixels are accurate. np.testing.assert_allclose(noise_img.array[14:17, 14:17], xi_obs_img.array[14:17, 14:17], rtol=0, atol=noise.getVariance() * tol)
def test_CRG(args): """Predict an LSST or Euclid image given HST images of a galaxy with color gradients.""" t0 = time.time() print("Constructing chromatic PSFs") in_PSF = galsim.ChromaticAiry(lam=700, diam=2.4) if args.lsst_psf: out_PSF = galsim.ChromaticAtmosphere(galsim.Kolmogorov(fwhm=0.6), 500.0, zenith_angle=0 * galsim.degrees, parallactic_angle=0.0 * galsim.degrees) else: out_PSF = galsim.ChromaticAiry(lam=700, diam=1.2) # Euclid-like print("Constructing filters and SEDs") waves = np.arange(550.0, 900.1, 10.0) visband = galsim.Bandpass(galsim.LookupTable(waves, np.ones_like(waves), interpolant='linear'), wave_type='nm') split_points = np.linspace(550.0, 900.0, args.Nim + 1, endpoint=True) bands = [ visband.truncate(blue_limit=blim, red_limit=rlim) for blim, rlim in zip(split_points[:-1], split_points[1:]) ] outband = visband.truncate(blue_limit=args.out_blim, red_limit=args.out_rlim) maxk = max([ out_PSF.evaluateAtWavelength(waves[0]).maxK(), out_PSF.evaluateAtWavelength(waves[-1]).maxK() ]) SEDs = [ galsim.SED(galsim.LookupTable(waves, waves**i, interpolant='linear'), wave_type='nm', flux_type='fphotons').withFlux(1.0, visband) for i in range(args.NSED) ] print("Construction input noise correlation functions") rng = galsim.BaseDeviate(args.seed) in_xis = [ galsim.getCOSMOSNoise(cosmos_scale=args.in_scale, rng=rng).dilate(1 + i * 0.05).rotate( 30 * i * galsim.degrees) for i in range(args.Nim) ] print("Constructing galaxy") components = [galsim.Gaussian(half_light_radius=0.3).shear(e1=0.1)] for i in range(1, args.Nim): components.append( galsim.Gaussian(half_light_radius=0.3 + 0.1 * np.cos(i)).shear( e=0.4 + np.cos(i) * 0.4, beta=i * galsim.radians).shift(0.4 * i, -0.4 * i)) gal = galsim.Add([c * s for c, s in zip(components, SEDs)]) gal = gal.shift(-gal.centroid(visband)) in_prof = galsim.Convolve(gal, in_PSF) out_prof = galsim.Convolve(gal, out_PSF) print("Drawing input images") in_Nx = args.in_Nx in_Ny = args.in_Ny if args.in_Ny is not None else in_Nx in_imgs = [ in_prof.drawImage(band, nx=in_Nx, ny=in_Ny, scale=args.in_scale) for band in bands ] [ img.addNoiseSNR(xi, args.SNR, preserve_flux=True) for xi, img in zip(in_xis, in_imgs) ] print("Drawing true output image") out_img = out_prof.drawImage(outband, nx=args.out_Nx, ny=args.out_Nx, scale=args.out_scale) # Now "deconvolve" the chromatic HST PSF while asserting the correct SEDs. print("Constructing ChromaticRealGalaxy") crg = galsim.ChromaticRealGalaxy.makeFromImages(in_imgs, bands, in_PSF, in_xis, SEDs=SEDs, maxk=maxk) # crg should be effectively the same thing as gal now. Let's test. crg_prof = galsim.Convolve(crg, out_PSF) crg_img = crg_prof.drawImage(outband, nx=args.out_Nx, ny=args.out_Nx, scale=args.out_scale) print("Max comparison:", out_img.array.max(), crg_img.array.max()) print("Sum comparison:", out_img.array.sum(), crg_img.array.sum()) print("Took {} seconds".format(time.time() - t0)) if args.plot: import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec in_extent = [ -in_Nx * args.in_scale / 2, in_Nx * args.in_scale / 2, -in_Ny * args.in_scale / 2, in_Ny * args.in_scale / 2 ] out_extent = [ -args.out_Nx * args.out_scale / 2, args.out_Nx * args.out_scale / 2, -args.out_Nx * args.out_scale / 2, args.out_Nx * args.out_scale / 2 ] fig = plt.figure(figsize=(10, 5)) outer_grid = gridspec.GridSpec(2, 1) # Input images inner_grid = gridspec.GridSpecFromSubplotSpec(1, args.Nim, outer_grid[0]) for i, img in enumerate(in_imgs): ax = plt.Subplot(fig, inner_grid[i]) im = ax.imshow(img.array, extent=in_extent, cmap='viridis') ax.set_title("band[{}] input".format(i)) # ax.set_xticks([]) # ax.set_yticks([]) fig.add_subplot(ax) plt.colorbar(im) inner_grid = gridspec.GridSpecFromSubplotSpec(1, 3, outer_grid[1]) # Output image, truth, and residual ax = plt.Subplot(fig, inner_grid[0]) ax.set_title("True output") im = ax.imshow(out_img.array, extent=out_extent, cmap='viridis') # ax.set_xticks([]) # ax.set_yticks([]) fig.add_subplot(ax) plt.colorbar(im) ax = plt.Subplot(fig, inner_grid[1]) ax.set_title("Reconstructed output") # ax.set_xticks([]) # ax.set_yticks([]) im = ax.imshow(crg_img.array, extent=out_extent, cmap='viridis') fig.add_subplot(ax) plt.colorbar(im) ax = plt.Subplot(fig, inner_grid[2]) ax.set_title("Residual") ax.set_xticks([]) ax.set_yticks([]) resid = crg_img.array - out_img.array vmin, vmax = np.percentile(resid, [5.0, 95.0]) v = np.max([np.abs(vmin), np.abs(vmax)]) im = ax.imshow(resid, extent=out_extent, cmap='seismic', vmin=-v, vmax=v) fig.add_subplot(ax) plt.colorbar(im) plt.tight_layout() plt.show()