Exemple #1
0
def test_sum_paraboloid():
    # para_sag = r^2/(2*R^2)
    # so two paraboloids yields r^2 * (1/(2*R1) + 1/(2*R2))
    # so (1/(2*R1) + 1/(2*R2)) = 1/(2*R)
    # implies
    # 0.5/(1/(2*R1) + 1/(2*R2)) = R
    np.random.seed(5772)
    for _ in range(100):
        R1 = np.random.uniform(1, 2)
        R2 = np.random.uniform(2, 3)
        Rsum = 0.5/(1/(2*R1) + 1/(2*R2))

        para1 = batoid.Paraboloid(R1)
        para2 = batoid.Paraboloid(R2)
        paraSum = batoid.Paraboloid(Rsum)
        paraSum2 = batoid.Sum([para1, para2])

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

        np.testing.assert_allclose(
            paraSum.sag(x, y),
            paraSum2.sag(x, y),
            rtol=1e-12,
            atol=1e-12
        )

        for _x, _y in zip(x[:100], y[:100]):
            np.testing.assert_allclose(
                paraSum.normal(_x, _y),
                paraSum2.normal(_x, _y),
                rtol=1e-12,
                atol=1e-12
            )
Exemple #2
0
def test_ne():
    objs = [
        batoid.Mirror(batoid.Plane()),
        batoid.Detector(batoid.Plane()),
        batoid.Baffle(batoid.Plane()),
        batoid.RefractiveInterface(batoid.Plane()),
        batoid.Mirror(batoid.Paraboloid(0.1)),
        batoid.Detector(batoid.Paraboloid(0.1)),
        batoid.Baffle(batoid.Paraboloid(0.1)),
        batoid.RefractiveInterface(batoid.Paraboloid(0.1)),
        batoid.Mirror(batoid.Plane(), obscuration=batoid.ObscCircle(0.1)),
        batoid.Mirror(batoid.Plane(), inMedium=batoid.ConstMedium(1.1)),
        batoid.Mirror(batoid.Plane(), outMedium=batoid.ConstMedium(1.1)),
        batoid.Mirror(batoid.Plane(), coordSys=batoid.CoordSys([0, 0, 1])),
        batoid.CompoundOptic(
            [batoid.Mirror(batoid.Plane()),
             batoid.Mirror(batoid.Plane())]),
        batoid.CompoundOptic(
            [batoid.Mirror(batoid.Plane()),
             batoid.Baffle(batoid.Plane())]),
        batoid.CompoundOptic([
            batoid.RefractiveInterface(batoid.Plane()),
            batoid.RefractiveInterface(batoid.Plane())
        ]),
        batoid.Lens([
            batoid.RefractiveInterface(batoid.Plane()),
            batoid.RefractiveInterface(batoid.Plane())
        ]),
    ]
    all_obj_diff(objs)
Exemple #3
0
def test_sum_paraboloid():
    # para_sag = r^2/(2*R^2)
    # so two paraboloids yields r^2 * (1/(2*R1) + 1/(2*R2))
    # so (1/(2*R1) + 1/(2*R2)) = 1/(2*R)
    # implies
    # 0.5/(1/(2*R1) + 1/(2*R2)) = R
    rng = np.random.default_rng(57721566)
    for _ in range(100):
        R1 = rng.uniform(1, 2)
        R2 = rng.uniform(2, 3)
        Rsum = 0.5 / (1 / (2 * R1) + 1 / (2 * R2))

        para1 = batoid.Paraboloid(R1)
        para2 = batoid.Paraboloid(R2)
        paraSum = batoid.Paraboloid(Rsum)
        paraSum2 = batoid.Sum([para1, para2])

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

        np.testing.assert_allclose(paraSum.sag(x, y),
                                   paraSum2.sag(x, y),
                                   rtol=0,
                                   atol=1e-12)

        np.testing.assert_allclose(
            paraSum.normal(x, y),
            paraSum2.normal(x, y),
            rtol=0,
            atol=1e-12,
        )
