def Jz(self,*args,**kwargs): """ NAME: Jz PURPOSE: evaluate the action jz INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords OUTPUT: jz HISTORY: 2012-07-30 - Written - Bovy (IAS@MPIA) """ meta= actionAngle(*args) Phi= galpy.potential.evaluatePotentials(meta._R,meta._z,self._pot) Phio= galpy.potential.evaluatePotentials(meta._R,0.,self._pot) Ez= Phi-Phio+meta._vz**2./2. #Bigger than Ezzmax? thisEzZmax= numpy.exp(self._EzZmaxsInterp(meta._R)) if meta._R > self._Rmax or meta._R < self._Rmin or (Ez != 0. and numpy.log(Ez) > thisEzZmax): #Outside of the grid if _PRINTOUTSIDEGRID: #pragma: no cover print "Outside of grid in Ez" jz= self._aA(meta._R,0.,1.,#these two r dummies 0.,math.sqrt(2.*Ez), _justjz=True, **kwargs)[2] else: jz= (self._jzInterp(meta._R,Ez/thisEzZmax)\ *(numpy.exp(self._jzEzmaxInterp(meta._R))-10.**-5.))[0][0] return jz
def calczmax(self,*args,**kwargs): """ NAME: calczmax PURPOSE: calculate the maximum height INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well OUTPUT: zmax HISTORY: 2012-06-01 - Written - Bovy (IAS) """ #Set up the actionAngleAxi object meta= actionAngle(*args) if isinstance(self._pot,list): thispot= [p.toPlanar() for p in self._pot] else: thispot= self._pot.toPlanar() if isinstance(self._pot,list): thisverticalpot= [p.toVertical(meta._R) for p in self._pot] else: thisverticalpot= self._pot.toVertical(meta._R) aAAxi= actionAngleAxi(*args,pot=thispot, verticalPot=thisverticalpot, gamma=self._gamma) return aAAxi.calczmax(**kwargs)
def actionsFreqs(self,*args,**kwargs): """ NAME: actionsFreqs PURPOSE: evaluate the actions and frequencies (jr,lz,jz,Omegar,Omegaphi,Omegaz) INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords OUTPUT: (jr,lz,jz,Omegar,Omegaphi,Omegaz) HISTORY: 2013-09-08 - Written - Bovy (IAS) """ if len(args) == 5: #R,vR.vT, z, vz R,vR,vT, z, vz= args elif len(args) == 6: #R,vR.vT, z, vz, phi R,vR,vT, z, vz, phi= args else: meta= actionAngle(*args) R= meta._R vR= meta._vR vT= meta._vT z= meta._z vz= meta._vz if isinstance(R,float): R= nu.array([R]) vR= nu.array([vR]) vT= nu.array([vT]) z= nu.array([z]) vz= nu.array([vz]) if self._c: #pragma: no cover pass else: Lz= R*vT Lx= -z*vT Ly= z*vR-R*vz L2= Lx*Lx+Ly*Ly+Lz*Lz E= self._ip(R,z)+vR**2./2.+vT**2./2.+vz**2./2. L= nu.sqrt(L2) #Actions Jphi= Lz Jz= L-nu.fabs(Lz) Jr= self.amp/nu.sqrt(-2.*E)\ -0.5*(L+nu.sqrt((L2+4.*self.amp*self.b))) #Frequencies Omegar= (-2.*E)**1.5/self.amp Omegaz= 0.5*(1.+L/nu.sqrt(L2+4.*self.amp*self.b))*Omegar Omegaphi= copy.copy(Omegaz) indx= Lz < 0. Omegaphi[indx]*= -1. return (Jr,Jphi,Jz,Omegar,Omegaphi,Omegaz)
def Jz(self, *args, **kwargs): """ NAME: Jz PURPOSE: evaluate the action jz INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords OUTPUT: jz HISTORY: 2012-07-30 - Written - Bovy (IAS@MPIA) """ meta = actionAngle(*args) Phi = galpy.potential.evaluatePotentials(meta._R, meta._z, self._pot) Phio = galpy.potential.evaluatePotentials(meta._R, 0., self._pot) Ez = Phi - Phio + meta._vz**2. / 2. #Bigger than Ezzmax? thisEzZmax = numpy.exp(self._EzZmaxsInterp(meta._R)) if meta._R > self._Rmax or meta._R < self._Rmin or ( Ez != 0. and numpy.log(Ez) > thisEzZmax): #Outside of the grid if _PRINTOUTSIDEGRID: #pragma: no cover print("Outside of grid in Ez") jz = self._aA( meta._R, 0., 1., #these two r dummies 0., math.sqrt(2. * Ez), _justjz=True, **kwargs)[2] else: jz= (self._jzInterp(meta._R,Ez/thisEzZmax)\ *(numpy.exp(self._jzEzmaxInterp(meta._R))-10.**-5.))[0][0] return jz
def __call__(self,*args,**kwargs): """ NAME: __call__ PURPOSE: evaluate the actions (jr,lz,jz) INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords OUTPUT: (jr,lz,jz) HISTORY: 2012-07-27 - Written - Bovy (IAS@MPIA) NOTE: For a Miyamoto-Nagai potential, this seems accurate to 0.1% and takes ~0.13 ms For a MWPotential, this takes ~ 0.17 ms """ if len(args) == 5: #R,vR.vT, z, vz R,vR,vT, z, vz= args elif len(args) == 6: #R,vR.vT, z, vz, phi R,vR,vT, z, vz, phi= args else: meta= actionAngle(*args) R= meta._R vR= meta._vR vT= meta._vT z= meta._z vz= meta._vz #First work on the vertical action Phi= galpy.potential.evaluatePotentials(R,z,self._pot) try: Phio= galpy.potential.evaluatePotentials(R,numpy.zeros(len(R)),self._pot) except TypeError: Phio= galpy.potential.evaluatePotentials(R,0.,self._pot) Ez= Phi-Phio+vz**2./2. #Bigger than Ezzmax? thisEzZmax= numpy.exp(self._EzZmaxsInterp(R)) if isinstance(R,numpy.ndarray): indx= (R > self._Rmax) indx+= (R < self._Rmin) indx+= (Ez != 0.)*(numpy.log(Ez) > thisEzZmax) indxc= True-indx jz= numpy.empty(R.shape) if numpy.sum(indxc) > 0: jz[indxc]= (self._jzInterp.ev(R[indxc],Ez[indxc]/thisEzZmax[indxc])\ *(numpy.exp(self._jzEzmaxInterp(R[indxc]))-10.**-5.)) if numpy.sum(indx) > 0: jz[indx]= self._aA(R[indx], numpy.zeros(numpy.sum(indx)), numpy.ones(numpy.sum(indx)),#these two r dummies numpy.zeros(numpy.sum(indx)), numpy.sqrt(2.*Ez[indx]), _justjz=True, **kwargs)[2] else: if R > self._Rmax or R < self._Rmin or (Ez != 0 and numpy.log(Ez) > thisEzZmax): #Outside of the grid if _PRINTOUTSIDEGRID: #pragma: no cover print "Outside of grid in Ez", R > self._Rmax , R < self._Rmin , (Ez != 0 and numpy.log(Ez) > thisEzZmax) jz= self._aA(R,0.,1.,#these two r dummies 0.,math.sqrt(2.*Ez), _justjz=True, **kwargs)[2] else: jz= (self._jzInterp(R,Ez/thisEzZmax)\ *(numpy.exp(self._jzEzmaxInterp(R))-10.**-5.))[0][0] #Radial action ERLz= numpy.fabs(R*vT)+self._gamma*jz ER= Phio+vR**2./2.+ERLz**2./2./R**2. thisRL= self._RLInterp(ERLz) thisERRL= -numpy.exp(self._ERRLInterp(ERLz))+self._ERRLmax thisERRa= -numpy.exp(self._ERRaInterp(ERLz))+self._ERRamax if isinstance(R,numpy.ndarray): indx= ((ER-thisERRa)/(thisERRL-thisERRa) > 1.)\ *(((ER-thisERRa)/(thisERRL-thisERRa)-1.) < 10.**-2.) ER[indx]= thisERRL[indx] indx= ((ER-thisERRa)/(thisERRL-thisERRa) < 0.)\ *((ER-thisERRa)/(thisERRL-thisERRa) > -10.**-2.) ER[indx]= thisERRa[indx] indx= (ERLz < self._Lzmin) indx+= (ERLz > self._Lzmax) indx+= ((ER-thisERRa)/(thisERRL-thisERRa) > 1.) indx+= ((ER-thisERRa)/(thisERRL-thisERRa) < 0.) indxc= True-indx jr= numpy.empty(R.shape) if numpy.sum(indxc) > 0: jr[indxc]= (self._jrInterp.ev(ERLz[indxc], (ER[indxc]-thisERRa[indxc])/(thisERRL[indxc]-thisERRa[indxc]))\ *(numpy.exp(self._jrERRaInterp(ERLz[indxc]))-10.**-5.)) if numpy.sum(indx) > 0: jr[indx]= self._aA(thisRL[indx], numpy.sqrt(2.*(ER[indx]-galpy.potential.evaluatePotentials(thisRL[indx],0.,self._pot))-ERLz[indx]**2./thisRL[indx]**2.), ERLz[indx]/thisRL[indx], numpy.zeros(len(thisRL)), numpy.zeros(len(thisRL)), _justjr=True, **kwargs)[0] else: if (ER-thisERRa)/(thisERRL-thisERRa) > 1. \ and ((ER-thisERRa)/(thisERRL-thisERRa)-1.) < 10.**-2.: ER= thisERRL elif (ER-thisERRa)/(thisERRL-thisERRa) < 0. \ and (ER-thisERRa)/(thisERRL-thisERRa) > -10.**-2.: ER= thisERRa #Outside of grid? if ERLz < self._Lzmin or ERLz > self._Lzmax \ or (ER-thisERRa)/(thisERRL-thisERRa) > 1. \ or (ER-thisERRa)/(thisERRL-thisERRa) < 0.: if _PRINTOUTSIDEGRID: #pragma: no cover print "Outside of grid in ER/Lz", ERLz < self._Lzmin , ERLz > self._Lzmax \ , (ER-thisERRa)/(thisERRL-thisERRa) > 1. \ , (ER-thisERRa)/(thisERRL-thisERRa) < 0., ER, thisERRL, thisERRa, (ER-thisERRa)/(thisERRL-thisERRa) jr= self._aA(thisRL[0], numpy.sqrt(2.*(ER-galpy.potential.evaluatePotentials(thisRL,0.,self._pot))-ERLz**2./thisRL**2.)[0], (ERLz/thisRL)[0], 0.,0., _justjr=True, **kwargs)[0] else: jr= (self._jrInterp(ERLz, (ER-thisERRa)/(thisERRL-thisERRa))\ *(numpy.exp(self._jrERRaInterp(ERLz))-10.**-5.))[0][0] return (jr,R*vT,jz)
def __call__(self, *args, **kwargs): """ NAME: __call__ PURPOSE: evaluate the actions (jr,lz,jz) INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords OUTPUT: (jr,lz,jz) HISTORY: 2012-07-27 - Written - Bovy (IAS@MPIA) NOTE: For a Miyamoto-Nagai potential, this seems accurate to 0.1% and takes ~0.13 ms For a MWPotential, this takes ~ 0.17 ms """ if len(args) == 5: #R,vR.vT, z, vz R, vR, vT, z, vz = args elif len(args) == 6: #R,vR.vT, z, vz, phi R, vR, vT, z, vz, phi = args else: meta = actionAngle(*args) R = meta._R vR = meta._vR vT = meta._vT z = meta._z vz = meta._vz #First work on the vertical action Phi = galpy.potential.evaluatePotentials(R, z, self._pot) try: Phio = galpy.potential.evaluatePotentials(R, numpy.zeros(len(R)), self._pot) except TypeError: Phio = galpy.potential.evaluatePotentials(R, 0., self._pot) Ez = Phi - Phio + vz**2. / 2. #Bigger than Ezzmax? thisEzZmax = numpy.exp(self._EzZmaxsInterp(R)) if isinstance(R, numpy.ndarray): indx = (R > self._Rmax) indx += (R < self._Rmin) indx += (Ez != 0.) * (numpy.log(Ez) > thisEzZmax) indxc = True - indx jz = numpy.empty(R.shape) if numpy.sum(indxc) > 0: jz[indxc]= (self._jzInterp.ev(R[indxc],Ez[indxc]/thisEzZmax[indxc])\ *(numpy.exp(self._jzEzmaxInterp(R[indxc]))-10.**-5.)) if numpy.sum(indx) > 0: jz[indx] = self._aA( R[indx], numpy.zeros(numpy.sum(indx)), numpy.ones(numpy.sum(indx)), #these two r dummies numpy.zeros(numpy.sum(indx)), numpy.sqrt(2. * Ez[indx]), _justjz=True, **kwargs)[2] else: if R > self._Rmax or R < self._Rmin or ( Ez != 0 and numpy.log(Ez) > thisEzZmax): #Outside of the grid if _PRINTOUTSIDEGRID: #pragma: no cover print("Outside of grid in Ez", R > self._Rmax, R < self._Rmin, (Ez != 0 and numpy.log(Ez) > thisEzZmax)) jz = self._aA( R, 0., 1., #these two r dummies 0., math.sqrt(2. * Ez), _justjz=True, **kwargs)[2] else: jz= (self._jzInterp(R,Ez/thisEzZmax)\ *(numpy.exp(self._jzEzmaxInterp(R))-10.**-5.))[0][0] #Radial action ERLz = numpy.fabs(R * vT) + self._gamma * jz ER = Phio + vR**2. / 2. + ERLz**2. / 2. / R**2. thisRL = self._RLInterp(ERLz) thisERRL = -numpy.exp(self._ERRLInterp(ERLz)) + self._ERRLmax thisERRa = -numpy.exp(self._ERRaInterp(ERLz)) + self._ERRamax if isinstance(R, numpy.ndarray): indx= ((ER-thisERRa)/(thisERRL-thisERRa) > 1.)\ *(((ER-thisERRa)/(thisERRL-thisERRa)-1.) < 10.**-2.) ER[indx] = thisERRL[indx] indx= ((ER-thisERRa)/(thisERRL-thisERRa) < 0.)\ *((ER-thisERRa)/(thisERRL-thisERRa) > -10.**-2.) ER[indx] = thisERRa[indx] indx = (ERLz < self._Lzmin) indx += (ERLz > self._Lzmax) indx += ((ER - thisERRa) / (thisERRL - thisERRa) > 1.) indx += ((ER - thisERRa) / (thisERRL - thisERRa) < 0.) indxc = True - indx jr = numpy.empty(R.shape) if numpy.sum(indxc) > 0: jr[indxc]= (self._jrInterp.ev(ERLz[indxc], (ER[indxc]-thisERRa[indxc])/(thisERRL[indxc]-thisERRa[indxc]))\ *(numpy.exp(self._jrERRaInterp(ERLz[indxc]))-10.**-5.)) if numpy.sum(indx) > 0: jr[indx] = self._aA( thisRL[indx], numpy.sqrt(2. * (ER[indx] - galpy.potential.evaluatePotentials( thisRL[indx], 0., self._pot)) - ERLz[indx]**2. / thisRL[indx]**2.), ERLz[indx] / thisRL[indx], numpy.zeros(len(thisRL)), numpy.zeros(len(thisRL)), _justjr=True, **kwargs)[0] else: if (ER-thisERRa)/(thisERRL-thisERRa) > 1. \ and ((ER-thisERRa)/(thisERRL-thisERRa)-1.) < 10.**-2.: ER = thisERRL elif (ER-thisERRa)/(thisERRL-thisERRa) < 0. \ and (ER-thisERRa)/(thisERRL-thisERRa) > -10.**-2.: ER = thisERRa #Outside of grid? if ERLz < self._Lzmin or ERLz > self._Lzmax \ or (ER-thisERRa)/(thisERRL-thisERRa) > 1. \ or (ER-thisERRa)/(thisERRL-thisERRa) < 0.: if _PRINTOUTSIDEGRID: #pragma: no cover print("Outside of grid in ER/Lz", ERLz < self._Lzmin , ERLz > self._Lzmax \ , (ER-thisERRa)/(thisERRL-thisERRa) > 1. \ , (ER-thisERRa)/(thisERRL-thisERRa) < 0., ER, thisERRL, thisERRa, (ER-thisERRa)/(thisERRL-thisERRa)) jr = self._aA( thisRL[0], numpy.sqrt(2. * (ER - galpy.potential.evaluatePotentials( thisRL, 0., self._pot)) - ERLz**2. / thisRL**2.)[0], (ERLz / thisRL)[0], 0., 0., _justjr=True, **kwargs)[0] else: jr= (self._jrInterp(ERLz, (ER-thisERRa)/(thisERRL-thisERRa))\ *(numpy.exp(self._jrERRaInterp(ERLz))-10.**-5.))[0][0] return (jr, R * vT, jz)
def __call__(self,*args,**kwargs): """ NAME: __call__ PURPOSE: evaluate the actions (jr,lz,jz) INPUT: Either: R,vR,vT,z,vz scipy.integrate.quadrature keywords (for off-the-grid calcs) OUTPUT: (jr,lz,jz) HISTORY: 2012-11-29 - Written - Bovy (IAS) """ if len(args) == 5: #R,vR.vT, z, vz R,vR,vT, z, vz= args elif len(args) == 6: #R,vR.vT, z, vz, phi R,vR,vT, z, vz, phi= args else: meta= actionAngle(*args) R= meta._R vR= meta._vR vT= meta._vT z= meta._z vz= meta._vz Lz= R*vT Phi= galpy.potential.evaluatePotentials(R,z,self._pot) E= Phi+vR**2./2.+vT**2./2.+vz**2./2. thisRL= self._RLInterp(Lz) thisERL= -numpy.exp(self._ERLInterp(Lz))+self._ERLmax thisERa= -numpy.exp(self._ERaInterp(Lz))+self._ERamax if isinstance(R,numpy.ndarray): if len(R) == 1 and not isinstance(thisERL,numpy.ndarray): thisERL= numpy.array([thisERL]) thisERa= numpy.array([thisERa]) indx= ((E-thisERa)/(thisERL-thisERa) > 1.)\ *(((E-thisERa)/(thisERL-thisERa)-1.) < 10.**-2.) E[indx]= thisERL[indx] indx= ((E-thisERa)/(thisERL-thisERa) < 0.)\ *((E-thisERa)/(thisERL-thisERa) > -10.**-2.) E[indx]= thisERa[indx] indx= (Lz < self._Lzmin) indx+= (Lz > self._Lzmax) indx+= ((E-thisERa)/(thisERL-thisERa) > 1.) indx+= ((E-thisERa)/(thisERL-thisERa) < 0.) indxc= True-indx jr= numpy.empty(R.shape) jz= numpy.empty(R.shape) if numpy.sum(indxc) > 0: u0= numpy.exp(self._logu0Interp.ev(Lz[indxc], (_Efunc(E[indxc],thisERL[indxc])-_Efunc(thisERa[indxc],thisERL[indxc]))/(_Efunc(thisERL[indxc],thisERL[indxc])-_Efunc(thisERa[indxc],thisERL[indxc])))) # (E[indxc]-thisERa[indxc])/(thisERL[indxc]-thisERa[indxc]))) sinh2u0= numpy.sinh(u0)**2. thisEr= self.Er(R[indxc],z[indxc],vR[indxc],vz[indxc], E[indxc],Lz[indxc],sinh2u0,u0) thisEz= self.Ez(R[indxc],z[indxc],vR[indxc],vz[indxc], E[indxc],Lz[indxc],sinh2u0,u0) thisv2= self.vatu0(E[indxc],Lz[indxc],u0,self._delta*numpy.sinh(u0),retv2=True) cos2psi= 2.*thisEr/thisv2/(1.+sinh2u0) #latter is cosh2u0 cos2psi[(cos2psi > 1.)*(cos2psi < 1.+10.**-5.)]= 1. indxCos2psi= (cos2psi > 1.) indxCos2psi+= (cos2psi < 0.) indxc[indxc]= True-indxCos2psi#Handle these two cases as off-grid indx= True-indxc psi= numpy.arccos(numpy.sqrt(cos2psi[True-indxCos2psi])) coords= numpy.empty((3,numpy.sum(indxc))) coords[0,:]= (Lz[indxc]-self._Lzmin)/(self._Lzmax-self._Lzmin)*(self._nLz-1.) #coords[1,:]= (E[indxc]-thisERa[indxc])/(thisERL[indxc]-thisERa[indxc])*(self._nE-1.) y= (_Efunc(E[indxc],thisERL[indxc])-_Efunc(thisERa[indxc],thisERL[indxc]))/(_Efunc(thisERL[indxc],thisERL[indxc])-_Efunc(thisERa[indxc],thisERL[indxc])) coords[1,:]= y*(self._nE-1.) coords[2,:]= psi/numpy.pi*2.*(self._npsi-1.) jr[indxc]= (numpy.exp(ndimage.interpolation.map_coordinates(self._jrFiltered, coords, order=3, prefilter=False))-10.**-10.)*(numpy.exp(self._jrLzInterp(Lz[indxc]))-10.**-5.) #Switch to Ez-calculated psi sin2psi= 2.*thisEz[True-indxCos2psi]/thisv2[True-indxCos2psi]/(1.+sinh2u0[True-indxCos2psi]) #latter is cosh2u0 sin2psi[(sin2psi > 1.)*(sin2psi < 1.+10.**-5.)]= 1. indxSin2psi= (sin2psi > 1.) indxSin2psi+= (sin2psi < 0.) indxc[indxc]= True-indxSin2psi#Handle these two cases as off-grid indx= True-indxc psiz= numpy.arcsin(numpy.sqrt(sin2psi[True-indxSin2psi])) newcoords= numpy.empty((3,numpy.sum(indxc))) newcoords[0:2,:]= coords[0:2,True-indxSin2psi] newcoords[2,:]= psiz/numpy.pi*2.*(self._npsi-1.) jz[indxc]= (numpy.exp(ndimage.interpolation.map_coordinates(self._jzFiltered, newcoords, order=3, prefilter=False))-10.**-10.)*(numpy.exp(self._jzLzInterp(Lz[indxc]))-10.**-5.) if numpy.sum(indx) > 0: jrindiv, lzindiv, jzindiv= self._aA(R[indx], vR[indx], vT[indx], z[indx], vz[indx], **kwargs) jr[indx]= jrindiv jz[indx]= jzindiv """ jrindiv= numpy.empty(numpy.sum(indx)) jzindiv= numpy.empty(numpy.sum(indx)) for ii in range(numpy.sum(indx)): try: thisaA= actionAngleStaeckel.actionAngleStaeckelSingle(\ R[indx][ii], #R vR[indx][ii], #vR vT[indx][ii], #vT z[indx][ii], #z vz[indx][ii], #vz pot=self._pot,delta=self._delta) jrindiv[ii]= thisaA.JR(fixed_quad=True)[0] jzindiv[ii]= thisaA.Jz(fixed_quad=True)[0] except (UnboundError,OverflowError): jrindiv[ii]= numpy.nan jzindiv[ii]= numpy.nan jr[indx]= jrindiv jz[indx]= jzindiv """ else: jr,Lz, jz= self(numpy.array([R]), numpy.array([vR]), numpy.array([vT]), numpy.array([z]), numpy.array([vz]), **kwargs) return (jr[0],Lz[0],jz[0]) return (jr,R*vT,jz)
def __call__(self, *args, **kwargs): """ NAME: __call__ PURPOSE: evaluate the actions (jr,lz,jz) INPUT: Either: R,vR,vT,z,vz scipy.integrate.quadrature keywords (for off-the-grid calcs) OUTPUT: (jr,lz,jz) HISTORY: 2012-11-29 - Written - Bovy (IAS) """ if len(args) == 5: #R,vR.vT, z, vz R, vR, vT, z, vz = args elif len(args) == 6: #R,vR.vT, z, vz, phi R, vR, vT, z, vz, phi = args else: meta = actionAngle(*args) R = meta._R vR = meta._vR vT = meta._vT z = meta._z vz = meta._vz Lz = R * vT Phi = galpy.potential.evaluatePotentials(R, z, self._pot) E = Phi + vR**2. / 2. + vT**2. / 2. + vz**2. / 2. thisERL = -numpy.exp(self._ERLInterp(Lz)) + self._ERLmax thisERa = -numpy.exp(self._ERaInterp(Lz)) + self._ERamax if isinstance(R, numpy.ndarray): indx= ((E-thisERa)/(thisERL-thisERa) > 1.)\ *(((E-thisERa)/(thisERL-thisERa)-1.) < 10.**-2.) E[indx] = thisERL[indx] indx= ((E-thisERa)/(thisERL-thisERa) < 0.)\ *((E-thisERa)/(thisERL-thisERa) > -10.**-2.) E[indx] = thisERa[indx] indx = (Lz < self._Lzmin) indx += (Lz > self._Lzmax) indx += ((E - thisERa) / (thisERL - thisERa) > 1.) indx += ((E - thisERa) / (thisERL - thisERa) < 0.) indxc = True - indx jr = numpy.empty(R.shape) jz = numpy.empty(R.shape) if numpy.sum(indxc) > 0: u0 = numpy.exp( self._logu0Interp.ev( Lz[indxc], (_Efunc(E[indxc], thisERL[indxc]) - _Efunc(thisERa[indxc], thisERL[indxc])) / (_Efunc(thisERL[indxc], thisERL[indxc]) - _Efunc(thisERa[indxc], thisERL[indxc])))) sinh2u0 = numpy.sinh(u0)**2. thisEr = self.Er(R[indxc], z[indxc], vR[indxc], vz[indxc], E[indxc], Lz[indxc], sinh2u0, u0) thisEz = self.Ez(R[indxc], z[indxc], vR[indxc], vz[indxc], E[indxc], Lz[indxc], sinh2u0, u0) thisv2 = self.vatu0(E[indxc], Lz[indxc], u0, self._delta * numpy.sinh(u0), retv2=True) cos2psi = 2. * thisEr / thisv2 / (1. + sinh2u0 ) #latter is cosh2u0 cos2psi[(cos2psi > 1.) * (cos2psi < 1. + 10.**-5.)] = 1. indxCos2psi = (cos2psi > 1.) indxCos2psi += (cos2psi < 0.) indxc[ indxc] = True - indxCos2psi #Handle these two cases as off-grid indx = True - indxc psi = numpy.arccos(numpy.sqrt(cos2psi[True - indxCos2psi])) coords = numpy.empty((3, numpy.sum(indxc))) coords[0, :] = (Lz[indxc] - self._Lzmin) / ( self._Lzmax - self._Lzmin) * (self._nLz - 1.) y = (_Efunc(E[indxc], thisERL[indxc]) - _Efunc(thisERa[indxc], thisERL[indxc])) / ( _Efunc(thisERL[indxc], thisERL[indxc]) - _Efunc(thisERa[indxc], thisERL[indxc])) coords[1, :] = y * (self._nE - 1.) coords[2, :] = psi / numpy.pi * 2. * (self._npsi - 1.) jr[indxc] = (numpy.exp( ndimage.interpolation.map_coordinates( self._jrFiltered, coords, order=3, prefilter=False)) - 10.**-10.) * (numpy.exp( self._jrLzInterp(Lz[indxc])) - 10.**-5.) #Switch to Ez-calculated psi sin2psi = 2. * thisEz[True - indxCos2psi] / thisv2[ True - indxCos2psi] / (1. + sinh2u0[True - indxCos2psi] ) #latter is cosh2u0 sin2psi[(sin2psi > 1.) * (sin2psi < 1. + 10.**-5.)] = 1. indxSin2psi = (sin2psi > 1.) indxSin2psi += (sin2psi < 0.) indxc[ indxc] = True - indxSin2psi #Handle these two cases as off-grid indx = True - indxc psiz = numpy.arcsin(numpy.sqrt(sin2psi[True - indxSin2psi])) newcoords = numpy.empty((3, numpy.sum(indxc))) newcoords[0:2, :] = coords[0:2, True - indxSin2psi] newcoords[2, :] = psiz / numpy.pi * 2. * (self._npsi - 1.) jz[indxc] = (numpy.exp( ndimage.interpolation.map_coordinates( self._jzFiltered, newcoords, order=3, prefilter=False)) - 10.**-10.) * ( numpy.exp(self._jzLzInterp(Lz[indxc])) - 10.**-5.) if numpy.sum(indx) > 0: jrindiv, lzindiv, jzindiv = self._aA(R[indx], vR[indx], vT[indx], z[indx], vz[indx], **kwargs) jr[indx] = jrindiv jz[indx] = jzindiv """ jrindiv= numpy.empty(numpy.sum(indx)) jzindiv= numpy.empty(numpy.sum(indx)) for ii in range(numpy.sum(indx)): try: thisaA= actionAngleStaeckel.actionAngleStaeckelSingle(\ R[indx][ii], #R vR[indx][ii], #vR vT[indx][ii], #vT z[indx][ii], #z vz[indx][ii], #vz pot=self._pot,delta=self._delta) jrindiv[ii]= thisaA.JR(fixed_quad=True)[0] jzindiv[ii]= thisaA.Jz(fixed_quad=True)[0] except (UnboundError,OverflowError): jrindiv[ii]= numpy.nan jzindiv[ii]= numpy.nan jr[indx]= jrindiv jz[indx]= jzindiv """ else: jr, Lz, jz = self(numpy.array([R]), numpy.array([vR]), numpy.array([vT]), numpy.array([z]), numpy.array([vz]), **kwargs) return (jr[0], Lz[0], jz[0]) jr[jr < 0.] = 0. jz[jz < 0.] = 0. return (jr, R * vT, jz)
def __call__(self,*args,**kwargs): """ NAME: __call__ PURPOSE: evaluate the actions (jr,lz,jz) INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords _justjr, _justjz= if True, only calculate the radial or vertical action (internal use) OUTPUT: (jr,lz,jz), where jr=[jr,jrerr], and jz=[jz,jzerr] HISTORY: 2012-07-26 - Written - Bovy (IAS@MPIA) """ if ((self._c and not ('c' in kwargs and not kwargs['c']))\ or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \ and _check_c(self._pot): if len(args) == 5: #R,vR.vT, z, vz R,vR,vT, z, vz= args elif len(args) == 6: #R,vR.vT, z, vz, phi R,vR,vT, z, vz, phi= args else: meta= actionAngle(*args) R= meta._R vR= meta._vR vT= meta._vT z= meta._z vz= meta._vz if isinstance(R,float): R= nu.array([R]) vR= nu.array([vR]) vT= nu.array([vT]) z= nu.array([z]) vz= nu.array([vz]) Lz= R*vT jr, jz, err= actionAngleAdiabatic_c.actionAngleAdiabatic_c(\ self._pot,self._gamma,R,vR,vT,z,vz) if err == 0: return (jr,Lz,jz) else: #pragma: no cover raise RuntimeError("C-code for calculation actions failed; try with c=False") else: if 'c' in kwargs and kwargs['c'] and not self._c: warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover kwargs.pop('c',None) if (len(args) == 5 or len(args) == 6) \ and isinstance(args[0],nu.ndarray): ojr= nu.zeros((len(args[0]))) olz= nu.zeros((len(args[0]))) ojz= nu.zeros((len(args[0]))) for ii in range(len(args[0])): if len(args) == 5: targs= (args[0][ii],args[1][ii],args[2][ii], args[3][ii],args[4][ii]) elif len(args) == 6: targs= (args[0][ii],args[1][ii],args[2][ii], args[3][ii],args[4][ii],args[5][ii]) tjr,tlz,tjz= self(*targs,**copy.copy(kwargs)) ojr[ii]= tjr ojz[ii]= tjz olz[ii]= tlz return (ojr,olz,ojz) else: #Set up the actionAngleAxi object meta= actionAngle(*args) if isinstance(self._pot,list): thispot= [p.toPlanar() for p in self._pot] else: thispot= self._pot.toPlanar() if isinstance(self._pot,list): thisverticalpot= [p.toVertical(meta._R) for p in self._pot] else: thisverticalpot= self._pot.toVertical(meta._R) aAAxi= actionAngleAxi(*args,pot=thispot, verticalPot=thisverticalpot, gamma=self._gamma) if kwargs.get('_justjr',False): kwargs.pop('_justjr') return (aAAxi.JR(**kwargs),nu.nan,nu.nan) elif kwargs.get('_justjz',False): kwargs.pop('_justjz') return (nu.nan,nu.nan,aAAxi.Jz(**kwargs)) else: return (aAAxi.JR(**kwargs),aAAxi._R*aAAxi._vT,aAAxi.Jz(**kwargs))
def __call__(self, *args, **kwargs): """ NAME: __call__ PURPOSE: evaluate the actions (jr,lz,jz) INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well c= True/False; overrides the object's c= keyword to use C or not scipy.integrate.quadrature keywords OUTPUT: (jr,lz,jz) HISTORY: 2012-11-27 - Written - Bovy (IAS) """ if ((self._c and not ('c' in kwargs and not kwargs['c']))\ or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \ and _check_c(self._pot): if len(args) == 5: #R,vR.vT, z, vz R, vR, vT, z, vz = args elif len(args) == 6: #R,vR.vT, z, vz, phi R, vR, vT, z, vz, phi = args else: meta = actionAngle(*args) R = meta._R vR = meta._vR vT = meta._vT z = meta._z vz = meta._vz if isinstance(R, float): R = nu.array([R]) vR = nu.array([vR]) vT = nu.array([vT]) z = nu.array([z]) vz = nu.array([vz]) Lz = R * vT if self._useu0: #First calculate u0 if 'u0' in kwargs: u0 = nu.asarray(kwargs['u0']) else: E = nu.array([ evaluatePotentials(R[ii], z[ii], self._pot) + vR[ii]**2. / 2. + vz[ii]**2. / 2. + vT[ii]**2. / 2. for ii in range(len(R)) ]) u0 = actionAngleStaeckel_c.actionAngleStaeckel_calcu0( E, Lz, self._pot, self._delta)[0] kwargs.pop('u0', None) else: u0 = None jr, jz, err= actionAngleStaeckel_c.actionAngleStaeckel_c(\ self._pot,self._delta,R,vR,vT,z,vz,u0=u0) if err == 0: return (jr, Lz, jz) else: #pragma: no cover raise RuntimeError( "C-code for calculation actions failed; try with c=False") else: if 'c' in kwargs and kwargs['c'] and not self._c: #pragma: no cover warnings.warn( "C module not used because potential does not have a C implementation", galpyWarning) kwargs.pop('c', None) if (len(args) == 5 or len(args) == 6) \ and isinstance(args[0],nu.ndarray): ojr = nu.zeros((len(args[0]))) olz = nu.zeros((len(args[0]))) ojz = nu.zeros((len(args[0]))) for ii in range(len(args[0])): if len(args) == 5: targs = (args[0][ii], args[1][ii], args[2][ii], args[3][ii], args[4][ii]) elif len(args) == 6: targs = (args[0][ii], args[1][ii], args[2][ii], args[3][ii], args[4][ii], args[5][ii]) tjr, tlz, tjz = self(*targs, **copy.copy(kwargs)) ojr[ii] = tjr ojz[ii] = tjz olz[ii] = tlz return (ojr, olz, ojz) else: #Set up the actionAngleStaeckelSingle object aASingle = actionAngleStaeckelSingle(*args, pot=self._pot, delta=self._delta) return (aASingle.JR(**copy.copy(kwargs)), aASingle._R * aASingle._vT, aASingle.Jz(**copy.copy(kwargs)))
def actionsFreqsAngles(self, *args, **kwargs): """ NAME: actionsFreqsAngles PURPOSE: evaluate the actions, frequencies, and angles (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) INPUT: Either: a) R,vR,vT,z,vz,phi (MUST HAVE PHI) b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords OUTPUT: (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) HISTORY: 2013-08-28 - Written - Bovy (IAS) """ if ((self._c and not ('c' in kwargs and not kwargs['c']))\ or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \ and _check_c(self._pot): if len(args) == 5: #R,vR.vT, z, vz pragma: no cover raise IOError("Must specify phi") elif len(args) == 6: #R,vR.vT, z, vz, phi R, vR, vT, z, vz, phi = args else: meta = actionAngle(*args) R = meta._R vR = meta._vR vT = meta._vT z = meta._z vz = meta._vz phi = meta._phi if isinstance(R, float): R = nu.array([R]) vR = nu.array([vR]) vT = nu.array([vT]) z = nu.array([z]) vz = nu.array([vz]) phi = nu.array([phi]) Lz = R * vT if self._useu0: #First calculate u0 if 'u0' in kwargs: u0 = nu.asarray(kwargs['u0']) else: E = nu.array([ evaluatePotentials(R[ii], z[ii], self._pot) + vR[ii]**2. / 2. + vz[ii]**2. / 2. + vT[ii]**2. / 2. for ii in range(len(R)) ]) u0 = actionAngleStaeckel_c.actionAngleStaeckel_calcu0( E, Lz, self._pot, self._delta)[0] kwargs.pop('u0', None) else: u0 = None jr, jz, Omegar, Omegaphi, Omegaz, angler, anglephi,anglez, err= actionAngleStaeckel_c.actionAngleFreqAngleStaeckel_c(\ self._pot,self._delta,R,vR,vT,z,vz,phi,u0=u0) # Adjustements for close-to-circular orbits indx = nu.isnan(Omegar) * (jr < 10.**-3.) + nu.isnan(Omegaz) * ( jz < 10.**-3. ) #Close-to-circular and close-to-the-plane orbits if nu.sum(indx) > 0: Omegar[indx] = [epifreq(self._pot, r) for r in R[indx]] Omegaphi[indx] = [omegac(self._pot, r) for r in R[indx]] Omegaz[indx] = [verticalfreq(self._pot, r) for r in R[indx]] if err == 0: return (jr, Lz, jz, Omegar, Omegaphi, Omegaz, angler, anglephi, anglez) else: raise RuntimeError( "C-code for calculation actions failed; try with c=False" ) #pragma: no cover else: #pragma: no cover if 'c' in kwargs and kwargs['c'] and not self._c: #pragma: no cover warnings.warn( "C module not used because potential does not have a C implementation", galpyWarning) raise NotImplementedError( "actionsFreqs with c=False not implemented")
def __call__(self,*args,**kwargs): """ NAME: __call__ PURPOSE: evaluate the actions (jr,lz,jz) INPUT: Either: a) R,vR,vT,z,vz b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well c= True/False; overrides the object's c= keyword to use C or not scipy.integrate.quadrature keywords OUTPUT: (jr,lz,jz) HISTORY: 2012-11-27 - Written - Bovy (IAS) """ if ((self._c and not ('c' in kwargs and not kwargs['c']))\ or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \ and _check_c(self._pot): if len(args) == 5: #R,vR.vT, z, vz R,vR,vT, z, vz= args elif len(args) == 6: #R,vR.vT, z, vz, phi R,vR,vT, z, vz, phi= args else: meta= actionAngle(*args) R= meta._R vR= meta._vR vT= meta._vT z= meta._z vz= meta._vz if isinstance(R,float): R= nu.array([R]) vR= nu.array([vR]) vT= nu.array([vT]) z= nu.array([z]) vz= nu.array([vz]) Lz= R*vT if self._useu0: #First calculate u0 if 'u0' in kwargs: u0= nu.asarray(kwargs['u0']) else: E= nu.array([evaluatePotentials(R[ii],z[ii],self._pot) +vR[ii]**2./2.+vz[ii]**2./2.+vT[ii]**2./2. for ii in range(len(R))]) u0= actionAngleStaeckel_c.actionAngleStaeckel_calcu0(E,Lz, self._pot, self._delta)[0] kwargs.pop('u0',None) else: u0= None jr, jz, err= actionAngleStaeckel_c.actionAngleStaeckel_c(\ self._pot,self._delta,R,vR,vT,z,vz,u0=u0) if err == 0: return (jr,Lz,jz) else: #pragma: no cover raise RuntimeError("C-code for calculation actions failed; try with c=False") else: if 'c' in kwargs and kwargs['c'] and not self._c: #pragma: no cover warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) kwargs.pop('c',None) if (len(args) == 5 or len(args) == 6) \ and isinstance(args[0],nu.ndarray): ojr= nu.zeros((len(args[0]))) olz= nu.zeros((len(args[0]))) ojz= nu.zeros((len(args[0]))) for ii in range(len(args[0])): if len(args) == 5: targs= (args[0][ii],args[1][ii],args[2][ii], args[3][ii],args[4][ii]) elif len(args) == 6: targs= (args[0][ii],args[1][ii],args[2][ii], args[3][ii],args[4][ii],args[5][ii]) tjr,tlz,tjz= self(*targs,**copy.copy(kwargs)) ojr[ii]= tjr ojz[ii]= tjz olz[ii]= tlz return (ojr,olz,ojz) else: #Set up the actionAngleStaeckelSingle object aASingle= actionAngleStaeckelSingle(*args,pot=self._pot, delta=self._delta) return (aASingle.JR(**copy.copy(kwargs)), aASingle._R*aASingle._vT, aASingle.Jz(**copy.copy(kwargs)))
def actionsFreqsAngles(self,*args,**kwargs): """ NAME: actionsFreqsAngles PURPOSE: evaluate the actions, frequencies, and angles (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) INPUT: Either: a) R,vR,vT,z,vz,phi (MUST HAVE PHI) b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords OUTPUT: (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) HISTORY: 2013-08-28 - Written - Bovy (IAS) """ if ((self._c and not ('c' in kwargs and not kwargs['c']))\ or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \ and _check_c(self._pot): if len(args) == 5: #R,vR.vT, z, vz pragma: no cover raise IOError("Must specify phi") elif len(args) == 6: #R,vR.vT, z, vz, phi R,vR,vT, z, vz, phi= args else: meta= actionAngle(*args) R= meta._R vR= meta._vR vT= meta._vT z= meta._z vz= meta._vz phi= meta._phi if isinstance(R,float): R= nu.array([R]) vR= nu.array([vR]) vT= nu.array([vT]) z= nu.array([z]) vz= nu.array([vz]) phi= nu.array([phi]) Lz= R*vT if self._useu0: #First calculate u0 if 'u0' in kwargs: u0= nu.asarray(kwargs['u0']) else: E= nu.array([evaluatePotentials(R[ii],z[ii],self._pot) +vR[ii]**2./2.+vz[ii]**2./2.+vT[ii]**2./2. for ii in range(len(R))]) u0= actionAngleStaeckel_c.actionAngleStaeckel_calcu0(E,Lz, self._pot, self._delta)[0] kwargs.pop('u0',None) else: u0= None jr, jz, Omegar, Omegaphi, Omegaz, angler, anglephi,anglez, err= actionAngleStaeckel_c.actionAngleFreqAngleStaeckel_c(\ self._pot,self._delta,R,vR,vT,z,vz,phi,u0=u0) # Adjustements for close-to-circular orbits indx= nu.isnan(Omegar)*(jr < 10.**-3.)+nu.isnan(Omegaz)*(jz < 10.**-3.) #Close-to-circular and close-to-the-plane orbits if nu.sum(indx) > 0: Omegar[indx]= [epifreq(self._pot,r) for r in R[indx]] Omegaphi[indx]= [omegac(self._pot,r) for r in R[indx]] Omegaz[indx]= [verticalfreq(self._pot,r) for r in R[indx]] if err == 0: return (jr,Lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) else: raise RuntimeError("C-code for calculation actions failed; try with c=False") #pragma: no cover else: #pragma: no cover if 'c' in kwargs and kwargs['c'] and not self._c: #pragma: no cover warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) raise NotImplementedError("actionsFreqs with c=False not implemented")
def actionsFreqsAngles(self,*args,**kwargs): """ NAME: actionsFreqsAngles PURPOSE: evaluate the actions, frequencies, and angles (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) INPUT: Either: a) R,vR,vT,z,vz,phi (MUST HAVE PHI) b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well scipy.integrate.quadrature keywords OUTPUT: (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) HISTORY: 2013-09-08 - Written - Bovy (IAS) """ if len(args) == 5: #R,vR.vT, z, vz pragma: no cover raise IOError("You need to provide phi when calculating angles") elif len(args) == 6: #R,vR.vT, z, vz, phi R,vR,vT, z, vz, phi= args else: meta= actionAngle(*args) R= meta._R vR= meta._vR vT= meta._vT z= meta._z vz= meta._vz phi= meta._phi if isinstance(R,float): R= nu.array([R]) vR= nu.array([vR]) vT= nu.array([vT]) z= nu.array([z]) vz= nu.array([vz]) phi= nu.array([phi]) if self._c: #pragma: no cover pass else: Lz= R*vT Lx= -z*vT Ly= z*vR-R*vz L2= Lx*Lx+Ly*Ly+Lz*Lz E= self._ip(R,z)+vR**2./2.+vT**2./2.+vz**2./2. L= nu.sqrt(L2) #Actions Jphi= Lz Jz= L-nu.fabs(Lz) Jr= self.amp/nu.sqrt(-2.*E)\ -0.5*(L+nu.sqrt((L2+4.*self.amp*self.b))) #Frequencies Omegar= (-2.*E)**1.5/self.amp Omegaz= 0.5*(1.+L/nu.sqrt(L2+4.*self.amp*self.b))*Omegar Omegaphi= copy.copy(Omegaz) indx= Lz < 0. Omegaphi[indx]*= -1. #Angles c= -self.amp/2./E-self.b e2= 1.-L2/self.amp/c*(1.+self.b/c) e= nu.sqrt(e2) s= 1.+nu.sqrt(1.+(R**2.+z**2.)/self.b**2.) coseta= 1/e*(1.-self.b/c*(s-2.)) pindx= (coseta > 1.)*(coseta < (1.+10.**-7.)) coseta[pindx]= 1. pindx= (coseta < -1.)*(coseta > (-1.-10.**-7.)) coseta[pindx]= -1. eta= nu.arccos(coseta) costheta= z/nu.sqrt(R**2.+z**2.) sintheta= R/nu.sqrt(R**2.+z**2.) vrindx= (vR*sintheta+vz*costheta) < 0. eta[vrindx]= 2.*nu.pi-eta[vrindx] angler= eta-e*c/(c+self.b)*nu.sin(eta) tan11= nu.arctan(nu.sqrt((1.+e)/(1.-e))*nu.tan(0.5*eta)) tan12= nu.arctan(nu.sqrt((1.+e+2.*self.b/c)/(1.-e+2.*self.b/c))*nu.tan(0.5*eta)) vzindx= (-vz*sintheta+vR*costheta) > 0. tan11[tan11 < 0.]+= nu.pi tan12[tan12 < 0.]+= nu.pi pindx= (Lz/L > 1.)*(Lz/L < (1.+10.**-7.)) Lz[pindx]= L[pindx] pindx= (Lz/L < -1.)*(Lz/L > (-1.-10.**-7.)) Lz[pindx]= -L[pindx] i= nu.arccos(Lz/L) sinpsi= costheta/nu.sin(i) pindx= (sinpsi > 1.)*(sinpsi < (1.+10.**-7.)) sinpsi[pindx]= 1. pindx= (sinpsi < -1.)*(sinpsi > (-1.-10.**-7.)) sinpsi[pindx]= -1. psi= nu.arcsin(sinpsi) psi[vzindx]= nu.pi-psi[vzindx] psi= psi % (2.*nu.pi) anglez= psi+Omegaz/Omegar*angler\ -tan11-1./nu.sqrt(1.+4*self.amp*self.b/L2)*tan12 sinu= z/R/nu.tan(i) pindx= (sinu > 1.)*(sinu < (1.+10.**-7.)) sinu[pindx]= 1. pindx= (sinu < -1.)*(sinu > (-1.-10.**-7.)) sinu[pindx]= -1. u= nu.arcsin(sinu) u[vzindx]= nu.pi-u[vzindx] Omega= phi-u anglephi= Omega anglephi[indx]-= anglez[indx] anglephi[True-indx]+= anglez[True-indx] angler= angler % (2.*nu.pi) anglephi= anglephi % (2.*nu.pi) anglez= anglez % (2.*nu.pi) return (Jr,Jphi,Jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)