예제 #1
0
def test_omega_w():
    """Ensure `w` and `omega` are equivalent."""
    body = starry.Secondary(starry.Map(), porb=1.0, w=30.0)
    assert np.allclose(body.omega, 30)
    body.omega = 60
    assert np.allclose(body.w, 60)

    body = starry.Secondary(starry.Map(), porb=1.0, omega=30.0)
    assert np.allclose(body.w, 30)
    body.w = 60
    assert np.allclose(body.omega, 60)
예제 #2
0
def test_orientation(Omega=45, inc=35):
    # Instantiate
    pri = starry.Primary(starry.Map(amp=0))
    sec = starry.Secondary(
        starry.Map(ydeg=1, amp=1),
        porb=1.0,
        r=0,
        m=0,
        inc=inc,
        Omega=Omega,
        prot=1.0,
        theta0=180.0,
    )
    sec.map[1, 0] = 1.0
    sys = starry.System(pri, sec)

    # Align the rotational axis with the orbital axis
    sec.map.inc = sec.inc
    sec.map.obl = sec.Omega

    # Compute the flux
    t = np.linspace(-0.5, 0.5, 1000)
    flux = sys.flux(t)

    # This is the analytic result
    flux_analytic = 1.0 - np.sin(inc * np.pi / 180.0) * (
        2.0 / np.sqrt(3.0)
    ) * np.cos(2 * np.pi * t)

    assert np.allclose(flux, flux_analytic)
예제 #3
0
def test_bad_sys_data():
    pri = starry.Primary(starry.Map(ydeg=1))
    sec = starry.Secondary(starry.Map(ydeg=1), porb=1.0)
    sys = starry.System(pri, sec)

    # User didn't provide the covariance
    with pytest.raises(ValueError) as e:
        sys.set_data([0.0])

    # User didn't provide a dataset
    with pytest.raises(ValueError) as e:
        sys.solve(t=[0.0])

    # Provide a dummy dataset
    sys.set_data([0.0], C=1.0)

    # User didn't provide a prior for the primary
    with pytest.raises(ValueError) as e:
        sys.solve(t=[0.0])

    # Provide a prior for the primary
    pri.map.set_prior(L=1.0)

    # Provide a prior for the secondary
    sec.map.set_prior(L=1.0)

    # Now check that this works
    sys.solve(t=[0.0])
예제 #4
0
def test_system(ydeg, nw):

    # Oblate map
    map = starry.Map(udeg=2, ydeg=ydeg, oblate=True, nw=nw)
    map[1] = 0.5
    map[2] = 0.25
    map.omega = 0.5
    map.beta = 1.23
    map.tpole = 8000
    map.f = 1 - 2 / (map.omega**2 + 2)
    map.obl = 30

    # Compute system flux
    star = starry.Primary(map, r=1.5)
    planet = starry.Secondary(starry.Map(amp=0, nw=nw), porb=1.0, r=0.1, m=0)
    sys = starry.System(star, planet)
    t = np.linspace(-0.1, 0.1, 1000)
    flux_sys = sys.flux(t, integrated=True)

    # Compute map flux manually
    x, y, z = sys.position(t)
    xo = x[1] / star._r
    yo = y[1] / star._r
    flux_map = map.flux(xo=xo, yo=yo, ro=planet._r / star._r, integrated=True)

    # Check that they agree
    assert np.allclose(flux_map, flux_sys)
