Example #1
0
def computation(correct, lowers, uppers):
    #Eq.8 L14
    P_Syn = 100
    tau_Syn = 0.4
    e_Syn = 0.5
    a_Syn = 1
    i_Syn = np.radians(60)
    w_Syn = np.radians(250)
    Omega_Syn = np.radians(120)
    T_Syn = tau_Syn * P_Syn 
    A_Syn, B_Syn, F_Syn, G_Syn = orbits.Thiele_Innes_from_Campbell(w_Syn, a_Syn, i_Syn, Omega_Syn)
    
    f_orb_Syn = 0.6
    num_obs_Syn = 15
    times_obs_Syn = np.zeros(num_obs_Syn)
    times_obs_Syn = f_orb_Syn*P_Syn*np.arange(num_obs_Syn)/(num_obs_Syn-1)
    
    ra_theo_Syn, dec_theo_Syn = orbits.keplerian_xy_Thiele_Innes(times_obs_Syn, A_Syn, B_Syn, F_Syn, G_Syn, T_Syn, e_Syn, P_Syn)
    err_size = 0.05*a_Syn
    ra_errs_Syn = err_size*np.ones(num_obs_Syn)
    dec_errs_Syn = err_size*np.ones(num_obs_Syn)
    
    x_errs = dec_errs_Syn
    y_errs = ra_errs_Syn
    times_obs = times_obs_Syn
    
    # Measured values:
    #c.f. Fantino & Casotto pg. 11
    lit_a = a_Syn
    lit_i = np.rad2deg(i_Syn)
    lit_T = T_Syn
    lit_e = e_Syn
    lit_P = P_Syn
    lit_Omega = np.rad2deg(Omega_Syn)
    lit_w = np.rad2deg(w_Syn)
        
    #Eq. 11 L14
    ra_obs_Syn = ra_theo_Syn + np.random.normal(0, ra_errs_Syn)
    dec_obs_Syn = dec_theo_Syn + np.random.normal(0, dec_errs_Syn)
    
    # Careful with our x-y coordinate system - not the same as RA-Dec!
    x_obs = dec_obs_Syn
    y_obs = ra_obs_Syn
    
    # Now that we have the data, find the best fit
    # orbit by searching over a range of parameters:
    
    # Get the start date of the data - we'll use
    # this to set what times of periastron we test:
    data_start = np.min(times_obs)
    
    # Set trial orbital elements over a range.
    # Careful specifying this number - the output grid is of size n**3
    # This takes about 5 seconds with n = 100; time should scale 
    # from there roughly as (5 seconds) * (n/100)**3
    n = 100
    
    # Call a routine to define a grid of search parameters. 
    # Default is to search all eccentricities and periastrons.  Periods
    # to search are passed as log(years), so 1 to 3 is periods of 10 to 
    # 1000 years, for example.  For this system, we have a better constraint 
    # on the period since we have most of the orbit. 
    
    e_max = 0.99
    
    logP_min = np.log10(P_Syn*f_orb_Syn)
    logP_max = np.log10(1000)
    P_array, e_array, T_array = orbits.grid_P_e_T(n, logP_min, logP_max, T_start=data_start, e_max=e_max)
    
    
    # This is the routine that really does the optimization, returning parameters for 
    # *all* the orbits it tries, and their chi-squares: 
    A_array, B_array, F_array, G_array, sigma_list, chi_squared = orbits.Thiele_Innes_optimal(times_obs, P_array, e_array, \
                                                                                      T_array, x_obs, y_obs, \
                                                                                      x_errs, y_errs, debug=False)
    
    # Now optimize the grid a bit - only keep values within the bounds that give 
    # delta chi squared less than 10 from the best fit found so far: 
    best_chi_squared = np.min(chi_squared)
    delta_chi_squared = 21.85
    
    good_inds = np.where((chi_squared - best_chi_squared) < delta_chi_squared)
    
    e_min = np.min(e_array[good_inds])
    e_max = np.max(e_array[good_inds])
    
    logP_min = np.log10(np.min(P_array[good_inds]))
    logP_max = np.log10(np.max(P_array[good_inds]))
    
    tau_min = np.min((T_array[good_inds] - data_start)/P_array[good_inds])
    tau_max = np.max((T_array[good_inds] - data_start)/P_array[good_inds])
    
    # Now regrid with these bounds, and run grid search again: 
    P_array, e_array, T_array = orbits.grid_P_e_T(n, logP_min, logP_max, e_min, e_max, \
                                                      tau_min, tau_max, T_start=data_start)
    A_array, B_array, F_array, G_array, sigma_list, chi_squared = orbits.Thiele_Innes_optimal(times_obs, P_array, e_array, \
                                                                                      T_array, x_obs, y_obs, \
                                                                                      x_errs, y_errs, debug=False)
    
    # Then take these and get the other orbital parameters, too: 
    w_array, a_array, i_array, Omega_array = orbits.Campbell_from_Thiele_Innes(A_array, B_array, F_array, G_array)
        
    # Now get a more refined version of the mass posterior: 
    # Resample the above grid by an extra factor of N, following 
    # method in Lucy 2014B:
    
    N = 50
    
    w_N, a_N, i_N, T_N, e_N, P_N, Omega_N, new_likelihood, script_ABFG = orbits.correct_orbit_likelihood(\
                                                                                            P_array, e_array, \
                                                                                            T_array, A_array, \
                                                                                            B_array, F_array, \
                                                                                            G_array, sigma_list,\
                                                                                            chi_squared, N)
        
        
    # Get the credible interval for the semimajor axis: 
    a_mean, a_low, a_high = orbits.credible_interval(a_N, new_likelihood)
    
    # Get the credible interval for the inclination: 
    i_mean, i_low, i_high = orbits.credible_interval(i_N, new_likelihood)
    
    # Get the credible interval for the time of periastron passage: 
    T_mean, T_low, T_high = orbits.credible_interval(T_N, new_likelihood)
    
    # Get the credible interval for the semimajor axis: 
    e_mean, e_low, e_high = orbits.credible_interval(e_N, new_likelihood)
    
    # Get the credible interval for the period: 
    P_mean, P_low, P_high = orbits.credible_interval(P_N, new_likelihood)
    
    # Get the credible interval for the position angle of ascending node: 
    Omega_mean, Omega_low, Omega_high = orbits.credible_interval(Omega_N, new_likelihood)
    
    #Taking care of Omega offset that occurs in conversion to campbell elements
    if (Omega_Syn < 0):
        Omega_mean -= np.pi
        Omega_low -= np.pi
        Omega_high -= np.pi
    elif(Omega_Syn > np.pi):
        Omega_mean += np.pi
        Omega_low += np.pi
        Omega_high += np.pi
        
    # Get the credible interval for the longitude of periastron: 
    w_mean, w_low, w_high = orbits.credible_interval(w_N, new_likelihood)
    
    #Taking care of w offset that occurs in conversion to campbell elements
    if (Omega_Syn < 0):
        w_mean -= np.pi
        w_low -= np.pi
        w_high -= np.pi
    elif(Omega_Syn > np.pi):
        w_mean += np.pi
        w_low += np.pi
        w_high += np.pi
    
    #Returning to degrees
    w_mean = np.rad2deg(w_mean)
    w_low = np.rad2deg(w_low)
    w_high = np.rad2deg(w_high)
    
    Omega_mean = np.rad2deg(Omega_mean)
    Omega_low = np.rad2deg(Omega_low)
    Omega_high = np.rad2deg(Omega_high)
    
    i_mean = np.rad2deg(i_mean)
    i_low = np.rad2deg(i_low)
    i_high = np.rad2deg(i_high)
    
    #Comparison with true values
    #Remembering standard output of P, T, e, a, i, w, Omega
    if (lit_P > P_low and lit_P < P_high):
        correct[0] = 1    
    if (lit_T > T_low and lit_T < T_high):
        correct[1] = 1
    if (lit_e > e_low and lit_e < e_high):
        correct[2] = 1
    if (lit_a > a_low and lit_a < a_high):
        correct[3] = 1
    if (lit_i > i_low and lit_i < i_high):
        correct[4] = 1  
    if (lit_w > w_low and lit_w < w_high):
        correct[5] = 1  
    if (lit_Omega > Omega_low and lit_Omega < Omega_high):
        correct[6] = 1


    #Remembering standard output of P, T, e, a, i, w, Omega
    uppers[0] = P_high
    lowers[0] = P_low
    uppers[1] = T_high
    lowers[1] = T_low
    uppers[2] = e_high
    lowers[2] = e_low
    uppers[3] = a_high
    lowers[3] = a_low
    uppers[4] = i_high
    lowers[4] = i_low
    uppers[5] = w_high
    lowers[5] = w_low
    uppers[6] = Omega_high
    lowers[6] = Omega_low
