def test_circularGrid(): dist = 10.0 outer = 4.1 inner = 0.5 xcos = 0.1 ycos = 0.2 zcos = -np.sqrt(1.0 - xcos**2 - ycos**2) nradii = 5 naz = 50 wavelength = 500e-9 flux = 1.2 medium = batoid.ConstMedium(1.2) rays = batoid.circularGrid(dist, outer, inner, xcos, ycos, zcos, nradii, naz, wavelength, flux, medium) assert rays.monochromatic == True # Check that all rays are perpendicular to v ray0 = rays[0] for ray in rays: dr = ray.r - ray0.r dp = np.dot(dr, ray0.v) np.testing.assert_allclose(dp, 0.0, atol=1e-14, rtol=0.0) np.testing.assert_allclose(ray.wavelength, wavelength) np.testing.assert_allclose(ray.flux, flux) np.testing.assert_allclose(np.linalg.norm(ray.v), 1. / 1.2) np.testing.assert_allclose(ray.v[0] * 1.2, xcos) np.testing.assert_allclose(ray.v[1] * 1.2, ycos)
def test_sum_bicubic(): import os import yaml fn = os.path.join(batoid.datadir, "LSST", "LSST_i.yaml") config = yaml.safe_load(open(fn)) telescope = batoid.parse.parse_optic(config['opticalSystem']) xcos, ycos, zcos = batoid.utils.gnomonicToDirCos(np.deg2rad(0.8), np.deg2rad(0.8)) rays = batoid.circularGrid( telescope.dist, telescope.pupilSize / 2, telescope.pupilSize * telescope.pupilObscuration / 2, xcos, ycos, -zcos, 50, 50, 750e-9, 1.0, telescope.inMedium) out, _ = telescope.trace(rays) m2 = telescope.itemDict['LSST.M2'] xs = np.linspace(-m2.outRadius, m2.outRadius, 200) ys = xs zs = np.zeros((200, 200), dtype=float) bicubic = batoid.Bicubic(xs, ys, zs) m2.surface = batoid.Sum([m2.surface, bicubic]) out2, _ = telescope.trace(rays) # Don't expect exact equality, but should be very similar assert rays_allclose(out, out2, atol=1e-13)
def test_sum_bicubic(): telescope = batoid.Optic.fromYaml("LSST_i.yaml") xcos, ycos, zcos = batoid.utils.gnomonicToDirCos( np.deg2rad(0.8), np.deg2rad(0.8) ) rays = batoid.circularGrid( telescope.backDist, telescope.pupilSize/2, telescope.pupilSize*telescope.pupilObscuration/2, xcos, ycos, -zcos, 50, 50, 750e-9, 1.0, telescope.inMedium ) out = telescope.trace(rays) m2 = telescope['LSST.M2'] xs = np.linspace(-m2.outRadius, m2.outRadius, 200) ys = xs zs = np.zeros((200, 200), dtype=float) bicubic = batoid.Bicubic(xs, ys, zs) m2.surface = batoid.Sum([m2.surface, bicubic]) out2 = telescope.trace(rays) # Don't expect exact equality, but should be very similar assert rays_allclose(out, out2, atol=1e-13)
def test_decam_psf(): # Just testing that doesn't crash for the moment fn = os.path.join(batoid.datadir, "DECam", "DECam.yaml") config = yaml.load(open(fn)) telescope = batoid.parse.parse_optic(config['opticalSystem']) stampSize = 1.0 # arcsec nx = 64 focalLength = 10.0 # guess if __name__ == '__main__': thetas = [0.0, 1800.0, 3960.0] # arcsec else: thetas = [3960.0] for theta in thetas: print(theta / 3600.0) dirCos = batoid.utils.gnomicToDirCos(0.0, theta / 206265) rays = batoid.circularGrid(10.0, 1.95, 0.5, dirCos[0], dirCos[1], -dirCos[2], 10, 100, 620e-9, 1.0, batoid.Air()) telescope.traceInPlace(rays) rays.trimVignettedInPlace() xs = rays.x - np.mean(rays.x) ys = rays.y - np.mean(rays.y) xs *= 206265 / focalLength # meters to arcsec ys *= 206265 / focalLength # Need to add half-pixel offset xs += stampSize / nx / 2 ys += stampSize / nx / 2 dx = stampSize / nx * focalLength / 206265 # meters psf = batoid.huygensPSF(telescope, 0.0, theta / 206265, 620e-9, nx=nx, dx=dx, dy=dx) if __name__ == '__main__': import matplotlib.pyplot as plt fig = plt.figure(figsize=(12, 8)) ax = fig.add_subplot(111) ax.imshow(psf.array, extent=np.r_[-1, 1, -1, 1] * stampSize / 2) ax.scatter(xs, ys, s=5, c='r', alpha=0.5) ax.set_title("DECam PSF field={:5.2f}".format(theta / 3600.0)) ax.set_xlabel("arcsec") ax.set_ylabel("arcsec") fig.tight_layout() plt.show()
def test_hsc_psf(): # Just testing that doesn't crash for the moment telescope = batoid.Optic.fromYaml("HSC.yaml") stampSize = 0.75 # arcsec nx = 64 focalLength = 15.0 # guess if __name__ == '__main__': thetas = [0.0, 1350.0, 2700.0] # arcsec else: thetas = [2700.0] for theta in thetas: print(theta / 3600.0) dirCos = batoid.utils.gnomonicToDirCos(0.0, theta / 206265) rays = batoid.circularGrid(20.0, 4.1, 0.9, dirCos[0], dirCos[1], dirCos[2], 10, 100, 620e-9, 1.0, batoid.ConstMedium(1.0)) telescope.traceInPlace(rays) rays.trimVignettedInPlace() xs = rays.x - np.mean(rays.x) ys = rays.y - np.mean(rays.y) xs *= 206265 / focalLength # meters to arcsec ys *= 206265 / focalLength # Need to add half-pixel offset xs += stampSize / nx / 2 ys += stampSize / nx / 2 dx = stampSize / nx * focalLength / 206265 # meters psf = batoid.huygensPSF(telescope, 0.0, theta / 206265, 620e-9, nx=nx, dx=dx, dy=dx) if __name__ == '__main__': import matplotlib.pyplot as plt fig = plt.figure(figsize=(12, 8)) ax = fig.add_subplot(111) ax.imshow(psf.array, extent=np.r_[-1, 1, -1, 1] * stampSize / 2) ax.scatter(xs, ys, s=5, c='r', alpha=0.5) ax.set_title("HSC PSF field={:5.2f}".format(theta / 3600.0)) ax.set_xlabel("arcsec") ax.set_ylabel("arcsec") fig.tight_layout() plt.show()
fn = os.path.join(batoid.datadir, "HSC", "HSC.yaml") factor = 0.168 / 1.5e-5 / 3600 # fn = os.path.join(batoid.datadir, "DECam", "DECam.yaml") # factor = 0.27/1.5e-5/3600 config = yaml.load(open(fn)) telescope = batoid.parse.parse_optic(config['opticalSystem']) angles = np.linspace(0.0, 1.0, 21, endpoint=True) angles = [0.3] for angle in angles: dirCos = batoid.utils.gnomicToDirCos(0.0, np.deg2rad(angle)) rays = batoid.circularGrid( telescope.dist, telescope.pupilSize / 2, telescope.pupilSize * telescope.pupilObscuration / 2, dirCos[0], dirCos[1], -dirCos[2], 300, 900, 500e-9, 1.0, telescope.inMedium) rForward, rReverse, _, _ = telescope.traceSplit(rays, minFlux=1e-4, verbose=True) print(len(rays)) print(np.sum(rays.flux)) print(len(rForward)) print(len(rReverse)) print(np.sum(rForward.flux)) print(np.sum(rReverse.flux)) fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8, 8)) ax.hexbin(rForward.x * factor,
def parallel_trace_timing(nside=1024, nthread=None, minChunk=None): if nthread is not None: print("setting to nthread to {}".format(nthread)) batoid._batoid.setNThread(nthread) print("Using {} threads".format(batoid._batoid.getNThread())) if minChunk is not None: print("setting to minChunk to {}".format(minChunk)) batoid._batoid.setMinChunk(minChunk) print("Using minChunk of {}".format(batoid._batoid.getMinChunk())) # 0.3, 0.3 should be in bounds for current wide-field telescopes theta_x = np.deg2rad(0.3) theta_y = np.deg2rad(0.3) dirCos = np.array([theta_x, theta_y, -1.0]) dirCos = batoid.utils.normalized(dirCos) rays = batoid.circularGrid( 20, 4.2, 0.5, dirCos[0], dirCos[1], dirCos[2], nside, nside, 700e-9, 1.0, batoid.ConstMedium(1.0) ) nrays = len(rays) print("Tracing {} rays.".format(nrays)) print() if args.lsst: fn = os.path.join(batoid.datadir, "LSST", "LSST_r.yaml") pm = 'LSST.M1' else: fn = os.path.join(batoid.datadir, "HSC", "HSC.yaml") pm = 'SubaruHSC.PM' config = yaml.load(open(fn)) telescope = batoid.parse.parse_optic(config['opticalSystem']) # Optionally perturb the primary mirror using Zernike polynomial if args.perturbZ != 0: orig = telescope.itemDict[pm].surface coefs = np.random.normal(size=args.perturbZ+1)*1e-6 # micron perturbations perturbation = batoid.Zernike(coefs, R_outer=telescope.pupilSize) telescope.itemDict[pm].surface = batoid.Sum([orig, perturbation]) # Optionally perturb primary mirror using bicubic spline if args.perturbBC != 0: orig = telescope.itemDict[pm].surface xs = np.linspace(-5, 5, 100) ys = np.linspace(-5, 5, 100) def f(x, y): return args.perturbBC*(np.cos(x) + np.sin(y)) zs = f(*np.meshgrid(xs, ys)) bc = batoid.Bicubic(xs, ys, zs) telescope.itemDict[pm].surface = batoid.Sum([orig, bc]) print("Immutable trace") t0 = time.time() rays_out, _ = telescope.trace(rays) t1 = time.time() print("{} rays per second".format(int(nrays/(t1-t0)))) print() print("Trace in place") t0 = time.time() telescope.traceInPlace(rays) t1 = time.time() print("{} rays per second".format(int(nrays/(t1-t0)))) assert rays == rays_out if args.plot: import matplotlib.pyplot as plt rays.trimVignettedInPlace() x = rays.x y = rays.y x -= np.mean(x) y -= np.mean(y) x *= 1e6 y *= 1e6 plt.scatter(x, y, s=1, alpha=0.01) plt.xlim(np.std(x)*np.r_[-3,3]) plt.ylim(np.std(y)*np.r_[-3,3]) plt.xlabel("x (microns)") plt.ylabel("y (microns)") plt.show()
def parallel_trace_timing(nside=1024, nthread=None, minChunk=None): if nthread is not None: print("setting nthread to {}".format(nthread)) batoid._batoid.setNThread(nthread) print("Using {} threads".format(batoid._batoid.getNThread())) if minChunk is not None: print("setting minChunk to {}".format(minChunk)) batoid._batoid.setMinChunk(minChunk) print("Using minChunk of {}".format(batoid._batoid.getMinChunk())) # 0.3, 0.3 should be in bounds for current wide-field telescopes dirCos = batoid.utils.gnomicToDirCos(np.deg2rad(0.3), np.deg2rad(0.3)) if args.lsst: fn = os.path.join(batoid.datadir, "LSST", "LSST_i.yaml") pm = 'LSST.M1' elif args.decam: fn = os.path.join(batoid.datadir, "DECam", "DECam.yaml") pm = 'BlancoDECam.PM' else: fn = os.path.join(batoid.datadir, "HSC", "HSC.yaml") pm = 'SubaruHSC.PM' config = yaml.load(open(fn)) telescope = batoid.parse.parse_optic(config['opticalSystem']) rays = batoid.circularGrid( telescope.dist, 0.5 * telescope.pupilSize, 0.5 * telescope.pupilObscuration * telescope.pupilSize, dirCos[0], dirCos[1], -dirCos[2], nside, nside, 750e-9, 1.0, telescope.inMedium) nrays = len(rays) print("Tracing {} rays.".format(nrays)) print() # Optionally perturb the primary mirror using Zernike polynomial if args.perturbZ != 0: orig = telescope.itemDict[pm].surface coefs = np.random.normal(size=args.perturbZ + 1) * 1e-6 # micron perturbations perturbation = batoid.Zernike(coefs, R_outer=telescope.pupilSize) telescope.itemDict[pm].surface = batoid.Sum([orig, perturbation]) # Optionally perturb primary mirror using bicubic spline if args.perturbBC != 0: orig = telescope.itemDict[pm].surface rad = telescope.pupilSize / 2 * 1.1 xs = np.linspace(-rad, rad, 100) ys = np.linspace(-rad, rad, 100) def f(x, y): return args.perturbBC * (np.cos(x) + np.sin(y)) zs = f(*np.meshgrid(xs, ys)) bc = batoid.Bicubic(xs, ys, zs) telescope.itemDict[pm].surface = batoid.Sum([orig, bc]) if args.immutable: print("Immutable trace") t0 = time.time() for _ in range(args.nrepeat): rays_in = batoid.RayVector(rays) rays_out, _ = telescope.trace(rays_in) t1 = time.time() print("{} rays per second".format(int(nrays * args.nrepeat / (t1 - t0)))) print() else: print("Trace in place") t0 = time.time() for _ in range(args.nrepeat): rays_out = batoid.RayVector(rays) telescope.traceInPlace(rays_out) t1 = time.time() print("{} rays per second".format(int(nrays * args.nrepeat / (t1 - t0)))) if args.plot: import matplotlib.pyplot as plt rays_out.trimVignettedInPlace() x = rays_out.x y = rays_out.y x -= np.mean(x) y -= np.mean(y) x *= 1e6 y *= 1e6 plt.scatter(x, y, s=1, alpha=0.01) plt.xlim(np.std(x) * np.r_[-5, 5]) plt.ylim(np.std(y) * np.r_[-5, 5]) plt.xlabel("x (microns)") plt.ylabel("y (microns)") plt.show()