예제 #5
0
def test_integration():
    pri = starry.Primary(starry.Map(udeg=2), r=1.0)
    pri.map[1:] = [0.5, 0.25]
    sec = starry.Secondary(starry.Map(ydeg=1), porb=1.0, r=0.25)

    # Manual integration
    t = np.linspace(-0.1, 0.1, 10000)
    sys = starry.System(pri, sec, texp=0)
    flux = sys.flux(t)
    t = t.reshape(-1, 1000).mean(axis=1)
    flux = flux.reshape(-1, 1000).mean(axis=1)

    sys0 = starry.System(pri, sec, texp=0.02, order=0, oversample=999)
    assert sys0.order == 0
    assert sys0.oversample == 999
    flux0 = sys0.flux(t)
    assert np.allclose(flux, flux0)

    sys1 = starry.System(pri, sec, texp=0.02, order=1, oversample=999)
    assert sys1.order == 1
    assert sys1.oversample == 999
    flux1 = sys1.flux(t)
    assert np.allclose(flux, flux1)

    sys2 = starry.System(pri, sec, texp=0.02, order=2, oversample=999)
    assert sys2.order == 2
    assert sys2.oversample == 999
    flux2 = sys2.flux(t)
    assert np.allclose(flux, flux2)
예제 #6
0
def test_solve_with_zero_degree_primary():
    """
    Test for https://github.com/rodluger/starry/issues/253.

    """
    # Random data
    t = np.linspace(-0.1, 0.1, 100)
    flux = np.random.randn(len(t))
    sigma = 1.0

    # Instantiate a primary with ydeg = 0
    star_0 = starry.Primary(starry.Map(ydeg=0))
    star_0.map.set_prior(L=1)

    # Instantiate a secondary with ydeg > 0
    star_1 = starry.Secondary(starry.Map(ydeg=1), porb=1.0)

    # The system
    sys = starry.System(star_0, star_1)

    # Place a generous prior on the map coefficients
    star_1.map.set_prior(L=1)
    sys.set_data(flux, C=sigma**2)

    # Solve the linear problem
    mu, cho_cov = sys.solve(t=t)

    # Check that it didn't fail horribly
    assert not np.any(np.isnan(mu))
    assert not np.any(np.isnan(np.tril(cho_cov)))
예제 #7
0
def test_system_rv_show_pymc3():
    with pm.Model(**theano_config) as model:
        pri = starry.Primary(starry.Map(rv=True))
        sec = starry.Secondary(starry.Map(rv=True), porb=1.0)
        sec.inc = pm.Uniform("inc", 0, 90)
        sys = starry.System(pri, sec)
        sys.show(0.1, file="tmp.pdf", point=model.test_point)
        os.remove("tmp.pdf")
예제 #8
0
def test_system_rv_show():
    pri = starry.Primary(starry.Map(rv=True))
    sec = starry.Secondary(starry.Map(rv=True), porb=1.0)
    sys = starry.System(pri, sec)
    sys.show(0.1, file="tmp.pdf")
    os.remove("tmp.pdf")
    sys.show([0.1, 0.2], file="tmp.mp4")
    os.remove("tmp.mp4")
예제 #9
0
def test_bad_sys_settings():
    pri = starry.Primary(starry.Map())
    sec = starry.Secondary(starry.Map(), porb=1.0)

    # Bad exposure time
    with pytest.raises(AssertionError) as e:
        sys = starry.System(pri, sec, texp=-1.0)

    # Bad oversample factor
    with pytest.raises(AssertionError) as e:
        sys = starry.System(pri, sec, oversample=-1)

    # Bad integration order
    with pytest.raises(AssertionError) as e:
        sys = starry.System(pri, sec, order=99)

    # Bad primary
    with pytest.raises(AssertionError) as e:
        sys = starry.System(sec, sec)

    # Reflected light primary
    with pytest.raises(AssertionError) as e:
        sys = starry.System(starry.Primary(starry.Map(reflected=True)), sec)

    # Bad secondary
    with pytest.raises(AssertionError) as e:
        sys = starry.System(pri, pri)

    # No secondaries
    with pytest.raises(AssertionError) as e:
        sys = starry.System(pri)

    # Different number of wavelength bins
    with pytest.raises(AssertionError) as e:
        sys = starry.System(
            pri, starry.Secondary(starry.Map(ydeg=1, nw=2), porb=1.0))

    # RV for secondary, but not primary
    with pytest.raises(AssertionError) as e:
        sys = starry.System(pri, starry.Secondary(starry.Map(rv=True),
                                                  porb=1.0))

    # Reflected light for first secondary, but not second
    with pytest.raises(ValueError) as e:
        sys = starry.System(
            pri, sec, starry.Secondary(starry.Map(reflected=True), porb=1.0))
