Exemplo n.º 1
0
    def calculate_masses(self,
                         snapnr=None,
                         gc_max_age=10,
                         gc_max_radius=250,
                         print_header=True):
        with suppress_stdout():
            # snapnr=None --> redshift zero
            s, sf = self.load_snapshot(snapnr=snapnr, loadonlytype=range(6))

        M200 = sf.data["fmc2"][0]  # 1e10 Msun
        r200 = sf.data["frc2"][0] * 1e3  # kpc
        istars, = numpy.where(  # stars within 10% of R200
            (s.type == 4) & (s.age > 0.) & (s.r() > 0.) &
            (s.r() < 0.1 * r200 / 1e3)
            & (s.halo == 0) & (s.subhalo == 0))
        Mstars_tenpercent_r200 = s.mass[istars].sum()

        # Gas fraction within 0.1*R200
        igas, = numpy.where(  # gas within 10% of R200
            (s.type == 0) & (s.r() > 0.) & (s.r() < 0.1 * r200 / 1e3)
            & (s.halo == 0) & (s.subhalo == 0))
        Mgas_tenpercent_r200 = s.mass[igas].sum()
        fgas = Mgas_tenpercent_r200 / (Mgas_tenpercent_r200 +
                                       Mstars_tenpercent_r200)

        from investigate_auriga_gcs import GlobularClusterSystem
        with suppress_stdout():
            GCS = GlobularClusterSystem(None,
                                        self.level,
                                        self.halo,
                                        radius=gc_max_radius,
                                        age=gc_max_age)

            GCS.set_FeH_allstars(s, sf)
            GCS.set_age_allstars(s, sf)
            GCS.set_FeH_oldstars(s, sf)

        Mgcs_red = s.mass[GCS.oldstars][GCS.old_red].sum()
        Mgcs_blue = s.mass[GCS.oldstars][GCS.old_blue].sum()
        Mgc = Mgcs_red + Mgcs_blue

        istellarhalo, = numpy.where(  # stars within
            (s.type == 4) & (s.age > 0.) & (s.r() > 0.) &
            (s.r() < GCS.radius / 1000.)
            & (s.halo == 0) & (s.subhalo == 0))
        Mstellarhalo = s.mass[istellarhalo].sum()

        if print_header:
            header = ["Run", "M200", "R200", "Mstar", "M*halo", "Mgc", "fgas"]
            print("{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}".format(
                *header))
        info = [
            self.name, M200, r200, Mstars_tenpercent_r200, Mstellarhalo, Mgc,
            fgas
        ]
        print("{:<10s}{:<10.2f}{:<10.2f}{:<10.2f}{:<10.2f}{:<10.2f}{:<10.2f}".
              format(*info))

        del s, sf, GCS
        return info if not print_header else [header, info]
Exemplo n.º 2
0
    def get_snapshot_spacing(self, verbose=False):
        if not hasattr(self, "nsnaps"):
            self.find_all_snapshots(verbose=verbose)
        from areposnap.gadget import gadget_readsnap
        times = numpy.zeros(self.nsnaps)
        redshifts = numpy.zeros(self.nsnaps)
        for i, snapnr in enumerate(range(self.nsnaps)):
            # CAUTION, reruns seem to complain "couldnt find units in file" for each snapshot :o
            with suppress_stdout():
                s = gadget_readsnap(snapnr,
                                    snappath=self.rundir + "/output/",
                                    onlyHeader=True)
            s.cosmology_init()
            redshifts[i] = s.redshift
            times[i] = s.cosmology_get_lookback_time_from_a(
                s.time.astype('float64'), is_flat=True)

            if verbose:
                print(
                    "snapnr = {0:03d},\tz = {1:.5f},\ta = {2:.5f},\ttime = {3:.2f} Gyr"
                    .format(snapnr, s.redshift, s.time, times[i]))

        self.cosmo = s.cosmo
        del s
        # s.time is actually scalefactor a which can be computed as a = 1/(1+z)
        self.times, self.redshifts = times, redshifts
Exemplo n.º 3
0
def figure_1_bottom(MW_h96e10, M31_cr16_scaled_to_MW, MW_v13, MW_rvir,
                    M31_rvir):
    fname = "figures/MW_M31_Rgc_Histogram.png"
    fig, ax = pyplot.subplots(figsize=(12, 9))
    with suppress_stdout():
        add_Rgc_MWandM31_to_ax(
            ax,
            MW_h96e10,
            M31_cr16_scaled_to_MW,
            M31_c11=None,
            MW_v13=MW_v13,
            show_cr16_age_subset=True,
            density=False,
            MW_rvir=MW_rvir,
            M31_rvir=M31_rvir,
        )
    ax.set_xlim(0.15, 260)
    ax.set_xscale("log")
    ax.legend(loc="upper left", frameon=False, fontsize=18)
    fig.savefig(fname)
    pyplot.close(fig)
    os.system("convert -trim {} {}".format(fname,
                                           fname.replace(".png", "-trim.png")))
    os.remove(fname)
    print("Saved {}".format(fname))
Exemplo n.º 4
0
def plot_harris1996_figure1_7_th(part2):
    fig, ax = pyplot.subplots(figsize=(12, 9))

    with suppress_stdout():  # invalid value encountered in < and/or >
        red, = numpy.where((part2["FeH"] < -1) & numpy.isfinite(part2["FeH"]))
        blue, = numpy.where((part2["FeH"] >= -1)
                            & numpy.isfinite(part2["FeH"]))

    bins, edges = numpy.histogram(part2["FeH"][red],
                                  bins=30,
                                  range=(-2.5, 0.5))
    pyplot.plot((edges[1:] + edges[:-1]) / 2,
                bins,
                drawstyle="steps-mid",
                c="r")
    ax.fill_between(edges[:-1],
                    bins,
                    lw=0.0,
                    hatch="/",
                    step="post",
                    edgecolor="red",
                    facecolor="none")

    bins, edges = numpy.histogram(part2["FeH"][blue],
                                  bins=30,
                                  range=(-2.5, 0.5))
    ax.fill_between(edges[:-1],
                    bins,
                    lw=0.0,
                    hatch="/",
                    step="post",
                    edgecolor="blue",
                    facecolor="none")
    pyplot.plot((edges[1:] + edges[:-1]) / 2,
                bins,
                drawstyle="steps-mid",
                c="b")

    FeH_range = numpy.arange(-2.8, 0.5, 0.01)
    ax.plot(FeH_range, 7.5 * g(FeH_range, -1.6, 0.3), c="k", ls="dashed")
    ax.plot(FeH_range, 3 * g(FeH_range, -0.6, 0.2), c="k", ls="dashed")

    ax.text(0.7,
            0.7,
            "N = {0}".format(len(red) + len(blue)),
            transform=ax.transAxes)

    ax.set_xticks(numpy.arange(-2.5, 0.5, 0.5))
    ax.set_xticks(numpy.arange(-2.8, 0.5, 0.1), minor=True)
    ax.set_yticks(numpy.arange(0, 25, 5))
    ax.set_yticks(numpy.arange(0, 25, 1), minor=True)
    pyplot.xlim(-2.8, 0.4)
    pyplot.ylim(0, 20)
    pyplot.xlabel("Cluster Metallicity [Fe/H]")
    pyplot.ylabel("Number per Bin")
    pyplot.show()
