예제 #1
0
def test_properties():
    import random
    random.seed(57)
    for i in range(100):
        x = random.gauss(0.1, 2.3)
        y = random.gauss(2.1, 4.3)
        z = random.gauss(-0.13, 1.3)
        vx = random.gauss(3.1, 6.3)
        vy = random.gauss(5.1, 24.3)
        vz = random.gauss(-1.13, 31.3)
        t = random.gauss(0.1, 1.1)
        w = random.gauss(1000.0, 10.0)
        f = random.gauss(1000.0, 10.0)
        v = random.choice([True, False])

        ray1 = batoid.Ray(x, y, z, vx, vy, vz, t, w, f, v)
        ray2 = batoid.Ray([x, y, z], [vx, vy, vz], t, w, f, v)
        for ray in [ray1, ray2]:
            assert ray.x == x
            assert ray.y == y
            assert ray.z == z
            assert ray.vx == vx
            assert ray.vy == vy
            assert ray.vz == vz
            assert ray.t == t
            assert ray.wavelength == w
            assert ray.vignetted == v
        assert ray1 == ray2
예제 #2
0
def test_plane_refraction_reversal():
    import random
    random.seed(57)
    wavelength = 500e-9  # arbitrary
    plane = batoid.Plane()
    m1 = batoid.ConstMedium(1.5)
    m2 = batoid.ConstMedium(1.2)
    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 = plane.refract(ray.copy(), m1, m2)
        np.testing.assert_allclose(np.linalg.norm(rray.v), 1./m2.getN(wavelength), rtol=1e-14)

        # 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 = plane.intersect(return_ray.copy())
        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 = plane.refract(return_ray.copy(), m2, m1)
        np.testing.assert_allclose(np.linalg.norm(cray.v), 1./m1.getN(wavelength), rtol=1e-14)
        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)
예제 #3
0
def test_positionAtTime():
    import random
    random.seed(5)
    for i in range(100):
        x = random.gauss(0.1, 2.3)
        y = random.gauss(2.1, 4.3)
        z = random.gauss(-0.13, 1.3)
        vx = random.gauss(3.1, 6.3)
        vy = random.gauss(5.1, 24.3)
        vz = random.gauss(-1.13, 31.3)
        t0 = random.gauss(0.1, 1.1)
        t = random.gauss(5.5, 1.3)

        # Test both ways of constructing a Ray
        ray1 = batoid.Ray(x, y, z, vx, vy, vz, t0)
        ray2 = batoid.Ray([x, y, z], [vx, vy, vz], t0)
        ray3 = batoid.Ray((x, y, z), (vx, vy, vz), t0)
        ray4 = batoid.Ray(np.array([x, y, z]), np.array([vx, vy, vz]), t0)
        for ray in [ray1, ray2, ray3, ray4]:
            np.testing.assert_allclose(
                ray.positionAtTime(t)[0], x + vx * (t - t0))
            np.testing.assert_allclose(
                ray.positionAtTime(t)[1], y + vy * (t - t0))
            np.testing.assert_allclose(
                ray.positionAtTime(t)[2], z + vz * (t - t0))
        assert ray1 == ray2 == ray3 == ray4
        do_pickle(ray1)
예제 #4
0
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)
예제 #5
0
def test_intersect():
    np.random.seed(5772)
    def f(x, y):
        return x**2*y - y**2*x + 3*x - 2 + np.sin(y)*np.cos(x)**2

    xs = np.linspace(0, 1, 1000)
    ys = np.linspace(0, 1, 1000)

    zs = f(*np.meshgrid(xs, ys))
    bc = batoid.Bicubic(xs, ys, zs)

    for _ in range(1000):
        # If we shoot rays straight up, then it's easy to predict the
        # intersection points.
        x = np.random.uniform(0.1, 0.9)
        y = np.random.uniform(0.1, 0.9)

        r0 = batoid.Ray(x, y, -10, 0, 0, 1, 0)
        r = bc.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], bc.sag(x, y), rtol=0, atol=1e-9)

    # intersect should fail, but gracefully, outside of grid domain
    r0 = batoid.Ray(-1, -1, -10, 0, 0, 1, 0)
    assert bc.intersect(r0).failed