Exemple #4
0
def test_ne():
    objs = [
        batoid.Paraboloid(1.0),
        batoid.Paraboloid(2.0),
        batoid.Plane()
    ]
    all_obj_diff(objs)
Exemple #5
0
def test_properties():
    rng = np.random.default_rng(5)
    for i in range(100):
        R = rng.normal(0.0, 0.3)  # negative allowed
        para = batoid.Paraboloid(R)
        assert para.R == R
        do_pickle(para)
Exemple #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)  # negative allowed
        para = batoid.Paraboloid(R)
        x = rng.normal(0.0, 1.0, size=size)
        y = rng.normal(0.0, 1.0, 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(para, rv.copy())
        rvr2 = para.reflect(rv.copy())
        rays_allclose(rvr, rvr2)
        # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed")
        normal = para.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)
Exemple #7
0
def test_ne():
    objs = [
        batoid.Plane(),
        batoid.Plane(allowReverse=True),
        batoid.Paraboloid(2.0),
    ]
    all_obj_diff(objs)
def test_paraboloid_refraction_plane():
    import random
    random.seed(577)
    wavelength = 500e-9  # arbitrary
    para = batoid.Paraboloid(-20.0)
    m1 = batoid.ConstMedium(1.11)
    m2 = batoid.ConstMedium(1.32)
    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 = normalized(np.array([vx, vy, 1]))/m1.getN(wavelength)
        ray = batoid.Ray((x, y, -10), (v[0], v[1], v[2]), 0)
        rray = para.refract(ray.copy(), m1, m2)
        np.testing.assert_allclose(np.linalg.norm(rray.v), 1./m2.getN(wavelength), rtol=1e-14)

        # ray.v, surfaceNormal, and rray.v should all be in the same plane, and
        # hence (ray.v x surfaceNormal) . rray.v should have zero magnitude.
        # magnitude zero.
        normal = para.normal(rray.r[0], rray.r[1])
        np.testing.assert_allclose(
            np.dot(np.cross(ray.v, normal), rray.v),
            0.0, rtol=0, atol=1e-15)

        # Test Snell's law
        np.testing.assert_allclose(
            m1.getN(wavelength)*np.linalg.norm(np.cross(normalized(ray.v), normal)),
            m2.getN(wavelength)*np.linalg.norm(np.cross(normalized(rray.v), normal)),
            rtol=0, atol=1e-15)
Exemple #9
0
def test_reflect():
    rng = np.random.default_rng(57721)
    size = 10_000
    for _ in range(100):
        s1 = batoid.Sphere(1. / rng.normal(0., 0.2))
        s2 = batoid.Paraboloid(rng.uniform(1, 3))
        sum = batoid.Sum([s1, s2])
        x = rng.uniform(-1, 1, size=size)
        y = rng.uniform(-1, 1, size=size)
        z = np.full_like(x, -10.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(sum, rv.copy())
        rvr2 = sum.reflect(rv.copy())
        rays_allclose(rvr, rvr2)
        # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed")
        normal = sum.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)
Exemple #10
0
def test_refract():
    rng = np.random.default_rng(577215)
    size = 10_000
    for _ in range(100):
        s1 = batoid.Sphere(1. / rng.normal(0., 0.2))
        s2 = batoid.Paraboloid(rng.uniform(1, 3))
        sum = batoid.Sum([s1, s2])
        m0 = batoid.ConstMedium(rng.normal(1.2, 0.01))
        m1 = batoid.ConstMedium(rng.normal(1.3, 0.01))
        x = rng.uniform(-1, 1, size=size)
        y = rng.uniform(-1, 1, size=size)
        z = np.full_like(x, -10.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(sum, rv.copy(), m0, m1)
        rvr2 = sum.refract(rv.copy(), m0, m1)
        rays_allclose(rvr, rvr2)
        # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed")
        normal = sum.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)
