예제 #1
0
def _fit_params(params, bjd, fcorr, ef, Ms, Rs, Teff, Kep=False, TESS=False):
    '''Get best-fit parameters.'''
    assert params.shape == (4, )
    P, T0, depth, duration = params
    if Kep:
        u1, u2 = llnl.get_LDcoeffs_Kepler(Ms, Rs, Teff)
    elif TESS:
        u1, u2 = llnl.get_LDcoeffs_TESS(Ms, Rs, Teff)

    aRs = rvs.AU2m(rvs.semimajoraxis(P, Ms, 0)) / rvs.Rsun2m(Rs)
    rpRs = np.sqrt(depth)
    p0 = aRs, rpRs, 90.
    bnds = ((aRs * .9, 0, float(rvs.inclination(P, Ms, Rs, 1.1))),
            (aRs * 1.1, 1, float(rvs.inclination(P, Ms, Rs, -1.1))))
    try:
        popt, _ = curve_fit(transit_model_func_curve_fit(P, T0, u1, u2),
                            bjd,
                            fcorr,
                            p0=p0,
                            sigma=ef,
                            absolute_sigma=True,
                            bounds=bnds)
        aRs, rpRs, inc = popt
        depth = rpRs**2
        b = rvs.impactparam_inc(P, Ms, Rs, inc)
        duration = P / (np.pi * aRs) * np.sqrt((1 + np.sqrt(depth))**2 - b * b)
        return P, T0, depth, duration
    except RuntimeError:
        return params
예제 #2
0
def compute_transit_duration(rp, P, K, Rs, b=0):
    mp = np.array([runTESS.get_planet_mass(i) for i in rp])
    Ms = runTESS.get_stellar_mass(P, mp, K)
    sma = rvs.AU2m(rvs.semimajoraxis(P, Ms, mp))
    Rs2 = rvs.Rsun2m(Rs)
    tau0 = P * Rs2 / (2 * np.pi * sma)
    return 2. * tau0 * np.sqrt(1. - b**2)
예제 #3
0
    def compute_transit_prob(self):
        self.transit_prob, self.etransit_prob = np.zeros_like(self.sens), \
                                                       np.zeros_like(self.sens)
        self.logtransit_prob,self.elogtransit_prob = np.zeros_like(self.sens), \
                                                            np.zeros_like(self.sens)
        for i in range(self._xlen):
            for j in range(self._ylen):

                # compute transit probability in log-linear space
                Pmid = 10**(np.log10(self.logPgrid[i]) + \
                            np.diff(np.log10(self.logPgrid[:2])/2))
                rpmid = self.rpgrid[j] + np.diff(self.rpgrid)[0] / 2.
                sma = rvs.AU2m(
                    rvs.semimajoraxis(Pmid, unp.uarray(self.Ms, self.e_Ms), 0))
                transit_prob =  (rvs.Rsun2m(unp.uarray(self.Rs, self.e_Rs)) + \
                                 rvs.Rearth2m(rpmid)) / sma
                self.transit_prob[i, j] = unp.nominal_values(transit_prob)
                self.etransit_prob[i, j] = unp.std_devs(transit_prob)

                # compute transit probability in log-linear space
                rpmid = 10**(np.log10(self.logrpgrid[j]) + \
                             np.diff(np.log10(self.logrpgrid[:2])/2))
                transit_prob =  (rvs.Rsun2m(unp.uarray(self.Rs, self.e_Rs)) + \
                                               rvs.Rearth2m(rpmid)) / sma
                self.logtransit_prob[i, j] = unp.nominal_values(transit_prob)
                self.elogtransit_prob[i, j] = unp.std_devs(transit_prob)

        # correction from beta distribution fit (Kipping 2013)
        factor = 1.08
        self.transit_prob *= factor
        self.etransit_prob *= factor
        self.logtransit_prob *= factor
        self.elogtransit_prob *= factor