예제 #6
0
def test_fail():
    sum = batoid.Sum([batoid.Plane(), batoid.Sphere(1.0)])
    ray = batoid.Ray([0,0,sum.sag(0,0)-1], [0,0,-1])
    ray = sum.intersect(ray)
    assert ray.failed

    ray = batoid.Ray([0,0,sum.sag(0,0)-1], [0,0,-1])
    sum.intersectInPlace(ray)
    assert ray.failed
예제 #7
0
def test_fail():
    plane = batoid.Plane()
    ray = batoid.Ray([0, 0, -1], [0, 0, -1])
    ray = plane.intersect(ray)
    assert ray.failed

    ray = batoid.Ray([0, 0, -1], [0, 0, -1])
    plane.intersectInPlace(ray)
    assert ray.failed
예제 #8
0
def test_fail():
    zernike = batoid.Zernike([0,0,0,0,1])
    ray = batoid.Ray([0,0,zernike.sag(0,0)-1], [0,0,-1])
    ray = zernike.intersect(ray)
    assert ray.failed

    ray = batoid.Ray([0,0,zernike.sag(0,0)-1], [0,0,-1])
    zernike.intersect(ray)
    assert ray.failed
예제 #9
0
def test_fail():
    sphere = batoid.Sphere(1.0)
    ray = batoid.Ray([0,0,-1], [0,0,-1])
    ray = sphere.intersect(ray)
    assert ray.failed

    ray = batoid.Ray([0,0,-1], [0,0,-1])
    sphere.intersect(ray)
    assert ray.failed
예제 #10
0
def test_fail():
    asphere = batoid.Asphere(1.0, 1.0, [1.0, 1.0])
    ray = batoid.Ray([0,0,-1], [0,0,-1])
    ray = asphere.intersect(ray)
    assert ray.failed

    ray = batoid.Ray([0,0,-1], [0,0,-1])
    asphere.intersect(ray)
    assert ray.failed
예제 #11
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
예제 #12
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
예제 #13
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])
예제 #14
0
def test_plane_reflection_plane():
    import random
    random.seed(5)
    plane = batoid.Plane()
    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 = plane.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, plane.normal(rray.r[0], rray.r[1])), rray.v),
            0.0, rtol=0, atol=1e-15)

        # Actually, reflection off a plane is pretty straigtforward to test
        # directly.
        np.testing.assert_allclose(ray.v[0], rray.v[0])
        np.testing.assert_allclose(ray.v[1], rray.v[1])
        np.testing.assert_allclose(ray.v[2], -rray.v[2])
예제 #15
0
def test_intersect_vectorized():
    np.random.seed(57721)
    jmaxmax = 50
    r0s = [
        batoid.Ray([
            np.random.normal(0.0, 0.1),
            np.random.normal(0.0, 0.1),
            np.random.normal(10.0, 0.1)
        ], [
            np.random.normal(0.0, 0.1),
            np.random.normal(0.0, 0.1),
            np.random.normal(-1.0, 0.1)
        ], np.random.normal(0.0, 0.1)) for i in range(100)
    ]
    r0s = batoid.RayVector(r0s)

    for i in range(100):
        jmax = np.random.randint(1, jmaxmax)
        coef = np.random.normal(size=jmax + 1) * 1e-3
        R_outer = np.random.uniform(0.5, 5.0)
        R_inner = np.random.uniform(0.0, 0.8 * R_outer)
        zernike = batoid.Zernike(coef, R_outer=R_outer, R_inner=R_inner)

        r1s = zernike.intersect(r0s)
        r2s = batoid.RayVector([zernike.intersect(r0) for r0 in r0s])
        assert r1s == r2s
