Ejemplo n.º 1
0
def test_intersect():
    import random
    random.seed(577)
    for i in range(100):
        R = random.gauss(25.0, 0.2)
        conic = random.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        for j in range(100):
            x = random.gauss(0.0, 1.0)
            y = random.gauss(0.0, 1.0)

            # If we shoot rays straight up, then it's easy to predict the
            # intersection points.
            r0 = batoid.Ray((x, y, -10), (0, 0, 1), 0)
            r = quad.intersect(r0)
            np.testing.assert_allclose(r.r[0], x)
            np.testing.assert_allclose(r.r[1], y)
            np.testing.assert_allclose(r.r[2],
                                       quad.sag(x, y),
                                       rtol=0,
                                       atol=1e-9)

    # Check normal for R=0 paraboloid (a plane)
    quad = batoid.Quadric(0.0, 0.0)
    np.testing.assert_array_equal(quad.normal(0.1, 0.1), [0, 0, 1])
Ejemplo n.º 2
0
def test_ne():
    objs = [
        batoid.Quadric(10.0, 1.0),
        batoid.Quadric(11.0, 1.0),
        batoid.Quadric(10.0, 1.1),
        batoid.Sphere(10.0)
    ]
    all_obj_diff(objs)
Ejemplo n.º 3
0
def test_properties():
    np.random.seed(5)
    for _ in range(100):
        s1 = batoid.Sphere(np.random.uniform(1, 3))
        s2 = batoid.Paraboloid(np.random.uniform(1, 3))
        sum = batoid.Sum([s1, s2])
        do_pickle(sum)
        # check commutativity
        assert sum == batoid.Sum([s2, s1])

        # order of sum.surfaces is not guaranteed
        assert s1 in sum.surfaces
        assert s2 in sum.surfaces

        s3 = batoid.Quadric(np.random.uniform(3, 5), np.random.uniform(-0.1, 0.1))
        sum2 = batoid.Sum([s1, s2, s3])
        do_pickle(sum2)
        # check commutativity
        assert sum2 == batoid.Sum([s2, s3, s1])
        assert sum2 == batoid.Sum([s3, s1, s2])
        assert sum2 == batoid.Sum([s3, s2, s1])
        assert sum2 == batoid.Sum([s2, s1, s3])
        assert sum2 == batoid.Sum([s1, s3, s2])

        assert s1 in sum2.surfaces
        assert s2 in sum2.surfaces
        assert s3 in sum2.surfaces

        do_pickle(sum)
Ejemplo n.º 4
0
def test_sag():
    np.random.seed(57)
    for _ in range(100):
        s1 = batoid.Sphere(np.random.uniform(1, 3))
        s2 = batoid.Paraboloid(np.random.uniform(1, 3))
        sum = batoid.Sum([s1, s2])

        x = np.random.normal(size=5000)
        y = np.random.normal(size=5000)

        np.testing.assert_allclose(
            sum.sag(x, y),
            s1.sag(x, y) + s2.sag(x, y),
            rtol=1e-12,
            atol=1e-12
        )

        s3 = batoid.Quadric(np.random.uniform(3, 5), np.random.uniform(-0.1, 0.1))
        sum2 = batoid.Sum([s1, s2, s3])

        np.testing.assert_allclose(
            sum2.sag(x, y),
            s1.sag(x, y) + s2.sag(x, y) + s3.sag(x, y),
            rtol=1e-12,
            atol=1e-12
        )
Ejemplo n.º 5
0
def test_refract():
    rng = np.random.default_rng(577215)
    size = 10_000
    for i in range(100):
        R = 1. / rng.normal(0.0, 0.3)
        conic = rng.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        m0 = batoid.ConstMedium(rng.normal(1.2, 0.01))
        m1 = batoid.ConstMedium(rng.normal(1.3, 0.01))
        lim = min(0.7 * abs(R) / np.sqrt(1 + conic) if conic > -1 else 10, 10)
        x = rng.uniform(-lim, lim, size=size)
        y = rng.uniform(-lim, lim, size=size)
        z = np.full_like(x, -100.0)
        vx = rng.uniform(-1e-5, 1e-5, size=size)
        vy = rng.uniform(-1e-5, 1e-5, size=size)
        vz = np.sqrt(1 - vx * vx - vy * vy) / m0.n
        rv = batoid.RayVector(x, y, z, vx, vy, vz)
        rvr = batoid.refract(quad, rv.copy(), m0, m1)
        rvr2 = quad.refract(rv.copy(), m0, m1)
        rays_allclose(rvr, rvr2)
        # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed")
        normal = quad.normal(rvr.x, rvr.y)

        # Test Snell's law
        s0 = np.sum(np.cross(normal, rv.v * m0.n)[~rvr.failed], axis=-1)
        s1 = np.sum(np.cross(normal, rvr.v * m1.n)[~rvr.failed], axis=-1)
        np.testing.assert_allclose(m0.n * s0, m1.n * s1, rtol=0, atol=1e-9)

        # Test that rv.v, rvr.v and normal are all in the same plane
        np.testing.assert_allclose(np.einsum("ad,ad->a",
                                             np.cross(normal, rv.v),
                                             rv.v)[~rvr.failed],
                                   0.0,
                                   rtol=0,
                                   atol=1e-12)
