コード例 #1
0
ファイル: model.py プロジェクト: iancze/TWA-3-orbit
                          sd=0.12)  # milliarcsec GAIA DR2
    parallax = pm.Deterministic("parallax", 1e-3 * mparallax)  # arcsec

    a_ang = pm.Uniform("aAng", 0.1, 10.0, testval=3.51)  # milliarcsec

    # the semi-major axis in au
    a = pm.Deterministic("a", 1e-3 * a_ang / parallax)  # au

    logP = pm.Uniform("logP",
                      lower=np.log(20.0),
                      upper=np.log(50.0),
                      testval=np.log(34.87846))  # days
    P = pm.Deterministic("P", tt.exp(logP))

    e = pm.Uniform("e", lower=0, upper=1, testval=0.62)
    omega = Angle("omega", testval=80.5 * deg)  # omega_Aa
    Omega = Angle("Omega", testval=110.0 *
                  deg)  # - pi to pi # estimated assuming same as CB disk
    gamma = pm.Uniform("gamma", lower=0, upper=20, testval=10.1)  # km/s

    # uniform on cos incl. testpoint assuming same as CB disk.
    cos_incl = pm.Uniform("cosIncl",
                          lower=0.0,
                          upper=1.0,
                          testval=np.cos(48.0 *
                                         deg))  # radians, 0 to 180 degrees
    incl = pm.Deterministic("incl", tt.arccos(cos_incl))

    # Since we're doing an RV + astrometric fit, M2 now becomes a parameter of the model
    # use a bounded normal to enforce positivity
    PosNormal = pm.Bound(pm.Normal, lower=0.0)
コード例 #2
0
    a_ang_inner = pm.Uniform("aAngInner", 0.1, 10.0,
                             testval=4.613)  # milliarcsec

    # the semi-major axis in au
    a_inner = pm.Deterministic("aInner", 1e-3 * a_ang_inner / parallax)  # au

    logP_inner = pm.Uniform("logPInner",
                            lower=np.log(20),
                            upper=np.log(50.0),
                            testval=np.log(34.88))  # days
    P_inner = pm.Deterministic("PInner", tt.exp(logP_inner))

    e_inner = pm.Uniform("eInner", lower=0, upper=1, testval=0.63)

    omega_inner = Angle("omegaInner", testval=1.415)  # omega_Aa
    Omega_inner = Angle("OmegaInner", testval=1.821)

    # constrained to be i > 90
    cos_incl_inner = pm.Uniform("cosInclInner",
                                lower=-1.0,
                                upper=0.0,
                                testval=-0.659)
    incl_inner = pm.Deterministic("inclInner", tt.arccos(cos_incl_inner))

    MAb = pm.Normal("MAb", mu=0.29, sd=0.5, testval=0.241)  # solar masses

    t_periastron_inner = pm.Uniform("tPeriastronInner",
                                    lower=1140.0,
                                    upper=1180.0,
                                    testval=1159.57)  # + 2400000 + jd0