예제 #4
0
def _is_Vshaped(params,
                bjd,
                fcorr,
                ef,
                Ms,
                Rs,
                Teff,
                Kep,
                TESS,
                duration_frac=.05):
    '''check if transit is V-shaped although this does not imply an EB 
    because inclined transiting planets can look like this as well.'''
    # fit transit model
    assert params.shape == (4, )
    P, T0, depth = params[:3]
    if Kep:
        u1, u2 = llnl.get_LDcoeffs_Kepler(Ms, Rs, Teff)
    elif TESS:
        u1, u2 = llnl.get_LDcoeffs_TESS(Ms, Rs, Teff)

    aRs = rvs.AU2m(rvs.semimajoraxis(P, Ms, 0)) / rvs.Rsun2m(Rs)
    rpRs = np.sqrt(depth)
    p0 = aRs, rpRs, 90.
    bnds = ((aRs * .9, 0, float(rvs.inclination(P, Ms, Rs, 1.1))),
            (aRs * 1.1, 1, float(rvs.inclination(P, Ms, Rs, -1.1))))
    try:
        popt, _ = curve_fit(transit_model_func_curve_fit(P, T0, u1, u2),
                            bjd,
                            fcorr,
                            p0=p0,
                            sigma=ef,
                            absolute_sigma=True,
                            bounds=bnds)
        aRs, rpRs, inc = popt
    except RuntimeError:
        return False, 0.

    # get ingress, egress times and duration
    transit_func = transit_model_func_curve_fit(P, T0, 0, 0)
    fmodel = transit_func(bjd, *popt)
    phase = foldAt(bjd, P, T0)
    phase[phase > .5] -= 1
    depth = fmodel.min()
    T1, T4 = phase[(phase<=0) & (fmodel==1)].max()*P, \
             phase[(phase>=0) & (fmodel==1)].min()*P
    in_ingress = (phase <= 0) & np.isclose(fmodel, depth, rtol=1e-4)
    T2 = phase[in_ingress].min() * P if in_ingress.sum() > 0 else (T4 -
                                                                   T1) * .1
    in_egress = (phase >= 0) & np.isclose(fmodel, depth, rtol=1e-4)
    T3 = phase[in_egress].max() * P if in_egress.sum() > 0 else (T4 - T1) * .1
    Tingress, Tegress, duration = T2 - T1, T4 - T3, T4 - T1
    Tedge = Tingress + Tegress

    # V-shaped if T2==T3 or if ingress+egress time is the same as the duration
    if T2 == T3:
        return True, duration
    elif np.isclose(Tedge, duration, rtol=duration_frac):
        return True, duration
    else:
        return False, duration
예제 #5
0
def depth2rp(P_days, depth, duration_days, Ms, Rs):
    '''Compute the planet radius from the transit depth and 
    duration using the analtyical treatment from Mandel & Agol 2002'''
    assert 0 < depth < 1

    # compute distance from centres at T0
    sma = rvs.semimajoraxis(P_days, Ms, 0)
    a_Rs = rvs.AU2m(sma) / rvs.Rsun2m(Rs)
    assert a_Rs > 1
    b = rvs.impactparam_T(P_days, Ms, Rs, duration_days)
    assert abs(b) <= 1
    inc = float(rvs.inclination(P_days, Ms, Rs, b))
    z = compute_distance_center(a_Rs, inc)

    # compute size ratio (p=rp/Rs)
    p_simple = unp.sqrt(depth)
    if z <= 1 - p_simple:
        p = p_simple

    else:
        ps = np.logspace(-6, 0, 1000)
        depths = p2depth_grazing(ps, z)
        if (np.nanmax(depths) < z) or (np.nanmin(depths) > z):
            p = p_simple
        else:
            fint = interp1d(ps, depths)
            p = float(fint(depth))

    # compute planet radius
    rp = rvs.m2Rearth(rvs.Rsun2m(p * Rs))
    return rp
예제 #6
0
    def __init__(self, folder, index, index2, Nyrs=1e6, Nout=500):

        self.index, self.index2, self.Nyrs, self.Nout = int(index), int(
            index2), int(Nyrs), int(Nout)
        self.Ms = 0.
        while self.Ms <= 0:
            self.Ms = Ms + np.random.randn() * .0032
        self.bjd0 = 2458354.101878819  # first TESS photometry epoch
        self.DONE = False

        # Setup simulation
        self.folder = folder
        self.outname = '%s/SimArchive/archived%.4d_%.4d' % (
            self.folder, self.index, self.index2)
        sim = setupsim(self, self.outname)
        self.mps, self.sma0, self.ecc0, self.inc0, self.omega0, self.Omega0, self.theta0 = get_initial_parameters(
            sim)
        self.inc0 += 90
        #self.Rhill = get_Rhill_init(self.mps, self.Ms, self.sma0)
        self.pickleobject()

        # Integrate simulation
        print 'Integrating system...'
        self.bjds,self.RVs,self.smas,self.eccs,self.incs,self.dist,self.stable = \
         integrate_sim(np.linspace(0, rvs.yrs2days(self.Nyrs), self.Nout) + self.bjd0, sim)
        self.bs = np.zeros(self.incs.shape)
        for i in range(self.bjds.size):
            self.bs[i] = rvs.impactparam_inc(rvs.AU2m(self.smas[i]) /
                                             rvs.Rsun2m(Rs),
                                             self.incs[i] + 90,
                                             ecc=self.eccs[i])
        self.DONE = True
        self.pickleobject()