Ejemplo n.º 6
0
def test_reflect():
    rng = np.random.default_rng(57721)
    size = 10_000
    for i in range(100):
        R = 1. / rng.normal(0.0, 0.3)
        conic = rng.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        lim = min(0.7 * abs(R) / np.sqrt(1 + conic) if conic > -1 else 10, 10)
        x = rng.uniform(-lim, lim, size=size)
        y = rng.uniform(-lim, lim, size=size)
        z = np.full_like(x, -100.0)
        vx = rng.uniform(-1e-5, 1e-5, size=size)
        vy = rng.uniform(-1e-5, 1e-5, size=size)
        vz = np.full_like(x, 1)
        rv = batoid.RayVector(x, y, z, vx, vy, vz)
        rvr = batoid.reflect(quad, rv.copy())
        rvr2 = quad.reflect(rv.copy())
        rays_allclose(rvr, rvr2)
        # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed")
        normal = quad.normal(rvr.x, rvr.y)

        # Test law of reflection
        a0 = np.einsum("ad,ad->a", normal, rv.v)[~rvr.failed]
        a1 = np.einsum("ad,ad->a", normal, -rvr.v)[~rvr.failed]
        np.testing.assert_allclose(a0, a1, rtol=0, atol=1e-12)

        # Test that rv.v, rvr.v and normal are all in the same plane
        np.testing.assert_allclose(np.einsum("ad,ad->a",
                                             np.cross(normal, rv.v),
                                             rv.v)[~rvr.failed],
                                   0.0,
                                   rtol=0,
                                   atol=1e-12)
Ejemplo n.º 7
0
def test_intersect():
    rng = np.random.default_rng(5772)
    size = 10_000
    for i in range(100):
        R = 1./rng.normal(0.0, 0.3)
        conic = rng.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        quadCoordSys = batoid.CoordSys(origin=[0, 0, -1])
        lim = min(0.7*abs(R)/np.sqrt(1+conic) if conic > -1 else 10, 10)
        x = rng.uniform(-lim, lim, size=size)
        y = rng.uniform(-lim, lim, size=size)
        z = np.full_like(x, -100.0)
        # If we shoot rays straight up, then it's easy to predict the intersection
        vx = np.zeros_like(x)
        vy = np.zeros_like(x)
        vz = np.ones_like(x)
        rv = batoid.RayVector(x, y, z, vx, vy, vz)
        np.testing.assert_allclose(rv.z, -100.0)
        rv2 = batoid.intersect(quad, rv.copy(), quadCoordSys)
        assert rv2.coordSys == quadCoordSys

        rv2 = rv2.toCoordSys(batoid.CoordSys())
        np.testing.assert_allclose(rv2.x, x)
        np.testing.assert_allclose(rv2.y, y)
        np.testing.assert_allclose(rv2.z, quad.sag(x, y)-1, rtol=0, atol=1e-9)

        # Check default intersect coordTransform
        rv2 = rv.copy().toCoordSys(quadCoordSys)
        batoid.intersect(quad, rv2)
        assert rv2.coordSys == quadCoordSys
        rv2 = rv2.toCoordSys(batoid.CoordSys())
        np.testing.assert_allclose(rv2.x, x)
        np.testing.assert_allclose(rv2.y, y)
        np.testing.assert_allclose(rv2.z, quad.sag(x, y)-1, rtol=0, atol=1e-9)
