def lnlike_full(pars, t1, v1, v1_err, t2, v2, v2_err):
    K1, K2, P, T0, w, e, dv1, dv2, lnf = pars
    rv1_pred = get_rv(T0=T0, P=P, e=e, K1=K1, w=w, t=t1) + dv1
    rv2_pred = -get_rv(T0=T0, P=P, e=e, K1=K2, w=w, t=t2)
    
    inv_sigma2_1 = 1.0/v1_err**2
    inv_sigma2_2 = 1.0/(np.exp(lnf)*v2_err**2)
    s1 = np.nansum((rv1_pred - v1)**2 * inv_sigma2_1 - np.log(inv_sigma2_1))
    s2 = np.nansum((rv2_pred - (v2 - rv2_pred*K1/K2 - dv2))**2 * inv_sigma2_2 - np.log(inv_sigma2_2))
    #print(s1)
    #print(s2)
    return -0.5*(s1+s2)
def lnlike_full(pars, t1, v1, v1_err, t2, v2, v2_err):
    K1, K2, P, T0, w, e, dv1, dv2, gamma, lnf, noise1 = pars
    rv1_pred = get_rv(T0=T0, P=P, e=e, K1=K1, w=w, t=t1) + dv1 + gamma
    rv2_pred = -get_rv(T0=T0, P=P, e=e, K1=K2, w=w, t=t2)

    inv_sigma2_1 = 1.0 / (v1_err**2 + np.exp(noise1)**2)
    inv_sigma2_2 = 1.0 / (np.exp(lnf) * v2_err**2)
    s1 = np.nansum((rv1_pred - v1)**2 * inv_sigma2_1 - np.log(inv_sigma2_1 /
                                                              (2 * np.pi)))
    s2 = np.nansum((rv2_pred - (v2 - rv2_pred * K1 / K2 - dv2 - gamma))**2 *
                   inv_sigma2_2 - np.log(inv_sigma2_2 / (2 * np.pi)))
    # s2 = np.nansum((rv2_pred - (v2 - dv2))**2 * inv_sigma2_2 - np.log(inv_sigma2_2/(2*np.pi)))
    #print(s1)
    #print(s2)
    return -0.5 * (s1 + s2)
def fit_partial(T0, P, e, K1, w, t, rv2, rv2_err):
    """
    Get MCMC samples for the mass-ratio, velocity shift, and error scaling
    for the orbital parameters T0-w (fit by Stefano Meschiari)
    """
    # Get the predicted velocity of the primary at each time
    rv1_pred = get_rv(T0=T0, P=P, e=e, K1=K1, w=w * np.pi / 180, t=t)

    # Initialize MCMC sampler
    initial_pars = [0.47, -5.4, -3.6]
    ndim = len(initial_pars)
    nwalkers = 100
    p0 = emcee.utils.sample_ball(initial_pars,
                                 std=[1e-6] * ndim,
                                 size=nwalkers)
    sampler = emcee.EnsembleSampler(nwalkers,
                                    ndim,
                                    lnprob_partial,
                                    args=(rv2, rv2_err, rv1_pred),
                                    threads=2)

    # Run the sampler
    pos, lp, state = sampler.run_mcmc(p0, 1000)

    # Save the last 500 (we will just have to hope that the sampler sufficiently burns-in in 500 steps. That is true in tests I've done)
    samples = sampler.chain[:, 500:, :].reshape((-1, ndim))
    return samples
def lnlike_sb1(pars, t1, v1, v1_err):
    K1, P, T0, w, e, dv1 = pars
    rv1_pred = get_rv(T0=T0, P=P, e=e, K1=K1, w=w, t=t1) + dv1
    
    inv_sigma2_1 = 1.0/v1_err**2
    s1 = np.nansum((rv1_pred - v1)**2 * inv_sigma2_1 - np.log(inv_sigma2_1))

    return -0.5*s1
def lnlike_sb1(pars, t1, v1, v1_err):
    K1, P, T0, w, e, dv1 = pars
    rv1_pred = get_rv(T0=T0, P=P, e=e, K1=K1, w=w, t=t1) + dv1

    inv_sigma2_1 = 1.0 / v1_err**2
    s1 = np.nansum((rv1_pred - v1)**2 * inv_sigma2_1 - np.log(inv_sigma2_1))

    return -0.5 * s1