예제 #10
0
        def __init__(self):
            # Instantiate a star with a dipole map
            A = starry.Primary(starry.Map(ydeg=1), prot=0.0)
            amp_true = 0.75
            y_true = np.array([1, 0.1, 0.2, 0.3])
            inc_true = 60
            A.map.amp = amp_true
            A.map[1, :] = y_true[1:]
            A.map.inc = inc_true

            # Instantiate two transiting planets with different longitudes of
            # ascending node. This ensures there's no null space!
            b = starry.Secondary(starry.Map(amp=0),
                                 porb=1.0,
                                 r=0.1,
                                 t0=-0.05,
                                 Omega=30.0)
            c = starry.Secondary(starry.Map(amp=0),
                                 porb=1.0,
                                 r=0.1,
                                 t0=0.05,
                                 Omega=-30.0)
            sys = starry.System(A, b, c)

            # Generate a synthetic light curve with just a little noise
            t = np.linspace(-0.1, 0.1, 100)
            flux = sys.flux(t)
            sigma = 1e-5
            np.random.seed(1)
            flux += np.random.randn(len(t)) * sigma

            # Store
            self.A = A
            self.b = b
            self.c = c
            self.sys = sys
            self.t = t
            self.flux = flux
            self.sigma = sigma
            self.amp_true = amp_true
            self.y_true = y_true
            self.inc_true = inc_true
예제 #11
0
def test_period_semi():
    # Check that an error is raised if neither a nor porb is given
    with pytest.raises(ValueError) as e:
        body = starry.Secondary(starry.Map())
    assert "Must provide a value for either `porb` or `a`" in str(e.value)

    # Check that the semi --> period conversion works
    pri = starry.Primary(starry.Map(), m=1.0, mass_unit=u.Msun)
    sec = starry.Secondary(starry.Map(),
                           a=10.0,
                           m=1.0,
                           length_unit=u.AU,
                           mass_unit=u.Mearth)
    sys = starry.System(pri, sec)
    period = sys._get_periods()[0]
    true_period = (
        ((2 * np.pi) * (sec.a * sec.length_unit)**(3 / 2) /
         (np.sqrt(G * (pri.m * pri.mass_unit + sec.m * sec.mass_unit)))).to(
             u.day).value)
    assert np.allclose(period, true_period)
예제 #12
0
def test_system_show(mp4=False):
    pri = starry.Primary(starry.Map())
    sec = starry.Secondary(starry.Map(), porb=1.0)
    sys = starry.System(pri, sec)
    sys.show(0.1, file="tmp.pdf")
    os.remove("tmp.pdf")
    if mp4:
        sys.show([0.1, 0.2], file="tmp.mp4")
        os.remove("tmp.mp4")
    sys.show([0.1, 0.2], file="tmp.gif")
    os.remove("tmp.gif")
예제 #13
0
def test_compare_to_map_rv():
    """Ensure we get the same result by calling `map.rv()` and `sys.rv()`."""
    # Define the map
    map = starry.Map(ydeg=1, udeg=2, rv=True, amp=1, veq=1, alpha=0, lazy=True)
    map[1, 0] = 0.5

    # Define the star
    A = starry.Primary(
        map,
        r=1.0,
        m=1.0,
        prot=0,
        length_unit=u.Rsun,
        mass_unit=u.Msun,
        lazy=True,
    )

    # Define the planet
    b = starry.Secondary(
        starry.Map(rv=True, amp=1, veq=0, lazy=True),
        r=0.1,
        porb=1.0,
        m=0.01,
        t0=0.0,
        inc=86.0,
        ecc=0.3,
        w=60,
        length_unit=u.Rsun,
        mass_unit=u.Msun,
        angle_unit=u.degree,
        time_unit=u.day,
    )

    # Define the system
    sys = starry.System(A, b)

    # Time array
    time = np.linspace(-0.05, 0.05, 1000)

    # Get the positions of both bodies
    x, y, z = sys.position(time)

    # Compute the relative positions
    xo = x[1] - x[0]
    yo = y[1] - y[0]
    zo = z[1] - z[0]
    ro = b.r / A.r

    # Compare
    rv1 = map.rv(xo=xo, yo=yo, ro=ro).eval()
    rv2 = sys.rv(time, keplerian=False).eval()
    assert np.allclose(rv1, rv2)
