def test_call_marginalizevperp(): from galpy.orbit import Orbit idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(twophio=0.001) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot[0], to=-10.) #one with just one potential #l=0 R, phi, vR = 0.8, 0., 0.4 vts = numpy.linspace(0., 1.5, 51) pvts = numpy.array( [edf(Orbit([R, vR, vt, phi]), integrate_method='rk6_c') for vt in vts]) assert numpy.fabs(numpy.sum(pvts)*(vts[1]-vts[0])\ -edf(Orbit([R,vR,0.,phi]),marginalizeVperp=True,integrate_method='rk6_c')) < 10.**-3.5, 'evolveddiskdf call w/ marginalizeVperp does not work' #l=270 edf = evolveddiskdf(idf, pot=pot, to=-10.) R, phi, vT = numpy.sin(numpy.pi / 6.), -numpy.pi / 3., 0.7 #l=30 degree vrs = numpy.linspace(-1., 1., 101) pvrs = numpy.array( [edf(Orbit([R, vr, vT, phi]), integrate_method='rk6_c') for vr in vrs]) assert numpy.fabs(numpy.log(numpy.sum(pvrs)*(vrs[1]-vrs[0]))\ -edf(Orbit([R,0.,vT,phi]), marginalizeVperp=True, integrate_method='rk6_c',log=True, nsigma=4)) < 10.**-2.5, 'evolveddiskdf call w/ marginalizeVperp does not work' return None
def peculiar(ra, dec, d, pm_ra, pm_dec, V): o = Orbit([ra * u.deg, dec * u.deg, d * u.kpc, pm_ra * u.mas / u.yr, pm_dec * u.mas / u.yr, V * u.km / u.s], radec=True) o2 = Orbit(vxvv=[o.R(0.) / 8.0, 0., 1., 0., 0., o.phi(0.)], ro=8., vo=220.) current_vel = np.sqrt( (o.U(0.) - o2.U(0) + 11.1) ** 2 + (o.V(0.) - o2.V(0) + 12.24) ** 2 + (o.W(0.) - o2.W(0) + 7.25) ** 2) return current_vel
def test_qdf(): from galpy.df import quasiisothermaldf from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleStaeckel # Setup actionAngle instance for action calcs aAS= actionAngleStaeckel(pot=MWPotential2014,delta=0.45, c=True) # Quasi-iso df w/ hr=1/3, hsr/z=1, sr(1)=0.2, sz(1)=0.1 df= quasiisothermaldf(1./3.,0.2,0.1,1.,1.,aA=aAS, pot=MWPotential2014) # Evaluate DF w/ R,vR,vT,z,vz df(0.9,0.1,0.8,0.05,0.02) assert numpy.fabs(df(0.9,0.1,0.8,0.05,0.02)-numpy.array([ 123.57158928])) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF w/ Orbit instance, return ln from galpy.orbit import Orbit df(Orbit([0.9,0.1,0.8,0.05,0.02]),log=True) assert numpy.fabs(df(Orbit([0.9,0.1,0.8,0.05,0.02]),log=True)-numpy.array([ 4.81682066])) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF marginalized over vz df.pvRvT(0.1,0.9,0.9,0.05) assert numpy.fabs(df.pvRvT(0.1,0.9,0.9,0.05)-23.273310451852243) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF marginalized over vR,vT df.pvz(0.02,0.9,0.05) assert numpy.fabs(df.pvz(0.02,0.9,0.05)-50.949586235238172) < 10.**-4., 'qdf does not behave as expected' # Calculate the density df.density(0.9,0.05) assert numpy.fabs(df.density(0.9,0.05)-12.73725936526167) < 10.**-4., 'qdf does not behave as expected' # Estimate the DF's actual density scale length at z=0 df.estimate_hr(0.9,0.) assert numpy.fabs(df.estimate_hr(0.9,0.)-0.322420336223) < 10.**-2., 'qdf does not behave as expected' # Estimate the DF's actual surface-density scale length df.estimate_hr(0.9,None) assert numpy.fabs(df.estimate_hr(0.9,None)-0.38059909132766462) < 10.**-4., 'qdf does not behave as expected' # Estimate the DF's density scale height df.estimate_hz(0.9,0.02) assert numpy.fabs(df.estimate_hz(0.9,0.02)-0.064836202345657207) < 10.**-4., 'qdf does not behave as expected' # Calculate the mean velocities df.meanvR(0.9,0.05), df.meanvT(0.9,0.05), df.meanvz(0.9,0.05) assert numpy.fabs(df.meanvR(0.9,0.05)-3.8432265354618213e-18) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(df.meanvT(0.9,0.05)-0.90840425173325279) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(df.meanvz(0.9,0.05)+4.3579787517991084e-19) < 10.**-4., 'qdf does not behave as expected' # Calculate the velocity dispersions from numpy import sqrt sqrt(df.sigmaR2(0.9,0.05)), sqrt(df.sigmaz2(0.9,0.05)) assert numpy.fabs(sqrt(df.sigmaR2(0.9,0.05))-0.22695537077102387) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(sqrt(df.sigmaz2(0.9,0.05))-0.094215523962105044) < 10.**-4., 'qdf does not behave as expected' # Calculate the tilt of the velocity ellipsoid # 2017/10-28: CHANGED bc tilt now returns angle in rad, no longer in deg df.tilt(0.9,0.05) assert numpy.fabs(df.tilt(0.9,0.05)-2.5166061974413765/180.*numpy.pi) < 10.**-4., 'qdf does not behave as expected' # Calculate a higher-order moment of the velocity DF df.vmomentdensity(0.9,0.05,6.,2.,2.,gl=True) assert numpy.fabs(df.vmomentdensity(0.9,0.05,6.,2.,2.,gl=True)-0.0001591100892366438) < 10.**-4., 'qdf does not behave as expected' # Sample velocities at given R,z, check mean numpy.random.seed(1) vs= df.sampleV(0.9,0.05,n=500); mvt= numpy.mean(vs[:,1]) assert numpy.fabs(numpy.mean(vs[:,0])) < 0.05 # vR assert numpy.fabs(mvt-df.meanvT(0.9,0.05)) < 0.01 #vT assert numpy.fabs(numpy.mean(vs[:,2])) < 0.05 # vz return None
def test_surfacesection(): #Preliminary code import numpy from galpy.potential import MWPotential2014 from galpy.potential import evaluatePotentials as evalPot from galpy.orbit import Orbit E, Lz= -1.25, 0.6 o1= Orbit([0.8,0.,Lz/0.8,0.,numpy.sqrt(2.*(E-evalPot(MWPotential2014,0.8,0.)-(Lz/0.8)**2./2.)),0.]) ts= numpy.linspace(0.,100.,2001) o1.integrate(ts,MWPotential2014) o2= Orbit([0.8,0.3,Lz/0.8,0.,numpy.sqrt(2.*(E-evalPot(MWPotential2014,0.8,0.)-(Lz/0.8)**2./2.-0.3**2./2.)),0.]) o2.integrate(ts,MWPotential2014) def surface_section(Rs,zs,vRs): # Find points where the orbit crosses z from - to + shiftzs= numpy.roll(zs,-1) indx= (zs[:-1] < 0.)*(shiftzs[:-1] > 0.) return (Rs[:-1][indx],vRs[:-1][indx]) # Calculate and plot the surface of section ts= numpy.linspace(0.,1000.,20001) # long integration o1.integrate(ts,MWPotential2014) o2.integrate(ts,MWPotential2014) sect1Rs,sect1vRs=surface_section(o1.R(ts),o1.z(ts),o1.vR(ts)) sect2Rs,sect2vRs=surface_section(o2.R(ts),o2.z(ts),o2.vR(ts)) from matplotlib.pyplot import plot, xlim, ylim plot(sect1Rs,sect1vRs,'bo',mec='none') xlim(0.3,1.); ylim(-0.69,0.69) plot(sect2Rs,sect2vRs,'yo',mec='none') return None
def test_call_marginalizevlos(): from galpy.orbit import Orbit idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(twophio=0.001) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot[0], to=-10.) #one with just one potential #l=0 R, phi, vT = 0.8, 0., 0.7 vrs = numpy.linspace(-1., 1., 101) pvrs = numpy.array( [edf(Orbit([R, vr, vT, phi]), integrate_method='rk6_c') for vr in vrs]) assert numpy.fabs(numpy.log(numpy.sum(pvrs)*(vrs[1]-vrs[0]))\ -edf(Orbit([R,0.,vT,phi]),marginalizeVlos=True,integrate_method='rk6_c',log=True)) < 10.**-4., 'diskdf call w/ marginalizeVlos does not work' #l=270, this DF has some issues, but it suffices to test the mechanics of the code edf = evolveddiskdf(idf, pot=pot, to=-10.) R, phi, vR = numpy.sin(numpy.pi / 6.), -numpy.pi / 3., 0.4 #l=30 degree vts = numpy.linspace(0.3, 1.5, 101) pvts = numpy.array( [edf(Orbit([R, vR, vt, phi]), integrate_method='rk6_c') for vt in vts]) assert numpy.fabs(numpy.sum(pvts)*(vts[1]-vts[0])\ -edf(Orbit([R,vR,0.,phi]), marginalizeVlos=True, integrate_method='rk6_c', nsigma=4)) < 10.**-3.5, 'diskdf call w/ marginalizeVlos does not work' return None
def test_leapfrog_nfw_galpy(self): # Compare a more complicated set of initial conditions to the galpy # outputs (which are slow but known to work). # Set the parameters for a slightly offset circular orbit rho_0 = 0.1 r_scale = 1 G = 0.8962419740798497 dt = 0.001 num_dt = int(5e4) pos_nfw_array = np.tile(np.zeros(3,dtype=np.float64),(num_dt,1)) save_pos = np.zeros((num_dt+1,3)) save_vel = np.zeros((num_dt+1,3)) # Change the rho_0 and r_scale to a fixed array in time rho_0_array = rho_0*np.ones(num_dt,dtype=np.float64) r_scale_array = r_scale*np.ones(num_dt,dtype=np.float64) r_init = 20 pos_init = np.array([r_init,0,0],dtype=np.float64) M_r = 4*np.pi*rho_0*r_scale**3*(np.log((r_scale+r_init)/r_scale)+ r_scale/(r_scale+r_init) - 1) v_r = np.sqrt(G*M_r/r_init) v_kick = 1e-1 vel_init = np.array([v_kick,v_r,0],dtype=np.float64) integrator.leapfrog_int_nfw(pos_init,vel_init,rho_0_array, r_scale_array,pos_nfw_array,dt,save_pos,save_vel) # Compare to galpy orbits o=Orbit([r_init,v_kick,v_r,0,0,0]) nfw = NFWPotential(a=r_scale,amp=rho_0*G*4*np.pi*r_scale**3) ts = np.linspace(0,dt*num_dt,num_dt+1) o.integrate(ts,nfw,method='leapfrog',dt=dt) np.testing.assert_almost_equal(o.x(ts),save_pos[:,0]) np.testing.assert_almost_equal(o.y(ts),save_pos[:,1]) np.testing.assert_almost_equal(o.z(ts),save_pos[:,2]) # Make the kick bigger and see what happens v_kick = 5e-1 pos_init = np.array([r_init,0,0],dtype=np.float64) vel_init = np.array([v_kick,v_r,v_kick],dtype=np.float64) integrator.leapfrog_int_nfw(pos_init,vel_init,rho_0_array, r_scale_array,pos_nfw_array,dt,save_pos,save_vel) # Do the same for galpy o=Orbit([r_init,v_kick,v_r,0,v_kick,0]) nfw = NFWPotential(a=r_scale,amp=rho_0*G*4*np.pi*r_scale**3) ts = np.linspace(0,dt*num_dt,num_dt+1) o.integrate(ts,nfw,method='leapfrog',dt=dt) np.testing.assert_almost_equal(o.x(ts),save_pos[:,0]) np.testing.assert_almost_equal(o.y(ts),save_pos[:,1]) np.testing.assert_almost_equal(o.z(ts),save_pos[:,2])
def sample_spraydf_pal5_spiral(Nsamples, spiralpot, fo='blah_trailing.dat', trailing=True): p5 = Orbit([229.018, -0.124, 23.2, -2.296, -2.257, -58.7], radec=True, ro=ro, vo=vo, solarmotion=[-11.1, 24., 7.25]) #convert to galpy units pal5 = Orbit(p5._orb.vxvv) if trailing: spdft = streamspraydf.streamspraydf(50000. * u.Msun, progenitor=pal5, pot=spiralpot, leading=False, tdisrupt=5. * u.Gyr) RvR, dt = spdft.sample(n=Nsamples, returndt=True, integrate=True) R = RvR[0] vR = RvR[1] vT = RvR[2] z = RvR[3] vz = RvR[4] phi = RvR[5] fo = open(fo, 'w') else: spdf = streamspraydf.streamspraydf(50000. * u.Msun, progenitor=pal5, pot=spiralpot, tdisrupt=5. * u.Gyr) RvR, dt = spdf.sample(n=Nsamples, returndt=True, integrate=True) R = RvR[0] vR = RvR[1] vT = RvR[2] z = RvR[3] vz = RvR[4] phi = RvR[5] fo_lead = fo.replace('trailing', 'leading') fo = open(fo_lead, 'w') fo.write("#R phi z vR vT vz ts" + "\n") for jj in range(Nsamples): fo.write( str(R[jj]) + " " + str(phi[jj]) + " " + str(z[jj]) + " " + str(vR[jj]) + " " + str(vT[jj]) + " " + str(vz[jj]) + " " + str(dt[jj]) + "\n") fo.close() return None
def test_careful_traceback_and_forward(): """Step by step, project orbit forward, then backward""" bovy_times = np.array([0., np.pi / 3.]) chron_times = torb.convert_bovytime2myr(bovy_times) init_pos_chron = np.array([ 4000, 8000. * np.sqrt(3) / 2, 0, np.sin(np.pi / 3) * 220., -np.cos(np.pi / 3) * 220., 0 ]) init_pos_galpy = torb.convert_cart2galpycoords(init_pos_chron, ts=0.) assert np.allclose(np.array([1., 0, 1, 0, 0, np.pi / 3.]), init_pos_galpy) o = Orbit(vxvv=init_pos_galpy, ro=8., vo=220.) o.integrate(bovy_times, MWPotential2014, method='odeint') orbit_galpy = o.getOrbit() assert np.allclose(init_pos_galpy, orbit_galpy[0]) assert np.allclose( init_pos_galpy + np.array([0., 0., 0., 0., 0., bovy_times[-1]]), orbit_galpy[-1]) orbit_chron = torb.convert_galpycoords2cart(orbit_galpy, ts=bovy_times) assert np.allclose(init_pos_chron, orbit_chron[0]) assert np.allclose(init_pos_chron, orbit_chron[-1]) # Setup for backwards time integration # Currently at time of PI/3 back_init_pos_chron = orbit_chron[-1] back_init_pos_galpy = torb.convert_cart2galpycoords( back_init_pos_chron, bovy_times=bovy_times[-1], ) assert np.allclose( back_init_pos_galpy, torb.convert_cart2galpycoords(back_init_pos_chron, bovy_times=bovy_times[-1])) back_o = Orbit(vxvv=back_init_pos_galpy, ro=8., vo=220.) back_o.integrate(-1 * bovy_times, MWPotential2014, method='odeint') back_orbit_galpy = back_o.getOrbit() assert np.allclose(back_init_pos_galpy, back_orbit_galpy[0]) assert np.allclose( back_init_pos_galpy - np.array([0., 0., 0., 0., 0., bovy_times[-1]]), back_orbit_galpy[-1]) assert np.allclose(init_pos_galpy, back_orbit_galpy[-1]) back_orbit_chron = torb.convert_galpycoords2cart( back_orbit_galpy, ts=bovy_times[::-1], ) assert np.allclose(init_pos_chron, back_orbit_chron[-1])
def test_call_special(): from galpy.orbit import Orbit idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(twophio=0.001)] #very mild non-axi edf= evolveddiskdf(idf,pot=pot,to=-10.) o= Orbit([0.9,0.1,1.1,2.]) #call w/ and w/o explicit t assert numpy.fabs(numpy.log(edf(o,0.))-numpy.log(edf(o))) < 10.**-10., 'edf.__call__ w/ explicit t=0. and w/o t do not give the same answer' #call must get Orbit, otherwise error try: edf(0.9,0.1,1.1,2.) except IOError: pass else: raise AssertionError('edf.__call__ w/o Orbit input did not raise IOError') #Call w/ list, but just to assert numpy.fabs(numpy.log(edf(o,[-10.]))-numpy.log(idf(o))) < 10.**-10., 'edf.__call__ w/ tlist set to [to] did not return initial DF' #Call w/ just to assert numpy.fabs(numpy.log(edf(o,-10.))-numpy.log(idf(o))) < 10.**-10., 'edf.__call__ w/ tlist set to [to] did not return initial DF' #also w/ log assert numpy.fabs(edf(o,[-10.],log=True)-numpy.log(idf(o))) < 10.**-10., 'edf.__call__ w/ tlist set to [to] did not return initial DF (log)' assert numpy.fabs(edf(o,-10.,log=True)-numpy.log(idf(o))) < 10.**-10., 'edf.__call__ w/ tlist set to [to] did not return initial DF (log)' # Tests w/ odeint: tlist codeint= edf(o,[0.,-2.5,-5.,-7.5,-10.],integrate_method='odeint',log=True) crk6c= edf(o,[0.,-2.5,-5.,-7.5,-10.],integrate_method='rk6_c',log=True) assert numpy.all(numpy.fabs(codeint-crk6c) < 10.**-4.), 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c' # Crazy orbit w/ tlist crk6c= edf(Orbit([3.,1.,-1.,2.]),[0.],integrate_method='odeint',log=True) assert crk6c < -20., 'crazy orbit does not have DF equal to zero' # deriv w/ odeint codeint= edf(o,[0.,-2.5,-5.,-7.5,-10.],integrate_method='odeint', deriv='R') crk6c= edf(o,[0.,-2.5,-5.,-7.5,-10.],integrate_method='rk6_c',deriv='R') assert numpy.all(numpy.fabs(codeint-crk6c) < 10.**-4.), 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c (deriv=R)' # deriv w/ len(tlist)=1 crk6c= edf(o,[0.],integrate_method='rk6_c',deriv='R') crk6c2= edf(o,0.,integrate_method='rk6_c',deriv='R') assert numpy.all(numpy.fabs(crk6c-crk6c2) < 10.**-4.), 'edf.__call__ w/ tlist consisting of one time and just a scalar time do not agree' #Call w/ just to and deriv assert numpy.fabs(edf(o,-10.,deriv='R')-idf(o)*idf._dlnfdR(o._orb.vxvv[0],o._orb.vxvv[1],o._orb.vxvv[2])) < 10.**-10., 'edf.__call__ w/ to did not return initial DF (deriv=R)' assert numpy.fabs(edf(o,-10.,deriv='phi')) < 10.**-10., 'edf.__call__ w/ to did not return initial DF (deriv=phi)' # Call w/ just one t and odeint codeint= edf(o,0,integrate_method='odeint',log=True) crk6c= edf(o,0.,integrate_method='rk6_c',log=True) assert numpy.fabs(codeint-crk6c) < 10.**-4., 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c' # Call w/ just one t and fallback to odeint # turn off C edf._pot[0].hasC= False edf._pot[0].hasC_dxdv= False codeint= edf(o,0,integrate_method='dopr54_c',log=True) assert numpy.fabs(codeint-crk6c) < 10.**-4., 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c' # Call w/ just one t and fallback to leaprog cleapfrog= edf(o,0,integrate_method='leapfrog_c',log=True) assert numpy.fabs(cleapfrog-crk6c) < 10.**-4., 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c'
def sample_streamdf_pal5_noprog(N,barpot,nobarpot,fo='blah_trailing.dat',trailing=True): if trailing : sdf_trailing= pal5_util.setup_pal5model(pot=nobarpot) R,vR,vT,z,vz,phi,dt= sdf_trailing.sample(n=N,returndt=True) fo=open(fo,'w') else : sdf_leading= pal5_util.setup_pal5model(pot=nobarpot,leading=True) R,vR,vT,z,vz,phi,dt= sdf_leading.sample(n=N,returndt=True) fo_lead=fo.replace('trailing','leading') fo=open(fo_lead,'w') finalR= numpy.empty(N) finalvR=numpy.empty(N) finalvT=numpy.empty(N) finalvz=numpy.empty(N) finalphi= numpy.empty(N) finalz= numpy.empty(N) tt=numpy.empty(N) for ii in range(N): o= Orbit([R[ii],vR[ii],vT[ii],z[ii],vz[ii],phi[ii]]) o.turn_physical_off() ts= numpy.linspace(0.,-dt[ii],1001) o.integrate(ts,nobarpot) orb=Orbit([o.R(ts[-1]),o.vR(ts[-1]),o.vT(ts[-1]),o.z(ts[-1]),o.vz(ts[-1]),o.phi(ts[-1])]) ts_future= numpy.linspace(-dt[ii],0.,1001) #forward integrate in barred potential orb.integrate(ts_future,barpot) finalR[ii]= orb.R(ts_future[-1]) finalphi[ii]= orb.phi(ts_future[-1]) finalz[ii]= orb.z(ts_future[-1]) finalvR[ii]=orb.vR(ts_future[-1]) finalvT[ii]=orb.vT(ts_future[-1]) finalvz[ii]=orb.vz(ts_future[-1]) tt[ii]=dt[ii] fo.write("#R phi z vR vT vz ts" + "\n") for jj in range(N): fo.write(str(finalR[jj]) + " " + str(finalphi[jj]) + " " + str(finalz[jj]) + " " + str(finalvR[jj]) + " " + str(finalvT[jj]) + " " + str(finalvz[jj]) + " " + str(tt[jj]) + "\n") fo.close() return None
def test_orbitint(): import numpy from galpy.potential import MWPotential2014 from galpy.potential import evaluatePotentials as evalPot from galpy.orbit import Orbit E, Lz= -1.25, 0.6 o1= Orbit([0.8,0.,Lz/0.8,0.,numpy.sqrt(2.*(E-evalPot(MWPotential2014,0.8,0.)-(Lz/0.8)**2./2.)),0.]) ts= numpy.linspace(0.,100.,2001) o1.integrate(ts,MWPotential2014) o1.plot(xrange=[0.3,1.],yrange=[-0.2,0.2],color='k') o2= Orbit([0.8,0.3,Lz/0.8,0.,numpy.sqrt(2.*(E-evalPot(MWPotential2014,0.8,0.)-(Lz/0.8)**2./2.-0.3**2./2.)),0.]) o2.integrate(ts,MWPotential2014) o2.plot(xrange=[0.3,1.],yrange=[-0.2,0.2],color='k') return None
def add_orbit_from_prev(self, pot=None, vxvv=None, **kw): """Add orbit from prev conditions. Parameters ---------- pot: Potential vxvv: list Returns ------- self """ # Checking integrated previous orbit (has non-zero time domain) if not self._check_curr_orbit_integrated(): return # Forward or Backwards? drct = self._data.direction if drct == "forward": oldt = self._bounds[1] # getting current time if vxvv is None: # use most recent orbit orbit = Orbit(vxvv=self.o.SkyCoord(oldt)) elif isinstance(vxvv, Orbit): orbit = vxvv else: orbit = Orbit(vxvv=vxvv, **kw) self._data.append(oldt, orbit) else: oldt = self._bounds[0] # getting current time if vxvv is None: # use most recent orbit orbit = Orbit(vxvv=self.o.SkyCoord(oldt)) elif isinstance(vxvv, Orbit): orbit = vxvv else: orbit = Orbit(vxvv=vxvv, **kw) self._data.prepend(oldt, orbit) # potential if pot is not None: self._pot = pot return self
def test_nemo_MWPotential2014(): mp = potential.MWPotential2014 tmax = 3.5 vo, ro = 220., 8. o = Orbit([1., 0.1, 1.1, 0.2, 0.1, 1.4], ro=ro, vo=vo) run_orbitIntegration_comparison(o, mp, tmax, vo, ro, isList=True) return None
def test_nemo_PlummerPotential(): pp = potential.PlummerPotential(normalize=1., b=2.) tmax = 3. vo, ro = 213., 8.23 o = Orbit([1., 0.1, 1.1, 0.3, 0.1, 0.4], ro=ro, vo=vo) run_orbitIntegration_comparison(o, pp, tmax, vo, ro, tol=0.03) return None
def test_nemo_LogarithmicHaloPotential(): lp = potential.LogarithmicHaloPotential(normalize=1.) tmax = 2. vo, ro = 210., 8.5 o = Orbit([1., 0.1, 1.1, 0.3, 0.1, 0.4], ro=ro, vo=vo) run_orbitIntegration_comparison(o, lp, tmax, vo, ro, tol=0.03) return None
def test_nemo_HernquistPotential(): hp = potential.HernquistPotential(normalize=1., a=3.) tmax = 3. vo, ro = 210., 7.5 o = Orbit([1., 0.25, 1.4, 0.3, -0.1, 0.4], ro=ro, vo=vo) run_orbitIntegration_comparison(o, hp, tmax, vo, ro) return None
def test_nemo_NFWPotential(): np = potential.NFWPotential(normalize=1., a=3.) tmax = 3. vo, ro = 200., 7. o = Orbit([1., 0.5, 1.3, 0.3, 0.1, 0.4], ro=ro, vo=vo) run_orbitIntegration_comparison(o, np, tmax, vo, ro) return None
def observed_to_xyzuvw_orbit(obs, ts, lsr_orbit=None): """ Convert six-parameter astrometric solution to XYZUVW orbit. Parameters ---------- obs : [RA (deg), DEC (deg), pi (mas), mu_ra (mas/yr), mu_dec (mas/yr), vlos (km/s)] Current kinematics ts : [ntimes] array times (in Myr) to traceback to lsr_orbit : Orbit the orbit of the local standard of rest for comparison, if None can calculate on the fly XYZUVW : [ntimes, 6] array The space position and velocities of the star in a co-rotating frame centred on the LSR """ #convert times from Myr into bovy_time bovy_ts = ts / (bovy_conversion.time_in_Gyr(220., 8.) * 1000 ) # bovy-time/Myr logging.info("max time in Myr: {}".format(np.max(ts))) logging.info("max time in Bovy time: {}".format(np.max(bovy_ts))) o = Orbit(vxvv=obs, radec=True, solarmotion='schoenrich') o.integrate(bovy_ts, mp, method='odeint') data = o.getOrbit() XYZUVW = galpy_coords_to_xyzuvw(data, bovy_ts) return XYZUVW
def pass_v(ra, dec, d, pm_ra, pm_dec, V, time, numpoints): o = Orbit([ra * u.deg, dec * u.deg, d * u.kpc, pm_ra * u.mas / u.yr, pm_dec * u.mas / u.yr, V * u.km / u.s], radec=True) lp = MWPotential2014 ts = np.linspace(0, time, numpoints) * u.Gyr o.integrate(ts, lp) pass_t_array = ts[np.where(np.sign(o.z(ts)[:-1]) - np.sign(o.z(ts)[1:]) != 0)[0]] results = [] for pass_t in pass_t_array: o2 = Orbit(vxvv=[o.R(pass_t) / 8.0, 0., 1., 0., 0., o.phi(pass_t)], ro=8., vo=220.) # results.append(np.sqrt((o.U(pass_t)-o2.U(0)+11.1)**2 + (o.V(pass_t)-o2.V(0)+12.24)**2 + (o.W(pass_t)-o2.W(0)+7.25)**2)) results.append( np.sqrt((o.U(pass_t) - o2.U(0)) ** 2 + (o.V(pass_t) - o2.V(0)) ** 2 + (o.W(pass_t) - o2.W(0)) ** 2)) return results
def test_actionConservation(): #_____initialize some KKSPot_____ Delta = 1.0 pot = KuzminKutuzovStaeckelPotential(ac=20., Delta=Delta, normalize=True) #_____initialize an orbit (twice)_____ vxvv = [1., 0.1, 1.1, 0.01, 0.1] o = Orbit(vxvv=vxvv) #_____integrate the orbit with C_____ ts = numpy.linspace(0, 101, 100) o.integrate(ts, pot, method='leapfrog_c') #_____Setup ActionAngle object and calculate actions (Staeckel approximation)_____ aAS = actionAngleStaeckel(pot=pot, delta=Delta, c=True) jrs, lzs, jzs = aAS(o.R(ts), o.vR(ts), o.vT(ts), o.z(ts), o.vz(ts)) assert numpy.all(numpy.fabs(jrs - jrs[0]) < 10.**-8.), \ 'Radial action is not conserved along orbit.' assert numpy.all(numpy.fabs(lzs - lzs[0]) < 10.**-8.), \ 'Angular momentum is not conserved along orbit.' assert numpy.all(numpy.fabs(jzs - jzs[0]) < 10.**-8.), \ 'Vertical action is not conserved along orbit.' return None
def test_estimateDelta(): #_____initialize some KKSPot_____ Delta = 1.0 pot = KuzminKutuzovStaeckelPotential(ac=20., Delta=Delta, normalize=True) #_____initialize an orbit (twice)_____ vxvv = [1., 0.1, 1.1, 0.01, 0.1] o = Orbit(vxvv=vxvv) #_____integrate the orbit with C_____ ts = numpy.linspace(0, 101, 100) o.integrate(ts, pot, method='leapfrog_c') #____estimate Focal length Delta_____ #for each time step individually: deltas_estimate = numpy.zeros(len(ts)) for ii in range(len(ts)): deltas_estimate[ii] = estimateDeltaStaeckel(pot, o.R(ts[ii]), o.z(ts[ii])) assert numpy.all(numpy.fabs(deltas_estimate - Delta) < 10.**-8), \ 'Focal length Delta estimated along the orbit is not constant.' #for all time steps together: delta_estimate = estimateDeltaStaeckel(pot, o.R(ts), o.z(ts)) assert numpy.fabs(delta_estimate - Delta) < 10.**-8, \ 'Focal length Delta estimated from the orbit is not the same as the input focal length.' return None
def initialise_orbit(ID): cand = gk_candidates[(gk_candidates.T[-1] == int(ID))] cand = cand[0] ra_mean = cand[0] ra_err = 0 #unavailable dec_mean = cand[1] dec_err = 0 pmRA_mean = cand[3] pmRA_err = cand[6] pmDec_mean = cand[4] pmDec_err = cand[7] #calc a random value from gaussian # ra = generate_rand(ra_mean, ra_err, measurement_type = 'mas') # dec = generate_rand(dec_mean, dec_err, measurement_type = 'mas') ra = ra_mean dec = dec_mean pmRA = generate_rand(pmRA_mean, pmRA_err) if pmDec_mean == pmDec_err: #some issue with things being wrong just ignore it pmDec = pmDec_mean else: pmDec = generate_rand(pmDec_mean, pmDec_err) #no error for distance in this set dist = cand[2] #VLOS is reliable and stays as is Vlos = cand[5] orbit = Orbit(vxvv=[ra, dec, dist, pmRA, pmDec, Vlos], radec=True, ro=8., vo=220., solarmotion="schoenrich") return orbit
def traceback2(params, times): """Trace forward a cluster. First column of returned array is the position of the cluster at a given age. Parameters ---------- times: float array Times to trace forward, in Myr. Note that positive numbers are going forward in time. params: float array [RA,DE,Plx,PM(RA),PM(DE),RV] RA = Right Ascension (Deg) DE = Declination (Deg) Plx = Paralax (Mas) PM(RA) = Proper motion (Right Ascension) (mas/yr) PM(DE) = Proper motion (Declination) (mas/yr) RV = Radial Velocity (km/s) age: Age of cluster, in Myr """ #FIXME: This is very out of date and should be deleted!!! #Times in Myr ts = -(times / 1e3) / bovy_conversion.time_in_Gyr(220., 8.) nts = len(times) #Positions and velocities in the co-rotating solar reference frame. xyzuvw = np.zeros((1, nts, 6)) #Trace forward the local standard of rest. lsr_orbit = Orbit(vxvv=[1., 0, 1, 0, 0., 0], vo=220, ro=8) lsr_orbit.integrate(ts, MWPotential2014) #,method='odeint') xyzuvw = integrate_xyzuvw(params, ts, lsr_orbit, MWPotential2014) return xyzuvw
def test_correctInitialSolarMotion(): age = np.pi # Half a galactic revolution # For reference: the expected solar motion as provided by Schoenrich REFERENCE_SCHOENRICH_SOLAR_MOTION = np.array([-11.1, -12.24, -7.25]) ntimesteps = 10 # vxvv is in cylindrical coordinates here. [R,vR,vT(,z,vz,phi)] lsr_orbit = Orbit(vxvv=[1, 0, 1, 0, 0, 0], vo=220, ro=8, solarmotion='schoenrich') lsr_orbit.integrate(np.linspace(0., age, ntimesteps), MWPotential2014) U = lsr_orbit.U(0) V = lsr_orbit.V(0) W = lsr_orbit.W(0) results = np.array([U, V, W]).reshape(3) for i, vel in enumerate('UVW'): print("For velocity {}:".format(vel)) print(" expected: {}".format(REFERENCE_SCHOENRICH_SOLAR_MOTION[i])) print(" received: {}".format(results[i])) assert (np.allclose(REFERENCE_SCHOENRICH_SOLAR_MOTION, results)),\ '!!! Using galpy version {} Need galpy version 1.1 !!!'.format( galpy.__version__ )
def make_nondefault_pal5stream(chain_ind,leading=False,timpact=None,b=0.8,hernquist=False,td=5.): orb,pot,sigv,tvo=set_prog_potential(chain_ind) try : sdf= pal5_util.setup_pal5model_MWfit(ro=_REFR0,vo=tvo,timpact=timpact,pot=pot,orb=orb,hernquist=hernquist,leading=leading,age=td,sigv=sigv) except numpy.linalg.LinAlgError: print ("using estimateBIsochrone") ts= numpy.linspace(0.,td,1001)/bovy_conversion.time_in_Gyr(_REFV0, _REFR0) prog = Orbit(orb,radec=True,ro=_REFR0,vo=tvo,solarmotion=[-11.1,24.,7.25]) prog.integrate(ts,pot) estb= estimateBIsochrone(pot,prog.R(ts,use_physical=False), prog.z(ts,use_physical=False), phi=prog.phi(ts,use_physical=False)) if estb[1] < 0.3: isob= 0.3 elif estb[1] > 1.5: isob= 1.5 else: isob= estb[1] print ("b=%f"%isob) sdf=pal5_util.setup_pal5model_MWfit(ro=_REFR0,vo=tvo,leading=leading,pot=pot,orb=orb,timpact=timpact,b=isob,hernquist=hernquist,age=td,sigv=sigv) return sdf
def test_amuse_PowerSphericalPotentialwCutoffPotential(): pp= potential.PowerSphericalPotentialwCutoff(normalize=1.,alpha=1.,rc=0.4) tmax= 2. vo,ro= 180., 9. o= Orbit([1.,0.03,1.03,0.2,0.1,0.4],ro=ro,vo=vo) run_orbitIntegration_comparison(o,pp,tmax,vo,ro) return None
def test_orbmethods(): from galpy.orbit import Orbit from galpy.potential import MWPotential2014 # 8/17/2019: added explicit z=0.025, because that was the default at the # time of the galpy paper, but the default has been changed o = Orbit([0.8, 0.3, 0.75, 0., 0.2, 0.], zo=0.025) # setup R,vR,vT,z,vz,phi times = numpy.linspace(0., 10., 1001) # Output times o.integrate(times, MWPotential2014) # Integrate o.E() # Energy assert numpy.fabs(o.E() + 1.2547650648697966 ) < 10.**-5., 'Orbit method does not work as expected' o.L() # Angular momentum assert numpy.all( numpy.fabs(o.L() - numpy.array([[0., -0.16, 0.6]])) < 10.**-5. ), 'Orbit method does not work as expected' o.Jacobi(OmegaP=0.65) #Jacobi integral E-OmegaP Lz assert numpy.fabs(o.Jacobi(OmegaP=0.65) - numpy.array([-1.64476506]) ) < 10.**-5., 'Orbit method does not work as expected' o.ER(times[-1]), o.Ez(times[-1]) # Rad. and vert. E at end assert numpy.fabs(o.ER(times[-1]) + 1.27601734263047 ) < 10.**-5., 'Orbit method does not work as expected' assert numpy.fabs(o.Ez(times[-1]) - 0.021252201847851909 ) < 10.**-5., 'Orbit method does not work as expected' o.rperi(), o.rap(), o.zmax() # Peri-/apocenter r, max. |z| assert numpy.fabs(o.rperi() - 0.44231993168097 ) < 10.**-5., 'Orbit method does not work as expected' assert numpy.fabs(o.rap() - 0.87769030382105 ) < 10.**-5., 'Orbit method does not work as expected' assert numpy.fabs(o.zmax() - 0.077452357289016 ) < 10.**-5., 'Orbit method does not work as expected' o.e() # eccentricity (rap-rperi)/(rap+rperi) assert numpy.fabs(o.e() - 0.32982348199330563 ) < 10.**-5., 'Orbit method does not work as expected' o.R(2., ro=8.) # Cylindrical radius at time 2. in kpc assert numpy.fabs(o.R(2., ro=8.) - 3.5470772876920007 ) < 10.**-3., 'Orbit method does not work as expected' o.vR(5., vo=220.) # Cyl. rad. velocity at time 5. in km/s assert numpy.fabs(o.vR(5., vo=220.) - 45.202530965094553 ) < 10.**-3., 'Orbit method does not work as expected' o.ra(1.), o.dec(1.) # RA and Dec at t=1. (default settings) # 5/12/2016: test weakened, because improved galcen<->heliocen # transformation has changed these, but still close assert numpy.fabs(o.ra(1.) - numpy.array([288.19277]) ) < 10.**-1., 'Orbit method does not work as expected' assert numpy.fabs(o.dec(1.) - numpy.array([18.98069155]) ) < 10.**-1., 'Orbit method does not work as expected' o.jr(type='adiabatic'), o.jz() # R/z actions (ad. approx.) assert numpy.fabs(o.jr(type='adiabatic') - 0.05285302231137586 ) < 10.**-3., 'Orbit method does not work as expected' assert numpy.fabs(o.jz() - 0.006637988850751242 ) < 10.**-3., 'Orbit method does not work as expected' # Rad. period w/ Staeckel approximation w/ focal length 0.5, o.Tr(type='staeckel', delta=0.5, ro=8., vo=220.) # in Gyr assert numpy.fabs( o.Tr(type='staeckel', delta=0.5, ro=8., vo=220.) - 0.1039467864018446 ) < 10.**-3., 'Orbit method does not work as expected' o.plot(d1='R', d2='z') # Plot the orbit in (R,z) o.plot3d() # Plot the orbit in 3D, w/ default [x,y,z] return None
def test_nemo_MN3ExponentialDiskPotential(): mn = potential.MN3ExponentialDiskPotential(normalize=1., hr=0.5, hz=0.1) tmax = 3. vo, ro = 215., 8.75 o = Orbit([1., 0.1, 1.1, 0.3, 0.1, 0.4], ro=ro, vo=vo) run_orbitIntegration_comparison(o, mn, tmax, vo, ro) return None
def test_nemo_MiyamotoNagaiPotential(): mp = potential.MiyamotoNagaiPotential(normalize=1., a=0.5, b=0.1) tmax = 4. vo, ro = 220., 8. o = Orbit([1., 0.1, 1.1, 0.3, 0.1, 0.4], ro=ro, vo=vo) run_orbitIntegration_comparison(o, mp, tmax, vo, ro) return None
def initialise_orbit(ID): cand = gk_candidates[(gk_candidates[-1] == ID)] ra_mean = cand[0] ra_err = 0 #unavailable dec_mean = cand[1] dec_err = 0 pmRA_mean = cand[3] pmRA_err = cand[6] pmDec_mean = cand[4] pmDec_err = cand[7] #calc a random value from gaussian ra = generate_rand(ra_mean, ra_err, measurement_type='mas') dec = generate_rand(dec_mean, dec_err, measurement_type='mas') pmRA = generate_rand(pmRA_mean, pmRA_err) pmDec = generate_rand(pmDec_mean, pmDec_err) #no error for distance in this set dist = cand[2] #VLOS is reliable and stays as is Vlos = cand[5] orbit = Orbit(vxvv=[ra, dec, dist, pmRA, pmDec, Vlos], radec=True, ro=8., vo=220., solarmotion="schoenrich") return orbit