def main(args: Optional[list] = None,
         opts: Optional[argparse.Namespace] = None):
    """Fit Combination Pal5 and GD1 to MW Potential Script Function.

    Parameters
    ----------
    args : list, optional
        an optional single argument that holds the sys.argv list,
        except for the script name (e.g., argv[1:])

    """
    if opts is not None and args is None:
        pass
    else:
        parser = make_parser()
        opts = parser.parse_args(args)

    fpath = opts.fpath + "/" if not opts.fpath.endswith("/") else opts.fpath
    opath = opts.opath + "/" if not opts.opath.endswith("/") else opts.opath

    # -----------------------
    # Adding in the force measurements from Pal 5 *and* GD-1; also fitting
    # $R_0$ and $V_c(R_0)$

    plt.figure(figsize=(16, 5))
    p_b15_pal5gd1_voro = mw_pot.fit(
        fitc=True,
        c=None,
        addpal5=True,
        addgd1=True,
        fitvoro=True,
        mc16=True,
        plots=fpath + "fit.pdf",
    )

    # -----------------------

    samples_savefilename = opath + "mwpot14varyc-fitvoro-pal5gd1-samples.pkl"
    if os.path.exists(samples_savefilename):
        with open(samples_savefilename, "rb") as savefile:
            s = pickle.load(savefile)
    else:
        s = mw_pot.sample(
            nsamples=100000,
            params=p_b15_pal5gd1_voro[0],
            fitc=True,
            c=None,
            plots=fpath + "mwpot14varyc-fitvoro-pal5gd1-samples.pdf",
            mc16=True,
            addpal5=True,
            addgd1=True,
            fitvoro=True,
        )
        save_pickles(samples_savefilename, s)

    # -----------------------

    plt.figure()
    mw_pot.plot_samples(
        s,
        True,
        True,
        addpal5=True,
        addgd1=True,
        savefig=fpath + "mwpot14varyc-fitvoro-pal5gd1-samples-corner.pdf",
    )

    # -----------------------

    bf_savefilename = opath + "mwpot14varyc-bf.pkl"  # should already exist
    if os.path.exists(bf_savefilename):
        with open(bf_savefilename, "rb") as savefile:
            cs = pickle.load(savefile)
            bf_params = pickle.load(savefile)
    else:
        cs = np.arange(0.5, 4.1, 0.1)
        bf_params = []
        for c in tqdm(cs):
            dum = mw_pot.fit(
                fitc=False,
                c=c,
                plots=fpath + "mwpot14varyc-bf-fit.pdf",
            )
            bf_params.append(dum[0])
        save_pickles(bf_savefilename, cs, bf_params)

    # -----------------------

    plt.figure()
    bovy_plot.bovy_print(
        axes_labelsize=17.0,
        text_fontsize=12.0,
        xtick_labelsize=15.0,
        ytick_labelsize=15.0,
    )
    su.plot_mcmc_c(
        s,
        True,
        cs,
        bf_params,
        savefig=fpath + "mwpot14varyc-bf-combo_pal5_gd1-dependence.pdf",
    )
    if save_figures:
        plt.savefig(
            os.path.join(
                os.getenv("PAPERSDIR"),
                "2016-mwhalo-shape",
                "mwpot14-varyc-wp5g1.pdf",
            ),
            bbox_inches="tight",
        )

    # -----------------------

    plt.figure(figsize=(4, 4))
    cindx = 9
    dum = bovy_plot.bovy_hist(
        s[cindx],
        bins=36,
        histtype="step",
        lw=2.0,
        xlabel=r"$c/a$",
        xrange=[0.5, 1.5],
        normed=True,
    )
    plt.savefig(fpath + "mwpot14varyc-bf-combo_pal5_gd1-shape_hist.pdf")

    with open(opath + "fit_potential_combo-pal5-gd1.txt", "w") as file:
        sortedc = np.array(sorted(s[cindx][-50000:]))
        file.write("2.5%% and 0.5%% lower limits: %.3f, %.3f" % (
            sortedc[int(np.floor(0.025 * len(sortedc)))],
            sortedc[int(np.floor(0.005 * len(sortedc)))],
        ))
        file.write("2.5%% and 0.5%% upper limits: %.3f, %.3f" % (
            sortedc[int(np.floor(0.975 * len(sortedc)))],
            sortedc[int(np.floor(0.995 * len(sortedc)))],
        ))
        file.write("Median, 68%% confidence: %.3f, %.3f, %.3f" % (
            np.median(sortedc),
            sortedc[int(np.floor(0.16 * len(sortedc)))],
            sortedc[int(np.floor(0.84 * len(sortedc)))],
        ))
        file.write("Mean, std. dev.: %.2f,%.2f" % (
            np.mean(sortedc),
            np.std(sortedc),
        ))

    # -----------------------
    # What is the constraint on the mass of the halo?

    tR = 20.0 / REFR0
    skip = 1
    hmass = []
    for sa in tqdm(s.T[::skip]):
        pot = mw_pot.setup_potential(
            sa,
            sa[-1],
            True,
            False,
            REFR0 * sa[8],
            REFV0 * sa[7],
            fitvoro=True,
        )
        hmass.append(-integrate.quad(
            lambda x: tR**2.0 * potential.evaluaterforces(
                pot[2], tR * x, tR * np.sqrt(1.0 - x**2.0), phi=0.0),
            0.0,
            1.0,
        )[0] * bovy_conversion.mass_in_1010msol(REFV0, REFR0) / 10.0)
    hmass = np.array(hmass)

    with open(opath + "fit_potential_combo-pal5-gd1.txt",
              "a") as file:  # append

        file.write("\nMass Constraints:")

        sortedhm = np.array(sorted(hmass))
        file.write("2.5%% and 0.5%% lower limits: %.2f, %.2f" % (
            sortedhm[int(np.floor(0.025 * len(sortedhm)))],
            sortedhm[int(np.floor(0.005 * len(sortedhm)))],
        ))
        file.write("2.5%% and 0.5%% upper limits: %.2f, %.2f" % (
            sortedhm[int(np.floor(0.975 * len(sortedhm)))],
            sortedhm[int(np.floor(0.995 * len(sortedhm)))],
        ))
        file.write("Median, 68%% confidence: %.2f, %.2f, %.2f" % (
            np.median(sortedhm),
            sortedhm[int(np.floor(0.16 * len(sortedhm)))],
            sortedhm[int(np.floor(0.84 * len(sortedhm)))],
        ))

    # -----------------------

    bovy_plot.scatterplot(
        hmass,
        s[-1, ::skip],
        "k,",
        onedhists=True,
        bins=31,
        xrange=[0.5, 1.5],
        yrange=[0.5, 1.5],
        xlabel=r"$M_{\mathrm{halo}} (r<20\,\mathrm{kpc})\,(M_\odot)$",
        ylabel=r"$c/a$",
    )
    plt.savefig(fpath + "scatterplot.pdf")
