示例#1
0
def test_ne():
    objs = [
        batoid.Plane(),
        batoid.Plane(allowReverse=True),
        batoid.Paraboloid(2.0),
    ]
    all_obj_diff(objs)
示例#2
0
def test_ne():
    objs = [
        batoid.Sphere(1.0),
        batoid.Sphere(2.0),
        batoid.Plane()
    ]
    all_obj_diff(objs)
示例#3
0
def test_ne():
    objs = [
        batoid.Paraboloid(1.0),
        batoid.Paraboloid(2.0),
        batoid.Plane()
    ]
    all_obj_diff(objs)
示例#4
0
def test_add_plane():
    np.random.seed(577)
    for _ in range(100):
        # Adding a plane should have zero effect on sag or normal vector
        s1 = batoid.Sphere(np.random.uniform(1, 3))
        s2 = batoid.Plane()
        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),
            rtol=1e-12,
            atol=1e-12
        )

        for _x, _y in zip(x[:100], y[:100]):
            np.testing.assert_allclose(
                sum.normal(_x, _y),
                s1.normal(_x, _y),
                rtol=1e-12,
                atol=1e-12
            )
示例#5
0
def test_intersect():
    rng = np.random.default_rng(577)
    size = 10_000
    planeCoordSys = batoid.CoordSys(origin=[0, 0, -1])
    plane = batoid.Plane()
    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)
    # 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(plane, rv.copy(), planeCoordSys)
    assert rv2.coordSys == planeCoordSys
    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, -1, rtol=0, atol=1e-12)

    # Check default intersect coordTransform
    rv2 = rv.copy().toCoordSys(planeCoordSys)
    batoid.intersect(plane, rv2)
    assert rv2.coordSys == planeCoordSys
    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, -1, rtol=0, atol=1e-12)
示例#6
0
def test_plane_reflection_reversal():
    import random
    random.seed(57)
    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())

        # 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 = 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)
        # Reflect and propagate back to t=0.
        cray = plane.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)
示例#7
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)
示例#8
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)
示例#9
0
def test_reflect():
    rng = np.random.default_rng(5772)
    size = 10_000
    plane = batoid.Plane()
    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.ones_like(x)
    rv = batoid.RayVector(x, y, z, vx, vy, vz)
    rvr = batoid.reflect(plane, rv.copy())
    rvr2 = plane.reflect(rv.copy())
    rays_allclose(rvr, rvr2)
    # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed")
    normal = plane.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)
示例#10
0
def test_ne():
    objs = [
        batoid.Plane(),
        batoid.Tilted(0.0, 0.1),
        batoid.Tilted(0.1, 0.1),
    ]
    all_obj_diff(objs)
示例#11
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])
示例#12
0
def test_refract():
    rng = np.random.default_rng(57721)
    size = 10_000
    plane = batoid.Plane()
    m0 = batoid.ConstMedium(rng.normal(1.2, 0.01))
    m1 = batoid.ConstMedium(rng.normal(1.3, 0.01))
    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.sqrt(1 - vx * vx - vy * vy) / m0.n
    rv = batoid.RayVector(x, y, z, vx, vy, vz)
    rvr = batoid.refract(plane, rv.copy(), m0, m1)
    rvr2 = plane.refract(rv.copy(), m0, m1)
    rays_allclose(rvr, rvr2)
    # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed")
    normal = plane.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)
