Beispiel #1
0
def run_emcee(M2_d, P_orb_obs, ecc_obs, ra, dec, M2_d_err=1.0,
    P_orb_obs_err=1.0, ecc_obs_err=0.05, nburn=1000, nsteps=1000):
    """ Run the emcee function

    Parameters
    ----------
    M2_d : float
        Observed secondary mass
    P_orb_obs : float
        Observed orbital period
    ecc_obs : float
        Observed orbital eccentricity
    ra : float
        Observed right ascension
    dec : float
        Observed declination

    Returns
    -------
    sampler : emcee object
    """

    # First thing is to load the sse data and SF_history data
    load_sse.load_sse()
    sf_history.load_sf_history()

    # Get initial values
    initial_vals = get_initial_values(M2_d, nwalkers=nwalkers)

    # Define sampler
    args = [[M2_d, M2_d_err, P_orb_obs, P_orb_obs_err, ecc_obs, ecc_obs_err, ra, dec]]
    sampler = emcee.EnsembleSampler(nwalkers=nwalkers, dim=10, lnpostfn=ln_posterior, args=args)

    # Assign initial values
    p0 = np.zeros((nwalkers,10))
    p0 = set_walkers(initial_vals, args[0], nwalkers=nwalkers)

    # Burn-in
    pos,prob,state = sampler.run_mcmc(p0, N=nburn)

    # Full run
    sampler.reset()
    pos,prob,state = sampler.run_mcmc(pos, N=nsteps)

    return sampler
Beispiel #2
0
def run_emcee_population(nburn=10000, nsteps=100000, nwalkers=80):
    """ Run emcee on the entire X-ray binary population

    Parameters
    ----------
    nburn : float (optional)
        number of steps for the Burn-in (default=10000)
    nsteps : float (optional)
        number of steps for the simulation (default=100000)

    Returns
    -------
    sampler : emcee object
    """

    # First thing is to load the sse data and SF_history data
    load_sse.load_sse()
    sf_history.load_sf_history()

    # Get initial values - choose 12 Msun as a seed for initial position
    initial_vals = get_initial_values(12.0, nwalkers=nwalkers)

    # Define sampler
    sampler = emcee.EnsembleSampler(nwalkers=nwalkers, dim=10, lnpostfn=ln_posterior_population)

    # Assign initial values based on a random binary
    args = [12.0, 2.0, 500.0, 20.0, 0.50, 0.2, 13.5, -72.7] # SMC
    p0 = np.zeros((nwalkers,10))
    p0 = set_walkers(initial_vals, args, nwalkers=nwalkers)

    # Burn-in
    pos,prob,state = sampler.run_mcmc(p0, N=nburn)

    # Full run
    sampler.reset()
    pos,prob,state = sampler.run_mcmc(pos, N=nsteps)

    return sampler
