Пример #1
0
    def __init__(self,
                 init_pos,
                 init_vel,
                 mw=None,
                 t1=0 * u.Gyr,
                 t2=5 * u.Gyr,
                 dt=1 * u.Myr,
                 N_max=8,
                 save_orbit=False):

        if mw is None:
            self.mw = gp.MilkyWayPotential()
        else:
            self.mw = mw

        self.t1 = t1
        self.t2 = t2
        self.dt = dt
        self.N_max = 8

        self.q = gd.PhaseSpacePosition(pos=init_pos, vel=init_vel)
        with warnings.catch_warnings(record=True):
            warnings.simplefilter("ignore")
            orbit = self.mw.integrate_orbit(self.q,
                                            dt=self.dt,
                                            t1=self.t1,
                                            t2=self.t2)
            self.res = gd.find_actions(orbit, N_max=self.N_max)

        self.zmax = orbit.zmax()

        if save_orbit:
            #optional since orbit breaks pickling
            self.orbit = orbit
Пример #2
0
def evolve_cluster_in_galaxy(options_file):
    opt = options_reader(options_file)

    timestep = opt.options['timestep']  # in Myr
    tend = opt.options['tend']  # in Myr
    times = np.arange(0.0, tend, timestep) | units.Myr

    cluster = oc_code(opt)
    cluster_code = cluster.code
    galaxy_code = gizmo_interface(opt)

    snap_reader = snapshot_reader(opt, galaxy_code)

    stars = cluster_code.particles.copy()

    if opt.options['axisymmetric']:
        import astropy.units as u
        import gala.dynamics as gd
        import gala.potential as gp

        pos = [opt.options['axi_Rinit'], 0, 0] * u.kpc
        vel = [0, 0, 0] * u.km / u.s
        mw = gp.MilkyWayPotential()
        phase = gd.PhaseSpacePosition(pos, vel)
        vc = mw.circular_velocity(phase).to_value(u.km / u.s) | units.kms

        stars = cluster_code.particles.copy()
        stars.x += opt.options['axi_Rinit'] | units.kpc
        stars.vy += vc
        stars.z += opt.options['axi_zinit'] | units.kpc

    else:
        pos = galaxy_code.chosen_position_z0
        vel = galaxy_code.chosen_velocity_z0
        stars.x += pos[0] | units.kpc
        stars.y += pos[1] | units.kpc
        stars.z += pos[2] | units.kpc
        stars.vx += vel[0] | units.kms
        stars.vy += vel[1] | units.kms
        stars.vz += vel[2] | units.kms

    channel = stars.new_channel_to(cluster_code.particles)
    channel.copy_attributes(["x", "y", "z", "vx", "vy", "vz"])

    system = Bridge(timestep=timestep, use_threading=False)
    system.add_system(cluster_code, (galaxy_code, ))
    system.add_system(galaxy_code)

    converter = cluster_code.unit_converter

    for i, t in enumerate(tqdm(times)):
        system.evolve_model(t, timestep=timestep | units.Myr)

        bound_com = bound.center_of_mass().value_in(units.kpc)

        snap_reader.process_snapshot(system, galaxy_code, bound_com, i, t)

    snap_reader.finish_sim()

    cluster_code.stop()
Пример #3
0
def input_des():
    """Compile stream input parameters for DES streams from Shipp+2018"""

    tin = Table.read('des_raw.txt',
                     format='ascii.commented_header',
                     delimiter=' ')
    tin.pprint()

    streams = tin['Name']
    length = tin['Length'] * u.kpc
    r = tin['Rgal'] * u.kpc

    # get circular velocity
    ham = gp.Hamiltonian(gp.MilkyWayPotential())
    xyz = np.array([r.value,
                    np.zeros_like(r.value),
                    np.zeros_like(r.value)]) * r.unit
    vcirc = ham.potential.circular_velocity(xyz)

    # get age
    M = vcirc**2 * r / G
    m = tin['Mprog'] * 1e4 * u.Msun
    age = ((tin['l'] * u.deg).to(u.radian).value /
           (2**(2 / 3) * (m / M)**(1 / 3) * np.sqrt(G * M / r**3))).to(u.Gyr)
    age = np.ones(np.size(length)) * 8 * u.Gyr

    # get subhalo density
    a = 0.678
    r2 = 162.4 * u.kpc
    n = -1.9
    m0 = 2.52e7 * u.Msun
    m1 = 1e6 * u.Msun
    m2 = 1e7 * u.Msun
    cdisk = 2.02e-13 * (u.kpc)**-3 * u.Msun**-1
    nsub = cdisk * np.exp(-2 / a * ((r / r2)**a - 1)) * m0 / (n + 1) * (
        (m2 / m0)**(n + 1) - (m1 / m0)**(n + 1))

    # replace with actual LSST estimates
    tf = Table.read('min_depths_LSST.txt', format='ascii', delimiter=',')
    fcut = 1 - tf['col2']
    t = Table([streams, length, age, r, vcirc, nsub, fcut],
              names=('name', 'length', 'age', 'rgal', 'vcirc', 'nsub', 'fcut'))
    t.write('DES_streams_LSST.fits', overwrite=True)

    tf = Table.read('min_depths_LSST10.txt', format='ascii', delimiter=',')
    fcut = 1 - tf['col2']
    t = Table([streams, length, age, r, vcirc, nsub, fcut],
              names=('name', 'length', 'age', 'rgal', 'vcirc', 'nsub', 'fcut'))
    t.write('DES_streams_LSST10.fits', overwrite=True)