Пример #2
0
def model_vary_d():

    # ----------------------------------------------------------
    # The Pal 5 stream is not very sensitive to changes in $b$.
    # Vary the distance:

    p_b15 = [
        0.60122692,
        0.36273147,
        -0.97591502,
        -3.34169377,
        0.71877924,
        -0.01519337,
        -0.01928001,
    ]
    progs = []
    progfs = []
    times = np.linspace(0.0, 3.0, 101)
    ds = np.linspace(22.5, 24.5, 101)
    for d in ds:
        pot = mw_pot.setup_potential(p_b15, 1.0, False, False, REFR0, REFV0)
        prog = Orbit(
            [229.018, -0.124, d, -2.296, -2.257, -58.7],
            radec=True,
            ro=REFR0,
            vo=REFV0,
            solarmotion=[-11.1, 24.0, 7.25],
        )
        prog.integrate(times, pot)
        progs.append(prog)
        prog = Orbit(
            [229.018, -0.124, d, -2.296, -2.257, -58.7],
            radec=True,
            ro=REFR0,
            vo=REFV0,
            solarmotion=[-11.1, 24.0, 7.25],
        ).flip()
        prog.integrate(times, pot)
        prog.flip(inplace=True)
        progfs.append(prog)

    # -------------------------------------------

    plt.figure(figsize=(12, 4))

    for d, orb, orbf in zip(ds, progs, progfs):
        tc = cmap((d - np.amin(ds)) / (np.amax(ds) - np.amin(ds)))
        plt.subplot(1, 2, 1)
        orb.plot(d1="ra", d2="dec", color=tc, overplot=True)
        orbf.plot(d1="ra", d2="dec", color=tc, overplot=True)
        plt.subplot(1, 2, 2)
        orb.plot(d1="ra", d2="vlos", color=tc, overplot=True)
        orbf.plot(d1="ra", d2="vlos", color=tc, overplot=True)
    plot_data_add_labels(color="k")
    add_colorbar(
        np.amin(ds),
        np.amax(ds),
        r"$\mathrm{distance}\,(\mathrm{kpc})$",
        save_figures=False,
    )
    plt.savefig("figures/varyd.pdf")
Пример #3
0
def model_vary_pm_perp():

    # ----------------------------------------------------------
    # Vary the proper motion perpendicular to the stream:

    p_b15 = [
        0.60122692,
        0.36273147,
        -0.97591502,
        -3.34169377,
        0.71877924,
        -0.01519337,
        -0.01928001,
    ]
    progs = []
    progfs = []
    times = np.linspace(0.0, 2.5, 101)
    pms = np.linspace(-0.3, 0.3, 101)
    for pm in pms:
        pot = mw_pot.setup_potential(p_b15, 1.0, False, False, REFR0, REFV0)
        prog = Orbit(
            [
                229.018,
                -0.124,
                23.2,
                -2.296 + pm,
                -2.257 - 2.296 / 2.257 * pm,
                -58.7,
            ],
            radec=True,
            ro=REFR0,
            vo=REFV0,
            solarmotion=[-11.1, 24.0, 7.25],
        )
        prog.integrate(times, pot)
        progs.append(prog)
        prog = Orbit(
            [
                229.018,
                -0.124,
                23.2,
                -2.296 + pm,
                -2.257 - 2.296 / 2.257 * pm,
                -58.7,
            ],
            radec=True,
            ro=REFR0,
            vo=REFV0,
            solarmotion=[-11.1, 24.0, 7.25],
        ).flip()
        prog.integrate(times, pot)
        prog.flip(inplace=True)
        progfs.append(prog)

    plt.figure(figsize=(12, 4))
    for pm, orb, orbf in zip(pms, progs, progfs):
        tc = cmap((pm - np.amin(pms)) / (np.amax(pms) - np.amin(pms)))
        plt.subplot(1, 2, 1)
        orb.plot(d1="ra", d2="dec", color=tc, overplot=True)
        orbf.plot(d1="ra", d2="dec", color=tc, overplot=True)
        plt.subplot(1, 2, 2)
        orb.plot(d1="ra", d2="vlos", color=tc, overplot=True)
        orbf.plot(d1="ra", d2="vlos", color=tc, overplot=True)
    plot_data_add_labels(color="k")
    add_colorbar(
        np.amin(pms),
        np.amax(pms),
        r"$\mathrm{proper\ motion\ offset}\,(\mathrm{mas\,yr}^{-1})$",
        save_figures=False,
    )
    plt.savefig("figures/varypm-perp.pdf")
Пример #4
0
def model_vary_b_for_c_1_pa_45():

    # ----------------------------------------------------------
    # Vary $b$ for $c=1$ (pa=45 degree):

    p_b15 = [
        0.60122692,
        0.36273147,
        -0.97591502,
        -3.34169377,
        0.71877924,
        -0.01519337,
        -0.01928001,
    ]
    progs = []
    progfs = []
    times = np.linspace(0.0, 3.0, 101)
    bs = np.arange(0.5, 2.1, 0.1)
    for b in bs:
        pot = mw_pot.setup_potential(p_b15,
                                     1.0,
                                     False,
                                     False,
                                     REFR0,
                                     REFV0,
                                     b=b,
                                     pa=np.pi / 4.0)
        prog = Orbit(
            [229.018, -0.124, 23.2, -2.296, -2.257, -58.7],
            radec=True,
            ro=REFR0,
            vo=REFV0,
            solarmotion=[-11.1, 24.0, 7.25],
        )
        prog.integrate(times, pot)
        progs.append(prog)
        prog = Orbit(
            [229.018, -0.124, 23.2, -2.296, -2.257, -58.7],
            radec=True,
            ro=REFR0,
            vo=REFV0,
            solarmotion=[-11.1, 24.0, 7.25],
        ).flip()
        prog.integrate(times, pot)
        prog.flip(inplace=True)
        progfs.append(prog)

    # -------------------------------------------

    plt.figure(figsize=(12, 4))

    for b, orb, orbf in zip(bs, progs, progfs):
        tc = cmap((b - 0.5) / 1.5)
        plt.subplot(1, 2, 1)
        orb.plot(d1="ra", d2="dec", color=tc, overplot=True)
        orbf.plot(d1="ra", d2="dec", color=tc, overplot=True)
        plt.subplot(1, 2, 2)
        orb.plot(d1="ra", d2="vlos", color=tc, overplot=True)
        orbf.plot(d1="ra", d2="vlos", color=tc, overplot=True)

    plot_data_add_labels(color="k")
    add_colorbar(0.5, 2.0, r"$b$", save_figures=False)
    plt.savefig("figures/varyb_c-1_pa-45.pdf")

    return