Ejemplo n.º 8
0
def test_normal():
    rng = np.random.default_rng(577)
    for i in range(100):
        R = 1./rng.normal(0.0, 0.3)
        conic = rng.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        for j in range(10):
            lim = 0.7*abs(R)/np.sqrt(1+conic) if conic > -1 else 1
            x = rng.uniform(-lim, lim)
            y = rng.uniform(-lim, lim)
            result = quad.normal(x, y)
            np.testing.assert_allclose(
                result,
                quadric_normal(R, conic)(x, y)[0,0]
            )
        # Check 0,0
        np.testing.assert_equal(quad.normal(0, 0), np.array([0, 0, 1]))
        # Check vectorization
        x = rng.uniform(-lim, lim, size=(10, 10))
        y = rng.uniform(-lim, lim, size=(10, 10))
        np.testing.assert_allclose(
            quad.normal(x, y),
            quadric_normal(R, conic)(x, y)
        )
        # Make sure non-unit stride arrays also work
        np.testing.assert_allclose(
            quad.normal(x[::5,::2], y[::5,::2]),
            quadric_normal(R, conic)(x, y)[::5, ::2]
        )
Ejemplo n.º 9
0
def test_fail():
    quad = batoid.Quadric(1.0, 1.0)
    ray = batoid.Ray([0, 0, -1], [0, 0, -1])
    ray = quad.intersect(ray)
    assert ray.failed

    ray = batoid.Ray([0, 0, -1], [0, 0, -1])
    quad.intersectInPlace(ray)
    assert ray.failed
Ejemplo n.º 10
0
def test_properties():
    rng = np.random.default_rng(5)
    for i in range(100):
        R = rng.normal(0.0, 0.3)  # negative allowed
        conic = rng.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        assert quad.R == R
        assert quad.conic == conic
        do_pickle(quad)
Ejemplo n.º 11
0
def test_fail():
    quad = batoid.Quadric(1.0, 0.0)
    rv = batoid.RayVector(0, 10, 0, 0, 0, -1)  # Too far to side
    rv2 = batoid.intersect(quad, rv.copy())
    np.testing.assert_equal(rv2.failed, np.array([True]))
    # This one passes
    rv = batoid.RayVector(0, 0, -1, 0, 0, -1)
    rv2 = batoid.intersect(quad, rv.copy())
    np.testing.assert_equal(rv2.failed, np.array([False]))
Ejemplo n.º 12
0
def test_ne():
    objs = [
        batoid.Zernike([0,0,0,0,1]),
        batoid.Zernike([0,0,0,1]),
        batoid.Zernike([0,0,0,0,1], R_outer=1.1),
        batoid.Zernike([0,0,0,0,1], R_inner=0.8),
        batoid.Zernike([0,0,0,0,1], R_outer=1.1, R_inner=0.8),
        batoid.Quadric(10.0, 1.0)
    ]
    all_obj_diff(objs)
Ejemplo n.º 13
0
def test_properties():
    import random
    random.seed(5)
    for i in range(100):
        R = random.gauss(0.7, 0.8)
        conic = random.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        assert quad.R == R
        assert quad.conic == conic
        do_pickle(quad)
Ejemplo n.º 14
0
def test_ne():
    objs = [
        batoid.Asphere(10.0, 1.0, []),
        batoid.Asphere(10.0, 1.0, [0]),
        batoid.Asphere(10.0, 1.0, [0,1]),
        batoid.Asphere(10.0, 1.0, [1,0]),
        batoid.Asphere(10.0, 1.1, []),
        batoid.Asphere(10.1, 1.0, []),
        batoid.Quadric(10.0, 1.0)
    ]
    all_obj_diff(objs)
Ejemplo n.º 15
0
def test_quad_plus_poly():
    import random
    random.seed(5772)
    for i in range(100):
        R = random.gauss(25.0, 0.2)
        conic = random.uniform(-2.0, 1.0)
        ncoefs = random.randint(0, 4)
        coefs = [random.gauss(0, 1e-10) for i in range(ncoefs)]
        asphere = batoid.Asphere(R, conic, coefs)
        quad = batoid.Quadric(R, conic)
        poly = py_poly(coefs)
        for j in range(100):
            x = random.gauss(0.0, 1.0)
            y = random.gauss(0.0, 1.0)
            np.testing.assert_allclose(asphere.sag(x, y), quad.sag(x, y)+poly(x, y))
Ejemplo n.º 16
0
def test_paraboloid():
    rng = np.random.default_rng(57721566)
    size = 1000
    for i in range(100):
        R = 1/rng.normal(0.0, 0.3)
        conic = -1.0
        quad = batoid.Quadric(R, conic)
        para = batoid.Paraboloid(R)
        x = rng.uniform(-0.7*R, 0.7*R, size=size)
        y = rng.uniform(-0.7*R, 0.7*R, size=size)
        np.testing.assert_allclose(
            quad.sag(x,y), para.sag(x, y),
            rtol=0, atol=1e-11
        )
        np.testing.assert_allclose(
            quad.normal(x,y), para.normal(x, y),
            rtol=0, atol=1e-11
        )
