def test_asphere_reflection_coordtransform(): import random random.seed(5772156) asphere = batoid.Asphere(23.0, -0.97, [1e-5, 1e-6]) for i in range(1000): x = random.gauss(0, 1) y = random.gauss(0, 1) vx = random.gauss(0, 1e-1) vy = random.gauss(0, 1e-1) v = np.array([vx, vy, 1]) v /= np.linalg.norm(v) ray = batoid.Ray([x, y, -0.1], v, 0) ray2 = ray.copy() cs = batoid.CoordSys( [random.uniform(-0.01, 0.01), random.uniform(-0.01, 0.01), random.uniform(-0.01, 0.01)], (batoid.RotX(random.uniform(-0.01, 0.01)) .dot(batoid.RotY(random.uniform(-0.01, 0.01))) .dot(batoid.RotZ(random.uniform(-0.01, 0.01))) ) ) rray = asphere.reflect(ray, coordSys=cs) rray2 = asphere.reflect(ray2.toCoordSys(cs)) assert ray_isclose(rray, rray2)
def test_rotation(): try: import galsim except ImportError: print("optic rotation test requires GalSim") return np.random.seed(57) telescope = batoid.Optic.fromYaml("HSC.yaml") rot = batoid.RotX(np.random.uniform(low=0.0, high=2*np.pi)) rot = rot.dot(batoid.RotY(np.random.uniform(low=0.0, high=2*np.pi))) rot = rot.dot(batoid.RotZ(np.random.uniform(low=0.0, high=2*np.pi))) rotInv = np.linalg.inv(rot) # It's hard to test the two telescopes for equality due to rounding errors, so we test by # comparing zernikes rotTel = telescope.withLocalRotation(rot).withLocalRotation(rotInv) theta_x = np.random.uniform(-0.005, 0.005) theta_y = np.random.uniform(-0.005, 0.005) wavelength = 750e-9 np.testing.assert_allclose( batoid.psf.zernike(telescope, theta_x, theta_y, wavelength), batoid.psf.zernike(rotTel, theta_x, theta_y, wavelength), atol=1e-5 ) for item in telescope.itemDict: rotTel = telescope.withLocallyRotatedOptic(item, rot) rotTel = rotTel.withLocallyRotatedOptic(item, rotInv) rotTel2 = telescope.withLocallyRotatedOptic(item, np.eye(3)) theta_x = np.random.uniform(-0.005, 0.005) theta_y = np.random.uniform(-0.005, 0.005) np.testing.assert_allclose( batoid.psf.zernike(telescope, theta_x, theta_y, wavelength), batoid.psf.zernike(rotTel, theta_x, theta_y, wavelength), atol=1e-5 ) np.testing.assert_allclose( batoid.psf.zernike(telescope, theta_x, theta_y, wavelength), batoid.psf.zernike(rotTel2, theta_x, theta_y, wavelength), atol=1e-5 ) # Test with non-fully-qualified name rotTel = telescope.withLocallyRotatedOptic('G1', rot) rotTel = rotTel.withLocallyRotatedOptic('G1', rotInv) rotTel2 = rotTel.withLocallyRotatedOptic('G1', np.eye(3)) np.testing.assert_allclose( batoid.psf.zernike(telescope, theta_x, theta_y, wavelength), batoid.psf.zernike(rotTel, theta_x, theta_y, wavelength), atol=1e-5 ) np.testing.assert_allclose( batoid.psf.zernike(telescope, theta_x, theta_y, wavelength), batoid.psf.zernike(rotTel2, theta_x, theta_y, wavelength), atol=1e-5 )
def randomCoordSys(): import random return batoid.CoordSys( randomVec3(), (batoid.RotX(random.uniform(0, 1)) .dot(batoid.RotY(random.uniform(0, 1))) .dot(batoid.RotZ(random.uniform(0, 1)))) )
def test_rotation(): try: import galsim except ImportError: print("optic rotation test requires GalSim") return np.random.seed(57) fn = os.path.join(batoid.datadir, "HSC", "HSC.yaml") config = yaml.load(open(fn)) telescope = batoid.parse.parse_optic(config['opticalSystem']) rot = batoid.RotX(np.random.uniform(low=0.0, high=2 * np.pi)) rot = rot.dot(batoid.RotY(np.random.uniform(low=0.0, high=2 * np.pi))) rot = rot.dot(batoid.RotZ(np.random.uniform(low=0.0, high=2 * np.pi))) rotInv = np.linalg.inv(rot) # It's hard to test the two telescopes for equality due to rounding errors, so we test by # comparing zernikes rotTel = telescope.withLocalRotation(rot).withLocalRotation(rotInv) theta_x = np.random.uniform(-0.005, 0.005) theta_y = np.random.uniform(-0.005, 0.005) wavelength = 750e-9 np.testing.assert_allclose(batoid.psf.zernike(telescope, theta_x, theta_y, wavelength), batoid.psf.zernike(rotTel, theta_x, theta_y, wavelength), atol=1e-5) for item in telescope.itemDict: rotTel = telescope.withLocallyRotatedOptic(item, rot) rotTel = rotTel.withLocallyRotatedOptic(item, rotInv) rotTel2 = telescope.withLocallyRotatedOptic(item, np.eye(3)) theta_x = np.random.uniform(-0.005, 0.005) theta_y = np.random.uniform(-0.005, 0.005) np.testing.assert_allclose(batoid.psf.zernike(telescope, theta_x, theta_y, wavelength), batoid.psf.zernike(rotTel, theta_x, theta_y, wavelength), atol=1e-5) np.testing.assert_allclose(batoid.psf.zernike(telescope, theta_x, theta_y, wavelength), batoid.psf.zernike(rotTel2, theta_x, theta_y, wavelength), atol=1e-5)
def randomCoordSys(rng): return batoid.CoordSys( rng.uniform(size=3), (batoid.RotX(rng.uniform()).dot( batoid.RotY(rng.uniform())).dot(batoid.RotZ(rng.uniform()))))
def test_rotation(): rng = np.random.default_rng(57) telescope = batoid.Optic.fromYaml("HSC.yaml") rot = batoid.RotX(rng.uniform(low=0.0, high=2 * np.pi)) rot = rot.dot(batoid.RotY(rng.uniform(low=0.0, high=2 * np.pi))) rot = rot.dot(batoid.RotZ(rng.uniform(low=0.0, high=2 * np.pi))) rotInv = np.linalg.inv(rot) # It's hard to test the two telescopes for equality due to rounding errors, # so we test by comparing zernikes rotTel = telescope.withLocalRotation(rot).withLocalRotation(rotInv) theta_x = rng.uniform(-0.005, 0.005) theta_y = rng.uniform(-0.005, 0.005) wavelength = 750e-9 for k in telescope.itemDict.keys(): np.testing.assert_allclose(telescope[k].coordSys.origin, rotTel[k].coordSys.origin, rtol=0, atol=1e-14) np.testing.assert_allclose(telescope[k].coordSys.rot, rotTel[k].coordSys.rot, rtol=0, atol=1e-14) np.testing.assert_allclose(batoid.zernikeGQ(telescope, theta_x, theta_y, wavelength), batoid.zernikeGQ(rotTel, theta_x, theta_y, wavelength), atol=1e-7) for item in telescope.itemDict: rotTel = telescope.withLocallyRotatedOptic(item, rot) rotTel = rotTel.withLocallyRotatedOptic(item, rotInv) rotTel2 = telescope.withLocallyRotatedOptic(item, np.eye(3)) theta_x = rng.uniform(-0.005, 0.005) theta_y = rng.uniform(-0.005, 0.005) np.testing.assert_allclose(batoid.zernikeGQ(telescope, theta_x, theta_y, wavelength), batoid.zernikeGQ(rotTel, theta_x, theta_y, wavelength), atol=1e-7) np.testing.assert_allclose(batoid.zernikeGQ(telescope, theta_x, theta_y, wavelength), batoid.zernikeGQ(rotTel2, theta_x, theta_y, wavelength), atol=1e-7) # Test with non-fully-qualified name rotTel = telescope.withLocallyRotatedOptic('G1', rot) rotTel = rotTel.withLocallyRotatedOptic('G1', rotInv) rotTel2 = rotTel.withLocallyRotatedOptic('G1', np.eye(3)) np.testing.assert_allclose(batoid.zernikeGQ(telescope, theta_x, theta_y, wavelength), batoid.zernikeGQ(rotTel, theta_x, theta_y, wavelength), atol=1e-7) np.testing.assert_allclose(batoid.zernikeGQ(telescope, theta_x, theta_y, wavelength), batoid.zernikeGQ(rotTel2, theta_x, theta_y, wavelength), atol=1e-7)
def test_params(): rng = np.random.default_rng(5) for _ in range(30): origin = rng.uniform(size=3) rot = (batoid.RotX(rng.uniform()) @ batoid.RotY(rng.uniform()) @ batoid.RotZ(rng.uniform())) coordSys = batoid.CoordSys(origin, rot) np.testing.assert_equal(coordSys.origin, origin) np.testing.assert_equal(coordSys.rot, rot) np.testing.assert_equal(coordSys.xhat, rot[:, 0]) np.testing.assert_equal(coordSys.yhat, rot[:, 1]) np.testing.assert_equal(coordSys.zhat, rot[:, 2]) coordSys = batoid.CoordSys(origin=origin) np.testing.assert_equal(coordSys.origin, origin) np.testing.assert_equal(coordSys.rot, np.eye(3)) np.testing.assert_equal(coordSys.xhat, [1, 0, 0]) np.testing.assert_equal(coordSys.yhat, [0, 1, 0]) np.testing.assert_equal(coordSys.zhat, [0, 0, 1]) coordSys = batoid.CoordSys(rot=rot) np.testing.assert_equal(coordSys.origin, np.zeros(3)) np.testing.assert_equal(coordSys.rot, rot) np.testing.assert_equal(coordSys.xhat, rot[:, 0]) np.testing.assert_equal(coordSys.yhat, rot[:, 1]) np.testing.assert_equal(coordSys.zhat, rot[:, 2]) coordSys = batoid.CoordSys() np.testing.assert_equal(coordSys.origin, np.zeros(3)) np.testing.assert_equal(coordSys.rot, np.eye(3)) np.testing.assert_equal(coordSys.xhat, [1, 0, 0]) np.testing.assert_equal(coordSys.yhat, [0, 1, 0]) np.testing.assert_equal(coordSys.zhat, [0, 0, 1]) coordSys = batoid.CoordSys() coordSys = coordSys.rotateGlobal(rot).shiftGlobal(origin) np.testing.assert_equal(coordSys.origin, origin) np.testing.assert_equal(coordSys.rot, rot) np.testing.assert_equal(coordSys.xhat, rot[:, 0]) np.testing.assert_equal(coordSys.yhat, rot[:, 1]) np.testing.assert_equal(coordSys.zhat, rot[:, 2]) coordSys = batoid.CoordSys() coordSys = coordSys.rotateLocal(rot).shiftGlobal(origin) np.testing.assert_equal(coordSys.origin, origin) np.testing.assert_equal(coordSys.rot, rot) np.testing.assert_equal(coordSys.xhat, rot[:, 0]) np.testing.assert_equal(coordSys.yhat, rot[:, 1]) np.testing.assert_equal(coordSys.zhat, rot[:, 2]) coordSys = batoid.CoordSys() coordSys = coordSys.shiftLocal(origin).rotateLocal(rot) np.testing.assert_equal(coordSys.origin, origin) np.testing.assert_equal(coordSys.rot, rot) np.testing.assert_equal(coordSys.xhat, rot[:, 0]) np.testing.assert_equal(coordSys.yhat, rot[:, 1]) np.testing.assert_equal(coordSys.zhat, rot[:, 2]) coordSys = batoid.CoordSys() coordSys = coordSys.shiftGlobal(origin).rotateLocal(rot) np.testing.assert_equal(coordSys.origin, origin) np.testing.assert_equal(coordSys.rot, rot) np.testing.assert_equal(coordSys.xhat, rot[:, 0]) np.testing.assert_equal(coordSys.yhat, rot[:, 1]) np.testing.assert_equal(coordSys.zhat, rot[:, 2]) # Can't simply do a global rotation after a shift, since that will # change the origin too. Works if we manually specify the rotation # center though coordSys = batoid.CoordSys() coordSys1 = coordSys.shiftGlobal(origin) coordSys = coordSys1.rotateGlobal(rot, origin, coordSys) np.testing.assert_equal(coordSys.origin, origin) np.testing.assert_equal(coordSys.rot, rot) np.testing.assert_equal(coordSys.xhat, rot[:, 0]) np.testing.assert_equal(coordSys.yhat, rot[:, 1]) np.testing.assert_equal(coordSys.zhat, rot[:, 2])
def test_rotate(): rng = np.random.default_rng(57) for _ in range(10): r1 = batoid.RotX(rng.uniform()) r2 = batoid.RotY(rng.uniform()) r3 = batoid.RotZ(rng.uniform()) r4 = batoid.RotX(rng.uniform()) r5 = batoid.RotY(rng.uniform()) r6 = batoid.RotZ(rng.uniform()) rot = r6 @ r5 @ r4 @ r3 @ r2 @ r1 coordSys = batoid.CoordSys().rotateGlobal(rot) np.testing.assert_equal(coordSys.xhat, rot[:, 0]) np.testing.assert_equal(coordSys.yhat, rot[:, 1]) np.testing.assert_equal(coordSys.zhat, rot[:, 2]) np.testing.assert_equal(coordSys.origin, 0) rot1 = r3 @ r2 @ r1 rot2 = r6 @ r5 @ r4 coordSys = batoid.CoordSys().rotateGlobal(rot1).rotateGlobal(rot2) np.testing.assert_allclose(coordSys.xhat, rot[:, 0]) np.testing.assert_allclose(coordSys.yhat, rot[:, 1]) np.testing.assert_allclose(coordSys.zhat, rot[:, 2]) np.testing.assert_equal(coordSys.origin, 0) coordSys = batoid.CoordSys(rot=rot1) coordSys2 = coordSys.rotateLocal(batoid.RotX(np.pi / 2)) # Since second rotation was about the local X, both should have same # xhat np.testing.assert_allclose(coordSys.xhat, coordSys2.xhat) # 90 degree positive rotation then means y -> -z, z -> y np.testing.assert_allclose(coordSys.yhat, -coordSys2.zhat) np.testing.assert_allclose(coordSys.zhat, coordSys2.yhat) # Try a loop coordSys = batoid.CoordSys(rot=rot) coordSys = coordSys.rotateGlobal(batoid.RotX(0.1)) coordSys = coordSys.rotateGlobal(batoid.RotZ(np.pi)) coordSys = coordSys.rotateGlobal(batoid.RotX(0.1)) coordSys = coordSys.rotateGlobal(batoid.RotZ(np.pi)) # Should be back where we started... np.testing.assert_allclose(coordSys.rot, rot) # Miscentered origins origin = rng.uniform(size=3) coordSys = batoid.CoordSys(origin=origin, rot=rot) np.testing.assert_equal(origin, coordSys.origin) coordSys2 = coordSys.rotateGlobal(rot) np.testing.assert_equal(rot @ origin, coordSys2.origin) coordSys3 = coordSys.rotateLocal(rot) np.testing.assert_equal(origin, coordSys3.origin) # Miscentered rotation axes # Global with center specified is same as local coordSys = batoid.CoordSys(origin=origin, rot=rot) coordSys2 = coordSys.rotateLocal(rot) coordSys3 = coordSys.rotateGlobal(rot, origin, batoid.CoordSys()) np.testing.assert_allclose(coordSys2.origin, origin) np.testing.assert_allclose(coordSys2.origin, coordSys3.origin) np.testing.assert_allclose(coordSys2.rot, coordSys3.rot)