Пример #4
0
def calculate_actions(w0,
                      pot=gp.MilkyWayPotential(),
                      dt=0.5,
                      n_steps=10000,
                      full_output=False):
    """ Approximate actions following https://github.com/adrn/gala/blob/master/docs/dynamics/actionangle.rst """
    assert len(w0.shape) == 0
    w = gp.Hamiltonian(pot).integrate_orbit(w0, dt=dt, n_steps=n_steps)
    toy_potential = gd.fit_isochrone(w)
    toy_actions, toy_angles, toy_freqs = toy_potential.action_angle(w)
    with warnings.catch_warnings(record=True):
        warnings.simplefilter("ignore")
        result = gd.find_actions(w, N_max=8, toy_potential=toy_potential)
    if full_output: return result, w
    return result["actions"]
Пример #5
0
    galcen_distance=rsun,
    galcen_v_sun=coord.CartesianDifferential(*vsun),
    z_sun=zsun)

# load in data, load MW potential
with warnings.catch_warnings(record=True):
    warnings.simplefilter("ignore")
    gaiadata = GaiaData(filein)
    hdul = fits.open(filein)
    sttable = Table(hdul[1].data)
    if (totnodes > 1):
        thiskeys = np.array_split(range(len(sttable['source_id'])),
                                  totnodes)[node]
        gaiadata = gaiadata[thiskeys]
        sttable = sttable[thiskeys]
    mw = gp.MilkyWayPotential()

print(sttable['source_id'][0])

# for the montecarlo loop later
cov = gaiadata.get_cov()
meanvals = [
    gaiadata.ra.value, gaiadata.dec.value, gaiadata.parallax.value,
    gaiadata.pmra.value, gaiadata.pmdec.value, gaiadata.radial_velocity.value
]
meanvals = list(map(list, zip(*meanvals)))  # transpose

nentries = len(sttable)