Ejemplo n.º 17
0
def test_properties():
    rng = np.random.default_rng(5)
    for i in range(100):
        s1 = batoid.Sphere(rng.uniform(1, 3))
        s2 = batoid.Paraboloid(rng.uniform(1, 3))
        sum = batoid.Sum([s1, s2])
        do_pickle(sum)

        assert s1 is sum.surfaces[0]
        assert s2 is sum.surfaces[1]

        s3 = batoid.Quadric(rng.uniform(3, 5), rng.uniform(-0.1, 0.1))
        sum2 = batoid.Sum([s1, s2, s3])
        do_pickle(sum2)

        assert s1 is sum2.surfaces[0]
        assert s2 is sum2.surfaces[1]
        assert s3 is sum2.surfaces[2]
Ejemplo n.º 18
0
def test_sphere():
    rng = np.random.default_rng(5772156)
    size = 1000
    for i in range(100):
        R = 1/rng.normal(0.0, 0.3)
        conic = 0.0
        quad = batoid.Quadric(R, conic)
        sphere = batoid.Sphere(R)
        x = rng.uniform(-0.7*R, 0.7*R, size=size)
        y = rng.uniform(-0.7*R, 0.7*R, size=size)
        np.testing.assert_allclose(
            quad.sag(x,y), sphere.sag(x, y),
            rtol=0, atol=1e-11
        )
        np.testing.assert_allclose(
            quad.normal(x,y), sphere.normal(x, y),
            rtol=0, atol=1e-11
        )
Ejemplo n.º 19
0
def test_properties():
    np.random.seed(5)
    for _ in range(100):
        s1 = batoid.Sphere(np.random.uniform(1, 3))
        s2 = batoid.Paraboloid(np.random.uniform(1, 3))
        sum = batoid.Sum([s1, s2])
        do_pickle(sum)

        assert s1 is sum.surfaces[0]
        assert s2 is sum.surfaces[1]

        s3 = batoid.Quadric(np.random.uniform(3, 5), np.random.uniform(-0.1, 0.1))
        sum2 = batoid.Sum([s1, s2, s3])
        do_pickle(sum2)

        assert s1 is sum2.surfaces[0]
        assert s2 is sum2.surfaces[1]
        assert s3 is sum2.surfaces[2]

        do_pickle(sum)
Ejemplo n.º 20
0
def test_sag():
    rng = np.random.default_rng(57)
    for i in range(100):
        R = 1. / rng.normal(0.0, 0.3)
        conic = rng.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        for j in range(100):
            lim = 0.7 * abs(R) / np.sqrt(1 + conic) if conic > -1 else 1
            x = rng.uniform(-lim, lim)
            y = rng.uniform(-lim, lim)
            result = quad.sag(x, y)
            np.testing.assert_allclose(result, quadric_sag(R, conic)(x, y))
            # Check that it returned a scalar float and not an array
            assert isinstance(result, float)
        # Check vectorization
        x = rng.uniform(-lim, lim, size=(10, 10))
        y = rng.uniform(-lim, lim, size=(10, 10))
        np.testing.assert_allclose(quad.sag(x, y), quadric_sag(R, conic)(x, y))
        # Make sure non-unit stride arrays also work
        np.testing.assert_allclose(quad.sag(x[::5, ::2], y[::5, ::2]),
                                   quadric_sag(R, conic)(x, y)[::5, ::2])
Ejemplo n.º 21
0
def test_sag():
    import random
    random.seed(57)
    for i in range(100):
        R = random.gauss(25.0, 0.2)
        conic = random.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        for j in range(100):
            x = random.gauss(0.0, 1.0)
            y = random.gauss(0.0, 1.0)
            result = quad.sag(x, y)
            np.testing.assert_allclose(result, quadric(R, conic)(x, y))
            # Check that it returned a scalar float and not an array
            assert isinstance(result, float)
        # Check vectorization
        x = np.random.normal(0.0, 1.0, size=(10, 10))
        y = np.random.normal(0.0, 1.0, size=(10, 10))
        np.testing.assert_allclose(quad.sag(x, y), quadric(R, conic)(x, y))
        # Make sure non-unit stride arrays also work
        np.testing.assert_allclose(quad.sag(x[::5, ::2], y[::5, ::2]),
                                   quadric(R, conic)(x, y)[::5, ::2])