Exemplo n.º 5
0
def figure_4(auriga, MW_h96e10, M31_cr16, age_min):
    fname = "figures/FeH_mu_sigma_{:.1f}.png".format(age_min)
    with suppress_stdout():
        fig, mu_insituold_minus_mu_accreted_old = plot_FeH_mean_vs_std(
            auriga, MW_h96e10, M31_cr16, age_min=args.age_min, debug=False)
    fig.savefig(fname)
    pyplot.close(fig)
    os.system("convert -trim {} {}".format(fname,
                                           fname.replace(".png", "-trim.png")))
    os.remove(fname)
    print("Saved {}".format(fname))
Exemplo n.º 6
0
def figure_1_top(MW_v13, M31_cr16):
    fname = "figures/MW_M31_Age_Histogram.png"
    fig, ax = pyplot.subplots(figsize=(12, 9))
    with suppress_stdout():
        add_age_MWandM31_to_ax(ax, MW_v13, M31_cr16)
    ax.set_xlim(4, 14)
    ax.set_yscale("log")
    fig.savefig(fname)
    pyplot.close(fig)
    os.system("convert -trim {} {}".format(fname,
                                           fname.replace(".png", "-trim.png")))
    os.remove(fname)
    print("Saved {}".format(fname))
Exemplo n.º 7
0
def figure_3(auriga, MW_h96e10, M31_cr16, age_min):
    fname = "figures/FeH_obs_Au4-4_Au4-10_Au4-21_{:.1f}.png".format(age_min)
    with suppress_stdout():
        fig = plot_FeH_obs_and_4_and_10_and_21(auriga,
                                               MW_h96e10,
                                               M31_cr16,
                                               age_min=age_min)
    fig.savefig(fname)
    pyplot.close(fig)
    os.system("convert -trim {} {}".format(fname,
                                           fname.replace(".png", "-trim.png")))
    os.remove(fname)
    print("Saved {}".format(fname))
Exemplo n.º 8
0
def figure_6(auriga, MWRgc, MW_h96e10, M31Rgc, age_min):
    fname = "figures/LogRgc_mu_sigma_{:.1f}.png".format(age_min)
    with suppress_stdout():
        fig = plot_rgal_mean_vs_std(auriga,
                                    numpy.log10(MWRgc),
                                    MW_h96e10,
                                    numpy.log10(M31Rgc),
                                    age_min=age_min)
    fig.savefig(fname)
    pyplot.close(fig)
    os.system("convert -trim {} {}".format(fname,
                                           fname.replace(".png", "-trim.png")))
    os.remove(fname)
    print("Saved {}".format(fname))
Exemplo n.º 9
0
def figure_5(auriga, MW_h96e10, M31_cr16, age_min):
    fname = "figures/logMFeH_withRatios_{:.1f}.png".format(age_min)
    with suppress_stdout():
        fig = plot_FeH_ratios(auriga,
                              ["istars", "iold", "insitu_old", "accreted_old"],
                              MW_h96e10,
                              M31_cr16,
                              age_min=age_min)
    fig.savefig(fname)
    pyplot.close(fig)
    os.system("convert -trim {} {}".format(fname,
                                           fname.replace(".png", "-trim.png")))
    os.remove(fname)
    print("Saved {}".format(fname))
Exemplo n.º 10
0
    def load_snapshot(self,
                      snapnr=None,
                      redshift=None,
                      tlookback=None,
                      loadonlytype=[4],
                      rotate=True,
                      verbose=True):

        # Give snapnr to load a certain snapshot. If not given, use z=0
        if snapnr is None: snapnr = self.nsnaps - 1

        # If redshift is given, find the snapshot closest to this redshift
        if redshift is not None and type(redshift) is float:
            if not hasattr(self, "redshifts"):
                self.get_snapshot_spacing(verbose=verbose)
            snapnr = (numpy.abs(self.redshifts - redshift)).argmin()
            print("Loading snapshot closest to z = {0}".format(redshift))
            print("The closest snapshot is {0} (z = {1:.2f})".format(
                snapnr, self.redshifts[snapnr]))

        # If tlookback given, find the snapshot closest ot this tlookback
        if tlookback is not None and type(tlookback) is float or type(
                tlookback) is int:
            if not hasattr(self, "times"):
                self.get_snapshot_spacing(verbose=verbose)
            snapnr = (numpy.abs(self.times - tlookback)).argmin()
            print("Loading snapshot closest to tlookback = {0}".format(
                tlookback))
            print("The closest snapshot is {0} (tlookback = {1:.2f})".format(
                snapnr, self.times[snapnr]))

        if verbose:
            return eat_snap_and_fof(self.level,
                                    self.halo,
                                    snapnr,
                                    verbose=verbose,
                                    run=self,
                                    snappath=self.rundir + "/output/",
                                    loadonlytype=loadonlytype,
                                    rotate=rotate)
        else:
            with suppress_stdout():
                return eat_snap_and_fof(self.level,
                                        self.halo,
                                        snapnr,
                                        verbose=verbose,
                                        run=self,
                                        snappath=self.rundir + "/output/",
                                        loadonlytype=loadonlytype)
Exemplo n.º 11
0
    def plot_GCS_level345(self, halo, gc_max_age=10, gc_max_radius=250):
        print("plot_GCS_level345")
        print("  halo          = {0}".format(halo))
        print("  gc_max_age    = {0} Gyr".format(gc_max_age))
        print("  gc_max_radius = {0} kpc\n".format(gc_max_radius))

        from investigate_auriga_gcs import GlobularClusterSystem
        with suppress_stdout():
            GCS = GlobularClusterSystem(self,
                                        None,
                                        halo,
                                        radius=gc_max_radius,
                                        age=gc_max_age)

        GCS.plot_diagnostics_level345(self, halo)