def fit_partial(T0, P, e, K1, w, t, rv2, rv2_err):
    """
    Get MCMC samples for the mass-ratio, velocity shift, and error scaling
    for the orbital parameters T0-w (fit by Stefano Meschiari)
    """
    # Get the predicted velocity of the primary at each time
    rv1_pred = get_rv(T0=T0, P=P, e=e, K1=K1, w=w*np.pi/180, t=t)

    # Initialize MCMC sampler
    initial_pars = [0.47, -5.4, -3.6]
    ndim = len(initial_pars)
    nwalkers = 100
    p0 = emcee.utils.sample_ball(initial_pars, std=[1e-6]*ndim, size=nwalkers)
    sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob_partial, args=(rv2, rv2_err, rv1_pred), threads=2)

    # Run the sampler
    pos, lp, state = sampler.run_mcmc(p0, 1000)

    # Save the last 500 (we will just have to hope that the sampler sufficiently burns-in in 500 steps. That is true in tests I've done)
    samples = sampler.chain[:, 500:, :].reshape((-1, ndim))
    return samples
def plot(pars, t1, v1, v1_err, t2, v2, v2_err, resids=True):
    K1, K2, P, T0, w, e, dv1, dv2, lnf, noise = pars
    rv1_pred = get_rv(T0=T0, P=P, e=e, K1=K1, w=w, t=t1)
    rv2_pred = -get_rv(T0=T0, P=P, e=e, K1=K2, w=w, t=t2)
    tplot = np.linspace(min(min(t1), min(t2)), max(max(t2), max(t2)), 100)
    rv1_plot = get_rv(T0=T0, P=P, e=e, K1=K1, w=w, t=tplot)
    rv2_plot = get_rv(T0=T0, P=P, e=e, K1=-K2, w=w, t=tplot)
    
    inv_sigma2_1 = 1.0/v1_err**2
    inv_sigma2_2 = 1.0/(np.exp(lnf)*v2_err**2)
    s1 = np.nansum((rv1_pred - (v1-dv1))**2 * inv_sigma2_1 - np.log(inv_sigma2_1))
    s2 = np.nansum((rv2_pred - (v2 - rv2_pred*K1/K2 - dv2))**2 * inv_sigma2_2 - np.log(inv_sigma2_2))
    
    def tick_formatter(x, pos):
        return "{:.0f}".format(x - 2450000)
    MyFormatter = FuncFormatter(tick_formatter)
    
    fig = plt.figure()
    if resids:
        gs = gridspec.GridSpec(5, 1)
        top = plt.subplot(gs[:3])
        resid1 = plt.subplot(gs[3], sharex=top)
        resid2 = plt.subplot(gs[4], sharex=top)
        fig.subplots_adjust(bottom=0.15, left=0.15, hspace=0.0)
        
        top.errorbar(t1, v1-dv1, yerr=np.sqrt(v1_err**2 + np.exp(noise)), fmt='r^', label='Primary')
        top.errorbar(t2, v2 - rv2_pred*K1/K2 - dv2, yerr=v2_err*np.exp(lnf/2.), fmt='ko', label='Secondary')
        top.plot(tplot, rv1_plot, 'r-', alpha=0.5)
        top.plot(tplot, rv2_plot, 'k-', alpha=0.5)
        
        resid1.scatter(t1, v1-dv1 - rv1_pred)
        resid1.plot(t1, np.zeros(len(t1)), 'r--')
        resid1.set_ylabel('O-C (rv1)')
        print('RMS scatter on primary = {:.3f} km/s'.format(np.std(v1-dv1-rv1_pred)))
        
        resid2.scatter(t2, v2 - rv2_pred*K1/K2 - dv2 - rv2_pred)
        resid2.plot(t2, np.zeros(len(t2)), 'r--')
        resid2.set_ylabel('O-C (rv2)')
        print('RMS scatter on secondary = {:.3f} km/s'.format(np.std(v2 - rv2_pred*K1/K2 - dv2 - rv2_pred)))

        top.axes.get_xaxis().set_visible(False)
        resid1.axes.get_xaxis().set_visible(False)
        
        resid2.set_xlabel('JD - 2450000')
        top.set_ylabel('RV (km/s)')
        leg = top.legend(loc='best', fancybox=True)
        
        top.xaxis.set_major_formatter(MyFormatter)

        axes = [top, resid1, resid2]

    else:
        ax = fig.add_subplot(111)
        ax.errorbar(t1, v1-dv1, yerr=v1_err, fmt='r^', label='Primary')
        ax.errorbar(t2, v2 - rv2_pred*K1/K2 - dv2, yerr=v2_err*np.exp(lnf/2.), fmt='ko', label='Secondary')
        ax.plot(tplot, rv1_plot, 'r-', alpha=0.5)
        ax.plot(tplot, rv2_plot, 'k-', alpha=0.5)

        ax.xaxis.set_major_formatter(MyFormatter)
        ax.set_xlabel('JD - 2450000')
        ax.set_ylabel('RV (km/s)')
        leg = ax.legend(loc='best', fancybox=True)

        axes = [ax]

    # Calculate chi-squared
    chi2 = (np.sum((v1-dv1 - rv1_pred)**2 / (v1_err**2 + np.exp(noise))) + 
           np.sum((v2 - rv2_pred*K1/K2 - dv2 - rv2_pred)**2 / (v2_err**2 * np.exp(lnf))))
    N = len(v1) + len(v2)
    print('X^2 = {:.2f}\nN = {}'.format(chi2, N))

    return fig, axes