예제 #16
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)
예제 #17
0
def test_traceReverse():
    if __name__ == '__main__':
        nside = 128
    else:
        nside = 32

    telescope = batoid.Optic.fromYaml("HSC.yaml")

    init_rays = batoid.rayGrid(20, 12.0, 0.005, 0.005, -1.0, nside, 500e-9, 1.0, batoid.ConstMedium(1.0))
    forward_rays = telescope.trace(init_rays)

    # Now, turn the result rays around and trace backwards
    forward_rays = forward_rays.propagatedToTime(40.0)
    reverse_rays = batoid.RayVector(
        [batoid.Ray(r.r, -r.v, -r.t, r.wavelength) for r in forward_rays]
    )

    final_rays = telescope.traceReverse(reverse_rays)
    # propagate all the way to t=0
    final_rays = final_rays.propagatedToTime(0.0)
    final_rays.toCoordSysInPlace(batoid.globalCoordSys)

    w = np.where(np.logical_not(final_rays.vignetted))[0]
    for idx in w:
        np.testing.assert_allclose(init_rays[idx].x, final_rays[idx].x)
        np.testing.assert_allclose(init_rays[idx].y, final_rays[idx].y)
        np.testing.assert_allclose(init_rays[idx].z, final_rays[idx].z)
        np.testing.assert_allclose(init_rays[idx].vx, -final_rays[idx].vx)
        np.testing.assert_allclose(init_rays[idx].vy, -final_rays[idx].vy)
        np.testing.assert_allclose(init_rays[idx].vz, -final_rays[idx].vz)
        np.testing.assert_allclose(final_rays[idx].t, 0)
예제 #18
0
def test_asphere_refraction_plane():
    import random
    random.seed(57721)
    wavelength = 500e-9  # arbitrary
    asphere = batoid.Asphere(25.0, -0.97, [1e-3, 1e-5])
    m1 = batoid.ConstMedium(1.7)
    m2 = batoid.ConstMedium(1.2)
    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, -0.1), (v[0], v[1], v[2]), 0)
        rray = asphere.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 = asphere.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-14)

        # 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)
예제 #19
0
def test_fail():
    surface = batoid.Sphere(1.0)
    ray = batoid.Ray([0, 10, -1], [0, 0, 1])

    ray = surface.intersect(ray)
    assert ray.failed
    do_pickle(ray)
예제 #20
0
def test_plane_refraction_plane():
    import random
    random.seed(5)
    wavelength = 500e-9  # arbitrary
    plane = batoid.Plane()
    m1 = batoid.ConstMedium(1.1)
    m2 = batoid.ConstMedium(1.3)
    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/m1.getN(wavelength), 0)
        rray = plane.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.
        normal = plane.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)
예제 #21
0
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)
예제 #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)
        ncoefs = random.randint(0, 4)
        coefs = [random.gauss(0, 1e-10) for i in range(ncoefs)]
        asphere = batoid.Asphere(R, conic, coefs)

        r1s = asphere.intersect(r0s)
        r2s = batoid.RayVector([asphere.intersect(r0) for r0 in r0s])
        np.testing.assert_allclose(asphere.sag(r1s.x, r1s.y),
                                   r1s.z,
                                   rtol=0,
                                   atol=1e-12)
        assert r1s == r2s
예제 #23
0
def test_table_medium_refraction():
    import random
    random.seed(57721566)

    filename = os.path.join(batoid.datadir, "media", "silica_dispersion.txt")
    wave, n = np.genfromtxt(filename).T
    table = batoid.Table(wave, n, batoid.Table.Interpolant.linear)
    silica = batoid.TableMedium(table)
    air = batoid.ConstMedium(1.000277)

    asphere = batoid.Asphere(25.0, -0.97, [1e-3, 1e-5])
    for i in range(10000):
        x = random.gauss(0, 1)
        y = random.gauss(0, 1)
        vx = random.gauss(0, 1e-1)
        vy = random.gauss(0, 1e-1)
        wavelength = random.uniform(0.3, 1.2)
        ray = batoid.Ray(x, y, -0.1, vx, vy, 1, 0, wavelength)

        cm1 = batoid.ConstMedium(silica.getN(wavelength))
        cm2 = batoid.ConstMedium(air.getN(wavelength))

        rray1 = asphere.refract(ray, silica, air)
        rray2 = asphere.refract(ray, cm1, cm2)

        assert rray1 == rray2