Exemplo n.º 12
0
    def get_snapshot_spacing_highfreqstars(self,
                                           verbose=False,
                                           from_snapshots=False):
        if not hasattr(self, "highfreqstars"):
            self.find_all_highfreqstars(verbose=verbose)
        times = numpy.zeros(self.nhighfreqstars)
        redshifts = numpy.zeros(self.nhighfreqstars)

        output_list = self.rundir + "/output_list_high_freq_stars.txt"
        if os.path.exists(output_list) and os.path.isfile(
                output_list) and not from_snapshots:
            a = numpy.zeros(self.nhighfreqstars)
            with open(output_list) as w:
                for i, line in enumerate(w.readlines()):
                    a[i] = line  # a = 1/(1+z)
                    redshifts[i] = 1 / a[i] - 1
                    times[i] = self.cosmology_get_lookback_time_from_a(
                        a[i].astype('float64'), is_flat=True)
            self.times_highfreqstars, self.redshifts_highfreqstars = times, redshifts
            return

        from tlrh_util import print_progressbar
        from areposnap.gadget import gadget_readsnap
        print("Setting redshifts for highfreqstars")
        for i, snapnr in enumerate(range(self.nhighfreqstars)):
            print_progressbar(snapnr, self.nhighfreqstars, whitespace="  ")
            # CAUTION, reruns seem to complain "couldnt find units in file" for each snapshot :o
            with suppress_stdout():
                # What's up with 2763?? O_o ... 000, 001, ..., 2761, 2762, 6764
                s = gadget_readsnap(snapnr if snapnr != 2763 else 2764,
                                    snappath=self.rundir + "/output/",
                                    snapbase="snapshot_highfreqstars_",
                                    snapdirbase="snapdir_highfreqstars_",
                                    onlyHeader=True)
            s.cosmology_init()
            redshifts[i] = s.redshift
            times[i] = s.cosmology_get_lookback_time_from_a(
                s.time.astype('float64'), is_flat=True)

            if verbose:
                print(
                    "snapnr = {0:03d},\tz = {1:.5f},\ta = {2:.5f},\ttime = {3:.2f} Gyr"
                    .format(snapnr, s.redshift, s.time, times[i]))

        self.cosmo = s.cosmo
        del s
        # s.time is actually scalefactor a which can be computed as a = 1/(1+z)
        self.times_highfreqstars, self.redshifts_highfreqstars = times, redshifts
Exemplo n.º 13
0
def figure_2_bottom(M31_cr16_scaled_to_MW, plot_values_skip):
    fname = "figures/M31_RgcFeH_HistogramMassWeighted_CaldwellRomanowsky2016data.png"
    fig, ax = pyplot.subplots(figsize=(12, 9))
    with suppress_stdout():
        add_CaldwellRomanowsky_FeH_Rgc_logM_M31_to_ax(
            ax,
            M31_cr16_scaled_to_MW,
            do_scatter=False,
            plot_values_skip=plot_values_skip,
            debug=False,
        )
    fig.suptitle("Andromeda GCS")
    fig.savefig(fname)
    os.system("convert -trim {} {}".format(fname,
                                           fname.replace(".png", "-trim.png")))
    os.remove(fname)
    print("Saved {}".format(fname))
Exemplo n.º 14
0
def plot_caldwell2011_figure23(data):
    fig, (ax1, ax2) = pyplot.subplots(2, 1, figsize=(10, 11))

    finite, = numpy.where(numpy.isfinite(data["[Fe/H]"]))

    X, Y, Rproj = calculate_M31_Rgc_Wang2019(data["SkyCoord"],
                                             deproject=False,
                                             debug=False)

    ax1.plot(numpy.log10(Rproj[finite]), data["[Fe/H]"][finite], "ko", ms=6)
    with suppress_stdout(
    ):  # RuntimeWarning: invalid value encountered in log10
        ax2.plot(numpy.log10(Y[finite]), data["[Fe/H]"][finite], "ko", ms=6)

    # Sanity check: calculate Rproj with the given X and Y in the dataset
    # ax1.plot(numpy.log10(numpy.sqrt(data["X"][finite]**2 + data["Y"][finite]**2)),
    #     data["[Fe/H]"][finite], "ro", ms=6)

    # Sanity check: plot the given Y in the dataset
    # ax2.plot(numpy.log10(data["Y"][finite]), data["[Fe/H]"][finite], "ro", ms=6)

    # Sanity check: compare the given X in the dataset with the calculated X
    # ax2.plot(numpy.log10(X[finite]), data["[Fe/H]"][finite], "ko", ms=6)
    # ax2.plot(numpy.log10(data["X"][finite]), data["[Fe/H]"][finite], "ro", ms=6)

    ax2.axhline(-0.4, ls="--", c="k")

    for ax in [ax1, ax2]:
        ax.set_ylabel("[Fe/H]")
        ax.set_yticks(numpy.arange(-3, 2, 1))
        ax.set_yticks(numpy.arange(-3.2, 1.2, 0.2), minor=True)
        ax.set_ylim(-3, 1)

    ax1.set_xlabel("log(radius) (kpc)")
    ax1.set_xticks(numpy.arange(0, 3, 1))
    ax1.set_xticks(numpy.arange(-1, 2.2, 0.2), minor=True)
    ax1.set_xlim(-0.8, 2.2)

    ax2.set_xlabel("log(minor axis distance) (kpc)")
    ax2.set_xticks(numpy.arange(-2, 3, 1))
    ax2.set_xticks(numpy.arange(-2.2, 2.4, 0.2), minor=True)
    ax2.set_xlim(-2.1, 2.1)

    pyplot.tight_layout()
    pyplot.show()