Beispiel #3
0
def run_pop_synth(input_sys, N_sys=10000, t_low=15.0, t_high=60.0, delta_t=1):
    """ Run a forward population synthesis

    Parameters
    ----------
    input_sys : ra_sys, dec_sys, P_orb_sys, ecc_sys, M2_d_sys
        Observed values of individual system
    N_sys : int
        Number of systems per age calculated (10000)
    t_low : float
        Lower limit to age range tested (15 Myr)
    t_high : float
        Upper limit to age range tested (60 Myr)
    delta_t : float
        Age resolution (1 Myr)

    Returns
    -------
    HMXB_sys : numpy recarray
        Systems that evolve into the observed system
        names = ["ra", "dec", "ra_b", "dec_b", "P_orb", "ecc", "M_2_d", "theta_proj", "age", "norm"]
    init_params_sys : numpy recarray
        Initial conditions for the observed Systems
        names = ["M1","M2","A","ecc","v_k","theta","phi","ra_b","dec_b","t_b"]
    """


    ra_sys, dec_sys, P_orb_sys, ecc_sys, M2_d_sys = input_sys

    # First thing is to load the sse data and SF_history data
    load_sse.load_sse()
    sf_history.load_sf_history()

    names = ["ra", "dec", "ra_b", "dec_b", "P_orb", "ecc", "M_2_d", "theta_proj", "age", "norm"]

    HMXB = np.recarray(0, names=names, formats=['float64,float64,float64,float64,float64,float64,float64,float64,float64,float64'])
    HMXB_sys = np.recarray(0, names=names, formats=['float64,float64,float64,float64,float64,float64,float64,float64,float64,float64'])

    names = ["M1","M2","A","ecc","v_k","theta","phi","ra_b","dec_b","t_b"]
    init_params_sys = np.recarray(0, names=names, formats=['float64,float64,float64,float64,float64,float64,float64,float64,float64,float64'])


    theta_sep = np.array([])

    batch_size = 1000
    n_batch = int(np.ceil(float(N_sys)/float(batch_size)))

    for t_b in np.linspace(14.0, 56.0, 43):

        for batch in np.arange(n_batch):
            n_run = min(batch_size, N_sys - (batch)*batch_size)
            HMXB_t, init_params_t = create_HMXBs(t_b, N_sys=n_run, ra_in=ra_sys, dec_in=dec_sys)
            HMXB = np.concatenate((HMXB, HMXB_t))

            for i in np.arange(len(HMXB_t)):

                h = HMXB_t[i]
                p = init_params_t[i]

                angle = c.rad_to_deg * sf_history.get_theta_proj_degree(ra_sys, dec_sys, h["ra"], h["dec"])
                theta_sep = np.append(theta_sep, angle)

                if angle < 0.2 \
                    and np.abs(h["P_orb"] - P_orb_sys) < 5.0 \
                    and np.abs(h["ecc"] - ecc_sys) < 0.1 \
                    and np.abs(h["M_2_d"] - M2_d_sys) < 1.0:

                    HMXB_sys = np.append(HMXB_sys, h)
                    init_params_sys = np.append(init_params_sys, p)


    return HMXB_sys, init_params_sys
Beispiel #4
0
def get_random_positions(N, t_b, ra_in=None, dec_in=None):
    """ Use the star formation history to generate a population of new binaries

    Parameters
    ----------
    N : integer
        Number of positions to calculate
    t_b : float
        Birth time to calculate star formation history (Myr)
    ra_in : float
        RA of system (optional)
    dec_in : float
        Dec of system (optional)

    Returns
    -------
    ra_out : ndarray
        Array of output RA's (degrees)
    dec_out : ndarray
        Array of output Dec's (degrees)
    N_stars : int
        Normalization constant calculated from number of stars formed at time t_b
    """

    if sf_history.smc_sfh is None or sf_history.smc_coor is None:
        sf_history.load_sf_history()

    N_regions = len(sf_history.smc_sfh)

    # If provided with an ra and dec, only generate stars within 3 degrees of input position
    SF_regions = np.zeros((2,N_regions))
    for i in np.arange(N_regions):
        SF_regions[0,i] = i

        if ra_in is None or dec_in is None:
            SF_regions[1,i] = sf_history.smc_sfh[i](np.log10(t_b*1.0e6))
        elif sf_history.get_theta_proj_degree(sf_history.smc_coor["ra"][i], sf_history.smc_coor["dec"][i], ra_in, dec_in) < c.deg_to_rad * 3.0:
            SF_regions[1,i] = sf_history.smc_sfh[i](np.log10(t_b*1.0e6))
        else:
            SF_regions[1,i] = 0.0

    N_stars = np.sum(SF_regions, axis=1)[1]

    # Normalize
    SF_regions[1] = SF_regions[1] / N_stars

    # Sort
    SF_sort = SF_regions[:,SF_regions[1].argsort()]

    # Move from normed PDF to CDF
    SF_sort[1] = np.cumsum(SF_sort[1])

    # TEST #