예제 #24
0
def test_traceReverse():
    if __name__ == '__main__':
        nside = 128
    else:
        nside = 32

    fn = os.path.join(batoid.datadir, "HSC", "HSC.yaml")
    config = yaml.load(open(fn))
    telescope = batoid.parse.parse_optic(config['opticalSystem'])

    init_rays = batoid.rayGrid(20, 12.0, 0.005, 0.005, -1.0, nside, 500e-9,
                               1.0, batoid.ConstMedium(1.0))
    forward_rays, _ = telescope.trace(init_rays, outCoordSys=batoid.CoordSys())

    # Now, turn the result rays around and trace backwards
    forward_rays = forward_rays.propagatedToTime(40.0)
    reverse_rays = batoid.RayVector(
        [batoid.Ray(r.r, -r.v, -r.t, r.wavelength) for r in forward_rays])

    final_rays, _ = telescope.traceReverse(reverse_rays,
                                           outCoordSys=batoid.CoordSys())
    # propagate all the way to t=0
    final_rays = final_rays.propagatedToTime(0.0)

    w = np.where(np.logical_not(final_rays.vignetted))[0]
    for idx in w:
        np.testing.assert_allclose(init_rays[idx].x, final_rays[idx].x)
        np.testing.assert_allclose(init_rays[idx].y, final_rays[idx].y)
        np.testing.assert_allclose(init_rays[idx].z, final_rays[idx].z)
        np.testing.assert_allclose(init_rays[idx].vx, -final_rays[idx].vx)
        np.testing.assert_allclose(init_rays[idx].vy, -final_rays[idx].vy)
        np.testing.assert_allclose(init_rays[idx].vz, -final_rays[idx].vz)
        np.testing.assert_allclose(final_rays[idx].t, 0)
예제 #25
0
def test_HSC_trace():
    fn = os.path.join(batoid.datadir, "HSC", "HSC_old.yaml")
    config = yaml.load(open(fn))
    telescope = batoid.parse.parse_optic(config['opticalSystem'])

    # Zemax has a number of virtual surfaces that we don't trace in batoid.  Also, the HSC.yaml
    # above includes Baffle surfaces not in Zemax.  The following lists select out the surfaces in
    # common to both models.
    HSC_surfaces = [
        3, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 24, 25, 28, 29,
        31
    ]
    surface_names = [
        'PM', 'G1_entrance', 'G1_exit', 'G2_entrance', 'G2_exit',
        'ADC1_entrance', 'ADC1_exit', 'ADC2_entrance', 'ADC2_exit',
        'G3_entrance', 'G3_exit', 'G4_entrance', 'G4_exit', 'G5_entrance',
        'G5_exit', 'F_entrance', 'F_exit', 'W_entrance', 'W_exit', 'D'
    ]

    for fn in [
            "HSC_raytrace_1.txt", "HSC_raytrace_2.txt", "HSC_raytrace_3.txt"
    ]:
        filename = os.path.join(directory, "testdata", fn)
        with open(filename) as f:
            arr = np.loadtxt(f, skiprows=22, usecols=list(range(0, 12)))
        arr0 = arr[0]
        ray = batoid.Ray(arr0[1] / 1000,
                         arr0[2] / 1000,
                         16.0,
                         arr0[4],
                         arr0[5],
                         -arr0[6],
                         t=0,
                         wavelength=750e-9)
        tf = telescope.traceFull(ray)

        i = 0
        for surface in tf:
            if surface['name'] != surface_names[i]:
                continue

            s = surface['out']
            v = s.v / np.linalg.norm(s.v)

            transform = batoid.CoordTransform(surface['outCoordSys'],
                                              batoid.CoordSys())
            s = transform.applyForward(s)
            bt_isec = np.array([s.x, s.y, s.z - 16.0])
            zx_isec = arr[HSC_surfaces[i] - 1][1:4] / 1000
            np.testing.assert_allclose(bt_isec, zx_isec, rtol=0,
                                       atol=1e-9)  # nanometer agreement

            bt_angle = np.array([v[0], v[1], v[2]])
            zx_angle = arr[HSC_surfaces[i] - 1][4:7]
            # direction cosines agree to 1e-9
            np.testing.assert_allclose(bt_angle, zx_angle, rtol=0, atol=1e-9)

            i += 1
