Beispiel #1
0
def test_transits():
    """Test transit light curve generation."""
    # Input params
    u1 = 0.4
    u2 = 0.26
    mstar = 1       # solar masses
    rstar = 1       # solar radii
    rplanet = 0.1   # fraction of stellar radius
    b0 = 0.5        # impact parameter
    P = 50          # orbital period in days
    npts = 25
    time = np.linspace(-0.25, 0.25, npts)

    # Compute the semi-major axis from Kepler's third law in units of rstar
    a = ((P * 86400) ** 2 * (1.32712440018e20 * mstar) /
         (4 * np.pi ** 2)) ** (1. / 3.) / (6.957e8 * rstar)

    # Get the inclination in degrees
    inc = np.arccos(b0 / a) * 180 / np.pi

    # Compute the flux from numerical integration
    f = 2 * np.pi / P * time
    b = a * np.sqrt(1 - np.sin(np.pi / 2. + f) ** 2
                    * np.sin(inc * np.pi / 180) ** 2)
    nF = np.zeros_like(time)
    for i in range(npts):
        nF[i] = NumericalFlux(b[i], rplanet, u1, u2)
    nF /= np.nanmax(nF)
    den = (1 - nF)
    den[den == 0] = 1e-10

    # Compute the starry flux
    # Instantiate a second-order map and a third-order map with u(3) = 0
    # The second-order map is optimized for speed and uses different
    # equations, but they should yield identical results.
    for lmax in [2, 3]:
        star = Primary(lmax)
        star[1] = u1
        star[2] = u2
        planet = Secondary()
        planet.r = rplanet
        planet.a = a
        planet.inc = inc
        planet.porb = P
        planet.lambda0 = 90
        system = System(star, planet)
        system.compute(time)
        sF = np.array(star.lightcurve)
        sF /= sF[0]

        # Compute the error, check that it's better than 1 ppb
        error = np.max((np.abs(nF - sF) / den)[np.where(nF < 1)])
        assert error < 1e-9
Beispiel #2
0
def generate(x, tstart=1, tend=5.3, npts=100, ning=100, neg=100):
    """Generate a synthetic light curve."""
    # Instantiate the star (params known exactly)
    star = Primary()
    star[1] = 0.4
    star[2] = 0.26

    # Instantiate the planet
    planet = Secondary(lmax=1)
    planet.lambda0 = 270
    planet.r = 0.0916
    planet.L = 5e-3
    planet.inc = 87
    planet.a = 11.12799
    planet.prot = 4.3
    planet.porb = 4.3
    planet.tref = 2.0

    # Instantiate the system
    system = System(star, planet)

    # Set the map coeffs
    set_coeffs(x, planet)

    # Time array w/ extra resolution at ingress/egress
    ingress = (1.94, 1.96)
    egress = (2.04, 2.06)
    time = np.linspace(tstart, tend, npts)
    if ingress is not None:
        t = np.linspace(ingress[0], ingress[1], ning)
        time = np.append(time, t)
    if egress is not None:
        t = np.linspace(egress[0], egress[1], neg)
        time = np.append(time, t)
    time = time[np.argsort(time)]

    # Compute and plot the starry flux
    system.compute(time)
    flux = np.array(system.lightcurve)

    # Noise it
    yerr = 1e-4 * np.nanmedian(flux)
    y = flux + yerr * np.random.randn(len(flux))

    # Compute the flux at hi res for plotting
    time_hires = np.linspace(tstart, tend, npts * 100)
    system.compute(time_hires)
    flux_hires = np.array(system.lightcurve)

    return time, y, yerr, star, planet, system, time_hires, flux_hires
Beispiel #3
0
# Instantiate the star
star = Primary()

# Give the star a quadratic limb darkening profile
star[1] = 0.4
star[2] = 0.26

# Instantiate planet b
b = Secondary()
b.r = 0.091679
b.L = 5e-3
b.inc = 90
b.porb = 4.3
b.prot = 4.3
b.a = 11.127991
b.lambda0 = 90
b.tref = 2
b.axis = [0, 1, 0]

# Give the planet a simple dipole map
b[1, 0] = 0.5

# Rotate the planet map to produce a hotspot offset of 15 degrees
b.rotate(theta=15)

# Compute and plot the starry flux
time = np.linspace(0, 20, 10000)
system = System(star, b)
system.compute(time)
sF = np.array(system.lightcurve)
ax[0].plot(time, sF, '-', color='C0')
Beispiel #4
0
time_secondary = np.linspace(24.75, 25.5, 2500)

# Limb-darkened star
star = Primary()
star[1] = 0.4
star[2] = 0.26
star.r_m = 0

# Dipole-map hot jupiter
planet = Secondary()
planet.r = 0.1
planet.a = 60
planet.inc = 89.5
planet.porb = 50
planet.prot = 2.49
planet.lambda0 = 89.9
planet.ecc = 0.3
planet.w = 89
planet.L = 1e-3
planet[1, 0] = 0.5

# Instantiate the system
system = System(star, planet)
system.exposure_time = 0

# Set up the plot
fig = pl.figure(figsize=(8, 8))
fig.subplots_adjust(hspace=0, bottom=0.05, top=0.95)