#    ra_out = lmc_coor["ra"][SF_sort[0][-100:].astype(int)]
#    dec_out = lmc_coor["dec"][SF_sort[0][-100:].astype(int)]
#    return ra_out, dec_out
    # TEST #

    # Random numbers
    y = uniform.rvs(size=N)

    # Create a 2D grid of CDFs, and random numbers
    SF_out, y_out = np.meshgrid(SF_sort[1], y)

    # Get index of closest region in sorted array
    indices = np.argmin((SF_out - y_out)**2,axis=1)

    # Move to indices of stored LMC SFH data array
    indices = SF_sort[0][indices].astype(int)

    # Get random ra's and dec's of each region
    ra_out = sf_history.smc_coor["ra"][indices]
    dec_out = sf_history.smc_coor["dec"][indices]

    # Width is 12 arcmin or 12/60 degrees for outermost regions
    # Width is 6 arcmin or 6/60 degrees for inner regions
#    width = 12.0 / 60.0 * np.ones(len(indices))
    width = 6.0 / 60.0 * np.ones(len(indices))
#    for i in np.arange(len(indices)):
#        if str(smc_coor["region"][indices[i]]).find("_") != -1:
#            width[i] = 6.0 / 60.0

    tmp_delta_ra = width * (2.0 * uniform.rvs(size=len(indices)) - 1.0) / np.cos(c.deg_to_rad * dec_out) * 2.0
    tmp_delta_dec = width * (2.0 * uniform.rvs(size=len(indices)) - 1.0)

    ra_out = ra_out + tmp_delta_ra
    dec_out = dec_out + tmp_delta_dec

    return ra_out, dec_out, N_stars
Beispiel #5
0
def ln_priors(y):
    """ Priors on the model parameters

    Parameters
    ----------
    y : ra, dec, M1, M2, A, ecc, v_k, theta, phi, ra_b, dec_b, t_b
        Current HMXB location (ra, dec) and 10 model parameters

    Returns
    -------
    lp : float
        Natural log of the prior
    """

#    M1, M2, A, v_k, theta, phi, ra_b, dec_b, t_b = y
    ra, dec, M1, M2, A, ecc, v_k, theta, phi, ra_b, dec_b, t_b = y

    lp = 0.0

    # P(M1)
    if M1 < c.min_mass or M1 > c.max_mass: return -np.inf
    norm_const = (c.alpha+1.0) / (np.power(c.max_mass, c.alpha+1.0) - np.power(c.min_mass, c.alpha+1.0))
    lp += np.log( norm_const * np.power(M1, c.alpha) )
    # M1 must be massive enough to evolve off the MS by t_obs
    if load_sse.func_sse_tmax(M1) > t_b: return -np.inf

    # P(M2)
    # Normalization is over full q in (0,1.0)
    q = M2 / M1
    if q < 0.3 or q > 1.0: return -np.inf
    lp += np.log( (1.0 / M1 ) )

    # P(ecc)
    if ecc < 0.0 or ecc > 1.0: return -np.inf
    lp += np.log(2.0 * ecc)

    # P(A)
    if A*(1.0-ecc) < c.min_A or A*(1.0+ecc) > c.max_A: return -np.inf
    norm_const = np.log(c.max_A) - np.log(c.min_A)
    lp += np.log( norm_const / A )
    # A must avoid RLOF at ZAMS, by a factor of 2
    r_1_roche = binary_evolve.func_Roche_radius(M1, M2, A*(1.0-ecc))
    if 2.0 * load_sse.func_sse_r_ZAMS(M1) > r_1_roche: return -np.inf

    # P(v_k)
    if v_k < 0.0: return -np.inf
    lp += np.log( maxwell.pdf(v_k, scale=c.v_k_sigma) )

    # P(theta)
    if theta <= 0.0 or theta >= np.pi: return -np.inf
    lp += np.log(np.sin(theta) / 2.0)

    # P(phi)
    if phi < 0.0 or phi > np.pi: return -np.inf
    lp += -np.log( np.pi )

    # Get star formation history
    sf_history.load_sf_history()
    sfh = sf_history.get_SFH(ra_b, dec_b, t_b, sf_history.smc_coor, sf_history.smc_sfh)
    if sfh <= 0.0: return -np.inf

    # P(alpha, delta)
    # From spherical geometric effect, we need to care about cos(declination)
    lp += np.log(np.cos(c.deg_to_rad * dec_b) / 2.0)

    ##################################################################
    # We add an additional prior that scales the RA and Dec by the
    # area available to it, i.e. pi theta^2, where theta is the angle
    # of the maximum projected separation over the distance.
    #
    # Still under construction
    ##################################################################
    M1_b, M2_b, A_b = binary_evolve.func_MT_forward(M1, M2, A, ecc)
    A_c, v_sys, ecc = binary_evolve.func_SN_forward(M1_b, M2_b, A_b, v_k, theta, phi)
    if ecc < 0.0 or ecc > 1.0 or np.isnan(ecc): return -np.inf

    # Ensure that we only get non-compact object companions
    tobs_eff = binary_evolve.func_get_time(M1, M2, t_b)
    M_tmp, M_dot_tmp, R_tmp, k_type = load_sse.func_get_sse_star(M2_b, tobs_eff)
    if int(k_type) > 9: return -np.inf