def test_paraboloid_reflection_reversal():
    import random
    random.seed(5772)
    para = batoid.Paraboloid(-5.0)
    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, -10], v, 0)
        rray = para.reflect(ray.copy())

        # Invert the reflected ray, and see that it ends back at the starting
        # point

        # Keep going a bit before turning around though
        turn_around = rray.positionAtTime(rray.t+0.1)
        return_ray = batoid.Ray(turn_around, -rray.v, -(rray.t+0.1))
        riray = para.intersect(return_ray.copy())
        # First check that we intersected at the same point
        np.testing.assert_allclose(rray.r[0], riray.r[0], rtol=0, atol=1e-10)
        np.testing.assert_allclose(rray.r[1], riray.r[1], rtol=0, atol=1e-10)
        np.testing.assert_allclose(rray.r[2], riray.r[2], rtol=0, atol=1e-10)
        # Reflect and propagate back to t=0.
        cray = para.reflect(return_ray.copy())
        cray = cray.positionAtTime(0)
        np.testing.assert_allclose(cray[0], x, rtol=0, atol=1e-10)
        np.testing.assert_allclose(cray[1], y, rtol=0, atol=1e-10)
        np.testing.assert_allclose(cray[2], -10, rtol=0, atol=1e-10)
Exemple #12
0
def test_intersect():
    np.random.seed(57721)
    rv0 = batoid.RayVector([
        batoid.Ray(
            np.random.normal(scale=0.1),
            np.random.normal(scale=0.1),
            10,
            np.random.normal(scale=1e-4),
            np.random.normal(scale=1e-4),
            -1
        )
        for _ in range(100)
    ])
    for _ in range(100):
        s1 = batoid.Sphere(np.random.uniform(3, 10))
        s2 = batoid.Paraboloid(np.random.uniform(3, 10))
        sum = batoid.Sum([s1, s2])

        rv = batoid.RayVector(rv0)
        rv1 = sum.intersect(rv)
        rv2 = batoid.RayVector([sum.intersect(r) for r in rv])
        rv3 = batoid.RayVector(rv)
        sum.intersectInPlace(rv)

        for r in rv3:
            sum.intersectInPlace(r)

        assert rays_allclose(rv1, rv)
        assert rays_allclose(rv2, rv)
        assert rays_allclose(rv3, rv)
Exemple #13
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
        )
Exemple #14
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)
Exemple #15
0
def test_properties():
    import random
    random.seed(5)
    for i in range(100):
        R = random.gauss(0.7, 0.8)
        para = batoid.Paraboloid(R)
        assert para.R == R
        do_pickle(para)
Exemple #16
0
def test_fail():
    para = batoid.Paraboloid(1.0)
    ray = batoid.Ray([0,0,-1], [0,0,-1])
    ray = para.intersect(ray)
    assert ray.failed

    ray = batoid.Ray([0,0,-1], [0,0,-1])
    para.intersectInPlace(ray)
    assert ray.failed
Exemple #17
0
def test_fail():
    para = batoid.Paraboloid(1.0)
    rv = batoid.RayVector(0, 0, -10, 0, 0.99,
                          np.sqrt(1 - 0.99**2))  # Too shallow
    rv2 = batoid.intersect(para, 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(para, rv.copy())
    np.testing.assert_equal(rv2.failed, np.array([False]))
Exemple #18
0
def test_intersect():
    import random
    random.seed(577)
    for i in range(100):
        R = random.gauss(10.0, 0.1)
        para = batoid.Paraboloid(R)
        for j in range(10):
            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, -1000), (0, 0, 1), 0)
            r = para.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], para.sag(x, y), rtol=0, atol=1e-9)

    # Check normal for R=0 paraboloid (a plane)
    para = batoid.Paraboloid(0.0)
    np.testing.assert_array_equal(para.normal(0.1, 0.1), [0,0,1])