# convert to galactocentric coordinates
sc = gaiadata.skycoord
Пример #6
0
def ln_likelihood(p,
                  phi1,
                  pot,
                  data,
                  data_units,
                  frame_comp_names,
                  extra_var,
                  plot=False):
    phi2, dist, pm1, pm2, rv, *other_p = p
    lnMhalo, halo_c, lnMdisk = other_p

    # M_pal5 = np.exp(lnM)
    # if not 8e3 < M_pal5 < 4e5:
    #     return -np.inf

    if not 25 < lnMhalo < 29:
        return -np.inf
    if not 0.8 < halo_c < 1.2:
        return -np.inf

    if not 23 < lnMdisk < 28:
        return -np.inf

    pot = gp.MilkyWayPotential(halo=dict(m=np.exp(lnMhalo), c=halo_c),
                               disk=dict(m=np.exp(lnMdisk)))

    # galcen_frame = coord.Galactocentric(galcen_distance=8.1*u.kpc,
    #                                     galcen_v_sun=coord.CartesianDifferential([vx, vy, vz]*u.km/u.s))

    c = gc.Pal5PriceWhelan18(phi1=phi1,
                             phi2=phi2 * data_units['phi2'],
                             distance=dist * u.kpc,
                             pm_phi1_cosphi2=pm1 * u.mas / u.yr,
                             pm_phi2=pm2 * u.mas / u.yr,
                             radial_velocity=rv * u.km / u.s)
    w0 = gd.PhaseSpacePosition(c.transform_to(galcen_frame).data)

    # Integrate the orbit and generate the stream - set these parameters!:
    gen = ms.MockStreamGenerator(df, mw, progenitor_potential=pal5_pot)

    stream, _ = gen.run(w0,
                        2e4 * u.Msun,
                        dt=-1 * u.Myr,
                        n_steps=3000,
                        release_every=5)
    stream_c = stream.to_coord_frame(gc.Pal5PriceWhelan18,
                                     galactocentric_frame=galcen_frame)

    tracks, stds = get_stream_track(
        stream_c,
        frame_comp_names,
        phi1_bins=phi1_bins,
        phi1_lim=phi1_lim,
        # phi1_binsize=1.5*u.deg,
        units=data_units)

    if plot:
        fig, axes = plt.subplots(5, 1, figsize=(8, 12), sharex=True)

        grid = np.linspace(phi1_lim[0].value, phi1_lim[1].value, 1024)
        for i, name in enumerate(frame_comp_names[1:]):
            ax = axes[i]

            ax.plot(data['phi1'][data[name] != 0],
                    data[name][data[name] != 0],
                    marker='o',
                    ls='none',
                    color='k',
                    ms=4)

            ax.plot(stream_c.phi1.wrap_at(180 * u.deg).degree,
                    getattr(stream_c, name).value,
                    marker='o',
                    ls='none',
                    color='tab:blue',
                    ms=2,
                    alpha=0.4,
                    zorder=-100)

            ax.plot(grid,
                    tracks[name](grid),
                    marker='',
                    color='tab:orange',
                    alpha=0.5)

            ax.set_ylabel(name, fontsize=12)

        ax.set_xlim(phi1_lim.value)
        axes[0].set_ylim(-1.5, 3)
        axes[1].set_ylim(15, 25)
        axes[2].set_ylim(2, 5.5)
        axes[3].set_ylim(-1, 2)
        axes[4].set_ylim(-75, -20)
        fig.tight_layout()
        fig.set_facecolor('w')

        # -- residuals --
        fig, axes = plt.subplots(5, 1, figsize=(8, 12), sharex=True)

        grid = np.linspace(phi1_lim[0].value, phi1_lim[1].value, 1024)
        for i, name in enumerate(frame_comp_names[1:]):
            ax = axes[i]

            ivar = get_ivar(data[name + '_ivar'], extra_var[name])
            ax.errorbar(data['phi1'][ivar > 0.],
                        data[name][ivar > 0] -
                        tracks[name](data['phi1'][ivar > 0.]),
                        yerr=1 / np.sqrt(ivar[ivar > 0.]),
                        marker='o',
                        ls='none',
                        color='k',
                        ecolor='#aaaaaa')
            ax.axhline(0.)
            ax.set_ylabel(name, fontsize=12)

        ax.set_xlim(phi1_lim.value)
        axes[0].set_ylim(-1, 1)
        axes[1].set_ylim(-4, 4)
        axes[2].set_ylim(-2, 2)
        axes[3].set_ylim(-2, 2)
        axes[4].set_ylim(-10, 10)
        axes[0].set_title('Residuals')
        fig.tight_layout()
        fig.set_facecolor('w')

    lls = []
    for name in frame_comp_names[1:]:  # skip phi1
        ivar = get_ivar(data[name + '_ivar'],
                        stds[name](data['phi1'])**2 + extra_var[name])
        ll = ln_normal_ivar(tracks[name](data['phi1']), data[name], ivar)
        ll[~np.isfinite(ll)] = np.nan
        lls.append(ll)

    return np.nansum(lls, axis=0).sum()
# ** DEFAULTS **
# clockwise 1, widdershins -1, angular thing
c1 = 1.0
c2 = -1.0
w1 = 1.0
w2 = 1.0

# Milky Way and Andromeda
M_MW = 1.0E11 * u.Msun
M_AND = 1.23E12 * u.Msun
SIZE_MW = 36.8  # kpc
SIZE_AND = 33.7  # kpc
MW_AND_DIST = 778.0 / sqrt(3)
MW_AND_VEL = -110.0 / sqrt(3)

POT_MW = gp.MilkyWayPotential()
POT_AND = gp.HernquistPotential(M_AND.value, 0, units=galactic)
ICS_MW = gd.PhaseSpacePosition(pos=[0, 0, 0] * u.kpc,
                               vel=[0, 0, 0] * u.km / u.s)
ICS_AND = gd.PhaseSpacePosition(
    pos=[MW_AND_DIST, MW_AND_DIST, MW_AND_DIST] * u.kpc,
    vel=[MW_AND_VEL, MW_AND_VEL, MW_AND_VEL] * (u.km / u.s))

# Lörg and Smøl Magellanic Clouds
M_LORG = 1.0E10 * u.M_sun
SIZE_LORG = 4.3  # u.kpc
MW_LORG_DIST = 49.97  # wrt MW, in kpc
MW_LORG_VEL = 321.0  # wrt MW, in km/s

POT_LORG = gp.HernquistPotential(M_LORG.value, 0, units=galactic)
ICS_LORG = gd.PhaseSpacePosition(