コード例 #3
0
def default_nonlinear_prior(P_min=None,
                            P_max=None,
                            s=None,
                            model=None,
                            pars=None):
    r"""
    Retrieve pymc3 variables that specify the default prior on the nonlinear
    parameters of The Joker. See docstring of `JokerPrior.default()` for more
    information.

    The nonlinear parameters an default prior forms are:

    * ``P``, period: :math:`p(P) \propto 1/P`, over the domain
      :math:`(P_{\rm min}, P_{\rm max})`
    * ``e``, eccentricity: the short-period form from Kipping (2013)
    * ``M0``, phase: uniform over the domain :math:`(0, 2\pi)`
    * ``omega``, argument of pericenter: uniform over the domain
      :math:`(0, 2\pi)`
    * ``s``, additional extra variance added in quadrature to data
      uncertainties: delta-function at 0

    Parameters
    ----------
    P_min : `~astropy.units.Quantity` [time]
    P_max : `~astropy.units.Quantity` [time]
    s : `~pm.model.TensorVariable`, ~astropy.units.Quantity` [speed]
    model : `pymc3.Model`
        This is either required, or this function must be called within a pymc3
        model context.
    """
    import theano.tensor as tt
    import pymc3 as pm
    from exoplanet.distributions import Angle
    import exoplanet.units as xu
    from .distributions import UniformLog, Kipping13Global

    model = pm.modelcontext(model)

    if pars is None:
        pars = dict()

    if s is None:
        s = 0 * u.m / u.s

    if isinstance(s, pm.model.TensorVariable):
        pars['s'] = pars.get('s', s)
    else:
        if not hasattr(s, 'unit') or not s.unit.is_equivalent(u.km / u.s):
            raise u.UnitsError(
                "Invalid unit for s: must be equivalent to km/s")

    # dictionary of parameters to return
    out_pars = dict()

    with model:
        # Set up the default priors for parameters with defaults

        # Note: we have to do it this way (as opposed to with .get(..., default)
        # because this can only get executed if the param is not already
        # defined, otherwise variables are defined twice in the model
        if 'e' not in pars:
            out_pars['e'] = xu.with_unit(Kipping13Global('e'), u.one)

        # If either omega or M0 is specified by user, default to U(0,2π)
        if 'omega' not in pars:
            out_pars['omega'] = xu.with_unit(Angle('omega'), u.rad)

        if 'M0' not in pars:
            out_pars['M0'] = xu.with_unit(Angle('M0'), u.rad)

        if 's' not in pars:
            out_pars['s'] = xu.with_unit(
                pm.Deterministic('s', tt.constant(s.value)), s.unit)

        if 'P' not in pars:
            if P_min is None or P_max is None:
                raise ValueError(
                    "If you are using the default period prior, "
                    "you must pass in both P_min and P_max to set "
                    "the period prior domain.")
            out_pars['P'] = xu.with_unit(
                UniformLog('P', P_min.value, P_max.to_value(P_min.unit)),
                P_min.unit)

    for k in pars.keys():
        out_pars[k] = pars[k]

    return out_pars
コード例 #4
0
    # We'll include the parallax data as a prior on the parallax value

    # 27.31 mas +/- 0.12 mas # from GAIA
    mparallax = pm.Normal("mparallax", mu=27.31, sd=0.12)  # milliarcsec
    parallax = pm.Deterministic("parallax", 1e-3 * mparallax)  # arcsec
    a_ang = pm.Uniform("a_ang", 0.1, 4.0, testval=2.0)  # arcsec

    # the semi-major axis in au
    a = pm.Deterministic("a", a_ang / parallax)  # au

    # we expect the period to be somewhere in the range of 25 years,
    # so we'll set a broad prior on logP
    logP = pm.Normal("logP", mu=np.log(400), sd=1.0)
    P = pm.Deterministic("P", tt.exp(logP) * yr)  # days

    omega = Angle("omega", testval=1.8)  # - pi to pi
    Omega = Angle("Omega", testval=-0.7)  # - pi to pi

    phi = Angle("phi", testval=2.)

    n = 2 * np.pi * tt.exp(-logP) / yr

    t_periastron = (phi + omega) / n

    cos_incl = pm.Uniform("cosIncl", lower=-1., upper=1.0, testval=np.cos(3.0))
    incl = pm.Deterministic("incl", tt.arccos(cos_incl))
    e = pm.Uniform("e", lower=0.0, upper=1.0, testval=0.3)
    gamma_keck = pm.Uniform("gammaKeck", lower=5, upper=10,
                            testval=7.5)  # km/s on Keck RV scale

    MB = pm.Normal("MB", mu=0.3, sd=0.5)  # solar masses