Ejemplo n.º 22
0
def test_intersect_vectorized():
    import random
    random.seed(5772)
    r0s = [
        batoid.Ray([
            random.gauss(0.0, 0.1),
            random.gauss(0.0, 0.1),
            random.gauss(10.0, 0.1)
        ], [
            random.gauss(0.0, 0.1),
            random.gauss(0.0, 0.1),
            random.gauss(-1.0, 0.1)
        ], random.gauss(0.0, 0.1)) for i in range(1000)
    ]
    r0s = batoid.RayVector(r0s)

    for i in range(100):
        R = random.gauss(25.0, 0.2)
        conic = random.uniform(-2.0, 1.0)
        quad = batoid.Quadric(R, conic)
        r1s = quad.intersect(r0s)
        r2s = batoid.RayVector([quad.intersect(r0) for r0 in r0s])
        assert r1s == r2s
Ejemplo n.º 23
0
def test_normal():
    rng = np.random.default_rng(577)
    for _ in range(100):
        s1 = batoid.Sphere(rng.uniform(1, 3))
        s2 = batoid.Paraboloid(rng.uniform(1, 3))
        sum = batoid.Sum([s1, s2])

        x = rng.normal(size=5000)
        y = rng.normal(size=5000)

        n1 = s1.normal(x, y)
        n2 = s2.normal(x, y)
        nx = n1[:, 0] / n1[:, 2] + n2[:, 0] / n2[:, 2]
        ny = n1[:, 1] / n1[:, 2] + n2[:, 1] / n2[:, 2]
        nz = 1. / np.sqrt(nx * nx + ny * ny + 1)
        nx *= nz
        ny *= nz
        normal = np.array([nx, ny, nz]).T
        np.testing.assert_allclose(sum.normal(x, y),
                                   normal,
                                   rtol=0,
                                   atol=1e-12)

        s3 = batoid.Quadric(rng.uniform(3, 5), rng.uniform(-0.1, 0.1))
        sum2 = batoid.Sum([s1, s2, s3])
        n3 = s3.normal(x, y)
        nx = n1[:, 0] / n1[:, 2] + n2[:, 0] / n2[:, 2] + n3[:, 0] / n3[:, 2]
        ny = n1[:, 1] / n1[:, 2] + n2[:, 1] / n2[:, 2] + n3[:, 1] / n3[:, 2]
        nz = 1. / np.sqrt(nx * nx + ny * ny + 1)
        nx *= nz
        ny *= nz
        normal = np.array([nx, ny, nz]).T

        np.testing.assert_allclose(sum2.normal(x, y),
                                   normal,
                                   rtol=0,
                                   atol=1e-12)
Ejemplo n.º 24
0
def test_zeroscreen():
    """Add a zero phase OPDScreen in front of LSST entrance pupil.  Should have
    _no_ effect.
    """
    lsst = batoid.Optic.fromYaml("LSST_r.yaml")

    screens = [
        batoid.optic.OPDScreen(
            batoid.Plane(),
            batoid.Plane(),
            name='PS',
            coordSys=lsst.stopSurface.coordSys
        ),
        batoid.optic.OPDScreen(
            batoid.Paraboloid(100.0),
            batoid.Plane(),
            name='PS',
            coordSys=lsst.stopSurface.coordSys
        ),
        batoid.optic.OPDScreen(
            batoid.Quadric(11.0, -0.5),
            batoid.Plane(),
            name='PS',
            coordSys=lsst.stopSurface.coordSys
        ),
        batoid.optic.OPDScreen(
            batoid.Zernike([0, 0, 0, 0, 300e-9, 0, 0, 400e-9, -600e-9]),
            batoid.Zernike([0]*22),
            name='PS',
            coordSys=lsst.stopSurface.coordSys
        )
    ]

    for screen in screens:
        tel = batoid.CompoundOptic(
            (screen, *lsst.items),
            name='PS0',
            backDist=lsst.backDist,
            pupilSize=lsst.pupilSize,
            inMedium=lsst.inMedium,
            stopSurface=lsst.stopSurface,
            sphereRadius=lsst.sphereRadius,
            pupilObscuration=lsst.pupilObscuration
        )
        do_pickle(tel)

        rng = np.random.default_rng(57)
        thx = np.deg2rad(rng.uniform(-1, 1))
        thy = np.deg2rad(rng.uniform(-1, 1))
        rays = batoid.RayVector.asPolar(
            optic=tel, wavelength=620e-9,
            theta_x=thx, theta_y=thy,
            nrad=5, naz=60
        )

        tf1 = tel.traceFull(rays)
        tf2 = lsst.traceFull(rays)

        np.testing.assert_allclose(
            tf1['PS']['in'].v,
            tf1['PS']['out'].v,
            rtol=0, atol=1e-14
        )

        for key in tf2:
            rays_allclose(
                tf1[key]['out'],
                tf2[key]['out'],
                atol=1e-13
            )