Пример #5
0
def model_vary_c_along_the_best_fit_line():

    bf_savefilename = _MW_POT_SCRIPT_FOLDER + "/output/mwpot14varyc-bf.pkl"
    if os.path.exists(bf_savefilename):
        with open(bf_savefilename, "rb") as savefile:
            cs = pickle.load(savefile)
            bf_params = pickle.load(savefile)
    else:
        IOError(("Need to calculate best-fit potentials for different c "
                 "in MWPotential2014-varyc.ipynb first"))
    bf_params = np.array(bf_params)
    bf_params = bf_params[cs <= 3.0]
    cs = cs[cs <= 3.0]

    # ----------------------------------------------------------

    progs = []
    progfs = []
    times = np.linspace(0.0, 3.0, 101)

    for bp, c in zip(bf_params, cs):
        pot = mw_pot.setup_potential(bp, c, False, False, REFR0, REFV0)
        prog = Orbit(
            [229.018, -0.124, 23.2, -2.296, -2.257, -58.7],
            radec=True,
            ro=REFR0,
            vo=REFV0,
            solarmotion=[-11.1, 24.0, 7.25],
        )
        prog.integrate(times, pot)
        progs.append(prog)
        prog = Orbit(
            [229.018, -0.124, 23.2, -2.296, -2.257, -58.7],
            radec=True,
            ro=REFR0,
            vo=REFV0,
            solarmotion=[-11.1, 24.0, 7.25],
        ).flip()
        prog.integrate(times, pot)
        prog.flip(inplace=True)
        progfs.append(prog)

    # ----------------------------------------------------------
    # Vary $c$ along the best-fit line

    plt.figure(figsize=(12, 4))

    for c, orb, orbf in zip(cs, progs, progfs):
        tc = cmap((c - 0.5) / 2.5)
        plt.subplot(1, 2, 1)
        orb.plot(d1="ra", d2="dec", color=tc, overplot=True)
        orbf.plot(d1="ra", d2="dec", color=tc, overplot=True)
        plt.subplot(1, 2, 2)
        orb.plot(d1="ra", d2="vlos", color=tc, overplot=True)
        orbf.plot(d1="ra", d2="vlos", color=tc, overplot=True)

    plot_data_add_labels(color="k")
    add_colorbar(0.5, 3.0, r"$c$", save_figures=False)
    plt.savefig("figures/varyc_bestfitline.pdf")

    return
Пример #6
0
def fiducial_model(
    sdf_trailing="output/sdf_trailing.pkl",
    sdf_leading="output/sdf_leading.pkl",
    threshold=0.3,
    ro=REFR0,
    vo=REFV0,
):
    """Fiducial Model.

    The fiducial model assumes a spherical halo, with the best-fit
    parameters from fitting to the MWPotential2014 data

    """
    p_b15 = [
        0.60122692,
        0.36273147,
        -0.97591502,
        -3.34169377,
        0.71877924,
        -0.01519337,
        -0.01928001,
    ]

    pot = mw_pot.setup_potential(p_b15, 1.0, False, False, ro, vo)

    prog = Orbit(
        [229.018, -0.124, 23.2, -2.296, -2.257, -58.7],
        radec=True,
        ro=ro,
        vo=vo,
        solarmotion=[-11.1, 24.0, 7.25],
    )
    aAI = actionAngleIsochroneApprox(pot=pot, b=0.8)
    sigv = 0.2

    # ----------------------------------------------------------

    try:
        with open(sdf_trailing, "rb") as file:
            sdf_trailing = pickle.load(file)
    except Exception:
        sdf_trailing = streamdf(
            sigv / vo,
            progenitor=prog,
            pot=pot,
            aA=aAI,
            leading=False,
            nTrackChunks=11,
            tdisrupt=10.0 / bovy_conversion.time_in_Gyr(vo, ro),
            ro=ro,
            vo=vo,
            R0=ro,
            vsun=[-11.1, vo + 24.0, 7.25],
            custom_transform=pal5_util._TPAL5,
        )
        with open(sdf_trailing, "wb") as file:
            pickle.dump(sdf_trailing, file)

    try:
        with open(sdf_leading, "rb") as file:
            sdf_leading = pickle.load(file)
    except Exception:
        sdf_leading = streamdf(
            sigv / vo,
            progenitor=prog,
            pot=pot,
            aA=aAI,
            leading=True,
            nTrackChunks=11,
            tdisrupt=10.0 / bovy_conversion.time_in_Gyr(vo, ro),
            ro=ro,
            vo=vo,
            R0=ro,
            vsun=[-11.1, vo + 24.0, 7.25],
            custom_transform=pal5_util._TPAL5,
        )
        with open(sdf_leading, "wb") as file:
            pickle.dump(sdf_leading, file)

    # ----------------------------------------------------------

    print("Angular length: %f deg (leading,trailing)=(%f,%f) deg" % (
        sdf_leading.length(ang=True, coord="customra", threshold=threshold) +
        sdf_trailing.length(ang=True, coord="customra", threshold=threshold),
        sdf_leading.length(ang=True, coord="customra", threshold=threshold),
        sdf_trailing.length(ang=True, coord="customra", threshold=threshold),
    ))
    print("Angular width (FWHM): %f arcmin" %
          (pal5_util.width_trailing(sdf_trailing)))
    print("Velocity dispersion: %f km/s" %
          (pal5_util.vdisp_trailing(sdf_trailing)))

    # ----------------------------------------------------------

    trackRADec_trailing = bovy_coords.lb_to_radec(
        sdf_trailing._interpolatedObsTrackLB[:, 0],
        sdf_trailing._interpolatedObsTrackLB[:, 1],
        degree=True,
    )
    trackRADec_leading = bovy_coords.lb_to_radec(
        sdf_leading._interpolatedObsTrackLB[:, 0],
        sdf_leading._interpolatedObsTrackLB[:, 1],
        degree=True,
    )
    lb_sample_trailing = sdf_trailing.sample(n=10000, lb=True)
    lb_sample_leading = sdf_leading.sample(n=10000, lb=True)
    radec_sample_trailing = bovy_coords.lb_to_radec(lb_sample_trailing[0],
                                                    lb_sample_trailing[1],
                                                    degree=True)
    radec_sample_leading = bovy_coords.lb_to_radec(lb_sample_leading[0],
                                                   lb_sample_leading[1],
                                                   degree=True)

    # ----------------------------------------------------------
    # plotting

    plt.figure(figsize=(12, 4))
    plt.subplot(1, 2, 1)
    bovy_plot.bovy_plot(
        trackRADec_trailing[:, 0],
        trackRADec_trailing[:, 1],
        color=sns.color_palette()[0],
        xrange=[250.0, 210.0],
        yrange=[-15.0, 9.0],
        xlabel=r"$\mathrm{RA}\,(\mathrm{degree})$",
        ylabel=r"$\mathrm{Dec}\,(\mathrm{degree})$",
        gcf=True,
    )
    bovy_plot.bovy_plot(
        trackRADec_leading[:, 0],
        trackRADec_leading[:, 1],
        color=sns.color_palette()[0],
        overplot=True,
    )
    plt.plot(
        radec_sample_trailing[:, 0],
        radec_sample_trailing[:, 1],
        "k.",
        alpha=0.01,
        zorder=0,
    )
    plt.plot(
        radec_sample_leading[:, 0],
        radec_sample_leading[:, 1],
        "k.",
        alpha=0.01,
        zorder=0,
    )
    plt.errorbar(
        pos_radec[:, 0],
        pos_radec[:, 1],
        yerr=pos_radec[:, 2],
        ls="none",
        marker="o",
        color=sns.color_palette()[2],
    )
    plt.subplot(1, 2, 2)
    bovy_plot.bovy_plot(
        trackRADec_trailing[:, 0],
        sdf_trailing._interpolatedObsTrackLB[:, 3],
        color=sns.color_palette()[0],
        xrange=[250.0, 210.0],
        yrange=[-80.0, 0.0],
        xlabel=r"$\mathrm{RA}\,(\mathrm{degree})$",
        ylabel=r"$V_{\mathrm{los}}\,(\mathrm{km\,s}^{-1})$",
        gcf=True,
    )
    bovy_plot.bovy_plot(
        trackRADec_leading[:, 0],
        sdf_leading._interpolatedObsTrackLB[:, 3],
        color=sns.color_palette()[0],
        overplot=True,
    )
    plt.plot(
        radec_sample_trailing[:, 0],
        lb_sample_trailing[3],
        "k.",
        alpha=0.01,
        zorder=0,
    )
    plt.plot(
        radec_sample_leading[:, 0],
        lb_sample_leading[3],
        "k.",
        alpha=0.01,
        zorder=0,
    )
    plt.errorbar(
        rvel_ra[:, 0],
        rvel_ra[:, 1],
        yerr=rvel_ra[:, 2],
        ls="none",
        marker="o",
        color=sns.color_palette()[2],
    )

    plt.savefig("figures/fiducial_model.pdf")

    return