def main():
    
    num_iters = int(input("Number of iterations: "))
    print_every = int(input("Checkpoint amount of iterations: "))
    iter_correct_a = 0
    iter_correct_e = 0
    iter_correct_i = 0
    iter_correct_P = 0
    #iter_correct_T = 0
    iter_correct_Omega = 0
    iter_correct_w = 0
    iters_comp = 0
    runtimes = np.zeros(num_iters)
    a_uppers = np.zeros(num_iters)
    a_lowers = np.zeros(num_iters)
    w_uppers = np.zeros(num_iters)
    w_lowers = np.zeros(num_iters)
    i_uppers = np.zeros(num_iters)
    i_lowers = np.zeros(num_iters)
    T_uppers = np.zeros(num_iters)
    T_lowers = np.zeros(num_iters)
    P_uppers = np.zeros(num_iters)
    P_lowers = np.zeros(num_iters)
    e_uppers = np.zeros(num_iters)
    e_lowers = np.zeros(num_iters)
    Omega_uppers = np.zeros(num_iters)
    Omega_lowers = np.zeros(num_iters)
    
    # Read in orbital data, which we have saved in a file. 
    # Positions are in milliarcsecond units.  Different conversions
    # might be needed if your data are in different units.
    datafile = "SDSS_J1052.txt"
    t = Table.read(datafile, format='ascii.commented_header')
    
    # Convert the position angle and separation to RA and Dec separation: 
    ra_obs, dec_obs, ra_errs, dec_errs = orbits.rho_PA_to_RA_Dec( t['rho'],t['PA'], \
                                                                      t['rho_err'], t['PA_err'])
    
    x_errs = dec_errs
    y_errs = ra_errs
    # Code below assumes dates in years.  Convert if necessary. 
    times_obs = t['Date']
    
    # Measured values:
    #c.f. Dupuy et al.
    lit_a = 70.59
    lit_i = 62
    #No lit_T as Dupuy et al. doesn't specify one to test against 
    lit_e = 0.1387
    lit_P = 8.614
    lit_Omega = 126.7
    lit_w = 186.5
    
    for k in range(num_iters):
        if(iters_comp % print_every == 0 and iters_comp != 0):
            print("Most recent credibility interval guesses: ")
            print("--------------------------------------------------")
            print("Period (P): %0.3f to %0.3f years" %(P_low, P_high))
            print()
            print("Time of periastron passage (T): %0.3f to %0.3f years" %(T_low, T_high))
            print()
            print("Eccentricity (e): %0.3f to %0.3f" %(e_low, e_high))
            print()
            print("Semi major axis (a): %0.3f to %0.3f arcseconds" %(a_low, a_high))
            print()
            print("Inclination (i): %0.3f to %0.3f degrees" %(i_low, i_high))
            print()
            print("Longitude of periastron (w): %0.3f to %0.3f degrees" %(w_low, w_high))
            print()
            print("Position angle of ascending node (Omega): %0.3f to %0.3f degrees" %(Omega_low, Omega_high))
            print("--------------------------------------------------")
            print()
            cov_frac_P = iter_correct_P/iters_comp
            print("Coverage fraction for period (P) stands at %0.3f over %d runs" %(cov_frac_P, iters_comp))
            print()
            #cov_frac_T = iter_correct_T/iters_comp
            #print("Coverage fraction for time of periastron passage (T) stands at %0.3f over %d runs" %(cov_frac_T, iters_comp))
            #print()
            cov_frac_e = iter_correct_e/iters_comp
            print("Coverage fraction for eccentricity (e) stands at %0.3f over %d runs" %(cov_frac_e, iters_comp))
            print()
            cov_frac_a = iter_correct_a/iters_comp
            print("Coverage fraction for semi major axis (a) stands at %0.3f over %d runs" %(cov_frac_a, iters_comp))
            print()
            cov_frac_i = iter_correct_i/iters_comp
            print("Coverage fraction for inclination (i) stands at %0.3f over %d runs" %(cov_frac_i, iters_comp))
            print()
            cov_frac_w = iter_correct_w/iters_comp
            print("Coverage fraction for longitude of periastron (w) stands at %0.3f over %d runs" %(cov_frac_w, iters_comp))
            print()
            cov_frac_Omega = iter_correct_Omega/iters_comp
            print("Coverage fraction for position angle of ascending node (Omega) stands at %0.3f over %d runs" %(cov_frac_Omega, iters_comp))
            print()
            avg_runtime = np.mean(runtimes[:k])
            print("The average runtime of one iteration stands at %0.3f seconds after %d runs" %(avg_runtime, iters_comp))
            print("--------------------------------------------------")
            print()
        
        overall_start_time = Time.time()
                
        # Careful with our x-y coordinate system - not the same as RA-Dec!
        x_obs = dec_obs + np.random.normal(0, abs(dec_errs))
        y_obs = ra_obs + np.random.normal(0, abs(ra_errs))

        # Now that we have the data, find the best fit
        # orbit by searching over a range of parameters:
        
        # Get the start date of the data - we'll use
        # this to set what times of periastron we test:
        data_start = np.min(times_obs)
    
        # Set trial orbital elements over a range.
        # Careful specifying this number - the output grid is of size n**3
        # This takes about 5 seconds with n = 100; time should scale 
        # from there roughly as (5 seconds) * (n/100)**3
        n = 100
    
        # Call a routine to define a grid of search parameters. 
        # Default is to search all eccentricities and periastrons.  Periods
        # to search are passed as log(years), so 1 to 3 is periods of 10 to 
        # 1000 years, for example.  For this system, we have a better constraint 
        # on the period since we have most of the orbit. 
    
        e_max = 0.99
    
        logP_min = np.log10(5)
        logP_max = np.log10(10)
        P_array, e_array, T_array = orbits.grid_P_e_T(n, logP_min, logP_max, T_start=data_start, e_max=e_max)
    
    
        # This is the routine that really does the optimization, returning parameters for 
        # *all* the orbits it tries, and their chi-squares: 
        A_array, B_array, F_array, G_array, sigma_list, chi_squared = orbits.Thiele_Innes_optimal(times_obs, P_array, e_array, \
                                                                                      T_array, x_obs, y_obs, \
                                                                                      x_errs, y_errs, debug=False)
    
        # Now optimize the grid a bit - only keep values within the bounds that give 
        # delta chi squared less than 10 from the best fit found so far: 
        best_chi_squared = np.min(chi_squared)
        delta_chi_squared = 10
    
        good_inds = np.where((chi_squared - best_chi_squared) < delta_chi_squared)
    
        e_min = np.min(e_array[good_inds])
        e_max = np.max(e_array[good_inds])
    
        logP_min = np.log10(np.min(P_array[good_inds]))
        logP_max = np.log10(np.max(P_array[good_inds]))
    
        tau_min = np.min((T_array[good_inds] - data_start)/P_array[good_inds])
        tau_max = np.max((T_array[good_inds] - data_start)/P_array[good_inds])
    
        # Now regrid with these bounds, and run grid search again: 
        P_array, e_array, T_array = orbits.grid_P_e_T(n, logP_min, logP_max, e_min, e_max, \
                                                      tau_min, tau_max, T_start=data_start)
        A_array, B_array, F_array, G_array, sigma_list, chi_squared = orbits.Thiele_Innes_optimal(times_obs, P_array, e_array, \
                                                                                      T_array, x_obs, y_obs, \
                                                                                      x_errs, y_errs, debug=False)
    
        # Then take these and get the other orbital parameters, too: 
        w_array, a_array, i_array, Omega_array = orbits.Campbell_from_Thiele_Innes(A_array, B_array, F_array, G_array)
    
        # Now get a more refined version of the mass posterior: 
        # Resample the above grid by an extra factor of N, following 
        # method in Lucy 2014B:
    
        N = 20
    
        w_N, a_N, i_N, T_N, e_N, P_N, Omega_N, new_likelihood, script_ABFG = orbits.correct_orbit_likelihood(\
                                                                                            P_array, e_array, \
                                                                                            T_array, A_array, \
                                                                                            B_array, F_array, \
                                                                                            G_array, sigma_list,\
                                                                                            chi_squared, N)
        
        
        # Get the credible interval for the semimajor axis: 
        a_mean, a_low, a_high = orbits.credible_interval(a_N, new_likelihood)
        
        # Get the credible interval for the inclination: 
        i_mean, i_low, i_high = orbits.credible_interval(i_N, new_likelihood)
        
        # Get the credible interval for the time of periastron passage: 
        T_mean, T_low, T_high = orbits.credible_interval(T_N, new_likelihood)
        
        # Get the credible interval for the semimajor axis: 
        e_mean, e_low, e_high = orbits.credible_interval(e_N, new_likelihood)
        
        # Get the credible interval for the period: 
        P_mean, P_low, P_high = orbits.credible_interval(P_N, new_likelihood)
        
        # Get the credible interval for the position angle of ascending node: 
        Omega_mean, Omega_low, Omega_high = orbits.credible_interval(Omega_N, new_likelihood)

        # Get the credible interval for the longitude of periastron: 
        w_mean, w_low, w_high = orbits.credible_interval(w_N, new_likelihood)
        
        #Returning to degrees
        w_mean = np.rad2deg(w_mean)
        w_low = np.rad2deg(w_low)
        w_high = np.rad2deg(w_high)
        
        Omega_mean = np.rad2deg(Omega_mean)
        Omega_low = np.rad2deg(Omega_low)
        Omega_high = np.rad2deg(Omega_high)
        
        i_mean = np.rad2deg(i_mean)
        i_low = np.rad2deg(i_low)
        i_high = np.rad2deg(i_high)
        
        #Comparison with true values
        if (lit_a > a_low and lit_a < a_high):
            iter_correct_a += 1    
        if (lit_i > i_low and lit_i < i_high):
            iter_correct_i += 1    
        #if (lit_T > T_low and lit_T < T_high):
            #iter_correct_T += 1    
        if (lit_e > e_low and lit_e < e_high):
            iter_correct_e += 1    
        if (lit_P > P_low and lit_P < P_high):
            iter_correct_P += 1    
        if (lit_Omega > Omega_low and lit_Omega < Omega_high):
            iter_correct_Omega += 1    
        if (lit_w > w_low and lit_w < w_high):
            iter_correct_w += 1
        
        end_time = Time.time()
        runtimes[k] = end_time - overall_start_time
        a_uppers[k] = a_high
        a_lowers[k] = a_low
        w_uppers[k] = w_high
        w_lowers[k] = w_low
        i_uppers[k] = i_high
        i_lowers[k] = i_low
        T_uppers[k] = T_high
        T_lowers[k] = T_low
        P_uppers[k] = P_high
        P_lowers[k] = P_low
        e_uppers[k] = e_high
        e_lowers[k] = e_low
        Omega_uppers[k] = Omega_high
        Omega_lowers[k] = Omega_low
        
        iters_comp += 1
    
    cov_frac_P = iter_correct_P/num_iters
    print("Coverage fraction for period (P) stands at %0.3f over %d runs" %(cov_frac_P, num_iters))
    print()
    #cov_frac_T = iter_correct_T/num_iters
    #print("Coverage fraction for time of periastron passage (T) stands at %0.3f over %d runs" %(cov_frac_T, num_iters))
    #print()
    cov_frac_e = iter_correct_e/num_iters
    print("Coverage fraction for eccentricity (e) stands at %0.3f over %d runs" %(cov_frac_e, num_iters))
    print()
    cov_frac_a = iter_correct_a/num_iters
    print("Coverage fraction for semi major axis (a) stands at %0.3f over %d runs" %(cov_frac_a, num_iters))
    print()
    cov_frac_i = iter_correct_i/num_iters
    print("Coverage fraction for inclination (i) stands at %0.3f over %d runs" %(cov_frac_i, num_iters))
    print()
    cov_frac_w = iter_correct_w/num_iters
    print("Coverage fraction for longitude of periastron (w) stands at %0.3f over %d runs" %(cov_frac_w, num_iters))
    print()
    cov_frac_Omega = iter_correct_Omega/num_iters
    print("Coverage fraction for position angle of ascending node (Omega) stands at %0.3f over %d runs" %(cov_frac_Omega, num_iters))
    print()
    avg_runtime = np.mean(runtimes[:k])
    print("The average runtime of one iteration stands at %0.3f seconds after %d runs" %(avg_runtime, num_iters))
    print("--------------------------------------------------")
    print()
    
    P_range = np.vstack((P_lowers, P_uppers)).T
    T_range = np.vstack((T_lowers, T_uppers)).T
    e_range = np.vstack((e_lowers, e_uppers)).T
    a_range = np.vstack((a_lowers, a_uppers)).T
    i_range = np.vstack((i_lowers, i_uppers)).T
    w_range = np.vstack((w_lowers, w_uppers)).T
    Omega_range = np.vstack((Omega_lowers, Omega_uppers)).T
    
    np.savetxt("/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/P_Intervals_J1052.txt", P_range, fmt="%s")
    np.savetxt("/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/T_Intervals_J1052.txt", T_range, fmt="%s")
    np.savetxt("/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/e_Intervals_J1052.txt", e_range, fmt="%s")
    np.savetxt("/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/a_Intervals_J1052.txt", a_range, fmt="%s")
    np.savetxt("/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/i_Intervals_J1052.txt", i_range, fmt="%s")
    np.savetxt("/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/w_Intervals_J1052.txt", w_range, fmt="%s")
    np.savetxt("/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/Omega_Intervals_J1052.txt", Omega_range, fmt="%s")
    
    P_unit = "years"
    P_name = "period"
    print_min_max_avg(P_lowers, P_uppers, num_iters, P_name, P_unit)
    
    T_unit = "years"
    T_name = "time of periastron passage"
    print_min_max_avg(T_lowers, T_uppers, num_iters, T_name, T_unit)
    
    e_name = "eccentricity"
    print_min_max_avg(e_lowers, e_uppers, num_iters, e_name)
    
    a_unit = "arcseconds"
    a_name = "semi-major axis"
    print_min_max_avg(a_lowers, a_uppers, num_iters, a_name, a_unit)
    
    i_unit = "degrees"
    i_name = "inclination"
    print_min_max_avg(i_lowers, i_uppers, num_iters, i_name, i_unit)
    
    w_unit = "degrees"
    w_name = "longitude of periastron"
    print_min_max_avg(w_lowers, w_uppers, num_iters, w_name, w_unit)
    
    Omega_unit = "degrees"
    Omega_name = "position angle of ascending node"
    print_min_max_avg(Omega_lowers, Omega_uppers, num_iters, Omega_name, Omega_unit)