コード例 #5
0
ファイル: astrometric.py プロジェクト: emilygilbert/exoplanet
def get_model(parallax=None):
    with pm.Model() as model:

        if parallax is None:
            # Without an actual parallax measurement, we can model the orbit in units of arcseconds
            # by providing a fake_parallax and conversion constant
            plx = 1  # arcsec
        else:
            # Below we will run a version of this model where a measurement of parallax is provided
            # The measurement is in milliarcsec
            m_plx = pm.Bound(pm.Normal, lower=0, upper=100)(
                "m_plx", mu=parallax[0], sd=parallax[1], testval=parallax[0]
            )
            plx = pm.Deterministic("plx", 1e-3 * m_plx)

        a_ang = pm.Uniform("a_ang", 0.1, 1.0, testval=0.324)
        a = pm.Deterministic("a", a_ang / plx)

        # We expect the period to be somewhere in the range of 25 years,
        # so we'll set a broad prior on logP
        logP = pm.Normal(
            "logP", mu=np.log(25 * yr), sd=10.0, testval=np.log(28.8 * yr)
        )
        P = pm.Deterministic("P", tt.exp(logP))

        # For astrometric-only fits, it's generally better to fit in
        # p = (Omega + omega)/2 and m = (Omega - omega)/2 instead of omega and Omega
        # directly
        omega0 = 251.6 * deg - np.pi
        Omega0 = 159.6 * deg
        p = Angle("p", testval=0.5 * (Omega0 + omega0))
        m = Angle("m", testval=0.5 * (Omega0 - omega0))
        omega = pm.Deterministic("omega", p - m)
        Omega = pm.Deterministic("Omega", p + m)

        # For these orbits, it can also be better to fit for a phase angle
        # (relative to a reference time) instead of the time of periasteron
        # passage directly
        phase = Angle("phase", testval=0.0)
        tperi = pm.Deterministic("tperi", T0 + P * phase / (2 * np.pi))

        # Geometric uiform prior on cos(incl)
        cos_incl = pm.Uniform(
            "cos_incl", lower=-1, upper=1, testval=np.cos(96.0 * deg)
        )
        incl = pm.Deterministic("incl", tt.arccos(cos_incl))
        ecc = pm.Uniform("ecc", lower=0.0, upper=1.0, testval=0.798)

        # Set up the orbit
        orbit = xo.orbits.KeplerianOrbit(
            a=a * au_to_R_sun,
            t_periastron=tperi,
            period=P,
            incl=incl,
            ecc=ecc,
            omega=omega,
            Omega=Omega,
        )
        if parallax is not None:
            pm.Deterministic("M_tot", orbit.m_total)

        # Compute the model in rho and theta
        rho_model, theta_model = orbit.get_relative_angles(astro_jds, plx)
        pm.Deterministic("rho_model", rho_model)
        pm.Deterministic("theta_model", theta_model)

        # Add jitter terms to both separation and position angle
        log_rho_s = pm.Normal(
            "log_rho_s", mu=np.log(np.median(rho_err)), sd=5.0
        )
        log_theta_s = pm.Normal(
            "log_theta_s", mu=np.log(np.median(theta_err)), sd=5.0
        )
        rho_tot_err = tt.sqrt(rho_err ** 2 + tt.exp(2 * log_rho_s))
        theta_tot_err = tt.sqrt(theta_err ** 2 + tt.exp(2 * log_theta_s))

        # define the likelihood function, e.g., a Gaussian on both rho and theta
        pm.Normal("rho_obs", mu=rho_model, sd=rho_tot_err, observed=rho_data)

        # We want to be cognizant of the fact that theta wraps so the following is equivalent to
        # pm.Normal("obs_theta", mu=theta_model, observed=theta_data, sd=theta_tot_err)
        # but takes into account the wrapping. Thanks to Rob de Rosa for the tip.
        theta_diff = tt.arctan2(
            tt.sin(theta_model - theta_data), tt.cos(theta_model - theta_data)
        )
        pm.Normal("theta_obs", mu=theta_diff, sd=theta_tot_err, observed=0.0)

        # Set up predicted orbits for later plotting
        rho_dense, theta_dense = orbit.get_relative_angles(t_fine, plx)
        rho_save = pm.Deterministic("rho_save", rho_dense)
        theta_save = pm.Deterministic("theta_save", theta_dense)

        # Optimize to find the initial parameters
        map_soln = model.test_point
        map_soln = xo.optimize(map_soln, vars=[log_rho_s, log_theta_s])
        map_soln = xo.optimize(map_soln, vars=[phase])
        map_soln = xo.optimize(map_soln, vars=[p, m, ecc])
        map_soln = xo.optimize(map_soln, vars=[logP, a_ang, phase])
        map_soln = xo.optimize(map_soln)

    return model, map_soln
コード例 #6
0
ファイル: model.py プロジェクト: iancze/TWA-3-orbit
                          sd=0.12)  # milliarcsec GAIA DR2
    parallax = pm.Deterministic("parallax", 1e-3 * mparallax)  # arcsec

    # a_ang = pm.Uniform("aAng", 0.1, 4.0, testval=2.0) # arcsec
    a_ang = pm.Gamma("aAng", alpha=3.0, beta=1.5, testval=1.9)  # arcsec

    # the semi-major axis in au
    a = pm.Deterministic("a", a_ang / parallax)  # au

    # we expect the period to be somewhere in the range of 400 years,
    # so we'll set a broad prior on logP
    logP = pm.Normal("logP", mu=np.log(400), sd=0.8)
    P = pm.Deterministic("P", tt.exp(logP) * yr)  # days

    # omega = Angle("omega", testval=180 * deg)  # - pi to pi
    omega = Angle("omega")  # - pi to pi

    # because we don't have RV information in this model,
    # Omega and Omega + 180 are degenerate.
    # I think flipping Omega also advances omega and phi by pi
    # So, just limit it to -90 to 90 degrees
    # Omega_intermediate = Angle("OmegaIntermediate")  # - pi to pi
    # Omega = pm.Deterministic("Omega", Omega_intermediate / 2 + np.pi / 2)  # 0 to pi
    Omega = Angle("Omega")

    phi = Angle("phi")  # phase (Mean anom) at t = 0

    n = 2 * np.pi * tt.exp(-logP) / yr

    t_periastron = pm.Deterministic("tPeri", (phi + omega) / n)
