def test_actionAngleTorus_interppot_freqs(): from galpy.actionAngle import actionAngleTorus from galpy.potential import LogarithmicHaloPotential, interpRZPotential lp = LogarithmicHaloPotential(normalize=1.) ip = interpRZPotential(RZPot=lp, interpPot=True, interpDens=True, interpRforce=True, interpzforce=True, enable_c=True) aAT = actionAngleTorus(pot=lp) aATi = actionAngleTorus(pot=ip) jr, jphi, jz = 0.05, 1.1, 0.02 om = aAT.Freqs(jr, jphi, jz) omi = aATi.Freqs(jr, jphi, jz) assert numpy.fabs( (om[0] - omi[0]) / om[0] ) < 0.2, 'Radial frequency computed using the torus machine does not agree between potential and interpolated potential' assert numpy.fabs( (om[1] - omi[1]) / om[1] ) < 0.2, 'Azimuthal frequency computed using the torus machine does not agree between potential and interpolated potential' assert numpy.fabs( (om[2] - omi[2]) / om[2] ) < 0.8, 'Vertical frequency computed using the torus machine does not agree between potential and interpolated potential' return None
def test_actionAngleTorus_basic(): from galpy.actionAngle import actionAngleTorus from galpy.potential import MWPotential, rl, vcirc, \ FlattenedPowerPotential, PlummerPotential tol= -4. jr= 10.**-10. jz= 10.**-10. aAT= actionAngleTorus(pot=MWPotential) # at R=1, Lz=1 jphi= 1. angler= numpy.linspace(0.,2.*numpy.pi,101) anglephi= numpy.linspace(0.,2.*numpy.pi,101)+1. anglez= numpy.linspace(0.,2.*numpy.pi,101)+2. RvR= aAT(jr,jphi,jz,angler,anglephi,anglez).T assert numpy.all(numpy.fabs(RvR[0]-rl(MWPotential,jphi)) < 10.**tol), \ 'circular orbit does not have constant radius for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[1]) < 10.**tol), \ 'circular orbit does not have zero radial velocity for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[2]-vcirc(MWPotential,rl(MWPotential,jphi))) < 10.**tol), \ 'circular orbit does not have constant vT=vc for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[3]) < 10.**tol), \ 'circular orbit does not have zero vertical height for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[4]) < 10.**tol), \ 'circular orbit does not have zero vertical velocity for actionAngleTorus' # at Lz=1.5, using Plummer tol= -3.25 pp= PlummerPotential(normalize=1.) aAT= actionAngleTorus(pot=pp) jphi= 1.5 RvR= aAT(jr,jphi,jz,angler,anglephi,anglez).T assert numpy.all(numpy.fabs(RvR[0]-rl(pp,jphi)) < 10.**tol), \ 'circular orbit does not have constant radius for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[1]) < 10.**tol), \ 'circular orbit does not have zero radial velocity for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[2]-vcirc(pp,rl(pp,jphi))) < 10.**tol), \ 'circular orbit does not have constant vT=vc for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[3]) < 10.**tol), \ 'circular orbit does not have zero vertical height for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[4]) < 10.**tol), \ 'circular orbit does not have zero vertical velocity for actionAngleTorus' # at Lz=0.5, using FlattenedPowerPotential tol= -4. fp= FlattenedPowerPotential(normalize=1.) aAT= actionAngleTorus(pot=fp) jphi= 0.5 RvR= aAT(jr,jphi,jz,angler,anglephi,anglez).T assert numpy.all(numpy.fabs(RvR[0]-rl(fp,jphi)) < 10.**tol), \ 'circular orbit does not have constant radius for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[1]) < 10.**tol), \ 'circular orbit does not have zero radial velocity for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[2]-vcirc(fp,rl(fp,jphi))) < 10.**tol), \ 'circular orbit does not have constant vT=vc for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[3]) < 10.**tol), \ 'circular orbit does not have zero vertical height for actionAngleTorus' assert numpy.all(numpy.fabs(RvR[4]) < 10.**tol), \ 'circular orbit does not have zero vertical velocity for actionAngleTorus' return None
def test_actionAngleTorus_Isochrone_actions(): from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochrone ip = IsochronePotential(normalize=1., b=1.2) aAI = actionAngleIsochrone(ip=ip) tol = -6. aAT = actionAngleTorus(pot=ip, tol=tol) jr, jphi, jz = 0.075, 1.1, 0.05 angler = numpy.array([0.]) anglephi = numpy.array([numpy.pi]) anglez = numpy.array([numpy.pi / 2.]) # Calculate position from aAT RvR = aAT(jr, jphi, jz, angler, anglephi, anglez).T # Calculate actions from aAI ji = aAI(*RvR) djr = numpy.fabs((ji[0] - jr) / jr) dlz = numpy.fabs((ji[1] - jphi) / jphi) djz = numpy.fabs((ji[2] - jz) / jz) assert djr < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % ( djr * 100.) assert dlz < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % ( dlz * 100.) assert djz < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % ( djz * 100.) return None
def test_actionAngleTorus_Staeckel_actions(): from galpy.potential import KuzminKutuzovStaeckelPotential from galpy.actionAngle import actionAngleTorus, \ actionAngleStaeckel delta = 1.2 kp = KuzminKutuzovStaeckelPotential(normalize=1., Delta=delta) aAS = actionAngleStaeckel(pot=kp, delta=delta, c=True) tol = -3. aAT = actionAngleTorus(pot=kp, tol=tol) jr, jphi, jz = 0.075, 1.1, 0.05 angler = numpy.array([0.]) anglephi = numpy.array([numpy.pi]) anglez = numpy.array([numpy.pi / 2.]) # Calculate position from aAT RvR = aAT(jr, jphi, jz, angler, anglephi, anglez).T # Calculate actions from aAI ji = aAS(*RvR) djr = numpy.fabs((ji[0] - jr) / jr) dlz = numpy.fabs((ji[1] - jphi) / jphi) djz = numpy.fabs((ji[2] - jz) / jz) assert djr < 10.**tol, 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Jr at %f%%' % ( djr * 100.) assert dlz < 10.**tol, 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Jr at %f%%' % ( dlz * 100.) assert djz < 10.**tol, 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Jr at %f%%' % ( djz * 100.) return None
def test_actionAngleTorus_isochroneApprox_actions(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochroneApprox aAIA = actionAngleIsochroneApprox(pot=MWPotential2014, b=0.8) tol = -2.5 aAT = actionAngleTorus(pot=MWPotential2014, tol=tol) jr, jphi, jz = 0.075, 1.1, 0.05 angler = numpy.array([0.]) anglephi = numpy.array([numpy.pi]) anglez = numpy.array([numpy.pi / 2.]) # Calculate position from aAT RvR = aAT(jr, jphi, jz, angler, anglephi, anglez).T # Calculate actions from aAIA ji = aAIA(*RvR) djr = numpy.fabs((ji[0] - jr) / jr) dlz = numpy.fabs((ji[1] - jphi) / jphi) djz = numpy.fabs((ji[2] - jz) / jz) assert djr < 10.**tol, 'actionAngleTorus and actionAngleIsochroneApprox applied to MWPotential2014 potential disagree for Jr at %f%%' % ( djr * 100.) assert dlz < 10.**tol, 'actionAngleTorus and actionAngleIsochroneApprox applied to MWPotential2014 potential disagree for Jr at %f%%' % ( dlz * 100.) assert djz < 10.**tol, 'actionAngleTorus and actionAngleMWPotential2014 applied to MWPotential2014 potential disagree for Jr at %f%%' % ( djz * 100.) return None
def test_actionAngleTorus_hessian_symm(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus aAT= actionAngleTorus(pot=MWPotential2014) jr,jphi,jz= 0.075,1.1,0.05 h= aAT.hessianFreqs(jr,jphi,jz,tol=0.0001,nosym=True)[0] assert numpy.all(numpy.fabs((h-h.T)/h) < 0.03), 'actionAngleTorus Hessian is not symmetric' return None
def test_actionAngleTorus_interppot_freqs(): from galpy.actionAngle import actionAngleTorus from galpy.potential import LogarithmicHaloPotential, interpRZPotential lp= LogarithmicHaloPotential(normalize=1.) ip= interpRZPotential(RZPot=lp, interpPot=True, interpDens=True,interpRforce=True,interpzforce=True, enable_c=True) aAT= actionAngleTorus(pot=lp) aATi= actionAngleTorus(pot=ip) jr,jphi,jz= 0.05,1.1,0.02 om= aAT.Freqs(jr,jphi,jz) omi= aATi.Freqs(jr,jphi,jz) assert numpy.fabs((om[0]-omi[0])/om[0]) < 0.2, 'Radial frequency computed using the torus machine does not agree between potential and interpolated potential' assert numpy.fabs((om[1]-omi[1])/om[1]) < 0.2, 'Azimuthal frequency computed using the torus machine does not agree between potential and interpolated potential' assert numpy.fabs((om[2]-omi[2])/om[2]) < 0.8, 'Vertical frequency computed using the torus machine does not agree between potential and interpolated potential' return None
def setup_sdf(pot,prog,sigv,td,ro,vo,multi=None,nTrackChunks=8,isob=None, trailing_only=False,verbose=True,useTM=True,logpot=False): """Simple function to setup the stream model""" if isob is None: if True or logpot: isob= 0.75 if False: # Determine good one ts= numpy.linspace(0.,15.,1001) # Hack! epot= copy.deepcopy(pot) epot[2]._b= 1. epot[2]._b2= 1. epot[2]._isNonAxi= False epot[2]._aligned= True prog.integrate(ts,pot) estb= estimateBIsochrone(epot, 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] if verbose: print(pot[2]._c, isob,estb) if not logpot and numpy.fabs(pot[2]._b-1.) > 0.05: aAI= actionAngleIsochroneApprox(pot=pot,b=isob,tintJ=1000., ntintJ=30000) else: ts= numpy.linspace(0.,100.,10000) aAI= actionAngleIsochroneApprox(pot=pot,b=isob,tintJ=100., ntintJ=10000,dt=ts[1]-ts[0]) if useTM: aAT= actionAngleTorus(pot=pot,tol=0.001,dJ=0.0001) else: aAT= False try: sdf=\ streamdf(sigv/vo,progenitor=prog,pot=pot,aA=aAI, useTM=aAT,approxConstTrackFreq=True, leading=True,nTrackChunks=nTrackChunks, tdisrupt=td/bovy_conversion.time_in_Gyr(vo,ro), ro=ro,vo=vo,R0=ro, vsun=[-11.1,vo+24.,7.25], custom_transform=_TKOP, multi=multi, nospreadsetup=True) except numpy.linalg.LinAlgError: sdf=\ streamdf(sigv/vo,progenitor=prog,pot=pot,aA=aAI, useTM=aAT,approxConstTrackFreq=True, leading=True,nTrackChunks=nTrackChunks, nTrackIterations=0, tdisrupt=td/bovy_conversion.time_in_Gyr(vo,ro), ro=ro,vo=vo,R0=ro, vsun=[-11.1,vo+24.,7.25], custom_transform=_TKOP, multi=multi) return sdf
def test_actionAngleTorus_AutoFitWarning(): from galpy.potential import LogarithmicHaloPotential from galpy.actionAngle import actionAngleTorus lp= LogarithmicHaloPotential(normalize=1.,q=0.9) aAT= actionAngleTorus(pot=lp,tol=10.**-8.) # These should give warnings jr, jp, jz= 0.27209033, 1.80253892, 0.6078445 ar, ap, az= numpy.array([1.95732492]), numpy.array([6.16753224]), \ numpy.array([4.08233059]) #Turn warnings into errors to test for them import warnings with warnings.catch_warnings(record=True) as w: if PY2: reset_warning_registry('galpy') warnings.simplefilter("always",galpyWarning) aAT(jr,jp,jz,ar,ap,az) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always",galpyWarning) aAT.xvFreqs(jr,jp,jz,ar,ap,az) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always",galpyWarning) aAT.Freqs(jr,jp,jz) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always",galpyWarning) aAT.hessianFreqs(jr,jp,jz) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always",galpyWarning) aAT.xvJacobianFreqs(jr,jp,jz,ar,ap,az) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" return None
def test_actionAngleTorus_Staeckel_freqsAngles(): from galpy.potential import KuzminKutuzovStaeckelPotential from galpy.actionAngle import actionAngleTorus, \ actionAngleStaeckel delta = 1.2 kp = KuzminKutuzovStaeckelPotential(normalize=1., Delta=delta) aAS = actionAngleStaeckel(pot=kp, delta=delta, c=True) tol = -3. aAT = actionAngleTorus(pot=kp, tol=tol) jr, jphi, jz = 0.075, 1.1, 0.05 angler = numpy.array([0.1]) + numpy.linspace(0., numpy.pi, 101) angler = angler % (2. * numpy.pi) anglephi = numpy.array([numpy.pi]) + numpy.linspace(0., numpy.pi, 101) anglephi = anglephi % (2. * numpy.pi) anglez = numpy.array([numpy.pi / 2.]) + numpy.linspace(0., numpy.pi, 101) anglez = anglez % (2. * numpy.pi) # Calculate position from aAT RvRom = aAT.xvFreqs(jr, jphi, jz, angler, anglephi, anglez) # Calculate actions, frequencies, and angles from aAI ws = aAS.actionsFreqsAngles(*RvRom[0].T) dOr = numpy.fabs((ws[3] - RvRom[1])) dOp = numpy.fabs((ws[4] - RvRom[2])) dOz = numpy.fabs((ws[5] - RvRom[3])) dar = numpy.fabs((ws[6] - angler)) dap = numpy.fabs((ws[7] - anglephi)) daz = numpy.fabs((ws[8] - anglez)) dar[dar > numpy.pi] -= 2. * numpy.pi dar[dar < -numpy.pi] += 2. * numpy.pi dap[dap > numpy.pi] -= 2. * numpy.pi dap[dap < -numpy.pi] += 2. * numpy.pi daz[daz > numpy.pi] -= 2. * numpy.pi daz[daz < -numpy.pi] += 2. * numpy.pi assert numpy.all( dOr < 10.**tol ), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Or at %f%%' % ( numpy.nanmax(dOr) * 100.) assert numpy.all( dOp < 10.**tol ), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Ophi at %f%%' % ( numpy.nanmax(dOp) * 100.) assert numpy.all( dOz < 10.**tol ), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Oz at %f%%' % ( numpy.nanmax(dOz) * 100.) assert numpy.all( dar < 10.**tol ), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for ar at %f' % ( numpy.nanmax(dar)) assert numpy.all( dap < 10.**tol ), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for aphi at %f' % ( numpy.nanmax(dap)) assert numpy.all( daz < 10.**tol ), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for az at %f' % ( numpy.nanmax(daz)) return None
def test_actionAngleTorus_hessian_freqs(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus aAT= actionAngleTorus(pot=MWPotential2014) jr,jphi,jz= 0.075,1.1,0.05 fO= aAT.Freqs(jr,jphi,jz)[:3] hO= aAT.hessianFreqs(jr,jphi,jz)[1:4] assert numpy.all(numpy.fabs(numpy.array(fO)-numpy.array(hO)) < 10.**-8.), 'actionAngleTorus methods Freqs and hessianFreqs return different frequencies' return None
def test_actionAngleTorus_Isochrone_freqsAngles(): from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochrone ip = IsochronePotential(normalize=1., b=1.2) aAI = actionAngleIsochrone(ip=ip) tol = -6. aAT = actionAngleTorus(pot=ip, tol=tol) jr, jphi, jz = 0.075, 1.1, 0.05 angler = numpy.array([0.1]) + numpy.linspace(0., numpy.pi, 101) angler = angler % (2. * numpy.pi) anglephi = numpy.array([numpy.pi]) + numpy.linspace(0., numpy.pi, 101) anglephi = anglephi % (2. * numpy.pi) anglez = numpy.array([numpy.pi / 2.]) + numpy.linspace(0., numpy.pi, 101) anglez = anglez % (2. * numpy.pi) # Calculate position from aAT RvRom = aAT.xvFreqs(jr, jphi, jz, angler, anglephi, anglez) # Calculate actions, frequencies, and angles from aAI ws = aAI.actionsFreqsAngles(*RvRom[0].T) dOr = numpy.fabs((ws[3] - RvRom[1])) dOp = numpy.fabs((ws[4] - RvRom[2])) dOz = numpy.fabs((ws[5] - RvRom[3])) dar = numpy.fabs((ws[6] - angler)) dap = numpy.fabs((ws[7] - anglephi)) daz = numpy.fabs((ws[8] - anglez)) dar[dar > numpy.pi] -= 2. * numpy.pi dar[dar < -numpy.pi] += 2. * numpy.pi dap[dap > numpy.pi] -= 2. * numpy.pi dap[dap < -numpy.pi] += 2. * numpy.pi daz[daz > numpy.pi] -= 2. * numpy.pi daz[daz < -numpy.pi] += 2. * numpy.pi assert numpy.all( dOr < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Or at %f%%' % ( numpy.nanmax(dOr) * 100.) assert numpy.all( dOp < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Ophi at %f%%' % ( numpy.nanmax(dOp) * 100.) assert numpy.all( dOz < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Oz at %f%%' % ( numpy.nanmax(dOz) * 100.) assert numpy.all( dar < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for ar at %f' % ( numpy.nanmax(dar)) assert numpy.all( dap < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for aphi at %f' % ( numpy.nanmax(dap)) assert numpy.all( daz < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for az at %f' % ( numpy.nanmax(daz)) return None
def test_actionAngleTorus_nocerr(): from galpy.actionAngle import actionAngleTorus from test_potential import BurkertPotentialNoC bp= BurkertPotentialNoC() try: aAT= actionAngleTorus(pot=bp) except RuntimeError: pass else: raise AssertionError("actionAngleTorus initialization with potential w/o C should have given a RuntimeError, but didn't") return None
def test_actionAngleTorus_nonaxierr(): from galpy.actionAngle import actionAngleTorus from galpy.potential import TriaxialNFWPotential np= TriaxialNFWPotential(normalize=1.,b=0.9) try: aAT= actionAngleTorus(pot=np) except RuntimeError: pass else: raise AssertionError("actionAngleTorus initialization with non-axisymmetric potential should have given a RuntimeError, but didn't") return None
def test_actionAngleTorus_basic_freqs(): from galpy.actionAngle import actionAngleTorus from galpy.potential import epifreq, omegac, verticalfreq, rl, \ JaffePotential, PowerSphericalPotential, HernquistPotential tol= -3. jr= 10.**-6. jz= 10.**-6. jp= JaffePotential(normalize=1.) aAT= actionAngleTorus(pot=jp) # at Lz=1 jphi= 1. om= aAT.Freqs(jr,jphi,jz) assert numpy.fabs((om[0]-epifreq(jp,rl(jp,jphi)))/om[0]) < 10.**tol, \ 'Close-to-circular orbit does not have Or=kappa for actionAngleTorus' assert numpy.fabs((om[1]-omegac(jp,rl(jp,jphi)))/om[1]) < 10.**tol, \ 'Close-to-circular orbit does not have Ophi=omega for actionAngleTorus' assert numpy.fabs((om[2]-verticalfreq(jp,rl(jp,jphi)))/om[2]) < 10.**tol, \ 'Close-to-circular orbit does not have Oz=nu for actionAngleTorus' # at Lz=1.5, w/ different potential pp= PowerSphericalPotential(normalize=1.) aAT= actionAngleTorus(pot=pp) jphi= 1.5 om= aAT.Freqs(jr,jphi,jz) assert numpy.fabs((om[0]-epifreq(pp,rl(pp,jphi)))/om[0]) < 10.**tol, \ 'Close-to-circular orbit does not have Or=kappa for actionAngleTorus' assert numpy.fabs((om[1]-omegac(pp,rl(pp,jphi)))/om[1]) < 10.**tol, \ 'Close-to-circular orbit does not have Ophi=omega for actionAngleTorus' assert numpy.fabs((om[2]-verticalfreq(pp,rl(pp,jphi)))/om[2]) < 10.**tol, \ 'Close-to-circular orbit does not have Oz=nu for actionAngleTorus' # at Lz=0.5, w/ different potential tol= -2.5 # appears more difficult hp= HernquistPotential(normalize=1.) aAT= actionAngleTorus(pot=hp) jphi= 0.5 om= aAT.Freqs(jr,jphi,jz) assert numpy.fabs((om[0]-epifreq(hp,rl(hp,jphi)))/om[0]) < 10.**tol, \ 'Close-to-circular orbit does not have Or=kappa for actionAngleTorus' assert numpy.fabs((om[1]-omegac(hp,rl(hp,jphi)))/om[1]) < 10.**tol, \ 'Close-to-circular orbit does not have Ophi=omega for actionAngleTorus' assert numpy.fabs((om[2]-verticalfreq(hp,rl(hp,jphi)))/om[2]) < 10.**tol, \ 'Close-to-circular orbit does not have Oz=nu for actionAngleTorus' return None
def test_actionAngleTorus_jacobian_hessian(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus aAT= actionAngleTorus(pot=MWPotential2014) jr,jphi,jz= 0.075,1.1,0.05 fO= aAT.hessianFreqs(jr,jphi,jz)[0] hO= aAT.xvJacobianFreqs(jr,jphi,jz, numpy.array([0.]),numpy.array([1.]), numpy.array([2.]))[2] assert numpy.all(numpy.fabs(numpy.array(fO)-numpy.array(hO)) < 10.**-8.), 'actionAngleTorus methods hessianFreqs and xvJacobianFreqs return different Hessians' return None
def test_actionAngleTorus_hessian_linear(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus aAT= actionAngleTorus(pot=MWPotential2014) jr,jphi,jz= 0.075,1.1,0.05 h= aAT.hessianFreqs(jr,jphi,jz,tol=0.0001,nosym=True)[0] dj= numpy.array([0.02,0.005,-0.01]) do_fromhessian= numpy.dot(h,dj) O= numpy.array(aAT.Freqs(jr,jphi,jz)[:3]) do= numpy.array(aAT.Freqs(jr+dj[0],jphi+dj[1],jz+dj[2])[:3])-O assert numpy.all(numpy.fabs((do_fromhessian-do)/O)< 0.001), 'actionAngleTorus Hessian does not return good approximation to dO/dJ' return None
def test_actionAngleTorus_jacobian_xv(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus aAT= actionAngleTorus(pot=MWPotential2014) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.,1.]) anglephi= numpy.array([1.,2.]) anglez= numpy.array([2.,3.]) fO= aAT(jr,jphi,jz,angler,anglephi,anglez) hO= aAT.xvJacobianFreqs(jr,jphi,jz,angler,anglephi,anglez)[0] assert numpy.all(numpy.fabs(numpy.array(fO)-numpy.array(hO)) < 10.**-8.), 'actionAngleTorus methods __call__ and xvJacobianFreqs return different xv' return None
def test_actionAngleTorus_jacobian_detone(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus aAT= actionAngleTorus(pot=MWPotential2014,dJ=0.0001) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.,1.]) anglephi= numpy.array([1.,2.]) anglez= numpy.array([2.,3.]) jf= aAT.xvJacobianFreqs(jr,jphi,jz,angler,anglephi,anglez) assert numpy.fabs(jf[0][0,0]*numpy.fabs(numpy.linalg.det(jf[1][0]))-1) < 0.01, 'Jacobian returned by actionAngleTorus method xvJacobianFreqs does not have the expected determinant' assert numpy.fabs(jf[0][1,0]*numpy.fabs(numpy.linalg.det(jf[1][1]))-1) < 0.01, 'Jacobian returned by actionAngleTorus method xvJacobianFreqs does not have the expected determinant' return None
def test_MWPotential_warning_torus(): # Test that using MWPotential throws a warning, see #229 from galpy.actionAngle import actionAngleTorus from galpy.potential import MWPotential warnings.simplefilter("error",galpyWarning) try: aAA= actionAngleTorus(pot=MWPotential) except: pass else: raise AssertionError("actionAngleTorus with MWPotential should have thrown a warning, but didn't") #Turn warnings back into warnings warnings.simplefilter("always",galpyWarning) return None
def test_MWPotential_warning_torus(): # Test that using MWPotential throws a warning, see #229 from galpy.actionAngle import actionAngleTorus from galpy.potential import MWPotential if PY2: reset_warning_registry('galpy') warnings.simplefilter("error",galpyWarning) try: aAA= actionAngleTorus(pot=MWPotential) except: pass else: raise AssertionError("actionAngleTorus with MWPotential should have thrown a warning, but didn't") #Turn warnings back into warnings warnings.simplefilter("always",galpyWarning) return None
def test_actionAngleTorus_jacobian_linear(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus aAT= actionAngleTorus(pot=MWPotential2014) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.5]) anglephi= numpy.array([1.]) anglez= numpy.array([2.]) jf= aAT.xvJacobianFreqs(jr,jphi,jz,angler,anglephi,anglez) xv= aAT(jr,jphi,jz,angler,anglephi,anglez) dja= 2.*numpy.array([0.001,0.002,0.003,-0.002,0.004,0.002]) xv_direct= aAT(jr+dja[0],jphi+dja[1],jz+dja[2], angler+dja[3],anglephi+dja[4],anglez+dja[5]) xv_fromjac= xv+numpy.dot(jf[1],dja) assert numpy.all(numpy.fabs((xv_fromjac-xv_direct)/xv_direct) < 0.01), 'Jacobian returned by actionAngleTorus method xvJacobianFreqs does not appear to be correct' return None
def test_actionAngleTorus_Staeckel_freqsAngles(): from galpy.potential import KuzminKutuzovStaeckelPotential from galpy.actionAngle import actionAngleTorus, \ actionAngleStaeckel delta= 1.2 kp= KuzminKutuzovStaeckelPotential(normalize=1.,Delta=delta) aAS= actionAngleStaeckel(pot=kp,delta=delta,c=True) tol= -3. aAT= actionAngleTorus(pot=kp,tol=tol) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.1])+numpy.linspace(0.,numpy.pi,101) angler= angler % (2.*numpy.pi) anglephi= numpy.array([numpy.pi])+numpy.linspace(0.,numpy.pi,101) anglephi= anglephi % (2.*numpy.pi) anglez= numpy.array([numpy.pi/2.])+numpy.linspace(0.,numpy.pi,101) anglez= anglez % (2.*numpy.pi) # Calculate position from aAT RvRom= aAT.xvFreqs(jr,jphi,jz,angler,anglephi,anglez) # Calculate actions, frequencies, and angles from aAI ws= aAS.actionsFreqsAngles(*RvRom[0].T) dOr= numpy.fabs((ws[3]-RvRom[1])) dOp= numpy.fabs((ws[4]-RvRom[2])) dOz= numpy.fabs((ws[5]-RvRom[3])) dar= numpy.fabs((ws[6]-angler)) dap= numpy.fabs((ws[7]-anglephi)) daz= numpy.fabs((ws[8]-anglez)) dar[dar > numpy.pi]-= 2.*numpy.pi dar[dar < -numpy.pi]+= 2.*numpy.pi dap[dap > numpy.pi]-= 2.*numpy.pi dap[dap < -numpy.pi]+= 2.*numpy.pi daz[daz > numpy.pi]-= 2.*numpy.pi daz[daz < -numpy.pi]+= 2.*numpy.pi assert numpy.all(dOr < 10.**tol), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Or at %f%%' % (numpy.nanmax(dOr)*100.) assert numpy.all(dOp < 10.**tol), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Ophi at %f%%' % (numpy.nanmax(dOp)*100.) assert numpy.all(dOz < 10.**tol), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Oz at %f%%' % (numpy.nanmax(dOz)*100.) assert numpy.all(dar < 10.**tol), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for ar at %f' % (numpy.nanmax(dar)) assert numpy.all(dap < 10.**tol), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for aphi at %f' % (numpy.nanmax(dap)) assert numpy.all(daz < 10.**tol), 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for az at %f' % (numpy.nanmax(daz)) return None
def test_actionAngleTorus_orbit(): from galpy.actionAngle import actionAngleTorus from galpy.potential import MWPotential2014 from galpy.orbit import Orbit # Set up instance aAT= actionAngleTorus(pot=MWPotential2014,tol=10.**-5.) jr,jphi,jz= 0.05,1.1,0.025 # First calculate frequencies and the initial RvR RvRom= aAT.xvFreqs(jr,jphi,jz, numpy.array([0.]), numpy.array([1.]), numpy.array([2.])) om= RvRom[1:] # Angles along an orbit ts= numpy.linspace(0.,100.,1001) angler= ts*om[0] anglephi= 1.+ts*om[1] anglez= 2.+ts*om[2] # Calculate the orbit using actionAngleTorus RvR= aAT(jr,jphi,jz,angler,anglephi,anglez).T # Calculate the orbit using orbit integration orb= Orbit([RvRom[0][:,0],RvRom[0][:,1],RvRom[0][:,2], RvRom[0][:,3],RvRom[0][:,4],RvRom[0][:,5]]) orb.integrate(ts,MWPotential2014) # Compare tol= -3. assert numpy.all(numpy.fabs(orb.R(ts)-RvR[0]) < 10.**tol), \ 'Integrated orbit does not agree with torus orbit in R' assert numpy.all(numpy.fabs(orb.vR(ts)-RvR[1]) < 10.**tol), \ 'Integrated orbit does not agree with torus orbit in vR' assert numpy.all(numpy.fabs(orb.vT(ts)-RvR[2]) < 10.**tol), \ 'Integrated orbit does not agree with torus orbit in vT' assert numpy.all(numpy.fabs(orb.z(ts)-RvR[3]) < 10.**tol), \ 'Integrated orbit does not agree with torus orbit in z' assert numpy.all(numpy.fabs(orb.vz(ts)-RvR[4]) < 10.**tol), \ 'Integrated orbit does not agree with torus orbit in vz' assert numpy.all(numpy.fabs(orb.phi(ts)-RvR[5]) < 10.**tol), \ 'Integrated orbit does not agree with torus orbit in phi' return None
def test_actionAngleTorus_isochroneApprox_actions(): from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochroneApprox aAIA= actionAngleIsochroneApprox(pot=MWPotential2014,b=0.8) tol= -2.5 aAT= actionAngleTorus(pot=MWPotential2014,tol=tol) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.]) anglephi= numpy.array([numpy.pi]) anglez= numpy.array([numpy.pi/2.]) # Calculate position from aAT RvR= aAT(jr,jphi,jz,angler,anglephi,anglez).T # Calculate actions from aAIA ji= aAIA(*RvR) djr= numpy.fabs((ji[0]-jr)/jr) dlz= numpy.fabs((ji[1]-jphi)/jphi) djz= numpy.fabs((ji[2]-jz)/jz) assert djr < 10.**tol, 'actionAngleTorus and actionAngleIsochroneApprox applied to MWPotential2014 potential disagree for Jr at %f%%' % (djr*100.) assert dlz < 10.**tol, 'actionAngleTorus and actionAngleIsochroneApprox applied to MWPotential2014 potential disagree for Jr at %f%%' % (dlz*100.) assert djz < 10.**tol, 'actionAngleTorus and actionAngleMWPotential2014 applied to MWPotential2014 potential disagree for Jr at %f%%' % (djz*100.) return None
def test_actionAngleTorus_Isochrone_freqsAngles(): from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochrone ip= IsochronePotential(normalize=1.,b=1.2) aAI= actionAngleIsochrone(ip=ip) tol= -6. aAT= actionAngleTorus(pot=ip,tol=tol) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.1])+numpy.linspace(0.,numpy.pi,101) angler= angler % (2.*numpy.pi) anglephi= numpy.array([numpy.pi])+numpy.linspace(0.,numpy.pi,101) anglephi= anglephi % (2.*numpy.pi) anglez= numpy.array([numpy.pi/2.])+numpy.linspace(0.,numpy.pi,101) anglez= anglez % (2.*numpy.pi) # Calculate position from aAT RvRom= aAT.xvFreqs(jr,jphi,jz,angler,anglephi,anglez) # Calculate actions, frequencies, and angles from aAI ws= aAI.actionsFreqsAngles(*RvRom[0].T) dOr= numpy.fabs((ws[3]-RvRom[1])) dOp= numpy.fabs((ws[4]-RvRom[2])) dOz= numpy.fabs((ws[5]-RvRom[3])) dar= numpy.fabs((ws[6]-angler)) dap= numpy.fabs((ws[7]-anglephi)) daz= numpy.fabs((ws[8]-anglez)) dar[dar > numpy.pi]-= 2.*numpy.pi dar[dar < -numpy.pi]+= 2.*numpy.pi dap[dap > numpy.pi]-= 2.*numpy.pi dap[dap < -numpy.pi]+= 2.*numpy.pi daz[daz > numpy.pi]-= 2.*numpy.pi daz[daz < -numpy.pi]+= 2.*numpy.pi assert numpy.all(dOr < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Or at %f%%' % (numpy.nanmax(dOr)*100.) assert numpy.all(dOp < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Ophi at %f%%' % (numpy.nanmax(dOp)*100.) assert numpy.all(dOz < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Oz at %f%%' % (numpy.nanmax(dOz)*100.) assert numpy.all(dar < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for ar at %f' % (numpy.nanmax(dar)) assert numpy.all(dap < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for aphi at %f' % (numpy.nanmax(dap)) assert numpy.all(daz < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for az at %f' % (numpy.nanmax(daz)) return None
def test_actionAngleTorus_Isochrone_actions(): from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochrone ip= IsochronePotential(normalize=1.,b=1.2) aAI= actionAngleIsochrone(ip=ip) tol= -6. aAT= actionAngleTorus(pot=ip,tol=tol) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.]) anglephi= numpy.array([numpy.pi]) anglez= numpy.array([numpy.pi/2.]) # Calculate position from aAT RvR= aAT(jr,jphi,jz,angler,anglephi,anglez).T # Calculate actions from aAI ji= aAI(*RvR) djr= numpy.fabs((ji[0]-jr)/jr) dlz= numpy.fabs((ji[1]-jphi)/jphi) djz= numpy.fabs((ji[2]-jz)/jz) assert djr < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % (djr*100.) assert dlz < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % (dlz*100.) assert djz < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % (djz*100.) return None
def test_actionAngleTorus_Staeckel_actions(): from galpy.potential import KuzminKutuzovStaeckelPotential from galpy.actionAngle import actionAngleTorus, \ actionAngleStaeckel delta= 1.2 kp= KuzminKutuzovStaeckelPotential(normalize=1.,Delta=delta) aAS= actionAngleStaeckel(pot=kp,delta=delta,c=True) tol= -3. aAT= actionAngleTorus(pot=kp,tol=tol) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.]) anglephi= numpy.array([numpy.pi]) anglez= numpy.array([numpy.pi/2.]) # Calculate position from aAT RvR= aAT(jr,jphi,jz,angler,anglephi,anglez).T # Calculate actions from aAI ji= aAS(*RvR) djr= numpy.fabs((ji[0]-jr)/jr) dlz= numpy.fabs((ji[1]-jphi)/jphi) djz= numpy.fabs((ji[2]-jz)/jz) assert djr < 10.**tol, 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Jr at %f%%' % (djr*100.) assert dlz < 10.**tol, 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Jr at %f%%' % (dlz*100.) assert djz < 10.**tol, 'actionAngleTorus and actionAngleStaeckel applied to Staeckel potential disagree for Jr at %f%%' % (djz*100.) return None
def setup_sdf( pot: Sequence[Potential], prog: Orbit, sigv: float, td: float, ro: float = REFR0, vo: float = REFV0, multi: Optional[Any] = None, nTrackChunks: int = 8, isob: Optional[bool] = None, trailing_only: bool = False, verbose: bool = True, useTM: bool = True, logpot: bool = False, ): """Simple function to setup the stream model.""" if isob is None: if True or logpot: # FIXME, "if True" isob = 0.75 if isob is False: # FIXME, was "if False" # Determine good one ts = np.linspace(0.0, 15.0, 1001) # Hack! epot = copy.deepcopy(pot) epot[2]._b = 1.0 epot[2]._b2 = 1.0 epot[2]._isNonAxi = False epot[2]._aligned = True prog.integrate(ts, pot) estb = estimateBIsochrone( epot, 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] if verbose: print(pot[2]._c, isob, estb) if not logpot and np.fabs(pot[2]._b - 1.0) > 0.05: aAI = actionAngleIsochroneApprox(pot=pot, b=isob, tintJ=1000.0, ntintJ=30000) else: ts = np.linspace(0.0, 100.0, 10000) aAI = actionAngleIsochroneApprox( pot=pot, b=isob, tintJ=100.0, ntintJ=10000, dt=ts[1] - ts[0] ) if useTM: aAT = actionAngleTorus(pot=pot, tol=0.001, dJ=0.0001) else: aAT = False try: sdf = streamdf( sigv / vo, progenitor=prog, pot=pot, aA=aAI, useTM=aAT, approxConstTrackFreq=True, leading=True, nTrackChunks=nTrackChunks, tdisrupt=td / bovy_conversion.time_in_Gyr(vo, ro), ro=ro, vo=vo, R0=ro, vsun=[-11.1, vo + 24.0, 7.25], custom_transform=_TKOP, multi=multi, nospreadsetup=True, ) except np.linalg.LinAlgError: sdf = streamdf( sigv / vo, progenitor=prog, pot=pot, aA=aAI, useTM=aAT, approxConstTrackFreq=True, leading=True, nTrackChunks=nTrackChunks, nTrackIterations=0, tdisrupt=td / bovy_conversion.time_in_Gyr(vo, ro), ro=ro, vo=vo, R0=ro, vsun=[-11.1, vo + 24.0, 7.25], custom_transform=_TKOP, multi=multi, ) return sdf
def setup_sdf( pot: potential.Potential, prog: Orbit, sigv: float, td: float, ro: float = REFR0, vo: float = REFV0, multi: Optional[bool] = None, nTrackChunks: float = 8, isob=None, trailing_only: bool = False, verbose: bool = True, useTM: bool = True, ) -> Tuple[Optional[streamdf], Optional[streamdf]]: """Setup Stream Distribution Function. Parameters ---------- pot : Potential prog : Orbit Progenitor sigv : float td : float ro : float vo : float multi default None nTrackChunks: float default 8 isob default None trailing_only: bool default False verbose: bool default True useTM: bool default True Returns ------- sdf_trailing, sdf_leading: streamdf or None """ if isob is None: # Determine good one ts = np.linspace(0.0, 150.0, 1001) # Hack! epot = copy.deepcopy(pot) epot[2]._b = 1.0 epot[2]._b2 = 1.0 epot[2]._isNonAxi = False epot[2]._aligned = True prog.integrate(ts, pot) estb = estimateBIsochrone( epot, 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] if verbose: print(pot[2]._c, isob) if np.fabs(pot[2]._b - 1.0) > 0.05: aAI = actionAngleIsochroneApprox(pot=pot, b=isob, tintJ=1000.0, ntintJ=30000) else: aAI = actionAngleIsochroneApprox(pot=pot, b=isob) if useTM: aAT = actionAngleTorus(pot=pot, tol=0.001, dJ=0.0001) else: aAT = False trailing_kwargs = dict( progenitor=prog, pot=pot, aA=aAI, useTM=aAT, approxConstTrackFreq=True, leading=False, nTrackChunks=nTrackChunks, tdisrupt=td / bovy_conversion.time_in_Gyr(vo, ro), ro=ro, vo=vo, R0=ro, vsun=[-11.1, vo + 24.0, 7.25], custom_transform=_TPAL5, multi=multi, ) try: sdf_trailing = streamdf(sigv / vo, **trailing_kwargs) except np.linalg.LinAlgError: sdf_trailing = streamdf(sigv / vo, nTrackIterations=0, **trailing_kwargs) if trailing_only: sdf_leading = None else: leading_kwargs = dict( progenitor=prog, pot=pot, aA=aAI, useTM=aAT, approxConstTrackFreq=True, leading=True, nTrackChunks=nTrackChunks, tdisrupt=td / bovy_conversion.time_in_Gyr(vo, ro), ro=ro, vo=vo, R0=ro, vsun=[-11.1, vo + 24.0, 7.25], custom_transform=_TPAL5, multi=multi, ) try: sdf_leading = streamdf(sigv / vo, **leading_kwargs) except np.linalg.LinAlgError: sdf_leading = streamdf(sigv / vo, nTrackIterations=0, **leading_kwargs) return sdf_trailing, sdf_leading
- https://galpy.readthedocs.io/en/v1.4.0/actionAngle.html#actionanglestaeckel - https://galpy.readthedocs.io/en/v1.4.0/orbit.html#fastchar - https://galpy.readthedocs.io/en/v1.4.0/actionAngle.html#accessing-action-angle-coordinates-for-orbit-instances """ import numpy as np from galpy.orbit import Orbit from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleTorus from galpy.potential import MWPotential2014 import sys sys.path.insert(0, '..') import chronostar.traceorbit as torb xyzuvw_start = [0., 0., 25., 0., 0., 0.] print('xyzuvw start: {}'.format(xyzuvw_start)) galpy_coords = torb.convert_cart2galpycoords(xyzuvw_start) print('galpy start: {}'.format(galpy_coords)) aAT = actionAngleTorus(pot=MWPotential2014) o = Orbit(vxvv=galpy_coords, ro=8., vo=220.) o.e(analytic=True, type='staeckel', pot=MWPotential2014) aAS = actionAngleStaeckel(pot=mp, delta=0.4) # Om= aAT.Freqs(jr,lz,jz)