示例#13
0
def test_prescreen():
    """Add an OPDScreen in front of LSST entrance pupil.  The OPD that comes out
    should be _negative_ the added phase delay by convention.
    """
    lsst = batoid.Optic.fromYaml("LSST_r.yaml")
    wavelength = 620e-9

    z_ref = batoid.zernikeGQ(
        lsst, 0, 0, wavelength, rings=10, reference='chief', jmax=37, eps=0.61
    )
    rng = np.random.default_rng(577)

    for i in range(4, 38):
        amplitude = rng.uniform(0.1, 0.2)
        zern = batoid.Zernike(
            np.array([0]*i+[amplitude])*wavelength,
            R_outer=4.18, R_inner=0.61*4.18
        )

        tel = batoid.CompoundOptic(
            (
                batoid.optic.OPDScreen(
                    batoid.Plane(),
                    zern,
                    name='PS',
                    obscuration=batoid.ObscNegation(batoid.ObscCircle(5.0)),
                    coordSys=lsst.stopSurface.coordSys
                ),
                *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)

        zGQ = batoid.zernikeGQ(
            tel, 0, 0, wavelength, rings=10, reference='chief', jmax=37, eps=0.61
        )
        zTA = batoid.zernikeTA(
            tel, 0, 0, wavelength, nrad=10, naz=60, reference='chief', jmax=37, eps=0.61
        )

        z_expect = np.zeros_like(zGQ)
        z_expect[i] = -amplitude  # Longer OPL => negative OPD
        np.testing.assert_allclose(
            (zGQ-z_ref)[4:], z_expect[4:],
            rtol=0, atol=5e-4
        )
        # Distortion makes this comparison less precise
        np.testing.assert_allclose(
            zGQ[4:], zTA[4:],
            rtol=0, atol=5e-3
        )
示例#14
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
示例#15
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
示例#16
0
def test_fail():
    sum = batoid.Sum([batoid.Plane(), batoid.Sphere(1.0)])
    rv = batoid.RayVector(0, 10, 0, 0, 0, -1)  # Too far to side
    rv2 = batoid.intersect(sum, 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(sum, rv.copy())
    np.testing.assert_equal(rv2.failed, np.array([False]))
示例#17
0
def test_refraction_chromatic():
    import random
    random.seed(577215664)
    wavelength1 = 500e-9
    wavelength2 = 600e-9
    flux = 1.0

    plane = batoid.Plane()
    filename = os.path.join(batoid.datadir, "media", "silica_dispersion.txt")
    wave, n = np.genfromtxt(filename).T
    wave *= 1e-6  # micron -> meters
    table = batoid.Table(wave, n, batoid.Table.Interpolant.linear)
    silica = batoid.TableMedium(table)
    air = batoid.Air()

    thx, thy = 0.001, 0.0001
    dirCos = batoid.utils.gnomonicToDirCos(thx, thy)
    rv1 = batoid.rayGrid(10.0, 1., dirCos[0], dirCos[1], -dirCos[2], 2,
                         wavelength1, flux, silica)
    rv2 = batoid.rayGrid(10.0, 1., dirCos[0], dirCos[1], -dirCos[2], 2,
                         wavelength2, flux, silica)
    rays = []
    for ray in rv1:
        rays.append(ray)
    for ray in rv2:
        rays.append(ray)
    rvCombined = batoid.RayVector(rays)

    rv1r = plane.refract(rv1, silica, air)
    rv2r = plane.refract(rv2, silica, air)
    assert rv1r != rv2r
    rays = []
    for ray in rv1r:
        rays.append(ray)
    for ray in rv2r:
        rays.append(ray)
    rvrCombined1 = batoid.RayVector(rays)

    rvrCombined2 = plane.refract(rvCombined, silica, air)

    assert rvrCombined1 == rvrCombined2

    # Check in-place
    plane.refractInPlace(rv1, silica, air)
    plane.refractInPlace(rv2, silica, air)
    assert rv1 != rv2
    plane.refractInPlace(rvCombined, silica, air)
    rays = []
    for ray in rv1:
        rays.append(ray)
    for ray in rv2:
        rays.append(ray)
    rvCombined2 = batoid.RayVector(rays)

    assert rvCombined == rvCombined2
示例#18
0
def test_fail():
    plane = batoid.Plane()

    # Only fail if vz == 0
    rv = batoid.RayVector(0, 0, 0, 0, 1, 0)
    rv2 = batoid.intersect(plane, rv.copy())
    np.testing.assert_equal(rv2.failed, np.array([True]))

    # Otherwise, succeeds
    rv = batoid.RayVector(0, 0, 0, 0, 0, -1)
    rv2 = batoid.intersect(plane, rv.copy())
    np.testing.assert_equal(rv2.failed, np.array([False]))
示例#19
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
示例#20
0
def test_asPolar():
    rng = np.random.default_rng(5772156)
    for _ in range(10):
        backDist = rng.uniform(9.0, 11.0)
        wavelength = rng.uniform(300e-9, 1100e-9)
        inner = rng.uniform(1.0, 3.0)
        outer = inner + rng.uniform(1.0, 3.0)
        nrad = rng.integers(1, 11)
        naz = rng.integers(10, 21)
        dirCos = np.array([
            rng.uniform(-0.1, 0.1),
            rng.uniform(-0.1, 0.1),
            rng.uniform(-1.2, -0.8),
        ])
        dirCos /= np.sqrt(np.dot(dirCos, dirCos))

        rays = batoid.RayVector.asPolar(backDist=backDist,
                                        wavelength=wavelength,
                                        outer=outer,
                                        inner=inner,
                                        nrad=nrad,
                                        naz=naz,
                                        dirCos=dirCos)

        np.testing.assert_allclose(rays.t, 0)
        np.testing.assert_allclose(rays.wavelength, wavelength)
        np.testing.assert_allclose(rays.vignetted, False)
        np.testing.assert_allclose(rays.failed, False)
        np.testing.assert_allclose(rays.vx, dirCos[0])
        np.testing.assert_allclose(rays.vy, dirCos[1])
        np.testing.assert_allclose(rays.vz, dirCos[2])

        assert len(rays) % 6 == 0

        # If we set inner=0, then last ray should
        # intersect the center of the pupil

        inner = 0.0
        rays = batoid.RayVector.asPolar(backDist=backDist,
                                        wavelength=wavelength,
                                        outer=outer,
                                        inner=inner,
                                        nrad=nrad,
                                        naz=naz,
                                        dirCos=dirCos)
        assert len(rays) % 6 == 1

        pupil = batoid.Plane()
        pupil.intersect(rays)
        np.testing.assert_allclose(rays.x[-1], 0, atol=1e-14)
        np.testing.assert_allclose(rays.y[-1], 0, atol=1e-14)
        np.testing.assert_allclose(rays.z[-1], 0, atol=1e-14)
示例#21
0
def test_RVasPolar():
    for _ in range(10):
        backDist = np.random.uniform(9.0, 11.0)
        wavelength = np.random.uniform(300e-9, 1100e-9)
        inner = np.random.uniform(1.0, 3.0)
        outer = inner + np.random.uniform(1.0, 3.0)
        nrad = np.random.randint(1, 10)
        naz = np.random.randint(10, 20)
        dirCos = np.array([
            np.random.uniform(-0.1, 0.1),
            np.random.uniform(-0.1, 0.1),
            np.random.uniform(-1.2, -0.8),
        ])
        dirCos /= np.sqrt(np.dot(dirCos, dirCos))

        rays = batoid.RayVector.asPolar(backDist=backDist,
                                        wavelength=wavelength,
                                        outer=outer,
                                        inner=inner,
                                        nrad=nrad,
                                        naz=naz,
                                        dirCos=dirCos)

        np.testing.assert_allclose(rays.t, 0)
        np.testing.assert_allclose(rays.wavelength, wavelength)
        np.testing.assert_allclose(rays.vignetted, False)
        np.testing.assert_allclose(rays.failed, False)
        np.testing.assert_allclose(rays.vx, dirCos[0])
        np.testing.assert_allclose(rays.vy, dirCos[1])
        np.testing.assert_allclose(rays.vz, dirCos[2])

        assert len(rays) % 6 == 0

        # If we set inner=0, then last ray should
        # intersect the center of the pupil

        inner = 0.0
        rays = batoid.RayVector.asPolar(backDist=backDist,
                                        wavelength=wavelength,
                                        outer=outer,
                                        inner=inner,
                                        nrad=nrad,
                                        naz=naz,
                                        dirCos=dirCos)
        assert len(rays) % 6 == 1

        # Check distribution of points propagated to entrance pupil
        pupil = batoid.Plane()
        pupil.intersect(rays)
        np.testing.assert_allclose(rays[len(rays) - 1].x, 0, atol=1e-14)
        np.testing.assert_allclose(rays[len(rays) - 1].y, 0, atol=1e-14)
        np.testing.assert_allclose(rays[len(rays) - 1].z, 0, atol=1e-14)
示例#22
0
def test_sag():
    rng = np.random.default_rng(5)
    for i in range(100):
        plane = batoid.Plane()
        for j in range(10):
            x = rng.normal()
            y = rng.normal()
            result = plane.sag(x, y)
            np.testing.assert_equal(result, 0.0)
            # Check that it returned a scalar float and not an array
            assert isinstance(result, float)
        # Check vectorization
        x = rng.normal(size=(10, 10))
        y = rng.normal(size=(10, 10))
        np.testing.assert_allclose(plane.sag(x, y), 0.0)
        # Make sure non-unit stride arrays also work
        np.testing.assert_allclose(plane.sag(x[::5, ::2], y[::5, ::2]), 0.0)
        do_pickle(plane)
示例#23
0
def test_withSurface():
    telescope = batoid.Optic.fromYaml("HSC.yaml")
    rays = batoid.RayVector.asPolar(telescope,
                                    wavelength=620e-9,
                                    theta_x=np.deg2rad(0.1),
                                    theta_y=0.0,
                                    nrad=10,
                                    naz=60)
    trays = telescope.trace(rays.copy())
    for key, item in telescope.itemDict.items():
        if not isinstance(item, batoid.Interface):
            continue
        # Do a trivial surface replacement
        surf2 = batoid.Sum([batoid.Plane(), item.surface])
        telescope2 = telescope.withSurface(key, surf2)
        assert telescope != telescope2
        trays2 = telescope.trace(rays.copy())
        rays_allclose(trays, trays2)
示例#24
0
def test_normal():
    rng = np.random.default_rng(57)
    for i in range(100):
        plane = batoid.Plane()
        for j in range(10):
            x = rng.normal()
            y = rng.normal()
            result = plane.normal(x, y)
            np.testing.assert_equal(result, np.array([0., 0., 1.]))
        # Check vectorization
        x = rng.normal(size=(10, 10))
        y = rng.normal(size=(10, 10))
        np.testing.assert_allclose(
            plane.normal(x, y),
            np.broadcast_to(np.array([0., 0., 1.]), (10, 10, 3)))
        # Make sure non-unit stride arrays also work
        np.testing.assert_allclose(
            plane.normal(x[::5, ::2], y[::5, ::2]),
            np.broadcast_to(np.array([0., 0., 1.]), (2, 5, 3)))
示例#25
0
def test_intersect():
    import random
    random.seed(577)
    for i in range(100):
        plane = batoid.Plane()
        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 = plane.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],
                                       plane.sag(x, y),
                                       rtol=0,
                                       atol=1e-9)