#    t_sn = (t_b - func_sse_tmax(M1)) * 1.0e6 * yr_to_sec  # The time since the primary's core collapse
#    theta_max = (v_sys * t_sn) / dist_LMC  # Unitless
#    area = np.pi * rad_to_dec(theta_max)**2
#    lp += np.log(1.0 / area)
    ##################################################################
    # Instead, let's estimate the number of stars formed within a cone
    # around the observed position, over solid angle and time.
    # Prior is in Msun/Myr/steradian
    ##################################################################
    t_min = load_sse.func_sse_tmax(M1) * 1.0e6 * c.yr_to_sec
    t_max = (load_sse.func_sse_tmax(M2_b) - binary_evolve.func_get_time(M1, M2, 0.0)) * 1.0e6 * c.yr_to_sec
    if t_max-t_min < 0.0: return -np.inf
    theta_C = (v_sys * (t_max - t_min)) / c.dist_SMC
    stars_formed = get_stars_formed(ra, dec, t_min, t_max, v_sys, c.dist_SMC)
    if stars_formed == 0.0: return -np.inf
    volume_cone = (np.pi/3.0 * theta_C**2 * (t_max - t_min) / c.yr_to_sec / 1.0e6)
    lp += np.log(sfh / stars_formed / volume_cone)
    ##################################################################

#    # P(t_b | alpha, delta)
#    sfh_normalization = 1.0e-6
#    lp += np.log(sfh_normalization * sfh)

    # Add a prior so that the post-MT secondary is within the correct bounds
    M2_c = M1 + M2 - load_sse.func_sse_he_mass(M1)
    if M2_c > c.max_mass or M2_c < c.min_mass: return -np.inf

    # Add a prior so the effective time remains bounded
    t_eff_obs = binary_evolve.func_get_time(M1, M2, t_b)
    if t_eff_obs < 0.0: return -np.inf

    if t_b * 1.0e6 * c.yr_to_sec < t_min: return -np.inf
    if t_b * 1.0e6 * c.yr_to_sec > t_max: return -np.inf

    return lp