コード例 #7
0
ファイル: intro-to-pymc3.py プロジェクト: t-brandt/exoplanet
with pm.Model() as model:

    # Parameters
    logK = pm.Uniform(
        "logK",
        lower=0,
        upper=np.log(200),
        testval=np.log(0.5 * (np.max(rv) - np.min(rv))),
    )
    logP = pm.Uniform("logP",
                      lower=0,
                      upper=np.log(10),
                      testval=np.log(lit_period))
    phi = pm.Uniform("phi", lower=0, upper=2 * np.pi, testval=0.1)
    e = pm.Uniform("e", lower=0, upper=1, testval=0.1)
    w = Angle("w")
    logjitter = pm.Uniform("logjitter",
                           lower=-10,
                           upper=5,
                           testval=np.log(np.mean(rv_err)))
    rv0 = pm.Normal("rv0", mu=0.0, sd=10.0, testval=0.0)
    rvtrend = pm.Normal("rvtrend", mu=0.0, sd=10.0, testval=0.0)

    # Deterministic transformations
    n = 2 * np.pi * tt.exp(-logP)
    P = pm.Deterministic("P", tt.exp(logP))
    K = pm.Deterministic("K", tt.exp(logK))
    cosw = tt.cos(w)
    sinw = tt.sin(w)
    s2 = tt.exp(2 * logjitter)
    t0 = (phi + w) / n
コード例 #8
0
ファイル: sample_joint.py プロジェクト: iancze/TWA-3-orbit
    a_ang_inner = pm.Uniform("a_ang_inner", 0.1, 10.0,
                             testval=4.66)  # milliarcsec

    # the semi-major axis in au
    a_inner = pm.Deterministic("a_inner", 1e-3 * a_ang_inner / parallax)  # au

    logP_inner = pm.Uniform("logP_inner",
                            lower=0,
                            upper=np.log(50.0),
                            testval=np.log(34.879))  # days
    P_inner = pm.Deterministic("P_inner", tt.exp(logP_inner))

    e_inner = pm.Uniform("e_inner", lower=0, upper=1, testval=0.63)

    omega_inner = Angle("omega_inner", testval=1.42)  # omega_Aa
    Omega_inner = Angle("Omega_inner", testval=1.99)

    cos_incl_inner = pm.Uniform("cos_incl_inner",
                                lower=-1.0,
                                upper=1.0,
                                testval=0.67)
    incl_inner = pm.Deterministic("incl_inner", tt.arccos(cos_incl_inner))

    MAb = pm.Normal("MAb", mu=0.29, sd=0.5)  # solar masses

    t_periastron_inner = pm.Uniform("t_periastron_inner",
                                    lower=4050.0,
                                    upper=4100.0,
                                    testval=4073.0)  # + 2400000 + jd0
コード例 #9
0
                        upper=np.log(100),
                        testval=np.log(25))  # km/s

    KAa = pm.Deterministic("KAa", tt.exp(logKAa))
    KAb = pm.Deterministic("KAb", tt.exp(logKAb))

    logP = pm.Uniform("logP",
                      lower=np.log(20.0),
                      upper=np.log(50.0),
                      testval=np.log(34.87846))  # days

    P = pm.Deterministic("P", tt.exp(logP))

    e = pm.Uniform("e", lower=0, upper=1, testval=0.62)

    omega = Angle("omega", testval=80.5 * deg)  # omega_Aa

    gamma = pm.Uniform("gamma", lower=0, upper=20, testval=10.1)

    # relative to jd0
    t_periastron = pm.Uniform("tPeri",
                              lower=1130.0,
                              upper=1180.0,
                              testval=1159.0)  # + 2400000 days

    orbit = xo.orbits.KeplerianOrbit(period=P,
                                     ecc=e,
                                     t_periastron=t_periastron,
                                     omega=omega)

    # since we have 4 instruments, we need to predict 4 different dataseries