예제 #7
0
def optimize_singletransit_params(params,
                                  bjd,
                                  fcorr,
                                  ef,
                                  Ms,
                                  Rs,
                                  u1,
                                  u2,
                                  pltt=True):
    '''Get best-fit parameters using the periodic fit parameters for 
    initialization (i.e. P_input < P_singletransit).'''
    assert params.shape == (4, )
    P, T0, depth, duration = params
    if depth >= .9:  # sometimes the dimming is passed instead of depth
        return np.nan, np.nan, np.nan, np.nan, \
            np.repeat(np.nan, bjd.size), np.repeat(np.nan, 7)
    # focus on data centered around T0
    g = (bjd >= T0 - 10 * duration) & (bjd <= T0 + 10 * duration)
    bjdred, fcorrred, efred = bjd[g], fcorr[g], ef[g]

    # initialize
    aRs = rvs.AU2m(rvs.semimajoraxis(P, Ms, 0)) / rvs.Rsun2m(Rs)
    rpRs = np.sqrt(depth)
    p0 = P, T0, aRs, rpRs, 90.
    incs = np.array([
        float(rvs.inclination(P, Ms, Rs, 1)),
        float(rvs.inclination(P, Ms, Rs, -1))
    ])
    bnds = ((0, T0 - .2, 0, 0, incs.min()), (P * 100, T0 + .2, aRs * 100, 1,
                                             incs.max()))
    try:
        popt, _ = curve_fit(llnl.transit_model_func_curve_fit(u1, u2),
                            bjdred,
                            fcorrred,
                            p0=p0,
                            sigma=efred,
                            absolute_sigma=True,
                            bounds=bnds)
        P, T0, aRs, rpRs, inc = popt
        depth = rpRs**2
        b = rvs.impactparam_inc(P, Ms, Rs, inc)
        duration = P / (np.pi * aRs) * np.sqrt((1 + np.sqrt(depth))**2 - b * b)
        func = llnl.transit_model_func_curve_fit(u1, u2)
        fmodel = func(bjdred, P, T0, aRs, rpRs, inc)
        params = np.array([P, T0, aRs, rpRs, inc, u1, u2])
    except RuntimeError, ValueError:
        func = llnl.transit_model_func_curve_fit(u1, u2)
        fmodel = func(bjdred, P, T0, aRs, rpRs, 90.)
        P, T0, depth, duration = np.repeat(np.nan, 4)
        params = np.repeat(np.nan, 7)
예제 #8
0
def fit_params(params, bjd, fcorr, ef, Ms, Rs, Teff, Kep=False, TESS=False):
    '''Get best-fit parameters.'''
    assert params.shape == (4, )
    P, T0, depth, duration = params
    if depth >= .9:  # sometimes the dimming is passed instead of depth
        return np.nan, np.nan, np.nan, np.nan, \
               np.repeat(np.nan, bjd.size), np.repeat(np.nan, 7)
    if Kep:
        u1, u2 = get_LDcoeffs_Kepler(Ms, Rs, Teff)
    if TESS:
        u1, u2 = get_LDcoeffs_TESS(Ms, Rs, Teff)
    assert np.all(np.isfinite([u1, u2]))
    aRs = rvs.AU2m(rvs.semimajoraxis(P, Ms, 0)) / rvs.Rsun2m(Rs)
    rpRs = np.sqrt(depth)
    p0 = P, T0, aRs, rpRs, 90.
    incs = np.array([
        float(rvs.inclination(P, Ms, Rs, 1)),
        float(rvs.inclination(P, Ms, Rs, -1))
    ])
    bnds = ((P * .9, T0 - P * 1.1, aRs * .9, 0, incs.min()),
            (P * 1.1, T0 + P * 1.1, aRs * 1.1, 1, incs.max()))
    try:
        popt, _ = curve_fit(transit_model_func_curve_fit(u1, u2),
                            bjd,
                            fcorr,
                            p0=p0,
                            sigma=ef,
                            absolute_sigma=True,
                            bounds=bnds)
        P, T0, aRs, rpRs, inc = popt
        depth = rpRs**2
        b = rvs.impactparam_inc(P, Ms, Rs, inc)
        duration = P / (np.pi * aRs) * np.sqrt((1 + np.sqrt(depth))**2 - b * b)
        func = transit_model_func_curve_fit(u1, u2)
        fmodel = func(bjd, P, T0, aRs, rpRs, inc)
        params = np.array([P, T0, aRs, rpRs, inc, u1, u2])
    except RuntimeError, ValueError:
        func = transit_model_func_curve_fit(u1, u2)
        fmodel = func(bjd, P, T0, aRs, rpRs, 90.)
        P, T0, depth, duration = np.repeat(np.nan, 4)
        params = np.repeat(np.nan, 7)