Exemple #19
0
def test_reflect_to_focus():
    rng = np.random.default_rng(5772156)
    size = 10_000
    for i in range(100):
        R = rng.normal(0, 3.0)
        para = batoid.Paraboloid(R)
        x = rng.normal(size=size)
        y = rng.normal(size=size)
        rv = batoid.RayVector(x, y, -1000, 0, 0, 1)
        para.reflect(rv)
        # Now, see if rays pass through paraboloid focus at (0, 0, R/2)
        # Solve 0 = x + vx (t - t0) for t, then propagate to that t
        t = rv.t[0] - rv.r[0, 0] / rv.v[0, 0]
        focus = rv.positionAtTime(t)
        np.testing.assert_allclose(focus[:, 0], 0, atol=1e-12)
        np.testing.assert_allclose(focus[:, 1], 0, atol=1e-12)
        np.testing.assert_allclose(focus[:, 2], R / 2, atol=1e-12)
Exemple #20
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]
Exemple #21
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
        )
def test_paraboloid_reflection_plane():
    import random
    random.seed(577)
    para = batoid.Paraboloid(-0.1)
    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)
        ray = batoid.Ray((x, y, -10), (vx, vy, 1), 0)
        rray = para.reflect(ray.copy())

        # ray.v, surfaceNormal, and rray.v should all be in the same plane, and
        # hence (ray.v x surfaceNormal) . rray.v should have zero magnitude.
        # magnitude zero.
        np.testing.assert_allclose(
            np.dot(np.cross(ray.v, para.normal(rray.r[0], rray.r[1])), rray.v),
            0.0, rtol=0, atol=1e-15)
Exemple #23
0
def test_sag():
    import random
    random.seed(57)
    for i in range(100):
        R = random.gauss(0.2, 0.3)
        para = batoid.Paraboloid(R)
        for j in range(10):
            x = random.gauss(0.0, 1.0)
            y = random.gauss(0.0, 1.0)
            result = para.sag(x, y)
            np.testing.assert_allclose(result, (x*x + y*y)/2/R)
            # 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(para.sag(x, y), (x*x + y*y)/2/R)
        # Make sure non-unit stride arrays also work
        np.testing.assert_allclose(para.sag(x[::5,::2], y[::5,::2]), ((x*x + y*y)/2/R)[::5,::2])
Exemple #24
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(0.05, 0.01)
        para = batoid.Paraboloid(R)
        r1s = para.intersect(r0s)
        r2s = batoid.RayVector([para.intersect(r0) for r0 in r0s])
        assert r1s == r2s
def test_paraboloid_reflection_to_focus():
    import random
    random.seed(57721)
    for i in range(100):
        R = random.gauss(0, 3.0)
        para = batoid.Paraboloid(R)
        for j in range(100):
            x = random.gauss(0, 1)
            y = random.gauss(0, 1)
            ray = batoid.Ray((x,y,-1000), (0,0,1), 0)
            rray = para.reflect(ray.copy())
            # Now see if rray goes through (0,0,R/2)
            # Solve the x equation: 0 = rray.r[0] + rray.v[0]*(t-t0) for t:
            # t = t0 - p0[0]/vx
            t = rray.t - rray.r[0]/rray.v[0]
            focus = rray.positionAtTime(t)
            np.testing.assert_allclose(focus[0], 0, atol=1e-12)
            np.testing.assert_allclose(focus[1], 0, atol=1e-12)
            np.testing.assert_allclose(focus[2], R/2.0, atol=1e-12)