Exemplo n.º 15
0
    def get_total_stellar_mass_versus_time(self, verbose=False):
        if verbose: print("\nRunning get_total_stellar_mass_versus_time")

        if not hasattr(self, "nsnaps"):
            self.find_all_snapshots(verbose=verbose)

        binary_file = "../out/{0}/{0}_total_stellar_mass".format(self.name)
        if os.path.exists(binary_file):
            self.total_stellar_mass = numpy.fromfile(binary_file)
        else:
            self.total_stellar_mass = numpy.zeros(self.nsnaps)
            # TODO move insitu_fraction from RenaudOgertGieles2017 to here?
            # self.insitu_fraction = numpy.zeros(self.nsnaps)
            for snapnr in range(self.nsnaps):
                if verbose:
                    print("  Eating snapshot: {0}/{1}".format(
                        snapnr, self.nsnaps - 1))
                s, sf = self.load_snapshot(snapnr=snapnr,
                                           loadonlytype=[4],
                                           verbose=True)

                required = ["pos", "halo", "subhalo", "mass"]
                if not all(x in s.data.keys() for x in required):
                    missing = [x for x in required if x not in s.data.keys()]
                    if not verbose:
                        print("  Eating snapshot: {0}/{1}".format(
                            snapnr, self.nsnaps - 1))
                    print("    WARNING: not all required data is available!")
                    print("    required: {0}".format(required))
                    print("    missing:  {0}\n".format(missing))
                    continue

                with suppress_stdout():
                    sr = s.r()
                stars_in_main_galaxy, = numpy.where((s.halo == 0)
                                                    & (s.subhalo == 0)
                                                    & (s.type == 4)
                                                    & (s.age > 0.))

                self.total_stellar_mass[
                    snapnr] = s.mass[stars_in_main_galaxy].sum() * 1e10
                if verbose: print("    Success!\n")

            self.total_stellar_mass.tofile(binary_file)
            del s, sf
Exemplo n.º 16
0
def figure_2_top(MW_h96e10, plot_values_skip):
    fname = "figures/MW_RgcFeH_HistogramMassWeighted_Harris1996ed2010data.png"
    fig, ax = pyplot.subplots(figsize=(12, 9))
    with suppress_stdout():
        add_Harris_FeH_Rgc_logM_MW_to_ax(
            ax,
            MW_h96e10,
            do_scatter=False,
            plot_values_skip=plot_values_skip,
            debug=False,
        )
    fig.suptitle("Milky Way GCS")
    fig.savefig(fname)
    pyplot.close(fig)
    os.system("convert -trim {} {}".format(fname,
                                           fname.replace(".png", "-trim.png")))
    os.remove(fname)
    print("Saved {}".format(fname))
Exemplo n.º 17
0
if __name__ == "__main__":
    pyplot.style.use("tlrh")
    data = read_caldwell_romanowsky_2016_data()

    print("There are {0: >3d} globular clusters in total".format(len(data)))

    i_has_vel, = numpy.where(numpy.isfinite(data["RVel"]))
    print(
        "There are {0: >3d} globular clusters /w velocity measurement".format(
            len(i_has_vel)))

    i_has_logM, = numpy.where(numpy.isfinite(data["LogM"]))
    print("There are {0: >3d} globular clusters /w logM measurement".format(
        len(i_has_logM)))

    with suppress_stdout():
        i_has_FeH, = numpy.where((data["[Fe/H]"] > -6) & (data["[Fe/H]"] < 4))
    print("There are {0: >3d} globular clusters /w [Fe/H] measurement".format(
        len(i_has_FeH)))

    with suppress_stdout():
        i_has_FeH_and_logM, = numpy.where(
            numpy.isfinite(data["[Fe/H]"])
            & (data["[Fe/H]"] > -6) & (data["[Fe/H]"] < 4)
            & numpy.isfinite(data["LogM"]))
    print(
        "There are {0: >3d} globular clusters /w [Fe/H] and logM measurement".
        format(len(i_has_FeH_and_logM)))

    with suppress_stdout():
        i_has_age, = numpy.where((data["Age"] < 13.99))