Beispiel #6
0
def run_emcee_2(M2_d, P_orb_obs, ecc_obs, ra, dec, M2_d_err=1.0,
    P_orb_obs_err=1.0, ecc_obs_err=0.05, nwalkers=80, nburn=1000,
    nsteps=1000,
    threads=1, mpi=False):
    """ Run the emcee function

    Parameters
    ----------
    M2_d : float
        Observed secondary mass
    P_orb_obs : float
        Observed orbital period
    ecc_obs : float
        Observed orbital eccentricity
    ra : float
        Observed right ascension
    dec : float
        Observed declination
    threads : int
        Number of threads to use for parallelization
    mpi : bool
        If true, use MPIPool for parallelization

    Returns
    -------
    sampler : emcee object
    """

    # First thing is to load the sse data and SF_history data
    load_sse.load_sse()
    sf_history.load_sf_history()

    # Get initial values
    initial_vals = get_initial_values(M2_d, nwalkers=nwalkers)

    # Define sampler
    args = [[M2_d, M2_d_err, P_orb_obs, P_orb_obs_err, ecc_obs, ecc_obs_err, ra, dec]]

    if mpi == True:
        pool = MPIPool()
        if not pool.is_master():
            pool.wait()
            sys.exit(0)
        sampler = emcee.EnsembleSampler(nwalkers=nwalkers, dim=10, lnpostfn=ln_posterior, args=args, pool=pool)

    elif threads != 1:
        sampler = emcee.EnsembleSampler(nwalkers=nwalkers, dim=10, lnpostfn=ln_posterior, args=args, threads=threads)
    else:
        sampler = emcee.EnsembleSampler(nwalkers=nwalkers, dim=10, lnpostfn=ln_posterior, args=args)

    # Assign initial values
    p0 = np.zeros((nwalkers,10))
    p0 = set_walkers(initial_vals, args[0], nwalkers=nwalkers)

    # Burn-in 1
    pos,prob,state = sampler.run_mcmc(p0, N=nburn)
    sampler1 = copy.copy(sampler)

    # TESTING BEGIN - Get limiting ln_prob for worst 10 chains
    prob_lim = (np.sort(prob)[9] + np.sort(prob)[10])/2.0
    index_best = np.argmax(prob)
    for i in np.arange(len(prob)):
        # if sampler1.acceptance_fraction[i] == 0.0: pos[i] = np.copy(pos[index_best]) + np.random.normal(0.0, 0.005, size=10)
        if prob[i] < prob_lim:  pos[i] = np.copy(pos[index_best]) + np.random.normal(0.0, 0.005, size=10)
    # TESTING END

    print "Burn-in 1 finished."
    print "Starting burn-in 2..."

    # Burn-in 2
    sampler.reset()
    pos,prob,state = sampler.run_mcmc(pos, N=nburn)
    sampler2 = copy.copy(sampler)

    # TESTING BEGIN - Get limiting ln_prob for worst 10 chains
    prob_lim = (np.sort(prob)[9] + np.sort(prob)[10])/2.0
    index_best = np.argmax(prob)
    for i in np.arange(len(prob)):
        # if sampler2.acceptance_fraction[i] == 0.0: pos[i] = np.copy(pos[index_best]) + np.random.normal(0.0, 0.005, size=10)
        if prob[i] < prob_lim:  pos[i] = np.copy(pos[index_best]) + np.random.normal(0.0, 0.005, size=10)
    # TESTING END

    print "Burn-in 2 finished."
    print "Starting burn-in 3..."

    # Burn-in 3
    sampler.reset()
    pos,prob,state = sampler.run_mcmc(pos, N=nburn)
    sampler3 = copy.copy(sampler)

    # TESTING BEGIN - Get limiting ln_prob for worst 10 chains
    prob_lim = (np.sort(prob)[9] + np.sort(prob)[10])/2.0
    index_best = np.argmax(prob)
    for i in np.arange(len(prob)):
        # if sampler3.acceptance_fraction[i] == 0.0: pos[i] = np.copy(pos[index_best]) + np.random.normal(0.0, 0.005, size=10)
        if prob[i] < prob_lim:  pos[i] = np.copy(pos[index_best]) + np.random.normal(0.0, 0.005, size=10)
    # TESTING END

    print "Burn-in 3 finished."
    print "Starting burn-in 4..."

    # Burn-in 4
    sampler.reset()
    pos,prob,state = sampler.run_mcmc(pos, N=nburn)
    sampler4 = copy.copy(sampler)

    print "Burn-in 4 finished."
    print "Starting production run..."

    # Full run
    sampler.reset()
    pos,prob,state = sampler.run_mcmc(pos, N=nsteps)

    print "Finished production run"

    if mpi is True: pool.close()


    return sampler1, sampler2, sampler3, sampler4, sampler