def sample_planet_params(self, index, postGAIA=True):
    '''sample distribution of planet parameters from observables and stellar pdfs'''
    # get stellar parameters PDFs either from derived from GAIA distances
    # or from original Kepler parameters (approximate distributions as skewnormal)
    g = int(index)
    print self.KepIDs[g]
    if postGAIA:
        path = '../GAIAMdwarfs/Gaia-DR2-distances_custom/DistancePosteriors/'
        try:
            samp_Rs, samp_Teff, samp_Ms = np.loadtxt('%s/KepID_allpost_%i' %
                                                     (path, self.KepIDs[g]),
                                                     delimiter=',',
                                                     usecols=(9, 10, 11)).T
        except IOError:
            samp_Rs, samp_Teff, samp_Ms = np.zeros(1000), np.zeros(
                1000), np.zeros(1000)

        if np.all(np.isnan(samp_Rs)) or np.all(np.isnan(samp_Teff)) or np.all(
                np.isnan(samp_Ms)):
            samp_Rs, samp_Teff, samp_Ms = np.zeros(1000), np.zeros(
                1000), np.zeros(1000)

        samp_Rs = resample_PDF(samp_Rs[np.isfinite(samp_Rs)],
                               samp_Rs.size,
                               sig=1e-3)
        samp_Teff = resample_PDF(samp_Teff[np.isfinite(samp_Teff)],
                                 samp_Teff.size,
                                 sig=5)
        samp_Ms = resample_PDF(samp_Ms[np.isfinite(samp_Ms)],
                               samp_Ms.size,
                               sig=1e-3)
    else:
        _, _, samp_Rs = get_samples_from_percentiles(self.Rss1[g],
                                                     self.ehi_Rss1[g],
                                                     self.elo_Rss1[g],
                                                     Nsamp=1e3)
        _, _, samp_Teff = get_samples_from_percentiles(self.Teffs1[g],
                                                       self.ehi_Teffs1[g],
                                                       self.elo_Teffs1[g],
                                                       Nsamp=1e3)
        _, _, samp_Ms = get_samples_from_percentiles(self.Mss1[g],
                                                     self.ehi_Mss1[g],
                                                     self.elo_Mss1[g],
                                                     Nsamp=1e3)

    # sample rp/Rs distribution from point estimates
    _, _, samp_rpRs = get_samples_from_percentiles(self.rpRs[g],
                                                   self.ehi_rpRs[g],
                                                   self.elo_rpRs[g],
                                                   Nsamp=samp_Rs.size)

    # compute planet radius PDF
    samp_rp = rvs.m2Rearth(rvs.Rsun2m(samp_rpRs * samp_Rs))
    v = np.percentile(samp_rp, (16, 50, 84))
    rps = v[1], v[2] - v[1], v[1] - v[0]

    # compute semi-major axis PDF
    samp_Ps = np.random.normal(self.Ps[g], self.e_Ps[g], samp_Ms.size)
    samp_as = rvs.semimajoraxis(samp_Ps, samp_Ms, 0)
    v = np.percentile(samp_as, (16, 50, 84))
    smas = v[1], v[2] - v[1], v[1] - v[0]

    # compute equilibrium T PDF (Bond albedo=0)
    samp_Teq = samp_Teff * np.sqrt(
        .5 * rvs.Rsun2m(samp_Rs) / rvs.AU2m(samp_as))
    v = np.percentile(samp_Teq, (16, 50, 84))
    Teqs = v[1], v[2] - v[1], v[1] - v[0]

    # compute insolation
    samp_F = samp_Rs**2 * (samp_Teff / 5778.)**4 / samp_as**2
    v = np.percentile(samp_F, (16, 50, 84))
    Fs = v[1], v[2] - v[1], v[1] - v[0]

    return rps, smas, Teqs, Fs