Exemple #26
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)
def test_paraboloid_refraction_reversal():
    import random
    random.seed(5772)
    wavelength = 500e-9  # arbitrary
    para = batoid.Paraboloid(-20.0)
    m1 = batoid.ConstMedium(1.43)
    m2 = batoid.ConstMedium(1.34)
    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)
        ray = batoid.Ray([x, y, -10],
                         normalized(np.array([vx, vy, 1])) /
                         m1.getN(wavelength), 0)
        rray = para.refract(ray, m1, m2)
        np.testing.assert_allclose(np.linalg.norm(rray.v),
                                   1. / m2.getN(wavelength),
                                   rtol=1e-15)

        # Invert the refracted ray, and see that it ends back at the starting
        # point

        # Keep going a bit before turning around though
        turn_around = rray.positionAtTime(rray.t + 0.1)
        return_ray = batoid.Ray(turn_around, -rray.v, -(rray.t + 0.1))
        riray = para.intersect(return_ray)
        # First check that we intersected at the same point
        np.testing.assert_allclose(rray.r[0], riray.r[0], rtol=0, atol=1e-10)
        np.testing.assert_allclose(rray.r[1], riray.r[1], rtol=0, atol=1e-10)
        np.testing.assert_allclose(rray.r[2], riray.r[2], rtol=0, atol=1e-10)
        # Refract and propagate back to t=0.
        cray = para.refract(return_ray, m2, m1)
        np.testing.assert_allclose(np.linalg.norm(cray.v),
                                   1. / m1.getN(wavelength),
                                   rtol=1e-15)
        cpoint = cray.positionAtTime(0)
        np.testing.assert_allclose(cpoint[0], x, rtol=0, atol=1e-10)
        np.testing.assert_allclose(cpoint[1], y, rtol=0, atol=1e-10)
        np.testing.assert_allclose(cpoint[2], -10, rtol=0, atol=1e-10)
Exemple #28
0
def test_intersect():
    rng = np.random.default_rng(5772)
    size = 10_000
    for _ in range(100):
        s1 = batoid.Sphere(1. / rng.normal(0., 0.2))
        s2 = batoid.Paraboloid(rng.uniform(1, 3))
        sum = batoid.Sum([s1, s2])
        sumCoordSys = batoid.CoordSys(origin=[0, 0, -1])
        x = rng.uniform(-1, 1, size=size)
        y = rng.uniform(-1, 1, size=size)
        z = np.full_like(x, -10.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, -10.0)
        rv2 = batoid.intersect(sum, rv.copy(), sumCoordSys)
        assert rv2.coordSys == sumCoordSys

        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,
                                   sum.sag(x, y) - 1,
                                   rtol=0,
                                   atol=1e-12)

        # Check default intersect coordTransform
        rv2 = rv.copy().toCoordSys(sumCoordSys)
        batoid.intersect(sum, rv2)
        assert rv2.coordSys == sumCoordSys
        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,
                                   sum.sag(x, y) - 1,
                                   rtol=0,
                                   atol=1e-12)
Exemple #29
0
def test_normal():
    rng = np.random.default_rng(577)
    for i in range(100):
        R = rng.normal(0.0, 0.3)
        para = batoid.Paraboloid(R)
        for j in range(10):
            x = rng.normal()
            y = rng.normal()
            result = para.normal(x, y)
            normal = np.array([-x / R, -y / R, 1])
            normal /= np.sqrt(np.sum(np.square(normal)))
            np.testing.assert_allclose(result, normal)
        # Check 0,0
        np.testing.assert_equal(para.normal(0, 0), np.array([0, 0, 1]))
        # Check vectorization
        x = rng.normal(size=(10, 10))
        y = rng.normal(size=(10, 10))
        normal = np.dstack([-x / R, -y / R, np.ones_like(x)])
        normal /= np.sqrt(np.sum(np.square(normal), axis=-1))[..., None]
        np.testing.assert_allclose(para.normal(x, y), normal)
        # Make sure non-unit stride arrays also work
        np.testing.assert_allclose(para.normal(x[::5, ::2], y[::5, ::2]),
                                   normal[::5, ::2])
Exemple #30
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)