def __init__(self, *args, **kwargs): """ NAME: __init__ PURPOSE: initialize an actionAngleIsochrone object INPUT: Either: b= scale parameter of the isochrone parameter (can be Quantity) ip= instance of a IsochronePotential ro= distance from vantage point to GC (kpc; can be Quantity) vo= circular velocity at ro (km/s; can be Quantity) OUTPUT: instance HISTORY: 2013-09-08 - Written - Bovy (IAS) """ actionAngle.__init__(self, ro=kwargs.get('ro', None), vo=kwargs.get('vo', None)) if not 'b' in kwargs and not 'ip' in kwargs: #pragma: no cover raise IOError("Must specify b= for actionAngleIsochrone") if 'ip' in kwargs: ip = kwargs['ip'] if not isinstance(ip, IsochronePotential): #pragma: no cover raise IOError( "'Provided ip= does not appear to be an instance of an IsochronePotential" ) # Check the units self._pot = ip self._check_consistent_units() self.b = ip.b self.amp = ip._amp else: self.b = kwargs['b'] if _APY_LOADED and isinstance(self.b, units.Quantity): self.b = self.b.to(units.kpc).value / self._ro rb = nu.sqrt(self.b**2. + 1.) self.amp = (self.b + rb)**2. * rb self._c = False ext_loaded = False if ext_loaded and (('c' in kwargs and kwargs['c']) or not 'c' in kwargs): #pragma: no cover self._c = True else: self._c = False if not self._c: self._ip = IsochronePotential(amp=self.amp, b=self.b) #Define _pot, because some functions that use actionAngle instances need this self._pot = IsochronePotential(amp=self.amp, b=self.b) # Check the units self._check_consistent_units() return None
def test_setup_diffsetups(): #Test the different ways to setup a qdf object #Test errors try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., aA=aAS,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/o pot set did not raise exception") try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/o aA set did not raise exception") from galpy.potential import LogarithmicHaloPotential try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=LogarithmicHaloPotential(), aA=aAS,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/ aA potential different from pot= did not raise exception") #qdf setup with an actionAngleIsochrone instance (issue #190) from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleIsochrone ip= IsochronePotential(normalize=1.,b=2.) try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=ip, aA=actionAngleIsochrone(ip=ip),cutcounter=True) except: raise raise AssertionError('quasi-isothermaldf setup w/ an actionAngleIsochrone instance failed') #qdf setup with an actionAngleIsochrone instance should raise error if potentials are not the same ip= IsochronePotential(normalize=1.,b=2.) try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=ip, aA=actionAngleIsochrone(ip=IsochronePotential(normalize=1.,b=2.5)), cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/ aA potential different from pot= did not raise exception") #precompute qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True, _precomputerg=True) qdfnpc= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True, _precomputerg=False) assert numpy.fabs(qdf.rg(1.1)-qdfnpc.rg(1.1)) < 10.**-5., 'rg calculated from qdf instance w/ precomputerg set is not the same as that computed from an instance w/o it set'
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_adinvariance(): from galpy.potential import IsochronePotential from galpy.orbit import Orbit from galpy.actionAngle import actionAngleIsochrone # Initialize two different IsochronePotentials ip1= IsochronePotential(normalize=1.,b=1.) ip2= IsochronePotential(normalize=0.5,b=1.) # Use TimeInterpPotential to interpolate smoothly tip= TimeInterpPotential(ip1,ip2,dt=100.,tform=50.) # Integrate: 1) Orbit in the first isochrone potential o1= Orbit([1.,0.1,1.1,0.0,0.1,0.]) ts= numpy.linspace(0.,50.,1001) o1.integrate(ts,tip) o1.plot(d1='x',d2='y',xrange=[-1.6,1.6],yrange=[-1.6,1.6], color='b') # 2) Orbit in the transition o2= o1(ts[-1]) # Last time step => initial time step ts2= numpy.linspace(50.,150.,1001) o2.integrate(ts2,tip) o2.plot(d1='x',d2='y',overplot=True,color='g') # 3) Orbit in the second isochrone potential o3= o2(ts2[-1]) ts3= numpy.linspace(150.,200.,1001) o3.integrate(ts3,tip) o3.plot(d1='x',d2='y',overplot=True,color='r') # Now we calculate energy, maximum height, and mean radius print(o1.E(pot=ip1), (o1.rperi()+o1.rap())/2, o1.zmax()) assert numpy.fabs(o1.E(pot=ip1)+2.79921356237) < 10.**-4., 'Energy in the adiabatic invariance test is different' assert numpy.fabs((o1.rperi()+o1.rap())/2-1.07854158141) < 10.**-4., 'mean radius in the adiabatic invariance test is different' assert numpy.fabs(o1.zmax()-0.106331362938) < 10.**-4., 'zmax in the adiabatic invariance test is different' print(o3.E(pot=ip2), (o3.rperi()+o3.rap())/2, o3.zmax()) assert numpy.fabs(o3.E(pot=ip2)+1.19677002624) < 10.**-4., 'Energy in the adiabatic invariance test is different' assert numpy.fabs((o3.rperi()+o3.rap())/2-1.39962036137) < 10.**-4., 'mean radius in the adiabatic invariance test is different' assert numpy.fabs(o3.zmax()-0.138364269321) < 10.**-4., 'zmax in the adiabatic invariance test is different' # The orbit has clearly moved to larger radii, # the actions are however conserved from beginning to end aAI1= actionAngleIsochrone(ip=ip1); print(aAI1(o1)) js= aAI1(o1) assert numpy.fabs(js[0]-numpy.array([ 0.00773779])) < 10.**-4., 'action in the adiabatic invariance test is different' assert numpy.fabs(js[1]-numpy.array([ 1.1])) < 10.**-4., 'action in the adiabatic invariance test is different' assert numpy.fabs(js[2]-numpy.array([ 0.0045361])) < 10.**-4., 'action in the adiabatic invariance test is different' aAI2= actionAngleIsochrone(ip=ip2); print(aAI2(o3)) js= aAI2(o3) assert numpy.fabs(js[0]-numpy.array([ 0.00773812])) < 10.**-4., 'action in the adiabatic invariance test is different' assert numpy.fabs(js[1]-numpy.array([ 1.1])) < 10.**-4., 'action in the adiabatic invariance test is different' assert numpy.fabs(js[2]-numpy.array([ 0.0045361])) < 10.**-4., 'action in the adiabatic invariance test is different' 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 __init__(self,*args,**kwargs): """ NAME: __init__ PURPOSE: initialize an actionAngleIsochrone object INPUT: Either: b= scale parameter of the isochrone parameter ip= instance of a IsochronePotential OUTPUT: HISTORY: 2013-09-08 - Written - Bovy (IAS) """ if not 'b' in kwargs and not 'ip' in kwargs: #pragma: no cover raise IOError("Must specify b= for actionAngleIsochrone") if 'ip' in kwargs: ip= kwargs['ip'] if not isinstance(ip,IsochronePotential): #pragma: no cover raise IOError("'Provided ip= does not appear to be an instance of an IsochronePotential") self.b= ip.b self.amp= ip._amp else: self.b= kwargs['b'] rb= nu.sqrt(self.b**2.+1.) self.amp= (self.b+rb)**2.*rb self._c= False ext_loaded= False if ext_loaded and (('c' in kwargs and kwargs['c']) or not 'c' in kwargs): #pragma: no cover self._c= True else: self._c= False if not self._c: self._ip= IsochronePotential(amp=self.amp,b=self.b) #Define _pot, because some functions that use actionAngle instances need this self._pot= IsochronePotential(amp=self.amp,b=self.b) return None
def __init__(self,*args,**kwargs): """ NAME: __init__ PURPOSE: initialize an actionAngleIsochroneApprox object INPUT: Either: b= scale parameter of the isochrone parameter ip= instance of a IsochronePotential aAI= instance of an actionAngleIsochrone pot= potential to calculate action-angle variables for tintJ= (default: 100) time to integrate orbits for to estimate actions ntintJ= (default: 10000) number of time-integration points integrate_method= (default: 'dopr54_c') integration method to use OUTPUT: HISTORY: 2013-09-10 - Written - Bovy (IAS) """ if not 'pot' in kwargs: #pragma: no cover raise IOError("Must specify pot= for actionAngleIsochroneApprox") self._pot= kwargs['pot'] if self._pot == MWPotential: warnings.warn("Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy", galpyWarning) if not 'b' in kwargs and not 'ip' in kwargs \ and not 'aAI' in kwargs: #pragma: no cover raise IOError("Must specify b=, ip=, or aAI= for actionAngleIsochroneApprox") if 'aAI' in kwargs: if not isinstance(kwargs['aAI'],actionAngleIsochrone): #pragma: no cover raise IOError("'Provided aAI= does not appear to be an instance of an actionAngleIsochrone") self._aAI= kwargs['aAI'] elif 'ip' in kwargs: ip= kwargs['ip'] if not isinstance(ip,IsochronePotential): #pragma: no cover raise IOError("'Provided ip= does not appear to be an instance of an IsochronePotential") self._aAI= actionAngleIsochrone(ip=ip) else: self._aAI= actionAngleIsochrone(ip=IsochronePotential(b=kwargs['b'], normalize=1.)) self._tintJ= kwargs.get('tintJ',100.) self._ntintJ= kwargs.get('ntintJ',10000) self._tsJ= nu.linspace(0.,self._tintJ,self._ntintJ) self._integrate_method= kwargs.get('integrate_method','dopr54_c') self._c= False ext_loaded= False if ext_loaded and (('c' in kwargs and kwargs['c']) or not 'c' in kwargs): #pragma: no cover self._c= True else: self._c= False return None
def __init__(self,*args,**kwargs): """ NAME: __init__ PURPOSE: initialize an actionAngleIsochroneApprox object INPUT: Either: b= scale parameter of the isochrone parameter (can be Quantity) ip= instance of a IsochronePotential aAI= instance of an actionAngleIsochrone pot= potential to calculate action-angle variables for tintJ= (default: 100) time to integrate orbits for to estimate actions (can be Quantity) ntintJ= (default: 10000) number of time-integration points integrate_method= (default: 'dopr54_c') integration method to use dt= (None) orbit.integrate dt keyword (for fixed stepsize integration) maxn= (default: 3) Default value for all methods when using a grid in vec(n) up to this n (zero-based) ro= distance from vantage point to GC (kpc; can be Quantity) vo= circular velocity at ro (km/s; can be Quantity) OUTPUT: instance HISTORY: 2013-09-10 - Written - Bovy (IAS) """ actionAngle.__init__(self, ro=kwargs.get('ro',None),vo=kwargs.get('vo',None)) if not 'pot' in kwargs: #pragma: no cover raise IOError("Must specify pot= for actionAngleIsochroneApprox") self._pot= flatten_potential(kwargs['pot']) if self._pot == MWPotential: warnings.warn("Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy", galpyWarning) if not 'b' in kwargs and not 'ip' in kwargs \ and not 'aAI' in kwargs: #pragma: no cover raise IOError("Must specify b=, ip=, or aAI= for actionAngleIsochroneApprox") if 'aAI' in kwargs: if not isinstance(kwargs['aAI'],actionAngleIsochrone): #pragma: no cover raise IOError("'Provided aAI= does not appear to be an instance of an actionAngleIsochrone") self._aAI= kwargs['aAI'] elif 'ip' in kwargs: ip= kwargs['ip'] if not isinstance(ip,IsochronePotential): #pragma: no cover raise IOError("'Provided ip= does not appear to be an instance of an IsochronePotential") self._aAI= actionAngleIsochrone(ip=ip) else: if _APY_LOADED and isinstance(kwargs['b'],units.Quantity): b= kwargs['b'].to(units.kpc).value/self._ro else: b= kwargs['b'] self._aAI= actionAngleIsochrone(ip=IsochronePotential(b=b, normalize=1.)) self._tintJ= kwargs.get('tintJ',100.) if _APY_LOADED and isinstance(self._tintJ,units.Quantity): self._tintJ= self._tintJ.to(units.Gyr).value\ /time_in_Gyr(self._vo,self._ro) self._ntintJ= kwargs.get('ntintJ',10000) self._integrate_dt= kwargs.get('dt',None) self._tsJ= nu.linspace(0.,self._tintJ,self._ntintJ) self._integrate_method= kwargs.get('integrate_method','dopr54_c') self._maxn= kwargs.get('maxn',3) self._c= False ext_loaded= False if ext_loaded and (('c' in kwargs and kwargs['c']) or not 'c' in kwargs): #pragma: no cover self._c= True else: self._c= False # Check the units self._check_consistent_units() return None
def create_frames(basefilename): """Create Frames. Parameters ---------- basefilename : str Returns ------- None """ pot = IsochronePotential(normalize=1.0, b=1.2) aAT = actionAngleIsochrone(ip=pot) bmock = 0.8 aAF = actionAngleIsochrone(b=bmock) o = Orbit([1.0, 0.3, 0.9, 0.2, 1.0, 0.1]) tfac, skip = 10, 1 ndesired = 30 * 25 times = numpy.linspace(0.0, 7.0, tfac * ndesired) * u.Gyr # Subsample otimesIndices = (numpy.arange(len(times)) / float(len(times) - 1))**10 * (len(times) - 2) otimesIndices = numpy.unique(numpy.floor(otimesIndices).astype("int")) if len(otimesIndices) > ndesired: sfac = int(numpy.floor(len(otimesIndices) / float(ndesired))) otimesIndices = otimesIndices[::sfac] otimes = times[otimesIndices] o.integrate(times, pot) # Compute all actions in the wrong potential acfs = aAF.actionsFreqsAngles( o.R(times), o.vR(times), o.vT(times), o.z(times), o.vz(times), o.phi(times), ) js = (acfs[0], acfs[1], acfs[2]) danglerI = ((numpy.roll(acfs[6], -1) - acfs[6]) % (2.0 * numpy.pi))[:-1] jrC = numpy.cumsum(acfs[0][:-1] * danglerI) / numpy.cumsum(danglerI) # And also the actions in the true potential jsT = aAT(o.R(times), o.vR(times), o.vT(times), o.z(times), o.vz(times)) jrT = numpy.median(jsT[0]) * _RO * _VO # --------------------------------------------------------------- # Plotting # Setup gridspec gs = gridspec.GridSpec(1, 3, wspace=0.325, bottom=0.2, left=0.075) # For each time step, plot: orbit, Jr, <Jr> for ii in tqdm(range(len(otimes))): bovy_plot.bovy_print( fig_width=11.2, fig_height=4.0, axes_labelsize=17.0, text_fontsize=12.0, xtick_labelsize=13.0, ytick_labelsize=13.0, ) pyplot.figure() pyplot.subplot(gs[0]) minIndx = otimesIndices[ii] - 100 if minIndx < 0: minIndx = 0 bovy_plot.bovy_plot( [o.x(otimes[ii:ii + 1]) * _RO], [o.z(otimes[ii:ii + 1]) * _RO], "o", ms=15.0, gcf=True, xrange=[-19.0, 19.0], yrange=[-19.0, 19.0], xlabel=r"$X\,(\mathrm{kpc})$", ylabel=r"$z\,(\mathrm{kpc})$", ) if ii > 0: bovy_plot.bovy_plot( o.x(times[minIndx:otimesIndices[ii]:skip]) * _RO, o.z(times[minIndx:otimesIndices[ii]:skip]) * _RO, "-", overplot=True, ) pyplot.subplot(gs[1]) bovy_plot.bovy_plot( [times[otimesIndices[ii]].value], [js[0][otimesIndices[ii]] * _RO * _VO], "o", ms=15.0, gcf=True, xrange=[0.0, 1.0 + times[otimesIndices[ii]].value], yrange=[0.0, 349.0], xlabel=r"$\mathrm{time}\,(\mathrm{Gyr})$", ylabel=r"$J_R\,(\mathrm{kpc\,km\,s}^{-1})$", ) if ii > 0: bovy_plot.bovy_plot( times[:otimesIndices[ii]:skip].value, js[0][:otimesIndices[ii]:skip] * _RO * _VO, "-", overplot=True, ) pyplot.axhline(jrT, ls="--", color="k") pyplot.subplot(gs[2]) bovy_plot.bovy_plot( [otimes[ii].value], [jrC[otimesIndices[ii]] * _RO * _VO], "o", ms=15.0, gcf=True, xrange=[0.0, 1.0 + times[otimesIndices[ii]].value], yrange=[ (otimes[ii] / times[-1])**0.3 * (jrT - 3), 349.0 + (otimes[ii] / times[-1])**0.3 * (jrT + 3 - 349.0), ], xlabel=r"$\mathrm{time}\,(\mathrm{Gyr})$", ylabel=r"$J_R\,(\mathrm{kpc\,km\,s}^{-1})$", ) if ii > 0: bovy_plot.bovy_plot( times[:otimesIndices[ii]:skip].value, jrC[:otimesIndices[ii]:skip] * _RO * _VO, "-", overplot=True, ) pyplot.axhline(jrT, ls="--", color="k") bovy_plot.bovy_end_print(basefilename + "_%05d.png" % ii) return None