Exemplo n.º 18
0
def get_insitu_for_snapnr(run, snapnr, insitu_def, verbose=False, debug=False):
    previous_redshift = run.redshifts[snapnr - 1]
    previous_time = run.times[snapnr - 1]
    previous_a = 1 / (previous_redshift + 1)
    current_redshift = run.redshifts[snapnr]
    current_time = run.times[snapnr]
    current_a = 1 / (current_redshift + 1)
    if snapnr is 0:
        previous_redshift = 1000  # should be infinity
        # perhaps calculate lookbacktime for a=0 and see what happens?
        previous_time = current_time
        previous_a = 0

    if verbose:
        print("\nEating snapshot: {0}/{1}".format(snapnr, run.nsnaps - 1))
        print("  previous redshift: {0}".format(previous_redshift))
        print("  current  redshift: {0}".format(current_redshift))
        print("  previous time: {0}".format(previous_time))
        print("  current  time: {0}".format(current_time))
        print("  previous a: {0}".format(previous_a))
        print("  current  a: {0}".format(current_a))

    with suppress_stdout():
        s, sf = run.load_snapshot(snapnr=snapnr,
                                  loadonlytype=[4],
                                  verbose=True)

    required = ["id", "pos", "age", "halo", "subhalo"]
    if not all(x in s.data.keys() for x in required):
        missing = [x for x in required if x not in s.data.keys()]
        if verbose:
            print(
                "WARNING: s does not have all required info. Saving empty file."
            )
            print("required: {0}".format(required))
            print("missing:  {0}\n".format(missing))
        if not os.path.exists("../out/{0}/insitu".format(s.name)):
            os.mkdir("../out/{0}/insitu".format(s.name))
        numpy.savetxt(
            "../out/{0}/insitu/{0}_insitu_{1}_{2}.txt".format(
                s.name, snapnr, insitu_def),
            numpy.array([], dtype=numpy.uint64),
            fmt='%d',
        )
        numpy.savetxt(
            "../out/{0}/insitu/{0}_satellite_{1}.txt".format(s.name, snapnr),
            numpy.array([], dtype=numpy.uint64),
            fmt='%d',
        )
        # optional
        istars = numpy.array([], dtype=numpy.uint64)
        insitu = numpy.array([], dtype=numpy.uint64)
        isatellite = numpy.array([], dtype=numpy.uint64)
        igalaxy = numpy.array([], dtype=numpy.uint64)
        igalaxy_10percentr200 = numpy.array([], dtype=numpy.uint64)
    else:
        # s.age is actually scalefactor, so redshift z = (1/a -1)
        # born is the snapshot in which a particle first appeared
        s_redshifts = (1 / s.age - 1)

        istars, = numpy.where((s.type == 4) & (s.age > 0.))
        igalaxy, = numpy.where((s.type == 4) & (s.age > 0.) & (s.halo == 0)
                               & (s.subhalo == 0))
        igalaxy_10percentr200, = numpy.where((s.type == 4) & (s.age > 0.)
                                             & (s.halo == 0) & (s.subhalo == 0)
                                             & (s.r() < s.galrad))

        # To find accreted stars we look for stars born outside of halo 0 subhalo 0
        # Stars in this subset that live within r200 at z=0 can then be classified
        # as accreted.
        isatellite, = numpy.where((s.type == 4) & (s.age > 0.)
                                  & ((s.halo != 0) | (
                                      (s.halo == 0) & (s.subhalo != 0))))

        # TODO: perhaps not fixed def, but function of galradfrac?
        if insitu_def == "galrad":
            if verbose:
                print("\nInsitu requires r < galrad (=10% of virial radius)")
            insitu, = numpy.where(
                # Stars in the main halo + main subhalo,
                # within 10% of the virial radius (--> disk)
                (s.type == 4) & (s.halo == 0) & (s.subhalo == 0)
                & (s.r() < s.galrad)
                # only look at stars that have formed in the timespan from last
                # snapshot until now the condition s.age < current_a should not
                # make a difference because no star can be older of course
                & (s.age > 0.) & (s.age > previous_a) & (s.age < current_a))
        elif insitu_def == "virial":
            if verbose:
                print("\nInsitu requires r < 10*galrad (= virial radius)")
            insitu, = numpy.where(
                # Stars in the main halo + main subhalo,
                # within 10% of the virial radius (--> disk)
                (s.type == 4) & (s.halo == 0) & (s.subhalo == 0)
                & (s.r() < 10 * s.galrad)  # galrad is 10% of virial radius
                # only look at stars that have formed in the timespan from last
                # snapshot until now the condition s.age < current_a should not
                # make a difference because no star can be older of course
                & (s.age > 0.) & (s.age > previous_a) & (s.age < current_a))
        elif insitu_def == "30kpc":
            if verbose: print("\nInsitu requires r < 30 kpc")
            insitu, = numpy.where(
                # Stars in the main halo + main subhalo,
                # within 10% of the virial radius (--> disk)
                (s.type == 4) & (s.halo == 0) & (s.subhalo == 0)
                & (s.r() < float(30) / 1000)  # galrad is 10% of virial radius
                # only look at stars that have formed in the timespan from last
                # snapshot until now the condition s.age < current_a should not
                # make a difference because no star can be older of course
                & (s.age > 0.) & (s.age > previous_a) & (s.age < current_a))

        if not os.path.exists("../out/{0}/insitu".format(s.name)):
            os.mkdir("../out/{0}/insitu".format(s.name))
        numpy.savetxt("../out/{0}/insitu/{0}_insitu_{1}_{2}.txt".format(
            s.name, snapnr, insitu_def),
                      s.id[insitu],
                      fmt='%d')
        numpy.savetxt("../out/{0}/insitu/{0}_satellite_{1}.txt".format(
            s.name, snapnr),
                      s.id[isatellite],
                      fmt='%d')

    if verbose:
        print("  len(istars):     {0}".format(len(istars)))
        print("  len(insitu):     {0}".format(len(insitu)))
        print("  len(isatellite): {0}".format(len(isatellite)))
        print("  len(igalaxy):    {0}".format(len(igalaxy)))
        print("  len(igalaxy_10percentr200):  {0}".format(
            len(igalaxy_10percentr200)))
        print("")

    # At end of function we delete s and sf
    del s, sf
Exemplo n.º 19
0
def plot_caldwell2011_figure24(M31_c11, MW_h96e10, debug=False):
    fig, (ax1, ax2) = pyplot.subplots(1, 2, figsize=(16, 8), sharey=True)

    Ryz = numpy.log10(numpy.sqrt(MW_h96e10["Y"]**2 + MW_h96e10["Z"]**2))
    Rproj = numpy.log10(M31_c11["Rproj"])

    # RuntimeWarning: invalid value encountered in less
    with suppress_stdout():
        FeH_high, = numpy.where((M31_c11["[Fe/H]"] > -0.4))
        FeH_med, = numpy.where((M31_c11["[Fe/H]"] < -0.4)
                               & (M31_c11["[Fe/H]"] > -0.9))
        FeH_low, = numpy.where((M31_c11["[Fe/H]"] < -0.9))

    r_ana = numpy.linspace(-0.2, 1.3, 9)
    for rmin, rmax in zip(r_ana[:-1], r_ana[1:]):
        rmid = (rmin + rmax) / 2
        area = numpy.pi * (10**rmid)**2

        Nmw = len(numpy.where((Ryz > rmin) & (Ryz < rmax))[0])
        Nm31 = len(numpy.where((Rproj > rmin) & (Rproj < rmax))[0])
        if debug:
            print("{:7.3f}{:7.3f}{:10.3f}{:7d}{:7.3f}{:7d}{:7.3f}".format(
                rmin, rmax, area, Nmw, numpy.log10(Nmw / area), Nm31,
                numpy.log10(Nm31 / area)))
        # TODO: calculate the errorbars
        mw = ax1.errorbar(rmid,
                          numpy.log10(Nmw / area),
                          yerr=0.2 * numpy.log10(numpy.sqrt(Nmw)),
                          ls="none",
                          marker="+",
                          c="r",
                          ms=10,
                          capsize=4)
        for ax in [ax1, ax2]:
            m31 = ax.errorbar(
                rmid,
                numpy.log10(Nm31 / area),
                yerr=0.2 * numpy.log10(numpy.sqrt(Nm31)),
                ls="none",
                marker="o",
                c="k",
                ms=10,
                capsize=4,
            )

        # [Fe/H] > -0.4 --> 'high'
        Nm31_high = len(
            numpy.where((Rproj[FeH_high] > rmin)
                        & (Rproj[FeH_high] < rmax))[0])
        with suppress_stdout(
        ):  # RuntimeWarning: divide by zero encountered in log10
            m31_high = ax.errorbar(
                rmid,
                numpy.log10(Nm31_high / area),
                yerr=0.2 * numpy.log10(numpy.sqrt(Nm31_high)),
                ls="none",
                marker="X",
                c="r",
                ms=10,
                capsize=4,
            )

        # -0.9 < [Fe/H] < -0.4 --> 'med'
        Nm31_med = len(
            numpy.where((Rproj[FeH_med] > rmin) & (Rproj[FeH_med] < rmax))[0])
        m31_med = ax.errorbar(
            rmid,
            numpy.log10(Nm31_med / area),
            yerr=0.2 * numpy.log10(numpy.sqrt(Nm31_med)),
            ls="none",
            marker="o",
            c="orange",
            ms=10,
            mfc="none",
            capsize=4,
        )

        # [Fe/H] < -0.9 --> 'low'
        Nm31_low = len(
            numpy.where((Rproj[FeH_low] > rmin) & (Rproj[FeH_low] < rmax))[0])
        m31_low = ax.errorbar(
            rmid,
            numpy.log10(Nm31_low / area),
            yerr=0.2 * numpy.log10(numpy.sqrt(Nm31_low)),
            ls="none",
            marker="o",
            c="b",
            ms=8,
            capsize=4,
        )

    # Add powerlaw with slope -2.5
    r_ana = numpy.linspace(0, 1, 64)
    ax1.plot(r_ana, -2.5 * r_ana, c="r")

    for ax in [ax1, ax2]:
        ax.set_xticks(numpy.arange(-0.5, 2.5, 0.5))
        ax.set_xticks(numpy.arange(-0.25, 1.75, 0.25), minor=True)
        ax.set_yticks(numpy.arange(-2.5, 1.5, 0.5))
        ax.set_yticks(numpy.arange(-3, 1.25, 0.25), minor=True)
        ax.set_xlim(-0.2, 1.4)
        ax.set_ylim(-2.8, 1.2)
        ax.set_xlabel("log R (kpc)")
    ax1.legend([m31, mw], ["M31", "MW"], frameon=True, fontsize=16)
    ax1.set_ylabel(r"log (Clusters kpc$^{-2}$)")

    ax2.legend([m31, m31_high, m31_med, m31_low], [
        "M31", "[Fe/H]$>$-0.4 ({})".format(
            len(FeH_high)), "-0.9$<$[Fe/H]$<$-0.4 ({})".format(len(FeH_med)),
        "[Fe/H]$<$-0.9 ({})".format(len(FeH_low))
    ],
               frameon=True,
               fontsize=16)

    # pyplot.tight_layout()
    pyplot.subplots_adjust(wspace=0, hspace=0)
    pyplot.show()