def main():

    num_iters = int(input("Number of iterations: "))
    print_every = int(input("Checkpoint amount of iterations: "))
    iter_correct_a = 0
    iter_correct_e = 0
    iter_correct_i = 0
    iter_correct_P = 0
    iter_correct_T = 0
    iter_correct_Omega = 0
    iter_correct_w = 0
    iters_comp = 0
    runtimes = np.zeros(num_iters)
    a_uppers = np.zeros(num_iters)
    a_lowers = np.zeros(num_iters)
    w_uppers = np.zeros(num_iters)
    w_lowers = np.zeros(num_iters)
    i_uppers = np.zeros(num_iters)
    i_lowers = np.zeros(num_iters)
    T_uppers = np.zeros(num_iters)
    T_lowers = np.zeros(num_iters)
    P_uppers = np.zeros(num_iters)
    P_lowers = np.zeros(num_iters)
    e_uppers = np.zeros(num_iters)
    e_lowers = np.zeros(num_iters)
    Omega_uppers = np.zeros(num_iters)
    Omega_lowers = np.zeros(num_iters)

    #Eq.8 L14
    P_Syn = 100
    tau_Syn = 0.4
    e_Syn = 0.5
    a_Syn = 1
    i_Syn = np.radians(60)
    w_Syn = np.radians(250)
    Omega_Syn = np.radians(120)
    T_Syn = tau_Syn * P_Syn
    A_Syn, B_Syn, F_Syn, G_Syn = orbits.Thiele_Innes_from_Campbell(
        w_Syn, a_Syn, i_Syn, Omega_Syn)

    f_orb_Syn = 0.6
    num_obs_Syn = 15
    times_obs_Syn = np.zeros(num_obs_Syn)
    times_obs_Syn = f_orb_Syn * P_Syn * np.arange(num_obs_Syn) / (num_obs_Syn -
                                                                  1)

    ra_theo_Syn, dec_theo_Syn = orbits.keplerian_xy_Thiele_Innes(
        times_obs_Syn, A_Syn, B_Syn, F_Syn, G_Syn, T_Syn, e_Syn, P_Syn)
    err_size = 0.05 * a_Syn
    ra_errs_Syn = err_size * np.ones(num_obs_Syn)
    dec_errs_Syn = err_size * np.ones(num_obs_Syn)

    x_errs = dec_errs_Syn
    y_errs = ra_errs_Syn
    times_obs = times_obs_Syn

    # Measured values:
    #c.f. Fantino & Casotto pg. 11
    lit_a = a_Syn
    lit_i = np.rad2deg(i_Syn)
    lit_T = T_Syn
    lit_e = e_Syn
    lit_P = P_Syn
    lit_Omega = np.rad2deg(Omega_Syn)
    lit_w = np.rad2deg(w_Syn)

    for k in range(num_iters):
        if (iters_comp % print_every == 0 and iters_comp != 0):
            print("Most recent credibility interval guesses: ")
            print("--------------------------------------------------")
            print("Period (P): %0.3f to %0.3f years" % (P_low, P_high))
            print()
            print("Time of periastron passage (T): %0.3f to %0.3f years" %
                  (T_low, T_high))
            print()
            print("Eccentricity (e): %0.3f to %0.3f" % (e_low, e_high))
            print()
            print("Semi major axis (a): %0.3f to %0.3f arcseconds" %
                  (a_low, a_high))
            print()
            print("Inclination (i): %0.3f to %0.3f degrees" % (i_low, i_high))
            print()
            print("Longitude of periastron (w): %0.3f to %0.3f degrees" %
                  (w_low, w_high))
            print()
            print(
                "Position angle of ascending node (Omega): %0.3f to %0.3f degrees"
                % (Omega_low, Omega_high))
            print("--------------------------------------------------")
            print()
            cov_frac_P = iter_correct_P / iters_comp
            print(
                "Coverage fraction for period (P) stands at %0.3f over %d runs"
                % (cov_frac_P, iters_comp))
            print()
            cov_frac_T = iter_correct_T / iters_comp
            print(
                "Coverage fraction for time of periastron passage (T) stands at %0.3f over %d runs"
                % (cov_frac_T, iters_comp))
            print()
            cov_frac_e = iter_correct_e / iters_comp
            print(
                "Coverage fraction for eccentricity (e) stands at %0.3f over %d runs"
                % (cov_frac_e, iters_comp))
            print()
            cov_frac_a = iter_correct_a / iters_comp
            print(
                "Coverage fraction for semi major axis (a) stands at %0.3f over %d runs"
                % (cov_frac_a, iters_comp))
            print()
            cov_frac_i = iter_correct_i / iters_comp
            print(
                "Coverage fraction for inclination (i) stands at %0.3f over %d runs"
                % (cov_frac_i, iters_comp))
            print()
            cov_frac_w = iter_correct_w / iters_comp
            print(
                "Coverage fraction for longitude of periastron (w) stands at %0.3f over %d runs"
                % (cov_frac_w, iters_comp))
            print()
            cov_frac_Omega = iter_correct_Omega / iters_comp
            print(
                "Coverage fraction for position angle of ascending node (Omega) stands at %0.3f over %d runs"
                % (cov_frac_Omega, iters_comp))
            print()
            avg_runtime = np.mean(runtimes[:k])
            print(
                "The average runtime of one iteration stands at %0.3f seconds after %d runs"
                % (avg_runtime, iters_comp))
            print("--------------------------------------------------")
            print()

        #Eq. 11 L14
        ra_obs_Syn = ra_theo_Syn + np.random.normal(0, ra_errs_Syn)
        dec_obs_Syn = dec_theo_Syn + np.random.normal(0, dec_errs_Syn)

        overall_start_time = Time.time()

        # Careful with our x-y coordinate system - not the same as RA-Dec!
        x_obs = dec_obs_Syn
        y_obs = ra_obs_Syn

        # Now that we have the data, find the best fit
        # orbit by searching over a range of parameters:

        # Get the start date of the data - we'll use
        # this to set what times of periastron we test:
        data_start = np.min(times_obs)

        # Set trial orbital elements over a range.
        # Careful specifying this number - the output grid is of size n**3
        # This takes about 5 seconds with n = 100; time should scale
        # from there roughly as (5 seconds) * (n/100)**3
        n = 100

        # Call a routine to define a grid of search parameters.
        # Default is to search all eccentricities and periastrons.  Periods
        # to search are passed as log(years), so 1 to 3 is periods of 10 to
        # 1000 years, for example.  For this system, we have a better constraint
        # on the period since we have most of the orbit.

        e_max = 0.99

        logP_min = np.log10(f_orb_Syn * P_Syn)
        logP_max = np.log10(1000)
        P_array, e_array, T_array = orbits.grid_P_e_T(n,
                                                      logP_min,
                                                      logP_max,
                                                      T_start=data_start,
                                                      e_max=e_max)

        # This is the routine that really does the optimization, returning parameters for
        # *all* the orbits it tries, and their chi-squares:
        A_array, B_array, F_array, G_array, sigma_list, chi_squared = orbits.Thiele_Innes_optimal(times_obs, P_array, e_array, \
                                                                                      T_array, x_obs, y_obs, \
                                                                                      x_errs=x_errs, y_errs=y_errs, debug=False)

        # Now optimize the grid a bit - only keep values within the bounds that give
        # delta chi squared less than 10 from the best fit found so far:
        best_chi_squared = np.min(chi_squared)
        delta_chi_squared = 21.85

        good_inds = np.where(
            (chi_squared - best_chi_squared) < delta_chi_squared)

        e_min = np.min(e_array[good_inds])
        e_max = np.max(e_array[good_inds])

        logP_min = np.log10(np.min(P_array[good_inds]))
        logP_max = np.log10(np.max(P_array[good_inds]))

        tau_min = np.min(
            (T_array[good_inds] - data_start) / P_array[good_inds])
        tau_max = np.max(
            (T_array[good_inds] - data_start) / P_array[good_inds])

        # Now regrid with these bounds, and run grid search again:
        P_array, e_array, T_array = orbits.grid_P_e_T(n, logP_min, logP_max, e_min, e_max, \
                                                      tau_min, tau_max, T_start=data_start)
        A_array, B_array, F_array, G_array, sigma_list, chi_squared = orbits.Thiele_Innes_optimal(times_obs, P_array, e_array, \
                                                                                      T_array, x_obs, y_obs, \
                                                                                      x_errs=x_errs, y_errs=y_errs, debug=False)

        # Then take these and get the other orbital parameters, too:
        w_array, a_array, i_array, Omega_array = orbits.Campbell_from_Thiele_Innes(
            A_array, B_array, F_array, G_array)

        # Now get a more refined version of the mass posterior:
        # Resample the above grid by an extra factor of N, following
        # method in Lucy 2014B:

        N = 50

        w_N, a_N, i_N, T_N, e_N, P_N, Omega_N, new_likelihood, script_ABFG = orbits.correct_orbit_likelihood(\
                                                                                            P_array, e_array, \
                                                                                            T_array, A_array, \
                                                                                            B_array, F_array, \
                                                                                            G_array, sigma_list,\
                                                                                            chi_squared, N)

        # Get the credible interval for the semimajor axis:
        a_mean, a_low, a_high = orbits.credible_interval(a_N, new_likelihood)

        # Get the credible interval for the inclination:
        i_mean, i_low, i_high = orbits.credible_interval(i_N, new_likelihood)

        # Get the credible interval for the time of periastron passage:
        T_mean, T_low, T_high = orbits.credible_interval(T_N, new_likelihood)

        # Get the credible interval for the semimajor axis:
        e_mean, e_low, e_high = orbits.credible_interval(e_N, new_likelihood)

        # Get the credible interval for the period:
        P_mean, P_low, P_high = orbits.credible_interval(P_N, new_likelihood)

        # Get the credible interval for the position angle of ascending node:
        Omega_mean, Omega_low, Omega_high = orbits.credible_interval(
            Omega_N, new_likelihood)

        #Taking care of Omega offset that occurs in conversion to campbell elements
        if (Omega_Syn < 0):
            Omega_mean -= np.pi
            Omega_low -= np.pi
            Omega_high -= np.pi
        elif (Omega_Syn > np.pi):
            Omega_mean += np.pi
            Omega_low += np.pi
            Omega_high += np.pi

        # Get the credible interval for the longitude of periastron:
        w_mean, w_low, w_high = orbits.credible_interval(w_N, new_likelihood)

        #Taking care of w offset that occurs in conversion to campbell elements
        if (Omega_Syn < 0):
            w_mean -= np.pi
            w_low -= np.pi
            w_high -= np.pi
        elif (Omega_Syn > np.pi):
            w_mean += np.pi
            w_low += np.pi
            w_high += np.pi

        #Returning to degrees
        w_mean = np.rad2deg(w_mean)
        w_low = np.rad2deg(w_low)
        w_high = np.rad2deg(w_high)

        Omega_mean = np.rad2deg(Omega_mean)
        Omega_low = np.rad2deg(Omega_low)
        Omega_high = np.rad2deg(Omega_high)

        i_mean = np.rad2deg(i_mean)
        i_low = np.rad2deg(i_low)
        i_high = np.rad2deg(i_high)

        #Comparison with true values
        if (lit_a > a_low and lit_a < a_high):
            iter_correct_a += 1
        if (lit_i > i_low and lit_i < i_high):
            iter_correct_i += 1
        if (lit_T > T_low and lit_T < T_high):
            iter_correct_T += 1
        if (lit_e > e_low and lit_e < e_high):
            iter_correct_e += 1
        if (lit_P > P_low and lit_P < P_high):
            iter_correct_P += 1
        if (lit_Omega > Omega_low and lit_Omega < Omega_high):
            iter_correct_Omega += 1
        if (lit_w > w_low and lit_w < w_high):
            iter_correct_w += 1

        end_time = Time.time()
        runtimes[k] = end_time - overall_start_time
        a_uppers[k] = a_high
        a_lowers[k] = a_low
        w_uppers[k] = w_high
        w_lowers[k] = w_low
        i_uppers[k] = i_high
        i_lowers[k] = i_low
        T_uppers[k] = T_high
        T_lowers[k] = T_low
        P_uppers[k] = P_high
        P_lowers[k] = P_low
        e_uppers[k] = e_high
        e_lowers[k] = e_low
        Omega_uppers[k] = Omega_high
        Omega_lowers[k] = Omega_low

        iters_comp += 1

    cov_frac_P = iter_correct_P / num_iters
    print("Coverage fraction for period (P) stands at %0.3f over %d runs" %
          (cov_frac_P, num_iters))
    print()
    cov_frac_T = iter_correct_T / num_iters
    print(
        "Coverage fraction for time of periastron passage (T) stands at %0.3f over %d runs"
        % (cov_frac_T, num_iters))
    print()
    cov_frac_e = iter_correct_e / num_iters
    print(
        "Coverage fraction for eccentricity (e) stands at %0.3f over %d runs" %
        (cov_frac_e, num_iters))
    print()
    cov_frac_a = iter_correct_a / num_iters
    print(
        "Coverage fraction for semi major axis (a) stands at %0.3f over %d runs"
        % (cov_frac_a, num_iters))
    print()
    cov_frac_i = iter_correct_i / num_iters
    print(
        "Coverage fraction for inclination (i) stands at %0.3f over %d runs" %
        (cov_frac_i, num_iters))
    print()
    cov_frac_w = iter_correct_w / num_iters
    print(
        "Coverage fraction for longitude of periastron (w) stands at %0.3f over %d runs"
        % (cov_frac_w, num_iters))
    print()
    cov_frac_Omega = iter_correct_Omega / num_iters
    print(
        "Coverage fraction for position angle of ascending node (Omega) stands at %0.3f over %d runs"
        % (cov_frac_Omega, num_iters))
    print()
    avg_runtime = np.mean(runtimes[:k])
    print(
        "The average runtime of one iteration stands at %0.3f seconds after %d runs"
        % (avg_runtime, num_iters))
    print("--------------------------------------------------")
    print()

    P_range = np.vstack((P_lowers, P_uppers)).T
    T_range = np.vstack((T_lowers, T_uppers)).T
    e_range = np.vstack((e_lowers, e_uppers)).T
    a_range = np.vstack((a_lowers, a_uppers)).T
    i_range = np.vstack((i_lowers, i_uppers)).T
    w_range = np.vstack((w_lowers, w_uppers)).T
    Omega_range = np.vstack((Omega_lowers, Omega_uppers)).T

    np.savetxt(
        "/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/P_Intervals_Synthetic_68.3.txt",
        P_range,
        fmt="%s")
    np.savetxt(
        "/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/T_Intervals_Synthetic_68.3.txt",
        T_range,
        fmt="%s")
    np.savetxt(
        "/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/e_Intervals_Synthetic_68.3.txt",
        e_range,
        fmt="%s")
    np.savetxt(
        "/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/a_Intervals_Synthetic_68.3.txt",
        a_range,
        fmt="%s")
    np.savetxt(
        "/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/i_Intervals_Synthetic_68.3.txt",
        i_range,
        fmt="%s")
    np.savetxt(
        "/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/w_Intervals_Synthetic_68.3.txt",
        w_range,
        fmt="%s")
    np.savetxt(
        "/Users/ssheppa1/Documents/Notebooks/Fit_Synthetic/Intervals/Omega_Intervals_Synthetic_68.3.txt",
        Omega_range,
        fmt="%s")

    P_unit = "years"
    P_name = "period"
    print_min_max_avg(P_lowers, P_uppers, num_iters, P_name, P_unit)

    T_unit = "years"
    T_name = "time of periastron passage"
    print_min_max_avg(T_lowers, T_uppers, num_iters, T_name, T_unit)

    e_name = "eccentricity"
    print_min_max_avg(e_lowers, e_uppers, num_iters, e_name)

    a_unit = "arcseconds"
    a_name = "semi-major axis"
    print_min_max_avg(a_lowers, a_uppers, num_iters, a_name, a_unit)

    i_unit = "degrees"
    i_name = "inclination"
    print_min_max_avg(i_lowers, i_uppers, num_iters, i_name, i_unit)

    w_unit = "degrees"
    w_name = "longitude of periastron"
    print_min_max_avg(w_lowers, w_uppers, num_iters, w_name, w_unit)

    Omega_unit = "degrees"
    Omega_name = "position angle of ascending node"
    print_min_max_avg(Omega_lowers, Omega_uppers, num_iters, Omega_name,
                      Omega_unit)