예제 #10
0
def run_emcee(theta,
              bjd,
              bjdred,
              fred,
              efred,
              initialize,
              u1,
              u2,
              Ms,
              Rs,
              nwalkers=200,
              burnin=200,
              nsteps=400,
              a=2,
              zeroplanetmodel=False):
    '''Run mcmc on an input light curve with no transit model.'''
    # get limits on P and aRs
    P, T0 = theta[:2]
    Plim = np.max([T0 - bjd.min(), bjd.max() - T0])
    aRslim = rvs.AU2m(rvs.semimajoraxis(Plim, Ms, 0)) / rvs.Rsun2m(Rs)
    print 'Plim = %.4f' % Plim
    print 'aRslim = %.4f' % aRslim

    # initialize chains
    assert len(theta) == len(initialize)
    assert len(theta) == 5
    theta[0], theta[2] = Plim + 10, aRslim + 10
    p0 = []
    for i in range(nwalkers):
        p0.append(theta + initialize * np.random.randn(len(theta)))

    # initialize sampler
    P = theta[0]
    inclims = np.array([
        float(rvs.inclination(P, Ms, Rs, 1)),
        float(rvs.inclination(P, Ms, Rs, -1))
    ])
    args = (theta, bjdred, fred, efred, Plim, aRslim, inclims, u1, u2,
            zeroplanetmodel)
    sampler = emcee.EnsembleSampler(nwalkers,
                                    len(theta),
                                    lnprob,
                                    args=args,
                                    a=a)

    # run burnin
    print 'Running burnin...'
    t0 = time.time()
    p0, _, _ = sampler.run_mcmc(p0, burnin)
    print 'Burnin acceptance fraction is %.4f' % np.mean(
        sampler.acceptance_fraction)
    print 'Burnin took %.4f minutes\n' % ((time.time() - t0) / 60.)
    sampler.reset()

    # run MCMC
    print 'Running full MCMC...'
    p0, _, _ = sampler.run_mcmc(p0, nsteps)
    samples = sampler.chain.reshape((-1, len(theta)))
    print "Mean acceptance fraction: %.4f" % np.mean(
        sampler.acceptance_fraction)
    print 'Full MCMC took %.4f minutes' % ((time.time() - t0) / 60.)

    return sampler, samples
예제 #11
0
def integrate_sim(bjd, sim):
    '''
    Integrate the system forward in time with outputs computed over 
    the window function.

    Parameters
    ----------
    `bjd` : array (Nobs,)
	Numpy array of the window function to output measurements at in BJD.
	For dynamical modeling of RVs this should be the window function
	of observations. For dynamical stability it should be much 
	larger.
    `sim` : rebound simulation object
	Output from setup_sim(); the simulation to integrate forward 
	in time.

    Returns
    -------
    `bjd` : array (Nobs,)
	The input window function; time arrray.
    `RVs` : array (Nobs,)
	Numpy array of the stellar RVs in m/s.
    `smas` : array (Nobs, Nplanets,)
	Numpy array of each planets' semimajor axis at the 
	times in bjd in AU.
    `eccs` : array (Nobs, Nplanets,)
        Numpy array of each planets' eccentricity at the
        times in bjd.
    `incs` : array (Nobs, Nplanets,)
        Numpy array of each planets' inclination at the
        times in bjd in degrees.

    '''
    # Get window function for outputs
    times = days2years(
        bjd - bjd.min())  ##np.linspace(sim.t, sim.t+Tfin_yrs, int(Nout))

    # Get timestep
    nparticles, dts = len(
        sim.particles.keys()), [np.diff(days2years(times)).min() * 1e-1]
    for i in range(1, nparticles):
        dts.append(sim.particles[i].P * 1e-1)
    sim.dt = np.min(dts)

    # Save output
    nparticles = len(sim.particles.keys())
    RVs = np.zeros(times.size)
    stable = True
    smas, eccs, incs = np.zeros((times.size, nparticles-1)), \
                       np.zeros((times.size, nparticles-1)), \
                       np.zeros((times.size, nparticles-1))
    dist = np.zeros(times.size)
    ps = sim.particles
    try:
        for i in range(times.size):
            sim.integrate(times[i])
            dp = ps[1] - ps[2]
            dist[i] = np.sqrt(dp.x**2 + dp.y**2 + dp.z**2)
            RVs[i] = -sim.particles['star'].vx
            for j in range(nparticles - 1):
                smas[i, j] = sim.particles[j + 1].a  # AU
                eccs[i, j] = sim.particles[j + 1].e
                incs[i, j] = np.rad2deg(sim.particles[j + 1].inc)
    except rebound.Encounter as error:
        stable = False

    # Convert units (AU/yr -> m/s)
    RVs = rvs.AU2m(RVs) / (365.25 * 24 * 60 * 60)

    return bjd, RVs, smas, eccs, incs, dist, stable