Exemplo n.º 20
0
def plot_caldwell_mass_metallicity_relation(data, do_fit=True):
    fig, ax = pyplot.subplots(figsize=(12, 9))

    # RuntimeWarning: invalid value encountered in less_equal
    with suppress_stdout():
        rich, = numpy.where(
            numpy.isfinite(data["[Fe/H]"])
            & numpy.isfinite(data["logM"])
            & (data["[Fe/H]"] > -0.8))
        poor, = numpy.where(
            numpy.isfinite(data["[Fe/H]"])
            & numpy.isfinite(data["logM"])
            & (data["[Fe/H]"] <= -0.8))

    ax.plot(data["[Fe/H]"][rich], data["logM"][rich], "ko", ms=8)
    ax.plot(data["[Fe/H]"][poor], data["logM"][poor], "ko", ms=8, mfc="none")

    finite = numpy.union1d(rich, poor)
    print("Sample size: {0}".format(len(finite)))
    # First, calculate Pearson correlation coefficient
    # Here -1 (negative correlation) or +1 (positive correlation)
    # imply an exact linear relationship. 0 means no correlation.
    # The p value is the 2-tailed p-value that an uncorrelated system produces
    # two datasets that have a Pearson correlation at least as extreme as
    # computed from these datasets. Assumes both datasets are normally distributed
    r, p = scipy.stats.pearsonr(data["[Fe/H]"][finite], data["logM"][finite])
    print("Pearson    r: {0:.5f} (p = {1:.5f})".format(r, p))

    # Does not assume normal distribution in both data sets.
    rho, p = scipy.stats.spearmanr(data["[Fe/H]"][finite],
                                   data["logM"][finite])
    print("Spearman rho: {0:.5f} (p = {1:.5f})".format(rho, p))

    # https://www.statisticshowto.datasciencecentral.com/
    #    spearman-rank-correlation-definition-calculate/
    FeHrank = scipy.stats.rankdata(data["[Fe/H]"][finite])
    massrank = scipy.stats.rankdata(data["logM"][finite])
    sxy = numpy.sum(
        (FeHrank - numpy.mean(FeHrank)) * (massrank - numpy.mean(massrank)))
    sxy /= len(FeHrank)
    sx = numpy.sum((FeHrank - numpy.mean(FeHrank))**2) / len(FeHrank)
    sy = numpy.sum((massrank - numpy.mean(massrank))**2) / len(massrank)
    rho = sxy / numpy.sqrt(sx * sy)

    # Fit to y|x
    mmr_mean, edges, binnumbers = scipy.stats.binned_statistic(
        data["[Fe/H]"][finite], data["logM"][finite], statistic="mean")
    mmr_sem, edges, binnumbers = scipy.stats.binned_statistic(
        data["[Fe/H]"][finite],
        data["logM"][finite],
        statistic=lambda array: scipy.stats.sem(array))
    mmr_std, edges, binnumbers = scipy.stats.binned_statistic(
        data["[Fe/H]"][finite],
        data["logM"][finite],
        statistic=lambda array: numpy.std(array))
    ax.errorbar((edges[1:] + edges[:-1]) / 2,
                mmr_mean,
                yerr=mmr_sem,
                ls="none",
                marker="o",
                c="r",
                ms=8)

    if do_fit:
        from tlrh_statistics import fit_to_data
        fitfunc = lambda p, x: p[0] * x + p[1]
        x = (edges[1:] + edges[:-1]) / 2
        x_ana = numpy.linspace(-3.2, 1.4, 128)
        popt, perr = fit_to_data(ax,
                                 x,
                                 mmr_mean,
                                 mmr_std,
                                 fitfunc, [0, 5.5],
                                 x_ana=x_ana)

    # Fit to x|y
    mmr_mean_inv, edges_inv, binnumbers_inv = scipy.stats.binned_statistic(
        data["logM"][finite], data["[Fe/H]"][finite], statistic="mean")
    mmr_sem_inv, edges_inv, binnumbers_inv = scipy.stats.binned_statistic(
        data["logM"][finite],
        data["[Fe/H]"][finite],
        statistic=lambda array: scipy.stats.sem(array))
    mmr_std_inv, edges_inv, binnumbers_inv = scipy.stats.binned_statistic(
        data["logM"][finite],
        data["[Fe/H]"][finite],
        statistic=lambda array: numpy.std(array))
    ax.errorbar(mmr_mean_inv, (edges_inv[1:] + edges_inv[:-1]) / 2,
                xerr=mmr_sem_inv,
                ls="none",
                marker="o",
                c="b",
                ms=8)
    # TODO: do the fit?

    ax.set_xlabel("[Fe/H]")
    ax.set_ylabel(r"log$_{10}(\rm M/\rm M_{\odot})$")
    ax.set_xticks(numpy.arange(-3.5, 1.5, 0.5))
    ax.set_xticks(numpy.arange(-3.2, 1.5, 0.1), minor=True)
    ax.set_yticks(numpy.arange(3, 9, 1))
    ax.set_yticks(numpy.arange(3, 8.2, 0.2), minor=True)
    pyplot.xlim(-3.2, 1.4)
    pyplot.ylim(4, 7.5)

    pyplot.show()