# Compute the flux during transit and during secondary eclipse
titles = ['Transit', 'Secondary Eclipse']
def test_gradients(plot=False):
    """Test the gradients in the `System` class."""
    # Limb-darkened star
    A = Primary(lmax=3)
    A[1] = 0.4
    A[2] = 0.26
    A[3] = -0.25
    A.r_m = 1e11

    # Dipole-map hot jupiter
    b = Secondary(lmax=2)
    b.r = 0.09
    b.a = 60
    b.inc = 89.943
    b.porb = 50
    b.prot = 2.49
    b.lambda0 = 89.9
    b.ecc = 0.3
    b.w = 89
    b.L = 1.75e-3
    b[1, 0] = 0.5
    b[2, 1] = 0.1
    b[2, 2] = -0.05

    # Dipole-map hot jupiter
    c = Secondary(lmax=1)
    c.r = 0.12
    c.a = 80
    c.inc = 89.95
    c.porb = 100
    c.prot = 7.83
    c.lambda0 = 85
    c.ecc = 0.29
    c.w = 87.4
    c.L = 1.5e-3
    c[1, 0] = 0.4

    # Instantiate the system
    # We're adding a ton of light travel delay
    # and a finite exposure time: this is a
    # comprehensive test of the main `starry` features
    system = System(A, b, c)
    system.exposure_time = 0.02

    # Light curves and gradients of this object
    object = system

    # Let's plot transit, eclipse, and a PPO
    for t1, t2, figname in zip([-0.425, 25.1, -2.6], [0.0, 25.75, -2.0], [
            "gradients_transit.png", "gradients_eclipse.png",
            "gradients_ppo.png"
    ]):

        # Time arrays
        time = np.linspace(t1, t2, 500)
        time_num = np.linspace(t1, t2, 50)

        # Set up the plot
        if plot:
            fig = pl.figure(figsize=(6, 10))
            fig.subplots_adjust(hspace=0, bottom=0.05, top=0.95)

        # Run!
        system.compute(time, gradient=True)
        flux = np.array(object.lightcurve)
        grad = dict(object.gradient)

        # Numerical flux
        system.compute(time_num, gradient=True)
        flux_num = np.array(object.lightcurve)

        # Plot it
        if plot:
            ax = pl.subplot2grid((18, 3), (0, 0), rowspan=5, colspan=3)
            ax.plot(time, flux, color='C0')
            ax.plot(time_num, flux_num, 'o', ms=3, color='C1')
            ax.set_yticks([])
            ax.set_xticks([])
            [i.set_linewidth(0.) for i in ax.spines.values()]
            col = 0
            row = 0
        eps = 1e-8
        error_rel = []
        for key in grad.keys():
            if key.endswith('.y') or key.endswith('.u'):
                for i, gradient in enumerate(grad[key]):
                    if plot:
                        axg = pl.subplot2grid((18, 3), (5 + row, col),
                                              colspan=1)
                        axg.plot(time, gradient, lw=1, color='C0')
                    if key.endswith('.y'):
                        y0 = eval(key)
                        y = np.array(y0)
                        y[i + 1] += eps
                        exec(key[0] + "[:, :] = y")
                        system.compute(time)
                        exec(key[0] + "[:, :] = y0")
                    else:
                        u0 = eval(key)
                        u = np.array(u0)
                        u[i] += eps
                        exec(key[0] + "[:] = u")
                        system.compute(time)
                        exec(key[0] + "[:] = u0")
                    numgrad = (object.lightcurve - flux) / eps
                    error_rel.append(np.max(abs(numgrad - gradient)))
                    if plot:
                        axg.plot(time, numgrad, lw=1, alpha=0.5, color='C1')
                        axg.set_ylabel(r"$%s_%d$" % (key, i), fontsize=5)
                        axg.margins(None, 0.5)
                        axg.set_xticks([])
                        axg.set_yticks([])
                        [i.set_linewidth(0.) for i in axg.spines.values()]
                        if row < 12:
                            row += 1
                        else:
                            row = 0
                            col += 1
            else:
                if plot:
                    axg = pl.subplot2grid((18, 3), (5 + row, col), colspan=1)
                    axg.plot(time, grad[key], lw=1, color='C0')
                exec(key + " += eps")
                system.compute(time)
                exec(key + " -= eps")
                numgrad = (object.lightcurve - flux) / eps
                error_rel.append(np.max(abs(numgrad - grad[key])))
                if plot:
                    axg.plot(time, numgrad, lw=1, alpha=0.5, color='C1')
                    axg.margins(None, 0.5)
                    axg.set_xticks([])
                    axg.set_yticks([])
                    axg.set_ylabel(r"$%s$" % key, fontsize=5)
                    [i.set_linewidth(0.) for i in axg.spines.values()]
                    if row < 12:
                        row += 1
                    else:
                        row = 0
                        col += 1

        # Generous error tolerance
        assert np.all(np.array(error_rel) < 1e-5)

        # Save the figure
        if plot:
            fig.savefig(figname, bbox_inches='tight', dpi=300)
            pl.close()
Beispiel #6
0
     (4 * np.pi**2))**(1. / 3.) / (6.957e8 * rstar)

# Get the inclination in degrees
inc = np.arccos(b0 / a) * 180 / np.pi

# Compute and plot the starry flux
star = Primary()
star[1] = u1
star[2] = u2

planet = Secondary()
planet.r = rplanet
planet.inc = inc
planet.porb = P
planet.a = a
planet.lambda0 = 90
system = System(star, planet)
system.compute(time)
sF = np.array(star.lightcurve)
sF /= sF[0]
ax[0].plot(time, sF, '-', color='C0', label='starry')

# Compute and plot the flux from numerical integration
print("Computing numerical flux...")
f = 2 * np.pi / P * time
b = a * np.sqrt(1 - np.sin(np.pi / 2. + f)**2 * np.sin(inc * np.pi / 180)**2)
nF = np.zeros_like(time)
for i in tqdm(range(npts)):
    nF[i] = NumericalFlux(b[i], rplanet, u1, u2)
nF /= np.nanmax(nF)
ax[0].plot(time[::20], nF[::20], 'o', color='C4', label='numerical')