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
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()
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)
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"]
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
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(