Exemplo n.º 21
0
def read_caldwell2011_data_from_vizier(fname="../data/Caldwell2011/table1.dat",
                                       verbose=False,
                                       debug=False):
    dirname = os.path.dirname(__file__)
    fname = os.path.join(dirname, fname)
    Ncols = 13 + 2 + 2
    Nrows = sum(1 for line in open(fname, "r"))

    # Default to float in column, but change for known strings
    formats = [numpy.float for i in range(Ncols)]
    formats[0] = "S10"
    formats[1] = "S1"
    formats[2] = "S13"
    formats[3] = "S13"
    formats[5] = "S1"
    formats[12] = "S1"
    formats[13] = "object"
    formats[14] = "object"
    formats[15] = "f8"
    formats[16] = "f8"

    # Name columns to access 'm by later-on
    names = [
        "Name ", "n_Name", "RA", "DEC", "E(B-V)", ")", "Vel", "e_Vel", "logM",
        "[Fe/H]", "e_[Fe/H]", "Age", "Notes", "SkyCoord", "ICRS", "Rproj",
        "Rdeproj"
    ]

    # Pack it all up, and initialise empty array
    dtype = {"names": names, "formats": formats}
    data = numpy.empty(Nrows, dtype=dtype)

    # Start and end indices from catalog's ReadMe file
    cs = [1, 11, 13, 23, 35, 39, 41, 48, 51, 55, 60, 64, 69]
    ce = [10, 12, 22, 33, 38, 40, 46, 49, 53, 58, 62, 67, 81]

    with open(fname, "rb") as f:
        for i, row in enumerate(f.readlines()):
            # SkyCoord, ICRS, Rproj, Rdeproj not in data
            for j in range(Ncols - 4):
                value = row[cs[j] - 1:ce[j]].strip()
                if formats[j] == numpy.float:
                    if len(value) is 0:
                        value = numpy.nan
                    else:
                        value = float(value)
                if formats[j] == numpy.bytes_:
                    if len(value) is 0:
                        value = ""
                data[names[j]][i] = value

    for x in range(Nrows):
        data["SkyCoord"][x] = coord.SkyCoord(data["RA"][x].decode("ascii"),
                                             data["DEC"][x].decode("ascii"),
                                             frame="icrs",
                                             equinox="J2000",
                                             unit=(u.hourangle, u.deg))

    # Here we follow sec 4.1 from Wang, Ma & Liu (2019, sec 4.1). arXiv 1901.11229v1
    # However, what they call deprojected galactocentric radius does not have units
    # kpc, so this must be an angle in units of radian. So we convert this angle
    # on the sky to kpc by using the distance to Andromeda galaxy.
    X, Y, Rproj = calculate_M31_Rgc_Wang2019(data["SkyCoord"],
                                             deproject=False,
                                             debug=False)
    data["Rproj"] = Rproj
    X, Y, Rdeproj = calculate_M31_Rgc_Wang2019(data["SkyCoord"],
                                               deproject=True,
                                               debug=False)
    data["Rdeproj"] = Rdeproj

    with suppress_stdout():
        has_no_age, = numpy.where(data["Age"] == 14.00)
        data["Age"][has_no_age] = numpy.nan

    if verbose:
        print("\nWARNING: {0} GC ages were changed".format(len(has_no_age)),
              end="")

        print(" from 14.00 to numpy.nan (b/c no age estimate available)\n")
        print("Succesfully read: '{0}'".format(fname))
        print("Usage: data = read_caldwell2011_data() ")
        print("You can then access rows using data[0]")
        print("You can access columns using data['colname']")
        print("To find all column names, use 'data.dtype.names'")
        print_caldwell2011_data(data, example=True)

    return data
Exemplo n.º 22
0
def plot_harris1996_figure1_8(part1, part2):
    fig, (ax1, ax2) = pyplot.subplots(2, 1, figsize=(9, 14))

    # RuntimeWarning: invalid value encountered in greater
    with suppress_stdout():
        rich, = numpy.where(
            numpy.isfinite(part2["FeH"])
            & (part2["FeH"] > -1.0))
        poor, = numpy.where(
            numpy.isfinite(part2["FeH"])
            & (part2["FeH"] <= -1.0))

    ax1.plot(numpy.log10(part1["R_gc"][rich]), part2["FeH"][rich], "ko", ms=8)
    ax1.plot(numpy.log10(part1["R_gc"][poor]),
             part2["FeH"][poor],
             "ko",
             ms=8,
             mfc="none")

    FeH_mean, edges, binnumbers = scipy.stats.binned_statistic(
        numpy.log10(part1["R_gc"][rich]), part2["FeH"][rich], bins=5)
    FeH_sem, edges, binnumbers = scipy.stats.binned_statistic(
        numpy.log10(part1["R_gc"][rich]),
        part2["FeH"][rich],
        statistic=lambda x: scipy.stats.sem(x),
        bins=5)
    ax2.errorbar((edges[1:] + edges[:-1]) / 2,
                 FeH_mean,
                 yerr=FeH_sem,
                 ls="none",
                 marker="o",
                 c="k",
                 ms=8)

    FeH_mean, edges, binnumbers = scipy.stats.binned_statistic(
        numpy.log10(part1["R_gc"][poor]), part2["FeH"][poor], statistic="mean")
    # CAUTION, using std err as errorbar in the mean
    FeH_sem, edges, binnumbers = scipy.stats.binned_statistic(
        numpy.log10(part1["R_gc"][poor]),
        part2["FeH"][poor],
        statistic=lambda x: scipy.stats.sem(x))
    ax2.errorbar((edges[1:] + edges[:-1]) / 2,
                 FeH_mean,
                 yerr=FeH_sem,
                 ls="none",
                 marker="o",
                 c="k",
                 ms=8,
                 mfc="none")

    # Harris' trend line Delta [Fe/H] / Delta log(Rgc) = -0.30
    radii = numpy.power(10, numpy.linspace(0.0001, 1, 42))
    ax2.plot(numpy.log10(radii), numpy.log10(radii**(-0.30)) - 0.4, c="k")
    ax2.plot(numpy.log10(radii), numpy.log10(radii**(-0.30)) - 1.2, c="k")

    for ax in [ax1, ax2]:
        ax.set_xticks(numpy.arange(0, 3, 0.5))
        ax.set_xticks(numpy.arange(-0.4, 2.6, 0.1), minor=True)
        ax.set_yticks(numpy.arange(-2.0, 1, 1))
        ax.set_yticks(numpy.arange(-2.4, 0.6, 0.2), minor=True)
        ax.set_xlim(-0.3, 2.5)
        ax.set_ylim(-2.8, 0.4)
    ax1.set_ylabel("[Fe/H]")
    ax2.set_xlabel(r"log R$_{\text{GC}}$ (kpc)")
    ax2.set_ylabel(r"$<$[Fe/H]$>$")
    pyplot.show()