예제 #14
0
def test_compare_to_exoplanet():
    """Ensure we get the same result with `starry` and `exoplanet`.
    """
    # Define the star
    A = starry.Primary(
        starry.Map(rv=True, veq=0),
        r=1.0,
        m=1.0,
        prot=0,
        length_unit=u.Rsun,
        mass_unit=u.Msun,
    )

    # Define the planet
    b = starry.Secondary(
        starry.Map(rv=True, veq=0),
        r=0.1,
        porb=1.0,
        m=0.01,
        t0=0.0,
        inc=86.0,
        ecc=0.3,
        w=60,
        length_unit=u.Rsun,
        mass_unit=u.Msun,
        angle_unit=u.degree,
        time_unit=u.day,
    )

    # Define the system
    sys = starry.System(A, b)

    # Compute with starry
    time = np.linspace(-0.5, 0.5, 1000)
    rv1 = sys.rv(time, keplerian=True)

    # Compute with exoplanet
    orbit = exoplanet.orbits.KeplerianOrbit(
        period=1.0,
        t0=0.0,
        incl=86.0 * np.pi / 180,
        ecc=0.3,
        omega=60 * np.pi / 180,
        m_planet=0.01,
        m_star=1.0,
        r_star=1.0,
    )
    rv2 = orbit.get_radial_velocity(time).eval()

    assert np.allclose(rv1, rv2)
예제 #15
0
def test_normalization(d=10, r=1):
    """Test the normalization of the flux."""
    # Instantiate a system. Planet has radius `r` and is at
    # distance `d` from a point illumination source.
    planet = starry.Secondary(starry.Map(reflected=True), a=d, r=r)
    star = starry.Primary(starry.Map(), r=0)
    sys = starry.System(star, planet)

    # Get the star & planet flux when it's at full phase
    t_full = 0.5 * sys._get_periods()[0]
    f_star, f_planet = sys.flux(t=t_full, total=False)

    # Star should have unit flux
    assert np.allclose(f_star, 1.0)

    # Planet should have flux equal to (2 / 3) r^2 / d^2
    assert np.allclose(f_planet, (2.0 / 3.0) * r**2 / d**2)
예제 #16
0
def test_unit_conversions():
    body = starry.Secondary(
        starry.Map(ydeg=1, inc=1.0, obl=1.0, angle_unit=u.radian),
        r=1.0,
        m=1.0,
        inc=1.0,
        porb=1.0,
        prot=1.0,
        t0=1.0,
        theta0=1.0,
        Omega=1.0,
        length_unit=u.cm,
        mass_unit=u.gram,
        time_unit=u.second,
        angle_unit=u.radian,
    )
    assert body.r == 1.0
    assert body._r == body.length_unit.in_units(u.Rsun)
    assert body.m == 1.0
    assert body._m == body.mass_unit.in_units(u.Msun)
    assert body.inc == 1.0
    assert body._inc == body.angle_unit.in_units(u.radian)
    assert body.theta0 == 1.0
    assert body._theta0 == body.angle_unit.in_units(u.radian)
    assert body.Omega == 1.0
    assert body._Omega == body.angle_unit.in_units(u.radian)
    assert body.prot == 1.0
    assert body._prot == body.time_unit.in_units(u.day)
    assert body.t0 == 1.0
    assert body._t0 == body.time_unit.in_units(u.day)
    assert body.ecc == 0.0
    assert body.map.inc == 1.0
    assert body.map._inc == body.map.angle_unit.in_units(u.radian)
    assert body.map.obl == 1.0
    assert body.map._obl == body.map.angle_unit.in_units(u.radian)

    # First test the orbital period
    assert body.porb == 1.0
    assert body._porb == body.time_unit.in_units(u.day)

    # Now test the semi-major axis
    assert body.a is None
    body.a = 1.0
    assert body.a == 1.0
    assert body._a == body.length_unit.in_units(u.Rsun)
    assert body.porb is None