def main(args: Optional[list] = None, opts: Optional[Namespace] = None):
    """Fit MWPotential2014 Script Function.

    Parameters
    ----------
    args : list, optional
        an optional single argument that holds the sys.argv list,
        except for the script name (e.g., argv[1:])
    opts : Namespace, optional
        pre-constructed results of parsed args
        if not None, used ONLY if args is None

    """
    if opts is not None and args is None:
        pass
    else:
        if opts is not None:
            warnings.warn("Not using `opts` because `args` are given")
        parser = make_parser()
        opts = parser.parse_args(args)

    fpath = opts.fpath + "/" if not opts.fpath.endswith("/") else opts.fpath
    opath = opts.opath + "/" if not opts.opath.endswith("/") else opts.opath

    # plot chains
    print("Plotting Chains")
    fig = mcmc_util.plot_chains(opath)
    fig.savefig(fpath + "chains.pdf")
    plt.close(fig)

    print("Need to continue chains:", end=" ")
    for i in range(32):
        ngood = mcmc_util.determine_nburn(
            filename=opath + f"mwpot14-fitsigma-{i:02}.dat", return_nsamples=True,
        )
        if ngood < 4000:
            print(f"{i:02} (N={ngood})", end=", ")

    ###############################################################
    # RESULTING PDFS

    data, _, weights, _ = read_mcmc(nburn=None, skip=1, evi_func=lambda x: 1.0)

    plot_corner(data, weights=weights)
    plt.savefig("figures/PDFs/corner.pdf")
    plt.close()

    # --------------

    savefilename = "output/pal5_forces_mcmc.pkl"
    if not os.path.exists(savefilename):
        data_wf, index_wf, weights_wf, evi_wf = read_mcmc(
            nburn=None, addforces=True, skip=1, evi_func=lambda x: 1.0
        )
        save_pickles(savefilename, data_wf, index_wf, weights_wf, evi_wf)
    else:
        with open(savefilename, "rb") as savefile:
            data_wf = pickle.load(savefile)
            index_wf = pickle.load(savefile)
            weights_wf = pickle.load(savefile)
            evi_wf = pickle.load(savefile)

    # --------------
    plot_corner(data_wf, weights=weights_wf, addvcprior=False)
    plt.savefig("figures/PDFs/corner_wf.pdf")
    plt.close()

    # --------------
    # Which potential is preferred?
    data_noforce, potindx, weights, evidences = read_mcmc(evi_func=evi_harmonic)

    fig = plt.figure(figsize=(6, 4))
    bovy_plot.bovy_plot(
        potindx,
        np.log(evidences),
        "o",
        xrange=[-1, 34],
        yrange=[-35, -22],
        xlabel=r"$\mathrm{Potential\ index}$",
        ylabel=r"$\ln\ \mathrm{evidence}$",
    )
    data_noforce, potindx, weights, evidences = read_mcmc(evi_func=evi_laplace)
    bovy_plot.bovy_plot(potindx, np.log(evidences) - 30.0, "d", overplot=True)
    data_noforce, potindx, weights, evidences = read_mcmc(
        evi_func=lambda x: np.exp(np.amax(x[:, -1]))
    )
    bovy_plot.bovy_plot(potindx, np.log(evidences) - 8.0, "s", overplot=True)
    data_noforce, potindx, weights, evidences = read_mcmc(
        evi_func=lambda x: np.exp(-25.0)
        if (np.log(evi_harmonic(x)) > -25.0)
        else np.exp(-50.0)
    )
    bovy_plot.bovy_plot(potindx, np.log(evidences), "o", overplot=True)
    plt.savefig("figures/PDFs/preferred_pot.pdf")
    plt.close()

    ###############################################################
    # Look at the results for individual potentials

    # --------------
    # The flattening $c$
    npot = 32
    nwalkers = 12

    plt.figure(figsize=(16, 6))
    cmap = cm.plasma
    maxl = np.zeros((npot, 2))
    for en, ii in enumerate(range(npot)):
        data_ip, _, weights_ip, evi_ip = read_mcmc(singlepot=ii, evi_func=evi_harmonic)
        try:
            maxl[en, 0] = np.amax(data_ip[:, -1])
            maxl[en, 1] = np.log(evi_ip[0])
        except ValueError:
            maxl[en] = -10000000.0
        plt.subplot(2, 4, en // 4 + 1)
        bovy_plot.bovy_hist(
            data_ip[:, 0],
            range=[0.5, 2.0],
            bins=26,
            histtype="step",
            color=cmap((en % 4) / 3.0),
            normed=True,
            xlabel=r"$c$",
            lw=1.5,
            overplot=True,
        )
        if en % 4 == 0:
            bovy_plot.bovy_text(
                r"$\mathrm{Potential\ %i\ to\ % i}$" % (en, en + 3),
                size=17.0,
                top_left=True,
            )
    plt.tight_layout()
    plt.savefig("figures/flattening_c.pdf")
    plt.close()

    ###############################################################
    # What is the effective prior in $(F_R,F_Z)$?

    frfzprior_savefilename = "frfzprior.pkl"
    if not os.path.exists(frfzprior_savefilename):
        # Compute for each potential separately
        nvoc = 10000
        ro = 8.0
        npot = 32
        fs = np.zeros((2, nvoc, npot))
        for en, ii in tqdm(enumerate(range(npot))):
            fn = f"output/fitsigma/mwpot14-fitsigma-{i:02}.dat"
            # Read the potential parameters
            with open(fn, "r") as savefile:
                line1 = savefile.readline()
            potparams = [float(s) for s in (line1.split(":")[1].split(","))]
            for jj in range(nvoc):
                c = np.random.uniform() * 1.5 + 0.5
                tvo = np.random.uniform() * 50.0 + 200.0
                pot = mw_pot.setup_potential(potparams, c, False, False, REFR0, tvo)
                fs[:, jj, ii] = np.array(pal5_util.force_pal5(pot, 23.46, REFR0, tvo))[
                    :2
                ]
        save_pickles(frfzprior_savefilename, fs)
    else:
        with open(frfzprior_savefilename, "rb") as savefile:
            fs = pickle.load(savefile)

    # --------------
    plt.figure(figsize=(6, 6))
    bovy_plot.scatterplot(
        fs[0].flatten(),
        fs[1].flatten(),
        "k,",
        xrange=[-1.75, -0.25],
        yrange=[-2.5, -1.2],
        xlabel=r"$F_R(\mathrm{Pal\ 5})$",
        ylabel=r"$F_Z(\mathrm{Pal\ 5})$",
        onedhists=True,
    )
    bovy_plot.scatterplot(
        data_wf[:, 7],
        data_wf[:, 8],
        weights=weights_wf,
        bins=26,
        xrange=[-1.75, -0.25],
        yrange=[-2.5, -1.2],
        justcontours=True,
        cntrcolors="w",
        overplot=True,
        onedhists=True,
    )
    plt.axvline(-0.81, color=sns.color_palette()[0])
    plt.axhline(-1.85, color=sns.color_palette()[0])
    plt.savefig("figures/effective_force_prior.pdf")
    plt.close()

    # --------------
    # The ratio of the posterior and the prior

    bovy_plot.bovy_print(
        axes_labelsize=17.0,
        text_fontsize=12.0,
        xtick_labelsize=14.0,
        ytick_labelsize=14.0,
    )
    plt.figure(figsize=(12.5, 4))

    def axes_white():
        for k, spine in plt.gca().spines.items():  # ax.spines is a dictionary
            spine.set_color("w")
        plt.gca().tick_params(axis="x", which="both", colors="w")
        plt.gca().tick_params(axis="y", which="both", colors="w")
        [t.set_color("k") for t in plt.gca().xaxis.get_ticklabels()]
        [t.set_color("k") for t in plt.gca().yaxis.get_ticklabels()]
        return None

    bins = 32
    trange = [[-1.75, -0.25], [-2.5, -1.2]]
    tw = copy.deepcopy(weights_wf)
    tw[index_wf == 14] = 0.0  # Didn't converge properly
    H_prior, xedges, yedges = np.histogram2d(
        fs[0].flatten(), fs[1].flatten(), bins=bins, range=trange, normed=True
    )
    H_post, xedges, yedges = np.histogram2d(
        data_wf[:, 7], data_wf[:, 8], weights=tw, bins=bins, range=trange, normed=True,
    )
    H_like = H_post / H_prior
    H_like[H_prior == 0.0] = 0.0
    plt.subplot(1, 3, 1)
    bovy_plot.bovy_dens2d(
        H_prior.T,
        origin="lower",
        cmap="viridis",
        interpolation="nearest",
        xrange=[xedges[0], xedges[-1]],
        yrange=[yedges[0], yedges[-1]],
        xlabel=r"$F_R(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$",
        ylabel=r"$F_Z(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$",
        gcf=True,
    )
    bovy_plot.bovy_text(r"$\mathbf{Prior}$", top_left=True, size=19.0, color="w")
    axes_white()
    plt.subplot(1, 3, 2)
    bovy_plot.bovy_dens2d(
        H_post.T,
        origin="lower",
        cmap="viridis",
        interpolation="nearest",
        xrange=[xedges[0], xedges[-1]],
        yrange=[yedges[0], yedges[-1]],
        xlabel=r"$F_R(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$",
        gcf=True,
    )
    bovy_plot.bovy_text(r"$\mathbf{Posterior}$", top_left=True, size=19.0, color="w")
    axes_white()
    plt.subplot(1, 3, 3)
    bovy_plot.bovy_dens2d(
        H_like.T,
        origin="lower",
        cmap="viridis",
        interpolation="nearest",
        vmin=0.1,
        vmax=4.0,
        xrange=[xedges[0], xedges[-1]],
        yrange=[yedges[0], yedges[-1]],
        xlabel=r"$F_R(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$",
        gcf=True,
    )
    bovy_plot.bovy_text(r"$\mathbf{Likelihood}$", top_left=True, size=19.0, color="w")
    axes_white()

    def qline(FR, q=0.95):
        return 2.0 * FR / q ** 2.0

    q = 0.94
    plt.plot([-1.25, -0.2], [qline(-1.25, q=q), qline(-0.2, q=q)], "w--")
    bovy_plot.bovy_text(-1.7, -2.2, r"$q_\Phi = 0.94$", size=16.0, color="w")
    plt.plot((-1.25, -1.02), (-2.19, qline(-1.02, q=q)), "w-", lw=0.8)

    plt.tight_layout()
    plt.savefig(
        "figures/pal5post.pdf", bbox_inches="tight",
    )
    plt.close()

    # --------------
    # Projection onto the direction perpendicular to constant $q = 0.94$:
    frs = np.tile(0.5 * (xedges[:-1] + xedges[1:]), (len(yedges) - 1, 1)).T
    fzs = np.tile(0.5 * (yedges[:-1] + yedges[1:]), (len(xedges) - 1, 1))
    plt.figure(figsize=(6, 4))
    txlabel = r"$F_\perp$"
    dum = bovy_plot.bovy_hist(
        (-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten(),
        weights=H_prior.flatten(),
        bins=21,
        histtype="step",
        lw=2.0,
        xrange=[-1.5, 1.5],
        xlabel=txlabel,
        normed=True,
    )
    dum = bovy_plot.bovy_hist(
        (-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten(),
        weights=H_post.flatten(),
        bins=21,
        histtype="step",
        lw=2.0,
        overplot=True,
        xrange=[-1.5, 1.5],
        normed=True,
    )
    dum = bovy_plot.bovy_hist(
        (-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten(),
        weights=H_like.flatten(),
        bins=21,
        histtype="step",
        lw=2.0,
        overplot=True,
        xrange=[-1.5, 1.5],
        normed=True,
    )
    plt.savefig("figures/PDFs/projection_perp_to_q0p94.pdf")
    plt.close()

    mq = (
        np.sum(
            (-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten()
            * H_like.flatten()
        )
    ) / np.sum(H_like.flatten())

    print(
        mq,
        np.sqrt(
            (
                np.sum(
                    ((-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten() - mq)
                    ** 2.0
                    * H_like.flatten()
                )
            )
            / np.sum(H_like.flatten())
        ),
    )

    # --------------
    # Projection onto the direction parallel to constant $q = 0.94$:
    frs = np.tile(0.5 * (xedges[:-1] + xedges[1:]), (len(yedges) - 1, 1)).T
    fzs = np.tile(0.5 * (yedges[:-1] + yedges[1:]), (len(xedges) - 1, 1))
    plt.figure(figsize=(6, 4))
    txlabel = r"$F_\parallel$"
    dum = bovy_plot.bovy_hist(
        (0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten(),
        weights=H_prior.flatten(),
        bins=21,
        histtype="step",
        lw=2.0,
        xrange=[-2.5, 2.5],
        xlabel=txlabel,
        normed=True,
    )
    dum = bovy_plot.bovy_hist(
        (0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten(),
        weights=H_post.flatten(),
        bins=21,
        histtype="step",
        lw=2.0,
        overplot=True,
        xrange=[-2.5, 2.5],
        normed=True,
    )
    dum = bovy_plot.bovy_hist(
        (0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten(),
        weights=H_like.flatten(),
        bins=21,
        histtype="step",
        lw=2.0,
        overplot=True,
        xrange=[-2.5, 2.5],
        normed=True,
    )
    plt.savefig("figures/PDFs/projection_prll_to_q0p94.pdf")
    plt.close()
    mq = (
        np.sum(
            (0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten()
            * H_like.flatten()
        )
    ) / np.sum(H_like.flatten())
    print(
        mq,
        np.sqrt(
            (
                np.sum(
                    ((0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten() - mq)
                    ** 2.0
                    * H_like.flatten()
                )
            )
            / np.sum(H_like.flatten())
        ),
    )

    # --------------
    # Thus, there is only a weak constraint on $F_\parallel$.

    nrow = int(np.ceil(npot / 4.0))
    plt.figure(figsize=(16, nrow * 4))
    for en, ii in enumerate(range(npot)):
        plt.subplot(nrow, 4, en + 1)
        if ii % 4 == 0:
            tylabel = r"$F_Z(\mathrm{Pal\ 5})$"
        else:
            tylabel = None
        if ii // 4 == nrow - 1:
            txlabel = r"$F_R(\mathrm{Pal\ 5})$"
        else:
            txlabel = None
        bovy_plot.scatterplot(
            fs[0][:, en],
            fs[1][:, en],
            "k,",
            xrange=[-1.75, -0.25],
            yrange=[-2.5, -1.0],
            xlabel=txlabel,
            ylabel=tylabel,
            gcf=True,
        )
        bovy_plot.scatterplot(
            data_wf[:, 7],
            data_wf[:, 8],
            weights=weights_wf,
            bins=26,
            xrange=[-1.75, -0.25],
            yrange=[-2.5, -1.0],
            justcontours=True,
            cntrcolors="w",
            overplot=True,
        )
        bovy_plot.scatterplot(
            data_wf[index_wf == ii, 7],
            data_wf[index_wf == ii, 8],
            weights=weights_wf[index_wf == ii],
            bins=26,
            xrange=[-1.75, -0.25],
            yrange=[-2.5, -1.0],
            justcontours=True,
            # cntrcolors=sns.color_palette()[2],
            overplot=True,
        )
        plt.axvline(-0.80, color=sns.color_palette()[0])
        plt.axhline(-1.83, color=sns.color_palette()[0])
        bovy_plot.bovy_text(r"$\mathrm{Potential}\ %i$" % ii, size=17.0, top_left=True)
    plt.savefig("figures/PDFs/constain_F_prll.pdf")
    plt.close()

    # --------------
    # Let's plot four representative ones for the paper:

    bovy_plot.bovy_print(
        axes_labelsize=17.0,
        text_fontsize=12.0,
        xtick_labelsize=14.0,
        ytick_labelsize=14.0,
    )
    nullfmt = NullFormatter()
    nrow = 1

    plt.figure(figsize=(15, nrow * 4))
    for en, ii in enumerate([0, 15, 24, 25]):
        plt.subplot(nrow, 4, en + 1)
        if en % 4 == 0:
            tylabel = (
                r"$F_Z(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$"
            )
        else:
            tylabel = None
        if en // 4 == nrow - 1:
            txlabel = (
                r"$F_R(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$"
            )
        else:
            txlabel = None
        bovy_plot.scatterplot(
            fs[0][:, ii],
            fs[1][:, ii],
            "k,",
            bins=31,
            xrange=[-1.75, -0.25],
            yrange=[-2.5, -1.0],
            xlabel=txlabel,
            ylabel=tylabel,
            gcf=True,
        )
        bovy_plot.scatterplot(
            data_wf[:, 7],
            data_wf[:, 8],
            weights=weights_wf,
            bins=21,
            xrange=[-1.75, -0.25],
            yrange=[-2.5, -1.0],
            justcontours=True,
            cntrcolors=sns.color_palette("colorblind")[2],
            cntrls="--",
            cntrlw=2.0,
            overplot=True,
        )
        bovy_plot.scatterplot(
            data_wf[index_wf == ii, 7],
            data_wf[index_wf == ii, 8],
            weights=weights_wf[index_wf == ii],
            bins=21,
            xrange=[-1.75, -0.25],
            yrange=[-2.5, -1.0],
            justcontours=True,
            cntrcolors=sns.color_palette("colorblind")[0],
            cntrlw=2.5,
            overplot=True,
        )
        if en > 0:
            plt.gca().yaxis.set_major_formatter(nullfmt)

    plt.tight_layout()
    plt.savefig(
        "figures/pal5post_examples.pdf", bbox_inches="tight",
    )
    plt.close()

    ###############################################################
    # What about $q_\Phi$?

    bins = 47
    plt.figure(figsize=(6, 4))
    dum = bovy_plot.bovy_hist(
        np.sqrt(2.0 * fs[0].flatten() / fs[1].flatten()),
        histtype="step",
        lw=2.0,
        bins=bins,
        xlabel=r"$q_\mathrm{\Phi}$",
        xrange=[0.7, 1.25],
        normed=True,
    )
    dum = bovy_plot.bovy_hist(
        np.sqrt(16.8 / 8.4 * data_wf[:, -2] / data_wf[:, -1]),
        weights=weights_wf,
        histtype="step",
        lw=2.0,
        bins=bins,
        overplot=True,
        xrange=[0.7, 1.25],
        normed=True,
    )
    mq = np.sum(
        np.sqrt(16.8 / 8.4 * data_wf[:, -2] / data_wf[:, -1]) * weights_wf
    ) / np.sum(weights_wf)
    sq = np.sqrt(
        np.sum(
            (np.sqrt(16.8 / 8.4 * data_wf[:, -2] / data_wf[:, -1]) - mq) ** 2.0
            * weights_wf
        )
        / np.sum(weights_wf)
    )
    print("From posterior samples: q = %.3f +/- %.3f" % (mq, sq))
    Hq_post, xedges = np.histogram(
        np.sqrt(16.8 / 8.4 * data_wf[:, -2] / data_wf[:, -1]),
        weights=weights_wf,
        bins=bins,
        range=[0.7, 1.25],
        normed=True,
    )
    Hq_prior, xedges = np.histogram(
        np.sqrt(2.0 * fs[0].flatten() / fs[1].flatten()),
        bins=bins,
        range=[0.7, 1.25],
        normed=True,
    )
    qs = 0.5 * (xedges[:-1] + xedges[1:])
    Hq_like = Hq_post / Hq_prior
    Hq_like[Hq_post == 0.0] = 0.0
    mq = np.sum(qs * Hq_like) / np.sum(Hq_like)
    sq = np.sqrt(np.sum((qs - mq) ** 2.0 * Hq_like) / np.sum(Hq_like))
    print("From likelihood of samples: q = %.3f +/- %.3f" % (mq, sq))

    plt.savefig("figures/q_phi.pdf")
    plt.close()

    # It appears that $q_\Phi$ is the quantity that is the most strongly constrained by the Pal 5 data.

    ###############################################################
    # A sampling of tracks from the MCMC

    savefilename = "mwpot14-pal5-mcmcTracks.pkl"
    pmdecpar = 2.257 / 2.296
    pmdecperp = -2.296 / 2.257
    if os.path.exists(savefilename):
        with open(savefilename, "rb") as savefile:
            pal5_track_samples = pickle.load(savefile)
            forces = pickle.load(savefile)
            all_potparams = pickle.load(savefile)
            all_params = pickle.load(savefile)
    else:
        np.random.seed(1)
        ntracks = 21
        multi = 8
        pal5_track_samples = np.zeros((ntracks, 2, 6, pal5varyc[0].shape[1]))
        forces = np.zeros((ntracks, 2))
        all_potparams = np.zeros((ntracks, 5))
        all_params = np.zeros((ntracks, 7))
        for ii in range(ntracks):
            # Pick a random potential from among the set, but leave 14 out
            pindx = 14
            while pindx == 14:
                pindx = np.random.permutation(32)[0]
            # Load this potential
            fn = f"output/fitsigma/mwpot14-fitsigma-{pindx:02}.dat"
            with open(fn, "r") as savefile:
                line1 = savefile.readline()
            potparams = [float(s) for s in (line1.split(":")[1].split(","))]
            all_potparams[ii] = potparams
            # Now pick a random sample from this MCMC chain
            tnburn = mcmc_util.determine_nburn(fn)
            tdata = np.loadtxt(fn, comments="#", delimiter=",")
            tdata = tdata[tnburn::]
            tdata = tdata[np.random.permutation(len(tdata))[0]]
            all_params[ii] = tdata
            tvo = tdata[1] * REFV0
            pot = mw_pot.setup_potential(potparams, tdata[0], False, False, REFR0, tvo)
            forces[ii, :] = pal5_util.force_pal5(pot, 23.46, REFR0, tvo)[:2]
            # Now compute the stream model for this setup
            dist = tdata[2] * 22.0
            pmra = -2.296 + tdata[3] + tdata[4]
            pmdecpar = 2.257 / 2.296
            pmdecperp = -2.296 / 2.257
            pmdec = -2.257 + tdata[3] * pmdecpar + tdata[4] * pmdecperp
            vlos = -58.7
            sigv = 0.4 * np.exp(tdata[5])
            prog = Orbit(
                [229.018, -0.124, dist, pmra, pmdec, vlos],
                radec=True,
                ro=REFR0,
                vo=tvo,
                solarmotion=[-11.1, 24.0, 7.25],
            )
            tsdf_trailing, tsdf_leading = pal5_util.setup_sdf(
                pot,
                prog,
                sigv,
                10.0,
                REFR0,
                tvo,
                multi=multi,
                nTrackChunks=8,
                trailing_only=False,
                verbose=True,
                useTM=False,
            )
            # Compute the track
            for jj, sdf in enumerate([tsdf_trailing, tsdf_leading]):
                trackRADec = bovy_coords.lb_to_radec(
                    sdf._interpolatedObsTrackLB[:, 0],
                    sdf._interpolatedObsTrackLB[:, 1],
                    degree=True,
                )
                trackpmRADec = bovy_coords.pmllpmbb_to_pmrapmdec(
                    sdf._interpolatedObsTrackLB[:, 4],
                    sdf._interpolatedObsTrackLB[:, 5],
                    sdf._interpolatedObsTrackLB[:, 0],
                    sdf._interpolatedObsTrackLB[:, 1],
                    degree=True,
                )
                # Store the track
                pal5_track_samples[ii, jj, 0] = trackRADec[:, 0]
                pal5_track_samples[ii, jj, 1] = trackRADec[:, 1]
                pal5_track_samples[ii, jj, 2] = sdf._interpolatedObsTrackLB[:, 2]
                pal5_track_samples[ii, jj, 3] = sdf._interpolatedObsTrackLB[:, 3]
                pal5_track_samples[ii, jj, 4] = trackpmRADec[:, 0]
                pal5_track_samples[ii, jj, 5] = trackpmRADec[:, 1]
        save_pickles(
            savefilename, pal5_track_samples, forces, all_potparams, all_params
        )

    # --------------
    bovy_plot.bovy_print(
        axes_labelsize=17.0,
        text_fontsize=12.0,
        xtick_labelsize=14.0,
        ytick_labelsize=14.0,
    )
    plt.figure(figsize=(12, 8))
    gs = gridspec.GridSpec(2, 2, wspace=0.225, hspace=0.1, right=0.94)
    ntracks = pal5_track_samples.shape[0]
    cmap = cm.plasma
    alpha = 0.7
    for ii in range(ntracks):
        tc = cmap((forces[ii, 1] + 2.5) / 1.0)
        for jj in range(2):
            # RA, Dec
            plt.subplot(gs[0])
            plt.plot(
                pal5_track_samples[ii, jj, 0],
                pal5_track_samples[ii, jj, 1],
                "-",
                color=tc,
                alpha=alpha,
            )
            # RA, Vlos
            plt.subplot(gs[1])
            plt.plot(
                pal5_track_samples[ii, jj, 0],
                pal5_track_samples[ii, jj, 3],
                "-",
                color=tc,
                alpha=alpha,
            )
            # RA, Dist
            plt.subplot(gs[2])
            plt.plot(
                pal5_track_samples[ii, jj, 0],
                pal5_track_samples[ii, jj, 2] - all_params[ii, 2] * 22.0,
                "-",
                color=tc,
                alpha=alpha,
            )
            # RA, pm_parallel
            plt.subplot(gs[3])
            plt.plot(
                pal5_track_samples[ii, jj, 0, : 500 + 500 * (1 - jj)],
                np.sqrt(1.0 + (2.257 / 2.296) ** 2.0)
                * (
                    (pal5_track_samples[ii, jj, 4, : 500 + 500 * (1 - jj)] + 2.296)
                    * pmdecperp
                    - (pal5_track_samples[ii, jj, 5, : 500 + 500 * (1 - jj)] + 2.257)
                )
                / (pmdecpar - pmdecperp),
                "-",
                color=tc,
                alpha=alpha,
            )
    plot_data_add_labels(
        p1=(gs[0],), p2=(gs[1],), noxlabel_dec=True, noxlabel_vlos=True
    )
    plt.subplot(gs[2])
    plt.xlim(250.0, 221.0)
    plt.ylim(-3.0, 1.5)
    bovy_plot._add_ticks()
    plt.xlabel(r"$\mathrm{RA}\,(\mathrm{degree})$")
    plt.ylabel(r"$\Delta\mathrm{Distance}\,(\mathrm{kpc})$")
    plt.subplot(gs[3])
    plt.xlim(250.0, 221.0)
    plt.ylim(-0.5, 0.5)
    bovy_plot._add_ticks()
    plt.xlabel(r"$\mathrm{RA}\,(\mathrm{degree})$")
    plt.ylabel(r"$\Delta\mu_\parallel\,(\mathrm{mas\,yr}^{-1})$")
    # Colorbar
    gs2 = gridspec.GridSpec(2, 1, wspace=0.0, left=0.95, right=0.975)
    plt.subplot(gs2[:, -1])
    sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=-2.5, vmax=-1.5))
    sm._A = []
    CB1 = plt.colorbar(sm, orientation="vertical", cax=plt.gca())
    CB1.set_label(
        r"$F_Z(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$",
        fontsize=18.0,
    )
    plt.savefig(
        "figures/pal5tracksamples.pdf", bbox_inches="tight",
    )
    plt.close()

    ###############################################################
    # What about Kuepper et al. (2015)?

    # Can we recover the Kuepper et al. (2015) result as prior + $q_\Phi =
    # 0.94 \pm 0.05$ + $V_c(R_0)$ between 200 and 280 km/s? For simplicity
    # we will not vary $R_0$, which should not have a big impact.

    s = sample_kuepper_flattening_post(50000, 0.94, 0.05)
    plot_kuepper_samples(s)
    plt.savefig("figures/kuepper_samples.pdf")
    plt.close()

    # The constraint on the potential flattening gets you far, but there
    # is more going on (the constraint on the halo mass and scale
    # parameter appear to come completely from the $V_c(R_0)$ constraint).
    # Let's add the weak constraint on the sum of the forces, scaled to
    # Kuepper et al.'s best-fit acceleration (which is higher than ours):

    s = sample_kuepper_flatteningforce_post(50000, 0.94, 0.05, -0.83, 0.36)
    plot_kuepper_samples(s)
    plt.savefig("figures/kuepper_samples_flatF.pdf")
    plt.close()

    # This gets a tight relation between $M_\mathrm{halo}$ and the scale
    # parameter of the halo, but does not lead to a constraint on either
    # independently; the halo potential flattening constraint is that of
    # Kuepper et al. Based on this, it appears that the information that
    # ties down $M_\mathrm{halo}$ comes from the overdensities, which may
    # be spurious (Thomas et al. 2016) and whose use in dynamical modeling
    # is dubious anyway.

    # What is Kuepper et al.'s prior on $a_{\mathrm{Pal\ 5}}$?

    apal5s = []
    ns = 100000
    for ii in range(ns):
        Mh = np.random.uniform() * (10.0 - 0.001) + 0.001
        a = np.random.uniform() * (100.0 - 0.1) + 0.1
        q = np.random.uniform() * (1.8 - 0.2) + 0.2
        pot = setup_potential_kuepper(Mh, a)
        FR, FZ = force_pal5_kuepper(pot, q)
        apal5s.append(np.sqrt(FR ** 2.0 + FZ ** 2.0))
    apal5s = np.array(apal5s)

    plt.figure(figsize=(6, 4))
    dum = bovy_plot.bovy_hist(
        apal5s, range=[0.0, 10.0], lw=2.0, bins=51, histtype="step", normed=True,
    )
    plt.savefig("figures/kuepper_samples_prior.pdf")
    plt.close()
def read_mcmc(
    filename: str = "output/fitsigma/mwpot14-fitsigma-*.dat",
    nburn: Optional[int] = None,
    evi_func: FunctionType = evi_laplace,
    evi_cut: float = -10.0,
    addforces: bool = False,
    addmwpot14weights: bool = False,
    singlepot: Optional[int] = None,
    skip: int = 1,
):
    """Read MCMC.

    Parameters
    ----------
    filename : str
    nburn : int, optional
    evi_func : FunctionType, optional
        evidence function
    evi_cut : float, optional
    addforces : bool, optional
    addmwpot14weights : bool, optional
    singlepot : int, optional
        whether to use a single potential, specified by number
        default (None) is to use all
    skip : int, optional


    Returns
    -------
    alldata
    indx : ndarray
        shape (N, )
    weights : ndarray
        shape (N, )
    evis: ndarray
        shape (N, )

    """
    fn = glob.glob(filename)  # filename

    alldata = np.zeros((0, 7 + 2 * addforces))
    indx = np.zeros((0, 1))
    weights = np.zeros((0, 1))
    evis = np.zeros((0, 1))

    for f in tqdm(fn):
        pindx = int(f.split("-")[2].split(".dat")[0])
        # if pindx == 14 or pindx > 27:
        #    print("Remember: skipping 14 and > 27 for now ...")
        #    continue
        if singlepot is not None and not pindx == singlepot:
            continue

        continue_flag = False
        try:
            if nburn is None:
                tnburn = mcmc_util.determine_nburn(f)
            else:
                tnburn = nburn
            tdata = np.loadtxt(f, comments="#", delimiter=",")
            tdata = tdata[tnburn::skip]
            tdata = tdata[tdata[:, -1] > np.nanmax(tdata[:, -1]) + evi_cut]
            if len(tdata) < 100:
                continue_flag = True
        except:
            continue_flag = True  # not enough samples yet

        if continue_flag:
            continue

        # Needs to be before addforces, because evi uses -1 as the lnlike index
        tweights = np.ones((len(tdata), 1)) / float(len(tdata)) * evi_func(tdata)
        evis = np.vstack((evis, np.ones((len(tdata), 1)) * evi_func(tdata)))
        if addforces:
            # Read the potential from the file
            with open(f, "r") as savefile:  # not byte b/c split with str
                line1 = savefile.readline()
            potparams = [float(s) for s in (line1.split(":")[1].split(","))]
            forces = np.empty((len(tdata), 2))
            for ee, c in enumerate(tdata[:, 0]):
                tvo = tdata[ee, 1] * REFV0
                pot = mw_pot.setup_potential(potparams, c, False, False, REFR0, tvo)
                forces[ee, :] = pal5_util.force_pal5(pot, 23.46, REFR0, tvo)[:2]
            tdata = np.hstack((tdata, forces))
        if addmwpot14weights:
            # Not terribly useful right now
            # Add the relative importance weights of this (c,vc) compared to the one
            # that this potential was sampled from
            # Read the potential from the file
            with open(f, "rb") as savefile:
                line1 = savefile.readline()
            potparams = [float(s) for s in (line1.split(":")[1].split(","))]
            # Also load the samples to find the c that this set was sampled with
            with open("mwpot14varyc-samples.pkl", "rb") as savefile:
                s = pickle.load(savefile)
            rndindx = np.argmin(np.fabs(s[0] - potparams[0]))
            pot_params = s[:, rndindx]
            print(pot_params[7])
            base_like = mw_pot.like_func(
                pot_params,
                pot_params[7],
                surfrs,
                kzs,
                kzerrs,
                termdata,
                700.0,
                False,
                False,
                False,
                False,
                REFR0,
                220.0,
            )
            for ee, c in enumerate(tdata[:, 0]):
                tvo = tdata[ee, 1] * REFV0
                tweights[ee] *= np.exp(
                    -mw_pot.like_func(
                        pot_params,
                        c,
                        surfrs,
                        kzs,
                        kzerrs,
                        termdata,
                        700.0,
                        False,
                        False,
                        False,
                        False,
                        REFR0,
                        tvo,
                    )  # last one is no vo prior
                    + base_like
                )
        # Only keep
        alldata = np.vstack((alldata, tdata))
        indx = np.vstack((indx, np.zeros((len(tdata), 1), dtype="int") + pindx))
        weights = np.vstack((weights, tweights))

    return alldata, indx[:, 0], weights[:, 0], evis[:, 0]