def compute_orbit(icrs, dt=-0.1 * u.Myr, n_steps=50000): """Integrate the orbit.""" c_icrs = icrs.transform_to(gc_frame).cartesian object_phase_space = gd.PhaseSpacePosition( pos=c_icrs.xyz, vel=c_icrs.differentials['s'].d_xyz) return gp.Hamiltonian(pot).integrate_orbit(object_phase_space, dt=dt, n_steps=n_steps)
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 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) if not opt.options['axisymmetric']: cluster.clean_ejections(system) bound = system.particles.bound_subset(unit_converter=converter) bound_com = bound.center_of_mass().value_in(units.kpc) if not opt.options['axisymmetric']: galaxy_code.evolve_grid(bound_com) snap_reader.process_snapshot(system, galaxy_code, bound_com, i, t) snap_reader.finish_sim() cluster_code.stop()
def cache_file(): fn = path.join('/tmp/cache.hdf5') w0 = gd.PhaseSpacePosition(pos=np.random.random((3, 16)) * u.kpc, vel=np.random.random((3, 16)) * u.m / u.s) with h5py.File(fn, 'w') as f: g = f.create_group('w0') w0.to_hdf5(g) return fn
def cache_file(tmpdir_factory): fn = tmpdir_factory.mktemp('cache').join('cache.hdf5') w0 = gd.PhaseSpacePosition(pos=np.random.random((3, 16)) * u.kpc, vel=np.random.random((3, 16)) * u.m / u.s) with h5py.File(fn, 'w') as f: g = f.create_group('w0') w0.to_hdf5(g) return str(fn)
def make_perfect_stream(X_start=[-8.122, 0., 0.5], V_start=[-16., 0., -200.], dt=.00048, n_steps=10000, number_of_stars=1000, intrinsic_spread=None): pot = MilkyWayPotential() kpcMyr2kms = 977.951 / (u.kpc / u.Myr) w0 = gd.PhaseSpacePosition(pos=X_start * u.kpc, vel=V_start * u.km / u.s) orbit = gp.Hamiltonian(pot).integrate_orbit(w0, dt=dt, n_steps=n_steps) indices = np.random.randint(0, len(orbit.x), size=number_of_stars) orb_x = orbit.x[indices] / u.kpc orb_y = orbit.y[indices] / u.kpc orb_z = orbit.z[indices] / u.kpc orb_vx = orbit.v_x[indices] * kpcMyr2kms orb_vy = orbit.v_y[indices] * kpcMyr2kms orb_vz = orbit.v_z[indices] * kpcMyr2kms if intrinsic_spread != None: for i in range(len(orb_x)): z_pot_start = pot.value([orb_x[i], orb_y[i], orb_z[i] ])[0] * 978.5**2 / (u.kpc / u.Myr)**2 orb_z[i] += intrinsic_spread[0] * np.random.normal() z_pot_diff = pot.value([ orb_x[i], orb_y[i], orb_z[i] ])[0] * 978.5**2 / (u.kpc / u.Myr)**2 - z_pot_start orb_x[i] += intrinsic_spread[0] * np.random.normal() orb_y[i] += intrinsic_spread[0] * np.random.normal() orb_vx[i] += intrinsic_spread[1] * np.random.normal() orb_vy[i] += intrinsic_spread[1] * np.random.normal() # this last line adds dispersion to v_z, but in a way that counteracts # the change in vertical energy coming from the shift in height z orb_vz[i] = np.sign(orb_vz[i]) * np.sqrt( orb_vz[i]**2 - 2. * z_pot_diff) + intrinsic_spread[1] * np.random.normal() return np.transpose([orb_x, orb_y, orb_z, orb_vx, orb_vy, orb_vz]) # EXAMPLES: # this is stream S1 # xyzs = make_perfect_stream(X_start=[-8.122,0., 0.4], V_start=[-25., 0., -100.], dt=2.*2.*.00048, intrinsic_spread=[0.020, 1.], n_steps=4000) # np.savez('../GeneratedStreams/mock_stream_20-1000_slow', xyzs=xyzs) # this is stream S2 # xyzs = make_perfect_stream(X_start=[-8.122, -.6, -0.2], V_start=[0., 220., -50.], dt=2.*2.*.00048, intrinsic_spread=[0.020, 1.], n_steps=2700) # np.savez('../GeneratedStreams/mock_stream_20-1000_corotB', xyzs=xyzs) # this is stream S3 # xyzs = make_perfect_stream(X_start=[-8.122, -.3, 0.4], V_start=[-10., 200., -70.], dt=2.*.00048, intrinsic_spread=[0.020, 1.], n_steps=2500) # np.savez('../GeneratedStreams/mock_stream_20-1000_corotC', xyzs=xyzs) # this is stream S4 # xyzs = make_perfect_stream(X_start=[-7.835, -.3, 0.4], V_start=[-160., 160., -60.], dt=2.*.00048, intrinsic_spread=[0.020, 1.], n_steps=3800) # np.savez('../GeneratedStreams/mock_stream_20-1000_inclined', xyzs=xyzs)
def backintegrate( icrs = coord.SkyCoord(ra=coord.Angle('17h 20m 12.4s'), dec=coord.Angle('+57° 54′ 55″'), distance=76*u.kpc, pm_ra_cosdec=0.0569*u.mas/u.yr, pm_dec=-0.1673*u.mas/u.yr, radial_velocity=-291*u.km/u.s), dt=-0.1*u.Myr, n_steps=int(1e3), outpath=None ): """ Note: this is a thin wrapper to Gala's "integrate_orbit" method. Args: icrs (SkyCoord). Default is Draco. Note however that you can pass many ICRS coordinates to a coord.SkyCoord instance, via a construct like: ``` icrs_samples = coord.SkyCoord(ra=ra, dec=dec, distance=dist, pm_ra_cosdec=pm_ra_cosdec, pm_dec=pm_dec, radial_velocity=rv) ``` where ra, dec, etc are correctly unit-ed arrays. dt (Quantity): timestep. (Default: 1e5 yr) n_steps (int): how many steps. (Default: 1e3, so total 1e8 years back). outpath (str): if passed, makes a plot of the orbit here. Returns: gala orbit object. """ # Transform the measured values to a Galactocentric reference frame so we # can integrate an orbit in our Milky Way model. gc_frame = coord.Galactocentric() # Transform the mean observed kinematics to this frame. galcen = icrs.transform_to(gc_frame) # Turn the `Galactocentric` object into orbital initial conditions, and # integrate. Timestep: 0.5 Myr, and integrate back for 1e4 steps (5 Gyr). w0 = gd.PhaseSpacePosition(galcen.data) orbit = potential.integrate_orbit(w0, dt=dt, n_steps=n_steps) if isinstance(outpath, str): fig = orbit.plot() savefig(fig, outpath) return orbit
def vary_potential(): # the normal parameters for the potential and the Sgr dSph sag_mass = 1e8 normal_mw_mass = 130.0075e10*u.Msun normal_mw_conc = 9.39 normal_mw_rs = 18.927757889861788 * u.kpc # reads the coordinates from the file to w0 w0 = int_sgr.read_file('centroid_part_1000', columns=[3, 4, 5, 6, 7, 8], skip_lines=[0]) gvs = [] m_ratios = [0.8, 0.9, 1.0, 1.1, 1.2] c_ratios = [0.8, 0.9, 1.0, 1.1, 1.2] rs_ratios = [0.8, 0.9, 1.0, 1.1, 1.2] # makes a potential using 80%, 90%, 100%, 110% and 120% of each of the normal potential parameters for m_ratio in m_ratios: for c_ratio in c_ratios: for rs_ratio in rs_ratios: # gets the current potential parameters curr_mass = normal_mw_mass * m_ratio curr_c = normal_mw_conc * c_ratio curr_rs = normal_mw_rs * rs_ratio print('Theta:',\ 'mass =', curr_mass,\ 'c =', curr_c,\ 'rs =', curr_rs,\ ) # creates the current potential object and uses it to integrate the particle orbits curr_pot = int_sgr.get_potential(total_mass=curr_mass, r_scale=curr_rs, mw_conc=curr_c) orbit, pot = int_sgr.integrate(w0, pot=curr_pot) # finds the center of mass of the particle distribution and integrates its orbit com_p, com_v, com_index = int_sgr.calc_com(w0) com_orbit,pot = int_sgr.integrate(gd.PhaseSpacePosition(pos=com_p, vel=com_v)) # calculates the generalized variance of the particle distribution gv = int_sgr.calc_dps(sag_mass, orbit, curr_pot, com_orbit) print('Generalized Variance:', gv) gvs.append(gv) # prints the generalized variances calculated from the potential parameters np.set_printoptions(precision=3) print(np.reshape(gvs, [len(m_ratios), len(c_ratios), len(rs_ratios)]))
def morphology(omega, m_b, release_every=1, n_particles=1, dt=-1, n_steps=6000): """ Takes the pattern speed (with units, in km/s/kpc), and release_every, which controls how often to release particles, and the bar mass m_b. Creates mock streams, returns RA, dec to be used for track calculation """ S = np.load('../data/Sn9l19m.npy') #expansion coeff. S = S[:2, :6, :6] w0 = gd.PhaseSpacePosition(pal5_c.transform_to(galcen_frame).cartesian) pot = gp.CCompositePotential() pot['disk'] = default_mw['disk'] pot['halo'] = default_mw['halo'] pot['bar'] = get_bar_model(Omega=omega, Snlm=S, m=m_b) frame = gp.ConstantRotatingFrame(Omega=[0, 0, -1] * omega, units=galactic) H = gp.Hamiltonian( pot, frame) #frame such that we're "moving" with respect to bar df = gd.FardalStreamDF(random_state=np.random.RandomState(42)) prog_pot = gp.PlummerPotential(pal5_M, 4 * u.pc, units=galactic) gen = gd.MockStreamGenerator(df=df, hamiltonian=H, progenitor_potential=prog_pot) # gen = gd.MockStreamGenerator(df=df, hamiltonian=H) stream_data, _ = gen.run(w0, pal5_M, dt=dt, n_steps=n_steps, release_every=release_every, n_particles=n_particles) cache_file = 'BarModels_RL{:d}_Mb{:.0e}_Om{:.1f}.hdf5'.format( release_every, m_b.value, omega.value) if path.exists(cache_file): os.unlink(cache_file) stream_data.to_hdf5(cache_file) sim_c = stream_data.to_coord_frame(coord.ICRS, galactocentric_frame=galcen_frame) return sim_c
def plot_dps(): # the parameters for the Sgr dSph sag_mass = 1e8 # reads the coordinates from the file to w0 w0 = int_sgr.read_file('centroid_part_1000', columns=[3, 4, 5, 6, 7, 8], skip_lines=[0]) # integrates the orbits with initial conditions w0 orbit, pot = int_sgr.integrate(w0) # finds the center of mass of the particle distribution and integrates its orbit com_p, com_v, com_index = int_sgr.calc_com(w0) com_orbit,pot = int_sgr.integrate(gd.PhaseSpacePosition(pos=com_p, vel=com_v)) # calculates the generalized variance of the particle distribution in verbose mode, and displays the dps plot gv = int_sgr.calc_dps(sag_mass, orbit, pot, com_orbit, \ ylims = [0.2, 400], plot_title = 'Example Dps Plot', show_plot=True, verbose=True) print('Generalized Variance:', gv)
def get_orbit_gal(self, p, dt=0.5 * u.Myr, n_steps=500): kw = {'l': self.l0 * _units['l']} for k in _units: if k == 'l': continue kw[k] = p[k] * _units[k] c = coord.Galactic(**kw) # TODO: why is astropy so slow here? # cart = c.transform_to(gc_frame) # cart = cart.cartesian w0 = gd.PhaseSpacePosition(fast_to_galcen(c, self.galcen_frame)) pot = self.get_potential(p) orbit = pot.integrate_orbit(w0, dt=dt, n_steps=n_steps) model_gal = orbit.to_coord_frame( coord.Galactic, galactocentric_frame=self.galcen_frame) return model_gal
def get_orbit(): """""" t_impact, M, rs, bnorm, bx, vnorm, vx = impact_params() # load one orbital point pos = np.load('../data/log_orbit.npy') phi1, phi2, d, pm1, pm2, vr = pos c = gc.GD1(phi1=phi1 * u.deg, phi2=phi2 * u.deg, distance=d * u.kpc, pm_phi1_cosphi2=pm1 * u.mas / u.yr, pm_phi2=pm2 * u.mas / u.yr, radial_velocity=vr * u.km / u.s) w0 = gd.PhaseSpacePosition(c.transform_to(gc_frame).cartesian) # best-fitting orbit dt = 0.5 * u.Myr n_steps = 120 wangle = 180 * u.deg # integrate back in time fit_orbit = ham.integrate_orbit(w0, dt=dt, n_steps=n_steps) prog_phi0 = -20 * u.deg model_gd1 = fit_orbit.to_coord_frame(gc.GD1, galactocentric_frame=gc_frame) prog_i = np.abs(model_gd1.phi1.wrap_at(180 * u.deg) - prog_phi0).argmin() prog_w0 = fit_orbit[prog_i] dt_orbit = 0.5 * u.Myr nstep_impact = np.int64(t_impact / dt_orbit) prog_orbit = ham.integrate_orbit(prog_w0, dt=-dt_orbit, t1=0 * u.Myr, t2=-3 * u.Gyr) #impact_orbit = prog_orbit[nstep_impact:] #impact_orbit = impact_orbit[::-1] prog_orbit = prog_orbit[::-1] #print(nstep_impact, impact_orbit) return prog_orbit
def rv_to_3d_isotropic(r, v): """Given radii and velocity magnitudes, generate a set of 6D initial conditions by assuming isotropy. Parameters ---------- r : quantity_like [length] Radii. v : quantity_like [speed] Velocity magnidues. """ phi = np.random.uniform(0, 2*np.pi, size=r.size) * u.radian theta = np.arccos(2*np.random.uniform(size=r.size) - 1) * u.radian sph = coord.PhysicsSphericalRepresentation(phi=phi, theta=theta, r=r) xyz = sph.represent_as(coord.CartesianRepresentation).xyz phi = np.random.uniform(0, 2*np.pi, size=r.size) * u.radian theta = np.arccos(2*np.random.uniform(size=r.size) - 1) * u.radian v_sph = coord.PhysicsSphericalRepresentation(phi=phi, theta=theta, r=np.ones_like(v.value)*u.one) v_xyz = v * v_sph.represent_as(coord.CartesianRepresentation).xyz return gd.PhaseSpacePosition(pos=xyz, vel=v_xyz)
def run_gala_orbit(pos_sat, vel_sat, pos_tp, vel_tp): """ Specify units in ICs """ ## GALA set up # Design gala potential using Nbody and a test particle # Present-day position/velocity in inertial frame moving with instantaneous # Milky Way velocity: w0_mw = gd.PhaseSpacePosition( pos=[0, 0, 0] * u.kpc, vel=[0, 0, 0] * u.km / u.s, ) pot_mw = gp.HernquistPotential(m=Mhost * u.Msun, c=1 * u.kpc, units=galactic) # Values from Vasiliev et al. 2020 w0_lmc = gd.PhaseSpacePosition( pos=pos_sat, vel=vel_sat, ) w0_test = gd.PhaseSpacePosition( pos=pos_tp, vel=vel_tp, ) pot_lmc = gp.HernquistPotential(m=Msat * u.Msun, c=1 * u.kpc, units=galactic) w0 = gd.combine((w0_mw, w0_lmc, w0_test)) nbody = gd.DirectNBody(w0, [pot_mw, pot_lmc, None]) w1 = gd.combine((w0_lmc, w0_test)) isolated = gd.DirectNBody(w1, [pot_lmc, None]) # Full : Host - Satellite - test particle orbits = nbody.integrate_orbit(dt=dt * u.Gyr, t1=tmin * u.Gyr, t2=tmax * u.Gyr) # Orbit quantities full orbit pos_halo = np.array([orbits.xyz[:, :, 0].to(u.kpc).value])[0] pos_sat = np.array([orbits.xyz[:, :, 1].to(u.kpc).value])[0] pos_tp = np.array([orbits.xyz[:, :, 2].to(u.kpc).value])[0] vel_halo = np.array([orbits.v_xyz[:, :, 0].to(u.km / u.s).value])[0] vel_sat = np.array([orbits.v_xyz[:, :, 1].to(u.km / u.s).value])[0] vel_tp = np.array([orbits.v_xyz[:, :, 2].to(u.km / u.s).value])[0] r_halo = (np.sum(orbits.xyz[:, :, 0]**2, axis=0))**0.5 r_sat = (np.sum(orbits.xyz[:, :, 1]**2, axis=0))**0.5 r_tp = (np.sum(orbits.xyz[:, :, 2]**2, axis=0))**0.5 v_halo = (np.sum(orbits.v_xyz[:, :, 0].to(u.km / u.s).value**2, axis=0))**0.5 v_sat = (np.sum(orbits.v_xyz[:, :, 1].to(u.km / u.s).value**2, axis=0))**0.5 v_tp = (np.sum(orbits.v_xyz[:, :, 2].to(u.km / u.s).value**2, axis=0))**0.5 rtp_r2_sat = np.sum((np.array(orbits.xyz[:, :, 2].to(u.kpc).value - orbits.xyz[:, :, 1].to(u.kpc).value))**2, axis=0)**0.5 vtp_r2_sat = np.sum( (np.array(orbits.v_xyz[:, :, 2].to(u.km / u.s).value - orbits.v_xyz[:, :, 1].to(u.km / u.s).value))**2, axis=0)**0.5 return [pos_halo, vel_halo], [pos_sat, vel_sat], [pos_tp, vel_tp]
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()
STwvel = STtable['wvel'] STFe = STtable['feh'] STMgFe = STtable['[MgI]'] - STtable['feh'] STgd = GaiaData(STtable) gaiadata = GaiaData(APOKASCtable) rsun = 8 * u.kpc zsun = 0.025 * u.kpc vsun = [11.1, 232.24, 7.25] * u.km/u.s gc_frame = coord.Galactocentric(galcen_distance=rsun, galcen_v_sun=coord.CartesianDifferential(*vsun), z_sun=zsun) sc = gaiadata.skycoord STsc = STgd.skycoord APOKASCdyn = gd.PhaseSpacePosition(sc.transform_to(gc_frame).cartesian) STdyn = gd.PhaseSpacePosition(STsc.transform_to(gc_frame).cartesian) APOKASCrad = APOKASCdyn.represent_as('cylindrical').rho.to(u.kpc).value STrad = STdyn.represent_as('cylindrical').rho.to(u.kpc).value APOKASCz = APOKASCdyn.represent_as('cylindrical').z.to(u.kpc).value STz = STdyn.represent_as('cylindrical').z.to(u.kpc).value #process Jr = np.sqrt(Jr) Lz = Lz/(8. * 220.) vvel = vvel - 220. STJr = np.sqrt(STJr) STLz = STLz/(8. * 220.)
dec=0 * u.deg, distance=6 * u.kpc, pm_ra_cosdec=0.009 * u.mas / u.yr, pm_dec=0.009 * u.mas / u.yr, radial_velocity=0.1 * u.km / u.s) # Start by transforming the measured values to a Galactocentric reference frame # so we can integrate an orbit in our Milky Way model gc_frame = coord.Galactocentric() # Transform the mean observed kinematics to this frame: galcen = icrs.transform_to(gc_frame) # Turn the `Galactocentric` object into orbital initial conditions, and # integrate. Timestep: 0.5 Myr, and integrate back for 1e4 steps (5 Gyr). w0 = gd.PhaseSpacePosition(galcen.data) orbit = potential.integrate_orbit(w0, dt=-0.5 * u.Myr, n_steps=10000) fig = orbit.plot() fig.savefig('../results/test_results/sandbox_gala_integration.png') print(orbit.pericenter(), orbit.apocenter(), orbit.eccentricity()) # Now we’ll sample from the error distribution over the distance, proper # motions, and radial velocity, compute orbits, and plot distributions of mean # pericenter and apocenter: n_samples = 32 dist = np.random.normal(icrs.distance.value, icrs_err.distance.value, n_samples) * icrs.distance.unit pm_ra_cosdec = np.random.normal(icrs.pm_ra_cosdec.value,
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 scdyn = gd.PhaseSpacePosition(sc.transform_to(gc_frame).cartesian) """ compute u, v, w """ distgalcenter = np.sqrt(scdyn.pos.x * scdyn.pos.x + scdyn.pos.y * scdyn.pos.y + scdyn.pos.z * scdyn.pos.z) cylndvel = scdyn.vel.represent_as(coord.CylindricalDifferential, base=scdyn.pos) #rvel = cylndvel.d_rho.to(u.km / u.s) uvel = -cylndvel.d_rho.to(u.km / u.s).value vvel = -(distgalcenter * cylndvel.d_phi).to( u.km / u.s, equivalencies=u.dimensionless_angles()).value #zvel = cylndvel.d_z.to(u.km/u.s) wvel = cylndvel.d_z.to(u.km / u.s).value """
textwidth = 7.10000594991 columnwidth = 3.35224200913 tb_c = ['#4e79a7', '#f28e2b', '#e15759', '#76b7b2', '#59a14f', '#edc948', '#b07aa1', '#ff9da7', '#9c755f', '#bab0ac'] Rsolar = 8.2 #cluster min, max mass mc_min = 100 mc_max = 10000 mc_list = np.linspace(mc_min, mc_max, 1000) # find mass enclosed within Rsolar mw = gp.MilkyWayPotential() q = gd.PhaseSpacePosition(pos=[Rsolar, 0, 0] * u.kpc, vel=[0, 0, 0] * u.km/u.s) M_enclosed = float(mw.mass_enclosed(q).to_value(u.Msun)) dJzJz_target = np.power(mc_list / M_enclosed, 1/3) # load in results fname_list = ['thin', 'thick'] name_list = ['thin-disk', 'thick-disk'] def zoffset_gen(offlist, dJzJz): interp = interp1d(offlist, dJzJz) def to_minimize(off, target): return np.abs(interp(float(off)) - target) offlist_target = []
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( pos=[MW_LORG_DIST, MW_LORG_DIST, MW_LORG_DIST] * u.kpc, vel=[-MW_LORG_VEL, 0, 0] * (u.km / u.s))
def fiducial_at_start(): """Create fiducial model at the beginning of the movie""" np.random.seed(143531) t_impact = 2 * 0.495 * u.Gyr # load one orbital point pos = np.load('../data/log_orbit.npy') phi1, phi2, d, pm1, pm2, vr = pos c = gc.GD1(phi1=phi1 * u.deg, phi2=phi2 * u.deg, distance=d * u.kpc, pm_phi1_cosphi2=pm1 * u.mas / u.yr, pm_phi2=pm2 * u.mas / u.yr, radial_velocity=vr * u.km / u.s) w0 = gd.PhaseSpacePosition(c.transform_to(gc_frame).cartesian) # best-fitting orbit dt = 0.5 * u.Myr n_steps = 120 wangle = 180 * u.deg # integrate back in time fit_orbit = ham.integrate_orbit(w0, dt=dt, n_steps=n_steps) prog_phi0 = -20 * u.deg model_gd1 = fit_orbit.to_coord_frame(gc.GD1, galactocentric_frame=gc_frame) prog_i = np.abs(model_gd1.phi1.wrap_at(180 * u.deg) - prog_phi0).argmin() prog_w0 = fit_orbit[prog_i] dt_orbit = 0.5 * u.Myr nstep_impact = np.int64((t_impact / dt_orbit).decompose()) #prog_orbit = ham.integrate_orbit(prog_w0, dt=-dt_orbit, t1=0*u.Myr, t2=-3*u.Gyr) prog_orbit = ham.integrate_orbit(prog_w0, dt=-dt_orbit, t1=0 * u.Myr, t2=-3 * u.Gyr) impact_orbit = prog_orbit[nstep_impact:] impact_orbit = impact_orbit[::-1] prog_orbit = prog_orbit[::-1] t_disrupt = -300 * u.Myr minit = 7e4 mfin = 1e3 nrelease = 1 n_times = (prog_orbit.t < t_disrupt).sum() prog_mass = np.linspace(minit, mfin, n_times) prog_mass = np.concatenate( (prog_mass, np.zeros(len(prog_orbit.t) - n_times))) * u.Msun model_present = mockstream.dissolved_fardal_stream(ham, prog_orbit, prog_mass=prog_mass, t_disrupt=t_disrupt, release_every=nrelease) n_steps_disrupt = int(abs(t_disrupt / (prog_orbit.t[1] - prog_orbit.t[0]))) model_present = model_present[:-2 * n_steps_disrupt] model_gd1 = model_present.to_coord_frame(gc.GD1, galactocentric_frame=gc_frame) ind_gap = np.where((model_gd1.phi1.wrap_at(wangle) > -43 * u.deg) & (model_gd1.phi1.wrap_at(wangle) < -33 * u.deg))[0] n_times = (impact_orbit.t < t_disrupt).sum() prog_mass = np.linspace(minit, mfin, n_times) prog_mass = np.concatenate( (prog_mass, np.zeros(len(impact_orbit.t) - n_times))) * u.Msun model = mockstream.dissolved_fardal_stream(ham, impact_orbit, prog_mass=prog_mass, t_disrupt=t_disrupt, release_every=nrelease) n_steps_disrupt = int( abs(t_disrupt / (impact_orbit.t[1] - impact_orbit.t[0]))) model = model[:-2 * n_steps_disrupt] xsub = np.ones(3) * u.kpc vsub = np.ones(3) * u.km / u.s outdict = {'model': model, 'xsub': xsub, 'vsub': vsub} pickle.dump(outdict, open('../data/fiducial_at_start.pkl', 'wb'))
def get_gccoo_w0(coo): gc_frame = get_gc_frame() gccoo = coo.transform_to(gc_frame) w0 = gd.PhaseSpacePosition(gccoo.data) return gccoo, w0
## Adding halo to potential now that mock galaxy image is in place pot['halo'] = gp.NFWPotential(m=10E11, r_s=25 * u.kpc, units=galactic) ######################################## # Set up progenitor initial conditions - syntax is a bit weird but I didn't come up with it! x, y, z, vx, vy, vz = [x_0, y_0, z_0, vx_0, vy_0, vz_0] # in kpc and km/s c_gc = coord.Galactocentric(x=x * u.kpc, y=y * u.kpc, z=z * u.kpc, v_x=vx * u.km / u.s, v_y=vy * u.km / u.s, v_z=vz * u.km / u.s) psp = gd.PhaseSpacePosition(pos=c_gc.data.xyz, vel=[vx, vy, vz] * u.km / u.s) orbit = gp.Hamiltonian(pot).integrate_orbit(psp, dt=-0.5 * u.Myr, n_steps=n_steps) #orbit.plot() ######################################## # Compute spray model, note that stream.plot() conveniently shows the results # Description of the method in https://ui.adsabs.harvard.edu/abs/2015MNRAS.452..301F/abstract or gala docs stream = fardal_stream(pot, orbit[::-1], prog_mass=M_progenitor * u.Msun, release_every=1) # Binning stream to a histogram that matches mock galaxy image
agama.setUnits(mass=1, length=1, velocity=1) # import the MW potential from gala bulge = agama.Potential(type='Dehnen', gamma=1, mass=5E9, scaleRadius=1.0) nucleus = agama.Potential(type='Dehnen', gamma=1, mass=1.71E09, scaleRadius=0.07) disk = agama.Potential(type='MiyamotoNagai', mass=6.80e+10, scaleRadius=3.0, scaleHeight=0.28) halo = agama.Potential(type='NFW', mass=5.4E11, scaleRadius=15.62) mwpot = agama.Potential(bulge, nucleus, disk, halo) af = agama.ActionFinder(mwpot, interp=False) pos_vel = np.array([8., 0., 0., 75., 150., 50.]) agama_act = af(pos_vel) # now do it for gala pot = gp.MilkyWayPotential() w0 = gd.PhaseSpacePosition(pos=[8, 0, 0.] * u.kpc, vel=[75, 150, 50.] * u.km / u.s) w = gp.Hamiltonian(pot).integrate_orbit(w0, dt=0.5, n_steps=10000) gala_act = gd.find_actions(w, N_max=8)
plt.legend(loc='best') # - # The SCF potential object acts like any other `gala.potential` object, meaning # we can, e.g., plot density or potential contours: # + grid = np.linspace(-8, 8, 128) fig, axes = plt.subplots(1, 2, figsize=(10, 5), sharex=True, sharey=True) _ = pot_flat.plot_contours((grid, grid, 0), ax=axes[0]) axes[0].set_xlabel('$x$') axes[0].set_ylabel('$y$') _ = pot_flat.plot_contours((grid, 0, grid), ax=axes[1]) axes[1].set_xlabel('$x$') axes[1].set_ylabel('$z$') for ax in axes: ax.set_aspect('equal') # - # And numerically integrate orbits by passing in initial conditions and # integration parameters: w0 = gd.PhaseSpacePosition(pos=[3.5, 0, 1], vel=[0, 0.4, 0.05]) orbit_flat = pot_flat.integrate_orbit(w0, dt=1., n_steps=5000) _ = orbit_flat.plot()
def sample_backintegrate( icrs = coord.SkyCoord(ra=coord.Angle('17h 20m 12.4s'), dec=coord.Angle('+57° 54′ 55″'), distance=76*u.kpc, pm_ra_cosdec=0.0569*u.mas/u.yr, pm_dec=-0.1673*u.mas/u.yr, radial_velocity=-291*u.km/u.s), icrs_err = coord.SkyCoord(ra=0*u.deg, dec=0*u.deg, distance=6*u.kpc, pm_ra_cosdec=0.009*u.mas/u.yr, pm_dec=0.009*u.mas/u.yr, radial_velocity=0.1*u.km/u.s) ): """ Sample from the error distribution over the distance, proper motions, and radial velocity, compute orbits, and plot distributions of mean pericenter and apocenter """ n_samples = 32 dist = np.random.normal(icrs.distance.value, icrs_err.distance.value, n_samples) * icrs.distance.unit pm_ra_cosdec = np.random.normal(icrs.pm_ra_cosdec.value, icrs_err.pm_ra_cosdec.value, n_samples) * icrs.pm_ra_cosdec.unit pm_dec = np.random.normal(icrs.pm_dec.value, icrs_err.pm_dec.value, n_samples) * icrs.pm_dec.unit rv = np.random.normal(icrs.radial_velocity.value, icrs_err.radial_velocity.value, n_samples) * icrs.radial_velocity.unit ra = np.full(n_samples, icrs.ra.degree) * u.degree dec = np.full(n_samples, icrs.dec.degree) * u.degree icrs_samples = coord.SkyCoord(ra=ra, dec=dec, distance=dist, pm_ra_cosdec=pm_ra_cosdec, pm_dec=pm_dec, radial_velocity=rv) galcen_samples = icrs_samples.transform_to(gc_frame) w0_samples = gd.PhaseSpacePosition(galcen_samples.data) orbit_samples = potential.integrate_orbit(w0_samples, dt=-1*u.Myr, n_steps=4000) pers = orbit_samples.pericenter(approximate=True) apos = orbit_samples.apocenter(approximate=True) eccs = orbit_samples.eccentricity(approximate=True) plt.close('all') fig, axes = plt.subplots(1, 3, figsize=(12, 4)) axes[0].hist(pers.to_value(u.kpc), bins='auto') axes[0].set_xlabel('pericenter [kpc]') axes[1].hist(apos.to_value(u.kpc), bins='auto') axes[1].set_xlabel('apocenter [kpc]') axes[2].hist(eccs.value, bins='auto') axes[2].set_xlabel('eccentricity') fig.savefig('../results/test_results/sandbox_gala_sampling.png')
""" icrs_err = coord.ICRS(ra=0*u.deg, dec=0*u.deg, distance=6*u.kpc, pm_ra_cosdec=0.009*u.mas/u.yr, pm_dec=0.009*u.mas/u.yr, radial_velocity=0.1*u.km/u.s) """ v_sun = coord.CartesianDifferential([0, 0, 0] * u.km / u.s) gc_frame = coord.Galactocentric(galcen_distance=8.3 * u.kpc, z_sun=0 * u.pc, galcen_v_sun=v_sun) gc = icrs.transform_to(gc_frame) w0 = gd.PhaseSpacePosition(gc.data) if (star["Ba_only_candidate"] == 'true' and star["Ba_Sr_candidate"] == 'false'): Ba_velx.append(w0.v_x.to(u.km / u.s).value) Ba_vely.append(w0.v_y.to(u.km / u.s).value) Ba_velz.append(w0.v_z.to(u.km / u.s).value) Ba_y.append(np.sqrt(Ba_velx[-1]**2 + Ba_velz[-1]**2)) if (star["Sr_only_candidate"] == 'true' and star["Ba_Sr_candidate"] == 'false'): Sr_velx.append(w0.v_x.to(u.km / u.s).value) Sr_vely.append(w0.v_y.to(u.km / u.s).value) Sr_velz.append(w0.v_z.to(u.km / u.s).value)
def fiducial_at_encounter(): """Create fiducial model at the time of encounter""" np.random.seed(143531) t_impact = 0.495 * u.Gyr bnorm = 15 * u.pc bx = 6 * u.pc vnorm = 250 * u.km / u.s vx = -25 * u.km / u.s # load one orbital point pos = np.load('../data/log_orbit.npy') phi1, phi2, d, pm1, pm2, vr = pos c = gc.GD1(phi1=phi1 * u.deg, phi2=phi2 * u.deg, distance=d * u.kpc, pm_phi1_cosphi2=pm1 * u.mas / u.yr, pm_phi2=pm2 * u.mas / u.yr, radial_velocity=vr * u.km / u.s) w0 = gd.PhaseSpacePosition(c.transform_to(gc_frame).cartesian) # best-fitting orbit dt = 0.5 * u.Myr n_steps = 120 wangle = 180 * u.deg # integrate back in time fit_orbit = ham.integrate_orbit(w0, dt=dt, n_steps=n_steps) prog_phi0 = -20 * u.deg model_gd1 = fit_orbit.to_coord_frame(gc.GD1, galactocentric_frame=gc_frame) prog_i = np.abs(model_gd1.phi1.wrap_at(180 * u.deg) - prog_phi0).argmin() prog_w0 = fit_orbit[prog_i] dt_orbit = 0.5 * u.Myr nstep_impact = np.int64((t_impact / dt_orbit).decompose()) #prog_orbit = ham.integrate_orbit(prog_w0, dt=-dt_orbit, t1=0*u.Myr, t2=-3*u.Gyr) prog_orbit = ham.integrate_orbit(prog_w0, dt=-dt_orbit, t1=0 * u.Myr, t2=-3 * u.Gyr) impact_orbit = prog_orbit[nstep_impact:] impact_orbit = impact_orbit[::-1] prog_orbit = prog_orbit[::-1] t_disrupt = -300 * u.Myr minit = 7e4 mfin = 1e3 nrelease = 1 n_times = (prog_orbit.t < t_disrupt).sum() prog_mass = np.linspace(minit, mfin, n_times) prog_mass = np.concatenate( (prog_mass, np.zeros(len(prog_orbit.t) - n_times))) * u.Msun model_present = mockstream.dissolved_fardal_stream(ham, prog_orbit, prog_mass=prog_mass, t_disrupt=t_disrupt, release_every=nrelease) n_steps_disrupt = int(abs(t_disrupt / (prog_orbit.t[1] - prog_orbit.t[0]))) model_present = model_present[:-2 * n_steps_disrupt] model_gd1 = model_present.to_coord_frame(gc.GD1, galactocentric_frame=gc_frame) ind_gap = np.where((model_gd1.phi1.wrap_at(wangle) > -43 * u.deg) & (model_gd1.phi1.wrap_at(wangle) < -33 * u.deg))[0] n_times = (impact_orbit.t < t_disrupt).sum() prog_mass = np.linspace(minit, mfin, n_times) prog_mass = np.concatenate( (prog_mass, np.zeros(len(impact_orbit.t) - n_times))) * u.Msun model = mockstream.dissolved_fardal_stream(ham, impact_orbit, prog_mass=prog_mass, t_disrupt=t_disrupt, release_every=nrelease) n_steps_disrupt = int( abs(t_disrupt / (impact_orbit.t[1] - impact_orbit.t[0]))) model = model[:-2 * n_steps_disrupt] Nstar = np.shape(model)[0] ivalid = ind_gap < Nstar ind_gap = ind_gap[ivalid] xgap = np.median(model.xyz[:, ind_gap], axis=1) vgap = np.median(model.v_xyz[:, ind_gap], axis=1) ######################## # Perturber at encounter i = np.array([1, 0, 0], dtype=float) j = np.array([0, 1, 0], dtype=float) k = np.array([0, 0, 1], dtype=float) # find positional plane bi = np.cross(j, vgap) bi = bi / np.linalg.norm(bi) bj = np.cross(vgap, bi) bj = bj / np.linalg.norm(bj) # pick b by = np.sqrt(bnorm**2 - bx**2) b = bx * bi + by * bj xsub = xgap + b # find velocity plane vi = np.cross(vgap, b) vi = vi / np.linalg.norm(vi) vj = np.cross(b, vi) vj = vj / np.linalg.norm(vj) # pick v vy = np.sqrt(vnorm**2 - vx**2) vsub = vx * vi + vy * vj outdict = {'model': model, 'xsub': xsub, 'vsub': vsub} pickle.dump(outdict, open('../data/fiducial_at_encounter.pkl', 'wb'))