예제 #17
0
    porb=1.481,
    r=21.1770214,
    length_unit=u.earthRad,
    inc=87.2,
    t0=-0.65625,
)

# Time arrays (secondary eclipse ingress / full phase curve)
t_ingress = np.linspace(0, 0.017, 1000)
t_egress = 218 / 60 / 24 + t_ingress
t_sec = np.append(t_ingress, t_egress)
t_phase = kwargs["t0"] + kwargs["porb"] * np.linspace(-0.5, 0.5, 1000)

# Uniform
e_map = starry.Map(ydeg=1, reflected=False)
e = starry.Secondary(e_map, **kwargs)
sys = starry.System(star, e)
flux_em = sys.flux(t=t_sec, total=False)[1]

# Noon approximation
e_map = starry.Map(udeg=1, reflected=False)
e_map[1] = 1
e = starry.Secondary(e_map, **kwargs)
sys = starry.System(star, e)
flux_ld = sys.flux(t=t_sec, total=False)[1]

# Reflected, point source
e_map = starry.Map(ydeg=1, reflected=True)
e_map.amp *= 0.2
e = starry.Secondary(e_map, **kwargs)
sys = starry.System(star, e)
예제 #18
0
def test_default_system_units():
    pri = starry.Primary(starry.Map())
    sec = starry.Secondary(starry.Map(), porb=1.0)
    sys = starry.System(pri, sec)
    assert sys.time_unit == u.day
예제 #19
0
star = starry.Primary(starry.Map(udeg=2, amp=1),
                      r=0.805,
                      m=0.846,
                      length_unit=u.Rsun,
                      mass_unit=u.Msun)
star.map[1:] = [0.5, 0.25]

planet_amp = 0.6 * 0.0035  # ensure depth is 3.85 ppt
planet = starry.Secondary(
    starry.Map(
        6,
        amp=planet_amp,
        inc=85.76,
    ),
    r=1.138,
    m=1.162,
    inc=85.76,
    porb=2.22,
    prot=2.22,
    theta0=180,
    length_unit=u.Rjup,
    mass_unit=u.Mjup,
    angle_unit=u.degree,
)

sys = starry.System(star, planet)
time = np.arange(-2, 2, MINUTE)

A0 = planet_amp * sys.design_matrix(time)[:, 1]
A = planet_amp * sys.design_matrix(time)[:, 2:]

# Generate
예제 #20
0
woodbury = [False, True]
solve_inputs = itertools.product(vals, vals)
lnlike_inputs = itertools.product(vals, vals, woodbury)

# Instantiate a star with a dipole map
A = starry.Primary(starry.Map(ydeg=1), prot=0.0)
amp_true = 0.75
y_true = np.array([1, 0.1, 0.2, 0.3])
inc_true = 60
A.map.amp = amp_true
A.map[1, :] = y_true[1:]
A.map.inc = inc_true

# Instantiate two transiting planets with different longitudes of
# ascending node. This ensures there's no null space!
b = starry.Secondary(starry.Map(amp=0), porb=1.0, r=0.1, t0=-0.05, Omega=30.0)
c = starry.Secondary(starry.Map(amp=0), porb=1.0, r=0.1, t0=0.05, Omega=-30.0)
sys = starry.System(A, b, c)

