def fit_King_prof(nchains, nruns, nburn, x, y, cl_cent, field_dens, cl_rad, n_memb_i, rt_max_f, N_integ=1000, ndim=2, N_conv=1000, tau_stable=0.05): """ rt_max_f: factor that caps the maximum tidal radius, given the previously estimated cluster radius. HARDCODED: N_integ : number of values used in the tidal radius array. N_conv tau_stable """ from emcee import ensemble from emcee import moves # HARDCODED # mv = moves.StretchMove() # mv = moves.KDEMove() mv = [ (moves.DESnookerMove(), 0.1), (moves.DEMove(), 0.9 * 0.9), (moves.DEMove(gamma0=1.0), 0.9 * 0.1), ] # HARDCODED # Steps to store Bayes params. KP_steps = int(nruns * .01) xy = np.array((x, y)).T # area_tot = np.ptp(x) * np.ptp(y) # cx, cy = cl_cent # # Frame limits # x0, x1 = min(xy.T[0]), max(xy.T[0]) # y0, y1 = min(xy.T[1]), max(xy.T[1]) # dx0, dx1 = abs(cl_cent[0] - x0), abs(cl_cent[0] - x1) # dy0, dy1 = abs(cl_cent[1] - y0), abs(cl_cent[1] - y1) # dxy = min(dx0, dx1, dy0, dy1) # # Parameters used to estimate the fraction of cluster area inside the # # frame if it spills outside of it. # circarea_pars = (dxy, x0, x1, y0, y1, N_MC, rand_01_MC, cos_t, sin_t) # This assumes that the tidal radius can not be larger than 'rt_max' times # the estimated cluster radius. rt_max = rt_max_f * cl_rad # Tidal radius array. Used for integrating rt_rang = np.linspace(0., rt_max, int(rt_max_f * N_integ)) # if ndim == 2: # Dimensions: rc, rt # Initial guesses. rc_pos0 = np.random.uniform(.05 * rt_max, rt_max, nchains) rt_pos0 = np.random.uniform(rc_pos0, rt_max, nchains) pos0 = np.array([rc_pos0, rt_pos0]).T # Stars inside the cut-out given by the 'rt_max' value. xy_cent_dist = spatial.distance.cdist([cl_cent], xy)[0] msk = xy_cent_dist <= rt_max r_in = xy_cent_dist[msk] # Fixed values fd, N_memb = field_dens, n_memb_i # elif KP_mode == 3: # # Dimensions: fd, rc, rt # ndim = 3 # # Initial guesses. # fd_pos0 = np.random.uniform(.5 * fd, 2. * fd, nchains) # rc_pos0 = np.random.uniform(.05 * rt_max, rt_max, nchains) # rt_pos0 = np.random.uniform(rc_pos0, rt_max, nchains) # pos0 = np.array([fd_pos0, rc_pos0, rt_pos0]).T # # Stars inside the cut-out given by the 'rt_max' value. # xy_cent_dist = spatial.distance.cdist([cl_cent], xy)[0] # msk = xy_cent_dist <= rt_max # r_in = xy_cent_dist[msk] # fd, N_memb, fd_max = None, None, r_in.size / rt_max**2 # elif ndim == 4: # # Dimensions: cent_x, cent_y, rc, rt # ndim = 4 # # Initial guesses. # cx_pos0 = np.random.uniform( # cx - .9 * cl_rad, cx + .9 * cl_rad, nchains) # cy_pos0 = np.random.uniform( # cy - .9 * cl_rad, cy + .9 * cl_rad, nchains) # rc_pos0 = np.random.uniform(.05 * rt_max, rt_max, nchains) # rt_pos0 = np.random.uniform(rc_pos0, rt_max, nchains) # pos0 = np.array([cx_pos0, cy_pos0, rc_pos0, rt_pos0]).T # r_in = [] args = { 'rt_max': rt_max, 'rt_rang': rt_rang, 'fd': fd, 'N_memb': N_memb, 'r_in': r_in } # emcee sampler sampler = ensemble.EnsembleSampler(nchains, ndim, lnprob, kwargs=args, moves=mv) with warnings.catch_warnings(): warnings.simplefilter("ignore") tau_index, autocorr_vals, afs = 0, np.empty(nruns), np.empty(nruns) old_tau = np.inf for i, (pos, prob, stat) in enumerate(sampler.sample(pos0, iterations=nruns)): # Every X steps if i % KP_steps and i < (nruns - 1): continue afs[tau_index] = np.mean(sampler.acceptance_fraction) tau = np.mean(sampler.get_autocorr_time(tol=0)) autocorr_vals[tau_index] = tau tau_index += 1 # Check convergence converged = tau * (N_conv / nchains) < i * nburn converged &= np.abs(old_tau - tau) / tau < tau_stable if converged: print("") break old_tau = tau update_progress.updt(nruns, i + 1) KP_mean_afs = afs[:tau_index] KP_tau_autocorr = autocorr_vals[:tau_index] nburn = int(i * nburn) samples = sampler.get_chain(discard=nburn, flat=True) # if ndim == 4: # cx, cy, rc, rt = np.mean(samples, 0) # print(cx, cy) # e_cx, e_cy, e_rc, e_rt = np.percentile(samples, (16, 84), 0).T # if ndim == 2: rc, rt = np.mean(samples, 0) rc_16, rc_50, rc_84, rt_16, rt_50, rt_84 = np.percentile( samples, (16, 50, 84), 0).T.flatten() # Mode and KDE to plot # This simulates the 'fundam_params and 'varIdxs' arrays. fp, vi = [[-np.inf, np.inf], [-np.inf, np.inf]], [0, 1] KP_Bys_mode, KP_Bayes_kde = modeKDE(fp, vi, samples.T) # Store: 16, median, 84, mean, mode KP_Bys_rc = np.array([rc_16, rc_50, rc_84, rc, KP_Bys_mode[0]]) KP_Bys_rt = np.array([rt_16, rt_50, rt_84, rt, KP_Bys_mode[1]]) # Effective sample size KP_ESS = samples.shape[0] / np.mean(sampler.get_autocorr_time(tol=0)) # For plotting, (nsteps, nchains, ndim) KP_samples = sampler.get_chain() # Central density, for plotting. # if ndim == 4: # N_memb = rMmembN( # fd, rt_max, rt, xy, area_tot, (cx, cy), circarea_pars)[-1] KP_cd = centDens(N_memb, rc, rt, rt_rang) return KP_cd, KP_steps, KP_mean_afs, KP_tau_autocorr, KP_ESS, KP_samples,\ KP_Bys_rc, KP_Bys_rt, KP_Bayes_kde
def test_uniform_de_snooker(**kwargs): _test_uniform(moves.DESnookerMove(), **kwargs)
def fit_King_prof(nchains, nruns, nburn, x, y, cl_cent, field_dens, cl_rad, n_memb_i, rt_max_f, N_integ=1000, N_conv=1000, tau_stable=0.05): """ rt_max_f: factor that caps the maximum tidal radius, given the previously estimated cluster radius. """ from emcee import ensemble from emcee import moves # HARDCODED ########################## # Move used by emcee mv = [ (moves.DESnookerMove(), 0.1), (moves.DEMove(), 0.9 * 0.9), (moves.DEMove(gamma0=1.0), 0.9 * 0.1), ] # mv = moves.StretchMove() # mv = moves.KDEMove() # Steps to store Bayes params. KP_steps = int(nruns * .01) # Field density and estimated number of members (previously # obtained) fd = field_dens # Fix N_memb N_memb = n_memb_i # Estimate N_memb with each sampler step # N_memb = None # Select the number of parameters to fit: # ndim = 2 fits (rc, rt) # ndim = 4 fits (rc, rt, ecc, theta) ndim = 2 # HARDCODED ########################## # The tidal radius can not be larger than 'rt_max' times the estimated # "optimal" cluster radius. Used as a prior. rt_max = rt_max_f * cl_rad # Tidal radius array. Used for integrating rt_rang = np.linspace(0., rt_max, int(rt_max_f * N_integ)) # Initial positions for the sampler. if ndim == 2: # Dimensions: rc, rt rc_pos0 = np.random.uniform(.05 * rt_max, rt_max, nchains) rt_pos0 = np.random.uniform(rc_pos0, rt_max, nchains) pos0 = np.array([rc_pos0, rt_pos0]).T elif ndim == 4: # Dimensions: rc, rt, ecc, theta rc_pos0 = np.random.uniform(.05 * rt_max, rt_max, nchains) rt_pos0 = np.random.uniform(rc_pos0, rt_max, nchains) ecc = np.random.uniform(0., 1., nchains) theta = np.random.uniform(0., np.pi, nchains) pos0 = np.array([rc_pos0, rt_pos0, ecc, theta]).T # Identify stars inside the cut-out given by the 'rt_max' value. Only these # stars will be processed below. xy = np.array((x, y)).T xy_cent_dist = spatial.distance.cdist([cl_cent], xy)[0] msk = xy_cent_dist <= rt_max xy_in = xy[msk].T r_in = xy_cent_dist[msk] args = { 'ndim': ndim, 'rt_max': rt_max, 'cl_cent': cl_cent, 'fd': fd, 'N_memb': N_memb, 'rt_rang': rt_rang, 'xy_in': xy_in, 'r_in': r_in } # emcee sampler sampler = ensemble.EnsembleSampler(nchains, ndim, lnprob, kwargs=args, moves=mv) # Run the smpler hiding some warnings with warnings.catch_warnings(): warnings.simplefilter("ignore") tau_index, autocorr_vals, afs = 0, np.empty(nruns), np.empty(nruns) old_tau = np.inf for i, (pos, prob, stat) in enumerate(sampler.sample(pos0, iterations=nruns)): # Every X steps if i % KP_steps and i < (nruns - 1): continue afs[tau_index] = np.mean(sampler.acceptance_fraction) tau = np.mean(sampler.get_autocorr_time(tol=0)) autocorr_vals[tau_index] = tau tau_index += 1 # Check convergence converged = tau * (N_conv / nchains) < i * nburn converged &= np.abs(old_tau - tau) / tau < tau_stable if converged: print("") break old_tau = tau update_progress.updt(nruns, i + 1) KP_mean_afs = afs[:tau_index] KP_tau_autocorr = autocorr_vals[:tau_index] # Remove burn-in nburn = int(i * nburn) samples = sampler.get_chain(discard=nburn, flat=True) # Extract mean, median, mode, 16th, 84th percentiles for each parameter rc, rt = np.mean(samples[:, :2], 0) rc_16, rc_50, rc_84, rt_16, rt_50, rt_84 = np.percentile( samples[:, :2], (16, 50, 84), 0).T.flatten() if ndim == 2: ecc, theta = 0., 0. ecc_16, ecc_50, ecc_84, theta_16, theta_50, theta_84 =\ [np.array([np.nan] * 3) for _ in range(6)] # Mode and KDE to plot # This simulates the 'fundam_params and 'varIdxs' arrays. fp, vi = [[-np.inf, np.inf], [-np.inf, np.inf]], [0, 1] KP_Bys_mode, KP_Bayes_kde = modeKDE(fp, vi, samples.T) KP_Bys_mode += [0., 0.] KP_Bayes_kde += [[], []] elif ndim == 4: ecc = np.mean(samples[:, 2], 0) theta = circmean(samples[:, 3] * u.rad).value # Beware: the median and percentiles for theta might not be # properly defined. ecc_16, ecc_50, ecc_84, theta_16, theta_50, theta_84 =\ np.percentile(samples[:, 2:], (16, 50, 84), 0).T.flatten() # Estimate the mode fp, vi = [[-np.inf, np.inf], [-np.inf, np.inf], [-np.inf, np.inf], [-np.inf, np.inf]], [0, 1, 2, 3] KP_Bys_mode, KP_Bayes_kde = modeKDE(fp, vi, samples.T) # Store: 16th, median, 84th, mean, mode KP_Bys_rc = np.array([rc_16, rc_50, rc_84, rc, KP_Bys_mode[0]]) KP_Bys_rt = np.array([rt_16, rt_50, rt_84, rt, KP_Bys_mode[1]]) KP_Bys_ecc = np.array([ecc_16, ecc_50, ecc_84, ecc, KP_Bys_mode[2]]) KP_Bys_theta = np.array( [theta_16, theta_50, theta_84, theta, KP_Bys_mode[3]]) # Effective sample size KP_ESS = samples.shape[0] / np.mean(sampler.get_autocorr_time(tol=0)) # For plotting, (nsteps, nchains, ndim) KP_samples = sampler.get_chain() # Central density, for plotting. Use mean values for all the parameters. KP_cd = lnlike((rc, rt, ecc, theta), ndim, rt_max, cl_cent, fd, N_memb, xy_in, r_in, rt_rang, True) return KP_cd, KP_steps, KP_mean_afs, KP_tau_autocorr, KP_ESS, KP_samples,\ KP_Bys_rc, KP_Bys_rt, KP_Bys_ecc, KP_Bys_theta, KP_Bayes_kde
def test_normal_de_snooker(**kwargs): kwargs["nsteps"] = 4000 _test_normal(moves.DESnookerMove(), **kwargs)
def test_normal_de_snooker(**kwargs): _test_normal(moves.DESnookerMove(), **kwargs)