def plot(pars, t1, v1, v1_err, t2, v2, v2_err, resids=True):
    K1, K2, P, T0, w, e, dv1, dv2, lnf, noise = pars
    rv1_pred = get_rv(T0=T0, P=P, e=e, K1=K1, w=w, t=t1)
    rv2_pred = -get_rv(T0=T0, P=P, e=e, K1=K2, w=w, t=t2)
    tplot = np.linspace(min(min(t1), min(t2)), max(max(t2), max(t2)), 100)
    rv1_plot = get_rv(T0=T0, P=P, e=e, K1=K1, w=w, t=tplot)
    rv2_plot = get_rv(T0=T0, P=P, e=e, K1=-K2, w=w, t=tplot)

    inv_sigma2_1 = 1.0 / v1_err**2
    inv_sigma2_2 = 1.0 / (np.exp(lnf) * v2_err**2)
    s1 = np.nansum((rv1_pred - (v1 - dv1))**2 * inv_sigma2_1 -
                   np.log(inv_sigma2_1))
    s2 = np.nansum((rv2_pred -
                    (v2 - rv2_pred * K1 / K2 - dv2))**2 * inv_sigma2_2 -
                   np.log(inv_sigma2_2))

    def tick_formatter(x, pos):
        return "{:.0f}".format(x - 2450000)

    MyFormatter = FuncFormatter(tick_formatter)

    fig = plt.figure()
    if resids:
        gs = gridspec.GridSpec(5, 1)
        top = plt.subplot(gs[:3])
        resid1 = plt.subplot(gs[3], sharex=top)
        resid2 = plt.subplot(gs[4], sharex=top)
        fig.subplots_adjust(bottom=0.15, left=0.15, hspace=0.0)

        top.errorbar(t1,
                     v1 - dv1,
                     yerr=np.sqrt(v1_err**2 + np.exp(noise)),
                     fmt='r^',
                     label='Primary')
        top.errorbar(t2,
                     v2 - rv2_pred * K1 / K2 - dv2,
                     yerr=v2_err * np.exp(lnf / 2.),
                     fmt='ko',
                     label='Secondary')
        top.plot(tplot, rv1_plot, 'r-', alpha=0.5)
        top.plot(tplot, rv2_plot, 'k-', alpha=0.5)

        resid1.scatter(t1, v1 - dv1 - rv1_pred)
        resid1.plot(t1, np.zeros(len(t1)), 'r--')
        resid1.set_ylabel('O-C (rv1)')
        print('RMS scatter on primary = {:.3f} km/s'.format(
            np.std(v1 - dv1 - rv1_pred)))

        resid2.scatter(t2, v2 - rv2_pred * K1 / K2 - dv2 - rv2_pred)
        resid2.plot(t2, np.zeros(len(t2)), 'r--')
        resid2.set_ylabel('O-C (rv2)')
        print('RMS scatter on secondary = {:.3f} km/s'.format(
            np.std(v2 - rv2_pred * K1 / K2 - dv2 - rv2_pred)))

        top.axes.get_xaxis().set_visible(False)
        resid1.axes.get_xaxis().set_visible(False)

        resid2.set_xlabel('JD - 2450000')
        top.set_ylabel('RV (km/s)')
        leg = top.legend(loc='best', fancybox=True)

        top.xaxis.set_major_formatter(MyFormatter)

        axes = [top, resid1, resid2]

    else:
        ax = fig.add_subplot(111)
        ax.errorbar(t1, v1 - dv1, yerr=v1_err, fmt='r^', label='Primary')
        ax.errorbar(t2,
                    v2 - rv2_pred * K1 / K2 - dv2,
                    yerr=v2_err * np.exp(lnf / 2.),
                    fmt='ko',
                    label='Secondary')
        ax.plot(tplot, rv1_plot, 'r-', alpha=0.5)
        ax.plot(tplot, rv2_plot, 'k-', alpha=0.5)

        ax.xaxis.set_major_formatter(MyFormatter)
        ax.set_xlabel('JD - 2450000')
        ax.set_ylabel('RV (km/s)')
        leg = ax.legend(loc='best', fancybox=True)

        axes = [ax]

    # Calculate chi-squared
    chi2 = (np.sum(
        (v1 - dv1 - rv1_pred)**2 / (v1_err**2 + np.exp(noise))) + np.sum(
            (v2 - rv2_pred * K1 / K2 - dv2 - rv2_pred)**2 /
            (v2_err**2 * np.exp(lnf))))
    N = len(v1) + len(v2)
    print('X^2 = {:.2f}\nN = {}'.format(chi2, N))

    return fig, axes