# Generate a synthetic light curve with just a little noise
t = np.linspace(-0.1, 0.1, 100)
flux = sys.flux(t)
sigma = 1e-5
np.random.seed(1)
flux += np.random.randn(len(t)) * sigma


@pytest.mark.parametrize("L,C", solve_inputs)
def test_solve(L, C):
    # Place a generous prior on the map coefficients
    if L == "scalar":
예제 #21
0
def test_light_delay():
    pri = starry.Primary(starry.Map())
    sec = starry.Secondary(starry.Map(), porb=1.0)
    sys = starry.System(pri, sec, light_delay=True)
    assert sys.light_delay is True
예제 #22
0
def test_edge_on_eccentric():
    # Params
    ydeg = 10
    u = [0.5, 0.25]
    y = 0.1 * np.random.randn((ydeg + 1)**2 - 1)
    porb = 1.0
    prot = 1.0
    amp = 0.25
    r = 0.5
    m = 0.25
    ecc = 0.5
    w = 75
    t = np.linspace(-0.75, 0.75, 10000)

    # Beta version
    pri_beta = starry_beta.kepler.Primary(lmax=2)
    pri_beta[1], pri_beta[2] = u
    sec_beta = starry_beta.kepler.Secondary(lmax=ydeg)
    sec_beta[1:, :] = y
    sec_beta.porb = porb
    sec_beta.prot = prot
    sec_beta.L = amp
    sec_beta.r = r
    sec_beta.a = (G_grav * (1.0 + m) * porb**2 / (4 * np.pi**2))**(1.0 / 3)
    sec_beta.inc = 90
    sec_beta.Omega = 0
    sec_beta.ecc = ecc
    sec_beta.w = w
    sys_beta = starry_beta.kepler.System(pri_beta, sec_beta)
    sys_beta.compute(t)
    flux_beta = np.array(sys_beta.lightcurve)

    # Compute the time of transit
    M0 = 0.5 * np.pi - w * np.pi / 180.0
    f = M0
    E = np.arctan2(np.sqrt(1 - ecc**2) * np.sin(f), ecc + np.cos(f))
    M = E - ecc * np.sin(E)
    t0 = (M - M0) * porb / (2 * np.pi)

    # Compute the time of eclipse
    E = np.arctan2(
        np.sqrt(1 - ecc**2) * np.sin(f + np.pi), ecc + np.cos(f + np.pi))
    M = E - ecc * np.sin(E)
    t_ecl = (M - M0) * porb / (2 * np.pi)

    # This is the required phase offset such that the map coefficients
    # correspond to what the observer sees at secondary eclipse
    theta0 = -(t_ecl - t0) * 360

    # Version 1
    pri = starry.Primary(starry.Map(udeg=2))
    pri.map[1:] = u
    sec = starry.Secondary(
        starry.Map(ydeg=ydeg, amp=amp),
        porb=porb,
        r=r,
        m=m,
        inc=90,
        Omega=0,
        ecc=ecc,
        w=w,
        t0=t0,
        theta0=theta0,
    )
    sec.map[1:, :] = y
    sys = starry.System(pri, sec)
    flux = sys.flux(t)

    # Compare
    assert np.allclose(flux, flux_beta)
예제 #23
0
def test_bodies():
    pri = starry.Primary(starry.Map())
    sec = starry.Secondary(starry.Map(ydeg=1), porb=1.0)
    sys = starry.System(pri, sec)
    assert sys.primary == pri
    assert sys.secondaries[0] == sec
예제 #24
0
def test_reflected_light():
    pri = starry.Primary(starry.Map(amp=0), r=1)
    sec = starry.Secondary(starry.Map(reflected=True), porb=1.0, r=1)
    sys = starry.System(pri, sec)
    t = np.concatenate((np.linspace(0.1, 0.4, 50), np.linspace(0.6, 0.9, 50)))
    flux = sys.flux(t)