示例#26
0
def test_sag():
    import random
    random.seed(57)
    for i in range(100):
        plane = batoid.Plane()
        for j in range(10):
            x = random.gauss(0.0, 1.0)
            y = random.gauss(0.0, 1.0)
            result = plane.sag(x, y)
            np.testing.assert_allclose(result, 0.0)
            # 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(plane.sag(x, y), 0.0)
        # Make sure non-unit stride arrays also work
        np.testing.assert_allclose(plane.sag(x[::5, ::2], y[::5, ::2]), 0.0)
        do_pickle(plane)
示例#27
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):
        plane = batoid.Plane()
        r1s = plane.intersect(r0s)
        r2s = batoid.RayVector([plane.intersect(r0) for r0 in r0s])
        assert r1s == r2s
示例#28
0
def test_add_plane():
    rng = np.random.default_rng(5772156)
    for _ in range(100):
        # Adding a plane should have zero effect on sag or normal vector
        s1 = batoid.Sphere(rng.uniform(1, 3))
        s2 = batoid.Plane()
        sum = batoid.Sum([s1, s2])

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

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

        np.testing.assert_allclose(
            sum.normal(x, y),
            s1.normal(x, y),
            rtol=0,
            atol=1e-12,
        )
示例#29
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)
示例#30
0
def test_huygens_paraboloid(plot=False):
    if __name__ == '__main__':
        obscurations = [0.0, 0.25, 0.5, 0.75]
    else:
        obscurations = [0.25]

    print("Testing HuygensPSF")
    # Just do a single parabolic mirror test
    focalLength = 1.5
    diam = 0.3
    R = 2*focalLength
    for obscuration in obscurations:
        telescope = batoid.CompoundOptic(
            items = [
                batoid.Mirror(
                    batoid.Paraboloid(R),
                    name="Mirror",
                    obscuration=batoid.ObscNegation(
                        batoid.ObscAnnulus(0.5*obscuration*diam, 0.5*diam)
                    )
                ),
                batoid.Detector(
                    batoid.Plane(),
                    name="detector",
                    coordSys=batoid.CoordSys(origin=[0, 0, focalLength])
                )
            ],
            pupilSize=diam,
            backDist=10.0,
            inMedium=batoid.ConstMedium(1.0)
        )

        airy_size = 1.22*500e-9/diam * 206265
        print()
        print("Airy radius: {:4.2f} arcsec".format(airy_size))

        # Start with the HuygensPSF
        npix = 96
        size = 3.0 # arcsec
        dsize = size/npix
        dsize_X = dsize*focalLength/206265  # meters

        psf = batoid.huygensPSF(
            telescope, 0.0, 0.0, 500e-9,
            nx=npix, dx=dsize_X, dy=dsize_X
        )
        psf.array /= np.max(psf.array)

        scale = np.sqrt(np.abs(np.linalg.det(psf.primitiveVectors)))  # meters
        scale *= 206265/focalLength  # arcsec
        obj = galsim.Airy(lam=500, diam=diam, obscuration=obscuration)
        # Need to shift by half a pixel.
        obj = obj.shift(scale/2, scale/2)
        im = obj.drawImage(nx=npix, ny=npix, scale=scale, method='no_pixel')
        arr = im.array/np.max(im.array)
        gs_mom = galsim.hsm.FindAdaptiveMom(im)

        psfim = galsim.Image(psf.array)
        jt_mom = galsim.hsm.FindAdaptiveMom(psfim)

        print("GalSim shape: ", gs_mom.observed_shape)
        print("batoid shape: ", jt_mom.observed_shape)
        print("GalSim centroid:  ", gs_mom.moments_centroid)
        print("batoid centroid:  ", jt_mom.moments_centroid)
        print("GalSim size: ", gs_mom.moments_sigma)
        print("batoid size: ", jt_mom.moments_sigma)
        print("GalSim rho4: ", gs_mom.moments_rho4)
        print("batoid rho4: ", jt_mom.moments_rho4)

        np.testing.assert_allclose(
            gs_mom.observed_shape.g1,
            jt_mom.observed_shape.g1,
            rtol=0.0, atol=3e-3
        )
        np.testing.assert_allclose(
            gs_mom.observed_shape.g2,
            jt_mom.observed_shape.g2,
            rtol=0.0, atol=3e-3
        )
        np.testing.assert_allclose(
            gs_mom.moments_centroid.x,
            jt_mom.moments_centroid.x,
            rtol=0.0, atol=1e-9
        )
        np.testing.assert_allclose(
            gs_mom.moments_centroid.y,
            jt_mom.moments_centroid.y,
            rtol=0.0, atol=1e-9
        )
        np.testing.assert_allclose(
            gs_mom.moments_sigma,
            jt_mom.moments_sigma,
            rtol=1e-2  # why not better?!
        )
        np.testing.assert_allclose(
            gs_mom.moments_rho4,
            jt_mom.moments_rho4,
            rtol=2e-2
        )

        if plot:
            size = scale*npix
            import matplotlib.pyplot as plt
            fig = plt.figure(figsize=(15, 4))
            ax1 = fig.add_subplot(131)
            im1 = ax1.imshow(
                np.log10(arr),
                extent=np.r_[-1,1,-1,1]*size/2,
                vmin=-7, vmax=0
            )
            plt.colorbar(im1, ax=ax1, label=r'$\log_{10}$ flux')
            ax1.set_title('GalSim')
            ax1.set_xlabel("arcsec")
            ax1.set_ylabel("arcsec")

            sizeX = dsize_X * npix * 1e6  # microns
            ax2 = fig.add_subplot(132)
            im2 = ax2.imshow(
                np.log10(psf.array),
                extent=np.r_[-1,1,-1,1]*sizeX/2,
                vmin=-7, vmax=0
            )
            plt.colorbar(im2, ax=ax2, label=r'$\log_{10}$ flux')
            ax2.set_title('batoid')
            ax2.set_xlabel(r"$\mu m$")
            ax2.set_ylabel(r"$\mu m$")

            ax3 = fig.add_subplot(133)
            im3 = ax3.imshow(
                (psf.array-arr)/np.max(arr),
                vmin=-0.01, vmax=0.01,
                cmap='seismic'
            )
            plt.colorbar(im3, ax=ax3, label="(batoid-GalSim)/max(GalSim)")
            ax3.set_title('resid')
            ax3.set_xlabel(r"$\mu m$")
            ax3.set_ylabel(r"$\mu m$")

            fig.tight_layout()

            plt.show()