예제 #26
0
def randomRay():
    import random
    return batoid.Ray(
        randomVec3(),
        randomVec3(),
        random.uniform(0, 1),
        random.uniform(0, 1),
        random.uniform(0, 1),
    )
예제 #27
0
def test_fail():
    plane = batoid.Plane()
    assert plane.allowReverse == False
    ray = batoid.Ray([0, 0, -1], [0, 0, -1])
    ray = plane.intersect(ray)
    assert ray.failed

    ray = batoid.Ray([0, 0, -1], [0, 0, -1])
    plane.intersectInPlace(ray)
    assert ray.failed

    # These should succeed though if allowReverse is True
    plane = batoid.Plane(allowReverse=True)
    assert plane.allowReverse == True
    ray = batoid.Ray([0, 0, -1], [0, 0, -1])
    ray = plane.intersect(ray)
    assert not ray.failed

    ray = batoid.Ray([0, 0, -1], [0, 0, -1])
    plane.intersectInPlace(ray)
    assert not ray.failed
예제 #28
0
def test_asphere_refraction_reversal():
    import random
    random.seed(577215)
    wavelength = 500e-9  # arbitrary
    asphere = batoid.Asphere(23.0, -0.97, [1e-5, 1e-6])
    m1 = batoid.ConstMedium(1.7)
    m2 = batoid.ConstMedium(1.9)
    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, -0.1],
                         normalized(np.array([vx, vy, 1])) /
                         m1.getN(wavelength), 0)
        rray = asphere.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 = asphere.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 = asphere.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], -0.1, rtol=0, atol=1e-10)
예제 #29
0
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, m1, m2)
        np.testing.assert_allclose(np.linalg.norm(rray.v),
                                   1. / m2.getN(wavelength),
                                   rtol=1e-15)
        # also check refractInPlace
        rray2 = batoid.Ray(ray)
        para.refractInPlace(rray2, m1, m2)
        assert rray == rray2

        # 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)
예제 #30
0
def test_HSC_trace():
    telescope = batoid.Optic.fromYaml("HSC_old.yaml")

    # Zemax has a number of virtual surfaces that we don't trace in batoid.  Also, the HSC.yaml
    # above includes Baffle surfaces not in Zemax.  The following lists select out the surfaces in
    # common to both models.
    HSC_surfaces = [
        3, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 24, 25, 28, 29,
        31
    ]
    surface_names = [
        'PM', 'G1_entrance', 'G1_exit', 'G2_entrance', 'G2_exit',
        'ADC1_entrance', 'ADC1_exit', 'ADC2_entrance', 'ADC2_exit',
        'G3_entrance', 'G3_exit', 'G4_entrance', 'G4_exit', 'G5_entrance',
        'G5_exit', 'F_entrance', 'F_exit', 'W_entrance', 'W_exit', 'D'
    ]

    for fn in [
            "HSC_raytrace_1.txt", "HSC_raytrace_2.txt", "HSC_raytrace_3.txt"
    ]:
        filename = os.path.join(directory, "testdata", fn)
        with open(filename) as f:
            arr = np.loadtxt(f, skiprows=22, usecols=list(range(0, 12)))
        arr0 = arr[0]
        ray = batoid.Ray((arr0[1] / 1000, arr0[2] / 1000, 16.0),
                         (arr0[4], arr0[5], -arr0[6]),
                         t=0,
                         wavelength=750e-9)
        tf = telescope.traceFull(ray)

        i = 0
        for name in surface_names:
            surface = tf[name]
            s = surface['out']
            v = s.v / np.linalg.norm(s.v)

            s.toCoordSysInPlace(batoid.CoordSys())
            bt_isec = np.array([s.x, s.y, s.z - 16.0])
            zx_isec = arr[HSC_surfaces[i] - 1][1:4] / 1000
            np.testing.assert_allclose(bt_isec, zx_isec, rtol=0,
                                       atol=1e-9)  # nanometer agreement

            bt_angle = np.array([v[0], v[1], v[2]])
            zx_angle = arr[HSC_surfaces[i] - 1][4:7]
            # direction cosines agree to 1e-9
            np.testing.assert_allclose(bt_angle, zx_angle, rtol=0, atol=1e-9)

            i += 1