Exemplo n.º 23
0
def plot_harris1996_figure1_3_th(part1, part2, use_2d=False):
    fig, ax = pyplot.subplots(figsize=(9, 9))
    ax.text(0.5,
            1.02,
            "Space Distribution (Milky Way)",
            transform=ax.transAxes,
            ha="center",
            va="bottom")

    # RuntimeWarning: invalid value encountered in greater
    with suppress_stdout():
        red, = numpy.where(numpy.isfinite(part2["FeH"]) & (part2["FeH"] > -1))
        blue, = numpy.where(
            numpy.isfinite(part2["FeH"])
            & (part2["FeH"] <= -1))

    rmax = 10**2.5
    radii = numpy.power(10, numpy.linspace(numpy.log10(1), numpy.log10(rmax),
                                           7))
    volume = 4 / 3 * numpy.pi * radii**3

    NredOld = numpy.zeros(radii.shape, dtype="i8")
    NblueOld = numpy.zeros(radii.shape, dtype="i8")

    for i, (r1, r2) in enumerate(zip(radii[:-1], radii[1:])):
        nRedOld, = numpy.where((part1["R_gc"][red] > r1)
                               & (part1["R_gc"][red] < r2))
        nBlueOld, = numpy.where((part1["R_gc"][blue] > r1)
                                & (part1["R_gc"][blue] < r2))
        NredOld[i] = len(nRedOld)
        NblueOld[i] = len(nBlueOld)
        if use_2d: volume[i] = 4 * numpy.pi * ((r1 + r2) / 2)**2 * (r2 - r1)

    with suppress_stdout():  # divide by zero encountered in log10
        pyplot.plot(numpy.log10(radii),
                    numpy.log10(NblueOld / volume),
                    "bo",
                    ms=5,
                    label=r"[Fe/H] $\leq$ -1, N = {0}".format(len(blue)))
        pyplot.plot(numpy.log10(radii),
                    numpy.log10(NredOld / volume),
                    "ro",
                    ms=5,
                    label=r"[Fe/H] $>$ -1, N = {0}".format(len(red)))

    radii_red = numpy.power(10, numpy.linspace(0.5, 2.2, 42))
    radii_blue = numpy.power(10, numpy.linspace(0.0001, 0.7, 42))
    pyplot.plot(numpy.log10(radii_red), numpy.log10(radii_red**(-3.5)), c="k")
    pyplot.plot(numpy.log10(radii_blue),
                numpy.log10(radii_blue**(-2)) - 0.75,
                c="k",
                ls="--")

    ax.text(0.7,
            0.2,
            r"$\phi \sim $R$^{-3.5}$",
            transform=ax.transAxes,
            fontsize=22)
    ax.set_xticks(numpy.arange(0, 3, 0.5))
    ax.set_xticks(numpy.arange(0, 2.6, 0.1), minor=True)
    ax.set_yticks(range(0, -8, -2))
    ax.set_yticks(numpy.arange(0.5, -8, -0.5), minor=True)
    ax.set_xlim(0, 2.5)
    ax.set_ylim(-7.5, 1)
    pyplot.xlabel(r"log R$_{\text{GC}}$ (kpc)")
    pyplot.ylabel(r"log $\phi$ (number per kpc$^3$)")

    ax.grid(color='grey', ls=":", lw=1, alpha=0.2, which="minor")
    ax.grid(color='grey', ls=":", lw=1, alpha=0.5, which="major")
    pyplot.legend(loc="lower left", frameon=False, fontsize=16)

    # pyplot.tight_layout()
    pyplot.savefig("../out/MilkyWay_GlobularClusterSystem_phi-vs-Rgc_th.png")
    pyplot.show()
Exemplo n.º 24
0
    pyplot.ylim(3, 7)

    pyplot.show()


if __name__ == "__main__":
    pyplot.switch_backend("agg")
    pyplot.style.use("tlrh")

    part1, part2, part3 = read_harris1996_data()
    print_harris1996_data(part1, part2, part3, example=True)

    print("There are {0: >3d} globular clusters in total".format(len(part2)))

    i_has_M_vt, = numpy.where(numpy.isfinite(part2["M_Vt"]))
    print("There are {0: >3d} globular clusters /w M_Vt measurement".format(
        len(i_has_M_vt)))

    with suppress_stdout():  # invalid value encountered in < and/or >
        i_has_FeH, = numpy.where((part2["FeH"] > -6) & (part2["FeH"] < 4))
    print("There are {0: >3d} globular clusters /w FeH measurement".format(
        len(i_has_FeH)))

    # plot_harris1996_figure1_2(part1)
    # plot_harris1996_figure1_2_th(part1, part2)
    # plot_harris1996_figure1_3(part1, part2)
    # plot_harris1996_figure1_3_th(part1, part2)
    # plot_harris1996_figure1_7(part2)
    # plot_harris1996_figure1_7_th(part2)
    # plot_MW_mass_distribution(part2)