diff -Nru galpy-1.5/AUTHORS.txt galpy-1.6.0.post0/AUTHORS.txt --- galpy-1.5/AUTHORS.txt 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/AUTHORS.txt 2020-04-24 19:48:38.000000000 +0000 @@ -25,7 +25,7 @@ Samuel Wong (sampleV_interpolate method of quasiisothermaldf) James Lane (General mass distributions in MovingObjectPotential) Henry Leung (addition of Python and C implementation of Dormand-Prince 8(5,3) integrator) -Nathaniel Starkman (custom coordinates in bovy_coords) +Nathaniel Starkman (custom coordinates in bovy_coords, DehnenSphericalPotential, time dependences in potential, amuse-astropy Potential compatibility) General help: ============== diff -Nru galpy-1.5/debian/changelog galpy-1.6.0.post0/debian/changelog --- galpy-1.5/debian/changelog 2020-02-18 09:19:35.000000000 +0000 +++ galpy-1.6.0.post0/debian/changelog 2020-05-18 00:47:44.000000000 +0000 @@ -1,8 +1,9 @@ -galpy (1.5-1build1) focal; urgency=medium +galpy (1.6.0.post0-1) unstable; urgency=medium - * No-change rebuild to drop python3.7. + * New upstream release 1.6.0.post0 + * Bump Standards-Version to 4.5.0. No changes required - -- Matthias Klose Tue, 18 Feb 2020 10:19:35 +0100 + -- Josue Ortega Sun, 17 May 2020 18:47:44 -0600 galpy (1.5-1) unstable; urgency=medium diff -Nru galpy-1.5/debian/control galpy-1.6.0.post0/debian/control --- galpy-1.5/debian/control 2019-10-04 18:26:56.000000000 +0000 +++ galpy-1.6.0.post0/debian/control 2020-05-18 00:47:44.000000000 +0000 @@ -15,7 +15,7 @@ python3-tk, python3-future, libgsl-dev -Standards-Version: 4.4.1 +Standards-Version: 4.5.0 Homepage: https://pypi.python.org/pypi/galpy Vcs-Git: https://salsa.debian.org/debian-astro-team/galpy.git Vcs-Browser: https://salsa.debian.org/debian-astro-team/galpy diff -Nru galpy-1.5/galpy/actionAngle/actionAngleAdiabatic_c.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleAdiabatic_c.py --- galpy-1.5/galpy/actionAngle/actionAngleAdiabatic_c.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleAdiabatic_c.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,39 +1,10 @@ -import os -import sys -import distutils.sysconfig as sysconfig -import warnings import ctypes import ctypes.util import numpy from numpy.ctypeslib import ndpointer -from galpy.util import galpyWarning -#Find and load the library -_lib= None -outerr= None -PY3= sys.version > '3' -if PY3: - _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') -else: #pragma: no cover - _ext_suffix= '.so' -for path in sys.path: - try: - _lib = ctypes.CDLL(os.path.join(path,'galpy_actionAngle_c%s' % _ext_suffix)) - except OSError as e: - if os.path.exists(os.path.join(path,'galpy_actionAngle_c%s' % _ext_suffix)): #pragma: no cover - outerr= e - _lib = None - else: - break -if _lib is None: #pragma: no cover - if not outerr is None: - warnings.warn("actionAngleAdiabatic_c extension module not loaded, because of error '%s' " % outerr, - galpyWarning) - else: - warnings.warn("actionAngleAdiabatic_c extension module not loaded, because galpy_actionAngle_c%s image was not found" % _ext_suffix, - galpyWarning) - _ext_loaded= False -else: - _ext_loaded= True +from ..util import _load_extension_libs + +_lib, _ext_loaded= _load_extension_libs.load_libgalpy() def actionAngleAdiabatic_c(pot,gamma,R,vR,vT,z,vz): """ @@ -53,7 +24,7 @@ 2012-12-10 - Written - Bovy (IAS) """ #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Set up result arrays @@ -134,7 +105,7 @@ 2017-12-21 - Written - Bovy (UofT) """ #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Set up result arrays diff -Nru galpy-1.5/galpy/actionAngle/actionAngleAdiabaticGrid.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleAdiabaticGrid.py --- galpy-1.5/galpy/actionAngle/actionAngleAdiabaticGrid.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleAdiabaticGrid.py 2020-04-24 19:48:38.000000000 +0000 @@ -11,15 +11,14 @@ # ############################################################################### from __future__ import print_function -import math import numpy from scipy import interpolate from .actionAngleAdiabatic import actionAngleAdiabatic from .actionAngle import actionAngle, UnboundError -import galpy.potential -from galpy.potential.Potential import _evaluatePotentials -from galpy.potential.Potential import flatten as flatten_potential -from galpy.util import multi +from .. import potential +from ..potential.Potential import _evaluatePotentials +from ..potential.Potential import flatten as flatten_potential +from ..util import multi _PRINTOUTSIDEGRID= False class actionAngleAdiabaticGrid(actionAngle): """Action-angle formalism for axisymmetric potentials using the adiabatic approximation, grid-based interpolation""" @@ -99,7 +98,7 @@ else: if numcores > 1: jz= multi.parallel_map((lambda x: self._aA(thisRs[x],0.,1.,#these two r dummies - 0.,math.sqrt(2.*thisy[x]*thisEzZmaxs[x]), + 0.,numpy.sqrt(2.*thisy[x]*thisEzZmaxs[x]), _justjz=True, **kwargs)[2]), range(nR*nEz),numcores=numcores) @@ -126,12 +125,11 @@ self._Lzmin= 0.01 self._Lzs= numpy.linspace(self._Lzmin, self._Rmax\ - *galpy.potential.vcirc(self._pot, - self._Rmax), + *potential.vcirc(self._pot,self._Rmax), nLz) self._Lzmax= self._Lzs[-1] #Calculate ER(vr=0,R=RL) - self._RL= numpy.array([galpy.potential.rl(self._pot,l) for l in self._Lzs]) + self._RL= numpy.array([potential.rl(self._pot,l) for l in self._Lzs]) self._RLInterp= interpolate.InterpolatedUnivariateSpline(self._Lzs, self._RL,k=3) self._ERRL= _evaluatePotentials(self._pot,self._RL,numpy.zeros(nLz)) +self._Lzs**2./2./self._RL**2. @@ -262,7 +260,7 @@ 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), + 0.,numpy.sqrt(2.*Ez), _justjz=True, **kwargs)[2] else: @@ -353,7 +351,7 @@ if _PRINTOUTSIDEGRID: #pragma: no cover print("Outside of grid in Ez") jz= self._aA(self._eval_R,0.,1.,#these two r dummies - 0.,math.sqrt(2.*Ez), + 0.,numpy.sqrt(2.*Ez), _justjz=True, **kwargs)[2] else: diff -Nru galpy-1.5/galpy/actionAngle/actionAngleAdiabatic.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleAdiabatic.py --- galpy-1.5/galpy/actionAngle/actionAngleAdiabatic.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleAdiabatic.py 2020-04-24 19:48:38.000000000 +0000 @@ -12,17 +12,16 @@ ############################################################################### import copy import warnings -import math as m -import numpy as nu -from galpy.util import galpyWarning -from galpy.potential import planarPotential, MWPotential -from galpy.potential.Potential import flatten as flatten_potential +import numpy +from ..util import galpyWarning +from ..potential import MWPotential +from ..potential.Potential import flatten as flatten_potential from ..potential import toPlanarPotential, toVerticalPotential from .actionAngleAxi import actionAngleAxi from .actionAngle import actionAngle from . import actionAngleAdiabatic_c from .actionAngleAdiabatic_c import _ext_loaded as ext_loaded -from galpy.potential.Potential import _check_c +from ..potential.Potential import _check_c class actionAngleAdiabatic(actionAngle): """Action-angle formalism for axisymmetric potentials using the adiabatic approximation""" def __init__(self,*args,**kwargs): @@ -105,11 +104,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) 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): @@ -125,9 +124,9 @@ warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover kwargs.pop('c',None) if len(R) > 1: - ojr= nu.zeros((len(R))) - olz= nu.zeros((len(R))) - ojz= nu.zeros((len(R))) + ojr= numpy.zeros((len(R))) + olz= numpy.zeros((len(R))) + ojz= numpy.zeros((len(R))) for ii in range(len(R)): targs= (R[ii],vR[ii],vT[ii],z[ii],vz[ii]) tjr,tlz,tjz= self(*targs,**copy.copy(kwargs)) @@ -145,16 +144,16 @@ gamma=self._gamma) if kwargs.get('_justjr',False): kwargs.pop('_justjr') - return (aAAxi.JR(**kwargs),nu.nan,nu.nan) + return (aAAxi.JR(**kwargs),numpy.nan,numpy.nan) elif kwargs.get('_justjz',False): kwargs.pop('_justjz') - return (nu.atleast_1d(nu.nan), - nu.atleast_1d(nu.nan), - nu.atleast_1d(aAAxi.Jz(**kwargs))) + return (numpy.atleast_1d(numpy.nan), + numpy.atleast_1d(numpy.nan), + numpy.atleast_1d(aAAxi.Jz(**kwargs))) else: - return (nu.atleast_1d(aAAxi.JR(**kwargs)), - nu.atleast_1d(aAAxi._R*aAAxi._vT), - nu.atleast_1d(aAAxi.Jz(**kwargs))) + return (numpy.atleast_1d(aAAxi.JR(**kwargs)), + numpy.atleast_1d(aAAxi._R*aAAxi._vT), + numpy.atleast_1d(aAAxi.Jz(**kwargs))) def _EccZmaxRperiRap(self,*args,**kwargs): """ @@ -186,18 +185,18 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) 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): rperi,Rap,zmax, err= actionAngleAdiabatic_c.actionAngleRperiRapZmaxAdiabatic_c(\ self._pot,self._gamma,R,vR,vT,z,vz) if err == 0: - rap= nu.sqrt(Rap**2.+zmax**2.) + rap= numpy.sqrt(Rap**2.+zmax**2.) ecc= (rap-rperi)/(rap+rperi) return (ecc,zmax,rperi,rap) else: #pragma: no cover @@ -207,10 +206,10 @@ warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover kwargs.pop('c',None) if len(R) > 1: - oecc= nu.zeros((len(R))) - orperi= nu.zeros((len(R))) - orap= nu.zeros((len(R))) - ozmax= nu.zeros((len(R))) + oecc= numpy.zeros((len(R))) + orperi= numpy.zeros((len(R))) + orap= numpy.zeros((len(R))) + ozmax= numpy.zeros((len(R))) for ii in range(len(R)): targs= (R[ii],vR[ii],vT[ii],z[ii],vz[ii]) tecc, tzmax, trperi,trap= self._EccZmaxRperiRap(\ @@ -230,10 +229,10 @@ gamma=self._gamma) rperi,Rap= aAAxi.calcRapRperi(**kwargs) zmax= aAAxi.calczmax(**kwargs) - rap= nu.sqrt(Rap**2.+zmax**2.) - return (nu.atleast_1d((rap-rperi)/(rap+rperi)), - nu.atleast_1d(zmax),nu.atleast_1d(rperi), - nu.atleast_1d(rap)) + rap= numpy.sqrt(Rap**2.+zmax**2.) + return (numpy.atleast_1d((rap-rperi)/(rap+rperi)), + numpy.atleast_1d(zmax),numpy.atleast_1d(rperi), + numpy.atleast_1d(rap)) def calcRapRperi(self,*args,**kwargs): """ diff -Nru galpy-1.5/galpy/actionAngle/actionAngleAxi.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleAxi.py --- galpy-1.5/galpy/actionAngle/actionAngleAxi.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleAxi.py 2020-04-24 19:48:38.000000000 +0000 @@ -13,14 +13,13 @@ # calcRapRperi # calcEL ############################################################################### -import math as m -import numpy as nu +import numpy from scipy import optimize, integrate -from .actionAngle import * +from .actionAngle import UnboundError from .actionAngleVertical import actionAngleVertical -from galpy.potential.planarPotential import _evaluateplanarPotentials -from galpy.potential.Potential import epifreq -from galpy.potential import vcirc +from ..potential.planarPotential import _evaluateplanarPotentials +from ..potential.Potential import epifreq +from ..potential import vcirc _EPS= 10.**-15. class actionAngleAxi(actionAngleVertical): """Action-angle formalism for axisymmetric potentials""" @@ -80,29 +79,29 @@ TR= self.TR(**kwargs)[0] EL= self.calcEL(**kwargs) E, L= EL - Rmean= m.exp((m.log(rperi)+m.log(rap))/2.) + Rmean= numpy.exp((numpy.log(rperi)+numpy.log(rap))/2.) if self._R < Rmean: if self._R > rperi: - wR= (2.*m.pi/TR* - nu.array(integrate.quadrature(_TRAxiIntegrandSmall, - 0.,m.sqrt(self._R-rperi), + wR= (2.*numpy.pi/TR* + numpy.array(integrate.quadrature(_TRAxiIntegrandSmall, + 0.,numpy.sqrt(self._R-rperi), args=(E,L,self._pot,rperi), **kwargs)))\ - +nu.array([m.pi,0.]) + +numpy.array([numpy.pi,0.]) else: - wR= nu.array([m.pi,0.]) + wR= numpy.array([numpy.pi,0.]) else: if self._R < rap: - wR= -(2.*m.pi/TR* - nu.array(integrate.quadrature(_TRAxiIntegrandLarge, - 0.,m.sqrt(rap-self._R), + wR= -(2.*numpy.pi/TR* + numpy.array(integrate.quadrature(_TRAxiIntegrandLarge, + 0.,numpy.sqrt(rap-self._R), args=(E,L,self._pot,rap), **kwargs))) else: - wR= nu.array([0.,0.]) + wR= numpy.array([0.,0.]) if self._vR < 0.: - wR[0]+= m.pi - self._angleR= nu.array([wR[0] % (2.*m.pi),wR[1]]) + wR[0]+= numpy.pi + self._angleR= numpy.array([wR[0] % (2.*numpy.pi),wR[1]]) return self._angleR def TR(self,**kwargs): #pragma: no cover @@ -121,21 +120,21 @@ if hasattr(self,'_TR'): return self._TR (rperi,rap)= self.calcRapRperi(**kwargs) - if nu.fabs(rap-rperi)/rap < 10.**-4.: #Rough limit - self._TR= 2.*m.pi/epifreq(self._pot,self._R,use_physical=False) + if numpy.fabs(rap-rperi)/rap < 10.**-4.: #Rough limit + self._TR= 2.*numpy.pi/epifreq(self._pot,self._R,use_physical=False) return self._TR - Rmean= m.exp((m.log(rperi)+m.log(rap))/2.) + Rmean= numpy.exp((numpy.log(rperi)+numpy.log(rap))/2.) EL= self.calcEL(**kwargs) E, L= EL TR= 0. if Rmean > rperi: TR+= integrate.quadrature(_TRAxiIntegrandSmall, - 0.,m.sqrt(Rmean-rperi), + 0.,numpy.sqrt(Rmean-rperi), args=(E,L,self._pot,rperi), **kwargs)[0] if Rmean < rap: TR+= integrate.quadrature(_TRAxiIntegrandLarge, - 0.,m.sqrt(rap-Rmean), + 0.,numpy.sqrt(rap-Rmean), args=(E,L,self._pot,rap), **kwargs)[0] self._TR= 2.*TR @@ -158,10 +157,10 @@ return self._Tphi (rperi,rap)= self.calcRapRperi(**kwargs) if rap == rperi:#Circular orbit - return 2.*m.pi*self._R/self._vT + return 2.*numpy.pi*self._R/self._vT TR= self.TR(**kwargs) I= self.I(**kwargs) - Tphi= TR/I*m.pi + Tphi= TR/I*numpy.pi self._Tphi= Tphi return self._Tphi @@ -181,23 +180,23 @@ if hasattr(self,'_I'): return self._I (rperi,rap)= self.calcRapRperi(**kwargs) - Rmean= m.exp((m.log(rperi)+m.log(rap))/2.) - if nu.fabs(rap-rperi)/rap < 10.**-4.: #Rough limit + Rmean= numpy.exp((numpy.log(rperi)+numpy.log(rap))/2.) + if numpy.fabs(rap-rperi)/rap < 10.**-4.: #Rough limit TR= self.TR()[0] Tphi= self.Tphi()[0] - self._I= TR/Tphi*m.pi + self._I= TR/Tphi*numpy.pi return self._I EL= self.calcEL(**kwargs) E, L= EL I= 0. if Rmean > rperi: I+= integrate.quadrature(_IAxiIntegrandSmall, - 0.,m.sqrt(Rmean-rperi), + 0.,numpy.sqrt(Rmean-rperi), args=(E,L,self._pot,rperi), **kwargs)[0] if Rmean < rap: I+= integrate.quadrature(_IAxiIntegrandLarge, - 0.,m.sqrt(rap-Rmean), + 0.,numpy.sqrt(rap-Rmean), args=(E,L,self._pot,rap), **kwargs)[0] self._I= I*self._R*self._vT @@ -235,7 +234,7 @@ (rperi,rap)= self.calcRapRperi(**kwargs) EL= self.calcEL(**kwargs) E, L= EL - self._JR= 1./nu.pi*integrate.quad(_JRAxiIntegrand,rperi,rap, + self._JR= 1./numpy.pi*integrate.quad(_JRAxiIntegrand,rperi,rap, args=(E,L,self._pot), **kwargs)[0] return self._JR @@ -257,7 +256,7 @@ if self._gamma != 0.: #Adjust E E-= self._vT**2./2. - L= m.fabs(L)+self._gamma*self.Jz(**kwargs) + L= numpy.fabs(L)+self._gamma*self.Jz(**kwargs) E+= L**2./2./self._R**2. return (E,L) @@ -277,14 +276,14 @@ return self._rperirap EL= self.calcEL(**kwargs) E, L= EL - if self._vR == 0. and m.fabs(self._vT - vcirc(self._pot,self._R,use_physical=False)) < _EPS: #We are on a circular orbit + if self._vR == 0. and numpy.fabs(self._vT - vcirc(self._pot,self._R,use_physical=False)) < _EPS: #We are on a circular orbit rperi= self._R rap = self._R elif self._vR == 0. and self._vT > vcirc(self._pot,self._R,use_physical=False): #We are exactly at pericenter rperi= self._R if self._gamma != 0.: startsign= _rapRperiAxiEq(self._R+10.**-8.,E,L,self._pot) - startsign/= m.fabs(startsign) + startsign/= numpy.fabs(startsign) else: startsign= 1. rend= _rapRperiAxiFindStart(self._R,E,L,self._pot,rap=True, startsign=startsign) @@ -295,7 +294,7 @@ rap= self._R if self._gamma != 0.: startsign= _rapRperiAxiEq(self._R-10.**-8.,E,L,self._pot) - startsign/= m.fabs(startsign) + startsign/= numpy.fabs(startsign) else: startsign= 1. rstart= _rapRperiAxiFindStart(self._R,E,L,self._pot, startsign=startsign) @@ -307,7 +306,7 @@ else: if self._gamma != 0.: startsign= _rapRperiAxiEq(self._R,E,L,self._pot) - startsign/= m.fabs(startsign) + startsign/= numpy.fabs(startsign) else: startsign= 1. rstart= _rapRperiAxiFindStart(self._R,E,L,self._pot, @@ -366,7 +365,7 @@ def _JRAxiIntegrand(r,E,L,pot): """The J_R integrand""" - return nu.sqrt(2.*(E-potentialAxi(r,pot))-L**2./r**2.) + return numpy.sqrt(2.*(E-potentialAxi(r,pot))-L**2./r**2.) def _TRAxiIntegrandSmall(t,E,L,pot,rperi): #pragma: no cover r= rperi+t**2.#part of the transformation diff -Nru galpy-1.5/galpy/actionAngle/actionAngle_c_ext/actionAngle.h galpy-1.6.0.post0/galpy/actionAngle/actionAngle_c_ext/actionAngle.h --- galpy-1.5/galpy/actionAngle/actionAngle_c_ext/actionAngle.h 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngle_c_ext/actionAngle.h 2020-04-24 19:48:38.000000000 +0000 @@ -13,14 +13,6 @@ #include #include #include "interp_2d.h" -#ifdef _WIN32 -// On Windows, *need* to define this function to allow the package to be imported -#if PY_MAJOR_VERSION >= 3 - PyMODINIT_FUNC PyInit_galpy_actionAngle_c(void); // Python 3 -#else - PyMODINIT_FUNC initgalpy_actionAngle_c(void); // Python 2 -#endif -#endif /* Macro for dealing with potentially unused variables due to OpenMP */ diff -Nru galpy-1.5/galpy/actionAngle/actionAngle_c_ext/actionAngleStaeckel.c galpy-1.6.0.post0/galpy/actionAngle/actionAngle_c_ext/actionAngleStaeckel.c --- galpy-1.5/galpy/actionAngle/actionAngle_c_ext/actionAngleStaeckel.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngle_c_ext/actionAngleStaeckel.c 2020-04-24 19:48:38.000000000 +0000 @@ -33,16 +33,6 @@ // Just do nothing? #define EXPORT #endif -#ifdef _WIN32 -// On Windows, *need* to define this function to allow the package to be imported -#if PY_MAJOR_VERSION >= 3 -PyMODINIT_FUNC PyInit_galpy_actionAngle_c(void) { // Python 3 - return NULL; -} -#else -PyMODINIT_FUNC initgalpy_actionAngle_c(void) {} // Python 2 -#endif -#endif /* Structure Declarations */ diff -Nru galpy-1.5/galpy/actionAngle/actionAngleIsochroneApprox.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleIsochroneApprox.py --- galpy-1.5/galpy/actionAngle/actionAngleIsochroneApprox.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleIsochroneApprox.py 2020-04-24 19:48:38.000000000 +0000 @@ -14,20 +14,19 @@ # actionsFreqsAngles: returns (jr,lz,jz,Or,Op,Oz,ar,ap,az) # ############################################################################### -import math import warnings -import numpy as nu -import numpy.linalg as linalg +import numpy +from numpy import linalg from scipy import optimize -from galpy.potential import dvcircdR, vcirc, _isNonAxi -from galpy.potential.Potential import flatten as flatten_potential +from ..potential import dvcircdR, vcirc, _isNonAxi +from ..potential.Potential import flatten as flatten_potential from .actionAngleIsochrone import actionAngleIsochrone from .actionAngle import actionAngle -from galpy.potential import IsochronePotential, MWPotential -from galpy.util import bovy_plot, galpyWarning -from galpy.util.bovy_conversion import physical_conversion, \ +from ..potential import IsochronePotential, MWPotential +from ..util import bovy_plot, galpyWarning +from ..util.bovy_conversion import physical_conversion, \ potential_physical_input, time_in_Gyr -_TWOPI= 2.*nu.pi +_TWOPI= 2.*numpy.pi _ANGLETOL= 0.02 #tolerance for deciding whether full angle range is covered _APY_LOADED= True try: @@ -108,7 +107,7 @@ /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._tsJ= numpy.linspace(0.,self._tintJ,self._ntintJ) self._integrate_method= kwargs.get('integrate_method','dopr54_c') self._maxn= kwargs.get('maxn',3) self._c= False @@ -152,30 +151,30 @@ z.flatten(), vz.flatten(), phi.flatten()) - jrI= nu.reshape(acfs[0],R.shape)[:,:-1] - jzI= nu.reshape(acfs[2],R.shape)[:,:-1] - anglerI= nu.reshape(acfs[6],R.shape) - anglezI= nu.reshape(acfs[8],R.shape) - if nu.any((nu.fabs(nu.amax(anglerI,axis=1)-_TWOPI) > _ANGLETOL)\ - *(nu.fabs(nu.amin(anglerI,axis=1)) > _ANGLETOL)): #pragma: no cover + jrI= numpy.reshape(acfs[0],R.shape)[:,:-1] + jzI= numpy.reshape(acfs[2],R.shape)[:,:-1] + anglerI= numpy.reshape(acfs[6],R.shape) + anglezI= numpy.reshape(acfs[8],R.shape) + if numpy.any((numpy.fabs(numpy.amax(anglerI,axis=1)-_TWOPI) > _ANGLETOL)\ + *(numpy.fabs(numpy.amin(anglerI,axis=1)) > _ANGLETOL)): #pragma: no cover warnings.warn("Full radial angle range not covered for at least one object; actions are likely not reliable",galpyWarning) - if nu.any((nu.fabs(nu.amax(anglezI,axis=1)-_TWOPI) > _ANGLETOL)\ - *(nu.fabs(nu.amin(anglezI,axis=1)) > _ANGLETOL)): #pragma: no cover + if numpy.any((numpy.fabs(numpy.amax(anglezI,axis=1)-_TWOPI) > _ANGLETOL)\ + *(numpy.fabs(numpy.amin(anglezI,axis=1)) > _ANGLETOL)): #pragma: no cover warnings.warn("Full vertical angle range not covered for at least one object; actions are likely not reliable",galpyWarning) - danglerI= ((nu.roll(anglerI,-1,axis=1)-anglerI) % _TWOPI)[:,:-1] - danglezI= ((nu.roll(anglezI,-1,axis=1)-anglezI) % _TWOPI)[:,:-1] + danglerI= ((numpy.roll(anglerI,-1,axis=1)-anglerI) % _TWOPI)[:,:-1] + danglezI= ((numpy.roll(anglezI,-1,axis=1)-anglezI) % _TWOPI)[:,:-1] if kwargs.get('cumul',False): - sumFunc= nu.cumsum + sumFunc= numpy.cumsum else: - sumFunc= nu.sum + sumFunc= numpy.sum jr= sumFunc(jrI*danglerI,axis=1)/sumFunc(danglerI,axis=1) jz= sumFunc(jzI*danglezI,axis=1)/sumFunc(danglezI,axis=1) if _isNonAxi(self._pot): - lzI= nu.reshape(acfs[1],R.shape)[:,:-1] - anglephiI= nu.reshape(acfs[7],R.shape) - danglephiI= ((nu.roll(anglephiI,-1,axis=1)-anglephiI) % _TWOPI)[:,:-1] - if nu.any((nu.fabs(nu.amax(anglephiI,axis=1)-_TWOPI) > _ANGLETOL)\ - *(nu.fabs(nu.amin(anglephiI,axis=1)) > _ANGLETOL)): #pragma: no cover + lzI= numpy.reshape(acfs[1],R.shape)[:,:-1] + anglephiI= numpy.reshape(acfs[7],R.shape) + danglephiI= ((numpy.roll(anglephiI,-1,axis=1)-anglephiI) % _TWOPI)[:,:-1] + if numpy.any((numpy.fabs(numpy.amax(anglephiI,axis=1)-_TWOPI) > _ANGLETOL)\ + *(numpy.fabs(numpy.amin(anglephiI,axis=1)) > _ANGLETOL)): #pragma: no cover warnings.warn("Full azimuthal angle range not covered for at least one object; actions are likely not reliable",galpyWarning) lz= sumFunc(lzI*danglephiI,axis=1)/sumFunc(danglephiI,axis=1) else: @@ -225,7 +224,7 @@ HISTORY: 2013-09-10 - Written - Bovy (IAS) """ - from galpy.orbit import Orbit + from ..orbit import Orbit _firstFlip= kwargs.get('_firstFlip',False) #If the orbit was already integrated, set ts to the integration times if isinstance(args[0],Orbit) and hasattr(args[0],'orbit') \ @@ -242,7 +241,7 @@ ts= ts.to(units.Gyr).value\ /time_in_Gyr(self._vo,self._ro) else: - ts= nu.empty(R.shape[1]) + ts= numpy.empty(R.shape[1]) ts[self._ntintJ-1:]= self._tsJ ts[:self._ntintJ-1]= -self._tsJ[1:][::-1] maxn= kwargs.get('maxn',self._maxn) @@ -258,40 +257,40 @@ z.flatten(), vz.flatten(), phi.flatten()) - jrI= nu.reshape(acfs[0],R.shape)[:,:-1] - jzI= nu.reshape(acfs[2],R.shape)[:,:-1] - anglerI= nu.reshape(acfs[6],R.shape) - anglezI= nu.reshape(acfs[8],R.shape) - if nu.any((nu.fabs(nu.amax(anglerI,axis=1)-_TWOPI) > _ANGLETOL)\ - *(nu.fabs(nu.amin(anglerI,axis=1)) > _ANGLETOL)): #pragma: no cover + jrI= numpy.reshape(acfs[0],R.shape)[:,:-1] + jzI= numpy.reshape(acfs[2],R.shape)[:,:-1] + anglerI= numpy.reshape(acfs[6],R.shape) + anglezI= numpy.reshape(acfs[8],R.shape) + if numpy.any((numpy.fabs(numpy.amax(anglerI,axis=1)-_TWOPI) > _ANGLETOL)\ + *(numpy.fabs(numpy.amin(anglerI,axis=1)) > _ANGLETOL)): #pragma: no cover warnings.warn("Full radial angle range not covered for at least one object; actions are likely not reliable",galpyWarning) - if nu.any((nu.fabs(nu.amax(anglezI,axis=1)-_TWOPI) > _ANGLETOL)\ - *(nu.fabs(nu.amin(anglezI,axis=1)) > _ANGLETOL)): #pragma: no cover + if numpy.any((numpy.fabs(numpy.amax(anglezI,axis=1)-_TWOPI) > _ANGLETOL)\ + *(numpy.fabs(numpy.amin(anglezI,axis=1)) > _ANGLETOL)): #pragma: no cover warnings.warn("Full vertical angle range not covered for at least one object; actions are likely not reliable",galpyWarning) - danglerI= ((nu.roll(anglerI,-1,axis=1)-anglerI) % _TWOPI)[:,:-1] - danglezI= ((nu.roll(anglezI,-1,axis=1)-anglezI) % _TWOPI)[:,:-1] - jr= nu.sum(jrI*danglerI,axis=1)/nu.sum(danglerI,axis=1) - jz= nu.sum(jzI*danglezI,axis=1)/nu.sum(danglezI,axis=1) + danglerI= ((numpy.roll(anglerI,-1,axis=1)-anglerI) % _TWOPI)[:,:-1] + danglezI= ((numpy.roll(anglezI,-1,axis=1)-anglezI) % _TWOPI)[:,:-1] + jr= numpy.sum(jrI*danglerI,axis=1)/numpy.sum(danglerI,axis=1) + jz= numpy.sum(jzI*danglezI,axis=1)/numpy.sum(danglezI,axis=1) if _isNonAxi(self._pot): #pragma: no cover - lzI= nu.reshape(acfs[1],R.shape)[:,:-1] - anglephiI= nu.reshape(acfs[7],R.shape) - if nu.any((nu.fabs(nu.amax(anglephiI,axis=1)-_TWOPI) > _ANGLETOL)\ - *(nu.fabs(nu.amin(anglephiI,axis=1)) > _ANGLETOL)): #pragma: no cover + lzI= numpy.reshape(acfs[1],R.shape)[:,:-1] + anglephiI= numpy.reshape(acfs[7],R.shape) + if numpy.any((numpy.fabs(numpy.amax(anglephiI,axis=1)-_TWOPI) > _ANGLETOL)\ + *(numpy.fabs(numpy.amin(anglephiI,axis=1)) > _ANGLETOL)): #pragma: no cover warnings.warn("Full azimuthal angle range not covered for at least one object; actions are likely not reliable",galpyWarning) - danglephiI= ((nu.roll(anglephiI,-1,axis=1)-anglephiI) % _TWOPI)[:,:-1] - lz= nu.sum(lzI*danglephiI,axis=1)/nu.sum(danglephiI,axis=1) + danglephiI= ((numpy.roll(anglephiI,-1,axis=1)-anglephiI) % _TWOPI)[:,:-1] + lz= numpy.sum(lzI*danglephiI,axis=1)/numpy.sum(danglephiI,axis=1) else: lz= R[:,len(ts)//2]*vT[:,len(ts)//2] #Now do an 'angle-fit' - angleRT= dePeriod(nu.reshape(acfs[6],R.shape)) - acfs7= nu.reshape(acfs[7],R.shape) - negFreqIndx= nu.median(acfs7-nu.roll(acfs7,1,axis=1),axis=1) < 0. #anglephi is decreasing - anglephiT= nu.empty(acfs7.shape) + angleRT= dePeriod(numpy.reshape(acfs[6],R.shape)) + acfs7= numpy.reshape(acfs[7],R.shape) + negFreqIndx= numpy.median(acfs7-numpy.roll(acfs7,1,axis=1),axis=1) < 0. #anglephi is decreasing + anglephiT= numpy.empty(acfs7.shape) anglephiT[negFreqIndx,:]= dePeriod(_TWOPI-acfs7[negFreqIndx,:]) - negFreqPhi= nu.zeros(R.shape[0],dtype='bool') + negFreqPhi= numpy.zeros(R.shape[0],dtype='bool') negFreqPhi[negFreqIndx]= True anglephiT[True^negFreqIndx,:]= dePeriod(acfs7[True^negFreqIndx,:]) - angleZT= dePeriod(nu.reshape(acfs[8],R.shape)) + angleZT= dePeriod(numpy.reshape(acfs[8],R.shape)) #Write the angle-fit as Y=AX, build A and Y nt= len(ts) no= R.shape[0] @@ -300,20 +299,20 @@ nn= (2*maxn-1)**2*maxn-(maxn-1)*(2*maxn-1)-maxn else: nn= maxn*(2*maxn-1)-maxn - A= nu.zeros((no,nt,2+nn)) + A= numpy.zeros((no,nt,2+nn)) A[:,:,0]= 1. A[:,:,1]= ts #sorting the phi and Z grids this way makes it easy to exclude the origin - phig= list(nu.arange(-maxn+1,maxn,1)) + phig= list(numpy.arange(-maxn+1,maxn,1)) phig.sort(key = lambda x: abs(x)) - phig= nu.array(phig,dtype='int') + phig= numpy.array(phig,dtype='int') if _isNonAxi(self._pot): - grid= nu.meshgrid(nu.arange(maxn),phig,phig) + grid= numpy.meshgrid(numpy.arange(maxn),phig,phig) else: - grid= nu.meshgrid(nu.arange(maxn),phig) + grid= numpy.meshgrid(numpy.arange(maxn),phig) gridR= grid[0].T.flatten()[1:] #remove 0,0,0 gridZ= grid[1].T.flatten()[1:] - mask = nu.ones(len(gridR),dtype=bool) + mask = numpy.ones(len(gridR),dtype=bool) # excludes axis that is not in half-space if _isNonAxi(self._pot): gridphi= grid[2].T.flatten()[1:] @@ -323,32 +322,32 @@ mask[:2*maxn-3:2]= False gridR= gridR[mask] gridZ= gridZ[mask] - tangleR= nu.tile(angleRT.T,(nn,1,1)).T - tgridR= nu.tile(gridR,(no,nt,1)) - tangleZ= nu.tile(angleZT.T,(nn,1,1)).T - tgridZ= nu.tile(gridZ,(no,nt,1)) + tangleR= numpy.tile(angleRT.T,(nn,1,1)).T + tgridR= numpy.tile(gridR,(no,nt,1)) + tangleZ= numpy.tile(angleZT.T,(nn,1,1)).T + tgridZ= numpy.tile(gridZ,(no,nt,1)) if _isNonAxi(self._pot): gridphi= gridphi[mask] - tgridphi= nu.tile(gridphi,(no,nt,1)) - tanglephi= nu.tile(anglephiT.T,(nn,1,1)).T - sinnR= nu.sin(tgridR*tangleR+tgridphi*tanglephi+tgridZ*tangleZ) + tgridphi= numpy.tile(gridphi,(no,nt,1)) + tanglephi= numpy.tile(anglephiT.T,(nn,1,1)).T + sinnR= numpy.sin(tgridR*tangleR+tgridphi*tanglephi+tgridZ*tangleZ) else: - sinnR= nu.sin(tgridR*tangleR+tgridZ*tangleZ) + sinnR= numpy.sin(tgridR*tangleR+tgridZ*tangleZ) A[:,:,2:]= sinnR #Matrix magic - atainv= nu.empty((no,2+nn,2+nn)) - AT= nu.transpose(A,axes=(0,2,1)) + atainv= numpy.empty((no,2+nn,2+nn)) + AT= numpy.transpose(A,axes=(0,2,1)) for ii in range(no): - atainv[ii,:,:,]= linalg.inv(nu.dot(AT[ii,:,:],A[ii,:,:])) - ATAR= nu.sum(AT*nu.transpose(nu.tile(angleRT,(2+nn,1,1)),axes=(1,0,2)),axis=2) - ATAT= nu.sum(AT*nu.transpose(nu.tile(anglephiT,(2+nn,1,1)),axes=(1,0,2)),axis=2) - ATAZ= nu.sum(AT*nu.transpose(nu.tile(angleZT,(2+nn,1,1)),axes=(1,0,2)),axis=2) - angleR= nu.sum(atainv[:,0,:]*ATAR,axis=1) - OmegaR= nu.sum(atainv[:,1,:]*ATAR,axis=1) - anglephi= nu.sum(atainv[:,0,:]*ATAT,axis=1) - Omegaphi= nu.sum(atainv[:,1,:]*ATAT,axis=1) - angleZ= nu.sum(atainv[:,0,:]*ATAZ,axis=1) - OmegaZ= nu.sum(atainv[:,1,:]*ATAZ,axis=1) + atainv[ii,:,:,]= linalg.inv(numpy.dot(AT[ii,:,:],A[ii,:,:])) + ATAR= numpy.sum(AT*numpy.transpose(numpy.tile(angleRT,(2+nn,1,1)),axes=(1,0,2)),axis=2) + ATAT= numpy.sum(AT*numpy.transpose(numpy.tile(anglephiT,(2+nn,1,1)),axes=(1,0,2)),axis=2) + ATAZ= numpy.sum(AT*numpy.transpose(numpy.tile(angleZT,(2+nn,1,1)),axes=(1,0,2)),axis=2) + angleR= numpy.sum(atainv[:,0,:]*ATAR,axis=1) + OmegaR= numpy.sum(atainv[:,1,:]*ATAR,axis=1) + anglephi= numpy.sum(atainv[:,0,:]*ATAT,axis=1) + Omegaphi= numpy.sum(atainv[:,1,:]*ATAT,axis=1) + angleZ= numpy.sum(atainv[:,0,:]*ATAZ,axis=1) + OmegaZ= numpy.sum(atainv[:,1,:]*ATAZ,axis=1) Omegaphi[negFreqIndx]= -Omegaphi[negFreqIndx] anglephi[negFreqIndx]= _TWOPI-anglephi[negFreqIndx] if kwargs.get('_retacfs',False): @@ -403,21 +402,21 @@ vz.flatten(), phi.flatten()) if type == 'jr' or type == 'lz' or type == 'jz': - jrI= nu.reshape(acfs[0],R.shape)[:,:-1] - jzI= nu.reshape(acfs[2],R.shape)[:,:-1] - anglerI= nu.reshape(acfs[6],R.shape) - anglezI= nu.reshape(acfs[8],R.shape) - danglerI= ((nu.roll(anglerI,-1,axis=1)-anglerI) % _TWOPI)[:,:-1] - danglezI= ((nu.roll(anglezI,-1,axis=1)-anglezI) % _TWOPI)[:,:-1] + jrI= numpy.reshape(acfs[0],R.shape)[:,:-1] + jzI= numpy.reshape(acfs[2],R.shape)[:,:-1] + anglerI= numpy.reshape(acfs[6],R.shape) + anglezI= numpy.reshape(acfs[8],R.shape) + danglerI= ((numpy.roll(anglerI,-1,axis=1)-anglerI) % _TWOPI)[:,:-1] + danglezI= ((numpy.roll(anglezI,-1,axis=1)-anglezI) % _TWOPI)[:,:-1] if True: - sumFunc= nu.cumsum + sumFunc= numpy.cumsum jr= sumFunc(jrI*danglerI,axis=1)/sumFunc(danglerI,axis=1) jz= sumFunc(jzI*danglezI,axis=1)/sumFunc(danglezI,axis=1) - lzI= nu.reshape(acfs[1],R.shape)[:,:-1] - anglephiI= nu.reshape(acfs[7],R.shape) - danglephiI= ((nu.roll(anglephiI,-1,axis=1)-anglephiI) % _TWOPI)[:,:-1] + lzI= numpy.reshape(acfs[1],R.shape)[:,:-1] + anglephiI= numpy.reshape(acfs[7],R.shape) + danglephiI= ((numpy.roll(anglephiI,-1,axis=1)-anglephiI) % _TWOPI)[:,:-1] lz= sumFunc(lzI*danglephiI,axis=1)/sumFunc(danglephiI,axis=1) - from galpy.orbit import Orbit + from ..orbit import Orbit if isinstance(args[0],Orbit) and hasattr(args[0],'t'): ts= args[0].t[:-1] else: @@ -439,8 +438,8 @@ xlabel=r'$t$', ylabel=r'$J^A_R / \langle J^A_R \rangle$', clabel=r'$\theta^A_R$', - vmin=0.,vmax=2.*nu.pi, - crange=[0.,2.*nu.pi], + vmin=0.,vmax=2.*numpy.pi, + crange=[0.,2.*numpy.pi], colorbar=True, **kwargs) elif type == 'lz': @@ -458,8 +457,8 @@ xlabel=r'$t$', ylabel=r'$L^A_Z / \langle L^A_Z \rangle$', clabel=r'$\theta^A_\phi$', - vmin=0.,vmax=2.*nu.pi, - crange=[0.,2.*nu.pi], + vmin=0.,vmax=2.*numpy.pi, + crange=[0.,2.*numpy.pi], colorbar=True, **kwargs) elif type == 'jz': @@ -477,39 +476,39 @@ xlabel=r'$t$', ylabel=r'$J^A_Z / \langle J^A_Z \rangle$', clabel=r'$\theta^A_Z$', - vmin=0.,vmax=2.*nu.pi, - crange=[0.,2.*nu.pi], + vmin=0.,vmax=2.*numpy.pi, + crange=[0.,2.*numpy.pi], colorbar=True, **kwargs) else: if deperiod: if 'ar' in type: - angleRT= dePeriod(nu.reshape(acfs[6],R.shape)) + angleRT= dePeriod(numpy.reshape(acfs[6],R.shape)) else: - angleRT= nu.reshape(acfs[6],R.shape) + angleRT= numpy.reshape(acfs[6],R.shape) if 'aphi' in type: - acfs7= nu.reshape(acfs[7],R.shape) - negFreqIndx= nu.median(acfs7-nu.roll(acfs7,1,axis=1),axis=1) < 0. #anglephi is decreasing - anglephiT= nu.empty(acfs7.shape) + acfs7= numpy.reshape(acfs[7],R.shape) + negFreqIndx= numpy.median(acfs7-numpy.roll(acfs7,1,axis=1),axis=1) < 0. #anglephi is decreasing + anglephiT= numpy.empty(acfs7.shape) anglephiT[negFreqIndx,:]= dePeriod(_TWOPI-acfs7[negFreqIndx,:]) - negFreqPhi= nu.zeros(R.shape[0],dtype='bool') + negFreqPhi= numpy.zeros(R.shape[0],dtype='bool') negFreqPhi[negFreqIndx]= True anglephiT[True^negFreqIndx,:]= dePeriod(acfs7[True^negFreqIndx,:]) else: - anglephiT= nu.reshape(acfs[7],R.shape) + anglephiT= numpy.reshape(acfs[7],R.shape) if 'az' in type: - angleZT= dePeriod(nu.reshape(acfs[8],R.shape)) + angleZT= dePeriod(numpy.reshape(acfs[8],R.shape)) else: - angleZT= nu.reshape(acfs[8],R.shape) + angleZT= numpy.reshape(acfs[8],R.shape) xrange= None yrange= None else: - angleRT= nu.reshape(acfs[6],R.shape) - anglephiT= nu.reshape(acfs[7],R.shape) - angleZT= nu.reshape(acfs[8],R.shape) - xrange= [-0.5,2.*nu.pi+0.5] - yrange= [-0.5,2.*nu.pi+0.5] - vmin, vmax= 0.,2.*nu.pi + angleRT= numpy.reshape(acfs[6],R.shape) + anglephiT= numpy.reshape(acfs[7],R.shape) + angleZT= numpy.reshape(acfs[8],R.shape) + xrange= [-0.5,2.*numpy.pi+0.5] + yrange= [-0.5,2.*numpy.pi+0.5] + vmin, vmax= 0.,2.*numpy.pi crange= [vmin,vmax] if type == 'araz': if downsample: @@ -575,7 +574,7 @@ def _parse_args(self,freqsAngles=True,_firstFlip=False,*args): """Helper function to parse the arguments to the __call__ and actionsFreqsAngles functions""" - from galpy.orbit import Orbit + from ..orbit import Orbit RasOrbit= False integrated= True #whether the orbit was already integrated when given if len(args) == 5 or len(args) == 3: #pragma: no cover @@ -628,12 +627,12 @@ integrated= False ntJ= os[0].getOrbit().shape[0] no= len(os) - R= nu.empty((no,ntJ)) - vR= nu.empty((no,ntJ)) - vT= nu.empty((no,ntJ)) - z= nu.zeros((no,ntJ))+10.**-7. #To avoid numpy warnings for - vz= nu.zeros((no,ntJ))+10.**-7. #planarOrbits - phi= nu.empty((no,ntJ)) + R= numpy.empty((no,ntJ)) + vR= numpy.empty((no,ntJ)) + vT= numpy.empty((no,ntJ)) + z= numpy.zeros((no,ntJ))+10.**-7. #To avoid numpy warnings for + vz= numpy.zeros((no,ntJ))+10.**-7. #planarOrbits + phi= numpy.empty((no,ntJ)) for ii in range(len(os)): this_orbit= os[ii].getOrbit() R[ii,:]= this_orbit[:,0] @@ -648,12 +647,12 @@ if freqsAngles and not integrated: #also integrate backwards in time, such that the requested point is not at the edge no= R.shape[0] nt= R.shape[1] - oR= nu.empty((no,2*nt-1)) - ovR= nu.empty((no,2*nt-1)) - ovT= nu.empty((no,2*nt-1)) - oz= nu.zeros((no,2*nt-1))+10.**-7. #To avoid numpy warnings for - ovz= nu.zeros((no,2*nt-1))+10.**-7. #planarOrbits - ophi= nu.empty((no,2*nt-1)) + oR= numpy.empty((no,2*nt-1)) + ovR= numpy.empty((no,2*nt-1)) + ovT= numpy.empty((no,2*nt-1)) + oz= numpy.zeros((no,2*nt-1))+10.**-7. #To avoid numpy warnings for + ovz= numpy.zeros((no,2*nt-1))+10.**-7. #planarOrbits + ophi= numpy.empty((no,2*nt-1)) if _firstFlip: oR[:,:nt]= R[:,::-1] ovR[:,:nt]= vR[:,::-1] @@ -738,28 +737,28 @@ """ if pot is None: #pragma: no cover raise IOError("pot= needs to be set to a Potential instance or list thereof") - if isinstance(R,nu.ndarray): + if isinstance(R,numpy.ndarray): if phi is None: phi= [None for r in R] - bs= nu.array([estimateBIsochrone(pot,R[ii],z[ii],phi=phi[ii], + bs= numpy.array([estimateBIsochrone(pot,R[ii],z[ii],phi=phi[ii], use_physical=False) for ii in range(len(R))]) - return nu.array([nu.amin(bs[True^nu.isnan(bs)]), - nu.median(bs[True^nu.isnan(bs)]), - nu.amax(bs[True^nu.isnan(bs)])]) + return numpy.array([numpy.amin(bs[True^numpy.isnan(bs)]), + numpy.median(bs[True^numpy.isnan(bs)]), + numpy.amax(bs[True^numpy.isnan(bs)])]) else: r2= R**2.+z**2 - r= math.sqrt(r2) + r= numpy.sqrt(r2) dlvcdlr= dvcircdR(pot,r,phi=phi,use_physical=False)/vcirc(pot,r,phi=phi,use_physical=False)*r try: - b= optimize.brentq(lambda x: dlvcdlr-(x/math.sqrt(r2+x**2.)-0.5*r2/(r2+x**2.)), + b= optimize.brentq(lambda x: dlvcdlr-(x/numpy.sqrt(r2+x**2.)-0.5*r2/(r2+x**2.)), 0.01,100.) except: #pragma: no cover - b= nu.nan + b= numpy.nan return b def dePeriod(arr): """make an array of periodic angles increase linearly""" - diff= arr-nu.roll(arr,1,axis=1) + diff= arr-numpy.roll(arr,1,axis=1) w= diff < -6. - addto= nu.cumsum(w.astype(int),axis=1) + addto= numpy.cumsum(w.astype(int),axis=1) return arr+_TWOPI*addto diff -Nru galpy-1.5/galpy/actionAngle/actionAngleIsochrone.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleIsochrone.py --- galpy-1.5/galpy/actionAngle/actionAngleIsochrone.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleIsochrone.py 2020-04-24 19:48:38.000000000 +0000 @@ -13,10 +13,10 @@ ############################################################################### import copy import warnings -import numpy as nu +import numpy from .actionAngle import actionAngle -from galpy.potential import IsochronePotential -from galpy.util import galpyWarning +from ..potential import IsochronePotential +from ..util import galpyWarning _APY_LOADED= True try: from astropy import units @@ -65,7 +65,7 @@ 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.) + rb= numpy.sqrt(self.b**2.+1.) self.amp= (self.b+rb)**2.*rb self._c= False ext_loaded= False @@ -111,11 +111,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) if self._c: #pragma: no cover pass else: @@ -124,12 +124,12 @@ 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) + L= numpy.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))) + Jz= L-numpy.fabs(Lz) + Jr= self.amp/numpy.sqrt(-2.*E)\ + -0.5*(L+numpy.sqrt((L2+4.*self.amp*self.b))) return (Jr,Jphi,Jz) def _actionsFreqs(self,*args,**kwargs): @@ -161,11 +161,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) if self._c: #pragma: no cover pass else: @@ -174,15 +174,15 @@ 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) + L= numpy.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))) + Jz= L-numpy.fabs(Lz) + Jr= self.amp/numpy.sqrt(-2.*E)\ + -0.5*(L+numpy.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 + Omegaz= 0.5*(1.+L/numpy.sqrt(L2+4.*self.amp*self.b))*Omegar Omegaphi= copy.copy(Omegaz) indx= Lz < 0. Omegaphi[indx]*= -1. @@ -218,12 +218,12 @@ vz= self._eval_vz phi= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) + phi= numpy.array([phi]) if self._c: #pragma: no cover pass else: @@ -232,71 +232,71 @@ 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) + L= numpy.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))) + Jz= L-numpy.fabs(Lz) + Jr= self.amp/numpy.sqrt(-2.*E)\ + -0.5*(L+numpy.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 + Omegaz= 0.5*(1.+L/numpy.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) + e= numpy.sqrt(e2) if self.b == 0.: - coseta= 1/e*(1.-nu.sqrt(R**2.+z**2.)/c) + coseta= 1/e*(1.-numpy.sqrt(R**2.+z**2.)/c) else: - s= 1.+nu.sqrt(1.+(R**2.+z**2.)/self.b**2.) + s= 1.+numpy.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.) + eta= numpy.arccos(coseta) + costheta= z/numpy.sqrt(R**2.+z**2.) + sintheta= R/numpy.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)) + eta[vrindx]= 2.*numpy.pi-eta[vrindx] + angler= eta-e*c/(c+self.b)*numpy.sin(eta) + tan11= numpy.arctan(numpy.sqrt((1.+e)/(1.-e))*numpy.tan(0.5*eta)) + tan12= numpy.arctan(numpy.sqrt((1.+e+2.*self.b/c)/(1.-e+2.*self.b/c))*numpy.tan(0.5*eta)) vzindx= (-vz*sintheta+vR*costheta) > 0. - tan11[tan11 < 0.]+= nu.pi - tan12[tan12 < 0.]+= nu.pi + tan11[tan11 < 0.]+= numpy.pi + tan12[tan12 < 0.]+= numpy.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) + i= numpy.arccos(Lz/L) + sinpsi= costheta/numpy.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) + psi= numpy.arcsin(sinpsi) + psi[vzindx]= numpy.pi-psi[vzindx] + psi= psi % (2.*numpy.pi) anglez= psi+Omegaz/Omegar*angler\ - -tan11-1./nu.sqrt(1.+4*self.amp*self.b/L2)*tan12 - sinu= z/R/nu.tan(i) + -tan11-1./numpy.sqrt(1.+4*self.amp*self.b/L2)*tan12 + sinu= z/R/numpy.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] + u= numpy.arcsin(sinu) + u[vzindx]= numpy.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) + angler= angler % (2.*numpy.pi) + anglephi= anglephi % (2.*numpy.pi) + anglez= anglez % (2.*numpy.pi) return (Jr,Jphi,Jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) def _EccZmaxRperiRap(self,*args,**kwargs): @@ -328,11 +328,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) if self._c: #pragma: no cover pass else: @@ -345,15 +345,15 @@ warnings.warn("zmax for point-mass (b=0) isochrone potential is only approximate, because it assumes that zmax is attained at rap, which is not necessarily the case",galpyWarning) a= -self.amp/2./E me2= L2/self.amp/a - e= nu.sqrt(1.-me2) + e= numpy.sqrt(1.-me2) rperi= a*(1.-e) rap= a*(1.+e) else: smin= 0.5*((2.*E-self.amp/self.b)\ - +nu.sqrt((2.*E-self.amp/self.b)**2. + +numpy.sqrt((2.*E-self.amp/self.b)**2. +2.*E*(4.*self.amp/self.b+L2/self.b**2.)))/E smax= 2.-self.amp/E/self.b-smin - rperi= smin*nu.sqrt(1.-2./smin)*self.b - rap= smax*nu.sqrt(1.-2./smax)*self.b - return ((rap-rperi)/(rap+rperi),rap*nu.sqrt(1.-Lz**2./L2), + rperi= smin*numpy.sqrt(1.-2./smin)*self.b + rap= smax*numpy.sqrt(1.-2./smax)*self.b + return ((rap-rperi)/(rap+rperi),rap*numpy.sqrt(1.-Lz**2./L2), rperi,rap) diff -Nru galpy-1.5/galpy/actionAngle/actionAngle.py galpy-1.6.0.post0/galpy/actionAngle/actionAngle.py --- galpy-1.5/galpy/actionAngle/actionAngle.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngle.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,11 +1,10 @@ from six import with_metaclass import types import copy -import math as m import numpy -from galpy.util import config -from galpy.util.bovy_conversion import physical_conversion_actionAngle, \ - actionAngle_physical_input +from ..util import config +from ..util.bovy_conversion import physical_conversion_actionAngle, \ + actionAngle_physical_input, physical_compatible _APY_LOADED= True try: from astropy import units @@ -71,26 +70,12 @@ def _check_consistent_units(self): """Internal function to check that the set of units for this object is consistent with that for the potential""" - if isinstance(self._pot,list): - if self._roSet and self._pot[0]._roSet: - assert m.fabs(self._ro-self._pot[0]._ro) < 10.**-10., 'Physical conversion for the actionAngle object is not consistent with that of the Potential given to it' - if self._voSet and self._pot[0]._voSet: - assert m.fabs(self._vo-self._pot[0]._vo) < 10.**-10., 'Physical conversion for the actionAngle object is not consistent with that of the Potential given to it' - else: - if self._roSet and self._pot._roSet: - assert m.fabs(self._ro-self._pot._ro) < 10.**-10., 'Physical conversion for the actionAngle object is not consistent with that of the Potential given to it' - if self._voSet and self._pot._voSet: - assert m.fabs(self._vo-self._pot._vo) < 10.**-10., 'Physical conversion for the actionAngle object is not consistent with that of the Potential given to it' - return None + assert physical_compatible(self,self._pot), 'Physical conversion for the actionAngle object is not consistent with that of the Potential given to it' def _check_consistent_units_orbitInput(self,orb): """Internal function to check that the set of units for this object is consistent with that for an input orbit""" - if self._roSet and orb._roSet: - assert m.fabs(self._ro-orb._ro) < 10.**-10., 'Physical conversion for the actionAngle object is not consistent with that of the Orbit given to it' - if self._voSet and orb._voSet: - assert m.fabs(self._vo-orb._vo) < 10.**-10., 'Physical conversion for the actionAngle object is not consistent with that of the Orbit given to it' - return None - + assert physical_compatible(self,orb), 'Physical conversion for the actionAngle object is not consistent with that of the Orbit given to it' + def turn_physical_off(self): """ NAME: @@ -142,14 +127,16 @@ 2016-06-05 - Written - Bovy (UofT) + 2020-04-22 - Don't turn on a parameter when it is False - Bovy (UofT) + """ - self._roSet= True - self._voSet= True - if not ro is None: + if not ro is False: self._roSet= True + if not vo is False: self._voSet= True + if not ro is None and ro: if _APY_LOADED and isinstance(ro,units.Quantity): ro= ro.to(units.kpc).value self._ro= ro - if not vo is None: + if not vo is None and vo: if _APY_LOADED and isinstance(vo,units.Quantity): vo= vo.to(units.km/units.s).value self._vo= vo diff -Nru galpy-1.5/galpy/actionAngle/actionAngleSpherical.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleSpherical.py --- galpy-1.5/galpy/actionAngle/actionAngleSpherical.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleSpherical.py 2020-04-24 19:48:38.000000000 +0000 @@ -10,13 +10,12 @@ # ############################################################################### import copy -import math as m -import numpy as nu +import numpy from scipy import integrate -from galpy.potential import epifreq, omegac, _dim -from galpy.potential.Potential import _evaluatePotentials -from galpy.potential.Potential import flatten as flatten_potential -from .actionAngle import * +from ..potential import epifreq, omegac, _dim +from ..potential.Potential import _evaluatePotentials +from ..potential.Potential import flatten as flatten_potential +from .actionAngle import actionAngle from .actionAngleAxi import actionAngleAxi, potentialAxi class actionAngleSpherical(actionAngle): """Action-angle formalism for spherical potentials""" @@ -103,11 +102,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) if self._c: #pragma: no cover pass else: @@ -117,13 +116,13 @@ L2= Lx*Lx+Ly*Ly+Lz*Lz E= _evaluatePotentials(self._pot,R,z)\ +vR**2./2.+vT**2./2.+vz**2./2. - L= nu.sqrt(L2) + L= numpy.sqrt(L2) #Actions Jphi= Lz - Jz= L-nu.fabs(Lz) + Jz= L-numpy.fabs(Lz) #Jr requires some more work #Set up an actionAngleAxi object for EL and rap/rperi calculations - axiR= nu.sqrt(R**2.+z**2.) + axiR= numpy.sqrt(R**2.+z**2.) axivT= L/axiR axivR= (R*vR+z*vz)/axiR Jr= [] @@ -134,7 +133,7 @@ EL= axiaA.calcEL() E, L= EL Jr.append(self._calc_jr(rperi,rap,E,L,fixed_quad,**kwargs)) - return (nu.array(Jr),Jphi,Jz) + return (numpy.array(Jr),Jphi,Jz) def _actionsFreqs(self,*args,**kwargs): """ @@ -168,11 +167,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) if self._c: #pragma: no cover pass else: @@ -181,13 +180,13 @@ Ly= z*vR-R*vz L2= Lx*Lx+Ly*Ly+Lz*Lz E= _evaluatePotentials(self._pot,R,z)+vR**2./2.+vT**2./2.+vz**2./2. - L= nu.sqrt(L2) + L= numpy.sqrt(L2) #Actions Jphi= Lz - Jz= L-nu.fabs(Lz) + Jz= L-numpy.fabs(Lz) #Jr requires some more work #Set up an actionAngleAxi object for EL and rap/rperi calculations - axiR= nu.sqrt(R**2.+z**2.) + axiR= numpy.sqrt(R**2.+z**2.) axivT= L/axiR axivR= (R*vR+z*vz)/axiR Jr= [] @@ -205,13 +204,13 @@ Or.append(epifreq(self._pot,axiR[ii],use_physical=False)) Op.append(omegac(self._pot,axiR[ii],use_physical=False)) continue - Rmean= m.exp((m.log(rperi)+m.log(rap))/2.) + Rmean= numpy.exp((numpy.log(rperi)+numpy.log(rap))/2.) Or.append(self._calc_or(Rmean,rperi,rap,E,L,fixed_quad,**kwargs)) Op.append(self._calc_op(Or[-1],Rmean,rperi,rap,E,L,fixed_quad,**kwargs)) - Op= nu.array(Op) + Op= numpy.array(Op) Oz= copy.copy(Op) Op[vT < 0.]*= -1. - return (nu.array(Jr),Jphi,Jz,nu.array(Or),Op,Oz) + return (numpy.array(Jr),Jphi,Jz,numpy.array(Or),Op,Oz) def _actionsFreqsAngles(self,*args,**kwargs): """ @@ -247,12 +246,12 @@ vz= self._eval_vz phi= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) + phi= numpy.array([phi]) if self._c: #pragma: no cover pass else: @@ -261,13 +260,13 @@ Ly= z*vR-R*vz L2= Lx*Lx+Ly*Ly+Lz*Lz E= _evaluatePotentials(self._pot,R,z)+vR**2./2.+vT**2./2.+vz**2./2. - L= nu.sqrt(L2) + L= numpy.sqrt(L2) #Actions Jphi= Lz - Jz= L-nu.fabs(Lz) + Jz= L-numpy.fabs(Lz) #Jr requires some more work #Set up an actionAngleAxi object for EL and rap/rperi calculations - axiR= nu.sqrt(R**2.+z**2.) + axiR= numpy.sqrt(R**2.+z**2.) axivT= L/axiR #these are really spherical coords, called axi bc they go in actionAngleAxi axivR= (R*vR+z*vz)/axiR axivz= (z*vR-R*vz)/axiR @@ -286,7 +285,7 @@ E, L= EL Jr.append(self._calc_jr(rperi,rap,E,L,fixed_quad,**kwargs)) #Radial period - Rmean= m.exp((m.log(rperi)+m.log(rap))/2.) + Rmean= numpy.exp((numpy.log(rperi)+numpy.log(rap))/2.) if Jr[-1] < 10.**-9.: #Circular orbit Or.append(epifreq(self._pot,axiR[ii],use_physical=False)) Op.append(omegac(self._pot,axiR[ii],use_physical=False)) @@ -301,18 +300,18 @@ Rmean,rperi,rap,E,L,Lz[ii], axivR[ii],axivz[ii], fixed_quad,**kwargs)) - Op= nu.array(Op) + Op= numpy.array(Op) Oz= copy.copy(Op) Op[vT < 0.]*= -1. ap= copy.copy(asc) - ar= nu.array(ar) - az= nu.array(az) + ar= numpy.array(ar) + az= numpy.array(az) ap[vT < 0.]-= az[vT < 0.] ap[vT >= 0.]+= az[vT >= 0.] - ar= ar % (2.*nu.pi) - ap= ap % (2.*nu.pi) - az= az % (2.*nu.pi) - return (nu.array(Jr),Jphi,Jz,nu.array(Or),Op,Oz, + ar= ar % (2.*numpy.pi) + ap= ap % (2.*numpy.pi) + az= az % (2.*numpy.pi) + return (numpy.array(Jr),Jphi,Jz,numpy.array(Or),Op,Oz, ar,ap,az) def _EccZmaxRperiRap(self,*args,**kwargs): @@ -344,11 +343,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) if self._c: #pragma: no cover pass else: @@ -356,9 +355,9 @@ Lx= -z*vT Ly= z*vR-R*vz L2= Lx*Lx+Ly*Ly+Lz*Lz - L= nu.sqrt(L2) + L= numpy.sqrt(L2) #Set up an actionAngleAxi object for EL and rap/rperi calculations - axiR= nu.sqrt(R**2.+z**2.) + axiR= numpy.sqrt(R**2.+z**2.) axivT= L/axiR axivR= (R*vR+z*vz)/axiR rperi, rap= [], [] @@ -368,9 +367,9 @@ trperi,trap= axiaA.calcRapRperi() rperi.append(trperi) rap.append(trap) - rperi= nu.array(rperi) - rap= nu.array(rap) - return ((rap-rperi)/(rap+rperi),rap*nu.sqrt(1.-Lz**2./L2), + rperi= numpy.array(rperi) + rap= numpy.array(rap) + return ((rap-rperi)/(rap+rperi),rap*numpy.sqrt(1.-Lz**2./L2), rperi,rap) def _calc_jr(self,rperi,rap,E,L,fixed_quad,**kwargs): @@ -379,139 +378,139 @@ rperi,rap, args=(E,L,self._2dpot), n=10, - **kwargs)[0]/nu.pi + **kwargs)[0]/numpy.pi else: - return (nu.array(integrate.quad(_JrSphericalIntegrand, + return (numpy.array(integrate.quad(_JrSphericalIntegrand, rperi,rap, args=(E,L,self._2dpot), - **kwargs)))[0]/nu.pi + **kwargs)))[0]/numpy.pi def _calc_or(self,Rmean,rperi,rap,E,L,fixed_quad,**kwargs): Tr= 0. if Rmean > rperi and not fixed_quad: - Tr+= nu.array(integrate.quadrature(_TrSphericalIntegrandSmall, - 0.,m.sqrt(Rmean-rperi), + Tr+= numpy.array(integrate.quadrature(_TrSphericalIntegrandSmall, + 0.,numpy.sqrt(Rmean-rperi), args=(E,L,self._2dpot, rperi), **kwargs))[0] elif Rmean > rperi and fixed_quad: Tr+= integrate.fixed_quad(_TrSphericalIntegrandSmall, - 0.,m.sqrt(Rmean-rperi), + 0.,numpy.sqrt(Rmean-rperi), args=(E,L,self._2dpot, rperi), n=10,**kwargs)[0] if Rmean < rap and not fixed_quad: - Tr+= nu.array(integrate.quadrature(_TrSphericalIntegrandLarge, - 0.,m.sqrt(rap-Rmean), + Tr+= numpy.array(integrate.quadrature(_TrSphericalIntegrandLarge, + 0.,numpy.sqrt(rap-Rmean), args=(E,L,self._2dpot, rap), **kwargs))[0] elif Rmean < rap and fixed_quad: Tr+= integrate.fixed_quad(_TrSphericalIntegrandLarge, - 0.,m.sqrt(rap-Rmean), + 0.,numpy.sqrt(rap-Rmean), args=(E,L,self._2dpot, rap), n=10,**kwargs)[0] Tr= 2.*Tr - return 2.*nu.pi/Tr + return 2.*numpy.pi/Tr def _calc_op(self,Or,Rmean,rperi,rap,E,L,fixed_quad,**kwargs): #Azimuthal period I= 0. if Rmean > rperi and not fixed_quad: - I+= nu.array(integrate.quadrature(_ISphericalIntegrandSmall, - 0.,m.sqrt(Rmean-rperi), + I+= numpy.array(integrate.quadrature(_ISphericalIntegrandSmall, + 0.,numpy.sqrt(Rmean-rperi), args=(E,L,self._2dpot, rperi), **kwargs))[0] elif Rmean > rperi and fixed_quad: I+= integrate.fixed_quad(_ISphericalIntegrandSmall, - 0.,m.sqrt(Rmean-rperi), + 0.,numpy.sqrt(Rmean-rperi), args=(E,L,self._2dpot,rperi), n=10,**kwargs)[0] if Rmean < rap and not fixed_quad: - I+= nu.array(integrate.quadrature(_ISphericalIntegrandLarge, - 0.,m.sqrt(rap-Rmean), + I+= numpy.array(integrate.quadrature(_ISphericalIntegrandLarge, + 0.,numpy.sqrt(rap-Rmean), args=(E,L,self._2dpot, rap), **kwargs))[0] elif Rmean < rap and fixed_quad: I+= integrate.fixed_quad(_ISphericalIntegrandLarge, - 0.,m.sqrt(rap-Rmean), + 0.,numpy.sqrt(rap-Rmean), args=(E,L,self._2dpot,rap), n=10,**kwargs)[0] I*= 2*L - return I*Or/2./nu.pi + return I*Or/2./numpy.pi def _calc_long_asc(self,z,R,axivz,phi,Lz,L): - i= nu.arccos(Lz/L) - sinu= z/R/nu.tan(i) + i= numpy.arccos(Lz/L) + sinu= z/R/numpy.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= numpy.arcsin(sinu) vzindx= axivz > 0. - u[vzindx]= nu.pi-u[vzindx] + u[vzindx]= numpy.pi-u[vzindx] return phi-u def _calc_angler(self,Or,r,Rmean,rperi,rap,E,L,vr,fixed_quad,**kwargs): if r < Rmean: if r > rperi and not fixed_quad: wr= Or*integrate.quadrature(_TrSphericalIntegrandSmall, - 0.,m.sqrt(r-rperi), + 0.,numpy.sqrt(r-rperi), args=(E,L,self._2dpot,rperi), **kwargs)[0] elif r > rperi and fixed_quad: wr= Or*integrate.fixed_quad(_TrSphericalIntegrandSmall, - 0.,m.sqrt(r-rperi), + 0.,numpy.sqrt(r-rperi), args=(E,L,self._2dpot,rperi), n=10,**kwargs)[0] else: wr= 0. - if vr < 0.: wr= 2*m.pi-wr + if vr < 0.: wr= 2*numpy.pi-wr else: if r < rap and not fixed_quad: wr= Or*integrate.quadrature(_TrSphericalIntegrandLarge, - 0.,m.sqrt(rap-r), + 0.,numpy.sqrt(rap-r), args=(E,L,self._2dpot,rap), **kwargs)[0] elif r < rap and fixed_quad: wr= Or*integrate.fixed_quad(_TrSphericalIntegrandLarge, - 0.,m.sqrt(rap-r), + 0.,numpy.sqrt(rap-r), args=(E,L,self._2dpot,rap), n=10,**kwargs)[0] else: - wr= m.pi + wr= numpy.pi if vr < 0.: - wr= m.pi+wr + wr= numpy.pi+wr else: - wr= m.pi-wr + wr= numpy.pi-wr return wr def _calc_anglez(self,Or,Op,ar,z,r,Rmean,rperi,rap,E,L,Lz,vr,axivz, fixed_quad,**kwargs): #First calculate psi - i= nu.arccos(Lz/L) - sinpsi= z/r/nu.sin(i) + i= numpy.arccos(Lz/L) + sinpsi= z/r/numpy.sin(i) if sinpsi > 1. and sinpsi < (1.+10.**-7.): sinpsi= 1. if sinpsi < -1. and sinpsi > (-1.-10.**-7.): sinpsi= -1. - psi= nu.arcsin(sinpsi) - if axivz > 0.: psi= nu.pi-psi - psi= psi % (2.*nu.pi) + psi= numpy.arcsin(sinpsi) + if axivz > 0.: psi= numpy.pi-psi + psi= psi % (2.*numpy.pi) #Calculate dSr/dL - dpsi= Op/Or*2.*nu.pi #this is the full I integral + dpsi= Op/Or*2.*numpy.pi #this is the full I integral if r < Rmean: if not fixed_quad: wz= L*integrate.quadrature(_ISphericalIntegrandSmall, - 0.,m.sqrt(r-rperi), + 0.,numpy.sqrt(r-rperi), args=(E,L,self._2dpot, rperi), **kwargs)[0] elif fixed_quad: wz= L*integrate.fixed_quad(_ISphericalIntegrandSmall, - 0.,m.sqrt(r-rperi), + 0.,numpy.sqrt(r-rperi), args=(E,L,self._2dpot, rperi), n=10,**kwargs)[0] @@ -519,13 +518,13 @@ else: if not fixed_quad: wz= L*integrate.quadrature(_ISphericalIntegrandLarge, - 0.,m.sqrt(rap-r), + 0.,numpy.sqrt(rap-r), args=(E,L,self._2dpot, rap), **kwargs)[0] elif fixed_quad: wz= L*integrate.fixed_quad(_ISphericalIntegrandLarge, - 0.,m.sqrt(rap-r), + 0.,numpy.sqrt(rap-r), args=(E,L,self._2dpot, rap), n=10,**kwargs)[0] @@ -539,7 +538,7 @@ def _JrSphericalIntegrand(r,E,L,pot): """The J_r integrand""" - return nu.sqrt(2.*(E-potentialAxi(r,pot))-L**2./r**2.) + return numpy.sqrt(2.*(E-potentialAxi(r,pot))-L**2./r**2.) def _TrSphericalIntegrandSmall(t,E,L,pot,rperi): r= rperi+t**2.#part of the transformation diff -Nru galpy-1.5/galpy/actionAngle/actionAngleStaeckel_c.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleStaeckel_c.py --- galpy-1.5/galpy/actionAngle/actionAngleStaeckel_c.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleStaeckel_c.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,40 +1,11 @@ -import os -import sys -import distutils.sysconfig as sysconfig -import warnings import ctypes import ctypes.util import numpy from numpy.ctypeslib import ndpointer -from galpy.util import galpyWarning -from galpy.util import bovy_coords -#Find and load the library -_lib= None -outerr= None -PY3= sys.version > '3' -if PY3: - _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') -else: #pragma: no cover - _ext_suffix= '.so' -for path in sys.path: - try: - _lib = ctypes.CDLL(os.path.join(path,'galpy_actionAngle_c%s' % _ext_suffix)) - except OSError as e: - if os.path.exists(os.path.join(path,'galpy_actionAngle_c%s' % _ext_suffix)): #pragma: no cover - outerr= e - _lib = None - else: - break -if _lib is None: #pragma: no cover - if not outerr is None: - warnings.warn("actionAngleStaeckel_c extension module not loaded, because of error '%s' " % outerr, - galpyWarning) - else: - warnings.warn("actionAngleStaeckel_c extension module not loaded, because galpy_actionAngle_c%s image was not found" % _ext_suffix, - galpyWarning) - _ext_loaded= False -else: - _ext_loaded= True +from ..util import bovy_coords +from ..util import _load_extension_libs + +_lib, _ext_loaded= _load_extension_libs.load_libgalpy() def actionAngleStaeckel_c(pot,delta,R,vR,vT,z,vz,u0=None,order=10): """ @@ -58,7 +29,7 @@ if u0 is None: u0, dummy= bovy_coords.Rz_to_uv(R,z,delta=numpy.atleast_1d(delta)) #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Parse delta @@ -155,7 +126,7 @@ 2012-12-03 - Written - Bovy (IAS) """ #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Set up result arrays @@ -231,7 +202,7 @@ if u0 is None: u0, dummy= bovy_coords.Rz_to_uv(R,z,delta=numpy.atleast_1d(delta)) #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Parse delta @@ -347,7 +318,7 @@ if u0 is None: u0, dummy= bovy_coords.Rz_to_uv(R,z,delta=numpy.atleast_1d(delta)) #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Parse delta @@ -477,7 +448,7 @@ if u0 is None: u0, dummy= bovy_coords.Rz_to_uv(R,z,delta=numpy.atleast_1d(delta)) #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Parse delta diff -Nru galpy-1.5/galpy/actionAngle/actionAngleStaeckelGrid.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleStaeckelGrid.py --- galpy-1.5/galpy/actionAngle/actionAngleStaeckelGrid.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleStaeckelGrid.py 2020-04-24 19:48:38.000000000 +0000 @@ -16,12 +16,10 @@ from .actionAngle import actionAngle from . import actionAngleStaeckel_c from .actionAngleStaeckel_c import _ext_loaded as ext_loaded -import galpy.potential -from galpy.potential.Potential import _evaluatePotentials -from galpy.potential.Potential import flatten as flatten_potential -from galpy.util import multi, bovy_coords -from galpy.util.bovy_conversion import physical_conversion_actionAngle, \ - actionAngle_physical_input +from .. import potential +from ..potential.Potential import _evaluatePotentials +from ..potential.Potential import flatten as flatten_potential +from ..util import multi, bovy_coords _PRINTOUTSIDEGRID= False _APY_LOADED= True try: @@ -89,13 +87,12 @@ self._Lzmin= 0.01 self._Lzs= numpy.linspace(self._Lzmin, self._Rmax\ - *galpy.potential.vcirc(self._pot, - self._Rmax), + *potential.vcirc(self._pot,self._Rmax), nLz) self._Lzmax= self._Lzs[-1] self._nLz= nLz #Calculate E_c(R=RL), energy of circular orbit - self._RL= numpy.array([galpy.potential.rl(self._pot,l) for l in self._Lzs]) + self._RL= numpy.array([potential.rl(self._pot,l) for l in self._Lzs]) self._RLInterp= interpolate.InterpolatedUnivariateSpline(self._Lzs, self._RL,k=3) self._ERL= _evaluatePotentials(self._pot,self._RL, @@ -106,7 +103,7 @@ numpy.log(-(self._ERL-self._ERLmax)),k=3) self._Ramax= 200./8. self._ERa= _evaluatePotentials(self._pot,self._Ramax,0.) +self._Lzs**2./2./self._Ramax**2. - #self._EEsc= numpy.array([self._ERL[ii]+galpy.potential.vesc(self._pot,self._RL[ii])**2./4. for ii in range(nLz)]) + #self._EEsc= numpy.array([self._ERL[ii]+potential.vesc(self._pot,self._RL[ii])**2./4. for ii in range(nLz)]) self._ERamax= numpy.amax(self._ERa)+1. self._ERaInterp= interpolate.InterpolatedUnivariateSpline(self._Lzs, numpy.log(-(self._ERa-self._ERamax)),k=3) @@ -125,7 +122,7 @@ thisERa= (numpy.tile(self._ERa,(nE,1)).T).flatten() thisy= (numpy.tile(y,(nLz,1))).flatten() thisE= _invEfunc(_Efunc(thisERa,thisERL)+thisy*(_Efunc(thisERL,thisERL)-_Efunc(thisERa,thisERL)),thisERL) - if isinstance(self._pot,galpy.potential.interpRZPotential) and hasattr(self._pot,'_origPot'): + if isinstance(self._pot,potential.interpRZPotential) and hasattr(self._pot,'_origPot'): u0pot= self._pot._origPot else: u0pot= self._pot @@ -168,7 +165,7 @@ thisLzs/thisR, #vT numpy.zeros(len(thisR)), #z thisv*numpy.sin(thispsi)) #vz - if isinstance(self._pot,galpy.potential.interpRZPotential) and hasattr(self._pot,'_origPot'): + if isinstance(self._pot,potential.interpRZPotential) and hasattr(self._pot,'_origPot'): #Interpolated potentials have problems with extreme orbits indx= (mjr == 9999.99) indx+= (mjz == 9999.99) diff -Nru galpy-1.5/galpy/actionAngle/actionAngleStaeckel.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleStaeckel.py --- galpy-1.5/galpy/actionAngle/actionAngleStaeckel.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleStaeckel.py 2020-04-24 19:48:38.000000000 +0000 @@ -12,22 +12,21 @@ ############################################################################### import copy import warnings -import numpy as nu +import numpy from scipy import optimize, integrate -from galpy.potential import evaluateR2derivs, evaluatez2derivs, \ +from ..potential import evaluateR2derivs, evaluatez2derivs, \ evaluateRzderivs, epifreq, omegac, verticalfreq, MWPotential -from galpy.potential.Potential import _evaluatePotentials, \ +from ..potential.Potential import _evaluatePotentials, \ _evaluateRforces, _evaluatezforces -from galpy.potential.Potential import flatten as flatten_potential -from galpy.util import bovy_coords #for prolate confocal transforms -from galpy.util import galpyWarning -from galpy.util.bovy_conversion import physical_conversion, \ - potential_physical_input, physical_conversion_actionAngle, \ - actionAngle_physical_input +from ..potential.Potential import flatten as flatten_potential +from ..util import bovy_coords #for prolate confocal transforms +from ..util import galpyWarning +from ..util.bovy_conversion import physical_conversion, \ + potential_physical_input from .actionAngle import actionAngle, UnboundError from . import actionAngleStaeckel_c from .actionAngleStaeckel_c import _ext_loaded as ext_loaded -from galpy.potential.Potential import _check_c +from ..potential.Potential import _check_c _APY_LOADED= True try: from astropy import units @@ -130,11 +129,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) 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): @@ -142,9 +141,9 @@ if self._useu0: #First calculate u0 if 'u0' in kwargs: - u0= nu.asarray(kwargs['u0']) + u0= numpy.asarray(kwargs['u0']) else: - E= nu.array([_evaluatePotentials(self._pot,R[ii],z[ii]) + E= numpy.array([_evaluatePotentials(self._pot,R[ii],z[ii]) +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,delta)[0] @@ -162,15 +161,15 @@ warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) kwargs.pop('c',None) if len(R) > 1: - ojr= nu.zeros((len(R))) - olz= nu.zeros((len(R))) - ojz= nu.zeros((len(R))) + ojr= numpy.zeros((len(R))) + olz= numpy.zeros((len(R))) + ojz= numpy.zeros((len(R))) for ii in range(len(R)): targs= (R[ii],vR[ii],vT[ii],z[ii],vz[ii]) tkwargs= copy.copy(kwargs) try: tkwargs['delta']= delta[ii] - except TypeError: + except (TypeError,IndexError): tkwargs['delta']= delta tjr,tlz,tjz= self(*targs,**tkwargs) ojr[ii]= tjr @@ -182,9 +181,9 @@ aASingle= actionAngleStaeckelSingle(R[0],vR[0],vT[0], z[0],vz[0],pot=self._pot, delta=delta) - return (nu.atleast_1d(aASingle.JR(**copy.copy(kwargs))), - nu.atleast_1d(aASingle._R*aASingle._vT), - nu.atleast_1d(aASingle.Jz(**copy.copy(kwargs)))) + return (numpy.atleast_1d(aASingle.JR(**copy.copy(kwargs))), + numpy.atleast_1d(aASingle._R*aASingle._vT), + numpy.atleast_1d(aASingle.Jz(**copy.copy(kwargs)))) def _actionsFreqs(self,*args,**kwargs): """ @@ -227,18 +226,18 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) Lz= R*vT if self._useu0: #First calculate u0 if 'u0' in kwargs: - u0= nu.asarray(kwargs['u0']) + u0= numpy.asarray(kwargs['u0']) else: - E= nu.array([_evaluatePotentials(self._pot,R[ii],z[ii]) + E= numpy.array([_evaluatePotentials(self._pot,R[ii],z[ii]) +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,delta)[0] @@ -248,8 +247,8 @@ jr, jz, Omegar, Omegaphi, Omegaz, err= actionAngleStaeckel_c.actionAngleFreqStaeckel_c(\ self._pot,delta,R,vR,vT,z,vz,u0=u0,order=order) # 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: + indx= numpy.isnan(Omegar)*(jr < 10.**-3.)+numpy.isnan(Omegaz)*(jz < 10.**-3.) #Close-to-circular and close-to-the-plane orbits + if numpy.sum(indx) > 0: Omegar[indx]= [epifreq(self._pot,r,use_physical=False) for r in R[indx]] Omegaphi[indx]= [omegac(self._pot,r,use_physical=False) for r in R[indx]] Omegaz[indx]= [verticalfreq(self._pot,r,use_physical=False) for r in R[indx]] @@ -304,19 +303,19 @@ vz= self._eval_vz phi= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) + phi= numpy.array([phi]) Lz= R*vT if self._useu0: #First calculate u0 if 'u0' in kwargs: - u0= nu.asarray(kwargs['u0']) + u0= numpy.asarray(kwargs['u0']) else: - E= nu.array([_evaluatePotentials(self._pot,R[ii],z[ii]) + E= numpy.array([_evaluatePotentials(self._pot,R[ii],z[ii]) +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,delta)[0] @@ -326,8 +325,8 @@ jr, jz, Omegar, Omegaphi, Omegaz, angler, anglephi,anglez, err= actionAngleStaeckel_c.actionAngleFreqAngleStaeckel_c(\ self._pot,delta,R,vR,vT,z,vz,phi,u0=u0,order=order) # 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: + indx= numpy.isnan(Omegar)*(jr < 10.**-3.)+numpy.isnan(Omegaz)*(jz < 10.**-3.) #Close-to-circular and close-to-the-plane orbits + if numpy.sum(indx) > 0: Omegar[indx]= [epifreq(self._pot,r,use_physical=False) for r in R[indx]] Omegaphi[indx]= [omegac(self._pot,r,use_physical=False) for r in R[indx]] Omegaz[indx]= [verticalfreq(self._pot,r,use_physical=False) for r in R[indx]] @@ -362,9 +361,9 @@ """ delta= kwargs.get('delta',self._delta) umin, umax, vmin= self._uminumaxvmin(*args,**kwargs) - rperi= bovy_coords.uv_to_Rz(umin,nu.pi/2.,delta=delta)[0] + rperi= bovy_coords.uv_to_Rz(umin,numpy.pi/2.,delta=delta)[0] rap_tmp, zmax= bovy_coords.uv_to_Rz(umax,vmin,delta=delta) - rap= nu.sqrt(rap_tmp**2.+zmax**2.) + rap= numpy.sqrt(rap_tmp**2.+zmax**2.) e= (rap-rperi)/(rap+rperi) return (e,zmax,rperi,rap) @@ -398,11 +397,11 @@ z= self._eval_z vz= self._eval_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]) + R= numpy.array([R]) + vR= numpy.array([vR]) + vT= numpy.array([vT]) + z= numpy.array([z]) + vz= numpy.array([vz]) 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): @@ -410,9 +409,9 @@ if self._useu0: #First calculate u0 if 'u0' in kwargs: - u0= nu.asarray(kwargs['u0']) + u0= numpy.asarray(kwargs['u0']) else: - E= nu.array([_evaluatePotentials(self._pot,R[ii],z[ii]) + E= numpy.array([_evaluatePotentials(self._pot,R[ii],z[ii]) +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,delta)[0] @@ -431,9 +430,9 @@ warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) kwargs.pop('c',None) if len(R) > 1: - oumin= nu.zeros((len(R))) - oumax= nu.zeros((len(R))) - ovmin= nu.zeros((len(R))) + oumin= numpy.zeros((len(R))) + oumax= numpy.zeros((len(R))) + ovmin= numpy.zeros((len(R))) for ii in range(len(R)): targs= (R[ii],vR[ii],vT[ii],z[ii],vz[ii]) tkwargs= copy.copy(kwargs) @@ -453,9 +452,9 @@ delta=delta) umin, umax= aASingle.calcUminUmax() vmin= aASingle.calcVmin() - return (nu.atleast_1d(umin), - nu.atleast_1d(umax), - nu.atleast_1d(vmin)) + return (numpy.atleast_1d(umin), + numpy.atleast_1d(umax), + numpy.atleast_1d(vmin)) class actionAngleStaeckelSingle(actionAngle): """Action-angle formalism for axisymmetric potentials using Binney (2012)'s Staeckel approximation""" @@ -490,10 +489,10 @@ #Pre-calculate everything self._ux, self._vx= bovy_coords.Rz_to_uv(self._R,self._z, delta=self._delta) - self._sinvx= nu.sin(self._vx) - self._cosvx= nu.cos(self._vx) - self._coshux= nu.cosh(self._ux) - self._sinhux= nu.sinh(self._ux) + self._sinvx= numpy.sin(self._vx) + self._cosvx= numpy.cos(self._vx) + self._coshux= numpy.cosh(self._ux) + self._sinhux= numpy.sinh(self._ux) self._pux= self._delta*(self._vR*self._coshux*self._sinvx +self._vz*self._sinhux*self._cosvx) self._pvx= self._delta*(self._vR*self._sinhux*self._cosvx @@ -504,12 +503,12 @@ #Determine umin and umax self._u0= kwargs.pop('u0',self._ux) #u0 as defined by Binney does not matter for a #single action evaluation, so we don't determine it here - self._sinhu0= nu.sinh(self._u0) + self._sinhu0= numpy.sinh(self._u0) self._potu0v0= potentialStaeckel(self._u0,self._vx, self._pot,self._delta) self._I3U= self._E*self._sinhux**2.-self._pux**2./2./self._delta**2.\ -self._Lz**2./2./self._delta**2./self._sinhux**2. - self._potupi2= potentialStaeckel(self._ux,nu.pi/2., + self._potupi2= potentialStaeckel(self._ux,numpy.pi/2., self._pot,self._delta) dV= (self._coshux**2.*self._potupi2 -(self._sinhux**2.+self._sinvx**2.) @@ -615,11 +614,11 @@ return self._JR umin, umax= self.calcUminUmax() #print self._ux, self._pux, (umax-umin)/umax - if (umax-umin)/umax < 10.**-6: return nu.array([0.]) + if (umax-umin)/umax < 10.**-6: return numpy.array([0.]) order= kwargs.pop('order',10) if kwargs.pop('fixed_quad',False): # factor in next line bc integrand=/2delta^2 - self._JR= 1./nu.pi*nu.sqrt(2.)*self._delta\ + self._JR= 1./numpy.pi*numpy.sqrt(2.)*self._delta\ *integrate.fixed_quad(_JRStaeckelIntegrand, umin,umax, args=(self._E,self._Lz,self._I3U, @@ -630,7 +629,7 @@ n=order, **kwargs)[0] else: - self._JR= 1./nu.pi*nu.sqrt(2.)*self._delta\ + self._JR= 1./numpy.pi*numpy.sqrt(2.)*self._delta\ *integrate.quad(_JRStaeckelIntegrand, umin,umax, args=(self._E,self._Lz,self._I3U, @@ -658,13 +657,13 @@ if hasattr(self,'_JZ'): #pragma: no cover return self._JZ vmin= self.calcVmin() - if (nu.pi/2.-vmin) < 10.**-7: return nu.array([0.]) + if (numpy.pi/2.-vmin) < 10.**-7: return numpy.array([0.]) order= kwargs.pop('order',10) if kwargs.pop('fixed_quad',False): # factor in next line bc integrand=/2delta^2 - self._JZ= 2./nu.pi*nu.sqrt(2.)*self._delta \ + self._JZ= 2./numpy.pi*numpy.sqrt(2.)*self._delta \ *integrate.fixed_quad(_JzStaeckelIntegrand, - vmin,nu.pi/2, + vmin,numpy.pi/2, args=(self._E,self._Lz,self._I3V, self._delta, self._ux,self._coshux**2., @@ -674,9 +673,9 @@ **kwargs)[0] else: # factor in next line bc integrand=/2delta^2 - self._JZ= 2./nu.pi*nu.sqrt(2.)*self._delta \ + self._JZ= 2./numpy.pi*numpy.sqrt(2.)*self._delta \ *integrate.quad(_JzStaeckelIntegrand, - vmin,nu.pi/2, + vmin,numpy.pi/2, args=(self._E,self._Lz,self._I3V, self._delta, self._ux,self._coshux**2., @@ -717,7 +716,7 @@ if hasattr(self,'_uminumax'): #pragma: no cover return self._uminumax E, L= self._E, self._Lz - if nu.fabs(self._pux) < 10.**-7.: #We are at umin or umax + if numpy.fabs(self._pux) < 10.**-7.: #We are at umin or umax eps= 10.**-8. peps= _JRStaeckelIntegrandSquared(self._ux+eps, E,L,self._I3U,self._delta, @@ -774,7 +773,7 @@ self._potu0v0,self._pot) if rstart == 0.: umin= 0. else: - if nu.fabs(prevr-self._ux) < 10.**-2.: rup= self._ux + if numpy.fabs(prevr-self._ux) < 10.**-2.: rup= self._ux else: rup= prevr try: umin= optimize.brentq(_JRStaeckelIntegrandSquared, @@ -817,7 +816,7 @@ if hasattr(self,'_vmin'): #pragma: no cover return self._vmin E, L= self._E, self._Lz - if nu.fabs(self._pvx) < 10.**-7.: #We are at vmin or vmax + if numpy.fabs(self._pvx) < 10.**-7.: #We are at vmin or vmax eps= 10.**-8. peps= _JzStaeckelIntegrandSquared(self._vx+eps, E,L,self._I3V,self._delta, @@ -950,7 +949,7 @@ def _JRStaeckelIntegrand(u,E,Lz,I3U,delta,u0,sinh2u0,v0,sin2v0, potu0v0,pot): - return nu.sqrt(_JRStaeckelIntegrandSquared(u,E,Lz,I3U,delta,u0,sinh2u0, + return numpy.sqrt(_JRStaeckelIntegrandSquared(u,E,Lz,I3U,delta,u0,sinh2u0, v0,sin2v0, potu0v0,pot)) @@ -958,7 +957,7 @@ potu0v0,pot): #potu0v0= potentialStaeckel(u0,v0,pot,delta) """The J_R integrand: p^2_u(u)/2/delta^2""" - sinh2u= nu.sinh(u)**2. + sinh2u= numpy.sinh(u)**2. dU= (sinh2u+sin2v0)*potentialStaeckel(u,v0, pot,delta)\ -(sinh2u0+sin2v0)*potu0v0 @@ -966,14 +965,14 @@ def _JzStaeckelIntegrand(v,E,Lz,I3V,delta,u0,cosh2u0,sinh2u0, potu0pi2,pot): - return nu.sqrt(_JzStaeckelIntegrandSquared(v,E,Lz,I3V,delta,u0,cosh2u0, + return numpy.sqrt(_JzStaeckelIntegrandSquared(v,E,Lz,I3V,delta,u0,cosh2u0, sinh2u0, potu0pi2,pot)) def _JzStaeckelIntegrandSquared(v,E,Lz,I3V,delta,u0,cosh2u0,sinh2u0, potu0pi2,pot): - #potu0pi2= potentialStaeckel(u0,nu.pi/2.,pot,delta) + #potu0pi2= potentialStaeckel(u0,numpy.pi/2.,pot,delta) """The J_z integrand: p_v(v)/2/delta^2""" - sin2v= nu.sin(v)**2. + sin2v= numpy.sin(v)**2. dV= cosh2u0*potu0pi2\ -(sinh2u0+sin2v)*potentialStaeckel(u0,v,pot,delta) return E*sin2v+I3V+dV-Lz**2./2./delta**2./sin2v @@ -1054,8 +1053,8 @@ 2013-08-28 - Written - Bovy (IAS) 2016-02-20 - Changed input order to allow physical conversions - Bovy (UofT) """ - if isinstance(R,nu.ndarray): - delta2= nu.array([(z[ii]**2.-R[ii]**2. #eqn. (9) has a sign error + if isinstance(R,numpy.ndarray): + delta2= numpy.array([(z[ii]**2.-R[ii]**2. #eqn. (9) has a sign error +(3.*R[ii]*_evaluatezforces(pot,R[ii],z[ii]) -3.*z[ii]*_evaluateRforces(pot,R[ii],z[ii]) +R[ii]*z[ii]*(evaluateR2derivs(pot,R[ii],z[ii], @@ -1065,7 +1064,7 @@ indx= (delta2 < 0.)*(delta2 > -10.**-10.) delta2[indx]= 0. if not no_median: - delta2= nu.median(delta2[True^nu.isnan(delta2)]) + delta2= numpy.median(delta2[True^numpy.isnan(delta2)]) else: delta2= (z**2.-R**2. #eqn. (9) has a sign error +(3.*R*_evaluatezforces(pot,R,z) @@ -1073,4 +1072,4 @@ +R*z*(evaluateR2derivs(pot,R,z,use_physical=False) -evaluatez2derivs(pot,R,z,use_physical=False)))/evaluateRzderivs(pot,R,z,use_physical=False)) if delta2 < 0. and delta2 > -10.**-10.: delta2= 0. - return nu.sqrt(delta2) + return numpy.sqrt(delta2) diff -Nru galpy-1.5/galpy/actionAngle/actionAngleTorus_c.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleTorus_c.py --- galpy-1.5/galpy/actionAngle/actionAngleTorus_c.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleTorus_c.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,39 +1,10 @@ -import os -import sys -import distutils.sysconfig as sysconfig -import warnings import ctypes import ctypes.util import numpy from numpy.ctypeslib import ndpointer -from galpy.util import galpyWarningVerbose -#Find and load the library -_lib= None -outerr= None -PY3= sys.version > '3' -if PY3: - _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') -else: #pragma: no cover - _ext_suffix= '.so' -for path in sys.path: - try: - _lib = ctypes.CDLL(os.path.join(path,'galpy_actionAngleTorus_c%s' % _ext_suffix)) - except OSError as e: - if os.path.exists(os.path.join(path,'galpy_actionAngleTorus_c%s' % _ext_suffix)): #pragma: no cover - outerr= e - _lib = None - else: - break -if _lib is None: #pragma: no cover - if not outerr is None: - warnings.warn("actionAngleTorus_c extension module not loaded, because of error '%s' " % outerr, - galpyWarningVerbose) - else: - warnings.warn("actionAngleTorus_c extension module not loaded, because galpy_actionAngleTorus_c%s image was not found" % _ext_suffix, - galpyWarningVerbose) - _ext_loaded= False -else: - _ext_loaded= True +from ..util import _load_extension_libs + +_lib, _ext_loaded= _load_extension_libs.load_libgalpy_actionAngleTorus() def actionAngleTorus_xvFreqs_c(pot,jr,jphi,jz, angler,anglephi,anglez, @@ -58,7 +29,7 @@ 2015-08-05/07 - Written - Bovy (UofT) """ #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potfortorus=True) #Set up result arrays @@ -158,7 +129,7 @@ 2015-08-05/07 - Written - Bovy (UofT) """ #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potfortorus=True) #Set up result @@ -222,7 +193,7 @@ 2016-07-15 - Written - Bovy (UofT) """ #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potfortorus=True) #Set up result @@ -297,7 +268,7 @@ 2016-07-19 - Written - Bovy (UofT) """ #Parse the potential - from galpy.orbit.integrateFullOrbit import _parse_pot + from ..orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args= _parse_pot(pot,potfortorus=True) #Set up result diff -Nru galpy-1.5/galpy/actionAngle/actionAngleTorus.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleTorus.py --- galpy-1.5/galpy/actionAngle/actionAngleTorus.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleTorus.py 2020-04-24 19:48:38.000000000 +0000 @@ -8,12 +8,12 @@ ############################################################################### import warnings import numpy -from galpy.potential import MWPotential, _isNonAxi -from galpy.util import galpyWarning +from ..potential import MWPotential, _isNonAxi +from ..util import galpyWarning from . import actionAngleTorus_c from .actionAngleTorus_c import _ext_loaded as ext_loaded -from galpy.potential.Potential import _check_c -from galpy.potential.Potential import flatten as flatten_potential +from ..potential.Potential import _check_c +from ..potential.Potential import flatten as flatten_potential _autofit_errvals= {} _autofit_errvals[-1]= 'something wrong with input, usually bad starting values for the parameters' _autofit_errvals[-2]= 'Fit failed the goal by a factor <= 2' diff -Nru galpy-1.5/galpy/actionAngle/actionAngleVertical.py galpy-1.6.0.post0/galpy/actionAngle/actionAngleVertical.py --- galpy-1.5/galpy/actionAngle/actionAngleVertical.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/actionAngle/actionAngleVertical.py 2020-04-24 19:48:38.000000000 +0000 @@ -10,12 +10,10 @@ # calczmax # calcEz ############################################################################### -import math as m -import numpy as nu +import numpy from scipy import optimize, integrate -from .actionAngle import * -from galpy.potential.linearPotential import linearPotential, \ - evaluatelinearPotentials +from .actionAngle import actionAngle +from ..potential.linearPotential import evaluatelinearPotentials class actionAngleVertical(actionAngle): """Action-angle formalism for vertical integral using the adiabatic approximation""" def __init__(self,*args,**kwargs): @@ -58,11 +56,11 @@ if hasattr(self,'_Jz'): return self._Jz zmax= self.calczmax() - if zmax == -9999.99: return nu.array([9999.99,nu.nan]) + if zmax == -9999.99: return numpy.array([9999.99,numpy.nan]) Ez= calcEz(self._z,self._vz,self._verticalpot) self._Jz= 2.*integrate.quad(_JzIntegrand,0.,zmax, args=(Ez,self._verticalpot), - **kwargs)[0]/nu.pi + **kwargs)[0]/numpy.pi return self._Jz def Tz(self,**kwargs): #pragma: no cover @@ -105,17 +103,17 @@ zmax= self.calczmax() Ez= calcEz(self._z,self._vz,self._verticalpot) Tz= self.Tz(**kwargs) - self._anglez= 2.*nu.pi*(nu.array(integrate.quad(_TzIntegrand,0.,nu.fabs(self._z), + self._anglez= 2.*numpy.pi*(numpy.array(integrate.quad(_TzIntegrand,0.,numpy.fabs(self._z), args=(Ez,self._verticalpot), **kwargs)))/Tz[0] if self._z >= 0. and self._vz >= 0.: pass elif self._z >= 0. and self._vz < 0.: - self._anglez[0]= nu.pi-self._anglez[0] + self._anglez[0]= numpy.pi-self._anglez[0] elif self._z < 0. and self._vz <= 0.: - self._anglez[0]= nu.pi+self._anglez[0] + self._anglez[0]= numpy.pi+self._anglez[0] else: - self._anglez[0]= 2.*nu.pi-self._anglez[0] + self._anglez[0]= 2.*numpy.pi-self._anglez[0] return self._anglez def calczmax(self): @@ -134,7 +132,7 @@ return self._zmax Ez= calcEz(self._z,self._vz,self._verticalpot) if self._vz == 0.: #We are exactly at the maximum height - zmax= nu.fabs(self._z) + zmax= numpy.fabs(self._z) else: zstart= self._z try: @@ -186,7 +184,7 @@ def _JzIntegrand(z,Ez,pot): """The J_z integrand""" - return nu.sqrt(2.*(Ez-potentialVertical(z,pot))) + return numpy.sqrt(2.*(Ez-potentialVertical(z,pot))) def _TzIntegrand(z,Ez,pot): #pragma: no cover """The T_z integrand""" @@ -208,7 +206,7 @@ 2012-06-01 - Written - Bovy (IAS) """ if z == 0.: ztry= 0.00001 - else: ztry= 2.*nu.fabs(z) + else: ztry= 2.*numpy.fabs(z) while (Ez-potentialVertical(ztry,pot)) > 0.: ztry*= 2. if ztry > 100.: #pragma: no cover diff -Nru galpy-1.5/galpy/df/df.py galpy-1.6.0.post0/galpy/df/df.py --- galpy-1.5/galpy/df/df.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/df/df.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,9 +1,10 @@ -from galpy.util import config +from ..util.bovy_conversion import physical_compatible _APY_LOADED= True try: from astropy import units except ImportError: _APY_LOADED= False +from ..util import config class df(object): """Top-level class for DF classes""" def __init__(self,ro=None,vo=None): @@ -38,6 +39,10 @@ self._voSet= True return None + def _check_consistent_units(self): + """Internal function to check that the set of units for this object is consistent with that for the potential""" + assert physical_compatible(self,self._pot), 'Physical conversion for the DF object is not consistent with that of the Potential given to it' + def turn_physical_off(self): """ NAME: @@ -89,14 +94,16 @@ 2016-06-05 - Written - Bovy (UofT) + 2020-04-22 - Don't turn on a parameter when it is False - Bovy (UofT) + """ - self._roSet= True - self._voSet= True - if not ro is None: + if not ro is False: self._roSet= True + if not vo is False: self._voSet= True + if not ro is None and ro: if _APY_LOADED and isinstance(ro,units.Quantity): ro= ro.to(units.kpc).value self._ro= ro - if not vo is None: + if not vo is None and vo: if _APY_LOADED and isinstance(vo,units.Quantity): vo= vo.to(units.km/units.s).value self._vo= vo diff -Nru galpy-1.5/galpy/df/diskdf.py galpy-1.6.0.post0/galpy/df/diskdf.py --- galpy-1.5/galpy/df/diskdf.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/df/diskdf.py 2020-04-24 19:48:38.000000000 +0000 @@ -18,36 +18,29 @@ _MAXD_REJECTLOS= 4. _PROFILE= False import copy -import re import os, os.path import pickle -import math -import numpy as nu -import scipy as sc -import scipy.integrate as integrate -import scipy.interpolate as interpolate -from scipy import linalg -from scipy import stats -from scipy import optimize -from .surfaceSigmaProfile import * -from galpy.orbit import Orbit -from galpy.util.bovy_ars import bovy_ars -from galpy.util import save_pickles -from galpy.util.bovy_conversion import physical_conversion, \ +import numpy +import scipy +numpylog= numpy.lib.scimath.log # somehow, this code produces log(negative), which scipy (now numpy.lib.scimath.log) implements as log(|negative|) + i pi while numpy gives NaN and we want the scipy behavior; not sure where the log(negative) comes from though! I think it's for sigma=0 DFs (this test fails with numpy.log) where the DF eval has a log(~zero) that can be slightly negative because of numerical precision issues +from scipy import integrate, interpolate, stats, optimize +from .surfaceSigmaProfile import surfaceSigmaProfile, expSurfaceSigmaProfile +from ..orbit import Orbit +from ..util.bovy_ars import bovy_ars +from ..util import save_pickles +from ..util.bovy_conversion import physical_conversion, \ potential_physical_input, _APY_UNITS, surfdens_in_msolpc2 -from galpy.potential import PowerSphericalPotential -from galpy.actionAngle import actionAngleAdiabatic, actionAngleAxi +from ..potential import PowerSphericalPotential +from ..actionAngle import actionAngleAdiabatic, actionAngleAxi from .df import df, _APY_LOADED if _APY_LOADED: from astropy import units #scipy version -try: - sversion=re.split(r'\.',sc.__version__) - _SCIPYVERSION=float(sversion[0])+float(sversion[1])/10. -except: #pragma: no cover - raise ImportError( "scipy.__version__ not understood, contact galpy developer, send scipy.__version__") +from pkg_resources import parse_version +_SCIPY_VERSION= parse_version(scipy.__version__) +_SCIPY_VERSION_BREAK= parse_version('0.9') _CORRECTIONSDIR=os.path.join(os.path.dirname(os.path.realpath(__file__)),'data') -_DEGTORAD= math.pi/180. +_DEGTORAD= numpy.pi/180. class diskdf(df): """Class that represents a disk DF""" def __init__(self,dftype='dehnen', @@ -94,7 +87,7 @@ profileParams= newprofileParams self._surfaceSigmaProfile= surfaceSigma(profileParams) self._beta= beta - self._gamma= sc.sqrt(2./(1.+self._beta)) + self._gamma= numpy.sqrt(2./(1.+self._beta)) if correct or 'corrections' in kwargs or 'rmax' in kwargs \ or 'niter' in kwargs or 'npoints' in kwargs: self._correct= True @@ -163,38 +156,38 @@ elif kwargs.pop('marginalizeVlos',False): return self._call_marginalizevlos(args[0],**kwargs) else: - return sc.real(self.eval(*vRvTRToEL(\ + return numpy.real(self.eval(*vRvTRToEL(\ args[0].vR(use_physical=False), args[0].vT(use_physical=False), args[0].R(use_physical=False), self._beta,self._dftype))) else: no= args[0](args[1]) - return sc.real(self.eval(*vRvTRToEL(no.vR(use_physical=False), + return numpy.real(self.eval(*vRvTRToEL(no.vR(use_physical=False), no.vT(use_physical=False), no.R(use_physical=False), self._beta, self._dftype))) elif isinstance(args[0],list) \ and isinstance(args[0][0],Orbit): - if nu.any([len(no) > 1 for no in args[0]]): + if numpy.any([len(no) > 1 for no in args[0]]): raise RuntimeError('Only single-object Orbit instances can be passed to DF instances at this point') #pragma: no cover #Grab all of the vR, vT, and R - vR= nu.array([o.vR(use_physical=False) for o in args[0]]) - vT= nu.array([o.vT(use_physical=False) for o in args[0]]) - R= nu.array([o.R(use_physical=False) for o in args[0]]) - return sc.real(self.eval(*vRvTRToEL(vR,vT,R,self._beta, - self._dftype))) - elif isinstance(args[0],nu.ndarray) and \ + vR= numpy.array([o.vR(use_physical=False) for o in args[0]]) + vT= numpy.array([o.vT(use_physical=False) for o in args[0]]) + R= numpy.array([o.R(use_physical=False) for o in args[0]]) + return numpy.real(self.eval(*vRvTRToEL(vR,vT,R,self._beta, + self._dftype))) + elif isinstance(args[0],numpy.ndarray) and \ not (hasattr(args[0],'isscalar') and args[0].isscalar): #Grab all of the vR, vT, and R vR= args[0][1] vT= args[0][2] R= args[0][0] - return sc.real(self.eval(*vRvTRToEL(vR,vT,R,self._beta, - self._dftype))) + return numpy.real(self.eval(*vRvTRToEL(vR,vT,R,self._beta, + self._dftype))) else: - return sc.real(self.eval(*args)) + return numpy.real(self.eval(*args)) def _call_marginalizevperp(self,o,**kwargs): """Call the DF, marginalizing over perpendicular velocity""" @@ -205,7 +198,7 @@ phi= o.phi(use_physical=False) #Get local circular velocity, projected onto the los vcirc= R**self._beta - vcirclos= vcirc*math.sin(phi+l) + vcirclos= vcirc*numpy.sin(phi+l) #Marginalize alphalos= phi+l if not 'nsigma' in kwargs or ('nsigma' in kwargs and \ @@ -215,31 +208,31 @@ nsigma= kwargs['nsigma'] kwargs.pop('nsigma',None) sigmaR2= self.targetSigma2(R,use_physical=False) - sigmaR1= sc.sqrt(sigmaR2) + sigmaR1= numpy.sqrt(sigmaR2) #Use the asymmetric drift equation to estimate va va= sigmaR2/2./R**self._beta*(1./self._gamma**2.-1. -R*self._surfaceSigmaProfile.surfacemassDerivative(R,log=True) -R*self._surfaceSigmaProfile.sigma2Derivative(R,log=True)) - if math.fabs(va) > sigmaR1: va = 0. #To avoid craziness near the center - if math.fabs(math.sin(alphalos)) < math.sqrt(1./2.): - cosalphalos= math.cos(alphalos) - tanalphalos= math.tan(alphalos) + if numpy.fabs(va) > sigmaR1: va = 0. #To avoid craziness near the center + if numpy.fabs(numpy.sin(alphalos)) < numpy.sqrt(1./2.): + cosalphalos= numpy.cos(alphalos) + tanalphalos= numpy.tan(alphalos) return integrate.quad(_marginalizeVperpIntegrandSinAlphaSmall, -self._gamma*va/sigmaR1-nsigma, -self._gamma*va/sigmaR1+nsigma, args=(self,R,cosalphalos,tanalphalos, vlos-vcirclos,vcirc, sigmaR1/self._gamma), - **kwargs)[0]/math.fabs(cosalphalos)\ + **kwargs)[0]/numpy.fabs(cosalphalos)\ *sigmaR1/self._gamma else: - sinalphalos= math.sin(alphalos) - cotalphalos= 1./math.tan(alphalos) + sinalphalos= numpy.sin(alphalos) + cotalphalos= 1./numpy.tan(alphalos) return integrate.quad(_marginalizeVperpIntegrandSinAlphaLarge, -nsigma,nsigma, args=(self,R,sinalphalos,cotalphalos, vlos-vcirclos,vcirc,sigmaR1), - **kwargs)[0]/math.fabs(sinalphalos)*sigmaR1 + **kwargs)[0]/numpy.fabs(sinalphalos)*sigmaR1 def _call_marginalizevlos(self,o,**kwargs): """Call the DF, marginalizing over line-of-sight velocity""" @@ -251,9 +244,9 @@ #Get local circular velocity, projected onto the perpendicular #direction vcirc= R**self._beta - vcircperp= vcirc*math.cos(phi+l) + vcircperp= vcirc*numpy.cos(phi+l) #Marginalize - alphaperp= math.pi/2.+phi+l + alphaperp= numpy.pi/2.+phi+l if not 'nsigma' in kwargs or ('nsigma' in kwargs and \ kwargs['nsigma'] is None): nsigma= _NSIGMA @@ -261,15 +254,15 @@ nsigma= kwargs['nsigma'] kwargs.pop('nsigma',None) sigmaR2= self.targetSigma2(R,use_physical=False) - sigmaR1= sc.sqrt(sigmaR2) + sigmaR1= numpy.sqrt(sigmaR2) #Use the asymmetric drift equation to estimate va va= sigmaR2/2./R**self._beta*(1./self._gamma**2.-1. -R*self._surfaceSigmaProfile.surfacemassDerivative(R,log=True) -R*self._surfaceSigmaProfile.sigma2Derivative(R,log=True)) - if math.fabs(va) > sigmaR1: va = 0. #To avoid craziness near the center - if math.fabs(math.sin(alphaperp)) < math.sqrt(1./2.): - cosalphaperp= math.cos(alphaperp) - tanalphaperp= math.tan(alphaperp) + if numpy.fabs(va) > sigmaR1: va = 0. #To avoid craziness near the center + if numpy.fabs(numpy.sin(alphaperp)) < numpy.sqrt(1./2.): + cosalphaperp= numpy.cos(alphaperp) + tanalphaperp= numpy.tan(alphaperp) #we can reuse the VperpIntegrand, since it is just another angle return integrate.quad(_marginalizeVperpIntegrandSinAlphaSmall, -self._gamma*va/sigmaR1-nsigma, @@ -277,17 +270,17 @@ args=(self,R,cosalphaperp,tanalphaperp, vperp-vcircperp,vcirc, sigmaR1/self._gamma), - **kwargs)[0]/math.fabs(cosalphaperp)\ + **kwargs)[0]/numpy.fabs(cosalphaperp)\ *sigmaR1/self._gamma else: - sinalphaperp= math.sin(alphaperp) - cotalphaperp= 1./math.tan(alphaperp) + sinalphaperp= numpy.sin(alphaperp) + cotalphaperp= 1./numpy.tan(alphaperp) #we can reuse the VperpIntegrand, since it is just another angle return integrate.quad(_marginalizeVperpIntegrandSinAlphaLarge, -nsigma,nsigma, args=(self,R,sinalphaperp,cotalphaperp, vperp-vcircperp,vcirc,sigmaR1), - **kwargs)[0]/math.fabs(sinalphaperp)*sigmaR1 + **kwargs)[0]/numpy.fabs(sinalphaperp)*sigmaR1 @potential_physical_input @physical_conversion('velocity2',pop=True) @@ -389,7 +382,7 @@ R, phi= _dlToRphi(d,lrad) if log: return self._surfaceSigmaProfile.surfacemass(R,log=log)\ - +math.log(d) + +numpylog(d) else: return self._surfaceSigmaProfile.surfacemass(R,log=log)\ *d @@ -507,16 +500,16 @@ out= [] while len(out) < n: #sample - prop= nu.random.random()*maxd + prop= numpy.random.random()*maxd if target: surfmassatprop= self.targetSurfacemassLOS(prop,l,deg=False, use_physical=False) else: surfmassatprop= self.surfacemassLOS(prop,l,deg=False, use_physical=False) - if surfmassatprop/maxSM > nu.random.random(): #accept + if surfmassatprop/maxSM > numpy.random.random(): #accept out.append(prop) - return nu.array(out) + return numpy.array(out) @potential_physical_input @physical_conversion('velocity',pop=True) @@ -562,18 +555,18 @@ nsigma= _NSIGMA out= [] if target: - sigma= math.sqrt(self.targetSigma2(R,use_physical=False)) + sigma= numpy.sqrt(self.targetSigma2(R,use_physical=False)) else: - sigma= math.sqrt(self.sigma2(R,use_physical=False)) + sigma= numpy.sqrt(self.sigma2(R,use_physical=False)) while len(out) < n: #sample - vrg, vtg= nu.random.normal(), nu.random.normal() + vrg, vtg= numpy.random.normal(), numpy.random.normal() propvR= vrg*nsigma*sigma propvT= vtg*nsigma*sigma/self._gamma+maxVT VDatprop= self(Orbit([R,propvR,propvT])) - if VDatprop/maxVD > nu.random.uniform()*nu.exp(-0.5*(vrg**2.+vtg**2.)): #accept - out.append(sc.array([propvR,propvT])) - return nu.array(out) + if VDatprop/maxVD > numpy.random.uniform()*numpy.exp(-0.5*(vrg**2.+vtg**2.)): #accept + out.append(numpy.array([propvR,propvT])) + return numpy.array(out) def sampleLOS(self,los,n=1,deg=True,maxd=None,nsigma=None, targetSurfmass=True,targetSigma2=True): @@ -700,25 +693,25 @@ nsigma= _NSIGMA logSigmaR= self.targetSurfacemass(R,log=True,use_physical=False) sigmaR2= self.targetSigma2(R,use_physical=False) - sigmaR1= sc.sqrt(sigmaR2) - logsigmaR2= sc.log(sigmaR2) + sigmaR1= numpy.sqrt(sigmaR2) + logsigmaR2= numpylog(sigmaR2) if relative: norm= 1. else: - norm= sc.exp(logSigmaR) + norm= numpy.exp(logSigmaR) #Use the asymmetric drift equation to estimate va va= sigmaR2/2./R**self._beta*(1./self._gamma**2.-1. -R*self._surfaceSigmaProfile.surfacemassDerivative(R,log=True) -R*self._surfaceSigmaProfile.sigma2Derivative(R,log=True)) - if math.fabs(va) > sigmaR1: va = 0.#To avoid craziness near the center + if numpy.fabs(va) > sigmaR1: va = 0.#To avoid craziness near the center if romberg: - return sc.real(bovy_dblquad(_surfaceIntegrand, + return numpy.real(bovy_dblquad(_surfaceIntegrand, self._gamma*(R**self._beta-va)/sigmaR1-nsigma, self._gamma*(R**self._beta-va)/sigmaR1+nsigma, lambda x: 0., lambda x: nsigma, [R,self,logSigmaR,logsigmaR2,sigmaR1, self._gamma], - tol=10.**-8)/sc.pi*norm) + tol=10.**-8)/numpy.pi*norm) else: return integrate.dblquad(_surfaceIntegrand, self._gamma*(R**self._beta-va)/sigmaR1-nsigma, @@ -726,7 +719,7 @@ lambda x: 0., lambda x: nsigma, (R,self,logSigmaR,logsigmaR2,sigmaR1, self._gamma), - epsrel=_EPSREL)[0]/sc.pi*norm + epsrel=_EPSREL)[0]/numpy.pi*norm @potential_physical_input @physical_conversion('velocity2surfacedensity',pop=True) @@ -767,25 +760,25 @@ nsigma= _NSIGMA logSigmaR= self.targetSurfacemass(R,log=True,use_physical=False) sigmaR2= self.targetSigma2(R,use_physical=False) - sigmaR1= sc.sqrt(sigmaR2) - logsigmaR2= sc.log(sigmaR2) + sigmaR1= numpy.sqrt(sigmaR2) + logsigmaR2= numpylog(sigmaR2) if relative: norm= 1. else: - norm= sc.exp(logSigmaR+logsigmaR2) + norm= numpy.exp(logSigmaR+logsigmaR2) #Use the asymmetric drift equation to estimate va va= sigmaR2/2./R**self._beta*(1./self._gamma**2.-1. -R*self._surfaceSigmaProfile.surfacemassDerivative(R,log=True) -R*self._surfaceSigmaProfile.sigma2Derivative(R,log=True)) - if math.fabs(va) > sigmaR1: va = 0. #To avoid craziness near the center + if numpy.fabs(va) > sigmaR1: va = 0. #To avoid craziness near the center if romberg: - return sc.real(bovy_dblquad(_sigma2surfaceIntegrand, + return numpy.real(bovy_dblquad(_sigma2surfaceIntegrand, self._gamma*(R**self._beta-va)/sigmaR1-nsigma, self._gamma*(R**self._beta-va)/sigmaR1+nsigma, lambda x: 0., lambda x: nsigma, [R,self,logSigmaR,logsigmaR2,sigmaR1, self._gamma], - tol=10.**-8)/sc.pi*norm) + tol=10.**-8)/numpy.pi*norm) else: return integrate.dblquad(_sigma2surfaceIntegrand, self._gamma*(R**self._beta-va)/sigmaR1-nsigma, @@ -793,7 +786,7 @@ lambda x: 0., lambda x: nsigma, (R,self,logSigmaR,logsigmaR2,sigmaR1, self._gamma), - epsrel=_EPSREL)[0]/sc.pi*norm + epsrel=_EPSREL)[0]/numpy.pi*norm def vmomentsurfacemass(self,*args,**kwargs): """ @@ -866,26 +859,26 @@ nsigma= _NSIGMA logSigmaR= self.targetSurfacemass(R,log=True,use_physical=False) sigmaR2= self.targetSigma2(R,use_physical=False) - sigmaR1= sc.sqrt(sigmaR2) - logsigmaR2= sc.log(sigmaR2) + sigmaR1= numpy.sqrt(sigmaR2) + logsigmaR2= numpylog(sigmaR2) if relative: norm= 1. else: - norm= sc.exp(logSigmaR+logsigmaR2*(n+m)/2.)/self._gamma**m + norm= numpy.exp(logSigmaR+logsigmaR2*(n+m)/2.)/self._gamma**m #Use the asymmetric drift equation to estimate va va= sigmaR2/2./R**self._beta*(1./self._gamma**2.-1. -R*self._surfaceSigmaProfile.surfacemassDerivative(R,log=True) -R*self._surfaceSigmaProfile.sigma2Derivative(R,log=True)) - if math.fabs(va) > sigmaR1: va = 0. #To avoid craziness near the center + if numpy.fabs(va) > sigmaR1: va = 0. #To avoid craziness near the center if deriv is None: if romberg: - return sc.real(bovy_dblquad(_vmomentsurfaceIntegrand, + return numpy.real(bovy_dblquad(_vmomentsurfaceIntegrand, self._gamma*(R**self._beta-va)/sigmaR1-nsigma, self._gamma*(R**self._beta-va)/sigmaR1+nsigma, lambda x: -nsigma, lambda x: nsigma, [R,self,logSigmaR,logsigmaR2,sigmaR1, self._gamma,n,m], - tol=10.**-8)/sc.pi*norm/2.) + tol=10.**-8)/numpy.pi*norm/2.) else: return integrate.dblquad(_vmomentsurfaceIntegrand, self._gamma*(R**self._beta-va)/sigmaR1-nsigma, @@ -893,16 +886,16 @@ lambda x: -nsigma, lambda x: nsigma, (R,self,logSigmaR,logsigmaR2,sigmaR1, self._gamma,n,m), - epsrel=_EPSREL)[0]/sc.pi*norm/2. + epsrel=_EPSREL)[0]/numpy.pi*norm/2. else: if romberg: - return sc.real(bovy_dblquad(_vmomentderivsurfaceIntegrand, + return numpy.real(bovy_dblquad(_vmomentderivsurfaceIntegrand, self._gamma*(R**self._beta-va)/sigmaR1-nsigma, self._gamma*(R**self._beta-va)/sigmaR1+nsigma, lambda x: -nsigma, lambda x: nsigma, [R,self,logSigmaR,logsigmaR2,sigmaR1, self._gamma,n,m,deriv], - tol=10.**-8)/sc.pi*norm/2.) + tol=10.**-8)/numpy.pi*norm/2.) else: return integrate.dblquad(_vmomentderivsurfaceIntegrand, self._gamma*(R**self._beta-va)/sigmaR1-nsigma, @@ -910,7 +903,7 @@ lambda x: -nsigma, lambda x: nsigma, (R,self,logSigmaR,logsigmaR2,sigmaR1, self._gamma,n,m,deriv), - epsrel=_EPSREL)[0]/sc.pi*norm/2. + epsrel=_EPSREL)[0]/numpy.pi*norm/2. @potential_physical_input @physical_conversion('frequency-kmskpc',pop=True) @@ -1483,7 +1476,7 @@ 2010-07-11 - Written - Bovy (NYU) """ if self._beta == 0.: - xE= sc.exp(E-.5) + xE= numpy.exp(E-.5) else: #non-flat rotation curve xE= (2.*E/(1.+1./self._beta))**(1./2./self._beta) rperi,rap= self._aA.calcRapRperi(xE,0.,L/xE,0.,0.) @@ -1492,7 +1485,7 @@ pot=PowerSphericalPotential(normalize=1., alpha=2.-2.*self._beta).toPlanar()) TR= aA.TR() - return (2.*math.pi/TR,rap,rperi) + return (2.*numpy.pi/TR,rap,rperi) def sample(self,n=1,rrange=None,returnROrbit=True,returnOrbit=False, nphi=1.,los=None,losdeg=True,nsigma=None,maxd=None,target=True): @@ -1617,7 +1610,7 @@ """ if log: return self.targetSigma2(R,log=log,use_physical=False)\ - -2.*nu.log(self._gamma) + -2.*numpylog(self._gamma) else: return self.targetSigma2(R,log=log,use_physical=False)\ /self._gamma**2. @@ -1698,18 +1691,18 @@ L= L.to(units.kpc*units.km/units.s).value/self._ro/self._vo #Calculate Re,LE, OmegaE if self._beta == 0.: - xE= sc.exp(E-.5) - logOLLE= sc.log(L/xE-1.) + xE= numpy.exp(E-.5) + logOLLE= numpylog(L/xE-1.) else: #non-flat rotation curve xE= (2.*E/(1.+1./self._beta))**(1./2./self._beta) - logOLLE= self._beta*sc.log(xE)+sc.log(L/xE-xE**self._beta) + logOLLE= self._beta*numpylog(xE)+numpylog(L/xE-xE**self._beta) if _PROFILE: #pragma: no cover one_time= (time.time()-start) start= time.time() if self._correct: correction= self._corr.correct(xE,log=True) else: - correction= sc.zeros(2) + correction= numpy.zeros(2) if _PROFILE: #pragma: no cover corr_time= (time.time()-start) start= time.time() @@ -1717,13 +1710,13 @@ if _PROFILE: #pragma: no cover targSigma_time= (time.time()-start) start= time.time() - out= self._gamma*sc.exp(logsigmaR2-SRE2+self.targetSurfacemass(xE,log=True,use_physical=False)-logSigmaR+sc.exp(logOLLE-SRE2)+correction[0])/2./nu.pi + out= self._gamma*numpy.exp(logsigmaR2-SRE2+self.targetSurfacemass(xE,log=True,use_physical=False)-logSigmaR+numpy.exp(logOLLE-SRE2)+correction[0])/2./numpy.pi out_time= (time.time()-start) tot_time= one_time+corr_time+targSigma_time+out_time print(one_time/tot_time, corr_time/tot_time, targSigma_time/tot_time, out_time/tot_time, tot_time) return out else: - return self._gamma*sc.exp(logsigmaR2-SRE2+self.targetSurfacemass(xE,log=True,use_physical=False)-logSigmaR+sc.exp(logOLLE-SRE2)+correction[0])/2./nu.pi + return self._gamma*numpy.exp(logsigmaR2-SRE2+self.targetSurfacemass(xE,log=True,use_physical=False)-logSigmaR+numpy.exp(logOLLE-SRE2)+correction[0])/2./numpy.pi def sample(self,n=1,rrange=None,returnROrbit=True,returnOrbit=False, nphi=1.,los=None,losdeg=True,nsigma=None,targetSurfmass=True, @@ -1762,24 +1755,24 @@ targetSigma2=targetSigma2) #First sample xE if self._correct: - xE= sc.array(bovy_ars([0.,0.],[True,False],[0.05,2.],_ars_hx, + xE= numpy.array(bovy_ars([0.,0.],[True,False],[0.05,2.],_ars_hx, _ars_hpx,nsamples=n, hxparams=(self._surfaceSigmaProfile, self._corr))) else: - xE= sc.array(bovy_ars([0.,0.],[True,False],[0.05,2.],_ars_hx, + xE= numpy.array(bovy_ars([0.,0.],[True,False],[0.05,2.],_ars_hx, _ars_hpx,nsamples=n, hxparams=(self._surfaceSigmaProfile, None))) #Calculate E if self._beta == 0.: - E= sc.log(xE)+0.5 + E= numpylog(xE)+0.5 else: #non-flat rotation curve E= .5*xE**(2.*self._beta)*(1.+1./self._beta) #Then sample Lz LCE= xE**(self._beta+1.) OR= xE**(self._beta-1.) - Lz= self._surfaceSigmaProfile.sigma2(xE)*sc.log(stats.uniform.rvs(size=n))/OR + Lz= self._surfaceSigmaProfile.sigma2(xE)*numpylog(stats.uniform.rvs(size=n))/OR if self._correct: Lz*= self._corr.correct(xE,log=False)[1,:] Lz+= LCE @@ -1798,19 +1791,19 @@ wR, rap, rperi= self._ELtowRRapRperi(E[ii],Lz[ii]) except ValueError: continue - TR= 2.*math.pi/wR + TR= 2.*numpy.pi/wR tr= stats.uniform.rvs()*TR if tr > TR/2.: tr-= TR/2. thisOrbit= Orbit([rperi,0.,Lz[ii]/rperi]) else: thisOrbit= Orbit([rap,0.,Lz[ii]/rap]) - thisOrbit.integrate(sc.array([0.,tr]),self._psp) + thisOrbit.integrate(numpy.array([0.,tr]),self._psp) if returnOrbit: vxvv= thisOrbit(tr).vxvv[0] - thisOrbit= Orbit(vxvv=sc.array([vxvv[0],vxvv[1],vxvv[2], + thisOrbit= Orbit(vxvv=numpy.array([vxvv[0],vxvv[1],vxvv[2], stats.uniform.rvs()\ - *math.pi*2.])\ + *numpy.pi*2.])\ .reshape(4)) else: thisOrbit= thisOrbit(tr) @@ -1819,13 +1812,13 @@ if thisOrbit.vxvv[0,0] < rrange[0] \ or thisOrbit.vxvv[0,0] > rrange[1]: continue - mult= sc.ceil(kappa/wR*nphi)-1. + mult= numpy.ceil(kappa/wR*nphi)-1. kappawR= kappa/wR*nphi-mult while mult > 0: if returnOrbit: - out.append(Orbit(vxvv=sc.array([vxvv[0],vxvv[1], + out.append(Orbit(vxvv=numpy.array([vxvv[0],vxvv[1], vxvv[2], - stats.uniform.rvs()*math.pi*2.]).reshape(4))) + stats.uniform.rvs()*numpy.pi*2.]).reshape(4))) else: out.append(thisOrbit) mult-= 1 @@ -1850,8 +1843,8 @@ def _dlnfdR(self,R,vR,vT): #Calculate a bunch of stuff that we need if self._beta == 0.: - E= vR**2./2.+vT**2./2.+sc.log(R) - xE= sc.exp(E-.5) + E= vR**2./2.+vT**2./2.+numpylog(R) + xE= numpy.exp(E-.5) OE= xE**-1. LCE= xE dRedR= xE/R @@ -1867,8 +1860,8 @@ def _dlnfdvR(self,R,vR,vT): #Calculate a bunch of stuff that we need if self._beta == 0.: - E= vR**2./2.+vT**2./2.+sc.log(R) - xE= sc.exp(E-.5) + E= vR**2./2.+vT**2./2.+numpylog(R) + xE= numpy.exp(E-.5) OE= xE**-1. LCE= xE dRedvR= xE*vR @@ -1883,8 +1876,8 @@ def _dlnfdvT(self,R,vR,vT): #Calculate a bunch of stuff that we need if self._beta == 0.: - E= vR**2./2.+vT**2./2.+sc.log(R) - xE= sc.exp(E-.5) + E= vR**2./2.+vT**2./2.+numpylog(R) + xE= numpy.exp(E-.5) OE= xE**-1. LCE= xE dRedvT= xE*vT @@ -1902,8 +1895,8 @@ #Calculate a bunch of stuff that we need if E is None or xE is None or OE is None or LCE is None: if self._beta == 0.: - E= vR**2./2.+vT**2./2.+sc.log(R) - xE= sc.exp(E-.5) + E= vR**2./2.+vT**2./2.+numpylog(R) + xE= numpy.exp(E-.5) OE= xE**-1. LCE= xE else: #non-flat rotation curve @@ -1922,8 +1915,8 @@ #Calculate a bunch of stuff that we need if E is None or xE is None or OE is None: if self._beta == 0.: - E= vR**2./2.+vT**2./2.+sc.log(R) - xE= sc.exp(E-.5) + E= vR**2./2.+vT**2./2.+numpylog(R) + xE= numpy.exp(E-.5) OE= xE**-1. else: #non-flat rotation curve E= vR**2./2.+vT**2./2.+1./2./self._beta*R**(2.*self._beta) @@ -2004,18 +1997,18 @@ #Calculate RL,LL, OmegaL if self._beta == 0.: xL= L - logECLE= sc.log(-sc.log(xL)-0.5+E) + logECLE= numpylog(-numpylog(xL)-0.5+E) else: #non-flat rotation curve xL= L**(1./(self._beta+1.)) - logECLE= sc.log(-0.5*(1./self._beta+1.)*xL**(2.*self._beta)+E) + logECLE= numpylog(-0.5*(1./self._beta+1.)*xL**(2.*self._beta)+E) if xL < 0.: #We must remove counter-rotating mass return 0. if self._correct: correction= self._corr.correct(xL,log=True) else: - correction= sc.zeros(2) + correction= numpy.zeros(2) SRE2= self.targetSigma2(xL,log=True,use_physical=False)+correction[1] - return self._gamma*sc.exp(logsigmaR2-SRE2+self.targetSurfacemass(xL,log=True,use_physical=False)-logSigmaR-sc.exp(logECLE-SRE2)+correction[0])/2./nu.pi + return self._gamma*numpy.exp(logsigmaR2-SRE2+self.targetSurfacemass(xL,log=True,use_physical=False)-logSigmaR-numpy.exp(logECLE-SRE2)+correction[0])/2./numpy.pi def sample(self,n=1,rrange=None,returnROrbit=True,returnOrbit=False, nphi=1.,los=None,losdeg=True,nsigma=None,maxd=None, @@ -2053,12 +2046,12 @@ targetSigma2=targetSigma2) #First sample xL if self._correct: - xL= sc.array(bovy_ars([0.,0.],[True,False],[0.05,2.],_ars_hx, + xL= numpy.array(bovy_ars([0.,0.],[True,False],[0.05,2.],_ars_hx, _ars_hpx,nsamples=n, hxparams=(self._surfaceSigmaProfile, self._corr))) else: - xL= sc.array(bovy_ars([0.,0.],[True,False],[0.05,2.],_ars_hx, + xL= numpy.array(bovy_ars([0.,0.],[True,False],[0.05,2.],_ars_hx, _ars_hpx,nsamples=n, hxparams=(self._surfaceSigmaProfile, None))) @@ -2066,10 +2059,10 @@ Lz= xL**(self._beta+1.) #Then sample E if self._beta == 0.: - ECL= sc.log(xL)+0.5 + ECL= numpylog(xL)+0.5 else: ECL= 0.5*(1./self._beta+1.)*xL**(2.*self._beta) - E= -self._surfaceSigmaProfile.sigma2(xL)*sc.log(stats.uniform.rvs(size=n)) + E= -self._surfaceSigmaProfile.sigma2(xL)*numpylog(stats.uniform.rvs(size=n)) if self._correct: E*= self._corr.correct(xL,log=False)[1,:] E+= ECL @@ -2088,18 +2081,18 @@ wR, rap, rperi= self._ELtowRRapRperi(E[ii],Lz[ii]) except ValueError: #pragma: no cover continue - TR= 2.*math.pi/wR + TR= 2.*numpy.pi/wR tr= stats.uniform.rvs()*TR if tr > TR/2.: tr-= TR/2. thisOrbit= Orbit([rperi,0.,Lz[ii]/rperi]) else: thisOrbit= Orbit([rap,0.,Lz[ii]/rap]) - thisOrbit.integrate(sc.array([0.,tr]),self._psp) + thisOrbit.integrate(numpy.array([0.,tr]),self._psp) if returnOrbit: vxvv= thisOrbit(tr).vxvv[0] - thisOrbit= Orbit(vxvv=sc.array([vxvv[0],vxvv[1],vxvv[2], - stats.uniform.rvs()*math.pi*2.]).reshape(4)) + thisOrbit= Orbit(vxvv=numpy.array([vxvv[0],vxvv[1],vxvv[2], + stats.uniform.rvs()*numpy.pi*2.]).reshape(4)) else: thisOrbit= thisOrbit(tr) kappa= _kappa(thisOrbit.vxvv[0,0],self._beta) @@ -2107,13 +2100,13 @@ if thisOrbit.vxvv[0,0] < rrange[0] \ or thisOrbit.vxvv[0,0] > rrange[1]: continue - mult= sc.ceil(kappa/wR*nphi)-1. + mult= numpy.ceil(kappa/wR*nphi)-1. kappawR= kappa/wR*nphi-mult while mult > 0: if returnOrbit: - out.append(Orbit(vxvv=sc.array([vxvv[0],vxvv[1], + out.append(Orbit(vxvv=numpy.array([vxvv[0],vxvv[1], vxvv[2], - stats.uniform.rvs()*math.pi*2.]).reshape(4))) + stats.uniform.rvs()*numpy.pi*2.]).reshape(4))) else: out.append(thisOrbit) mult-= 1 @@ -2139,7 +2132,7 @@ if self._beta == 0.: xL= L dRldR= vT - ECL= sc.log(xL)+0.5 + ECL= numpylog(xL)+0.5 dECLEdR= 0. else: #non-flat rotation curve xL= L**(1./(self._beta+1.)) @@ -2169,7 +2162,7 @@ if self._beta == 0.: xL= L dRldvT= R - ECL= sc.log(xL)+0.5 + ECL= numpylog(xL)+0.5 dECLEdvT= 1./vT-vT else: #non-flat rotation curve xL= L**(1./(self._beta+1.)) @@ -2241,20 +2234,20 @@ def _surfaceIntegrand(vR,vT,R,df,logSigmaR,logsigmaR2,sigmaR1,gamma): """Internal function that is the integrand for the surface mass integration""" E,L= _vRpvTpRToEL(vR,vT,R,df._beta,sigmaR1,gamma,df._dftype) - return df.eval(E,L,logSigmaR,logsigmaR2)*2.*nu.pi/df._gamma #correct + return df.eval(E,L,logSigmaR,logsigmaR2)*2.*numpy.pi/df._gamma #correct def _sigma2surfaceIntegrand(vR,vT,R,df,logSigmaR,logsigmaR2,sigmaR1,gamma): """Internal function that is the integrand for the sigma-squared times surface mass integration""" E,L= _vRpvTpRToEL(vR,vT,R,df._beta,sigmaR1,gamma,df._dftype) - return vR**2.*df.eval(E,L,logSigmaR,logsigmaR2)*2.*nu.pi/df._gamma #correct + return vR**2.*df.eval(E,L,logSigmaR,logsigmaR2)*2.*numpy.pi/df._gamma #correct def _vmomentsurfaceIntegrand(vR,vT,R,df,logSigmaR,logsigmaR2,sigmaR1,gamma, n,m): """Internal function that is the integrand for the velocity moment times surface mass integration""" E,L= _vRpvTpRToEL(vR,vT,R,df._beta,sigmaR1,gamma,df._dftype) - return vR**n*vT**m*df.eval(E,L,logSigmaR,logsigmaR2)*2.*nu.pi/df._gamma #correct + return vR**n*vT**m*df.eval(E,L,logSigmaR,logsigmaR2)*2.*numpy.pi/df._gamma #correct def _vmomentderivsurfaceIntegrand(vR,vT,R,df,logSigmaR,logsigmaR2,sigmaR1, gamma,n,m,deriv): @@ -2262,7 +2255,7 @@ moment times surface mass integration""" E,L= _vRpvTpRToEL(vR,vT,R,df._beta,sigmaR1,gamma,df._dftype) if deriv.lower() == 'r': - return vR**n*vT**m*df.eval(E,L,logSigmaR,logsigmaR2)*2.*nu.pi/df._gamma*df._dlnfdR(R,vR*sigmaR1,vT*sigmaR1/gamma) #correct + return vR**n*vT**m*df.eval(E,L,logSigmaR,logsigmaR2)*2.*numpy.pi/df._gamma*df._dlnfdR(R,vR*sigmaR1,vT*sigmaR1/gamma) #correct else: return 0. @@ -2334,7 +2327,7 @@ self._npoints= kwargs['npoints'] self._dftype= kwargs.get('dftype',dehnendf) self._beta= kwargs.get('beta',0.) - self._rs= sc.linspace(_RMIN,self._rmax,self._npoints) + self._rs= numpy.linspace(_RMIN,self._rmax,self._npoints) self._interp_k= kwargs.get('interp_k',_INTERPDEGREE) if 'corrections' in kwargs: self._corrections= kwargs['corrections'] @@ -2345,22 +2338,22 @@ self._savefilename= self._createSavefilename(self._niter) if os.path.exists(self._savefilename): savefile= open(self._savefilename,'rb') - self._corrections= sc.array(pickle.load(savefile)) + self._corrections= numpy.array(pickle.load(savefile)) savefile.close() else: #Calculate the corrections self._corrections= self._calc_corrections() #Interpolation; smoothly go to zero - interpRs= sc.append(self._rs,2.*self._rmax) + interpRs= numpy.append(self._rs,2.*self._rmax) self._surfaceInterpolate= interpolate.InterpolatedUnivariateSpline(interpRs, - sc.log(sc.append(self._corrections[:,0],1.)), + numpylog(numpy.append(self._corrections[:,0],1.)), k=self._interp_k) self._sigma2Interpolate= interpolate.InterpolatedUnivariateSpline(interpRs, - sc.log(sc.append(self._corrections[:,1],1.)), + numpylog(numpy.append(self._corrections[:,1],1.)), k=self._interp_k) #Interpolation for R < _RMIN - surfaceInterpolateSmallR= interpolate.UnivariateSpline(interpRs[0:_INTERPDEGREE+2],sc.log(self._corrections[0:_INTERPDEGREE+2,0]),k=_INTERPDEGREE) + surfaceInterpolateSmallR= interpolate.UnivariateSpline(interpRs[0:_INTERPDEGREE+2],numpylog(self._corrections[0:_INTERPDEGREE+2,0]),k=_INTERPDEGREE) self._surfaceDerivSmallR= surfaceInterpolateSmallR.derivatives(interpRs[0])[1] - sigma2InterpolateSmallR= interpolate.UnivariateSpline(interpRs[0:_INTERPDEGREE+2],sc.log(self._corrections[0:_INTERPDEGREE+2,1]),k=_INTERPDEGREE) + sigma2InterpolateSmallR= interpolate.UnivariateSpline(interpRs[0:_INTERPDEGREE+2],numpylog(self._corrections[0:_INTERPDEGREE+2,1]),k=_INTERPDEGREE) self._sigma2DerivSmallR= sigma2InterpolateSmallR.derivatives(interpRs[0])[1] return None @@ -2391,42 +2384,42 @@ HISTORY: 2010-03-10 - Written - Bovy (NYU) """ - if isinstance(R,nu.ndarray): - out= nu.empty((2,len(R))) + if isinstance(R,numpy.ndarray): + out= numpy.empty((2,len(R))) #R < _RMIN rmin_indx= (R < _RMIN) - if nu.sum(rmin_indx) > 0: - out[0,rmin_indx]= math.log(self._corrections[0,0])\ + if numpy.sum(rmin_indx) > 0: + out[0,rmin_indx]= numpylog(self._corrections[0,0])\ +self._surfaceDerivSmallR*(R[rmin_indx]-_RMIN) - out[1,rmin_indx]= math.log(self._corrections[0,1])\ + out[1,rmin_indx]= numpylog(self._corrections[0,1])\ +self._sigma2DerivSmallR*(R[rmin_indx]-_RMIN) #R > 2rmax rmax_indx= (R > (2.*self._rmax)) - if nu.sum(rmax_indx) > 0: + if numpy.sum(rmax_indx) > 0: out[:,rmax_indx]= 0. #'normal' R r_indx= (R >= _RMIN)*(R <= (2.*self._rmax)) - if nu.sum(r_indx) > 0: + if numpy.sum(r_indx) > 0: out[0,r_indx]= self._surfaceInterpolate(R[r_indx]) out[1,r_indx]= self._sigma2Interpolate(R[r_indx]) if log: return out - else: return nu.exp(out) + else: return numpy.exp(out) if R < _RMIN: - out= sc.array([sc.log(self._corrections[0,0])+self._surfaceDerivSmallR*(R-_RMIN), - sc.log(self._corrections[0,1])+self._sigma2DerivSmallR*(R-_RMIN)]) + out= numpy.array([numpylog(self._corrections[0,0])+self._surfaceDerivSmallR*(R-_RMIN), + numpylog(self._corrections[0,1])+self._sigma2DerivSmallR*(R-_RMIN)]) elif R > (2.*self._rmax): - out= sc.array([0.,0.]) + out= numpy.array([0.,0.]) else: - if _SCIPYVERSION >= 0.9: - out= sc.array([self._surfaceInterpolate(R), + if _SCIPY_VERSION >= _SCIPY_VERSION_BREAK: + out= numpy.array([self._surfaceInterpolate(R), self._sigma2Interpolate(R)]) else: #pragma: no cover - out= sc.array([self._surfaceInterpolate(R)[0], + out= numpy.array([self._surfaceInterpolate(R)[0], self._sigma2Interpolate(R)[0]]) if log: return out else: - return sc.exp(out) + return numpy.exp(out) def derivLogcorrect(self,R): @@ -2444,16 +2437,16 @@ 2010-03-10 - Written - Bovy (NYU) """ if R < _RMIN: - out= sc.array([self._surfaceDerivSmallR, + out= numpy.array([self._surfaceDerivSmallR, self._sigma2DerivSmallR]) elif R > (2.*self._rmax): - out= sc.array([0.,0.]) + out= numpy.array([0.,0.]) else: - if _SCIPYVERSION >= 0.9: - out= sc.array([self._surfaceInterpolate(R,nu=1), + if _SCIPY_VERSION >= _SCIPY_VERSION_BREAK: + out= numpy.array([self._surfaceInterpolate(R,nu=1), self._sigma2Interpolate(R,nu=1)]) else: #pragma: no cover - out= sc.array([self._surfaceInterpolate(R,nu=1)[0], + out= numpy.array([self._surfaceInterpolate(R,nu=1)[0], self._sigma2Interpolate(R,nu=1)[0]]) return out @@ -2465,13 +2458,13 @@ trySavefilename= self._createSavefilename(searchIter) if os.path.exists(trySavefilename): trySavefile= open(trySavefilename,'rb') - corrections= sc.array(pickle.load(trySavefile)) + corrections= numpy.array(pickle.load(trySavefile)) trySavefile.close() break else: searchIter-= 1 if searchIter == 0: - corrections= sc.ones((self._npoints,2)) + corrections= numpy.ones((self._npoints,2)) for ii in range(searchIter,self._niter): if ii == 0: currentDF= self._dftype(surfaceSigma=self._surfaceSigmaProfile, @@ -2484,7 +2477,7 @@ rmax=self._rmax, savedir=self._savedir, interp_k=self._interp_k) - newcorrections= sc.zeros((self._npoints,2)) + newcorrections= numpy.zeros((self._npoints,2)) for jj in range(self._npoints): thisSurface= currentDF.surfacemass(self._rs[jj], use_physical=False) @@ -2523,7 +2516,7 @@ """ if dftype == 'schwarzschild': # Compute E in the epicycle approximation - gamma= sc.sqrt(2./(1.+beta)) + gamma= numpy.sqrt(2./(1.+beta)) L= R*vT if beta == 0.: xL= L @@ -2550,13 +2543,13 @@ 2010-03-01 - Written - Bovy (NYU) """ if beta == 0.: - if nu.any(R == 0.): - out= nu.empty(R.shape) - out[R == 0.]= math.log(_RMIN) - out[R != 0.]= nu.log(R[R != 0.]) + if numpy.any(R == 0.): + out= numpy.empty(R.shape) + out[R == 0.]= numpylog(_RMIN) + out[R != 0.]= numpylog(R[R != 0.]) return out else: - return nu.log(R) + return numpylog(R) else: #non-flat rotation curve return R**(2.*beta)/2./beta @@ -2578,9 +2571,9 @@ """ surfaceSigma, dfcorr= args if dfcorr is None: - return math.log(x)+surfaceSigma.surfacemass(x,log=True) + return numpylog(x)+surfaceSigma.surfacemass(x,log=True) else: - return math.log(x)+surfaceSigma.surfacemass(x,log=True)+dfcorr.correct(x)[0] + return numpylog(x)+surfaceSigma.surfacemass(x,log=True)+dfcorr.correct(x)[0] def _ars_hpx(x,args): """ @@ -2606,26 +2599,26 @@ def _kappa(R,beta): """Internal function to give kappa(r)""" - return math.sqrt(2.*(1.+beta))*R**(beta-1) + return numpy.sqrt(2.*(1.+beta))*R**(beta-1) def _dlToRphi(d,l): """Convert d and l to R and phi, l is in radians""" - R= math.sqrt(1.+d**2.-2.*d*math.cos(l)) + R= numpy.sqrt(1.+d**2.-2.*d*numpy.cos(l)) if R == 0.: R+= 0.0001 d+= 0.0001 - if 1./math.cos(l) < d and math.cos(l) > 0.: - theta= math.pi-math.asin(d/R*math.sin(l)) + if 1./numpy.cos(l) < d and numpy.cos(l) > 0.: + theta= numpy.pi-numpy.arcsin(d/R*numpy.sin(l)) else: - theta= math.asin(d/R*math.sin(l)) + theta= numpy.arcsin(d/R*numpy.sin(l)) return (R,theta) def _vtmaxEq(vT,R,diskdf): """Equation to solve to find the max vT at R""" #Calculate a bunch of stuff that we need if diskdf._beta == 0.: - E= vT**2./2.+sc.log(R) - xE= sc.exp(E-.5) + E= vT**2./2.+numpylog(R) + xE= numpy.exp(E-.5) OE= xE**-1. LCE= xE dxEdvT= xE*vT diff -Nru galpy-1.5/galpy/df/evolveddiskdf.py galpy-1.6.0.post0/galpy/df/evolveddiskdf.py --- galpy-1.5/galpy/df/evolveddiskdf.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/df/evolveddiskdf.py 2020-04-24 19:48:38.000000000 +0000 @@ -11,26 +11,25 @@ _NTS= 1000 _PROFILE= False import sys -import math import copy import time as time_module import warnings -import numpy as nu +import numpy from scipy import integrate -from galpy.util import galpyWarning -from galpy.orbit import Orbit -from galpy.potential import calcRotcurve +from ..util import galpyWarning +from ..orbit import Orbit +from ..potential import calcRotcurve from .df import df, _APY_LOADED -from galpy.potential.Potential import _check_c -from galpy.util.bovy_quadpack import dblquad -from galpy.util import bovy_plot -from galpy.util.bovy_conversion import physical_conversion, \ +from ..potential.Potential import _check_c +from ..util.bovy_quadpack import dblquad +from ..util import bovy_plot +from ..util.bovy_conversion import physical_conversion, \ potential_physical_input, time_in_Gyr if _APY_LOADED: from astropy import units -_DEGTORAD= math.pi/180. -_RADTODEG= 180./math.pi -_NAN= nu.nan +_DEGTORAD= numpy.pi/180. +_RADTODEG= 180./numpy.pi +_NAN= numpy.nan class evolveddiskdf(df): """Class that represents a diskdf as initial DF + subsequent secular evolution""" def __init__(self,initdf,pot,to=0.): @@ -133,9 +132,9 @@ else: raise IOError("Input to __call__ not understood; this has to be an Orbit instance with optional time") if isinstance(t,list): - t= nu.array(t) + t= numpy.array(t) tlist= True - elif isinstance(t,nu.ndarray) and \ + elif isinstance(t,numpy.ndarray) and \ not (hasattr(t,'isscalar') and t.isscalar): tlist= True else: tlist= False @@ -144,20 +143,20 @@ if kwargs.pop('marginalizeVperp',False): if tlist: raise IOError("Input times to __call__ is a list; this is not supported in conjunction with marginalizeVperp") if kwargs.pop('log',False): - return nu.log(self._call_marginalizevperp(args[0],integrate_method=integrate_method,**kwargs)) + return numpy.log(self._call_marginalizevperp(args[0],integrate_method=integrate_method,**kwargs)) else: return self._call_marginalizevperp(args[0],integrate_method=integrate_method,**kwargs) elif kwargs.pop('marginalizeVlos',False): if tlist: raise IOError("Input times to __call__ is a list; this is not supported in conjunction with marginalizeVlos") if kwargs.pop('log',False): - return nu.log(self._call_marginalizevlos(args[0],integrate_method=integrate_method,**kwargs)) + return numpy.log(self._call_marginalizevlos(args[0],integrate_method=integrate_method,**kwargs)) else: return self._call_marginalizevlos(args[0],integrate_method=integrate_method,**kwargs) #Integrate back if tlist: if self._to == t[0]: if kwargs.get('log',False): - return nu.log([self._initdf(args[0],use_physical=False)]) + return numpy.log([self._initdf(args[0],use_physical=False)]) else: return [self._initdf(args[0],use_physical=False)] ts= self._create_ts_tlist(t,integrate_method) @@ -179,8 +178,8 @@ msg= o.integrate_dxdv([0.,0.,0.,dderiv],ts,self._pot,method=integrate_method) if not msg is None and msg > 0.: # pragma: no cover print("Warning: dxdv integration inaccurate, returning zero everywhere ... result might not be correct ...") - if kwargs.get('log',False) and deriv is None: return nu.zeros(len(t))-nu.finfo(nu.dtype(nu.float64)).max - else: return nu.zeros(len(t)) + if kwargs.get('log',False) and deriv is None: return numpy.zeros(len(t))-numpy.finfo(numpy.dtype(numpy.float64)).max + else: return numpy.zeros(len(t)) else: o.integrate(ts,self._pot,method=integrate_method) if _PROFILE: #pragma: no cover @@ -191,7 +190,7 @@ if integrate_method == 'odeint': retval= [] os= [o(self._to+t[0]-ti,use_physical=False) for ti in t] - retval= nu.array(self._initdf(os,use_physical=False)) + retval= numpy.array(self._initdf(os,use_physical=False)) else: if len(t) == 1: orb_array= o.getOrbit().T @@ -200,10 +199,10 @@ orb_array= o.getOrbit().T retval= self._initdf(orb_array,use_physical=False) if (isinstance(retval,float) or len(retval.shape) == 0) \ - and nu.isnan(retval): + and numpy.isnan(retval): retval= 0. elif not isinstance(retval,float) and len(retval.shape) > 0: - retval[(nu.isnan(retval))]= 0. + retval[(numpy.isnan(retval))]= 0. if len(t) > 1: retval= retval[::-1] if _PROFILE: #pragma: no cover df_time= (time_module.time()-start) @@ -211,21 +210,21 @@ print(int_time/tot_time, df_time/tot_time, tot_time) if not deriv is None: if integrate_method == 'odeint': - dlnfdRo= nu.array([self._initdf._dlnfdR(o.R(self._to+t[0]-ti,use_physical=False), + dlnfdRo= numpy.array([self._initdf._dlnfdR(o.R(self._to+t[0]-ti,use_physical=False), o.vR(self._to+t[0]-ti,use_physical=False), o.vT(self._to+t[0]-ti,use_physical=False)) for ti in t]) - dlnfdvRo= nu.array([self._initdf._dlnfdvR(o.R(self._to+t[0]-ti,use_physical=False), + dlnfdvRo= numpy.array([self._initdf._dlnfdvR(o.R(self._to+t[0]-ti,use_physical=False), o.vR(self._to+t[0]-ti,use_physical=False), o.vT(self._to+t[0]-ti,use_physical=False)) for ti in t]) - dlnfdvTo= nu.array([self._initdf._dlnfdvT(o.R(self._to+t[0]-ti,use_physical=False), + dlnfdvTo= numpy.array([self._initdf._dlnfdvT(o.R(self._to+t[0]-ti,use_physical=False), o.vR(self._to+t[0]-ti,use_physical=False), o.vT(self._to+t[0]-ti,use_physical=False)) for ti in t]) - dRo= nu.array([o.getOrbit_dxdv()[list(ts).index(self._to+t[0]-ti),0] for ti in t])/dderiv - dvRo= nu.array([o.getOrbit_dxdv()[list(ts).index(self._to+t[0]-ti),1] for ti in t])/dderiv - dvTo= nu.array([o.getOrbit_dxdv()[list(ts).index(self._to+t[0]-ti),2] for ti in t])/dderiv + dRo= numpy.array([o.getOrbit_dxdv()[list(ts).index(self._to+t[0]-ti),0] for ti in t])/dderiv + dvRo= numpy.array([o.getOrbit_dxdv()[list(ts).index(self._to+t[0]-ti),1] for ti in t])/dderiv + dvTo= numpy.array([o.getOrbit_dxdv()[list(ts).index(self._to+t[0]-ti),2] for ti in t])/dderiv #print(dRo, dvRo, dvTo) dlnfderiv= dlnfdRo*dRo+dlnfdvRo*dvRo+dlnfdvTo*dvTo retval*= dlnfderiv @@ -241,15 +240,15 @@ orb_array[1], orb_array[2]) else: - dlnfdRo= nu.array([self._initdf._dlnfdR(orb_array[0,ii], + dlnfdRo= numpy.array([self._initdf._dlnfdR(orb_array[0,ii], orb_array[1,ii], orb_array[2,ii]) for ii in range(len(t))]) - dlnfdvRo= nu.array([self._initdf._dlnfdvR(orb_array[0,ii], + dlnfdvRo= numpy.array([self._initdf._dlnfdvR(orb_array[0,ii], orb_array[1,ii], orb_array[2,ii]) for ii in range(len(t))]) - dlnfdvTo= nu.array([self._initdf._dlnfdvT(orb_array[0,ii], + dlnfdvTo= numpy.array([self._initdf._dlnfdvT(orb_array[0,ii], orb_array[1,ii], orb_array[2,ii]) for ii in range(len(t))]) @@ -265,7 +264,7 @@ else: if self._to == t and deriv is None: if kwargs.get('log',False): - return nu.log(self._initdf(args[0],use_physical=False)) + return numpy.log(self._initdf(args[0],use_physical=False)) else: return self._initdf(args[0],use_physical=False) elif self._to == t and not deriv is None: @@ -277,13 +276,13 @@ elif deriv.lower() == 'phi': return 0. if integrate_method == 'odeint': - ts= nu.linspace(t,self._to,_NTS) + ts= numpy.linspace(t,self._to,_NTS) else: - ts= nu.linspace(t,self._to,2) + ts= numpy.linspace(t,self._to,2) o= args[0] #integrate orbit if not deriv is None: - ts= nu.linspace(t,self._to,_NTS) + ts= numpy.linspace(t,self._to,_NTS) #Also calculate the derivative of the initial df with respect to R, phi, vR, and vT, and the derivative of Ro wrt R/phi etc., to calculate the derivative; in this case we also integrate a small area of phase space if deriv.lower() == 'r': dderiv= 10.**-10. @@ -301,14 +300,14 @@ #Now evaluate the DF if o.R(self._to-t,use_physical=False) <= 0.: if kwargs.get('log',False): - return -nu.finfo(nu.dtype(nu.float64)).max + return -numpy.finfo(numpy.dtype(numpy.float64)).max else: - return nu.finfo(nu.dtype(nu.float64)).eps + return numpy.finfo(numpy.dtype(numpy.float64)).eps #start= time.time() retval= self._initdf(o(self._to-t,use_physical=False), use_physical=False) #print( int_time/(time.time()-start)) - if nu.isnan(retval): print(retval, o.vxvv, o(self._to-t).vxvv) + if numpy.isnan(retval): print(retval, o.vxvv, o(self._to-t).vxvv) if not deriv is None: thisorbit= o(self._to-t).vxvv[0] dlnfdRo= self._initdf._dlnfdR(thisorbit[0], @@ -328,11 +327,11 @@ retval*= dlnfderiv if kwargs.get('log',False) and deriv is None: if tlist: - out= nu.log(retval) - out[retval == 0.]= -nu.finfo(nu.dtype(nu.float64)).max + out= numpy.log(retval) + out[retval == 0.]= -numpy.finfo(numpy.dtype(numpy.float64)).max else: - if retval == 0.: out= -nu.finfo(nu.dtype(nu.float64)).max - else: out= nu.log(retval) + if retval == 0.: out= -numpy.finfo(numpy.dtype(numpy.float64)).max + else: out= numpy.log(retval) return out else: return retval @@ -423,15 +422,15 @@ and hasattr(self._initdf,'_estimatemeanvT') \ and hasattr(self._initdf,'_estimateSigmaR2') \ and hasattr(self._initdf,'_estimateSigmaT2'): - sigmaR1= nu.sqrt(self._initdf._estimateSigmaR2(R,phi=az)) - sigmaT1= nu.sqrt(self._initdf._estimateSigmaT2(R,phi=az)) + sigmaR1= numpy.sqrt(self._initdf._estimateSigmaR2(R,phi=az)) + sigmaT1= numpy.sqrt(self._initdf._estimateSigmaT2(R,phi=az)) meanvR= self._initdf._estimatemeanvR(R,phi=az) meanvT= self._initdf._estimatemeanvT(R,phi=az) else: warnings.warn("No '_estimateSigmaR2' etc. functions found for initdf in evolveddf; thus using potentially slow sigmaR2 etc functions", galpyWarning) - sigmaR1= nu.sqrt(self._initdf.sigmaR2(R,phi=az,use_physical=False)) - sigmaT1= nu.sqrt(self._initdf.sigmaT2(R,phi=az,use_physical=False)) + sigmaR1= numpy.sqrt(self._initdf.sigmaR2(R,phi=az,use_physical=False)) + sigmaT1= numpy.sqrt(self._initdf.sigmaT2(R,phi=az,use_physical=False)) meanvR= self._initdf.meanvR(R,phi=az,use_physical=False) meanvT= self._initdf.meanvT(R,phi=az,use_physical=False) if _PROFILE: #pragma: no cover @@ -470,15 +469,15 @@ phi=phi) if initvmoment == 0.: initvmoment= 1. norm= sigmaR1**(n+1)*sigmaT1**(m+1)*initvmoment - if isinstance(t,(list,nu.ndarray)): + if isinstance(t,(list,numpy.ndarray)): raise IOError("list of times is only supported with grid-based calculation") return dblquad(_vmomentsurfaceIntegrand, meanvT/sigmaT1-nsigma, meanvT/sigmaT1+nsigma, lambda x: meanvR/sigmaR1 - -nu.sqrt(nsigma**2.-(x-meanvT/sigmaT1)**2.), + -numpy.sqrt(nsigma**2.-(x-meanvT/sigmaT1)**2.), lambda x: meanvR/sigmaR1 - +nu.sqrt(nsigma**2.-(x-meanvT/sigmaT1)**2.), + +numpy.sqrt(nsigma**2.-(x-meanvT/sigmaT1)**2.), (R,az,self,n,m,sigmaR1,sigmaT1,t,initvmoment), epsrel=epsrel,epsabs=epsabs)[0]*norm @@ -589,9 +588,9 @@ if returnGrid and ((isinstance(grid,bool) and grid) or isinstance(grid,evolveddiskdfGrid) or isinstance(grid,evolveddiskdfHierarchicalGrid)): - return (-nu.arctan(2.*sigmaRT/(sigmaR2-sigmaT2))/2.,grido) + return (-numpy.arctan(2.*sigmaRT/(sigmaR2-sigmaT2))/2.,grido) else: - return -nu.arctan(2.*sigmaRT/(sigmaR2-sigmaT2))/2. + return -numpy.arctan(2.*sigmaRT/(sigmaR2-sigmaT2))/2. @potential_physical_input @physical_conversion('velocity',pop=True) @@ -1833,11 +1832,11 @@ nt= grid.df.shape[2] out= [] for ii in range(nt): - out.append(nu.dot(grid.vRgrid**n,nu.dot(grid.df[:,:,ii],grid.vTgrid**m))*\ + out.append(numpy.dot(grid.vRgrid**n,numpy.dot(grid.df[:,:,ii],grid.vTgrid**m))*\ (grid.vRgrid[1]-grid.vRgrid[0])*(grid.vTgrid[1]-grid.vTgrid[0])) - return nu.array(out) + return numpy.array(out) else: - return nu.dot(grid.vRgrid**n,nu.dot(grid.df,grid.vTgrid**m))*\ + return numpy.dot(grid.vRgrid**n,numpy.dot(grid.df,grid.vTgrid**m))*\ (grid.vRgrid[1]-grid.vRgrid[0])*(grid.vTgrid[1]-grid.vTgrid[0]) def _buildvgrid(self,R,phi,nsigma,t,sigmaR1,sigmaT1,meanvR,meanvT, @@ -1848,13 +1847,13 @@ out.sigmaT1= sigmaT1 out.meanvR= meanvR out.meanvT= meanvT - out.vRgrid= nu.linspace(meanvR-nsigma*sigmaR1,meanvR+nsigma*sigmaR1, + out.vRgrid= numpy.linspace(meanvR-nsigma*sigmaR1,meanvR+nsigma*sigmaR1, gridpoints) - out.vTgrid= nu.linspace(meanvT-nsigma*sigmaT1,meanvT+nsigma*sigmaT1, + out.vTgrid= numpy.linspace(meanvT-nsigma*sigmaT1,meanvT+nsigma*sigmaT1, gridpoints) - if isinstance(t,(list,nu.ndarray)): + if isinstance(t,(list,numpy.ndarray)): nt= len(t) - out.df= nu.zeros((gridpoints,gridpoints,nt)) + out.df= numpy.zeros((gridpoints,gridpoints,nt)) for ii in range(gridpoints): for jj in range(gridpoints-1,-1,-1):#Reverse, so we get the peak before we get to the extreme lags NOT NECESSARY if print_progress: #pragma: no cover @@ -1862,13 +1861,13 @@ (jj+ii*gridpoints+1,gridpoints*gridpoints)) sys.stdout.flush() thiso= Orbit([R,out.vRgrid[ii],out.vTgrid[jj],phi]) - out.df[ii,jj,:]= self(thiso,nu.array(t).flatten(), + out.df[ii,jj,:]= self(thiso,numpy.array(t).flatten(), integrate_method=integrate_method, deriv=deriv,use_physical=False) - out.df[ii,jj,nu.isnan(out.df[ii,jj,:])]= 0. #BOVY: for now + out.df[ii,jj,numpy.isnan(out.df[ii,jj,:])]= 0. #BOVY: for now if print_progress: sys.stdout.write('\n') #pragma: no cover else: - out.df= nu.zeros((gridpoints,gridpoints)) + out.df= numpy.zeros((gridpoints,gridpoints)) for ii in range(gridpoints): for jj in range(gridpoints): if print_progress: #pragma: no cover @@ -1879,7 +1878,7 @@ out.df[ii,jj]= self(thiso,t, integrate_method=integrate_method, deriv=deriv,use_physical=False) - if nu.isnan(out.df[ii,jj]): out.df[ii,jj]= 0. #BOVY: for now + if numpy.isnan(out.df[ii,jj]): out.df[ii,jj]= 0. #BOVY: for now if print_progress: sys.stdout.write('\n') #pragma: no cover return out @@ -1889,20 +1888,20 @@ #Initialize if integrate_method == 'odeint': _NTS= 1000 - tmax= nu.amax(t) - ts= nu.linspace(tmax,self._to,_NTS) + tmax= numpy.amax(t) + ts= numpy.linspace(tmax,self._to,_NTS) #Add other t ts= list(ts) ts.extend([self._to+tmax-ti for ti in t if ti != tmax]) else: if len(t) == 1: #Special case this because it is confusing - ts= nu.array([t[0],self._to]) + ts= numpy.array([t[0],self._to]) else: - ts= -t+self._to+nu.amax(t) + ts= -t+self._to+numpy.amax(t) #sort ts= list(ts) ts.sort(reverse=True) - return nu.array(ts) + return numpy.array(ts) def _call_marginalizevperp(self,o,integrate_method='dopr54_c',**kwargs): """Call the DF, marginalizing over perpendicular velocity""" @@ -1916,7 +1915,7 @@ vcirc= calcRotcurve([p for p in self._pot if not p.isNonAxi],R)[0] else: vcirc= calcRotcurve(self._pot,R)[0] - vcirclos= vcirc*math.sin(phi+l) + vcirclos= vcirc*numpy.sin(phi+l) #Marginalize alphalos= phi+l if not 'nsigma' in kwargs or ('nsigma' in kwargs and \ @@ -1926,27 +1925,27 @@ nsigma= kwargs['nsigma'] kwargs.pop('nsigma',None) #BOVY: add asymmetric drift here? - if math.fabs(math.sin(alphalos)) < math.sqrt(1./2.): - sigmaR1= nu.sqrt(self._initdf.sigmaT2(R,phi=phi, + if numpy.fabs(numpy.sin(alphalos)) < numpy.sqrt(1./2.): + sigmaR1= numpy.sqrt(self._initdf.sigmaT2(R,phi=phi, use_physical=False)) #Slight abuse - cosalphalos= math.cos(alphalos) - tanalphalos= math.tan(alphalos) + cosalphalos= numpy.cos(alphalos) + tanalphalos= numpy.tan(alphalos) return integrate.quad(_marginalizeVperpIntegrandSinAlphaSmall, -nsigma,nsigma, args=(self,R,cosalphalos,tanalphalos, vlos-vcirclos,vcirc, sigmaR1,phi), - **kwargs)[0]/math.fabs(cosalphalos)*sigmaR1 + **kwargs)[0]/numpy.fabs(cosalphalos)*sigmaR1 else: - sigmaR1= nu.sqrt(self._initdf.sigmaR2(R,phi=phi, + sigmaR1= numpy.sqrt(self._initdf.sigmaR2(R,phi=phi, use_physical=False)) - sinalphalos= math.sin(alphalos) - cotalphalos= 1./math.tan(alphalos) + sinalphalos= numpy.sin(alphalos) + cotalphalos= 1./numpy.tan(alphalos) return integrate.quad(_marginalizeVperpIntegrandSinAlphaLarge, -nsigma,nsigma, args=(self,R,sinalphalos,cotalphalos, vlos-vcirclos,vcirc,sigmaR1,phi), - **kwargs)[0]/math.fabs(sinalphalos)*sigmaR1 + **kwargs)[0]/numpy.fabs(sinalphalos)*sigmaR1 def _call_marginalizevlos(self,o,integrate_method='dopr54_c',**kwargs): """Call the DF, marginalizing over line-of-sight velocity""" @@ -1961,21 +1960,21 @@ vcirc= calcRotcurve([p for p in self._pot if not p.isNonAxi],R)[0] else: vcirc= calcRotcurve(self._pot,R)[0] - vcircperp= vcirc*math.cos(phi+l) + vcircperp= vcirc*numpy.cos(phi+l) #Marginalize - alphaperp= math.pi/2.+phi+l + alphaperp= numpy.pi/2.+phi+l if not 'nsigma' in kwargs or ('nsigma' in kwargs and \ kwargs['nsigma'] is None): nsigma= _NSIGMA else: nsigma= kwargs['nsigma'] kwargs.pop('nsigma',None) - if math.fabs(math.sin(alphaperp)) < math.sqrt(1./2.): - sigmaR1= nu.sqrt(self._initdf.sigmaT2(R,phi=phi, + if numpy.fabs(numpy.sin(alphaperp)) < numpy.sqrt(1./2.): + sigmaR1= numpy.sqrt(self._initdf.sigmaT2(R,phi=phi, use_physical=False)) #slight abuse va= vcirc-self._initdf.meanvT(R,phi=phi,use_physical=False) - cosalphaperp= math.cos(alphaperp) - tanalphaperp= math.tan(alphaperp) + cosalphaperp= numpy.cos(alphaperp) + tanalphaperp= numpy.tan(alphaperp) #we can reuse the VperpIntegrand, since it is just another angle return integrate.quad(_marginalizeVperpIntegrandSinAlphaSmall, -va/sigmaR1-nsigma, @@ -1983,18 +1982,18 @@ args=(self,R,cosalphaperp,tanalphaperp, vperp-vcircperp,vcirc, sigmaR1,phi), - **kwargs)[0]/math.fabs(cosalphaperp)*sigmaR1 + **kwargs)[0]/numpy.fabs(cosalphaperp)*sigmaR1 else: - sigmaR1= nu.sqrt(self._initdf.sigmaR2(R,phi=phi, + sigmaR1= numpy.sqrt(self._initdf.sigmaR2(R,phi=phi, use_physical=False)) - sinalphaperp= math.sin(alphaperp) - cotalphaperp= 1./math.tan(alphaperp) + sinalphaperp= numpy.sin(alphaperp) + cotalphaperp= 1./numpy.tan(alphaperp) #we can reuse the VperpIntegrand, since it is just another angle return integrate.quad(_marginalizeVperpIntegrandSinAlphaLarge, -nsigma,nsigma, args=(self,R,sinalphaperp,cotalphaperp, vperp-vcircperp,vcirc,sigmaR1,phi), - **kwargs)[0]/math.fabs(sinalphaperp)*sigmaR1 + **kwargs)[0]/numpy.fabs(sinalphaperp)*sigmaR1 def _vmomentsurfacemassHierarchicalGrid(self,n,m,grid): """Internal function to evaluate vmomentsurfacemass using a @@ -2070,10 +2069,10 @@ self.meanvR= meanvR self.meanvT= meanvT self.gridpoints= gridpoints - self.vRgrid= nu.linspace(self.meanvR-nsigma*self.sigmaR1, + self.vRgrid= numpy.linspace(self.meanvR-nsigma*self.sigmaR1, self.meanvR+nsigma*self.sigmaR1, self.gridpoints) - self.vTgrid= nu.linspace(self.meanvT-nsigma*self.sigmaT1, + self.vTgrid= numpy.linspace(self.meanvT-nsigma*self.sigmaT1, self.meanvT+nsigma*self.sigmaT1, self.gridpoints) self.t= t @@ -2081,9 +2080,9 @@ nlevelsTotal= nlevels self.nlevels= nlevels self.nlevelsTotal= nlevelsTotal - if isinstance(t,(list,nu.ndarray)): + if isinstance(t,(list,numpy.ndarray)): nt= len(t) - self.df= nu.zeros((gridpoints,gridpoints,nt)) + self.df= numpy.zeros((gridpoints,gridpoints,nt)) dxdy= (self.vRgrid[1]-self.vRgrid[0])\ *(self.vTgrid[1]-self.vTgrid[0]) if nlevels > 0: @@ -2104,9 +2103,9 @@ and jj >= ysubmin and jj < ysubmax: continue thiso= Orbit([R,self.vRgrid[ii],self.vTgrid[jj],phi]) - self.df[ii,jj,:]= edf(thiso,nu.array(t).flatten(), + self.df[ii,jj,:]= edf(thiso,numpy.array(t).flatten(), deriv=deriv) - self.df[ii,jj,nu.isnan(self.df[ii,jj,:])]= 0.#BOVY: for now + self.df[ii,jj,numpy.isnan(self.df[ii,jj,:])]= 0.#BOVY: for now #Multiply in area, somewhat tricky for edge objects if upperdxdy is None or (ii != 0 and ii != gridpoints-1\ and jj != 0 @@ -2122,7 +2121,7 @@ self.df[ii,jj,:]*= 2.25*dxdy/2.25 #turn this off for now if print_progress: sys.stdout.write('\n') #pragma: no cover else: - self.df= nu.zeros((gridpoints,gridpoints)) + self.df= numpy.zeros((gridpoints,gridpoints)) dxdy= (self.vRgrid[1]-self.vRgrid[0])\ *(self.vTgrid[1]-self.vTgrid[0]) if nlevels > 0: @@ -2144,7 +2143,7 @@ continue thiso= Orbit([R,self.vRgrid[ii],self.vTgrid[jj],phi]) self.df[ii,jj]= edf(thiso,t,deriv=deriv) - if nu.isnan(self.df[ii,jj]): self.df[ii,jj]= 0. #BOVY: for now + if numpy.isnan(self.df[ii,jj]): self.df[ii,jj]= 0. #BOVY: for now #Multiply in area, somewhat tricky for edge objects if upperdxdy is None or (ii != 0 and ii != gridpoints-1\ and jj != 0 @@ -2180,21 +2179,21 @@ def __call__(self,n,m): """Call""" - if isinstance(self.t,(list,nu.ndarray)): tlist= True + if isinstance(self.t,(list,numpy.ndarray)): tlist= True else: tlist= False if tlist: nt= self.df.shape[2] out= [] for ii in range(nt): #We already multiplied in the area - out.append(nu.dot(self.vRgrid**n,nu.dot(self.df[:,:,ii], + out.append(numpy.dot(self.vRgrid**n,numpy.dot(self.df[:,:,ii], self.vTgrid**m))) - if self.subgrid is None: return nu.array(out) - else: return nu.array(out)+ self.subgrid(n,m) + if self.subgrid is None: return numpy.array(out) + else: return numpy.array(out)+ self.subgrid(n,m) else: #We already multiplied in the area - thislevel= nu.dot(self.vRgrid**n,nu.dot(self.df,self.vTgrid**m)) + thislevel= numpy.dot(self.vRgrid**n,numpy.dot(self.df,self.vTgrid**m)) if self.subgrid is None: return thislevel else: return thislevel+self.subgrid(n,m) @@ -2221,7 +2220,7 @@ nUpperLevels= self.nlevelsTotal-self.nlevels nvRTot= nvR*2**nUpperLevels nvTTot= nvT*2**nUpperLevels - plotthis= nu.zeros((nvRTot,nvTTot)) + plotthis= numpy.zeros((nvRTot,nvTTot)) if len(self.df.shape) == 3: plotdf= copy.copy(self.df[:,:,tt]) else: @@ -2268,16 +2267,16 @@ def max(self,tt=0): if not self.subgrid is None: if len(self.df.shape) == 3: - return nu.amax([nu.amax(self.df[:,:,tt]), + return numpy.amax([numpy.amax(self.df[:,:,tt]), self.subgrid.max(tt)]) else: - return nu.amax([nu.amax(self.df[:,:]), + return numpy.amax([numpy.amax(self.df[:,:]), self.subgrid.max()]) else: if len(self.df.shape) == 3: - return nu.amax(self.df[:,:,tt]) + return numpy.amax(self.df[:,:,tt]) else: - return nu.amax(self.df[:,:]) + return numpy.amax(self.df[:,:]) def _vmomentsurfaceIntegrand(vR,vT,R,az,df,n,m,sigmaR1,sigmaT1,t,initvmoment): diff -Nru galpy-1.5/galpy/df/jeans.py galpy-1.6.0.post0/galpy/df/jeans.py --- galpy-1.5/galpy/df/jeans.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/df/jeans.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,10 +1,10 @@ # jeans.py: utilities related to the Jeans equations import numpy from scipy import integrate -from galpy.potential.Potential import evaluateDensities, \ +from ..potential.Potential import evaluateDensities, \ evaluaterforces, evaluateSurfaceDensities -from galpy.potential.Potential import flatten as flatten_pot -from galpy.util.bovy_conversion import physical_conversion, \ +from ..potential.Potential import flatten as flatten_pot +from ..util.bovy_conversion import physical_conversion, \ potential_physical_input _INVSQRTTWO= 1./numpy.sqrt(2.) @potential_physical_input @@ -41,6 +41,7 @@ Pot= flatten_pot(Pot) if dens is None: dens= lambda r: evaluateDensities(Pot,r*_INVSQRTTWO,r*_INVSQRTTWO, + phi=numpy.pi/4., use_physical=False) if callable(beta): intFactor= lambda x: numpy.exp(2.*integrate.quad(lambda y: beta(y)/y, @@ -50,7 +51,8 @@ return numpy.sqrt(integrate.quad(lambda x: -intFactor(x)*dens(x) *evaluaterforces(Pot, x*_INVSQRTTWO, - x*_INVSQRTTWO, + x*_INVSQRTTWO, + phi=numpy.pi/4., use_physical=False), r,numpy.inf)[0]/ dens(r)/intFactor(r)) diff -Nru galpy-1.5/galpy/df/quasiisothermaldf.py galpy-1.6.0.post0/galpy/df/quasiisothermaldf.py --- galpy-1.5/galpy/df/quasiisothermaldf.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/df/quasiisothermaldf.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,19 +1,19 @@ #A 'Binney' quasi-isothermal DF -import math import warnings -import numpy import hashlib +import numpy from scipy import optimize, interpolate, integrate -from galpy import potential -from galpy import actionAngle -from galpy.actionAngle import actionAngleIsochrone -from galpy.potential import IsochronePotential -from galpy.potential import flatten as flatten_potential -from galpy.orbit import Orbit +from .. import potential +from .. import actionAngle +from ..actionAngle import actionAngleIsochrone +from ..potential import IsochronePotential +from ..potential import flatten as flatten_potential +from ..orbit import Orbit from .df import df, _APY_LOADED -from galpy.util import galpyWarning -from galpy.util.bovy_conversion import physical_conversion, \ - potential_physical_input, actionAngle_physical_input, _APY_UNITS +from ..util import galpyWarning +from ..util.bovy_conversion import physical_conversion, \ + potential_physical_input, actionAngle_physical_input, _APY_UNITS, \ + physical_compatible if _APY_LOADED: from astropy import units _NSIGMA=4 @@ -101,8 +101,8 @@ self._hsz= hsz self._refr= refr self._lo= lo - self._lnsr= math.log(self._sr) - self._lnsz= math.log(self._sz) + self._lnsr= numpy.log(self._sr) + self._lnsz= numpy.log(self._sz) self._maxVT_hash= None self._maxVT_ip= None if pot is None: @@ -118,6 +118,7 @@ not self._aA.b == self._pot.b and \ not self._aA.amp == self._pot._amp: raise IOError("Potential in aA does not appear to be the same as given potential pot") + self._check_consistent_units() self._cutcounter= cutcounter if _precomputerg: if _precomputergrmax is None: @@ -265,11 +266,11 @@ else: funcFactor= 1. if log: - lnfsr= numpy.log(Omega)+lnsurfmass-2.*lnsr-math.log(math.pi)\ + lnfsr= numpy.log(Omega)+lnsurfmass-2.*lnsr-numpy.log(numpy.pi)\ -numpy.log(kappa)\ +numpy.log(1.+numpy.tanh(lz/self._lo))\ -kappa*jr*numpy.exp(-2.*lnsr) - lnfsz= numpy.log(nu)-math.log(2.*math.pi)\ + lnfsz= numpy.log(nu)-numpy.log(2.*numpy.pi)\ -2.*lnsz-nu*jz*numpy.exp(-2.*lnsz) out= lnfsr+lnfsz+funcTerm if isinstance(lz,numpy.ndarray): @@ -278,11 +279,11 @@ elif numpy.isnan(out): out= -numpy.finfo(numpy.dtype(numpy.float64)).max else: srm2= numpy.exp(-2.*lnsr) - fsr= Omega*numpy.exp(lnsurfmass)*srm2/math.pi/kappa\ + fsr= Omega*numpy.exp(lnsurfmass)*srm2/numpy.pi/kappa\ *(1.+numpy.tanh(lz/self._lo))\ *numpy.exp(-kappa*jr*srm2) szm2= numpy.exp(-2.*lnsz) - fsz= nu/2./math.pi*szm2*numpy.exp(-nu*jz*szm2) + fsz= nu/2./numpy.pi*szm2*numpy.exp(-nu*jz*szm2) out= fsr*fsz*funcFactor if isinstance(lz,numpy.ndarray): out[numpy.isnan(out)]= 0. @@ -610,7 +611,7 @@ va= sigmaR1**2./2./thisvc\ *(gamma**2.-1. #Assume close to flat rotation curve, sigphi2/sigR2 =~ 0.5 +R*(1./self._hr+2./self._hsr)) - if math.fabs(va) > sigmaR1: va = 0.#To avoid craziness near the center + if numpy.fabs(va) > sigmaR1: va = 0.#To avoid craziness near the center if gl: if ngl % 2 == 1: raise ValueError("ngl must be even") @@ -824,7 +825,7 @@ va= sigmaR1**2./2./thisvc\ *(gamma**2.-1. #Assume close to flat rotation curve, sigphi2/sigR2 =~ 0.5 +R*(1./self._hr+2./self._hsr)) - if math.fabs(va) > sigmaR1: va = 0.#To avoid craziness near the center + if numpy.fabs(va) > sigmaR1: va = 0.#To avoid craziness near the center if mc: mvT= (thisvc-va)/gamma/sigmaR1 if _vrs is None: diff -Nru galpy-1.5/galpy/df/streamdf.py galpy-1.6.0.post0/galpy/df/streamdf.py --- galpy-1.5/galpy/df/streamdf.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/df/streamdf.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,26 +1,26 @@ #The DF of a tidal stream import copy -import numpy import multiprocessing +import warnings +from pkg_resources import parse_version +import numpy import scipy from scipy import special, interpolate, integrate, optimize -_SCIPY_VERSION= [int(v.split('rc')[0]) - for v in scipy.__version__.split('.')] -if _SCIPY_VERSION[0] < 1 and _SCIPY_VERSION[1] < 10: #pragma: no cover +_SCIPY_VERSION= parse_version(scipy.__version__) +if _SCIPY_VERSION < parse_version('0.10'): #pragma: no cover from scipy.maxentropy import logsumexp -elif _SCIPY_VERSION[0] < 1 and _SCIPY_VERSION[1] < 19: #pragma: no cover +elif _SCIPY_VERSION < parse_version('0.19'): #pragma: no cover from scipy.misc import logsumexp else: from scipy.special import logsumexp -from galpy.orbit import Orbit +from ..orbit import Orbit from .df import df, _APY_LOADED -from galpy.util import bovy_coords, fast_cholesky_invert, \ +from ..util import bovy_coords, fast_cholesky_invert, \ bovy_conversion, multi, bovy_plot, stable_cho_factor, bovy_ars -from galpy.util.bovy_conversion import physical_conversion, _APY_UNITS -from galpy.actionAngle.actionAngleIsochroneApprox import dePeriod -from galpy.potential import flatten as flatten_potential -import warnings -from galpy.util import galpyWarning +from ..util.bovy_conversion import physical_conversion, _APY_UNITS +from ..actionAngle.actionAngleIsochroneApprox import dePeriod +from ..potential import flatten as flatten_potential +from ..util import galpyWarning if _APY_LOADED: from astropy import units _INTERPDURINGSETUP= True @@ -169,6 +169,7 @@ self._aA= aA if not self._aA._pot == self._pot: raise IOError("Potential in aA does not appear to be the same as given potential pot") + self._check_consistent_units() if useTM: self._useTM= True self._aAT= useTM # confusing, no? diff -Nru galpy-1.5/galpy/df/streamgapdf.py galpy-1.6.0.post0/galpy/df/streamgapdf.py --- galpy-1.5/galpy/df/streamgapdf.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/df/streamgapdf.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,20 +1,20 @@ # The DF of a gap in a tidal stream from functools import wraps import copy -import numpy import warnings import multiprocessing +import numpy from scipy import integrate, interpolate, special -from galpy.util import galpyWarning, bovy_coords, multi, bovy_conversion -from galpy.util import _rotate_to_arbitrary_vector -from galpy.orbit import Orbit -from galpy.potential import evaluateRforces, MovingObjectPotential, \ +from ..util import galpyWarning, bovy_coords, multi, bovy_conversion +from ..util import _rotate_to_arbitrary_vector +from ..orbit import Orbit +from ..potential import evaluateRforces, MovingObjectPotential, \ PlummerPotential from .df import df, _APY_LOADED -from galpy.util.bovy_conversion import physical_conversion +from ..util.bovy_conversion import physical_conversion from . import streamdf from .streamdf import _determine_stream_track_single -from galpy.potential import flatten as flatten_potential +from ..potential import flatten as flatten_potential if _APY_LOADED: from astropy import units def impact_check_range(func): @@ -833,7 +833,7 @@ 0.) #angle = 0 auxiliaryTrack= Orbit(prog_stream_offset[3]) if dt < 0.: - self._gap_trackts= numpy.linspace(0.,-2.*dt,2.*self._nTrackChunksImpact-1) + self._gap_trackts= numpy.linspace(0.,-2.*dt,2*self._nTrackChunksImpact-1) #Flip velocities before integrating auxiliaryTrack= auxiliaryTrack.flip() auxiliaryTrack.integrate(self._gap_trackts,self._pot) diff -Nru galpy-1.5/galpy/df/surfaceSigmaProfile.py galpy-1.6.0.post0/galpy/df/surfaceSigmaProfile.py --- galpy-1.5/galpy/df/surfaceSigmaProfile.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/df/surfaceSigmaProfile.py 2020-04-24 19:48:38.000000000 +0000 @@ -9,7 +9,7 @@ # density profile and an exponential sigma_R # profile ############################################################################### -import scipy as sc +import numpy class surfaceSigmaProfile(object): """Class that contains the surface density and sigma_R^2 profile""" def __init__(self): @@ -116,7 +116,7 @@ if log: return -R/self._params[0] else: - return sc.exp(-R/self._params[0]) + return numpy.exp(-R/self._params[0]) def surfacemassDerivative(self,R,log=False): """ @@ -135,7 +135,7 @@ if log: return -1./self._params[0] else: - return -sc.exp(-R/self._params[0])/self._params[0] + return -numpy.exp(-R/self._params[0])/self._params[0] def sigma2(self,R,log=False): """ @@ -152,9 +152,9 @@ 2010-03-26 - Written - Bovy (NYU) """ if log: - return 2.*sc.log(self._params[2])-2.*(R-1.)/self._params[1] + return 2.*numpy.log(self._params[2])-2.*(R-1.)/self._params[1] else: - return self._params[2]**2.*sc.exp(-2.*(R-1.)/self._params[1]) + return self._params[2]**2.*numpy.exp(-2.*(R-1.)/self._params[1]) def sigma2Derivative(self,R,log=False): """ @@ -173,5 +173,5 @@ if log: return -2./self._params[1] else: - return self._params[2]**2.*sc.exp(-2.*(R-1.)/self._params[1])\ + return self._params[2]**2.*numpy.exp(-2.*(R-1.)/self._params[1])\ *(-2./self._params[1]) diff -Nru galpy-1.5/galpy/__init__.py galpy-1.6.0.post0/galpy/__init__.py --- galpy-1.5/galpy/__init__.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/__init__.py 2020-04-24 19:48:38.000000000 +0000 @@ -1 +1 @@ -__version__ = "1.5" +__version__ = "1.6.0" diff -Nru galpy-1.5/galpy/orbit/integrateFullOrbit.py galpy-1.6.0.post0/galpy/orbit/integrateFullOrbit.py --- galpy-1.5/galpy/orbit/integrateFullOrbit.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/orbit/integrateFullOrbit.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,47 +1,20 @@ -import sys -import distutils.sysconfig as sysconfig import warnings -import numpy as nu -from scipy import integrate import ctypes import ctypes.util from numpy.ctypeslib import ndpointer -import os -from galpy import potential -from galpy.util import galpyWarning +import numpy +from scipy import integrate +from .. import potential +from ..util import galpyWarning from ..potential.Potential import _evaluateRforces, _evaluatezforces,\ _evaluatephiforces from .integratePlanarOrbit import _parse_integrator, _parse_tol from ..util.multi import parallel_map from ..util.leung_dop853 import dop853 from ..util import bovy_symplecticode as symplecticode -#Find and load the library -_lib= None -outerr= None -PY3= sys.version > '3' -if PY3: - _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') -else: #pragma: no cover - _ext_suffix= '.so' -for path in sys.path: - try: - _lib = ctypes.CDLL(os.path.join(path,'galpy_integrate_c%s' % _ext_suffix)) - except OSError as e: - if os.path.exists(os.path.join(path,'galpy_integrate_c%s' % _ext_suffix)): #pragma: no cover - outerr= e - _lib = None - else: - break -if _lib is None: #pragma: no cover - if not outerr is None: - warnings.warn("integrateFullOrbit_c extension module not loaded, because of error '%s' " % outerr, - galpyWarning) - else: - warnings.warn("integrateFullOrbit_c extension module not loaded, because galpy_integrate_c%s image was not found" % _ext_suffix, - galpyWarning) - _ext_loaded= False -else: - _ext_loaded= True +from ..util import _load_extension_libs + +_lib, _ext_loaded= _load_extension_libs.load_libgalpy() def _parse_pot(pot,potforactions=False,potfortorus=False): """Parse the potential so it can be fed to C""" @@ -105,19 +78,19 @@ else: # pragma: no cover warnings.warn("You are attempting to use the C implementation of interpRZPotential, but have not interpolated the potential itself; if you think this is needed for what you want to do, initialize the interpRZPotential instance with interpPot=True", galpyWarning) - pot_args.extend(list(nu.ones(len(p._rgrid)*len(p._zgrid)))) + pot_args.extend(list(numpy.ones(len(p._rgrid)*len(p._zgrid)))) if hasattr(p,'_rforceGrid_splinecoeffs'): pot_args.extend([x for x in p._rforceGrid_splinecoeffs.flatten(order='C')]) else: # pragma: no cover warnings.warn("You are attempting to use the C implementation of interpRZPotential, but have not interpolated the Rforce; if you think this is needed for what you want to do, initialize the interpRZPotential instance with interpRforce=True", galpyWarning) - pot_args.extend(list(nu.ones(len(p._rgrid)*len(p._zgrid)))) + pot_args.extend(list(numpy.ones(len(p._rgrid)*len(p._zgrid)))) if hasattr(p,'_zforceGrid_splinecoeffs'): pot_args.extend([x for x in p._zforceGrid_splinecoeffs.flatten(order='C')]) else: # pragma: no cover warnings.warn("You are attempting to use the C implementation of interpRZPotential, but have not interpolated the zforce; if you think this is needed for what you want to do, initialize the interpRZPotential instance with interpzforce=True", galpyWarning) - pot_args.extend(list(nu.ones(len(p._rgrid)*len(p._zgrid)))) + pot_args.extend(list(numpy.ones(len(p._rgrid)*len(p._zgrid)))) pot_args.extend([p._amp,int(p._logR)]) elif isinstance(p,potential.IsochronePotential): pot_type.append(14) @@ -170,12 +143,12 @@ if not p._aligned: pot_args.extend(list(p._rot.flatten())) else: - pot_args.extend(list(nu.eye(3).flatten())) # not actually used + pot_args.extend(list(numpy.eye(3).flatten())) # not actually used pot_args.append(p._glorder) pot_args.extend([p._glx[ii] for ii in range(p._glorder)]) # this adds some common factors to the integration weights - pot_args.extend([-4.*nu.pi*p._glw[ii]*p._b*p._c\ - /nu.sqrt(( 1.+(p._b2-1.)*p._glx[ii]**2.) + pot_args.extend([-4.*numpy.pi*p._glw[ii]*p._b*p._c\ + /numpy.sqrt(( 1.+(p._b2-1.)*p._glx[ii]**2.) *(1.+(p._c2-1.)*p._glx[ii]**2.)) for ii in range(p._glorder)]) elif isinstance(p,potential.SCFPotential): @@ -199,15 +172,14 @@ npot+= 1 pot_type.append(26) stype= Sigma.get('type','exp') - if stype == 'exp' \ - or (stype == 'exp' and 'Rhole' in Sigma): + if stype == 'exp' and not 'Rhole' in Sigma: pot_args.extend([3,0, - 4.*nu.pi*Sigma.get('amp',1.)*p._amp, + 4.*numpy.pi*Sigma.get('amp',1.)*p._amp, Sigma.get('h',1./3.)]) elif stype == 'expwhole' \ or (stype == 'exp' and 'Rhole' in Sigma): pot_args.extend([4,1, - 4.*nu.pi*Sigma.get('amp',1.)*p._amp, + 4.*numpy.pi*Sigma.get('amp',1.)*p._amp, Sigma.get('h',1./3.), Sigma.get('Rhole',0.5)]) hztype= hz.get('type','exp') @@ -221,6 +193,17 @@ p._Rs, p._H, p._omega]) pot_args.extend(p._Cs) # 30: PerfectEllipsoidPotential, done with others above + # 31: KGPotential + # 32: IsothermalDiskPotential + elif isinstance(p,potential.DehnenCoreSphericalPotential): + pot_type.append(33) + pot_args.extend([p._amp,p.a]) + elif isinstance(p,potential.DehnenSphericalPotential): + pot_type.append(34) + pot_args.extend([p._amp,p.a,p.alpha]) + elif isinstance(p,potential.HomogeneousSpherePotential): + pot_type.append(35) + pot_args.extend([p._amp,p._R2,p._R3]) ############################## WRAPPERS ############################### elif isinstance(p,potential.DehnenSmoothWrapperPotential): pot_type.append(-1) @@ -275,8 +258,26 @@ pot_args.extend(p._orb.z(p._orb.t,use_physical=False)) pot_args.extend([p._amp]) pot_args.extend([p._orb.t[0],p._orb.t[-1]]) #t_0, t_f - pot_type= nu.array(pot_type,dtype=nu.int32,order='C') - pot_args= nu.array(pot_args,dtype=nu.float64,order='C') + elif isinstance(p,potential.ChandrasekharDynamicalFrictionForce): + pot_type.append(-7) + wrap_npot, wrap_pot_type, wrap_pot_args= \ + _parse_pot(p._dens_pot, + potforactions=potforactions,potfortorus=potfortorus) + pot_args.append(wrap_npot) + pot_type.extend(wrap_pot_type) + pot_args.extend(wrap_pot_args) + pot_args.extend([len(p._sigmar_rs_4interp)]) + pot_args.extend(p._sigmar_rs_4interp) + pot_args.extend(p._sigmars_4interp) + pot_args.extend([p._amp]) + pot_args.extend([-1.,0.,0.,0.,0.,0.,0.,0.]) # for caching + pot_args.extend([p._ms,p._rhm,p._gamma**2., + -1 if not p._lnLambda else p._lnLambda, + p._minr**2.]) + pot_args.extend([p._sigmar_rs_4interp[0], + p._sigmar_rs_4interp[-1]]) #r_0, r_f + pot_type= numpy.array(pot_type,dtype=numpy.int32,order='C') + pot_args= numpy.array(pot_args,dtype=numpy.float64,order='C') return (npot,pot_type,pot_args) def _parse_scf_pot(p,extra_amp=1.): @@ -315,7 +316,7 @@ """ if len(yo.shape) == 1: single_obj= True else: single_obj= False - yo= nu.atleast_2d(yo) + yo= numpy.atleast_2d(yo) nobj= len(yo) rtol, atol= _parse_tol(rtol,atol) npot, pot_type, pot_args= _parse_pot(pot) @@ -324,33 +325,33 @@ dt= -9999.99 #Set up result array - result= nu.empty((nobj,len(t),6)) - err= nu.zeros(nobj,dtype=nu.int32) + result= numpy.empty((nobj,len(t),6)) + err= numpy.zeros(nobj,dtype=numpy.int32) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') integrationFunc= _lib.integrateFullOrbit integrationFunc.argtypes= [ctypes.c_int, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.int32,flags=ndarrayFlags), - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.int32,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_double, ctypes.c_double, ctypes.c_double, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), - ndpointer(dtype=nu.int32,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.int32,flags=ndarrayFlags), ctypes.c_int] #Array requirements, first store old order f_cont= [yo.flags['F_CONTIGUOUS'], t.flags['F_CONTIGUOUS']] - yo= nu.require(yo,dtype=nu.float64,requirements=['C','W']) - t= nu.require(t,dtype=nu.float64,requirements=['C','W']) - result= nu.require(result,dtype=nu.float64,requirements=['C','W']) - err= nu.require(err,dtype=nu.int32,requirements=['C','W']) + yo= numpy.require(yo,dtype=numpy.float64,requirements=['C','W']) + t= numpy.require(t,dtype=numpy.float64,requirements=['C','W']) + result= numpy.require(result,dtype=numpy.float64,requirements=['C','W']) + err= numpy.require(err,dtype=numpy.int32,requirements=['C','W']) #Run the C code integrationFunc(ctypes.c_int(nobj), @@ -367,12 +368,12 @@ err, ctypes.c_int(int_method_c)) - if nu.any(err == -10): #pragma: no cover + if numpy.any(err == -10): #pragma: no cover raise KeyboardInterrupt("Orbit integration interrupted by CTRL-C (SIGINT)") #Reset input arrays - if f_cont[0]: yo= nu.asfortranarray(yo) - if f_cont[1]: t= nu.asfortranarray(t) + if f_cont[0]: yo= numpy.asfortranarray(yo) + if f_cont[1]: t= numpy.asfortranarray(t) if single_obj: return (result[0],err[0]) else: return (result,err) @@ -402,33 +403,33 @@ rtol, atol= _parse_tol(rtol,atol) npot, pot_type, pot_args= _parse_pot(pot) int_method_c= _parse_integrator(int_method) - yo= nu.concatenate((yo,dyo)) + yo= numpy.concatenate((yo,dyo)) #Set up result array - result= nu.empty((len(t),12)) + result= numpy.empty((len(t),12)) err= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') integrationFunc= _lib.integrateFullOrbit_dxdv - integrationFunc.argtypes= [ndpointer(dtype=nu.float64,flags=ndarrayFlags), + integrationFunc.argtypes= [ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.int32,flags=ndarrayFlags), - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.int32,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_double, ctypes.c_double, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int), ctypes.c_int] #Array requirements, first store old order f_cont= [yo.flags['F_CONTIGUOUS'], t.flags['F_CONTIGUOUS']] - yo= nu.require(yo,dtype=nu.float64,requirements=['C','W']) - t= nu.require(t,dtype=nu.float64,requirements=['C','W']) - result= nu.require(result,dtype=nu.float64,requirements=['C','W']) + yo= numpy.require(yo,dtype=numpy.float64,requirements=['C','W']) + t= numpy.require(t,dtype=numpy.float64,requirements=['C','W']) + result= numpy.require(result,dtype=numpy.float64,requirements=['C','W']) #Run the C code integrationFunc(yo, @@ -446,8 +447,8 @@ raise KeyboardInterrupt("Orbit integration interrupted by CTRL-C (SIGINT)") #Reset input arrays - if f_cont[0]: yo= nu.asfortranarray(yo) - if f_cont[1]: t= nu.asfortranarray(t) + if f_cont[0]: yo= numpy.asfortranarray(yo) + if f_cont[1]: t= numpy.asfortranarray(t) return (result,err.value) @@ -481,28 +482,28 @@ if len(yo[0]) == 5: nophi= True #We hack this by putting in a dummy phi=0 - yo= nu.pad(yo,((0,0),(0,1)),'constant',constant_values=0) + yo= numpy.pad(yo,((0,0),(0,1)),'constant',constant_values=0) if int_method.lower() == 'leapfrog': if rtol is None: rtol= 1e-8 def integrate_for_map(vxvv): #go to the rectangular frame - this_vxvv= nu.array([vxvv[0]*nu.cos(vxvv[5]), - vxvv[0]*nu.sin(vxvv[5]), + this_vxvv= numpy.array([vxvv[0]*numpy.cos(vxvv[5]), + vxvv[0]*numpy.sin(vxvv[5]), vxvv[3], - vxvv[1]*nu.cos(vxvv[5]) - -vxvv[2]*nu.sin(vxvv[5]), - vxvv[2]*nu.cos(vxvv[5]) - +vxvv[1]*nu.sin(vxvv[5]), + vxvv[1]*numpy.cos(vxvv[5]) + -vxvv[2]*numpy.sin(vxvv[5]), + vxvv[2]*numpy.cos(vxvv[5]) + +vxvv[1]*numpy.sin(vxvv[5]), vxvv[4]]) #integrate out= symplecticode.leapfrog(_rectForce,this_vxvv, t,args=(pot,),rtol=rtol) #go back to the cylindrical frame - R= nu.sqrt(out[:,0]**2.+out[:,1]**2.) - phi= nu.arccos(out[:,0]/R) - phi[(out[:,1] < 0.)]= 2.*nu.pi-phi[(out[:,1] < 0.)] - vR= out[:,3]*nu.cos(phi)+out[:,4]*nu.sin(phi) - vT= out[:,4]*nu.cos(phi)-out[:,3]*nu.sin(phi) + R= numpy.sqrt(out[:,0]**2.+out[:,1]**2.) + phi= numpy.arccos(out[:,0]/R) + phi[(out[:,1] < 0.)]= 2.*numpy.pi-phi[(out[:,1] < 0.)] + vR= out[:,3]*numpy.cos(phi)+out[:,4]*numpy.sin(phi) + vT= out[:,4]*numpy.cos(phi)-out[:,3]*numpy.sin(phi) out[:,3]= out[:,2] out[:,4]= out[:,5] out[:,0]= R @@ -525,7 +526,7 @@ init= [vxvv[0],vxvv[1],vxvv[3],vxvv[4]] intOut= integrator(_RZEOM,init,t=t,args=(pot,l2), **extra_kwargs) - out= nu.zeros((len(t),5)) + out= numpy.zeros((len(t),5)) out[:,0]= intOut[:,0] out[:,1]= intOut[:,1] out[:,3]= intOut[:,2] @@ -540,7 +541,7 @@ vphi= vxvv[2]/vxvv[0] init= [vxvv[0],vxvv[1],vxvv[5],vphi,vxvv[3],vxvv[4]] intOut= integrator(_EOM,init,t=t,args=(pot,)) - out= nu.zeros((len(t),6)) + out= numpy.zeros((len(t),6)) out[:,0]= intOut[:,0] out[:,1]= intOut[:,1] out[:,2]= out[:,0]*intOut[:,3] @@ -550,19 +551,19 @@ #post-process to remove negative radii neg_radii= (out[:,0] < 0.) out[neg_radii,0]= -out[neg_radii,0] - out[neg_radii,3]+= nu.pi + out[neg_radii,3]+= numpy.pi return out else: # Assume we are forcing parallel_mapping of a C integrator... def integrate_for_map(vxvv): - return integrateFullOrbit_c(pot,nu.copy(vxvv), + return integrateFullOrbit_c(pot,numpy.copy(vxvv), t,int_method,dt=dt)[0] if len(yo) == 1: # Can't map a single value... - out= nu.atleast_3d(integrate_for_map(yo[0]).T).T + out= numpy.atleast_3d(integrate_for_map(yo[0]).T).T else: - out= nu.array((parallel_map(integrate_for_map,yo,numcores=numcores))) + out= numpy.array((parallel_map(integrate_for_map,yo,numcores=numcores))) if nophi: out= out[:,:,:5] - return out, nu.zeros(len(yo)) + return out, numpy.zeros(len(yo)) def _RZEOM(y,t,pot,l2): """ @@ -630,15 +631,15 @@ 2011-02-02 - Written - Bovy (NYU) """ #x is rectangular so calculate R and phi - R= nu.sqrt(x[0]**2.+x[1]**2.) - phi= nu.arccos(x[0]/R) + R= numpy.sqrt(x[0]**2.+x[1]**2.) + phi= numpy.arccos(x[0]/R) sinphi= x[1]/R cosphi= x[0]/R - if x[1] < 0.: phi= 2.*nu.pi-phi + if x[1] < 0.: phi= 2.*numpy.pi-phi #calculate forces Rforce= _evaluateRforces(pot,R,x[2],phi=phi,t=t) phiforce= _evaluatephiforces(pot,R,x[2],phi=phi,t=t) - return nu.array([cosphi*Rforce-1./R*sinphi*phiforce, + return numpy.array([cosphi*Rforce-1./R*sinphi*phiforce, sinphi*Rforce+1./R*cosphi*phiforce, _evaluatezforces(pot,R,x[2],phi=phi,t=t)]) diff -Nru galpy-1.5/galpy/orbit/integrateLinearOrbit.py galpy-1.6.0.post0/galpy/orbit/integrateLinearOrbit.py --- galpy-1.5/galpy/orbit/integrateLinearOrbit.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/orbit/integrateLinearOrbit.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,49 +1,19 @@ -import sys -import distutils.sysconfig as sysconfig -import warnings -import numpy as nu -from scipy import integrate import ctypes import ctypes.util from numpy.ctypeslib import ndpointer -import os -from galpy import potential -from galpy.util import galpyWarning +import numpy +from scipy import integrate +from .. import potential from ..util.multi import parallel_map from .integratePlanarOrbit import _parse_integrator, _parse_tol from .integrateFullOrbit import _parse_pot as _parse_pot_full from ..potential.linearPotential import _evaluatelinearForces -from galpy.potential.verticalPotential import verticalPotential -from galpy.potential.WrapperPotential import parentWrapperPotential +from ..potential.verticalPotential import verticalPotential from ..util.leung_dop853 import dop853 from ..util import bovy_symplecticode as symplecticode -#Find and load the library -_lib= None -outerr= None -PY3= sys.version > '3' -if PY3: - _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') -else: #pragma: no cover - _ext_suffix= '.so' -for path in sys.path: - try: - _lib = ctypes.CDLL(os.path.join(path,'galpy_integrate_c%s' % _ext_suffix)) - except OSError as e: - if os.path.exists(os.path.join(path,'galpy_integrate_c%s' % _ext_suffix)): #pragma: no cover - outerr= e - _lib = None - else: - break -if _lib is None: #pragma: no cover - if not outerr is None: - warnings.warn("integrateLinearOrbit_c extension module not loaded, because of error '%s' " % outerr, - galpyWarning) - else: - warnings.warn("integrateLinearOrbit_c extension module not loaded, because galpy_integrate_c%s image was not found" % _ext_suffix, - galpyWarning) - _ext_loaded= False -else: - _ext_loaded= True +from ..util import _load_extension_libs + +_lib, _ext_loaded= _load_extension_libs.load_libgalpy() def _parse_pot(pot): """Parse the potential so it can be fed to C""" @@ -87,15 +57,14 @@ npot+= 1 pot_type.append(26) stype= Sigma.get('type','exp') - if stype == 'exp' \ - or (stype == 'exp' and 'Rhole' in Sigma): + if stype == 'exp' and not 'Rhole' in Sigma: pot_args.extend([3,0, - 4.*nu.pi*Sigma.get('amp',1.)*p._Pot._amp, + 4.*numpy.pi*Sigma.get('amp',1.)*p._Pot._amp, Sigma.get('h',1./3.)]) elif stype == 'expwhole' \ or (stype == 'exp' and 'Rhole' in Sigma): pot_args.extend([4,1, - 4.*nu.pi*Sigma.get('amp',1.)*p._Pot._amp, + 4.*numpy.pi*Sigma.get('amp',1.)*p._Pot._amp, Sigma.get('h',1./3.), Sigma.get('Rhole',0.5)]) hztype= hz.get('type','exp') @@ -117,8 +86,8 @@ pot_args.extend(pa) pot_args.append(p._R) pot_args.append(p._phi) - pot_type= nu.array(pot_type,dtype=nu.int32,order='C') - pot_args= nu.array(pot_args,dtype=nu.float64,order='C') + pot_type= numpy.array(pot_type,dtype=numpy.int32,order='C') + pot_args= numpy.array(pot_args,dtype=numpy.float64,order='C') return (npot,pot_type,pot_args) def integrateLinearOrbit_c(pot,yo,t,int_method,rtol=None,atol=None,dt=None): @@ -146,7 +115,7 @@ """ if len(yo.shape) == 1: single_obj= True else: single_obj= False - yo= nu.atleast_2d(yo) + yo= numpy.atleast_2d(yo) nobj= len(yo) rtol, atol= _parse_tol(rtol,atol) npot, pot_type, pot_args= _parse_pot(pot) @@ -155,33 +124,33 @@ dt= -9999.99 #Set up result array - result= nu.empty((nobj,len(t),2)) - err= nu.zeros(nobj,dtype=nu.int32) + result= numpy.empty((nobj,len(t),2)) + err= numpy.zeros(nobj,dtype=numpy.int32) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') integrationFunc= _lib.integrateLinearOrbit integrationFunc.argtypes= [ctypes.c_int, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.int32,flags=ndarrayFlags), - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.int32,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_double, ctypes.c_double, ctypes.c_double, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), - ndpointer(dtype=nu.int32,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.int32,flags=ndarrayFlags), ctypes.c_int] #Array requirements, first store old order f_cont= [yo.flags['F_CONTIGUOUS'], t.flags['F_CONTIGUOUS']] - yo= nu.require(yo,dtype=nu.float64,requirements=['C','W']) - t= nu.require(t,dtype=nu.float64,requirements=['C','W']) - result= nu.require(result,dtype=nu.float64,requirements=['C','W']) - err= nu.require(err,dtype=nu.int32,requirements=['C','W']) + yo= numpy.require(yo,dtype=numpy.float64,requirements=['C','W']) + t= numpy.require(t,dtype=numpy.float64,requirements=['C','W']) + result= numpy.require(result,dtype=numpy.float64,requirements=['C','W']) + err= numpy.require(err,dtype=numpy.int32,requirements=['C','W']) #Run the C code integrationFunc(ctypes.c_int(nobj), @@ -197,12 +166,12 @@ err, ctypes.c_int(int_method_c)) - if nu.any(err == -10): #pragma: no cover + if numpy.any(err == -10): #pragma: no cover raise KeyboardInterrupt("Orbit integration interrupted by CTRL-C (SIGINT)") #Reset input arrays - if f_cont[0]: yo= nu.asfortranarray(yo) - if f_cont[1]: t= nu.asfortranarray(t) + if f_cont[0]: yo= numpy.asfortranarray(yo) + if f_cont[1]: t= numpy.asfortranarray(t) if single_obj: return (result[0],err[0]) else: return (result,err) @@ -238,7 +207,7 @@ def integrate_for_map(vxvv): return symplecticode.leapfrog(lambda x,t=t: \ _evaluatelinearForces(pot,x,t=t), - nu.array(vxvv), + numpy.array(vxvv), t,rtol=rtol) elif int_method.lower() == 'dop853': if rtol is None: rtol= 1e-8 @@ -250,13 +219,13 @@ return integrate.odeint(_linearEOM,vxvv,t,args=(pot,),rtol=rtol) else: # Assume we are forcing parallel_mapping of a C integrator... def integrate_for_map(vxvv): - return integrateLinearOrbit_c(pot,nu.copy(vxvv), + return integrateLinearOrbit_c(pot,numpy.copy(vxvv), t,int_method,dt=dt)[0] if len(yo) == 1: # Can't map a single value... - return nu.atleast_3d(integrate_for_map(yo[0]).T).T, 0 + return numpy.atleast_3d(integrate_for_map(yo[0]).T).T, 0 else: - return (nu.array((parallel_map(integrate_for_map,yo,numcores=numcores))), - nu.zeros(len(yo))) + return (numpy.array((parallel_map(integrate_for_map,yo,numcores=numcores))), + numpy.zeros(len(yo))) def _linearEOM(y,t,pot): """ diff -Nru galpy-1.5/galpy/orbit/integratePlanarOrbit.py galpy-1.6.0.post0/galpy/orbit/integratePlanarOrbit.py --- galpy-1.5/galpy/orbit/integratePlanarOrbit.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/orbit/integratePlanarOrbit.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,49 +1,20 @@ -import sys -import distutils.sysconfig as sysconfig -import warnings -import numpy as nu -from scipy import integrate import ctypes import ctypes.util from numpy.ctypeslib import ndpointer -import os -from galpy import potential -from galpy.potential.planarPotential import planarPotentialFromFullPotential, \ +import numpy +from scipy import integrate +from .. import potential +from ..potential.planarPotential import planarPotentialFromFullPotential, \ planarPotentialFromRZPotential from ..potential.planarPotential import _evaluateplanarRforces,\ _evaluateplanarphiforces, _evaluateplanarPotentials -from galpy.potential.WrapperPotential import parentWrapperPotential -from galpy.util import galpyWarning +from ..potential.WrapperPotential import parentWrapperPotential from ..util.multi import parallel_map from ..util.leung_dop853 import dop853 from ..util import bovy_symplecticode as symplecticode -#Find and load the library -_lib= None -outerr= None -PY3= sys.version > '3' -if PY3: - _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') -else: #pragma: no cover - _ext_suffix= '.so' -for path in sys.path: - try: - _lib = ctypes.CDLL(os.path.join(path,'galpy_integrate_c%s' % _ext_suffix)) - except OSError as e: - if os.path.exists(os.path.join(path,'galpy_integrate_c%s' % _ext_suffix)): #pragma: no cover - outerr= e - _lib = None - else: - break -if _lib is None: #pragma: no cover - if not outerr is None: - warnings.warn("integratePlanarOrbit_c extension module not loaded, because of error '%s' " % outerr, - galpyWarning) - else: - warnings.warn("integratePlanarOrbit_c extension module not loaded, because galpy_integrate_c%s image was not found" % _ext_suffix, - galpyWarning) - _ext_loaded= False -else: - _ext_loaded= True +from ..util import _load_extension_libs + +_lib, _ext_loaded= _load_extension_libs.load_libgalpy() def _parse_pot(pot): """Parse the potential so it can be fed to C""" @@ -202,12 +173,12 @@ if not p._Pot._aligned: pot_args.extend(list(p._Pot._rot.flatten())) else: - pot_args.extend(list(nu.eye(3).flatten())) # not actually used + pot_args.extend(list(numpy.eye(3).flatten())) # not actually used pot_args.append(p._Pot._glorder) pot_args.extend([p._Pot._glx[ii] for ii in range(p._Pot._glorder)]) # this adds some common factors to the integration weights - pot_args.extend([-4.*nu.pi*p._Pot._glw[ii]*p._Pot._b*p._Pot._c\ - /nu.sqrt(( 1.+(p._Pot._b2-1.)*p._Pot._glx[ii]**2.) + pot_args.extend([-4.*numpy.pi*p._Pot._glw[ii]*p._Pot._b*p._Pot._c\ + /numpy.sqrt(( 1.+(p._Pot._b2-1.)*p._Pot._glx[ii]**2.) *(1.+(p._Pot._c2-1.)*p._Pot._glx[ii]**2.)) for ii in range(p._Pot._glorder)]) elif (isinstance(p,planarPotentialFromFullPotential) or isinstance(p,planarPotentialFromRZPotential)) \ @@ -234,15 +205,14 @@ npot+= 1 pot_type.append(26) stype= Sigma.get('type','exp') - if stype == 'exp' \ - or (stype == 'exp' and 'Rhole' in Sigma): + if stype == 'exp' and not 'Rhole' in Sigma: pot_args.extend([3,0, - 4.*nu.pi*Sigma.get('amp',1.)*p._Pot._amp, + 4.*numpy.pi*Sigma.get('amp',1.)*p._Pot._amp, Sigma.get('h',1./3.)]) elif stype == 'expwhole' \ or (stype == 'exp' and 'Rhole' in Sigma): pot_args.extend([4,1, - 4.*nu.pi*Sigma.get('amp',1.)*p._Pot._amp, + 4.*numpy.pi*Sigma.get('amp',1.)*p._Pot._amp, Sigma.get('h',1./3.), Sigma.get('Rhole',0.5)]) hztype= hz.get('type','exp') @@ -264,6 +234,21 @@ pot_type.append(29) pot_args.extend([p._amp]) # 30: PerfectEllipsoidPotential, done with other EllipsoidalPotentials above + # 31: KGPotential + # 32: IsothermalDiskPotential + elif isinstance(p, planarPotentialFromRZPotential) \ + and isinstance(p._Pot,potential.DehnenCoreSphericalPotential): + pot_type.append(33) + pot_args.extend([p._Pot._amp,p._Pot.a]) + elif isinstance(p, planarPotentialFromRZPotential) \ + and isinstance(p._Pot,potential.DehnenSphericalPotential): + pot_type.append(34) + pot_args.extend([p._Pot._amp,p._Pot.a,p._Pot.alpha]) + # 35: HomogeneousSpherePotential + elif isinstance(p,planarPotentialFromRZPotential) \ + and isinstance(p._Pot,potential.HomogeneousSpherePotential): + pot_type.append(35) + pot_args.extend([p._Pot._amp,p._Pot._R2,p._Pot._R3]) ############################## WRAPPERS ############################### elif ((isinstance(p,planarPotentialFromFullPotential) or isinstance(p,planarPotentialFromRZPotential)) \ and isinstance(p._Pot,potential.DehnenSmoothWrapperPotential)) \ @@ -326,8 +311,8 @@ pot_args.extend(p._orb.y(p._orb.t,use_physical=False)) pot_args.extend([p._amp]) pot_args.extend([p._orb.t[0],p._orb.t[-1]]) #t_0, t_f - pot_type= nu.array(pot_type,dtype=nu.int32,order='C') - pot_args= nu.array(pot_args,dtype=nu.float64,order='C') + pot_type= numpy.array(pot_type,dtype=numpy.int32,order='C') + pot_args= numpy.array(pot_args,dtype=numpy.float64,order='C') return (npot,pot_type,pot_args) def _parse_integrator(int_method): @@ -353,13 +338,13 @@ """Parse the tolerance keywords""" #Process atol and rtol if rtol is None: - rtol= -12.*nu.log(10.) + rtol= -12.*numpy.log(10.) else: #pragma: no cover - rtol= nu.log(rtol) + rtol= numpy.log(rtol) if atol is None: - atol= -12.*nu.log(10.) + atol= -12.*numpy.log(10.) else: #pragma: no cover - atol= nu.log(atol) + atol= numpy.log(atol) return (rtol,atol) def integratePlanarOrbit_c(pot,yo,t,int_method,rtol=None,atol=None, @@ -388,7 +373,7 @@ """ if len(yo.shape) == 1: single_obj= True else: single_obj= False - yo= nu.atleast_2d(yo) + yo= numpy.atleast_2d(yo) nobj= len(yo) rtol, atol= _parse_tol(rtol,atol) npot, pot_type, pot_args= _parse_pot(pot) @@ -397,33 +382,33 @@ dt= -9999.99 #Set up result array - result= nu.empty((nobj,len(t),4)) - err= nu.zeros(nobj,dtype=nu.int32) + result= numpy.empty((nobj,len(t),4)) + err= numpy.zeros(nobj,dtype=numpy.int32) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') integrationFunc= _lib.integratePlanarOrbit integrationFunc.argtypes= [ctypes.c_int, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.int32,flags=ndarrayFlags), - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.int32,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_double, ctypes.c_double, ctypes.c_double, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), - ndpointer(dtype=nu.int32,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.int32,flags=ndarrayFlags), ctypes.c_int] #Array requirements, first store old order f_cont= [yo.flags['F_CONTIGUOUS'], t.flags['F_CONTIGUOUS']] - yo= nu.require(yo,dtype=nu.float64,requirements=['C','W']) - t= nu.require(t,dtype=nu.float64,requirements=['C','W']) - result= nu.require(result,dtype=nu.float64,requirements=['C','W']) - err= nu.require(err,dtype=nu.int32,requirements=['C','W']) + yo= numpy.require(yo,dtype=numpy.float64,requirements=['C','W']) + t= numpy.require(t,dtype=numpy.float64,requirements=['C','W']) + result= numpy.require(result,dtype=numpy.float64,requirements=['C','W']) + err= numpy.require(err,dtype=numpy.int32,requirements=['C','W']) #Run the C code integrationFunc(ctypes.c_int(nobj), @@ -440,12 +425,12 @@ err, ctypes.c_int(int_method_c)) - if nu.any(err == -10): #pragma: no cover + if numpy.any(err == -10): #pragma: no cover raise KeyboardInterrupt("Orbit integration interrupted by CTRL-C (SIGINT)") #Reset input arrays - if f_cont[0]: yo= nu.asfortranarray(yo) - if f_cont[1]: t= nu.asfortranarray(t) + if f_cont[0]: yo= numpy.asfortranarray(yo) + if f_cont[1]: t= numpy.asfortranarray(t) if single_obj: return (result[0],err[0]) else: return (result,err) @@ -479,34 +464,34 @@ int_method_c= _parse_integrator(int_method) if dt is None: dt= -9999.99 - yo= nu.concatenate((yo,dyo)) + yo= numpy.concatenate((yo,dyo)) #Set up result array - result= nu.empty((len(t),8)) + result= numpy.empty((len(t),8)) err= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') integrationFunc= _lib.integratePlanarOrbit_dxdv - integrationFunc.argtypes= [ndpointer(dtype=nu.float64,flags=ndarrayFlags), + integrationFunc.argtypes= [ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, - ndpointer(dtype=nu.int32,flags=ndarrayFlags), - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.int32,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_double, ctypes.c_double, ctypes.c_double, - ndpointer(dtype=nu.float64,flags=ndarrayFlags), + ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int), ctypes.c_int] #Array requirements, first store old order f_cont= [yo.flags['F_CONTIGUOUS'], t.flags['F_CONTIGUOUS']] - yo= nu.require(yo,dtype=nu.float64,requirements=['C','W']) - t= nu.require(t,dtype=nu.float64,requirements=['C','W']) - result= nu.require(result,dtype=nu.float64,requirements=['C','W']) + yo= numpy.require(yo,dtype=numpy.float64,requirements=['C','W']) + t= numpy.require(t,dtype=numpy.float64,requirements=['C','W']) + result= numpy.require(result,dtype=numpy.float64,requirements=['C','W']) #Run the C code integrationFunc(yo, @@ -525,8 +510,8 @@ raise KeyboardInterrupt("Orbit integration interrupted by CTRL-C (SIGINT)") #Reset input arrays - if f_cont[0]: yo= nu.asfortranarray(yo) - if f_cont[1]: t= nu.asfortranarray(t) + if f_cont[0]: yo= numpy.asfortranarray(yo) + if f_cont[1]: t= numpy.asfortranarray(t) return (result,err.value) @@ -560,27 +545,27 @@ if len(yo[0]) == 3: nophi= True #We hack this by putting in a dummy phi=0 - yo= nu.pad(yo,((0,0),(0,1)),'constant',constant_values=0) + yo= numpy.pad(yo,((0,0),(0,1)),'constant',constant_values=0) if int_method.lower() == 'leapfrog': if rtol is None: rtol= 1e-8 def integrate_for_map(vxvv): #go to the rectangular frame - this_vxvv= nu.array([vxvv[0]*nu.cos(vxvv[3]), - vxvv[0]*nu.sin(vxvv[3]), - vxvv[1]*nu.cos(vxvv[3]) - -vxvv[2]*nu.sin(vxvv[3]), - vxvv[2]*nu.cos(vxvv[3]) - +vxvv[1]*nu.sin(vxvv[3])]) + this_vxvv= numpy.array([vxvv[0]*numpy.cos(vxvv[3]), + vxvv[0]*numpy.sin(vxvv[3]), + vxvv[1]*numpy.cos(vxvv[3]) + -vxvv[2]*numpy.sin(vxvv[3]), + vxvv[2]*numpy.cos(vxvv[3]) + +vxvv[1]*numpy.sin(vxvv[3])]) #integrate tmp_out= symplecticode.leapfrog(_planarRectForce,this_vxvv, t,args=(pot,),rtol=rtol) #go back to the cylindrical frame - R= nu.sqrt(tmp_out[:,0]**2.+tmp_out[:,1]**2.) - phi= nu.arccos(tmp_out[:,0]/R) - phi[(tmp_out[:,1] < 0.)]= 2.*nu.pi-phi[(tmp_out[:,1] < 0.)] - vR= tmp_out[:,2]*nu.cos(phi)+tmp_out[:,3]*nu.sin(phi) - vT= tmp_out[:,3]*nu.cos(phi)-tmp_out[:,2]*nu.sin(phi) - out= nu.zeros((len(t),4)) + R= numpy.sqrt(tmp_out[:,0]**2.+tmp_out[:,1]**2.) + phi= numpy.arccos(tmp_out[:,0]/R) + phi[(tmp_out[:,1] < 0.)]= 2.*numpy.pi-phi[(tmp_out[:,1] < 0.)] + vR= tmp_out[:,2]*numpy.cos(phi)+tmp_out[:,3]*numpy.sin(phi) + vT= tmp_out[:,3]*numpy.cos(phi)-tmp_out[:,2]*numpy.sin(phi) + out= numpy.zeros((len(t),4)) out[:,0]= R out[:,1]= vR out[:,2]= vT @@ -601,7 +586,7 @@ init= [vxvv[0],vxvv[1]] intOut= integrator(_planarREOM,init,t=t,args=(pot,l2), **extra_kwargs) - out= nu.zeros((len(t),3)) + out= numpy.zeros((len(t),3)) out[:,0]= intOut[:,0] out[:,1]= intOut[:,1] out[:,2]= l/out[:,0] @@ -615,7 +600,7 @@ init= [vxvv[0],vxvv[1],vxvv[3],vphi] intOut= integrator(_planarEOM,init,t=t,args=(pot,), **extra_kwargs) - out= nu.zeros((len(t),4)) + out= numpy.zeros((len(t),4)) out[:,0]= intOut[:,0] out[:,1]= intOut[:,1] out[:,3]= intOut[:,2] @@ -623,19 +608,19 @@ #post-process to remove negative radii neg_radii= (out[:,0] < 0.) out[neg_radii,0]= -out[neg_radii,0] - out[neg_radii,3]+= nu.pi + out[neg_radii,3]+= numpy.pi return out else: # Assume we are forcing parallel_mapping of a C integrator... def integrate_for_map(vxvv): - return integratePlanarOrbit_c(pot,nu.copy(vxvv), + return integratePlanarOrbit_c(pot,numpy.copy(vxvv), t,int_method,dt=dt)[0] if len(yo) == 1: # Can't map a single value... - out= nu.atleast_3d(integrate_for_map(yo[0]).T).T + out= numpy.atleast_3d(integrate_for_map(yo[0]).T).T else: - out= nu.array((parallel_map(integrate_for_map,yo,numcores=numcores))) + out= numpy.array((parallel_map(integrate_for_map,yo,numcores=numcores))) if nophi: out= out[:,:,:3] - return out, nu.zeros(len(yo)) + return out, numpy.zeros(len(yo)) def integratePlanarOrbit_dxdv(pot,yo,dyo,t,int_method, rectIn,rectOut, @@ -668,28 +653,28 @@ 2019-05-21 - Adapted to allow multiple objects and parallel mapping - Bovy (UofT) """ #go to the rectangular frame - this_yo= nu.array([yo[:,0]*nu.cos(yo[:,3]), - yo[:,0]*nu.sin(yo[:,3]), - yo[:,1]*nu.cos(yo[:,3]) - -yo[:,2]*nu.sin(yo[:,3]), - yo[:,2]*nu.cos(yo[:,3]) - +yo[:,1]*nu.sin(yo[:,3])]).T + this_yo= numpy.array([yo[:,0]*numpy.cos(yo[:,3]), + yo[:,0]*numpy.sin(yo[:,3]), + yo[:,1]*numpy.cos(yo[:,3]) + -yo[:,2]*numpy.sin(yo[:,3]), + yo[:,2]*numpy.cos(yo[:,3]) + +yo[:,1]*numpy.sin(yo[:,3])]).T if not rectIn: - this_dyo= nu.array([nu.cos(yo[:,3])*dyo[:,0] - -yo[:,0]*nu.sin(yo[:,3])*dyo[:,3], - nu.sin(yo[:,3])*dyo[:,0] - +yo[:,0]*nu.cos(yo[:,3])*dyo[:,3], - -(yo[:,1]*nu.sin(yo[:,3]) - +yo[:,2]*nu.cos(yo[:,3]))*dyo[:,3] - +nu.cos(yo[:,3])*dyo[:,1] - -nu.sin(yo[:,3])*dyo[:,2], - (yo[:,1]*nu.cos(yo[:,3]) - -yo[:,2]*nu.sin(yo[:,3]))*dyo[:,3] - +nu.sin(yo[:,3])*dyo[:,1] - +nu.cos(yo[:,3])*dyo[:,2]]).T + this_dyo= numpy.array([numpy.cos(yo[:,3])*dyo[:,0] + -yo[:,0]*numpy.sin(yo[:,3])*dyo[:,3], + numpy.sin(yo[:,3])*dyo[:,0] + +yo[:,0]*numpy.cos(yo[:,3])*dyo[:,3], + -(yo[:,1]*numpy.sin(yo[:,3]) + +yo[:,2]*numpy.cos(yo[:,3]))*dyo[:,3] + +numpy.cos(yo[:,3])*dyo[:,1] + -numpy.sin(yo[:,3])*dyo[:,2], + (yo[:,1]*numpy.cos(yo[:,3]) + -yo[:,2]*numpy.sin(yo[:,3]))*dyo[:,3] + +numpy.sin(yo[:,3])*dyo[:,1] + +numpy.cos(yo[:,3])*dyo[:,2]]).T else: this_dyo= dyo - this_yo= nu.hstack((this_yo,this_dyo)) + this_yo= numpy.hstack((this_yo,this_dyo)) if int_method.lower() == 'dop853' or int_method.lower() == 'odeint': if rtol is None: rtol= 1e-8 if int_method.lower() == 'dop853': @@ -703,23 +688,23 @@ **extra_kwargs) else: # Assume we are forcing parallel_mapping of a C integrator... def integrate_for_map(vxvv): - return integratePlanarOrbit_dxdv_c(pot,nu.copy(vxvv[:4]), - nu.copy(vxvv[4:]), + return integratePlanarOrbit_dxdv_c(pot,numpy.copy(vxvv[:4]), + numpy.copy(vxvv[4:]), t,int_method,dt=dt, rtol=rtol,atol=atol)[0] if len(this_yo) == 1: # Can't map a single value... - out= nu.atleast_3d(integrate_for_map(this_yo[0]).T).T + out= numpy.atleast_3d(integrate_for_map(this_yo[0]).T).T else: - out= nu.array((parallel_map(integrate_for_map,this_yo, + out= numpy.array((parallel_map(integrate_for_map,this_yo, numcores=numcores))) #go back to the cylindrical frame - R= nu.sqrt(out[...,0]**2.+out[...,1]**2.) - phi= nu.arccos(out[...,0]/R) - phi[(out[...,1] < 0.)]= 2.*nu.pi-phi[(out[...,1] < 0.)] - vR= out[...,2]*nu.cos(phi)+out[...,3]*nu.sin(phi) - vT= out[...,3]*nu.cos(phi)-out[...,2]*nu.sin(phi) - cp= nu.cos(phi) - sp= nu.sin(phi) + R= numpy.sqrt(out[...,0]**2.+out[...,1]**2.) + phi= numpy.arccos(out[...,0]/R) + phi[(out[...,1] < 0.)]= 2.*numpy.pi-phi[(out[...,1] < 0.)] + vR= out[...,2]*numpy.cos(phi)+out[...,3]*numpy.sin(phi) + vT= out[...,3]*numpy.cos(phi)-out[...,2]*numpy.sin(phi) + cp= numpy.cos(phi) + sp= numpy.sin(phi) out[...,0]= R out[...,1]= vR out[...,2]= vT @@ -735,7 +720,7 @@ out[...,7]= dphi out[...,5]= dvR out[...,6]= dvT - return out, nu.zeros(len(yo)) + return out, numpy.zeros(len(yo)) def _planarREOM(y,t,pot,l2): """ @@ -798,11 +783,11 @@ 2011-10-18 - Written - Bovy (IAS) """ #x is rectangular so calculate R and phi - R= nu.sqrt(x[0]**2.+x[1]**2.) - phi= nu.arccos(x[0]/R) + R= numpy.sqrt(x[0]**2.+x[1]**2.) + phi= numpy.arccos(x[0]/R) sinphi= x[1]/R cosphi= x[0]/R - if x[1] < 0.: phi= 2.*nu.pi-phi + if x[1] < 0.: phi= 2.*numpy.pi-phi #calculate forces Rforce= _evaluateplanarRforces(pot,R,phi=phi,t=t) phiforce= _evaluateplanarphiforces(pot,R,phi=phi,t=t) @@ -830,7 +815,7 @@ -2.*sinphi*cosphi/R*Rphideriv\ +cosphi**2./R*Rforce\ -cosphi**2./R**2.*phi2deriv - return nu.array([x[2],x[3], + return numpy.array([x[2],x[3], cosphi*Rforce-1./R*sinphi*phiforce, sinphi*Rforce+1./R*cosphi*phiforce, x[6],x[7], @@ -853,14 +838,14 @@ 2011-02-02 - Written - Bovy (NYU) """ #x is rectangular so calculate R and phi - R= nu.sqrt(x[0]**2.+x[1]**2.) - phi= nu.arccos(x[0]/R) + R= numpy.sqrt(x[0]**2.+x[1]**2.) + phi= numpy.arccos(x[0]/R) sinphi= x[1]/R cosphi= x[0]/R - if x[1] < 0.: phi= 2.*nu.pi-phi + if x[1] < 0.: phi= 2.*numpy.pi-phi #calculate forces Rforce= _evaluateplanarRforces(pot,R,phi=phi,t=t) phiforce= _evaluateplanarphiforces(pot,R,phi=phi,t=t) - return nu.array([cosphi*Rforce-1./R*sinphi*phiforce, + return numpy.array([cosphi*Rforce-1./R*sinphi*phiforce, sinphi*Rforce+1./R*cosphi*phiforce]) diff -Nru galpy-1.5/galpy/orbit/named_objects.json galpy-1.6.0.post0/galpy/orbit/named_objects.json --- galpy-1.5/galpy/orbit/named_objects.json 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/orbit/named_objects.json 2020-04-24 19:48:38.000000000 +0000 @@ -1,7 +1,8 @@ { "_collections": { "MWglobularclusters": ["NGC5286","Terzan12","Arp2","NGC5024","NGC6638","Crater","BH261","NGC6553","NGC6749","NGC6528","NGC4372","NGC2808","IC4499","BH229","NGC6642","NGC6779","NGC6541","NGC6441","Pal4","NGC6341","NGC5694","NGC2298","Ton2","NGC6637","NGC6325","NGC4147","NGC6366","Pal7","NGC5986","NGC5927","Terzan1","NGC4833","Pal8","NGC7078","NGC6517","NGC6284","Pal14","NGC6539","NGC7089","NGC5272","NGC362","NGC6144","NGC6287","E3","NGC6205","NGC6402","FSR1735","Pal3","NGC6256","NGC6342","Djorg2","NGC6093","NGC5139","Terzan5","NGC6333","NGC6934","NGC6101","NGC6171","NGC5466","Pal5","ESO45211","NGC6266","Pal15","Pal13","Terzan2","NGC6540","Terzan4","BH184","NGC5053","NGC6723","FSR1716","BH176","NGC6809","NGC5897","NGC6496","NGC6715","NGC6388","Pal2","NGC1261","NGC6362","Whiting1","NGC6522","NGC6254","NGC6535","NGC6440","NGC6316","NGC5634","NGC7492","Terzan9","NGC6352","Terzan7","Terzan6","NGC6235","NGC5904","NGC6626","IC1257","NGC5946","NGC6717","NGC288","NGC2419","Terzan10","NGC6218","Pal6","NGC6426","NGC6304","NGC6273","NGC6544","NGC6624","NGC6356","Pal12","Djorg1","NGC6293","NGC7006","NGC104","Pal11","NGC5824","Terzan3","NGC6584","NGC3201","Rup106","NGC6838","NGC7099","NGC6229","NGC6139","Pyxis","NGC6121","NGC6681","NGC6652","NGC1904","NGC1851","NGC6397","Terzan8","NGC6569","NGC6981","NGC6401","NGC6760","NGC6380","NGC6355","NGC4590","Pal1","NGC6656","ESO28006","NGC6558","Pal10","E1","NGC6712","NGC6752","NGC6453","NGC6864","Eridanus"], - "MWsatellitegalaxies": ["AquariusII", "BootesI", "BootesII", "CanesVenaticiI", "CanesVenaticiII", "Carina", "CarinaII", "CarinaIII", "ComaBerenices", "CraterII", "Draco", "DracoII", "EridanusII", "Fornax", "GrusI", "Hercules", "HorologiumI", "HydraII", "HydrusI", "LeoI", "LeoII", "LeoIV", "LeoV", "LMC", "PhoenixI", "PiscesII", "ReticulumII", "Sgr", "Sculptor", "Segue1", "Segue2", "SMC", "Sextans", "TriangulumII", "TucanaII", "TucanaIII", "UrsaMajorI", "UrsaMajorII", "UrsaMinor", "Willman1"] + "MWsatellitegalaxies": ["AquariusII", "BootesI", "BootesII", "CanesVenaticiI", "CanesVenaticiII", "Carina", "CarinaII", "CarinaIII", "ComaBerenices", "CraterII", "Draco", "DracoII", "EridanusII", "Fornax", "GrusI", "Hercules", "HorologiumI", "HydraII", "HydrusI", "LeoI", "LeoII", "LeoIV", "LeoV", "LMC", "PhoenixI", "PiscesII", "ReticulumII", "Sgr", "Sculptor", "Segue1", "Segue2", "SMC", "Sextans", "TriangulumII", "TucanaII", "TucanaIII", "UrsaMajorI", "UrsaMajorII", "UrsaMinor", "Willman1"], + "solarsystem": ["Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune"] }, "_synonyms": { "OmegaCen": "NGC5139", @@ -1779,5 +1780,109 @@ "pmdec": -2.273000, "vlos": -176.700000, "source": "arXiv:1807.09775" + }, + "Mercury": + { "ra": 272.53694669839313746706, + "dec": -23.26470710760313309606, + "distance": 0.00000000330782629431, + "pmra": 114048573.5889339447021484, + "pmdec": 1113250730.9213943481445312, + "vlos": 24.09379083329670834246, + "ro": 0.00000000484813681113, + "vo": 30.0, + "zo": 0.0, + "solarmotion": [0.0,0.0,0.0], + "source": "arXiv:0903.5308" + }, + "Venus": + { "ra": 261.59112990672980458839, + "dec": -33.02216800854332490189, + "distance": 0.00000000829181155636, + "pmra": -899463102.5785070657730103, + "pmdec": -1377271614.5834431648254395, + "vlos": -1.82400772039945135994, + "ro": 0.00000000484813681113, + "vo": 30.0, + "zo": 0.0, + "solarmotion": [0.0,0.0,0.0], + "source": "arXiv:0903.5308" + }, + "Earth": + { "ra": 262.96412147067331943617, + "dec": -33.59314845931364601483, + "distance": 0.00000000965631218281, + "pmra": -712425950.9163029193878174, + "pmdec": -1089092311.4748961925506592, + "vlos": 0.37735889881938400325, + "ro": 0.00000000484813681113, + "vo": 30.0, + "zo": 0.0, + "solarmotion": [0.0,0.0,0.0], + "source": "arXiv:0903.5308" + }, + "Mars": + { "ra": 127.89885319623307680104, + "dec": -44.74750104086731994357, + "distance": 0.00000000404254311334, + "pmra": -412616788.4622230529785156, + "pmdec": 620326241.2420622110366821, + "vlos": 10.39932018289293402802, + "ro": 0.00000000484813681113, + "vo": 30.0, + "zo": 0.0, + "solarmotion": [0.0,0.0,0.0], + "source": "arXiv:0903.5308" + }, + "Jupiter": + { "ra": 115.15711593351926467221, + "dec": -24.04306151473348052150, + "distance": 0.00000002182038447526, + "pmra": 10122386.4076392110437155, + "pmdec": -17153149.6331202201545238, + "vlos": 23.07793974607058729021, + "ro": 0.00000000484813681113, + "vo": 30.0, + "zo": 0.0, + "solarmotion": [0.0,0.0,0.0], + "source": "arXiv:0903.5308" + }, + "Saturn": + { "ra": 270.18477455320834224040, + "dec": -19.44459530285559978324, + "distance": 0.00000005032138429360, + "pmra": -83101997.5844055265188217, + "pmdec": -142355056.1714278459548950, + "vlos": -4.48093156668851833047, + "ro": 0.00000000484813681113, + "vo": 30.0, + "zo": 0.0, + "solarmotion": [0.0,0.0,0.0], + "source": "arXiv:0903.5308" + }, + "Uranus": + { "ra": 89.97246477323895419431, + "dec": 21.90938146499203753592, + "distance": 0.00000009262040283203, + "pmra": 26453654.0211135037243366, + "pmdec": -45851111.8113014400005341, + "vlos": 3.96038409978304484227, + "ro": 0.00000000484813681113, + "vo": 30.0, + "zo": 0.0, + "solarmotion": [0.0,0.0,0.0], + "source": "arXiv:0903.5308" + }, + "Neptune": + { "ra": 104.39324539298492311445, + "dec": -3.84039762053889033311, + "distance": 0.00000014167718752406, + "pmra": 12522815.9167627468705177, + "pmdec": -24543456.2938976883888245, + "vlos": 17.91906269190807421410, + "ro": 0.00000000484813681113, + "vo": 30.0, + "zo": 0.0, + "solarmotion": [0.0,0.0,0.0], + "source": "arXiv:0903.5308" } } diff -Nru galpy-1.5/galpy/orbit/orbit_c_ext/integrateFullOrbit.c galpy-1.6.0.post0/galpy/orbit/orbit_c_ext/integrateFullOrbit.c --- galpy-1.5/galpy/orbit/orbit_c_ext/integrateFullOrbit.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/orbit/orbit_c_ext/integrateFullOrbit.c 2020-04-24 19:48:38.000000000 +0000 @@ -35,11 +35,11 @@ #ifdef _WIN32 // On Windows, *need* to define this function to allow the package to be imported #if PY_MAJOR_VERSION >= 3 -PyMODINIT_FUNC PyInit_galpy_integrate_c(void) { // Python 3 +PyMODINIT_FUNC PyInit_libgalpy(void) { // Python 3 return NULL; } #else -PyMODINIT_FUNC initgalpy_integrate_c(void) {} // Python 2 +PyMODINIT_FUNC initlibgalpy(void) {} // Python 2 #endif #endif /* @@ -52,6 +52,7 @@ void evalRectDeriv_dxdv(double,double *, double *, int, struct potentialArg *); void initMovingObjectSplines(struct potentialArg *, double ** pot_args); +void initChandrasekharDynamicalFrictionSplines(struct potentialArg *, double ** pot_args); /* Actual functions */ @@ -70,81 +71,98 @@ potentialArgs->Rforce= &LogarithmicHaloPotentialRforce; potentialArgs->zforce= &LogarithmicHaloPotentialzforce; potentialArgs->phiforce= &LogarithmicHaloPotentialphiforce; + potentialArgs->dens= &LogarithmicHaloPotentialDens; //potentialArgs->R2deriv= &LogarithmicHaloPotentialR2deriv; //potentialArgs->planarphi2deriv= &ZeroForce; //potentialArgs->planarRphideriv= &ZeroForce; potentialArgs->nargs= 4; + potentialArgs->requiresVelocity= false; break; case 1: //DehnenBarPotential, 6 arguments potentialArgs->Rforce= &DehnenBarPotentialRforce; potentialArgs->phiforce= &DehnenBarPotentialphiforce; potentialArgs->zforce= &DehnenBarPotentialzforce; potentialArgs->nargs= 6; + potentialArgs->requiresVelocity= false; break; case 5: //MiyamotoNagaiPotential, 3 arguments potentialArgs->potentialEval= &MiyamotoNagaiPotentialEval; potentialArgs->Rforce= &MiyamotoNagaiPotentialRforce; potentialArgs->zforce= &MiyamotoNagaiPotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &MiyamotoNagaiPotentialDens; //potentialArgs->R2deriv= &MiyamotoNagaiPotentialR2deriv; //potentialArgs->planarphi2deriv= &ZeroForce; //potentialArgs->planarRphideriv= &ZeroForce; potentialArgs->nargs= 3; + potentialArgs->requiresVelocity= false; break; case 7: //PowerSphericalPotential, 2 arguments potentialArgs->potentialEval= &PowerSphericalPotentialEval; potentialArgs->Rforce= &PowerSphericalPotentialRforce; potentialArgs->zforce= &PowerSphericalPotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &PowerSphericalPotentialDens; //potentialArgs->R2deriv= &PowerSphericalPotentialR2deriv; //potentialArgs->planarphi2deriv= &ZeroForce; //potentialArgs->planarRphideriv= &ZeroForce; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 8: //HernquistPotential, 2 arguments potentialArgs->potentialEval= &HernquistPotentialEval; potentialArgs->Rforce= &HernquistPotentialRforce; potentialArgs->zforce= &HernquistPotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &HernquistPotentialDens; //potentialArgs->R2deriv= &HernquistPotentialR2deriv; //potentialArgs->planarphi2deriv= &ZeroForce; //potentialArgs->planarRphideriv= &ZeroForce; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 9: //NFWPotential, 2 arguments potentialArgs->potentialEval= &NFWPotentialEval; potentialArgs->Rforce= &NFWPotentialRforce; potentialArgs->zforce= &NFWPotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &NFWPotentialDens; //potentialArgs->R2deriv= &NFWPotentialR2deriv; //potentialArgs->planarphi2deriv= &ZeroForce; //potentialArgs->planarRphideriv= &ZeroForce; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 10: //JaffePotential, 2 arguments potentialArgs->potentialEval= &JaffePotentialEval; potentialArgs->Rforce= &JaffePotentialRforce; potentialArgs->zforce= &JaffePotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &JaffePotentialDens; //potentialArgs->R2deriv= &JaffePotentialR2deriv; //potentialArgs->planarphi2deriv= &ZeroForce; //potentialArgs->planarRphideriv= &ZeroForce; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 11: //DoubleExponentialDiskPotential, XX arguments potentialArgs->potentialEval= &DoubleExponentialDiskPotentialEval; potentialArgs->Rforce= &DoubleExponentialDiskPotentialRforce; potentialArgs->zforce= &DoubleExponentialDiskPotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &DoubleExponentialDiskPotentialDens; //Look at pot_args to figure out the number of arguments potentialArgs->nargs= (int) (8 + 2 * *(*pot_args+5) + 4 * ( *(*pot_args+4) + 1 )); + potentialArgs->requiresVelocity= false; break; case 12: //FlattenedPowerPotential, 4 arguments potentialArgs->potentialEval= &FlattenedPowerPotentialEval; potentialArgs->Rforce= &FlattenedPowerPotentialRforce; potentialArgs->zforce= &FlattenedPowerPotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &FlattenedPowerPotentialDens; potentialArgs->nargs= 4; + potentialArgs->requiresVelocity= false; break; case 13: //interpRZPotential, XX arguments //Grab the grids and the coefficients @@ -190,23 +208,28 @@ free(Rgrid); free(zgrid); free(potGrid_splinecoeffs); + potentialArgs->requiresVelocity= false; break; case 14: //IsochronePotential, 2 arguments potentialArgs->potentialEval= &IsochronePotentialEval; potentialArgs->Rforce= &IsochronePotentialRforce; potentialArgs->zforce= &IsochronePotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &IsochronePotentialDens; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 15: //PowerSphericalwCutoffPotential, 3 arguments potentialArgs->potentialEval= &PowerSphericalPotentialwCutoffEval; potentialArgs->Rforce= &PowerSphericalPotentialwCutoffRforce; potentialArgs->zforce= &PowerSphericalPotentialwCutoffzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &PowerSphericalPotentialwCutoffDens; //potentialArgs->R2deriv= &PowerSphericalPotentialR2deriv; //potentialArgs->planarphi2deriv= &ZeroForce; //potentialArgs->planarRphideriv= &ZeroForce; potentialArgs->nargs= 3; + potentialArgs->requiresVelocity= false; break; case 16: //KuzminKutuzovStaeckelPotential, 3 arguments potentialArgs->potentialEval= &KuzminKutuzovStaeckelPotentialEval; @@ -215,22 +238,27 @@ potentialArgs->phiforce= &ZeroForce; //potentialArgs->R2deriv= &KuzminKutuzovStaeckelPotentialR2deriv; potentialArgs->nargs= 3; + potentialArgs->requiresVelocity= false; break; case 17: //PlummerPotential, 2 arguments potentialArgs->potentialEval= &PlummerPotentialEval; potentialArgs->Rforce= &PlummerPotentialRforce; potentialArgs->zforce= &PlummerPotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &PlummerPotentialDens; //potentialArgs->R2deriv= &PlummerPotentialR2deriv; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 18: //PseudoIsothermalPotential, 2 arguments potentialArgs->potentialEval= &PseudoIsothermalPotentialEval; potentialArgs->Rforce= &PseudoIsothermalPotentialRforce; potentialArgs->zforce= &PseudoIsothermalPotentialzforce; potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &PseudoIsothermalPotentialDens; //potentialArgs->R2deriv= &PseudoIsothermalPotentialR2deriv; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 19: //KuzminDiskPotential, 2 arguments potentialArgs->potentialEval= &KuzminDiskPotentialEval; @@ -238,56 +266,67 @@ potentialArgs->zforce= &KuzminDiskPotentialzforce; potentialArgs->phiforce= &ZeroForce; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 20: //BurkertPotential, 2 arguments potentialArgs->potentialEval= &BurkertPotentialEval; potentialArgs->Rforce= &BurkertPotentialRforce; potentialArgs->zforce= &BurkertPotentialzforce; + potentialArgs->dens= &BurkertPotentialDens; potentialArgs->phiforce= &ZeroForce; potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; break; case 21: //TriaxialHernquistPotential, lots of arguments potentialArgs->potentialEval= &EllipsoidalPotentialEval; potentialArgs->Rforce = &EllipsoidalPotentialRforce; potentialArgs->zforce = &EllipsoidalPotentialzforce; potentialArgs->phiforce = &EllipsoidalPotentialphiforce; + potentialArgs->dens= &EllipsoidalPotentialDens; // Also assign functions specific to EllipsoidalPotential potentialArgs->psi= &TriaxialHernquistPotentialpsi; potentialArgs->mdens= &TriaxialHernquistPotentialmdens; potentialArgs->mdensDeriv= &TriaxialHernquistPotentialmdensDeriv; potentialArgs->nargs = (int) (21 + *(*pot_args+7) + 2 * *(*pot_args + (int) (*(*pot_args+7) + 20))); + potentialArgs->requiresVelocity= false; break; case 22: //TriaxialNFWPotential, lots of arguments potentialArgs->potentialEval= &EllipsoidalPotentialEval; potentialArgs->Rforce = &EllipsoidalPotentialRforce; potentialArgs->zforce = &EllipsoidalPotentialzforce; potentialArgs->phiforce = &EllipsoidalPotentialphiforce; + potentialArgs->dens= &EllipsoidalPotentialDens; // Also assign functions specific to EllipsoidalPotential potentialArgs->psi= &TriaxialNFWPotentialpsi; potentialArgs->mdens= &TriaxialNFWPotentialmdens; potentialArgs->mdensDeriv= &TriaxialNFWPotentialmdensDeriv; potentialArgs->nargs = (int) (21 + *(*pot_args+7) + 2 * *(*pot_args + (int) (*(*pot_args+7) + 20))); + potentialArgs->requiresVelocity= false; break; case 23: //TriaxialJaffePotential, lots of arguments potentialArgs->potentialEval= &EllipsoidalPotentialEval; potentialArgs->Rforce = &EllipsoidalPotentialRforce; potentialArgs->zforce = &EllipsoidalPotentialzforce; potentialArgs->phiforce = &EllipsoidalPotentialphiforce; + potentialArgs->dens= &EllipsoidalPotentialDens; // Also assign functions specific to EllipsoidalPotential potentialArgs->psi= &TriaxialJaffePotentialpsi; potentialArgs->mdens= &TriaxialJaffePotentialmdens; potentialArgs->mdensDeriv= &TriaxialJaffePotentialmdensDeriv; potentialArgs->nargs = (int) (21 + *(*pot_args+7) + 2 * *(*pot_args + (int) (*(*pot_args+7) + 20))); + potentialArgs->requiresVelocity= false; break; case 24: //SCFPotential, many arguments potentialArgs->potentialEval= &SCFPotentialEval; potentialArgs->Rforce= &SCFPotentialRforce; potentialArgs->zforce= &SCFPotentialzforce; potentialArgs->phiforce= &SCFPotentialphiforce; + potentialArgs->dens= &SCFPotentialDens; potentialArgs->nargs= (int) (5 + (1 + *(*pot_args + 1)) * *(*pot_args+2) * *(*pot_args+3)* *(*pot_args+4) + 7); + potentialArgs->requiresVelocity= false; break; case 25: //SoftenedNeedleBarPotential, 13 arguments potentialArgs->potentialEval= &SoftenedNeedleBarPotentialEval; @@ -295,13 +334,16 @@ potentialArgs->zforce= &SoftenedNeedleBarPotentialzforce; potentialArgs->phiforce= &SoftenedNeedleBarPotentialphiforce; potentialArgs->nargs= (int) 13; + potentialArgs->requiresVelocity= false; break; case 26: //DiskSCFPotential, nsigma+3 arguments potentialArgs->potentialEval= &DiskSCFPotentialEval; potentialArgs->Rforce= &DiskSCFPotentialRforce; potentialArgs->zforce= &DiskSCFPotentialzforce; + potentialArgs->dens= &DiskSCFPotentialDens; potentialArgs->phiforce= &ZeroForce; potentialArgs->nargs= (int) **pot_args + 3; + potentialArgs->requiresVelocity= false; break; case 27: // SpiralArmsPotential, 10 arguments + array of Cs potentialArgs->Rforce = &SpiralArmsPotentialRforce; @@ -313,12 +355,14 @@ //potentialArgs->Rzderiv = &SpiralArmsPotentialRzderiv; potentialArgs->Rphideriv = &SpiralArmsPotentialRphideriv; potentialArgs->nargs = (int) 10 + **pot_args; + potentialArgs->requiresVelocity= false; break; case 30: // PerfectEllipsoidPotential, lots of arguments potentialArgs->potentialEval= &EllipsoidalPotentialEval; potentialArgs->Rforce = &EllipsoidalPotentialRforce; potentialArgs->zforce = &EllipsoidalPotentialzforce; potentialArgs->phiforce = &EllipsoidalPotentialphiforce; + potentialArgs->dens= &EllipsoidalPotentialDens; //potentialArgs->R2deriv = &EllipsoidalPotentialR2deriv; //potentialArgs->z2deriv = &EllipsoidalPotentialz2deriv; //potentialArgs->phi2deriv = &EllipsoidalPotentialphi2deriv; @@ -330,9 +374,43 @@ potentialArgs->mdensDeriv= &PerfectEllipsoidPotentialmdensDeriv; potentialArgs->nargs = (int) (21 + *(*pot_args+7) + 2 * *(*pot_args + (int) (*(*pot_args+7) + 20))); - break; - // 31: KGPotential - // 32: IsothermalDiskPotential + potentialArgs->requiresVelocity= false; + break; + // 31: KGPotential + // 32: IsothermalDiskPotential + case 33: //DehnenCoreSphericalPotential, 2 arguments + potentialArgs->potentialEval= &DehnenCoreSphericalPotentialEval; + potentialArgs->Rforce= &DehnenCoreSphericalPotentialRforce; + potentialArgs->zforce= &DehnenCoreSphericalPotentialzforce; + potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &DehnenCoreSphericalPotentialDens; + //potentialArgs->R2deriv= &DehnenCoreSphericalPotentialR2deriv; + //potentialArgs->planarphi2deriv= &ZeroForce; + //potentialArgs->planarRphideriv= &ZeroForce; + potentialArgs->nargs= 2; + potentialArgs->requiresVelocity= false; + break; + case 34: //DehnenSphericalPotential, 3 arguments + potentialArgs->potentialEval= &DehnenSphericalPotentialEval; + potentialArgs->Rforce= &DehnenSphericalPotentialRforce; + potentialArgs->zforce= &DehnenSphericalPotentialzforce; + potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &DehnenSphericalPotentialDens; + //potentialArgs->R2deriv= &DehnenSphericalPotentialR2deriv; + //potentialArgs->planarphi2deriv= &ZeroForce; + //potentialArgs->planarRphideriv= &ZeroForce; + potentialArgs->nargs= 3; + potentialArgs->requiresVelocity= false; + break; + case 35: //HomogeneousSpherePotential, 3 arguments + potentialArgs->potentialEval= &HomogeneousSpherePotentialEval; + potentialArgs->Rforce= &HomogeneousSpherePotentialRforce; + potentialArgs->zforce= &HomogeneousSpherePotentialzforce; + potentialArgs->phiforce= &ZeroForce; + potentialArgs->dens= &HomogeneousSpherePotentialDens; + potentialArgs->nargs= 3; + potentialArgs->requiresVelocity= false; + break; //////////////////////////////// WRAPPERS ///////////////////////////////////// case -1: //DehnenSmoothWrapperPotential potentialArgs->potentialEval= &DehnenSmoothWrapperPotentialEval; @@ -340,18 +418,21 @@ potentialArgs->zforce= &DehnenSmoothWrapperPotentialzforce; potentialArgs->phiforce= &DehnenSmoothWrapperPotentialphiforce; potentialArgs->nargs= (int) 4; + potentialArgs->requiresVelocity= false; break; case -2: //SolidBodyRotationWrapperPotential potentialArgs->Rforce= &SolidBodyRotationWrapperPotentialRforce; potentialArgs->zforce= &SolidBodyRotationWrapperPotentialzforce; potentialArgs->phiforce= &SolidBodyRotationWrapperPotentialphiforce; potentialArgs->nargs= (int) 3; + potentialArgs->requiresVelocity= false; break; case -4: //CorotatingRotationWrapperPotential potentialArgs->Rforce= &CorotatingRotationWrapperPotentialRforce; potentialArgs->zforce= &CorotatingRotationWrapperPotentialzforce; potentialArgs->phiforce= &CorotatingRotationWrapperPotentialphiforce; potentialArgs->nargs= (int) 5; + potentialArgs->requiresVelocity= false; break; case -5: //GaussianAmplitudeWrapperPotential potentialArgs->potentialEval= &GaussianAmplitudeWrapperPotentialEval; @@ -359,15 +440,25 @@ potentialArgs->zforce= &GaussianAmplitudeWrapperPotentialzforce; potentialArgs->phiforce= &GaussianAmplitudeWrapperPotentialphiforce; potentialArgs->nargs= (int) 3; + potentialArgs->requiresVelocity= false; break; case -6: //MovingObjectPotential potentialArgs->Rforce= &MovingObjectPotentialRforce; potentialArgs->zforce= &MovingObjectPotentialzforce; potentialArgs->phiforce= &MovingObjectPotentialphiforce; potentialArgs->nargs= (int) 3; + potentialArgs->requiresVelocity= false; + break; + case -7: //ChandrasekharDynamicalFrictionForce + potentialArgs->RforceVelocity= &ChandrasekharDynamicalFrictionForceRforce; + potentialArgs->zforceVelocity= &ChandrasekharDynamicalFrictionForcezforce; + potentialArgs->phiforceVelocity= &ChandrasekharDynamicalFrictionForcephiforce; + potentialArgs->nargs= (int) 16; + potentialArgs->requiresVelocity= true; break; } - int setupSplines = *(*pot_type-1) == -6 ? 1 : 0; + int setupMovingObjectSplines = *(*pot_type-1) == -6 ? 1 : 0; + int setupChandrasekharDynamicalFrictionSplines = *(*pot_type-1) == -7 ? 1 : 0; if ( *(*pot_type-1) < 0 ) { // Parse wrapped potential for wrappers potentialArgs->nwrapped= (int) *(*pot_args)++; potentialArgs->wrappedPotentialArg= \ @@ -377,7 +468,10 @@ potentialArgs->wrappedPotentialArg, pot_type,pot_args); } - if (setupSplines) initMovingObjectSplines(potentialArgs, pot_args); + if (setupMovingObjectSplines) + initMovingObjectSplines(potentialArgs, pot_args); + if (setupChandrasekharDynamicalFrictionSplines) + initChandrasekharDynamicalFrictionSplines(potentialArgs,pot_args); potentialArgs->args= (double *) malloc( potentialArgs->nargs * sizeof(double)); for (jj=0; jj < potentialArgs->nargs; jj++){ *(potentialArgs->args)= *(*pot_args)++; @@ -575,13 +669,13 @@ } void evalRectDeriv(double t, double *q, double *a, int nargs, struct potentialArg * potentialArgs){ - double sinphi, cosphi, x, y, phi,R,Rforce,phiforce,z,zforce; + double sinphi, cosphi, x, y, phi,R,Rforce,phiforce,z,zforce,vR,vT; //first three derivatives are just the velocities *a++= *(q+3); *a++= *(q+4); *a++= *(q+5); //Rest is force - //q is rectangular so calculate R and phi + //q is rectangular so calculate R and phi, vR and vT (for dissipative) x= *q; y= *(q+1); z= *(q+2); @@ -590,10 +684,12 @@ sinphi= y/R; cosphi= x/R; if ( y < 0. ) phi= 2.*M_PI-phi; + vR= *(q+3) * cosphi + *(q+4) * sinphi; + vT= -*(q+3) * sinphi + *(q+4) * cosphi; //Calculate the forces - Rforce= calcRforce(R,z,phi,t,nargs,potentialArgs); - zforce= calczforce(R,z,phi,t,nargs,potentialArgs); - phiforce= calcPhiforce(R,z,phi,t,nargs,potentialArgs); + Rforce= calcRforce(R,z,phi,t,nargs,potentialArgs,vR,vT,*(q+5)); + zforce= calczforce(R,z,phi,t,nargs,potentialArgs,vR,vT,*(q+5)); + phiforce= calcPhiforce(R,z,phi,t,nargs,potentialArgs,vR,vT,*(q+5)); *a++= cosphi*Rforce-1./R*sinphi*phiforce; *a++= sinphi*Rforce+1./R*cosphi*phiforce; *a= zforce; @@ -627,17 +723,53 @@ gsl_spline_init(y_spline, t, y_arr, nPts); gsl_spline_init(z_spline, t, z_arr, nPts); - potentialArgs->xSpline = x_spline; - potentialArgs->accx = x_accel_ptr; - potentialArgs->ySpline = y_spline; - potentialArgs->accy = y_accel_ptr; - potentialArgs->zSpline = z_spline; - potentialArgs->accz = z_accel_ptr; + potentialArgs->nspline1d= 3; + potentialArgs->spline1d= (gsl_spline **) malloc ( 3*sizeof ( gsl_spline *) ); + potentialArgs->acc1d= (gsl_interp_accel **) \ + malloc ( 3 * sizeof ( gsl_interp_accel * ) ); + *potentialArgs->spline1d = x_spline; + *potentialArgs->acc1d = x_accel_ptr; + *(potentialArgs->spline1d+1)= y_spline; + *(potentialArgs->acc1d+1)= y_accel_ptr; + *(potentialArgs->spline1d+2)= z_spline; + *(potentialArgs->acc1d+2)= z_accel_ptr; *pot_args = *pot_args + (int) (1+4*nPts); free(t); } +void initChandrasekharDynamicalFrictionSplines(struct potentialArg * potentialArgs, + double ** pot_args){ + gsl_interp_accel *sr_accel_ptr = gsl_interp_accel_alloc(); + int nPts = (int) **pot_args; + + gsl_spline *sr_spline = gsl_spline_alloc(gsl_interp_cspline,nPts); + + double * r_arr = *pot_args+1; + double * sr_arr = r_arr+1*nPts; + + double * r= (double *) malloc ( nPts * sizeof (double) ); + double ro = *(r_arr+2*nPts+14); + double rf = *(r_arr+2*nPts+15); + + int ii; + for (ii=0; ii < nPts; ii++) + *(r+ii) = (r_arr[ii]-ro)/(rf-ro); + + gsl_spline_init(sr_spline,r,sr_arr,nPts); + + potentialArgs->nspline1d= 1; + potentialArgs->spline1d= (gsl_spline **) \ + malloc ( potentialArgs->nspline1d*sizeof ( gsl_spline *) ); + potentialArgs->acc1d= (gsl_interp_accel **) \ + malloc ( potentialArgs->nspline1d * sizeof ( gsl_interp_accel * ) ); + *potentialArgs->spline1d = sr_spline; + *potentialArgs->acc1d = sr_accel_ptr; + + *pot_args = *pot_args + (int) (1+(1+potentialArgs->nspline1d)*nPts); + free(r); +} + // LCOV_EXCL_START void evalRectDeriv_dxdv(double t, double *q, double *a, int nargs, struct potentialArg * potentialArgs){ diff -Nru galpy-1.5/galpy/orbit/orbit_c_ext/integrateFullOrbit.h galpy-1.6.0.post0/galpy/orbit/orbit_c_ext/integrateFullOrbit.h --- galpy-1.5/galpy/orbit/orbit_c_ext/integrateFullOrbit.h 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/orbit/orbit_c_ext/integrateFullOrbit.h 2020-04-24 19:48:38.000000000 +0000 @@ -11,9 +11,9 @@ #ifdef _WIN32 // On Windows, *need* to define this function to allow the package to be imported #if PY_MAJOR_VERSION >= 3 - PyMODINIT_FUNC PyInit_galpy_integrate_c(void); // Python 3 + PyMODINIT_FUNC PyInit_libgalpy(void); // Python 3 #else - PyMODINIT_FUNC initgalpy_integrate_c(void); // Python 2 + PyMODINIT_FUNC initlibgalpy(void); // Python 2 #endif #endif //OpenMP diff -Nru galpy-1.5/galpy/orbit/orbit_c_ext/integratePlanarOrbit.c galpy-1.6.0.post0/galpy/orbit/orbit_c_ext/integratePlanarOrbit.c --- galpy-1.5/galpy/orbit/orbit_c_ext/integratePlanarOrbit.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/orbit/orbit_c_ext/integratePlanarOrbit.c 2020-04-24 19:48:38.000000000 +0000 @@ -313,9 +313,36 @@ potentialArgs->mdensDeriv= &PerfectEllipsoidPotentialmdensDeriv; potentialArgs->nargs = (int) (21 + *(*pot_args+7) + 2 * *(*pot_args + (int) (*(*pot_args+7) + 20))); - break; - // 31: KGPotential - // 32: IsothermalDiskPotential + break; + // 31: KGPotential + // 32: IsothermalDiskPotential + case 33: //DehnenCoreSphericalpotential + potentialArgs->potentialEval= &DehnenCoreSphericalPotentialEval; + potentialArgs->planarRforce= &DehnenCoreSphericalPotentialPlanarRforce; + potentialArgs->planarphiforce= &ZeroPlanarForce; + potentialArgs->planarR2deriv= &DehnenCoreSphericalPotentialPlanarR2deriv; + potentialArgs->planarphi2deriv= &ZeroPlanarForce; + potentialArgs->planarRphideriv= &ZeroPlanarForce; + potentialArgs->nargs= 2; + break; + case 34: //DehnenSphericalpotential + potentialArgs->potentialEval= &DehnenSphericalPotentialEval; + potentialArgs->planarRforce= &DehnenSphericalPotentialPlanarRforce; + potentialArgs->planarphiforce= &ZeroPlanarForce; + potentialArgs->planarR2deriv= &DehnenSphericalPotentialPlanarR2deriv; + potentialArgs->planarphi2deriv= &ZeroPlanarForce; + potentialArgs->planarRphideriv= &ZeroPlanarForce; + potentialArgs->nargs= 3; + break; + case 35: //HomogeneousSpherePotential, 3 arguments + potentialArgs->potentialEval= &HomogeneousSpherePotentialEval; + potentialArgs->planarRforce= &HomogeneousSpherePotentialPlanarRforce; + potentialArgs->planarphiforce= &ZeroPlanarForce; + potentialArgs->planarR2deriv= &HomogeneousSpherePotentialPlanarR2deriv; + potentialArgs->planarphi2deriv= &ZeroPlanarForce; + potentialArgs->planarRphideriv= &ZeroPlanarForce; + potentialArgs->nargs= 3; + break; //////////////////////////////// WRAPPERS ///////////////////////////////////// case -1: //DehnenSmoothWrapperPotential potentialArgs->potentialEval= &DehnenSmoothWrapperPotentialEval; @@ -621,7 +648,6 @@ } void initPlanarMovingObjectSplines(struct potentialArg * potentialArgs, double ** pot_args){ - gsl_interp_accel *x_accel_ptr = gsl_interp_accel_alloc(); gsl_interp_accel *y_accel_ptr = gsl_interp_accel_alloc(); int nPts = (int) **pot_args; @@ -644,10 +670,14 @@ gsl_spline_init(x_spline, t, x_arr, nPts); gsl_spline_init(y_spline, t, y_arr, nPts); - potentialArgs->xSpline = x_spline; - potentialArgs->accx = x_accel_ptr; - potentialArgs->ySpline = y_spline; - potentialArgs->accy = y_accel_ptr; + potentialArgs->nspline1d= 2; + potentialArgs->spline1d= (gsl_spline **) malloc ( 2*sizeof ( gsl_spline *) ); + potentialArgs->acc1d= (gsl_interp_accel **) \ + malloc ( 2 * sizeof ( gsl_interp_accel * ) ); + *potentialArgs->spline1d = x_spline; + *potentialArgs->acc1d = x_accel_ptr; + *(potentialArgs->spline1d+1)= y_spline; + *(potentialArgs->acc1d+1)= y_accel_ptr; *pot_args = *pot_args+ (int) (1+3*nPts); free(t); diff -Nru galpy-1.5/galpy/orbit/Orbits.py galpy-1.6.0.post0/galpy/orbit/Orbits.py --- galpy-1.5/galpy/orbit/Orbits.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/orbit/Orbits.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,28 +5,27 @@ _PY3= sys.version > '3' import json import copy -import json import string from functools import wraps from random import choice from string import ascii_lowercase +from pkg_resources import parse_version import warnings import numpy from scipy import interpolate, optimize import scipy -_SCIPY_VERSION= [int(v.split('rc')[0]) - for v in scipy.__version__.split('.')] -if _SCIPY_VERSION[0] < 1 and _SCIPY_VERSION[1] < 10: #pragma: no cover +_SCIPY_VERSION= parse_version(scipy.__version__) +if _SCIPY_VERSION < parse_version('0.10'): #pragma: no cover from scipy.maxentropy import logsumexp -elif _SCIPY_VERSION[0] < 1 and _SCIPY_VERSION[1] < 19: #pragma: no cover +elif _SCIPY_VERSION < parse_version('0.19'): #pragma: no cover from scipy.misc import logsumexp else: from scipy.special import logsumexp from ..util import galpyWarning, galpyWarningVerbose -from ..util.bovy_conversion import physical_conversion +from ..util.bovy_conversion import physical_conversion, physical_compatible from ..util.bovy_coords import _K from ..util import bovy_coords as coords -import galpy.util.bovy_plot as plot +from ..util import bovy_plot as plot from ..util import bovy_conversion from ..potential import toPlanarPotential, PotentialError, evaluatePotentials,\ evaluateplanarPotentials, evaluatelinearPotentials @@ -49,14 +48,14 @@ if _APY_LOADED: from astropy import units, coordinates import astropy - _APY3= astropy.__version__ > '3' - _APY_GE_31= tuple(map(int,(astropy.__version__.split('.')))) > (3,0,5) + _APY3= parse_version(astropy.__version__) > parse_version('3') + _APY_GE_31= parse_version(astropy.__version__) > parse_version('3.0.5') _ASTROQUERY_LOADED= True try: from astroquery.simbad import Simbad except ImportError: _ASTROQUERY_LOADED= False -from galpy.util import config +from ..util import config _APY_UNITS= config.__config__.getboolean('astropy','astropy-units') if _APY_LOADED: vxvv_units= [units.kpc,units.km/units.s,units.km/units.s, @@ -450,6 +449,9 @@ equivalencies=units.dimensionless_angles()).value/self._vo vz= vxvvg.d_z.to(units.km/units.s).value/self._vo vxvv= numpy.array([R,vR,vT,z,vz,phi]) + # Make sure radec and lb are False (issue #402) + radec= False + lb= False elif not isinstance(vxvv,list): vxvv= vxvv.T # (norb,phasedim) --> (phasedim,norb) easier later if not (_APY_LOADED and isinstance(vxvv,SkyCoord)) and (radec or lb): @@ -599,7 +601,7 @@ _update_keys_named_objects() # Stack coordinate-transform parameters, so they can be changed... obs= numpy.array([kwargs.get('ro',None), - kwargs.get('vro',None), + kwargs.get('vo',None), kwargs.get('zo',None), kwargs.get('solarmotion',None)], dtype='object') @@ -730,18 +732,6 @@ return cls(new_vxvv, ro=ro,vo=vo,zo=zo,solarmotion=solarmotion) - def fit(self,*args,**kwargs): # pragma: no cover - raise RuntimeError('Orbit.fit has been deprecated in favor of Orbit.from_fit') - - def setphi(self,*args,**kwargs): # pragma: no cover - raise RuntimeError('Orbit.setphi has been deprecated') - - def reverse(self,*args,**kwargs): # pragma: no cover - raise RuntimeError('Orbit.reverse has been deprecated') - - def __add__(self,*args,**kwargs): # pragma: no cover - raise RuntimeError('Orbit.__add__ has been deprecated') - def __len__(self): return 1 if self.shape == () else self.shape[0] @@ -1032,14 +1022,16 @@ 2019-02-28 - Written - Bovy (UofT) + 2020-04-22 - Don't turn on a parameter when it is False - Bovy (UofT) + """ - self._roSet= True - self._voSet= True - if not ro is None: + if not ro is False: self._roSet= True + if not vo is False: self._voSet= True + if not ro is None and ro: if _APY_LOADED and isinstance(ro,units.Quantity): ro= ro.to(units.kpc).value self._ro= ro - if not vo is None: + if not vo is None and vo: if _APY_LOADED and isinstance(vo,units.Quantity): vo= vo.to(units.km/units.s).value self._vo= vo @@ -1105,7 +1097,7 @@ if _APY_LOADED and not dt is None and isinstance(dt,units.Quantity): dt= dt.to(units.Gyr).value\ /bovy_conversion.time_in_Gyr(self._vo,self._ro) - from galpy.potential import MWPotential + from ..potential import MWPotential if 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) @@ -1178,6 +1170,28 @@ out= out[:,:,:-1] # Store orbit internally self.orbit= out + # Check whether r ever < minr if dynamical friction is included and warn if so + from ..potential import ChandrasekharDynamicalFrictionForce + if numpy.any([isinstance(p,ChandrasekharDynamicalFrictionForce) + for p in flatten_potential([pot])]): # make sure pot=list + lpot= flatten_potential([pot]) + cdf_indx= numpy.arange(len(lpot))[\ + numpy.array([isinstance(p,ChandrasekharDynamicalFrictionForce) + for p in lpot],dtype='bool')][0] + if numpy.any(self.r(self.t,use_physical=False) \ + < lpot[cdf_indx]._minr): + warnings.warn("""Orbit integration with """ + """ChandrasekharDynamicalFrictionForce """ + """entered domain where r < minr and """ + """ChandrasekharDynamicalFrictionForce is """ + """turned off; initialize """ + """ChandrasekharDynamicalFrictionForce with a """ + """smaller minr to avoid this if you wish """ + """(but note that you want to turn it off """ + """close to the center for an object that """ + """sinks all the way to r=0, to avoid """ + """numerical instabilities)""", + galpyWarning) return None def integrate_dxdv(self,dxdv,t,pot,method='dopr54_c',dt=None, @@ -1905,7 +1919,7 @@ delta=delta, **kwargs) elif self._aAType.lower() == 'isochroneapprox': - from galpy.actionAngle import actionAngleIsochroneApprox + from ..actionAngle import actionAngleIsochroneApprox self._aA= actionAngleIsochroneApprox(pot=self._aAPot,b=b, **kwargs) elif self._aAType.lower() == 'spherical': @@ -4231,7 +4245,11 @@ t= args[0] # Parse t, first check whether we are dealing with the common case # where one wants all integrated times + # 2nd line: scalar Quantities have __len__, but raise TypeError + # for scalars t_exact_integration_times= hasattr(t,'__len__') \ + and not (_APY_LOADED and isinstance(t,units.Quantity) + and t.isscalar) \ and (len(t) == len(self.t)) \ and numpy.all(t == self.t) if _APY_LOADED and isinstance(t,units.Quantity): @@ -4248,11 +4266,11 @@ warnings.warn("You specified integration times as a Quantity, but are evaluating at times not specified as a Quantity; assuming that time given is in natural (internal) units (multiply time by unit to get output at physical time)",galpyWarning) if t_exact_integration_times: # Common case where one wants all integrated times return self.orbit.T - elif isinstance(t,(int,float)) and hasattr(self,'t') \ + elif isinstance(t,(int,float,numpy.number)) and hasattr(self,'t') \ and t in list(self.t): return numpy.array(self.orbit[:,list(self.t).index(t),:]).T else: - if isinstance(t,(int,float)): + if isinstance(t,(int,float,numpy.number)): nt= 1 t= numpy.atleast_1d(t) else: @@ -4584,15 +4602,21 @@ kwargs.pop('pot',None) kwargs.pop('OmegaP',None) kwargs.pop('quantity',None) + auto_scale= not 'xrange' in kwargs and not 'yrange' in kwargs \ + and not kwargs.get('overplot',False) + labels= kwargs.pop('label',['Orbit {}'.format(ii+1) + for ii in range(self.size)]) + if self.size == 1 and isinstance(labels,str): labels= [labels] #Plot if not 'xlabel' in kwargs: kwargs['xlabel']= labeldict.get(d1,r'${}$'.format(d1)) if not 'ylabel' in kwargs: kwargs['ylabel']= labeldict.get(d2,r'${}$'.format(d2)) - for tx,ty in zip(x,y): + for ii,(tx,ty) in enumerate(zip(x,y)): + kwargs['label']= labels[ii] line2d= plot.bovy_plot(tx,ty,*args,**kwargs)[0] kwargs['overplot']= True - line2d.axes.autoscale(enable=True) + if auto_scale: line2d.axes.autoscale(enable=True) plot._add_ticks() return [line2d] @@ -4715,6 +4739,8 @@ kwargs.pop('obs',None) kwargs.pop('use_physical',None) kwargs.pop('quantity',None) + auto_scale= not 'xrange' in kwargs and not 'yrange' in kwargs \ + and not 'zrange' in kwargs and not kwargs.get('overplot',False) #Plot if not 'xlabel' in kwargs: kwargs['xlabel']= labeldict.get(d1,r'${}$'.format(d1)) @@ -4725,7 +4751,7 @@ for tx,ty,tz in zip(x,y,z): line3d= plot.bovy_plot3d(tx,ty,tz,*args,**kwargs)[0] kwargs['overplot']= True - line3d.axes.autoscale(enable=True) + if auto_scale: line3d.axes.autoscale(enable=True) plot._add_ticks() return [line3d] @@ -4755,6 +4781,8 @@ json_filename= (None) if set, save the data necessary for the figure in this filename (e.g., json_filename= 'orbit_data/orbit.json'); this path is also used in the output HTML, so needs to be accessible + staticPlot= (False) if True, create a static plot that doesn't allow zooming, panning, etc. + ro= (Object-wide default) physical scale for distances to use to convert (can be Quantity) vo= (Object-wide default) physical scale for velocities to use to convert (can be Quantity) @@ -4892,10 +4920,9 @@ height= kwargs.pop('height',400) load_jslibs= kwargs.pop('load_jslibs',True) if load_jslibs: - load_jslibs_code= """ + load_jslibs_code= """ - + +""".format(json_code=json_code,close_json_code=close_json_code, divid=self.divid,width=width,height=height, - button_margin_left=button_margin_left, + button_margin_left=button_margin_left,config=config, layout=layout,load_jslibs_code=load_jslibs_code, + x_data_list=x_data_list, y_data_list=y_data_list, + trace_num_10_list=trace_num_10_list, trace_num_20_list=trace_num_20_list, setup_trace1=setup_trace1,setup_trace2=setup_trace2, - setup_trace3=setup_trace3,delete_trace2=delete_trace2, - delete_trace4=delete_trace4,delete_trace6=delete_trace6, - delete_trace1=delete_trace1,delete_trace3=delete_trace3, - delete_trace5=delete_trace5, - update_trace12=update_trace12, - update_trace34=update_trace34, - update_trace56=update_trace56)) + setup_trace3=setup_trace3, trace_num_list= [ii for ii in range(self.size * len(d1s))])) class _1DInterp(object): """Class to simulate 2D interpolation when using a single orbit""" @@ -5860,20 +5771,10 @@ return False def _check_potential_dim(orb,pot): - from galpy.potential import _dim + from ..potential import _dim # Don't deal with pot=None here, just dimensionality assert pot is None or orb.dim() <= _dim(pot), 'Orbit dimensionality is %i, but potential dimensionality is %i < %i; orbit needs to be of equal or lower dimensionality as the potential; you can reduce the dimensionality---if appropriate---of your orbit with orbit.toPlanar or orbit.toVertical' % (orb.dim(),_dim(pot),orb.dim()) def _check_consistent_units(orb,pot): if pot is None: return None - if isinstance(pot,list): - if orb._roSet and pot[0]._roSet: - assert numpy.fabs(orb._ro-pot[0]._ro) < 10.**-10., 'Physical conversion for the Orbit object is not consistent with that of the Potential given to it' - if orb._voSet and pot[0]._voSet: - assert numpy.fabs(orb._vo-pot[0]._vo) < 10.**-10., 'Physical conversion for the Orbit object is not consistent with that of the Potential given to it' - else: - if orb._roSet and pot._roSet: - assert numpy.fabs(orb._ro-pot._ro) < 10.**-10., 'Physical conversion for the Orbit object is not consistent with that of the Potential given to it' - if orb._voSet and pot._voSet: - assert numpy.fabs(orb._vo-pot._vo) < 10.**-10., 'Physical conversion for the Orbit object is not consistent with that of the Potential given to it' - return None + assert physical_compatible(orb,pot), 'Physical conversion for the Orbit object is not consistent with that of the Potential given to it' diff -Nru galpy-1.5/galpy/potential/amuse.py galpy-1.6.0.post0/galpy/potential/amuse.py --- galpy-1.5/galpy/potential/amuse.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/amuse.py 2020-04-24 19:48:38.000000000 +0000 @@ -97,14 +97,16 @@ Phi(x,y,z) HISTORY: 2019-08-12 - Written - Webb (UofT) + 2019-11-06 - added physical compatibility - Starkman (UofT) """ R= numpy.sqrt(x.value_in(units.kpc)**2.+y.value_in(units.kpc)**2.) zed= z.value_in(units.kpc) phi= numpy.arctan2(y.value_in(units.kpc),x.value_in(units.kpc)) - return potential.evaluatePotentials(self.pot,R/self.ro,zed/self.ro, - phi=phi,t=self.tgalpy, - ro=self.ro,vo=self.vo) \ - | units.km**2*units.s**-2 + res= potential.evaluatePotentials(self.pot,R/self.ro,zed/self.ro, + phi=phi,t=self.tgalpy, + ro=self.ro,vo=self.vo, + use_physical=False) + return res * self.vo**2 | units.kms**2 def get_gravity_at_point(self,eps,x,y,z): """ @@ -119,29 +121,33 @@ ax,ay,az HISTORY: 2019-08-12 - Written - Webb (UofT) + 2019-11-06 - added physical compatibility - Starkman (UofT) """ R= numpy.sqrt(x.value_in(units.kpc)**2.+y.value_in(units.kpc)**2.) zed= z.value_in(units.kpc) phi= numpy.arctan2(y.value_in(units.kpc),x.value_in(units.kpc)) # Cylindrical force Rforce= potential.evaluateRforces(self.pot,R/self.ro,zed/self.ro, - phi=phi,t=self.tgalpy) + phi=phi,t=self.tgalpy, + use_physical=False) phiforce= potential.evaluatephiforces(self.pot,R/self.ro,zed/self.ro, - phi=phi,t=self.tgalpy)\ + phi=phi,t=self.tgalpy, + use_physical=False)\ /(R/self.ro) zforce=potential.evaluatezforces(self.pot,R/self.ro,zed/self.ro, - phi=phi,t=self.tgalpy) + phi=phi,t=self.tgalpy, + use_physical=False) # Convert cylindrical force --> rectangular cp, sp= numpy.cos(phi), numpy.sin(phi) ax= (Rforce*cp - phiforce*sp)\ *bovy_conversion.force_in_kmsMyr(ro=self.ro,vo=self.vo) \ - | units.kms * units.myr**-1 + | units.kms / units.Myr ay= (Rforce*sp + phiforce*cp)\ *bovy_conversion.force_in_kmsMyr(ro=self.ro,vo=self.vo) \ - | units.kms * units.myr**-1 + | units.kms / units.Myr az= zforce\ *bovy_conversion.force_in_kmsMyr(ro=self.ro,vo=self.vo) \ - | units.kms * units.myr**-1 + | units.kms / units.Myr return ax,ay,az def mass_density(self,x,y,z): @@ -157,14 +163,17 @@ the density HISTORY: 2019-08-12 - Written - Webb (UofT) + 2019-11-06 - added physical compatibility - Starkman (UofT) """ R= numpy.sqrt(x.value_in(units.kpc)**2.+y.value_in(units.kpc)**2.) zed= z.value_in(units.kpc) phi= numpy.arctan2(y.value_in(units.kpc),x.value_in(units.kpc)) - return potential.evaluateDensities(self.pot,R/self.ro,zed/self.ro, - phi=phi,t=self.tgalpy, - ro=self.ro,vo=self.vo) \ - | units.MSun/(units.parsec**3.) + res= (potential.evaluateDensities(self.pot,R/self.ro,zed/self.ro, + phi=phi,t=self.tgalpy, + ro=self.ro,vo=self.vo, + use_physical=False) * + bovy_conversion.dens_in_msolpc3(self.vo,self.ro)) + return res | units.MSun / units.parsec**3 def circular_velocity(self,r): """ @@ -178,10 +187,13 @@ the circular velocity HISTORY: 2019-08-12 - Written - Webb (UofT) + 2019-11-06 - added physical compatibility - Starkman (UofT) """ - return potential.vcirc(self.pot,r.value_in(units.kpc)/self.ro,phi=0, - t=self.tgalpy,ro=self.ro,vo=self.vo) | units.kms - + res= potential.vcirc(self.pot,r.value_in(units.kpc)/self.ro,phi=0, + t=self.tgalpy,ro=self.ro,vo=self.vo, + use_physical=False) + return res * self.vo | units.kms + def enclosed_mass(self,r): """ NAME: @@ -194,10 +206,13 @@ the mass enclosed HISTORY: 2019-08-12 - Written - Webb (UofT) + 2019-11-06 - added physical compatibility - Starkman (UofT) """ - vc2= potential.vcirc(self.pot,r.value_in(units.kpc)/self.ro,phi=0, - t=self.tgalpy,ro=self.ro,vo=self.vo)**2. - return vc2*r.value_in(units.kpc)/bovy_conversion._G*1000. | units.MSun + vc= potential.vcirc(self.pot,r.value_in(units.kpc)/self.ro,phi=0, + t=self.tgalpy,ro=self.ro,vo=self.vo, + use_physical=False) * self.vo + return (vc**2.)*r.value_in(units.parsec)/bovy_conversion._G \ + | units.MSun def stop(self): """ diff -Nru galpy-1.5/galpy/potential/BurkertPotential.py galpy-1.6.0.post0/galpy/potential/BurkertPotential.py --- galpy-1.5/galpy/potential/BurkertPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/BurkertPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -56,6 +56,7 @@ self.normalize(normalize) self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True return None def _evaluate(self,R,z,phi=0.,t=0.): diff -Nru galpy-1.5/galpy/potential/ChandrasekharDynamicalFrictionForce.py galpy-1.6.0.post0/galpy/potential/ChandrasekharDynamicalFrictionForce.py --- galpy-1.5/galpy/potential/ChandrasekharDynamicalFrictionForce.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/ChandrasekharDynamicalFrictionForce.py 2020-04-24 19:48:38.000000000 +0000 @@ -6,9 +6,9 @@ import hashlib import numpy from scipy import special, interpolate -from galpy.util import bovy_conversion +from ..util import bovy_conversion from .DissipativeForce import DissipativeForce -from .Potential import _APY_LOADED, evaluateDensities +from .Potential import _APY_LOADED, evaluateDensities, _check_c from .Potential import flatten as flatten_pot if _APY_LOADED: from astropy import units @@ -111,19 +111,36 @@ R,z,phi=phi,t=t, use_physical=False) if sigmar is None: - from galpy.df import jeans + from ..df import jeans sigmar= lambda x: jeans.sigmar(self._dens_pot,x,beta=0., use_physical=False) - sigmar_rs= numpy.linspace(self._minr,self._maxr,nr) + self._sigmar_rs_4interp= numpy.linspace(self._minr,self._maxr,nr) + self._sigmars_4interp= numpy.array([sigmar(x) + for x in self._sigmar_rs_4interp]) + if numpy.any(numpy.isnan(self._sigmars_4interp)): + # Check for case where density is zero, in that case, just + # paint in the nearest neighbor for the interpolation + # (doesn't matter in the end, because force = 0 when dens = 0) + nanrs_indx= numpy.isnan(self._sigmars_4interp) + if numpy.all(numpy.array([self._dens(r*_INVSQRTTWO,r*_INVSQRTTWO) + for r in + self._sigmar_rs_4interp[nanrs_indx]]) + == 0.): + self._sigmars_4interp[nanrs_indx]= interpolate.interp1d(\ + self._sigmar_rs_4interp[True^nanrs_indx], + self._sigmars_4interp[True^nanrs_indx], + kind="nearest",fill_value="extrapolate")\ + (self._sigmar_rs_4interp[nanrs_indx]) self.sigmar_orig= sigmar self.sigmar= interpolate.InterpolatedUnivariateSpline(\ - sigmar_rs,numpy.array([sigmar(x) for x in sigmar_rs]),k=3) + self._sigmar_rs_4interp,self._sigmars_4interp,k=3) if const_lnLambda: self._lnLambda= const_lnLambda else: self._lnLambda= False self._amp*= 4.*numpy.pi self._force_hash= None + self.hasC= _check_c(self._dens_pot,dens=True) return None def GMs(self,gms): @@ -290,7 +307,7 @@ if self._dens_kwarg is None and self._sigmar_kwarg is None: self.sigmar_orig= lambda x: _INVSQRTTWO else: - from galpy.df import jeans + from ..df import jeans self.sigmar_orig= lambda x: jeans.sigmar(self._dens_pot,x,beta=0., use_physical=False) return None diff -Nru galpy-1.5/galpy/potential/CorotatingRotationWrapperPotential.py galpy-1.6.0.post0/galpy/potential/CorotatingRotationWrapperPotential.py --- galpy-1.5/galpy/potential/CorotatingRotationWrapperPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/CorotatingRotationWrapperPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,7 +5,7 @@ ############################################################################### from .WrapperPotential import parentWrapperPotential from .Potential import _APY_LOADED -from galpy.util import bovy_conversion +from ..util import bovy_conversion if _APY_LOADED: from astropy import units class CorotatingRotationWrapperPotential(parentWrapperPotential): diff -Nru galpy-1.5/galpy/potential/CosmphiDiskPotential.py galpy-1.6.0.post0/galpy/potential/CosmphiDiskPotential.py --- galpy-1.5/galpy/potential/CosmphiDiskPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/CosmphiDiskPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,11 +1,11 @@ ############################################################################### # CosmphiDiskPotential: cos(mphi) potential ############################################################################### -import math +import numpy from .planarPotential import planarPotential, _APY_LOADED if _APY_LOADED: from astropy import units -_degtorad= math.pi/180. +_degtorad= numpy.pi/180. class CosmphiDiskPotential(planarPotential): """Class that implements the disk potential @@ -87,10 +87,10 @@ self._phib= phib self._mphio= phio*self._m else: - self._mphio= math.sqrt(cp*cp+sp*sp) - self._phib= math.atan(sp/cp)/self._m + self._mphio= numpy.sqrt(cp*cp+sp*sp) + self._phib= numpy.arctan(sp/cp)/self._m if m < 2. and cp < 0.: - self._phib= math.pi+self._phib + self._phib= numpy.pi+self._phib self._p= p if rb is None: self._rb= 0. @@ -120,11 +120,11 @@ 2011-10-19 - Started - Bovy (IAS) """ if R < self._rb: - return self._mphio/self._m*math.cos(self._m*phi-self._mphib)\ + return self._mphio/self._m*numpy.cos(self._m*phi-self._mphib)\ *self._rbp*(2.*self._r1p-self._rbp/R**self._p) else: return self._mphio/self._m*R**self._p\ - *math.cos(self._m*phi-self._mphib) + *numpy.cos(self._m*phi-self._mphib) def _Rforce(self,R,phi=0.,t=0.): """ @@ -143,10 +143,10 @@ """ if R < self._rb: return -self._p*self._mphio/self._m*self._rb2p/R**(self._p+1.)\ - *math.cos(self._m*phi-self._mphib) + *numpy.cos(self._m*phi-self._mphib) else: return -self._p*self._mphio/self._m*R**(self._p-1.)\ - *math.cos(self._m*phi-self._mphib) + *numpy.cos(self._m*phi-self._mphib) def _phiforce(self,R,phi=0.,t=0.): """ @@ -164,34 +164,34 @@ 2011-10-19 - Written - Bovy (IAS) """ if R < self._rb: - return self._mphio*math.sin(self._m*phi-self._mphib)\ + return self._mphio*numpy.sin(self._m*phi-self._mphib)\ *self._rbp*(2.*self._r1p-self._rbp/R**self._p) else: - return self._mphio*R**self._p*math.sin(self._m*phi-self._mphib) + return self._mphio*R**self._p*numpy.sin(self._m*phi-self._mphib) def _R2deriv(self,R,phi=0.,t=0.): if R < self._rb: return -self._p*(self._p+1.)*self._mphio/self._m\ - *self._rb2p/R**(self._p+2.)*math.cos(self._m*phi-self._mphib) + *self._rb2p/R**(self._p+2.)*numpy.cos(self._m*phi-self._mphib) else: return self._p*(self._p-1.)/self._m*self._mphio*R**(self._p-2.)\ - *math.cos(self._m*phi-self._mphib) + *numpy.cos(self._m*phi-self._mphib) def _phi2deriv(self,R,phi=0.,t=0.): if R < self._rb: - return -self._m*self._mphio*math.cos(self._m*phi-self._mphib)\ + return -self._m*self._mphio*numpy.cos(self._m*phi-self._mphib)\ *self._rbp*(2.*self._r1p-self._rbp/R**self._p) else: return -self._m*self._mphio*R**self._p\ - *math.cos(self._m*phi-self._mphib) + *numpy.cos(self._m*phi-self._mphib) def _Rphideriv(self,R,phi=0.,t=0.): if R < self._rb: return -self._p*self._mphio/self._m*self._rb2p/R**(self._p+1.)\ - *math.sin(self._m*phi-self._mphib) + *numpy.sin(self._m*phi-self._mphib) else: return -self._p*self._mphio*R**(self._p-1.)*\ - math.sin(self._m*phi-self._mphib) + numpy.sin(self._m*phi-self._mphib) class LopsidedDiskPotential(CosmphiDiskPotential): """Class that implements the disk potential diff -Nru galpy-1.5/galpy/potential/DehnenBarPotential.py galpy-1.6.0.post0/galpy/potential/DehnenBarPotential.py --- galpy-1.5/galpy/potential/DehnenBarPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/DehnenBarPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -2,7 +2,7 @@ # DehnenBarPotential: Dehnen (2000)'s bar potential ############################################################################### import numpy -from galpy.util import bovy_conversion +from ..util import bovy_conversion from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units diff -Nru galpy-1.5/galpy/potential/DehnenSmoothWrapperPotential.py galpy-1.6.0.post0/galpy/potential/DehnenSmoothWrapperPotential.py --- galpy-1.5/galpy/potential/DehnenSmoothWrapperPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/DehnenSmoothWrapperPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -3,7 +3,7 @@ ############################################################################### from .WrapperPotential import parentWrapperPotential from .Potential import _APY_LOADED -from galpy.util import bovy_conversion +from ..util import bovy_conversion if _APY_LOADED: from astropy import units class DehnenSmoothWrapperPotential(parentWrapperPotential): diff -Nru galpy-1.5/galpy/potential/DiskSCFPotential.py galpy-1.6.0.post0/galpy/potential/DiskSCFPotential.py --- galpy-1.5/galpy/potential/DiskSCFPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/DiskSCFPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,14 +1,14 @@ ############################################################################### # DiskSCFPotential.py: Potential expansion for disk+halo potentials ############################################################################### +from pkg_resources import parse_version import copy import numpy import scipy -_SCIPY_VERSION= [int(v.split('rc')[0]) - for v in scipy.__version__.split('.')] -if _SCIPY_VERSION[0] < 1 and _SCIPY_VERSION[1] < 10: #pragma: no cover +_SCIPY_VERSION= parse_version(scipy.__version__) +if _SCIPY_VERSION < parse_version('0.10'): #pragma: no cover from scipy.maxentropy import logsumexp -elif _SCIPY_VERSION[0] < 1 and _SCIPY_VERSION[1] < 19: #pragma: no cover +elif _SCIPY_VERSION < parse_version('0.19'): #pragma: no cover from scipy.misc import logsumexp else: from scipy.special import logsumexp @@ -132,6 +132,7 @@ self._scf= SCFPotential(amp=1.,Acos=Acos,Asin=Asin,a=a,ro=None,vo=None) if not self._Sigma_dict is None and not self._hz_dict is None: self.hasC= True + self.hasC_dens= True if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): diff -Nru galpy-1.5/galpy/potential/DissipativeForce.py galpy-1.6.0.post0/galpy/potential/DissipativeForce.py --- galpy-1.5/galpy/potential/DissipativeForce.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/DissipativeForce.py 2020-04-24 19:48:38.000000000 +0000 @@ -3,7 +3,7 @@ ############################################################################### import numpy from .Force import Force -from galpy.util.bovy_conversion import physical_conversion, \ +from ..util.bovy_conversion import physical_conversion, \ potential_physical_input class DissipativeForce(Force): """Top-level class for non-conservative forces (cannot be derived from a potential function)""" @@ -23,6 +23,7 @@ self.isNonAxi= True # Default: are non-axisymmetric self.hasC= False self.hasC_dxdv= False + self.hasC_dens= False @potential_physical_input @physical_conversion('force',pop=True) diff -Nru galpy-1.5/galpy/potential/DoubleExponentialDiskPotential.py galpy-1.6.0.post0/galpy/potential/DoubleExponentialDiskPotential.py --- galpy-1.5/galpy/potential/DoubleExponentialDiskPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/DoubleExponentialDiskPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -4,10 +4,8 @@ # # rho(R,z) = rho_0 e^-R/h_R e^-|z|/h_z ############################################################################### -import numpy as nu -import warnings -from scipy import special, integrate -from galpy.util import galpyWarning +import numpy +from scipy import special from .PowerSphericalPotential import KeplerPotential from .Potential import Potential, _APY_LOADED if _APY_LOADED: @@ -68,6 +66,7 @@ if _APY_LOADED and isinstance(hz,units.Quantity): hz= hz.to(units.kpc).value/self._ro self.hasC= True + self.hasC_dens= True self._kmaxFac= kmaxFac self._glorder= glorder self._hr= hr @@ -80,29 +79,29 @@ self._tol= tol self._zforceNotSetUp= True #We have not calculated a typical Kz yet #Setup j0 zeros etc. - self._glx, self._glw= nu.polynomial.legendre.leggauss(self._glorder) + self._glx, self._glw= numpy.polynomial.legendre.leggauss(self._glorder) self._nzeros=100 #j0 for potential and z - self._j0zeros= nu.zeros(self._nzeros+1) + self._j0zeros= numpy.zeros(self._nzeros+1) self._j0zeros[1:self._nzeros+1]= special.jn_zeros(0,self._nzeros) - self._dj0zeros= self._j0zeros-nu.roll(self._j0zeros,1) + self._dj0zeros= self._j0zeros-numpy.roll(self._j0zeros,1) self._dj0zeros[0]= self._j0zeros[0] #j1 for R - self._j1zeros= nu.zeros(self._nzeros+1) + self._j1zeros= numpy.zeros(self._nzeros+1) self._j1zeros[1:self._nzeros+1]= special.jn_zeros(1,self._nzeros) - self._dj1zeros= self._j1zeros-nu.roll(self._j1zeros,1) + self._dj1zeros= self._j1zeros-numpy.roll(self._j1zeros,1) self._dj1zeros[0]= self._j1zeros[0] #j2 for R2deriv - self._j2zeros= nu.zeros(self._nzeros+1) + self._j2zeros= numpy.zeros(self._nzeros+1) self._j2zeros[1:self._nzeros+1]= special.jn_zeros(2,self._nzeros) - self._dj2zeros= self._j2zeros-nu.roll(self._j2zeros,1) + self._dj2zeros= self._j2zeros-numpy.roll(self._j2zeros,1) self._dj2zeros[0]= self._j2zeros[0] if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): #pragma: no cover self.normalize(normalize) #Load Kepler potential for large R - self._kp= KeplerPotential(normalize=4.*nu.pi/self._alpha**2./self._beta) + self._kp= KeplerPotential(normalize=4.*numpy.pi/self._alpha**2./self._beta) def _evaluate(self,R,z,phi=0.,t=0.,dR=0,dphi=0): """ @@ -129,31 +128,31 @@ if True: if isinstance(R,float): floatIn= True - R= nu.array([R]) - z= nu.array([z]) + R= numpy.array([R]) + z= numpy.array([z]) else: if isinstance(z,float): - z= z*nu.ones_like(R) + z= z*numpy.ones_like(R) floatIn= False outShape= R.shape # this code can't do arbitrary shapes R= R.flatten() z= z.flatten() - out= nu.empty(len(R)) + out= numpy.empty(len(R)) indx= (R <= 6.) - if nu.sum(True^indx) > 0: + if numpy.sum(True^indx) > 0: out[True^indx]= self._kp(R[True^indx],z[True^indx]) - R4max= nu.copy(R) + R4max= numpy.copy(R) R4max[(R < 1.)]= 1. kmax= self._kmaxFac*self._beta for jj in range(len(R)): if not indx[jj]: continue - maxj0zeroIndx= nu.argmin((self._j0zeros-kmax*R4max[jj])**2.) #close enough - ks= nu.array([0.5*(self._glx+1.)*self._dj0zeros[ii+1] + self._j0zeros[ii] for ii in range(maxj0zeroIndx)]).flatten() - weights= nu.array([self._glw*self._dj0zeros[ii+1] for ii in range(maxj0zeroIndx)]).flatten() - evalInt= special.jn(0,ks*R[jj])*(self._alpha**2.+ks**2.)**-1.5*(self._beta*nu.exp(-ks*nu.fabs(z[jj]))-ks*nu.exp(-self._beta*nu.fabs(z[jj])))/(self._beta**2.-ks**2.) - out[jj]= -2.*nu.pi*self._alpha*nu.sum(weights*evalInt) + maxj0zeroIndx= numpy.argmin((self._j0zeros-kmax*R4max[jj])**2.) #close enough + ks= numpy.array([0.5*(self._glx+1.)*self._dj0zeros[ii+1] + self._j0zeros[ii] for ii in range(maxj0zeroIndx)]).flatten() + weights= numpy.array([self._glw*self._dj0zeros[ii+1] for ii in range(maxj0zeroIndx)]).flatten() + evalInt= special.jn(0,ks*R[jj])*(self._alpha**2.+ks**2.)**-1.5*(self._beta*numpy.exp(-ks*numpy.fabs(z[jj]))-ks*numpy.exp(-self._beta*numpy.fabs(z[jj])))/(self._beta**2.-ks**2.) + out[jj]= -2.*numpy.pi*self._alpha*numpy.sum(weights*evalInt) if floatIn: return out[0] - else: return nu.reshape(out,outShape) + else: return numpy.reshape(out,outShape) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -173,20 +172,20 @@ DOCTEST: """ if True: - if isinstance(R,nu.ndarray): - if not isinstance(z,nu.ndarray): z= nu.ones_like(R)*z - out= nu.array([self._Rforce(rr,zz) for rr,zz in zip(R,z)]) + if isinstance(R,numpy.ndarray): + if not isinstance(z,numpy.ndarray): z= numpy.ones_like(R)*z + out= numpy.array([self._Rforce(rr,zz) for rr,zz in zip(R,z)]) return out if (R > 16.*self._hr or R > 6.) and hasattr(self,'_kp'): return self._kp.Rforce(R,z) if R < 1.: R4max= 1. else: R4max= R kmax= self._kmaxFac*self._beta kmax= 2.*self._kmaxFac*self._beta - maxj1zeroIndx= nu.argmin((self._j1zeros-kmax*R4max)**2.) #close enough - ks= nu.array([0.5*(self._glx+1.)*self._dj1zeros[ii+1] + self._j1zeros[ii] for ii in range(maxj1zeroIndx)]).flatten() - weights= nu.array([self._glw*self._dj1zeros[ii+1] for ii in range(maxj1zeroIndx)]).flatten() - evalInt= ks*special.jn(1,ks*R)*(self._alpha**2.+ks**2.)**-1.5*(self._beta*nu.exp(-ks*nu.fabs(z))-ks*nu.exp(-self._beta*nu.fabs(z)))/(self._beta**2.-ks**2.) - return -2.*nu.pi*self._alpha*nu.sum(weights*evalInt) + maxj1zeroIndx= numpy.argmin((self._j1zeros-kmax*R4max)**2.) #close enough + ks= numpy.array([0.5*(self._glx+1.)*self._dj1zeros[ii+1] + self._j1zeros[ii] for ii in range(maxj1zeroIndx)]).flatten() + weights= numpy.array([self._glw*self._dj1zeros[ii+1] for ii in range(maxj1zeroIndx)]).flatten() + evalInt= ks*special.jn(1,ks*R)*(self._alpha**2.+ks**2.)**-1.5*(self._beta*numpy.exp(-ks*numpy.fabs(z))-ks*numpy.exp(-self._beta*numpy.fabs(z)))/(self._beta**2.-ks**2.) + return -2.*numpy.pi*self._alpha*numpy.sum(weights*evalInt) def _zforce(self,R,z,phi=0.,t=0.): """ @@ -206,22 +205,22 @@ DOCTEST: """ if True: - if isinstance(R,nu.ndarray): - if not isinstance(z,nu.ndarray): z= nu.ones_like(R)*z - out= nu.array([self._zforce(rr,zz) for rr,zz in zip(R,z)]) + if isinstance(R,numpy.ndarray): + if not isinstance(z,numpy.ndarray): z= numpy.ones_like(R)*z + out= numpy.array([self._zforce(rr,zz) for rr,zz in zip(R,z)]) return out if R > 16.*self._hr or R > 6.: return self._kp.zforce(R,z) if R < 1.: R4max= 1. else: R4max= R kmax= self._kmaxFac*self._beta - maxj0zeroIndx= nu.argmin((self._j0zeros-kmax*R4max)**2.) #close enough - ks= nu.array([0.5*(self._glx+1.)*self._dj0zeros[ii+1] + self._j0zeros[ii] for ii in range(maxj0zeroIndx)]).flatten() - weights= nu.array([self._glw*self._dj0zeros[ii+1] for ii in range(maxj0zeroIndx)]).flatten() - evalInt= ks*special.jn(0,ks*R)*(self._alpha**2.+ks**2.)**-1.5*(nu.exp(-ks*nu.fabs(z))-nu.exp(-self._beta*nu.fabs(z)))/(self._beta**2.-ks**2.) + maxj0zeroIndx= numpy.argmin((self._j0zeros-kmax*R4max)**2.) #close enough + ks= numpy.array([0.5*(self._glx+1.)*self._dj0zeros[ii+1] + self._j0zeros[ii] for ii in range(maxj0zeroIndx)]).flatten() + weights= numpy.array([self._glw*self._dj0zeros[ii+1] for ii in range(maxj0zeroIndx)]).flatten() + evalInt= ks*special.jn(0,ks*R)*(self._alpha**2.+ks**2.)**-1.5*(numpy.exp(-ks*numpy.fabs(z))-numpy.exp(-self._beta*numpy.fabs(z)))/(self._beta**2.-ks**2.) if z > 0.: - return -2.*nu.pi*self._alpha*self._beta*nu.sum(weights*evalInt) + return -2.*numpy.pi*self._alpha*self._beta*numpy.sum(weights*evalInt) else: - return 2.*nu.pi*self._alpha*self._beta*nu.sum(weights*evalInt) + return 2.*numpy.pi*self._alpha*self._beta*numpy.sum(weights*evalInt) def _R2deriv(self,R,z,phi=0.,t=0.): """ @@ -240,24 +239,24 @@ 2012-12-27 - Written - Bovy (IAS) """ if True: - if isinstance(R,nu.ndarray): - if not isinstance(z,nu.ndarray): z= nu.ones_like(R)*z - out= nu.array([self._R2deriv(rr,zz) for rr,zz in zip(R,z)]) + if isinstance(R,numpy.ndarray): + if not isinstance(z,numpy.ndarray): z= numpy.ones_like(R)*z + out= numpy.array([self._R2deriv(rr,zz) for rr,zz in zip(R,z)]) return out if R > 16.*self._hr or R > 6.: return self._kp.R2deriv(R,z) if R < 1.: R4max= 1. else: R4max= R kmax= 2.*self._kmaxFac*self._beta - maxj0zeroIndx= nu.argmin((self._j0zeros-kmax*R4max)**2.) #close enough - maxj2zeroIndx= nu.argmin((self._j2zeros-kmax*R4max)**2.) #close enough - ks0= nu.array([0.5*(self._glx+1.)*self._dj0zeros[ii+1] + self._j0zeros[ii] for ii in range(maxj0zeroIndx)]).flatten() - weights0= nu.array([self._glw*self._dj0zeros[ii+1] for ii in range(maxj0zeroIndx)]).flatten() - ks2= nu.array([0.5*(self._glx+1.)*self._dj2zeros[ii+1] + self._j2zeros[ii] for ii in range(maxj2zeroIndx)]).flatten() - weights2= nu.array([self._glw*self._dj2zeros[ii+1] for ii in range(maxj2zeroIndx)]).flatten() - evalInt0= ks0**2.*special.jn(0,ks0*R)*(self._alpha**2.+ks0**2.)**-1.5*(self._beta*nu.exp(-ks0*nu.fabs(z))-ks0*nu.exp(-self._beta*nu.fabs(z)))/(self._beta**2.-ks0**2.) - evalInt2= ks2**2.*special.jn(2,ks2*R)*(self._alpha**2.+ks2**2.)**-1.5*(self._beta*nu.exp(-ks2*nu.fabs(z))-ks2*nu.exp(-self._beta*nu.fabs(z)))/(self._beta**2.-ks2**2.) - return nu.pi*self._alpha*(nu.sum(weights0*evalInt0) - -nu.sum(weights2*evalInt2)) + maxj0zeroIndx= numpy.argmin((self._j0zeros-kmax*R4max)**2.) #close enough + maxj2zeroIndx= numpy.argmin((self._j2zeros-kmax*R4max)**2.) #close enough + ks0= numpy.array([0.5*(self._glx+1.)*self._dj0zeros[ii+1] + self._j0zeros[ii] for ii in range(maxj0zeroIndx)]).flatten() + weights0= numpy.array([self._glw*self._dj0zeros[ii+1] for ii in range(maxj0zeroIndx)]).flatten() + ks2= numpy.array([0.5*(self._glx+1.)*self._dj2zeros[ii+1] + self._j2zeros[ii] for ii in range(maxj2zeroIndx)]).flatten() + weights2= numpy.array([self._glw*self._dj2zeros[ii+1] for ii in range(maxj2zeroIndx)]).flatten() + evalInt0= ks0**2.*special.jn(0,ks0*R)*(self._alpha**2.+ks0**2.)**-1.5*(self._beta*numpy.exp(-ks0*numpy.fabs(z))-ks0*numpy.exp(-self._beta*numpy.fabs(z)))/(self._beta**2.-ks0**2.) + evalInt2= ks2**2.*special.jn(2,ks2*R)*(self._alpha**2.+ks2**2.)**-1.5*(self._beta*numpy.exp(-ks2*numpy.fabs(z))-ks2*numpy.exp(-self._beta*numpy.fabs(z)))/(self._beta**2.-ks2**2.) + return numpy.pi*self._alpha*(numpy.sum(weights0*evalInt0) + -numpy.sum(weights2*evalInt2)) def _z2deriv(self,R,z,phi=0.,t=0.): """ @@ -276,19 +275,19 @@ 2012-12-26 - Written - Bovy (IAS) """ if True: - if isinstance(R,nu.ndarray): - if not isinstance(z,nu.ndarray): z= nu.ones_like(R)*z - out= nu.array([self._z2deriv(rr,zz) for rr,zz in zip(R,z)]) + if isinstance(R,numpy.ndarray): + if not isinstance(z,numpy.ndarray): z= numpy.ones_like(R)*z + out= numpy.array([self._z2deriv(rr,zz) for rr,zz in zip(R,z)]) return out if R > 16.*self._hr or R > 6.: return self._kp.z2deriv(R,z) if R < 1.: R4max= 1. else: R4max= R kmax= self._kmaxFac*self._beta - maxj0zeroIndx= nu.argmin((self._j0zeros-kmax*R4max)**2.) #close enough - ks= nu.array([0.5*(self._glx+1.)*self._dj0zeros[ii+1] + self._j0zeros[ii] for ii in range(maxj0zeroIndx)]).flatten() - weights= nu.array([self._glw*self._dj0zeros[ii+1] for ii in range(maxj0zeroIndx)]).flatten() - evalInt= ks*special.jn(0,ks*R)*(self._alpha**2.+ks**2.)**-1.5*(ks*nu.exp(-ks*nu.fabs(z))-self._beta*nu.exp(-self._beta*nu.fabs(z)))/(self._beta**2.-ks**2.) - return -2.*nu.pi*self._alpha*self._beta*nu.sum(weights*evalInt) + maxj0zeroIndx= numpy.argmin((self._j0zeros-kmax*R4max)**2.) #close enough + ks= numpy.array([0.5*(self._glx+1.)*self._dj0zeros[ii+1] + self._j0zeros[ii] for ii in range(maxj0zeroIndx)]).flatten() + weights= numpy.array([self._glw*self._dj0zeros[ii+1] for ii in range(maxj0zeroIndx)]).flatten() + evalInt= ks*special.jn(0,ks*R)*(self._alpha**2.+ks**2.)**-1.5*(ks*numpy.exp(-ks*numpy.fabs(z))-self._beta*numpy.exp(-self._beta*numpy.fabs(z)))/(self._beta**2.-ks**2.) + return -2.*numpy.pi*self._alpha*self._beta*numpy.sum(weights*evalInt) def _Rzderiv(self,R,z,phi=0.,t=0.): """ @@ -307,22 +306,22 @@ 2013-08-28 - Written - Bovy (IAS) """ if True: - if isinstance(R,nu.ndarray): - if not isinstance(z,nu.ndarray): z= nu.ones_like(R)*z - out= nu.array([self._Rzderiv(rr,zz) for rr,zz in zip(R,z)]) + if isinstance(R,numpy.ndarray): + if not isinstance(z,numpy.ndarray): z= numpy.ones_like(R)*z + out= numpy.array([self._Rzderiv(rr,zz) for rr,zz in zip(R,z)]) return out if R > 6.: return self._kp.Rzderiv(R,z) if R < 1.: R4max= 1. else: R4max= R kmax= 2.*self._kmaxFac*self._beta - maxj1zeroIndx= nu.argmin((self._j1zeros-kmax*R4max)**2.) #close enough - ks= nu.array([0.5*(self._glx+1.)*self._dj1zeros[ii+1] + self._j1zeros[ii] for ii in range(maxj1zeroIndx)]).flatten() - weights= nu.array([self._glw*self._dj1zeros[ii+1] for ii in range(maxj1zeroIndx)]).flatten() - evalInt= ks**2.*special.jn(1,ks*R)*(self._alpha**2.+ks**2.)**-1.5*(nu.exp(-ks*nu.fabs(z))-nu.exp(-self._beta*nu.fabs(z)))/(self._beta**2.-ks**2.) + maxj1zeroIndx= numpy.argmin((self._j1zeros-kmax*R4max)**2.) #close enough + ks= numpy.array([0.5*(self._glx+1.)*self._dj1zeros[ii+1] + self._j1zeros[ii] for ii in range(maxj1zeroIndx)]).flatten() + weights= numpy.array([self._glw*self._dj1zeros[ii+1] for ii in range(maxj1zeroIndx)]).flatten() + evalInt= ks**2.*special.jn(1,ks*R)*(self._alpha**2.+ks**2.)**-1.5*(numpy.exp(-ks*numpy.fabs(z))-numpy.exp(-self._beta*numpy.fabs(z)))/(self._beta**2.-ks**2.) if z >= 0.: - return -2.*nu.pi*self._alpha*self._beta*nu.sum(weights*evalInt) + return -2.*numpy.pi*self._alpha*self._beta*numpy.sum(weights*evalInt) else: - return 2.*nu.pi*self._alpha*self._beta*nu.sum(weights*evalInt) + return 2.*numpy.pi*self._alpha*self._beta*numpy.sum(weights*evalInt) def _dens(self,R,z,phi=0.,t=0.): """ @@ -340,7 +339,7 @@ HISTORY: 2010-08-08 - Written - Bovy (NYU) """ - return nu.exp(-self._alpha*R-self._beta*nu.fabs(z)) + return numpy.exp(-self._alpha*R-self._beta*numpy.fabs(z)) def _surfdens(self,R,z,phi=0.,t=0.): """ @@ -358,5 +357,5 @@ HISTORY: 2018-08-19 - Written - Bovy (UofT) """ - return 2.*nu.exp(-self._alpha*R)/self._beta\ - *(1.-nu.exp(-self._beta*nu.fabs(z))) + return 2.*numpy.exp(-self._alpha*R)/self._beta\ + *(1.-numpy.exp(-self._beta*numpy.fabs(z))) diff -Nru galpy-1.5/galpy/potential/EllipsoidalPotential.py galpy-1.6.0.post0/galpy/potential/EllipsoidalPotential.py --- galpy-1.5/galpy/potential/EllipsoidalPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/EllipsoidalPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -8,11 +8,11 @@ # with m^2 = x^2+y^2/b^2+z^2/c^2 # ############################################################################### -import numpy import hashlib +import numpy from scipy import integrate -from galpy.util import bovy_coords -from galpy.util import _rotate_to_arbitrary_vector +from ..util import bovy_coords +from ..util import _rotate_to_arbitrary_vector from .Potential import Potential, _APY_LOADED, \ check_potential_inputs_not_arrays if _APY_LOADED: diff -Nru galpy-1.5/galpy/potential/EllipticalDiskPotential.py galpy-1.6.0.post0/galpy/potential/EllipticalDiskPotential.py --- galpy-1.5/galpy/potential/EllipticalDiskPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/EllipticalDiskPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -2,12 +2,12 @@ # EllipticalDiskPotential: Kuijken & Tremaine (1994)'s elliptical disk # potential ############################################################################### -import math as m -from galpy.util import bovy_conversion +import numpy +from ..util import bovy_conversion from .planarPotential import planarPotential, _APY_LOADED if _APY_LOADED: from astropy import units -_degtorad= m.pi/180. +_degtorad= numpy.pi/180. class EllipticalDiskPotential(planarPotential): """Class that implements the Elliptical disk potential of Kuijken & Tremaine (1994) @@ -88,8 +88,8 @@ self._phib= phib self._twophio= twophio else: - self._twophio= m.sqrt(cp*cp+sp*sp) - self._phib= m.atan2(sp,cp)/2. + self._twophio= numpy.sqrt(cp*cp+sp*sp) + self._phib= numpy.arctan2(sp,cp)/2. self._p= p if not tform is None: self._tform= tform @@ -129,7 +129,7 @@ else: smooth= 1. return smooth*self._twophio/2.*R**self._p\ - *m.cos(2.*(phi-self._phib)) + *numpy.cos(2.*(phi-self._phib)) def _Rforce(self,R,phi=0.,t=0.): """ @@ -159,7 +159,7 @@ else: smooth= 1. return -smooth*self._p*self._twophio/2.*R**(self._p-1.)\ - *m.cos(2.*(phi-self._phib)) + *numpy.cos(2.*(phi-self._phib)) def _phiforce(self,R,phi=0.,t=0.): """ @@ -188,7 +188,7 @@ smooth= 1. else: smooth= 1. - return smooth*self._twophio*R**self._p*m.sin(2.*(phi-self._phib)) + return smooth*self._twophio*R**self._p*numpy.sin(2.*(phi-self._phib)) def _R2deriv(self,R,phi=0.,t=0.): #Calculate relevant time @@ -204,7 +204,7 @@ else: smooth= 1. return smooth*self._p*(self._p-1.)/2.*self._twophio*R**(self._p-2.)\ - *m.cos(2.*(phi-self._phib)) + *numpy.cos(2.*(phi-self._phib)) def _phi2deriv(self,R,phi=0.,t=0.): #Calculate relevant time @@ -219,7 +219,7 @@ smooth= 1. else: smooth= 1. - return -2.*smooth*self._twophio*R**self._p*m.cos(2.*(phi-self._phib)) + return -2.*smooth*self._twophio*R**self._p*numpy.cos(2.*(phi-self._phib)) def _Rphideriv(self,R,phi=0.,t=0.): #Calculate relevant time @@ -234,7 +234,7 @@ smooth= 1. else: smooth= 1. - return -smooth*self._p*self._twophio*R**(self._p-1.)*m.sin(2.*(phi-self._phib)) + return -smooth*self._p*self._twophio*R**(self._p-1.)*numpy.sin(2.*(phi-self._phib)) def tform(self): #pragma: no cover """ diff -Nru galpy-1.5/galpy/potential/FerrersPotential.py galpy-1.6.0.post0/galpy/potential/FerrersPotential.py --- galpy-1.5/galpy/potential/FerrersPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/FerrersPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -7,11 +7,11 @@ # # m^2 = x^2 + y^2/b^2 + z^2/c^2 ######################################################################## -import numpy as np import hashlib +import numpy from scipy import integrate from scipy.special import gamma -from galpy.util import bovy_conversion, bovy_coords +from ..util import bovy_conversion, bovy_coords from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units @@ -92,12 +92,12 @@ self._c2= self._c**2. self._force_hash= None self._pa = pa - self._rhoc_M = gamma(n+2.5)/gamma(n+1) / np.pi**1.5/a**3/b/c + self._rhoc_M = gamma(n+2.5)/gamma(n+1) / numpy.pi**1.5/a**3/b/c if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): #pragma: no cover self.normalize(normalize) - if np.fabs(self._b-1.) > 10.**-10.: + if numpy.fabs(self._b-1.) > 10.**-10.: self.isNonAxi= True return None @@ -118,14 +118,14 @@ if not self.isNonAxi: phi= 0. x,y,z= bovy_coords.cyl_to_rect(R,phi,z) - xy= np.dot(self.rot(t),np.array([x,y])) + xy= numpy.dot(self.rot(t),numpy.array([x,y])) x,y= xy[0],xy[1] return self._evaluate_xyz(x,y,z) def _evaluate_xyz(self,x,y,z=0.): """Evaluation of the potential as a function of (x,y,z) in the aligned coordinate frame""" - return -np.pi * self._rhoc_M /(self.n+1.)*self.a**3*self._b*self._c * \ + return -numpy.pi * self._rhoc_M /(self.n+1.)*self.a**3*self._b*self._c * \ _potInt(x, y, z, self._a2, self._b2*self._a2, self._c2*self._a2, self.n) def _Rforce(self,R,z,phi=0.,t=0.): @@ -145,7 +145,7 @@ if not self.isNonAxi: phi= 0. self._compute_xyzforces(R,z,phi,t) - return np.cos(phi)*self._cached_Fx+np.sin(phi)*self._cached_Fy + return numpy.cos(phi)*self._cached_Fx+numpy.sin(phi)*self._cached_Fy def _phiforce(self,R,z,phi=0.,t=0.): """ @@ -164,8 +164,8 @@ if not self.isNonAxi: phi= 0. self._compute_xyzforces(R,z,phi,t) - return R*(-np.sin(phi)*self._cached_Fx\ - +np.cos(phi)*self._cached_Fy) + return R*(-numpy.sin(phi)*self._cached_Fx\ + +numpy.cos(phi)*self._cached_Fy) def _zforce(self,R,z,phi=0.,t=0.): """ @@ -191,7 +191,7 @@ def _compute_xyzforces(self,R,z,phi,t): # Compute all rectangular forces - new_hash= hashlib.md5(np.array([R,phi,z,t])).hexdigest() + new_hash= hashlib.md5(numpy.array([R,phi,z,t])).hexdigest() if new_hash == self._force_hash: Fx= self._cached_Fx Fy= self._cached_Fy @@ -203,7 +203,7 @@ Fz= self._zforce_xyz(x,y,z) self._force_hash= new_hash tp= self._pa+self._omegab*t - cp, sp= np.cos(tp), np.sin(tp) + cp, sp= numpy.cos(tp), numpy.sin(tp) self._cached_Fx= cp*Fx-sp*Fy self._cached_Fy= sp*Fx+cp*Fy self._cached_Fz= Fz @@ -211,19 +211,19 @@ def _xforce_xyz(self,x,y,z): """Evaluation of the x force as a function of (x,y,z) in the aligned coordinate frame""" - return -2.*np.pi*self._rhoc_M * self.a**3*self._b*self._c * \ + return -2.*numpy.pi*self._rhoc_M * self.a**3*self._b*self._c * \ _forceInt(x, y, z, self._a2, self._b2*self._a2, self._c2*self._a2, self.n, 0) def _yforce_xyz(self,x,y,z): """Evaluation of the y force as a function of (x,y,z) in the aligned coordinate frame""" - return -2.*np.pi*self._rhoc_M * self.a**3*self._b*self._c * \ + return -2.*numpy.pi*self._rhoc_M * self.a**3*self._b*self._c * \ _forceInt(x, y, z, self._a2, self._b2*self._a2, self._c2*self._a2, self.n, 1) def _zforce_xyz(self,x,y,z): """Evaluation of the z force as a function of (x,y,z) in the aligned coordinate frame""" - return -2.*np.pi*self._rhoc_M * self.a**3*self._b*self._c * \ + return -2.*numpy.pi*self._rhoc_M * self.a**3*self._b*self._c * \ _forceInt(x, y, z, self._a2, self._b2*self._a2, self._c2*self._a2, self.n, 2) def _R2deriv(self,R,z,phi=0.,t=0.): @@ -247,12 +247,12 @@ phixya= self._2ndderiv_xyz(x,y,z,0,1) phiyya= self._2ndderiv_xyz(x,y,z,1,1) ang = self._omegab*t + self._pa - c, s = np.cos(ang), np.sin(ang) + c, s = numpy.cos(ang), numpy.sin(ang) phixx = c**2*phixxa + 2.*c*s*phixya + s**2*phiyya phixy = (c**2-s**2)*phixya + c*s*(phiyya - phixxa) phiyy = s**2*phixxa - 2.*c*s*phixya + c**2*phiyya - return np.cos(phi)**2.*phixx + np.sin(phi)**2.*phiyy + \ - 2.*np.cos(phi)*np.sin(phi)*phixy + return numpy.cos(phi)**2.*phixx + numpy.sin(phi)**2.*phiyy + \ + 2.*numpy.cos(phi)*numpy.sin(phi)*phixy def _Rzderiv(self,R,z,phi=0.,t=0.): """ @@ -274,10 +274,10 @@ phixza= self._2ndderiv_xyz(x,y,z,0,2) phiyza= self._2ndderiv_xyz(x,y,z,1,2) ang = self._omegab*t + self._pa - c, s = np.cos(ang), np.sin(ang) + c, s = numpy.cos(ang), numpy.sin(ang) phixz = c*phixza + s*phiyza phiyz = -s*phixza + c*phiyza - return np.cos(phi)*phixz + np.sin(phi)*phiyz + return numpy.cos(phi)*phixz + numpy.sin(phi)*phiyz def _z2deriv(self,R,z,phi=0.,t=0.): """ @@ -317,19 +317,19 @@ x,y,z= self._compute_xyz(R,phi,z,t) Fx= self._xforce_xyz(x,y,z) Fy= self._yforce_xyz(x,y,z) - Fxy= np.dot(self.rot(t, transposed = True),np.array([Fx,Fy])) + Fxy= numpy.dot(self.rot(t, transposed = True),numpy.array([Fx,Fy])) Fx, Fy= Fxy[0], Fxy[1] phixxa= self._2ndderiv_xyz(x,y,z,0,0) phixya= self._2ndderiv_xyz(x,y,z,0,1) phiyya= self._2ndderiv_xyz(x,y,z,1,1) ang = self._omegab*t + self._pa - c, s = np.cos(ang), np.sin(ang) + c, s = numpy.cos(ang), numpy.sin(ang) phixx = c**2*phixxa + 2.*c*s*phixya + s**2*phiyya phixy = (c**2-s**2)*phixya + c*s*(phiyya - phixxa) phiyy = s**2*phixxa - 2.*c*s*phixya + c**2*phiyya - return R**2.*(np.sin(phi)**2.*phixx+np.cos(phi)**2.*phiyy\ - -2.*np.cos(phi)*np.sin(phi)*phixy)\ - +R*(np.cos(phi)*Fx+np.sin(phi)*Fy) + return R**2.*(numpy.sin(phi)**2.*phixx+numpy.cos(phi)**2.*phiyy\ + -2.*numpy.cos(phi)*numpy.sin(phi)*phixy)\ + +R*(numpy.cos(phi)*Fx+numpy.sin(phi)*Fy) def _Rphideriv(self,R,z,phi=0.,t=0.): """ @@ -350,24 +350,24 @@ x,y,z= self._compute_xyz(R,phi,z,t) Fx= self._xforce_xyz(x,y,z) Fy= self._yforce_xyz(x,y,z) - Fxy= np.dot(self.rot(t, transposed = True),np.array([Fx,Fy])) + Fxy= numpy.dot(self.rot(t, transposed = True),numpy.array([Fx,Fy])) Fx, Fy= Fxy[0], Fxy[1] phixxa= self._2ndderiv_xyz(x,y,z,0,0) phixya= self._2ndderiv_xyz(x,y,z,0,1) phiyya= self._2ndderiv_xyz(x,y,z,1,1) ang = self._omegab*t + self._pa - c, s = np.cos(ang), np.sin(ang) + c, s = numpy.cos(ang), numpy.sin(ang) phixx = c**2*phixxa + 2.*c*s*phixya + s**2*phiyya phixy = (c**2-s**2)*phixya + c*s*(phiyya - phixxa) phiyy = s**2*phixxa - 2.*c*s*phixya + c**2*phiyya - return R*np.cos(phi)*np.sin(phi)*\ - (phiyy-phixx)+R*np.cos(2.*(phi))*phixy\ - +np.sin(phi)*Fx-np.cos(phi)*Fy + return R*numpy.cos(phi)*numpy.sin(phi)*\ + (phiyy-phixx)+R*numpy.cos(2.*(phi))*phixy\ + +numpy.sin(phi)*Fx-numpy.cos(phi)*Fy def _2ndderiv_xyz(self,x,y,z,i,j): """General 2nd derivative of the potential as a function of (x,y,z) in the aligned coordinate frame, d^2\Phi/dx_i/dx_j""" - return -np.pi*self._rhoc_M*self.a**3*self._b*self._c *\ + return -numpy.pi*self._rhoc_M*self.a**3*self._b*self._c *\ _2ndDerivInt(x,y,z,self._a2,self._b2*self._a2,self._c2*self._a2,self.n,i,j) def _dens(self,R,z,phi=0.,t=0.): @@ -408,9 +408,9 @@ """2D Rotation matrix for non-zero pa or pattern speed to goto the aligned coordinates """ - rotmat = np.array( - [[np.cos(self._pa+self._omegab*t),np.sin(self._pa+self._omegab*t)], - [-np.sin(self._pa+self._omegab*t),np.cos(self._pa+self._omegab*t)]]) + rotmat = numpy.array( + [[numpy.cos(self._pa+self._omegab*t),numpy.sin(self._pa+self._omegab*t)], + [-numpy.sin(self._pa+self._omegab*t),numpy.cos(self._pa+self._omegab*t)]]) if transposed: return rotmat.T else: @@ -425,7 +425,7 @@ """ def integrand(tau): return _FracInt(x, y, z, a2, b2, c2, tau, n+1) - return integrate.quad(integrand, lowerlim(x**2,y**2,z**2,a2,b2,c2), np.inf)[0] + return integrate.quad(integrand, lowerlim(x**2,y**2,z**2,a2,b2,c2), numpy.inf)[0] def _forceInt(x,y,z,a2,b2,c2,n,i): """Integral involved in the force at (x,y,z) @@ -437,7 +437,7 @@ def integrand(tau): return (x*(i==0) + y*(i==1) + z*(i==2))/(a2*(i==0) + b2*(i==1) + c2*(i==2) + tau) * \ _FracInt(x, y, z, a2, b2, c2, tau, n) - return integrate.quad(integrand, lowerlim(x**2, y**2, z**2, a2, b2, c2), np.inf, epsabs=1e-12)[0] + return integrate.quad(integrand, lowerlim(x**2, y**2, z**2, a2, b2, c2), numpy.inf, epsabs=1e-12)[0] def _2ndDerivInt(x,y,z,a2,b2,c2,n,i,j): """Integral involved in second derivatives d^\Phi/(dx_i dx_j) @@ -462,7 +462,7 @@ coef2 = a2*(i==0) + b2*(i==1) + c2*(i==2) return _FracInt(x,y,z,a2,b2,c2,tau,n-1)*n*(4.*var2)/(tau+coef2)**2 +\ _FracInt(x,y,z,a2,b2,c2,tau,n)*(-2./(tau+coef2)) - return integrate.quad(integrand, lowerlim(x**2,y**2,z**2,a2,b2,c2), np.inf)[0] + return integrate.quad(integrand, lowerlim(x**2,y**2,z**2,a2,b2,c2), numpy.inf)[0] def _FracInt(x,y,z,a,b,c,tau,n): """Returns @@ -470,7 +470,7 @@ -------------------------- (1 - ------- - ------- - -------)^n sqrt(tau+a)(tau+b)(tau+c)) tau+a tau+b tau+c """ - denom = np.sqrt((a + tau)*(b + tau)*(c + tau)) + denom = numpy.sqrt((a + tau)*(b + tau)*(c + tau)) return (1. - x**2/(a + tau) - y**2/(b + tau) - z**2/(c + tau))**n / denom def lowerlim(x, y, z, a, b, c): @@ -482,8 +482,8 @@ B = a + b + c - x - y - z C = a*b + a*c + b*c - a*y - a*z - b*x - b*z - c*x - c*y D = a*b*c - a*b*z - a*c*y - b*c*x - r = np.roots([1,B,C,D]) - ll = r[~np.iscomplex(r) & (r>0.)] + r = numpy.roots([1,B,C,D]) + ll = r[~numpy.iscomplex(r) & (r>0.)] return ll[0].real else: return 0. diff -Nru galpy-1.5/galpy/potential/FlattenedPowerPotential.py galpy-1.6.0.post0/galpy/potential/FlattenedPowerPotential.py --- galpy-1.5/galpy/potential/FlattenedPowerPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/FlattenedPowerPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -6,8 +6,7 @@ # phi(R,z)= --------- ; m^2 = R^2 + z^2/q^2 # m^\alpha ############################################################################### -import numpy as nu -from scipy import special, integrate +import numpy from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units @@ -76,6 +75,7 @@ self.normalize(normalize) self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True def _evaluate(self,R,z,phi=0.,t=0.): """ @@ -94,7 +94,7 @@ 2013-01-09 - Started - Bovy (IAS) """ if self.alpha == 0.: - return 1./2.*nu.log(R**2.+z**2./self.q2+self.core2) + return 1./2.*numpy.log(R**2.+z**2./self.q2+self.core2) else: m2= self.core2+R**2.+z**2./self.q2 return -m2**(-self.alpha/2.)/self.alpha @@ -206,9 +206,9 @@ 2013-01-09 - Written - Bovy (IAS) """ if self.alpha == 0.: - return 1./4./nu.pi/self.q2*((2.*self.q2+1.)*self.core2+R**2.\ + return 1./4./numpy.pi/self.q2*((2.*self.q2+1.)*self.core2+R**2.\ +(2.-1./self.q2)*z**2.)/\ (R**2.+z**2./self.q2+self.core2)**2. else: m2= self.core2+R**2.+z**2./self.q2 - return 1./self.q2*(self.core2*(1.+2.*self.q2)+R**2.*(1.-self.alpha*self.q2)+z**2.*(2.-(1.+self.alpha)/self.q2))*m2**(-self.alpha/2.-2.)/4./nu.pi + return 1./self.q2*(self.core2*(1.+2.*self.q2)+R**2.*(1.-self.alpha*self.q2)+z**2.*(2.-(1.+self.alpha)/self.q2))*m2**(-self.alpha/2.-2.)/4./numpy.pi diff -Nru galpy-1.5/galpy/potential/Force.py galpy-1.6.0.post0/galpy/potential/Force.py --- galpy-1.5/galpy/potential/Force.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/Force.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,10 +5,10 @@ ############################################################################### import copy import numpy -from galpy.util import config -from galpy.util import bovy_conversion -from galpy.util.bovy_conversion import physical_conversion, \ - potential_physical_input +from ..util import config +from ..util import bovy_conversion +from ..util.bovy_conversion import physical_conversion, \ + potential_physical_input, physical_compatible _APY_LOADED= True try: from astropy import units @@ -201,17 +201,33 @@ 2019-01-27 - Written - Bovy (UofT) + 2020-04-22 - Added check that unit systems of combined potentials are compatible - Bovy (UofT) + """ + from ..potential import flatten as flatten_pot + from ..potential import planarPotential + if not isinstance(flatten_pot([b])[0],(Force,planarPotential)): + raise TypeError("""Can only combine galpy Force objects with """ + """other Force objects or lists thereof""") + assert physical_compatible(self,b), \ + """Physical unit conversion parameters (ro,vo) are not """\ + """compatible between potentials to be combined""" if isinstance(b,list): return [self]+b else: return [self,b] # Define separately to keep order def __radd__(self,b): - if isinstance(b,list): - return b+[self] - else: - raise TypeError("Can only add a Force or Potential instance to another instance or to a list of such instances") + from ..potential import flatten as flatten_pot + from ..potential import planarPotential + if not isinstance(flatten_pot([b])[0],(Force,planarPotential)): + raise TypeError("""Can only combine galpy Force objects with """ + """other Force objects or lists thereof""") + assert physical_compatible(self,b), \ + """Physical unit conversion parameters (ro,vo) are not """\ + """compatible between potentials to be combined""" + # If we get here, b has to be a list + return b+[self] def turn_physical_off(self): """ @@ -264,15 +280,16 @@ 2016-01-30 - Written - Bovy (UofT) - """ + 2020-04-22 - Don't turn on a parameter when it is False - Bovy (UofT) - self._roSet= True - self._voSet= True - if not ro is None: + """ + if not ro is False: self._roSet= True + if not vo is False: self._voSet= True + if not ro is None and ro: if _APY_LOADED and isinstance(ro,units.Quantity): ro= ro.to(units.kpc).value self._ro= ro - if not vo is None: + if not vo is None and vo: if _APY_LOADED and isinstance(vo,units.Quantity): vo= vo.to(units.km/units.s).value self._vo= vo diff -Nru galpy-1.5/galpy/potential/GaussianAmplitudeWrapperPotential.py galpy-1.6.0.post0/galpy/potential/GaussianAmplitudeWrapperPotential.py --- galpy-1.5/galpy/potential/GaussianAmplitudeWrapperPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/GaussianAmplitudeWrapperPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,7 +5,7 @@ import numpy from .WrapperPotential import parentWrapperPotential from .Potential import _APY_LOADED -from galpy.util import bovy_conversion +from ..util import bovy_conversion if _APY_LOADED: from astropy import units class GaussianAmplitudeWrapperPotential(parentWrapperPotential): diff -Nru galpy-1.5/galpy/potential/HomogeneousSpherePotential.py galpy-1.6.0.post0/galpy/potential/HomogeneousSpherePotential.py --- galpy-1.5/galpy/potential/HomogeneousSpherePotential.py 1970-01-01 00:00:00.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/HomogeneousSpherePotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -0,0 +1,216 @@ +############################################################################### +# HomogeneousSpherePotential.py: The potential of a homogeneous sphere +############################################################################### +import numpy +from .Potential import Potential, _APY_LOADED +if _APY_LOADED: + from astropy import units +class HomogeneousSpherePotential(Potential): + """Class that implements the homogeneous sphere potential for :math:`\\rho(r) = \\rho_0 = \\mathrm{constant}` for all :math:`r < R` and zero otherwise. The potential is given by + + .. math:: + + \\Phi(r) = \\mathrm{amp}\\times\\left\\{\\begin{array}{lr} + (r^2-3R^2), & \\text{for } r < R\\\\ + -\\frac{2R^3}{r} & \\text{for } r \\geq R + \\end{array}\\right. + + We have that :math:`\\rho_0 = 3\\,\\mathrm{amp}/[2\\pi G]`. + """ + def __init__(self,amp=1.,R=1.1,normalize=False, + ro=None,vo=None): + """ + NAME: + + __init__ + + PURPOSE: + + initialize a homogeneous sphere potential + + INPUT: + + amp= amplitude to be applied to the potential (default: 1); can be a Quantity with units of mass density or Gxmass density + + R= size of the sphere (can be Quantity) + + normalize= if True, normalize such that vc(1.,0.)=1., or, if given as a number, such that the force is this fraction of the force necessary to make vc(1.,0.)=1. + + ro=, vo= distance and velocity scales for translation into internal units (default from configuration file) + + OUTPUT: + + (none) + + HISTORY: + + 2019-12-20 - Written - Bovy (UofT) + + """ + Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='density') + if _APY_LOADED and isinstance(R,units.Quantity): + R= R.to(units.kpc).value/self._ro + self.R= R + self._R2= self.R**2. + self._R3= self.R**3. + if normalize or \ + (isinstance(normalize,(int,float)) \ + and not isinstance(normalize,bool)): #pragma: no cover + self.normalize(normalize) + self.hasC= True + self.hasC_dxdv= True + self.hasC_dens= True + + def _evaluate(self,R,z,phi=0.,t=0.): + """ + NAME: + _evaluate + PURPOSE: + evaluate the potential at R,z + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + Phi(R,z) + HISTORY: + 2019-12-20 - Written - Bovy (UofT) + """ + r2= R**2.+z**2. + if r2 < self._R2: + return r2-3.*self._R2 + else: + return -2.*self._R3/numpy.sqrt(r2) + + def _Rforce(self,R,z,phi=0.,t=0.): + """ + NAME: + _Rforce + PURPOSE: + evaluate the radial force for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + the radial force + HISTORY: + 2019-12-20 - Written - Bovy (UofT) + """ + r2= R**2.+z**2. + if r2 < self._R2: + return -2.*R + else: + return -2.*self._R3*R/r2**1.5 + + def _zforce(self,R,z,phi=0.,t=0.): + """ + NAME: + _zforce + PURPOSE: + evaluate the vertical force for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + the vertical force + HISTORY: + 2019-12-20 - Written - Bovy (UofT) + """ + r2= R**2.+z**2. + if r2 < self._R2: + return -2.*z + else: + return -2.*self._R3*z/r2**1.5 + + def _R2deriv(self,R,z,phi=0.,t=0.): + """ + NAME: + _Rderiv + PURPOSE: + evaluate the second radial derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + the second radial derivative + HISTORY: + 2019-12-20 - Written - Bovy (UofT) + """ + r2= R**2.+z**2. + if r2 < self._R2: + return 2. + else: + return 2.*self._R3/r2**1.5-6.*self._R3*R**2./r2**2.5 + + def _z2deriv(self,R,z,phi=0.,t=0.): + """ + NAME: + _z2deriv + PURPOSE: + evaluate the second vertical derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t- time + OUTPUT: + the second vertical derivative + HISTORY: + 2019-12-20 - Written - Bovy (UofT) + """ + r2= R**2.+z**2. + if r2 < self._R2: + return 2. + else: + return 2.*self._R3/r2**1.5-6.*self._R3*z**2./r2**2.5 + + def _Rzderiv(self,R,z,phi=0.,t=0.): + """ + NAME: + _Rzderiv + PURPOSE: + evaluate the mixed R,z derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t- time + OUTPUT: + d2phi/dR/dz + HISTORY: + 2019-12-20 - Written - Bovy (UofT) + """ + r2= R**2.+z**2. + if r2 < self._R2: + return 0. + else: + return -6.*self._R3*R*z/r2**2.5 + + def _dens(self,R,z,phi=0.,t=0.): + """ + NAME: + _dens + PURPOSE: + evaluate the density for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + the density + HISTORY: + 2019-12-20 - Written - Bovy (UofT) + """ + r2= R**2.+z**2. + if r2 < self._R2: + return 1.5/numpy.pi + else: + return 0. diff -Nru galpy-1.5/galpy/potential/__init__.py galpy-1.6.0.post0/galpy/potential/__init__.py --- galpy-1.5/galpy/potential/__init__.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/__init__.py 2020-04-24 19:48:38.000000000 +0000 @@ -47,6 +47,7 @@ from . import PerfectEllipsoidPotential from . import IsothermalDiskPotential from . import NumericalPotentialDerivativesMixin +from . import HomogeneousSpherePotential # # Functions # @@ -121,6 +122,8 @@ KeplerPotential= PowerSphericalPotential.KeplerPotential PowerSphericalPotential= PowerSphericalPotential.PowerSphericalPotential PowerSphericalPotentialwCutoff= PowerSphericalPotentialwCutoff.PowerSphericalPotentialwCutoff +DehnenSphericalPotential= TwoPowerSphericalPotential.DehnenSphericalPotential +DehnenCoreSphericalPotential= TwoPowerSphericalPotential.DehnenCoreSphericalPotential NFWPotential= TwoPowerSphericalPotential.NFWPotential JaffePotential= TwoPowerSphericalPotential.JaffePotential HernquistPotential= TwoPowerSphericalPotential.HernquistPotential @@ -160,6 +163,7 @@ PerfectEllipsoidPotential= PerfectEllipsoidPotential.PerfectEllipsoidPotential IsothermalDiskPotential= IsothermalDiskPotential.IsothermalDiskPotential NumericalPotentialDerivativesMixin= NumericalPotentialDerivativesMixin.NumericalPotentialDerivativesMixin +HomogeneousSpherePotential= HomogeneousSpherePotential.HomogeneousSpherePotential #Wrappers DehnenSmoothWrapperPotential= DehnenSmoothWrapperPotential.DehnenSmoothWrapperPotential SolidBodyRotationWrapperPotential= SolidBodyRotationWrapperPotential.SolidBodyRotationWrapperPotential diff -Nru galpy-1.5/galpy/potential/interppotential_c_ext/interppotential_calc_potential.c galpy-1.6.0.post0/galpy/potential/interppotential_c_ext/interppotential_calc_potential.c --- galpy-1.5/galpy/potential/interppotential_c_ext/interppotential_calc_potential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/interppotential_c_ext/interppotential_calc_potential.c 2020-04-24 19:48:38.000000000 +0000 @@ -18,16 +18,6 @@ #include #include #include -#ifdef _WIN32 -// On Windows, *need* to define this function to allow the package to be imported -#if PY_MAJOR_VERSION >= 3 -PyMODINIT_FUNC PyInit_galpy_interppotential_c(void) { // Python 3 - return NULL; -} -#else -PyMODINIT_FUNC initgalpy_interppotential_c(void) {} // Python 2 -#endif -#endif //Macros to export functions in DLL on different OS #if defined(_WIN32) #define EXPORT __declspec(dllexport) diff -Nru galpy-1.5/galpy/potential/interpRZPotential.py galpy-1.6.0.post0/galpy/potential/interpRZPotential.py --- galpy-1.5/galpy/potential/interpRZPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/interpRZPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,45 +1,17 @@ -import os -import sys -import distutils.sysconfig as sysconfig import copy import ctypes import ctypes.util -import warnings from functools import wraps import numpy from numpy.ctypeslib import ndpointer from scipy import interpolate -from galpy.util import multi, galpyWarning +from ..util import multi from .Potential import Potential -from galpy.util.bovy_conversion import physical_conversion +from ..util.bovy_conversion import physical_conversion +from ..util import _load_extension_libs _DEBUG= False -#Find and load the library -_lib= None -outerr= None -PY3= sys.version > '3' -if PY3: - _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') -else: #pragma: no cover - _ext_suffix= '.so' -for path in sys.path: - try: - _lib = ctypes.CDLL(os.path.join(path,'galpy_interppotential_c%s' % _ext_suffix)) - except OSError as e: - if os.path.exists(os.path.join(path,'galpy_interppotential_c%s' % _ext_suffix)): #pragma: no cover - outerr= e - _lib = None - else: - break -if _lib is None: #pragma: no cover - if not outerr is None: - warnings.warn("interppotential_c extension module not loaded, because of error '%s' " % outerr, - galpyWarning) - else: - warnings.warn("interppotential_c extension module not loaded, because galpy_interppotential_c%s image was not found" % _ext_suffix, - galpyWarning) - ext_loaded= False -else: - ext_loaded= True + +_lib, ext_loaded= _load_extension_libs.load_libgalpy() def scalarVectorDecorator(func): """Decorator to return scalar outputs as a set""" @@ -154,7 +126,7 @@ """ if isinstance(RZPot,interpRZPotential): - from galpy.potential import PotentialError + from ..potential import PotentialError raise PotentialError('Cannot setup interpRZPotential with another interpRZPotential') # Propagate ro and vo roSet= True @@ -199,7 +171,7 @@ if use_c*ext_loaded: self._potGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid) else: - from galpy.potential import evaluatePotentials + from ..potential import evaluatePotentials potGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): @@ -221,7 +193,7 @@ if use_c*ext_loaded: self._rforceGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid,rforce=True) else: - from galpy.potential import evaluateRforces + from ..potential import evaluateRforces rforceGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): @@ -243,7 +215,7 @@ if use_c*ext_loaded: self._zforceGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid,zforce=True) else: - from galpy.potential import evaluatezforces + from ..potential import evaluatezforces zforceGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): @@ -262,7 +234,7 @@ if enable_c*ext_loaded: self._zforceGrid_splinecoeffs= calc_2dsplinecoeffs_c(self._zforceGrid) if interpDens: - from galpy.potential import evaluateDensities + from ..potential import evaluateDensities densGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): @@ -279,7 +251,7 @@ numpy.log(self._densGrid+10.**-10.), kx=3,ky=3,s=0.) if interpvcirc: - from galpy.potential import vcirc + from ..potential import vcirc if not numcores is None: self._vcircGrid= multi.parallel_map((lambda x: vcirc(self._origPot,self._rgrid[x])), list(range(len(self._rgrid))),numcores=numcores) @@ -290,7 +262,7 @@ else: self._vcircInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid,self._vcircGrid,k=3) if interpdvcircdr: - from galpy.potential import dvcircdR + from ..potential import dvcircdR if not numcores is None: self._dvcircdrGrid= multi.parallel_map((lambda x: dvcircdR(self._origPot,self._rgrid[x])), list(range(len(self._rgrid))),numcores=numcores) @@ -301,7 +273,7 @@ else: self._dvcircdrInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid,self._dvcircdrGrid,k=3) if interpepifreq: - from galpy.potential import epifreq + from ..potential import epifreq if not numcores is None: self._epifreqGrid= numpy.array(multi.parallel_map((lambda x: epifreq(self._origPot,self._rgrid[x])), list(range(len(self._rgrid))),numcores=numcores)) @@ -319,7 +291,7 @@ else: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid[indx],self._epifreqGrid[indx],k=3) if interpverticalfreq: - from galpy.potential import verticalfreq + from ..potential import verticalfreq if not numcores is None: self._verticalfreqGrid= multi.parallel_map((lambda x: verticalfreq(self._origPot,self._rgrid[x])), list(range(len(self._rgrid))),numcores=numcores) @@ -334,7 +306,7 @@ @scalarVectorDecorator @zsymDecorator(False) def _evaluate(self,R,z,phi=0.,t=0.): - from galpy.potential import evaluatePotentials + from ..potential import evaluatePotentials if self._interpPot: out= numpy.empty_like(R) indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1])\ @@ -358,7 +330,7 @@ @scalarVectorDecorator @zsymDecorator(False) def _Rforce(self,R,z,phi=0.,t=0.): - from galpy.potential import evaluateRforces + from ..potential import evaluateRforces if self._interpRforce: out= numpy.empty_like(R) indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1])\ @@ -382,7 +354,7 @@ @scalarVectorDecorator @zsymDecorator(True) def _zforce(self,R,z,phi=0.,t=0.): - from galpy.potential import evaluatezforces + from ..potential import evaluatezforces if self._interpzforce: out= numpy.empty_like(R) indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1])\ @@ -406,13 +378,13 @@ return evaluatezforces(self._origPot,R,z) def _Rzderiv(self,R,z,phi=0.,t=0.): - from galpy.potential import evaluateRzderivs + from ..potential import evaluateRzderivs return evaluateRzderivs(self._origPot,R,z) @scalarVectorDecorator @zsymDecorator(False) def _dens(self,R,z,phi=0.,t=0.): - from galpy.potential import evaluateDensities + from ..potential import evaluateDensities if self._interpDens: out= numpy.empty_like(R) indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1])\ @@ -433,7 +405,7 @@ @physical_conversion('velocity',pop=True) @scalarDecorator def vcirc(self,R): - from galpy.potential import vcirc + from ..potential import vcirc if self._interpvcirc: indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1]) out= numpy.empty_like(R) @@ -451,7 +423,7 @@ @physical_conversion('frequency',pop=True) @scalarDecorator def dvcircdR(self,R): - from galpy.potential import dvcircdR + from ..potential import dvcircdR if self._interpdvcircdr: indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1]) out= numpy.empty_like(R) @@ -469,7 +441,7 @@ @physical_conversion('frequency',pop=True) @scalarDecorator def epifreq(self,R): - from galpy.potential import epifreq + from ..potential import epifreq if self._interpepifreq: indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1]) out= numpy.empty_like(R) @@ -487,7 +459,7 @@ @physical_conversion('frequency',pop=True) @scalarDecorator def verticalfreq(self,R): - from galpy.potential import verticalfreq + from ..potential import verticalfreq if self._interpverticalfreq: indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1]) out= numpy.empty_like(R) @@ -519,7 +491,7 @@ 2013-01-24 - Written - Bovy (IAS) 2013-01-29 - Added forces - Bovy (IAS) """ - from galpy.orbit.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop + from ..orbit.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop #Parse the potential npot, pot_type, pot_args= _parse_pot(pot) @@ -613,7 +585,7 @@ HISTORY: 2013-01-24 - Written - Bovy (IAS) """ - from galpy.orbit.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop + from ..orbit.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop #Parse the potential npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) @@ -672,7 +644,7 @@ HISTORY: 2013-01-29 - Written - Bovy (IAS) """ - from galpy.orbit.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop + from ..orbit.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop #Parse the potential npot, pot_type, pot_args= _parse_pot(pot) diff -Nru galpy-1.5/galpy/potential/IsochronePotential.py galpy-1.6.0.post0/galpy/potential/IsochronePotential.py --- galpy-1.5/galpy/potential/IsochronePotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/IsochronePotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,7 +5,7 @@ # Phi(r)= --------------------- # b + sqrt{b^2+r^2} ############################################################################### -import numpy as nu +import numpy from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units @@ -31,7 +31,7 @@ INPUT: - amp= amplitude to be applied to the potential, the total mass (default: 1); can be a Quantity with units of mass density or Gxmass density + amp= amplitude to be applied to the potential, the total mass (default: 1); can be a Quantity with units of mass or Gxmass b= scale radius of the isochrone potential (can be Quantity) @@ -60,6 +60,7 @@ self.normalize(normalize) self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True def _evaluate(self,R,z,phi=0.,t=0.): """ @@ -78,7 +79,7 @@ 2013-09-08 - Written - Bovy (IAS) """ r2= R**2.+z**2. - rb= nu.sqrt(r2+self.b2) + rb= numpy.sqrt(r2+self.b2) return -1./(self.b+rb) def _Rforce(self,R,z,phi=0.,t=0.): @@ -98,7 +99,7 @@ 2013-09-08 - Written - Bovy (IAS) """ r2= R**2.+z**2. - rb= nu.sqrt(r2+self.b2) + rb= numpy.sqrt(r2+self.b2) dPhidrr= -1./rb/(self.b+rb)**2. return dPhidrr*R @@ -119,7 +120,7 @@ 2013-09-08 - Written - Bovy (IAS) """ r2= R**2.+z**2. - rb= nu.sqrt(r2+self.b2) + rb= numpy.sqrt(r2+self.b2) dPhidrr= -1./rb/(self.b+rb)**2. return dPhidrr*z @@ -140,7 +141,7 @@ 2013-09-08 - Written - Bovy (IAS) """ r2= R**2.+z**2. - rb= nu.sqrt(r2+self.b2) + rb= numpy.sqrt(r2+self.b2) return -(-self.b**3.-self.b*z**2.+(2.*R**2.-z**2.-self.b**2.)*rb)/\ rb**3./(self.b+rb)**3. @@ -161,7 +162,7 @@ 2013-09-08 - Written - Bovy (IAS) """ r2= R**2.+z**2. - rb= nu.sqrt(r2+self.b2) + rb= numpy.sqrt(r2+self.b2) return -(-self.b**3.-self.b*R**2.-(R**2.-2.*z**2.+self.b**2.)*rb)/\ rb**3./(self.b+rb)**3. @@ -182,7 +183,7 @@ 2013-09-08 - Written - Bovy (IAS) """ r2= R**2.+z**2. - rb= nu.sqrt(r2+self.b2) + rb= numpy.sqrt(r2+self.b2) return -R*z*(self.b+3.*rb)/\ rb**3./(self.b+rb)**3. @@ -203,9 +204,9 @@ 2013-09-08 - Written - Bovy (IAS) """ r2= R**2.+z**2. - rb= nu.sqrt(r2+self.b2) + rb= numpy.sqrt(r2+self.b2) return (3.*(self.b+rb)*rb**2.-r2*(self.b+3.*rb))/\ - rb**3./(self.b+rb)**3./4./nu.pi + rb**3./(self.b+rb)**3./4./numpy.pi def _surfdens(self,R,z,phi=0.,t=0.): """ @@ -224,8 +225,8 @@ 2018-08-19 - Written - Bovy (UofT) """ r2= R**2.+z**2. - rb= nu.sqrt(r2+self.b2) + rb= numpy.sqrt(r2+self.b2) return self.b*((R*z)/r2-(self.b*R*z*(self.b**2+2.*R**2+z**2)) /((self.b**2+R**2)*r2*rb) - +nu.arctan(z/R)-nu.arctan(self.b*z/R/rb))/R**3/2./nu.pi + +numpy.arctan(z/R)-numpy.arctan(self.b*z/R/rb))/R**3/2./numpy.pi diff -Nru galpy-1.5/galpy/potential/IsothermalDiskPotential.py galpy-1.6.0.post0/galpy/potential/IsothermalDiskPotential.py --- galpy-1.5/galpy/potential/IsothermalDiskPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/IsothermalDiskPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -46,6 +46,7 @@ sigma= sigma.to(units.km/units.s).value/self._vo self._sigma2= sigma**2. self._H= sigma/numpy.sqrt(8.*numpy.pi*self._amp) + self._amp= 1. # Need to manually set to 1, because amp is now contained in the combination of H and sigma^2 self.hasC= True def _evaluate(self,x,t=0.): diff -Nru galpy-1.5/galpy/potential/KGPotential.py galpy-1.6.0.post0/galpy/potential/KGPotential.py --- galpy-1.5/galpy/potential/KGPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/KGPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,5 +1,5 @@ -import scipy as sc -from galpy.util import bovy_conversion +import numpy +from ..util import bovy_conversion from .linearPotential import linearPotential, _APY_LOADED if _APY_LOADED: from astropy import units @@ -57,7 +57,7 @@ if _APY_LOADED and isinstance(F,units.Quantity): try: F= F.to(units.Msun/units.pc**3).value\ - /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)*4.*sc.pi + /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)*4.*numpy.pi except units.UnitConversionError: pass if _APY_LOADED and isinstance(F,units.Quantity): try: @@ -72,7 +72,7 @@ self.hasC= True def _evaluate(self,x,t=0.): - return self._K*(sc.sqrt(x**2.+self._D2)-self._D)+self._F*x**2. + return self._K*(numpy.sqrt(x**2.+self._D2)-self._D)+self._F*x**2. def _force(self,x,t=0.): - return -x*(self._K/sc.sqrt(x**2+self._D2)+2.*self._F) + return -x*(self._K/numpy.sqrt(x**2+self._D2)+2.*self._F) diff -Nru galpy-1.5/galpy/potential/KuzminDiskPotential.py galpy-1.6.0.post0/galpy/potential/KuzminDiskPotential.py --- galpy-1.5/galpy/potential/KuzminDiskPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/KuzminDiskPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,7 +5,7 @@ # Phi(R, z)= --------------------------- # \sqrt{R^2 + (a + |z|)^2} ############################################################################### -import numpy as nu +import numpy from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units @@ -111,7 +111,7 @@ HISTORY: 2016-05-09 - Written - Aladdin """ - return -nu.sign(z) * self._denom(R,z)**-1.5 * (self._a + nu.fabs(z)) + return -numpy.sign(z) * self._denom(R,z)**-1.5 * (self._a + numpy.fabs(z)) def _R2deriv(self,R,z,phi=0.,t=0.): """ @@ -148,7 +148,7 @@ 2016-05-13 - Written - Aladdin """ a = self._a - return self._denom(R, z)**-1.5 - 3. * (a + nu.fabs(z))**2. * self._denom(R, z)**-2.5 + return self._denom(R, z)**-1.5 - 3. * (a + numpy.fabs(z))**2. * self._denom(R, z)**-2.5 def _Rzderiv(self,R,z,phi=0.,t=0.): """ @@ -166,7 +166,7 @@ HISTORY: 2016-05-13 - Written - Aladdin """ - return -3 * nu.sign(z) * R * (self._a + nu.fabs(z)) *self._denom(R, z)**-2.5 + return -3 * numpy.sign(z) * R * (self._a + numpy.fabs(z)) *self._denom(R, z)**-2.5 def _surfdens(self,R,z,phi=0.,t=0.): """ @@ -184,7 +184,7 @@ HISTORY: 2018-08-19 - Written - Bovy (UofT) """ - return self._a*(R**2+self._a**2)**-1.5/2./nu.pi + return self._a*(R**2+self._a**2)**-1.5/2./numpy.pi def _denom(self, R, z): """ @@ -201,4 +201,4 @@ HISTORY: 2016-05-09 - Written - Aladdin """ - return (R**2. + (self._a + nu.fabs(z))**2.) + return (R**2. + (self._a + numpy.fabs(z))**2.) diff -Nru galpy-1.5/galpy/potential/KuzminKutuzovStaeckelPotential.py galpy-1.6.0.post0/galpy/potential/KuzminKutuzovStaeckelPotential.py --- galpy-1.5/galpy/potential/KuzminKutuzovStaeckelPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/KuzminKutuzovStaeckelPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -6,11 +6,11 @@ # Phi(r)= --------------------------- # \sqrt{lambda} + \sqrt{nu} ############################################################################### -import numpy as nu +import numpy from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units -from galpy.util import bovy_coords #for prolate spherical coordinate transforms +from ..util import bovy_coords #for prolate spherical coordinate transforms class KuzminKutuzovStaeckelPotential(Potential): """Class that implements the Kuzmin-Kutuzov Staeckel potential @@ -84,7 +84,7 @@ 2015-02-15 - Written - Trick (MPIA) """ l,n = bovy_coords.Rz_to_lambdanu(R,z,ac=self._ac,Delta=self._Delta) - return -1./(nu.sqrt(l) + nu.sqrt(n)) + return -1./(numpy.sqrt(l) + numpy.sqrt(n)) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -237,7 +237,7 @@ HISTORY: 2015-02-15 - Written - Trick (MPIA) """ - return 0.5/nu.sqrt(l)/(nu.sqrt(l)+nu.sqrt(n))**2 + return 0.5/numpy.sqrt(l)/(numpy.sqrt(l)+numpy.sqrt(n))**2 def _nderiv(self,l,n): """ @@ -253,7 +253,7 @@ HISTORY: 2015-02-15 - Written - Trick (MPIA) """ - return 0.5/nu.sqrt(n)/(nu.sqrt(l)+nu.sqrt(n))**2 + return 0.5/numpy.sqrt(n)/(numpy.sqrt(l)+numpy.sqrt(n))**2 def _l2deriv(self,l,n): """ @@ -269,8 +269,8 @@ HISTORY: 2015-02-15 - Written - Trick (MPIA) """ - numer = -3.*nu.sqrt(l) - nu.sqrt(n) - denom = 4. * l**1.5 * (nu.sqrt(l)+nu.sqrt(n))**3 + numer = -3.*numpy.sqrt(l) - numpy.sqrt(n) + denom = 4. * l**1.5 * (numpy.sqrt(l)+numpy.sqrt(n))**3 return numer / denom def _n2deriv(self,l,n): @@ -287,8 +287,8 @@ HISTORY: 2015-02-15 - Written - Trick (MPIA) """ - numer = -nu.sqrt(l) - 3.*nu.sqrt(n) - denom = 4. * n**1.5 * (nu.sqrt(l)+nu.sqrt(n))**3 + numer = -numpy.sqrt(l) - 3.*numpy.sqrt(n) + denom = 4. * n**1.5 * (numpy.sqrt(l)+numpy.sqrt(n))**3 return numer / denom def _lnderiv(self,l,n): @@ -305,5 +305,5 @@ HISTORY: 2015-02-13 - Written - Trick (MPIA) """ - return -0.5/(nu.sqrt(l) * nu.sqrt(n) * (nu.sqrt(l)+nu.sqrt(n))**3) + return -0.5/(numpy.sqrt(l) * numpy.sqrt(n) * (numpy.sqrt(l)+numpy.sqrt(n))**3) diff -Nru galpy-1.5/galpy/potential/linearPotential.py galpy-1.6.0.post0/galpy/potential/linearPotential.py --- galpy-1.5/galpy/potential/linearPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/linearPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -3,12 +3,12 @@ import os, os.path import copy import pickle -import numpy as nu -import galpy.util.bovy_plot as plot -from galpy.util import config +import numpy +from ..util import bovy_plot as plot +from ..util import config from .Potential import PotentialError, flatten -from galpy.util.bovy_conversion import physical_conversion,\ - potential_physical_input +from ..util.bovy_conversion import physical_conversion,\ + potential_physical_input, physical_compatible _APY_LOADED= True try: from astropy import units @@ -21,6 +21,8 @@ self.dim= 1 self.isRZ= False self.hasC= False + self.hasC_dxdv= False + self.hasC_dens= False # Parse ro and vo if ro is None: self._ro= config.__config__.getfloat('normalization','ro') @@ -96,16 +98,30 @@ 2019-01-27 - Written - Bovy (UofT) """ + from ..potential import flatten as flatten_pot + if not isinstance(flatten_pot([b])[0],linearPotential): + raise TypeError("""Can only combine galpy linearPotential""" + """ objects with """ + """other such objects or lists thereof""") + assert physical_compatible(self,b), \ + """Physical unit conversion parameters (ro,vo) are not """\ + """compatible between potentials to be combined""" if isinstance(b,list): return [self]+b else: return [self,b] # Define separately to keep order def __radd__(self,b): - if isinstance(b,list): - return b+[self] - else: - raise TypeError("Can only add a Force or Potential instance to another instance or to a list of such instances") + from ..potential import flatten as flatten_pot + if not isinstance(flatten_pot([b])[0],linearPotential): + raise TypeError("""Can only combine galpy linearPotential""" + """ objects with """ + """other such objects or lists thereof""") + assert physical_compatible(self,b), \ + """Physical unit conversion parameters (ro,vo) are not """\ + """compatible between potentials to be combined""" + # If we get here, b has to be a list + return b+[self] def turn_physical_off(self): """ @@ -158,14 +174,16 @@ 2016-01-30 - Written - Bovy (UofT) + 2020-04-22 - Don't turn on a parameter when it is False - Bovy (UofT) + """ - self._roSet= True - self._voSet= True - if not ro is None: + if not ro is False: self._roSet= True + if not vo is False: self._voSet= True + if not ro is None and ro: if _APY_LOADED and isinstance(ro,units.Quantity): ro= ro.to(units.kpc).value self._ro= ro - if not vo is None: + if not vo is None and vo: if _APY_LOADED and isinstance(vo,units.Quantity): vo= vo.to(units.km/units.s).value self._vo= vo @@ -279,8 +297,8 @@ xs= pickle.load(savefile) savefile.close() else: - xs= nu.linspace(min,max,ns) - potx= nu.zeros(ns) + xs= numpy.linspace(min,max,ns) + potx= numpy.zeros(ns) for ii in range(ns): potx[ii]= self._evaluate(xs[ii],t=t) if not savefilename == None: @@ -418,8 +436,8 @@ xs= pickle.load(savefile) savefile.close() else: - xs= nu.linspace(min,max,ns) - potx= nu.zeros(ns) + xs= numpy.linspace(min,max,ns) + potx= numpy.zeros(ns) for ii in range(ns): potx[ii]= evaluatelinearPotentials(Pot,xs[ii],t=t) if not savefilename == None: diff -Nru galpy-1.5/galpy/potential/LogarithmicHaloPotential.py galpy-1.6.0.post0/galpy/potential/LogarithmicHaloPotential.py --- galpy-1.5/galpy/potential/LogarithmicHaloPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/LogarithmicHaloPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -3,11 +3,11 @@ # potential Phi(r) = vc**2 ln(r) ############################################################################### import warnings -import numpy as nu +import numpy from .Potential import Potential, kms_to_kpcGyrDecorator, _APY_LOADED if _APY_LOADED: from astropy import units -from galpy.util import galpyWarning +from ..util import galpyWarning _CORE=10**-8 class LogarithmicHaloPotential(Potential): """Class that implements the logarithmic potential @@ -64,6 +64,7 @@ core= core.to(units.kpc).value/self._ro self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True self._core2= core**2. self._q= q self._b= b @@ -95,10 +96,10 @@ 2010-04-30 - Adapted for R,z - Bovy (NYU) """ if self.isNonAxi: - return 1./2.*nu.log(R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + return 1./2.*numpy.log(R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) +(z/self._q)**2.+self._core2) else: - return 1./2.*nu.log(R**2.+(z/self._q)**2.+self._core2) + return 1./2.*numpy.log(R**2.+(z/self._q)**2.+self._core2) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -116,7 +117,7 @@ HISTORY: """ if self.isNonAxi: - Rt2= R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) return -Rt2/R/(Rt2+(z/self._q)**2.+self._core2) else: return -R/(R**2.+(z/self._q)**2.+self._core2) @@ -137,7 +138,7 @@ HISTORY: """ if self.isNonAxi: - Rt2= R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) return -z/self._q**2./(Rt2+(z/self._q)**2.+self._core2) else: return -z/self._q**2./(R**2.+(z/self._q)**2.+self._core2) @@ -158,9 +159,9 @@ HISTORY: """ if self.isNonAxi: - Rt2= R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) return R**2./(Rt2+(z/self._q)**2.+self._core2)\ - *nu.sin(2.*phi)*self._1m1overb2/2. + *numpy.sin(2.*phi)*self._1m1overb2/2. else: return 0 @@ -181,17 +182,17 @@ """ if self.isNonAxi: R2= R**2. - Rt2= R2*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R2*(1.-self._1m1overb2*numpy.sin(phi)**2.) denom= 1./(Rt2+(z/self._q)**2.+self._core2) denom2= denom**2. - return 1./4./nu.pi\ + return 1./4./numpy.pi\ *(2.*Rt2/R2*(denom-Rt2*denom2)\ - +denom/self._q**2.-2.*z**2.*denom**2./self._q**4.\ + +denom/self._q**2.-2.*z**2.*denom2/self._q**4.\ -self._1m1overb2\ - *(2.*R2*nu.sin(2.*phi)**2./4.*self._1m1overb2\ - *denom**2.+denom*nu.cos(2.*phi))) + *(2.*R2*numpy.sin(2.*phi)**2./4.*self._1m1overb2\ + *denom2+denom*numpy.cos(2.*phi))) else: - return 1./4./nu.pi/self._q**2.*((2.*self._q**2.+1.)*self._core2+R**2.\ + return 1./4./numpy.pi/self._q**2.*((2.*self._q**2.+1.)*self._core2+R**2.\ +(2.-self._q**-2.)*z**2.)/\ (R**2.+(z/self._q)**2.+self._core2)**2. @@ -212,7 +213,7 @@ 2011-10-09 - Written - Bovy (IAS) """ if self.isNonAxi: - Rt2= R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) denom= 1./(Rt2+(z/self._q)**2.+self._core2) return (denom-2.*Rt2*denom**2.)*Rt2/R**2. else: @@ -236,7 +237,7 @@ 2012-07-25 - Written - Bovy (IAS@MPIA) """ if self.isNonAxi: - Rt2= R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) denom= 1./(Rt2+(z/self._q)**2.+self._core2) return denom/self._q**2.-2.*z**2.*denom**2./self._q**4. else: @@ -260,7 +261,7 @@ 2013-08-28 - Written - Bovy (IAS) """ if self.isNonAxi: - Rt2= R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) return -2.*Rt2/R*z/self._q**2./(Rt2+(z/self._q)**2.+self._core2)**2. else: return -2.*R*z/self._q**2./(R**2.+(z/self._q)**2.+self._core2)**2. @@ -282,12 +283,12 @@ 2017-10-15 - Written - Bovy (UofT) """ if self.isNonAxi: - Rt2= R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) denom= 1./(Rt2+(z/self._q)**2.+self._core2) return -self._1m1overb2\ - *(R**4.*nu.sin(2.*phi)**2./2.*self._1m1overb2\ + *(R**4.*numpy.sin(2.*phi)**2./2.*self._1m1overb2\ *denom**2. - +R**2.*denom*nu.cos(2.*phi)) + +R**2.*denom*numpy.cos(2.*phi)) else: return 0. @@ -308,9 +309,9 @@ 2017-10-15 - Written - Bovy (UofT) """ if self.isNonAxi: - Rt2= R**2.*(1.-self._1m1overb2*nu.sin(phi)**2.) + Rt2= R**2.*(1.-self._1m1overb2*numpy.sin(phi)**2.) denom= 1./(Rt2+(z/self._q)**2.+self._core2) - return -(denom-Rt2*denom**2.)*R*nu.sin(2.*phi)*self._1m1overb2 + return -(denom-Rt2*denom**2.)*R*numpy.sin(2.*phi)*self._1m1overb2 else: return 0. diff -Nru galpy-1.5/galpy/potential/McMillan17.py galpy-1.6.0.post0/galpy/potential/McMillan17.py --- galpy-1.5/galpy/potential/McMillan17.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/McMillan17.py 2020-04-24 19:48:38.000000000 +0000 @@ -55,8 +55,8 @@ #dicts used in DiskSCFPotential sigmadict = [{'type':'exp','h':Rd_HI,'amp':Sigma0_HI, 'Rhole':Rm_HI}, {'type':'exp','h':Rd_H2,'amp':Sigma0_H2, 'Rhole':Rm_H2}, - {'type':'exp','h':Rd_thin,'amp':Sigma0_thin, 'Rhole':0.}, - {'type':'exp','h':Rd_thick,'amp':Sigma0_thick, 'Rhole':0.}] + {'type':'exp','h':Rd_thin,'amp':Sigma0_thin}, + {'type':'exp','h':Rd_thick,'amp':Sigma0_thick}] hzdict = [{'type':'sech2', 'h':zd_HI}, {'type':'sech2', 'h':zd_H2}, diff -Nru galpy-1.5/galpy/potential/MiyamotoNagaiPotential.py galpy-1.6.0.post0/galpy/potential/MiyamotoNagaiPotential.py --- galpy-1.5/galpy/potential/MiyamotoNagaiPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/MiyamotoNagaiPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,7 +5,7 @@ # phi(R,z) = - --------------------------------- # \sqrt(R^2+(a+\sqrt(z^2+b^2))^2) ############################################################################### -import numpy as nu +import numpy from .Potential import Potential, kms_to_kpcGyrDecorator, _APY_LOADED if _APY_LOADED: from astropy import units @@ -65,6 +65,7 @@ self.normalize(normalize) self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True self._nemo_accname= 'MiyamotoNagai' def _evaluate(self,R,z,phi=0.,t=0.): @@ -83,7 +84,7 @@ HISTORY: 2010-07-09 - Started - Bovy (NYU) """ - return -1./nu.sqrt(R**2.+(self._a+nu.sqrt(z**2.+self._b2))**2.) + return -1./numpy.sqrt(R**2.+(self._a+numpy.sqrt(z**2.+self._b2))**2.) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -101,7 +102,7 @@ HISTORY: 2010-07-09 - Written - Bovy (NYU) """ - return -R/(R**2.+(self._a+nu.sqrt(z**2.+self._b2))**2.)**(3./2.) + return -R/(R**2.+(self._a+numpy.sqrt(z**2.+self._b2))**2.)**(3./2.) def _zforce(self,R,z,phi=0.,t=0.): """ @@ -119,14 +120,14 @@ HISTORY: 2010-07-09 - Written - Bovy (NYU) """ - sqrtbz= nu.sqrt(self._b2+z**2.) + sqrtbz= numpy.sqrt(self._b2+z**2.) asqrtbz= self._a+sqrtbz if isinstance(R,float) and sqrtbz == asqrtbz: return (-z/ - (R**2.+(self._a+nu.sqrt(z**2.+self._b2))**2.)**(3./2.)) + (R**2.+(self._a+numpy.sqrt(z**2.+self._b2))**2.)**(3./2.)) else: return (-z*asqrtbz/sqrtbz/ - (R**2.+(self._a+nu.sqrt(z**2.+self._b2))**2.)**(3./2.)) + (R**2.+(self._a+numpy.sqrt(z**2.+self._b2))**2.)**(3./2.)) def _dens(self,R,z,phi=0.,t=0.): """ @@ -144,14 +145,14 @@ HISTORY: 2010-08-08 - Written - Bovy (NYU) """ - sqrtbz= nu.sqrt(self._b2+z**2.) + sqrtbz= numpy.sqrt(self._b2+z**2.) asqrtbz= self._a+sqrtbz if isinstance(R,float) and sqrtbz == asqrtbz: return 3./\ - (R**2.+sqrtbz**2.)**2.5/4./nu.pi*self._b2 + (R**2.+sqrtbz**2.)**2.5/4./numpy.pi*self._b2 else: return (self._a*R**2.+(self._a+3.*sqrtbz)*asqrtbz**2.)/\ - (R**2.+asqrtbz**2.)**2.5/sqrtbz**3./4./nu.pi*self._b2 + (R**2.+asqrtbz**2.)**2.5/sqrtbz**3./4./numpy.pi*self._b2 def _R2deriv(self,R,z,phi=0.,t=0.): """ @@ -169,8 +170,8 @@ HISTORY: 2011-10-09 - Written - Bovy (IAS) """ - return 1./(R**2.+(self._a+nu.sqrt(z**2.+self._b2))**2.)**1.5 \ - -3.*R**2./(R**2.+(self._a+nu.sqrt(z**2.+self._b2))**2.)**2.5 + return 1./(R**2.+(self._a+numpy.sqrt(z**2.+self._b2))**2.)**1.5 \ + -3.*R**2./(R**2.+(self._a+numpy.sqrt(z**2.+self._b2))**2.)**2.5 def _z2deriv(self,R,z,phi=0.,t=0.): """ @@ -188,14 +189,14 @@ HISTORY: 2012-07-25 - Written - Bovy (IAS@MPIA) """ - sqrtbz= nu.sqrt(self._b2+z**2.) + sqrtbz= numpy.sqrt(self._b2+z**2.) asqrtbz= self._a+sqrtbz if isinstance(R,float) and sqrtbz == asqrtbz: return (self._b2+R**2.-2.*z**2.)*(self._b2+R**2.+z**2.)**-2.5 else: return ((self._a**3.*self._b2 + self._a**2.*(3.*self._b2 - 2.* z**2.) - *nu.sqrt(self._b2 + z**2.) + *numpy.sqrt(self._b2 + z**2.) + (self._b2 + R**2. - 2.*z**2.)*(self._b2 + z**2.)**1.5 +self._a* (3.*self._b2**2. - 4.*z**4. + self._b2*(R**2. - z**2.)))/ ((self._b2 + z**2.)**1.5* (R**2. + asqrtbz**2.)**2.5)) @@ -216,7 +217,7 @@ HISTORY: 2013-08-28 - Written - Bovy (IAS) """ - sqrtbz= nu.sqrt(self._b2+z**2.) + sqrtbz= numpy.sqrt(self._b2+z**2.) asqrtbz= self._a+sqrtbz if isinstance(R,float) and sqrtbz == asqrtbz: return -(3.*R*z/(R**2.+asqrtbz**2.)**2.5) diff -Nru galpy-1.5/galpy/potential/MN3ExponentialDiskPotential.py galpy-1.6.0.post0/galpy/potential/MN3ExponentialDiskPotential.py --- galpy-1.5/galpy/potential/MN3ExponentialDiskPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/MN3ExponentialDiskPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -4,9 +4,9 @@ # exponential disk potential of Smith et al. # 2015 ############################################################################### -import numpy import warnings -from galpy.util import galpyWarning +import numpy +from ..util import galpyWarning from .Potential import Potential, kms_to_kpcGyrDecorator, _APY_LOADED if _APY_LOADED: from astropy import units diff -Nru galpy-1.5/galpy/potential/MovingObjectPotential.py galpy-1.6.0.post0/galpy/potential/MovingObjectPotential.py --- galpy-1.5/galpy/potential/MovingObjectPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/MovingObjectPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -3,7 +3,7 @@ # a moving object ############################################################################### import copy -import numpy as nu +import numpy from .Potential import Potential, _isNonAxi, flatten, \ evaluatePotentials, evaluateRforces, evaluatezforces, evaluateDensities, _check_c from .PlummerPotential import PlummerPotential @@ -82,7 +82,8 @@ Rdist = _cylR(R,phi,self._orb.R(t),self._orb.phi(t)) orbz = self._orb.z(t) if self._orb.dim() == 3 else 0 #Evaluate potential - return evaluatePotentials( self._pot, Rdist, orbz-z, use_physical=False) + return evaluatePotentials(self._pot,Rdist,orbz-z,t=t, + use_physical=False) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -108,10 +109,10 @@ (xd,yd,zd) = _cyldiff(self._orb.R(t), self._orb.phi(t), orbz, R, phi, z) #Evaluate cylindrical radial force - RF = evaluateRforces(self._pot,Rdist,zd, use_physical=False) + RF = evaluateRforces(self._pot,Rdist,zd,t=t,use_physical=False) # Return R force, negative of radial vector to evaluation location. - return -RF*(nu.cos(phi)*xd+nu.sin(phi)*yd)/Rdist + return -RF*(numpy.cos(phi)*xd+numpy.sin(phi)*yd)/Rdist def _zforce(self,R,z,phi=0.,t=0.): """ @@ -137,7 +138,7 @@ (xd,yd,zd) = _cyldiff(self._orb.R(t), self._orb.phi(t), orbz, R, phi, z) #Evaluate and return z force - return -evaluatezforces(self._pot,Rdist,zd, use_physical=False) + return -evaluatezforces(self._pot,Rdist,zd,t=t,use_physical=False) def _phiforce(self,R,z,phi=0.,t=0.): """ @@ -163,9 +164,9 @@ (xd,yd,zd) = _cyldiff(self._orb.R(t), self._orb.phi(t), orbz, R, phi, z) #Evaluate cylindrical radial force. - RF = evaluateRforces(self._pot, Rdist, zd, use_physical=False) + RF = evaluateRforces(self._pot,Rdist,zd,t=t,use_physical=False) # Return phi force, negative of phi vector to evaluate location - return -RF*R*(nu.cos(phi)*yd-nu.sin(phi)*xd)/Rdist + return -RF*R*(numpy.cos(phi)*yd-numpy.sin(phi)*xd)/Rdist def _dens(self,R,z,phi=0.,t=0.): """ @@ -190,13 +191,13 @@ (xd,yd,zd) = _cyldiff(self._orb.R(t), self._orb.phi(t), orbz, R, phi, z) # Return the density - return evaluateDensities(self._pot, Rdist, zd, use_physical=False) + return evaluateDensities(self._pot,Rdist,zd,t=t,use_physical=False) def _cylR(R1,phi1,R2,phi2): - return nu.sqrt(R1**2.+R2**2.-2.*R1*R2*nu.cos(phi1-phi2)) # Cosine law + return numpy.sqrt(R1**2.+R2**2.-2.*R1*R2*numpy.cos(phi1-phi2)) # Cosine law def _cyldiff(R1,phi1,z1,R2,phi2,z2): - dx = R1*nu.cos(phi1)-R2*nu.cos(phi2) - dy = R1*nu.sin(phi1)-R2*nu.sin(phi2) + dx = R1*numpy.cos(phi1)-R2*numpy.cos(phi2) + dy = R1*numpy.sin(phi1)-R2*numpy.sin(phi2) dz = z1-z2 return (dx,dy,dz) diff -Nru galpy-1.5/galpy/potential/PerfectEllipsoidPotential.py galpy-1.6.0.post0/galpy/potential/PerfectEllipsoidPotential.py --- galpy-1.5/galpy/potential/PerfectEllipsoidPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/PerfectEllipsoidPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -76,6 +76,7 @@ self.normalize(normalize) self.hasC= not self._glorder is None self.hasC_dxdv= False + self.hasC_dens= self.hasC # works if mdens is defined, necessary for hasC return None def _psi(self,m): diff -Nru galpy-1.5/galpy/potential/planarPotential.py galpy-1.6.0.post0/galpy/potential/planarPotential.py --- galpy-1.5/galpy/potential/planarPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/planarPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -3,13 +3,14 @@ import os import copy import pickle -import numpy as nu +import numpy from scipy import integrate -import galpy.util.bovy_plot as plot -from galpy.util import config -from galpy.util.bovy_conversion import physical_conversion,\ - potential_physical_input, freq_in_Gyr +from ..util import bovy_plot as plot +from ..util import config +from ..util.bovy_conversion import physical_conversion,\ + potential_physical_input, freq_in_Gyr, physical_compatible from .Potential import Potential, PotentialError, lindbladR, flatten +from .DissipativeForce import _isDissipative from .plotRotcurve import plotRotcurve from .plotEscapecurve import _INF, plotEscapecurve _APY_LOADED= True @@ -26,6 +27,7 @@ self.isRZ= False self.hasC= False self.hasC_dxdv= False + self.hasC_dens= False # Parse ro and vo if ro is None: self._ro= config.__config__.getfloat('normalization','ro') @@ -101,16 +103,29 @@ 2019-01-27 - Written - Bovy (UofT) """ + from ..potential import flatten as flatten_pot + if not isinstance(flatten_pot([b])[0],(Potential,planarPotential)): + raise TypeError("""Can only combine galpy Potential""" + """/planarPotential objects with """ + """other such objects or lists thereof""") + assert physical_compatible(self,b), \ + """Physical unit conversion parameters (ro,vo) are not """\ + """compatible between potentials to be combined""" if isinstance(b,list): return [self]+b else: return [self,b] # Define separately to keep order def __radd__(self,b): - if isinstance(b,list): - return b+[self] - else: - raise TypeError("Can only add a Force or Potential instance to another instance or to a list of such instances") + from ..potential import flatten as flatten_pot + if not isinstance(flatten_pot([b])[0],(Potential,planarPotential)): + raise TypeError("""Can only combine galpy Force objects with """ + """other Force objects or lists thereof""") + assert physical_compatible(self,b), \ + """Physical unit conversion parameters (ro,vo) are not """\ + """compatible between potentials to be combined""" + # If we get here, b has to be a list + return b+[self] def turn_physical_off(self): """ @@ -163,14 +178,16 @@ 2016-01-30 - Written - Bovy (UofT) + 2020-04-22 - Don't turn on a parameter when it is False - Bovy (UofT) + """ - self._roSet= True - self._voSet= True - if not ro is None: + if not ro is False: self._roSet= True + if not vo is False: self._voSet= True + if not ro is None and ro: if _APY_LOADED and isinstance(ro,units.Quantity): ro= ro.to(units.kpc).value self._ro= ro - if not vo is None: + if not vo is None and vo: if _APY_LOADED and isinstance(vo,units.Quantity): vo= vo.to(units.km/units.s).value self._vo= vo @@ -471,7 +488,7 @@ @potential_physical_input @physical_conversion('velocity',pop=True) - def vcirc(self,R,phi=None): + def vcirc(self,R,phi=None,t=0.): """ NAME: @@ -490,6 +507,8 @@ phi= (None) azimuth to use for non-axisymmetric potentials + t - time (optional; can be Quantity) + OUTPUT: circular rotation velocity @@ -501,11 +520,11 @@ 2016-06-15 - Added phi= keyword for non-axisymmetric potential - Bovy (UofT) """ - return nu.sqrt(R*-self.Rforce(R,phi=phi,use_physical=False)) + return numpy.sqrt(R*-self.Rforce(R,phi=phi,t=t,use_physical=False)) @potential_physical_input @physical_conversion('frequency',pop=True) - def omegac(self,R): + def omegac(self,R,t=0.): """ NAME: @@ -521,6 +540,8 @@ Pot - Potential instance or list of such instances R - Galactocentric radius (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -531,11 +552,11 @@ 2011-10-09 - Written - Bovy (IAS) """ - return nu.sqrt(-self.Rforce(R,use_physical=False)/R) + return numpy.sqrt(-self.Rforce(R,t=t,use_physical=False)/R) @potential_physical_input @physical_conversion('frequency',pop=True) - def epifreq(self,R): + def epifreq(self,R,t=0.): """ NAME: @@ -549,6 +570,8 @@ INPUT: R - Galactocentric radius (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -559,11 +582,11 @@ 2011-10-09 - Written - Bovy (IAS) """ - return nu.sqrt(self.R2deriv(R,use_physical=False) - -3./R*self.Rforce(R,use_physical=False)) + return numpy.sqrt(self.R2deriv(R,t=t,use_physical=False) + -3./R*self.Rforce(R,t=t,use_physical=False)) @physical_conversion('position',pop=True) - def lindbladR(self,OmegaP,m=2,**kwargs): + def lindbladR(self,OmegaP,m=2,t=0.,**kwargs): """ NAME: @@ -581,6 +604,8 @@ m= order of the resonance (as in m(O-Op)=kappa (negative m for outer) use m='corotation' for corotation +scipy.optimize.brentq xtol,rtol,maxiter kwargs + + t - time (optional; can be Quantity) OUTPUT: @@ -593,11 +618,11 @@ """ if _APY_LOADED and isinstance(OmegaP,units.Quantity): OmegaP= OmegaP.to(1/units.Gyr).value/freq_in_Gyr(self._vo,self._ro) - return lindbladR(self,OmegaP,m=m,use_physical=False,**kwargs) + return lindbladR(self,OmegaP,m=m,t=t,use_physical=False,**kwargs) @potential_physical_input @physical_conversion('velocity',pop=True) - def vesc(self,R): + def vesc(self,R,t=0.): """ NAME: @@ -614,6 +639,8 @@ R - Galactocentric radius (can be Quantity) + t - time (optional; can be Quantity) + OUTPUT: escape velocity @@ -623,8 +650,8 @@ 2011-10-09 - Written - Bovy (IAS) """ - return nu.sqrt(2.*(self(_INF,use_physical=False) - -self(R,use_physical=False))) + return numpy.sqrt(2.*(self(_INF,t=t,use_physical=False) + -self(R,t=t,use_physical=False))) def plotRotcurve(self,*args,**kwargs): """ @@ -711,6 +738,7 @@ self._Pot= RZPot self.hasC= RZPot.hasC self.hasC_dxdv= RZPot.hasC_dxdv + self.hasC_dens= RZPot.hasC_dens return None def _evaluate(self,R,phi=0.,t=0.): @@ -788,6 +816,8 @@ """ RZPot= flatten(RZPot) + if _isDissipative(RZPot): + raise NotImplementedError("Converting dissipative forces to 2D potentials is currently not supported") if isinstance(RZPot,list): out= [] for pot in RZPot: @@ -828,6 +858,7 @@ self._Pot= Pot self.hasC= Pot.hasC self.hasC_dxdv= Pot.hasC_dxdv + self.hasC_dens= Pot.hasC_dens return None def _evaluate(self,R,phi=0.,t=0.): @@ -971,7 +1002,9 @@ """ Pot= flatten(Pot) - if isinstance(Pot,list): + if _isDissipative(Pot): + raise NotImplementedError("Converting dissipative forces to 2D potentials is currently not supported") + elif isinstance(Pot,list): out= [] for pot in Pot: if isinstance(pot,planarPotential): @@ -1033,7 +1066,7 @@ nonAxi= _isNonAxi(Pot) if nonAxi and phi is None: raise PotentialError("The (list of) planarPotential instances is non-axisymmetric, but you did not provide phi") - if isList and nu.all([isinstance(p,planarPotential) for p in Pot]): + if isList and numpy.all([isinstance(p,planarPotential) for p in Pot]): sum= 0. for pot in Pot: if nonAxi: @@ -1090,7 +1123,7 @@ if nonAxi and phi is None: raise PotentialError("The (list of) planarPotential instances is non-axisymmetric, but you did not provide phi") if isinstance(Pot,list) \ - and nu.all([isinstance(p,planarPotential) for p in Pot]): + and numpy.all([isinstance(p,planarPotential) for p in Pot]): sum= 0. for pot in Pot: if nonAxi: @@ -1146,7 +1179,7 @@ if nonAxi and phi is None: raise PotentialError("The (list of) planarPotential instances is non-axisymmetric, but you did not provide phi") if isinstance(Pot,list) \ - and nu.all([isinstance(p,planarPotential) for p in Pot]): + and numpy.all([isinstance(p,planarPotential) for p in Pot]): sum= 0. for pot in Pot: if nonAxi: @@ -1199,7 +1232,7 @@ if nonAxi and phi is None: raise PotentialError("The (list of) planarPotential instances is non-axisymmetric, but you did not provide phi") if isinstance(Pot,list) \ - and nu.all([isinstance(p,planarPotential) for p in Pot]): + and numpy.all([isinstance(p,planarPotential) for p in Pot]): sum= 0. for pot in Pot: if nonAxi: @@ -1254,7 +1287,7 @@ """ axiPot= flatten(axiPot) - from galpy.potential import omegac, epifreq + from ..potential import omegac, epifreq if nonaxiPot is None and (OmegaP is None or k is None or m is None): raise IOError("Need to specify either nonaxiPot= or m=, k=, OmegaP= for LinShuReductionFactor") elif not nonaxiPot is None: @@ -1264,10 +1297,10 @@ tepif= epifreq(axiPot,R) s= m*(OmegaP-omegac(axiPot,R))/tepif chi= sigmar**2.*k**2./tepif**2. - return (1.-s**2.)/nu.sin(nu.pi*s)\ - *integrate.quad(lambda t: nu.exp(-chi*(1.+nu.cos(t)))\ - *nu.sin(s*t)*nu.sin(t), - 0.,nu.pi)[0] + return (1.-s**2.)/numpy.sin(numpy.pi*s)\ + *integrate.quad(lambda t: numpy.exp(-chi*(1.+numpy.cos(t)))\ + *numpy.sin(s*t)*numpy.sin(t), + 0.,numpy.pi)[0] def plotplanarPotentials(Pot,*args,**kwargs): """ @@ -1341,22 +1374,22 @@ savefile.close() else: if nonAxi: - xs= nu.linspace(xrange[0],xrange[1],gridx) - ys= nu.linspace(yrange[0],yrange[1],gridy) - potR= nu.zeros((gridx,gridy)) + xs= numpy.linspace(xrange[0],xrange[1],gridx) + ys= numpy.linspace(yrange[0],yrange[1],gridy) + potR= numpy.zeros((gridx,gridy)) for ii in range(gridx): for jj in range(gridy): - thisR= nu.sqrt(xs[ii]**2.+ys[jj]**2.) + thisR= numpy.sqrt(xs[ii]**2.+ys[jj]**2.) if xs[ii] >= 0.: - thisphi= nu.arcsin(ys[jj]/thisR) + thisphi= numpy.arcsin(ys[jj]/thisR) else: - thisphi= -nu.arcsin(ys[jj]/thisR)+nu.pi + thisphi= -numpy.arcsin(ys[jj]/thisR)+numpy.pi potR[ii,jj]= evaluateplanarPotentials(Pot,thisR, phi=thisphi, use_physical=False) else: - Rs= nu.linspace(Rrange[0],Rrange[1],grid) - potR= nu.zeros(grid) + Rs= numpy.linspace(Rrange[0],Rrange[1],grid) + potR= numpy.zeros(grid) for ii in range(grid): potR[ii]= evaluateplanarPotentials(Pot,Rs[ii], use_physical=False) @@ -1387,7 +1420,7 @@ kwargs['cntrls']= '-' ncontours= kwargs.pop('ncontours',10) if not 'levels' in kwargs: - kwargs['levels']= nu.linspace(nu.nanmin(potR),nu.nanmax(potR),ncontours) + kwargs['levels']= numpy.linspace(numpy.nanmin(potR),numpy.nanmax(potR),ncontours) return plot.bovy_dens2d(potR.T, xrange=xrange, yrange=yrange,**kwargs) diff -Nru galpy-1.5/galpy/potential/plotEscapecurve.py galpy-1.6.0.post0/galpy/potential/plotEscapecurve.py --- galpy-1.5/galpy/potential/plotEscapecurve.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/plotEscapecurve.py 2020-04-24 19:48:38.000000000 +0000 @@ -2,9 +2,9 @@ import os import pickle -import numpy as nu -import galpy.util.bovy_plot as plot -from galpy.util.bovy_conversion import physical_conversion,\ +import numpy +from ..util import bovy_plot as plot +from ..util.bovy_conversion import physical_conversion,\ potential_physical_input _APY_LOADED= True try: @@ -92,7 +92,7 @@ Rs= pickle.load(savefile) savefile.close() else: - Rs= nu.linspace(Rrange[0],Rrange[1],grid) + Rs= numpy.linspace(Rrange[0],Rrange[1],grid) esccurve= calcEscapecurve(Pot,Rs) if not savefilename == None: print("Writing savefile "+savefilename+" ...") @@ -113,14 +113,14 @@ kwargs['xrange']= Rrange if not 'yrange' in kwargs: kwargs['yrange']=\ - [0.,1.2*nu.amax(esccurve[True^nu.isnan(esccurve)])] + [0.,1.2*numpy.amax(esccurve[True^numpy.isnan(esccurve)])] kwargs.pop('ro',None) kwargs.pop('vo',None) kwargs.pop('use_physical',None) return plot.bovy_plot(Rs,esccurve,*args, **kwargs) -def calcEscapecurve(Pot,Rs): +def calcEscapecurve(Pot,Rs,t=0.): """ NAME: calcEscapecurve @@ -131,6 +131,9 @@ Pot - Potential or list of Potential instances Rs - (array of) radius(i) + + t - instantaneous time (optional) + OUTPUT: array of v_esc HISTORY: @@ -144,15 +147,15 @@ grid= len(Rs) except TypeError: grid=1 - Rs= nu.array([Rs]) - esccurve= nu.zeros(grid) + Rs= numpy.array([Rs]) + esccurve= numpy.zeros(grid) for ii in range(grid): - esccurve[ii]= vesc(Pot,Rs[ii],use_physical=False) + esccurve[ii]= vesc(Pot,Rs[ii],t=t,use_physical=False) return esccurve @potential_physical_input @physical_conversion('velocity',pop=True) -def vesc(Pot,R): +def vesc(Pot,R,t=0.): """ NAME: @@ -169,6 +172,8 @@ R - Galactocentric radius (can be Quantity) + t - time (optional; can be Quantity) + OUTPUT: escape velocity @@ -178,12 +183,12 @@ 2011-10-09 - Written - Bovy (IAS) """ - from galpy.potential import evaluateplanarPotentials - from galpy.potential import PotentialError + from ..potential import evaluateplanarPotentials + from ..potential import PotentialError try: - return nu.sqrt(2.*(evaluateplanarPotentials(Pot,_INF,use_physical=False)-evaluateplanarPotentials(Pot,R,use_physical=False))) + return numpy.sqrt(2.*(evaluateplanarPotentials(Pot,_INF,t=t,use_physical=False)-evaluateplanarPotentials(Pot,R,t=t,use_physical=False))) except PotentialError: - from galpy.potential import RZToplanarPotential + from ..potential import RZToplanarPotential Pot= RZToplanarPotential(Pot) - return nu.sqrt(2.*(evaluateplanarPotentials(Pot,_INF,use_physical=False)-evaluateplanarPotentials(Pot,R,use_physical=False))) + return numpy.sqrt(2.*(evaluateplanarPotentials(Pot,_INF,t=t,use_physical=False)-evaluateplanarPotentials(Pot,R,t=t,use_physical=False))) diff -Nru galpy-1.5/galpy/potential/plotRotcurve.py galpy-1.6.0.post0/galpy/potential/plotRotcurve.py --- galpy-1.5/galpy/potential/plotRotcurve.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/plotRotcurve.py 2020-04-24 19:48:38.000000000 +0000 @@ -2,9 +2,9 @@ import os import pickle -import numpy as nu -import galpy.util.bovy_plot as plot -from galpy.util.bovy_conversion import physical_conversion,\ +import numpy +from ..util import bovy_plot as plot +from ..util.bovy_conversion import physical_conversion,\ potential_physical_input _APY_LOADED= True try: @@ -96,7 +96,7 @@ Rs= pickle.load(savefile) savefile.close() else: - Rs= nu.linspace(Rrange[0],Rrange[1],grid) + Rs= numpy.linspace(Rrange[0],Rrange[1],grid) rotcurve= calcRotcurve(Pot,Rs,phi=phi) if not savefilename == None: print("Writing savefile "+savefilename+" ...") @@ -116,14 +116,14 @@ if not 'xrange' in kwargs: kwargs['xrange']= Rrange if not 'yrange' in kwargs: - kwargs['yrange']= [0.,1.2*nu.amax(rotcurve)] + kwargs['yrange']= [0.,1.2*numpy.amax(rotcurve)] kwargs.pop('ro',None) kwargs.pop('vo',None) kwargs.pop('use_physical',None) return plot.bovy_plot(Rs,rotcurve,*args, **kwargs) -def calcRotcurve(Pot,Rs,phi=None): +def calcRotcurve(Pot,Rs,phi=None,t=0.): """ NAME: @@ -142,6 +142,8 @@ phi= (None) azimuth to use for non-axisymmetric potentials + ts - instantaneous time (optional) + OUTPUT: array of vc @@ -157,15 +159,15 @@ grid= len(Rs) except TypeError: grid=1 - Rs= nu.array([Rs]) - rotcurve= nu.zeros(grid) + Rs= numpy.array([Rs]) + rotcurve= numpy.zeros(grid) for ii in range(grid): - rotcurve[ii]= vcirc(Pot,Rs[ii],phi=phi,use_physical=False) + rotcurve[ii]= vcirc(Pot,Rs[ii],phi=phi,t=t,use_physical=False) return rotcurve @potential_physical_input @physical_conversion('velocity',pop=True) -def vcirc(Pot,R,phi=None): +def vcirc(Pot,R,phi=None,t=0.): """ NAME: @@ -184,6 +186,8 @@ phi= (None) azimuth to use for non-axisymmetric potentials + t= time (optional; can be Quantity) + OUTPUT: circular rotation velocity @@ -195,20 +199,20 @@ 2016-06-15 - Added phi= keyword for non-axisymmetric potential - Bovy (UofT) """ - from galpy.potential import evaluateplanarRforces - from galpy.potential import PotentialError + from ..potential import evaluateplanarRforces + from ..potential import PotentialError try: - return nu.sqrt(-R*evaluateplanarRforces(Pot,R,phi=phi, + return numpy.sqrt(-R*evaluateplanarRforces(Pot,R,phi=phi,t=t, use_physical=False)) except PotentialError: - from galpy.potential import toPlanarPotential + from ..potential import toPlanarPotential Pot= toPlanarPotential(Pot) - return nu.sqrt(-R*evaluateplanarRforces(Pot,R,phi=phi, + return numpy.sqrt(-R*evaluateplanarRforces(Pot,R,phi=phi,t=t, use_physical=False)) @potential_physical_input @physical_conversion('frequency',pop=True) -def dvcircdR(Pot,R,phi=None): +def dvcircdR(Pot,R,phi=None,t=0.): """ NAME: @@ -227,6 +231,8 @@ phi= (None) azimuth to use for non-axisymmetric potentials + t= time (optional; can be Quantity) + OUTPUT: derivative of the circular rotation velocity wrt R @@ -238,13 +244,13 @@ 2016-06-28 - Added phi= keyword for non-axisymmetric potential - Bovy (UofT) """ - from galpy.potential import evaluateplanarRforces, evaluateplanarR2derivs - from galpy.potential import PotentialError - tvc= vcirc(Pot,R,phi=phi,use_physical=False) + from ..potential import evaluateplanarRforces, evaluateplanarR2derivs + from ..potential import PotentialError + tvc= vcirc(Pot,R,phi=phi,t=t,use_physical=False) try: - return 0.5*(-evaluateplanarRforces(Pot,R,phi=phi,use_physical=False)+R*evaluateplanarR2derivs(Pot,R,phi=phi,use_physical=False))/tvc + return 0.5*(-evaluateplanarRforces(Pot,R,phi=phi,t=t,use_physical=False)+R*evaluateplanarR2derivs(Pot,R,phi=phi,t=t,use_physical=False))/tvc except PotentialError: - from galpy.potential import RZToplanarPotential + from ..potential import RZToplanarPotential Pot= RZToplanarPotential(Pot) - return 0.5*(-evaluateplanarRforces(Pot,R,phi=phi,use_physical=False)+R*evaluateplanarR2derivs(Pot,R,phi=phi,use_physical=False))/tvc + return 0.5*(-evaluateplanarRforces(Pot,R,phi=phi,t=t,use_physical=False)+R*evaluateplanarR2derivs(Pot,R,phi=phi,t=t,use_physical=False))/tvc diff -Nru galpy-1.5/galpy/potential/PlummerPotential.py galpy-1.6.0.post0/galpy/potential/PlummerPotential.py --- galpy-1.5/galpy/potential/PlummerPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/PlummerPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -4,7 +4,7 @@ # phi(R,z) = - --------------------------------- # \sqrt(R^2+z^2+b^2) ############################################################################### -import numpy as nu +import numpy from .Potential import Potential, kms_to_kpcGyrDecorator, _APY_LOADED if _APY_LOADED: from astropy import units @@ -59,6 +59,7 @@ self.normalize(normalize) self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True self._nemo_accname= 'Plummer' def _evaluate(self,R,z,phi=0.,t=0.): @@ -77,7 +78,7 @@ HISTORY: 2015-06-15 - Started - Bovy (IAS) """ - return -1./nu.sqrt(R**2.+z**2.+self._b2) + return -1./numpy.sqrt(R**2.+z**2.+self._b2) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -133,7 +134,7 @@ HISTORY: 2015-06-15 - Written - Bovy (IAS) """ - return 3./4./nu.pi*self._b2*(R**2.+z**2.+self._b2)**-2.5 + return 3./4./numpy.pi*self._b2*(R**2.+z**2.+self._b2)**-2.5 def _surfdens(self,R,z,phi=0.,t=0.): """ @@ -152,7 +153,7 @@ 2018-08-19 - Written - Bovy (UofT) """ Rb= R**2.+self._b2 - return self._b2*z*(3.*Rb+2.*z**2.)/Rb**2.*(Rb+z**2.)**-1.5/2./nu.pi + return self._b2*z*(3.*Rb+2.*z**2.)/Rb**2.*(Rb+z**2.)**-1.5/2./numpy.pi def _R2deriv(self,R,z,phi=0.,t=0.): """ diff -Nru galpy-1.5/galpy/potential/potential_c_ext/BurkertPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/BurkertPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/BurkertPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/BurkertPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -63,3 +63,14 @@ double R5= pow(R,5); return -amp * M_PI * pow(a,3) / R5 * (-4. * R5 / ( a * a + R * R ) / ( a + R ) - 2. * R * R * ( M_PI - 2. * atan ( 1. / x ) - 2. * log( 1. + x ) - log( 1. + x * x ))); } +double BurkertPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double a= *(args+1); + //Calculate potential + double x= sqrt( R*R + Z*Z) / a; + return amp / ( 1. + x ) / ( 1. + x * x ); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/ChandrasekharDynamicalFrictionForce.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/ChandrasekharDynamicalFrictionForce.c --- galpy-1.5/galpy/potential/potential_c_ext/ChandrasekharDynamicalFrictionForce.c 1970-01-01 00:00:00.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/ChandrasekharDynamicalFrictionForce.c 2020-04-24 19:48:38.000000000 +0000 @@ -0,0 +1,145 @@ +#include +// Constants not defined in MSVC's math.h +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654746172 +#endif +#ifndef M_2_SQRTPI +#define M_2_SQRTPI 1.12837916709551255856 +#endif +#include +#include +// ChandrasekharDynamicalFrictionForce: 8 arguments: amp,ms,rhm,gamma^2, +// lnLambda, minr^2, ro, rf +double ChandrasekharDynamicalFrictionForceAmplitude(double R,double z, + double phi,double t, + double r2, + struct potentialArg * potentialArgs, + double vR,double vT, + double vz){ + double sr,X,Xfactor,d_ind,forceAmplitude; + double * args= potentialArgs->args; + //Get args + double amp= *args; + double ms= *(args+9); + double rhm= *(args+10); + double gamma2= *(args+11); + double lnLambda= *(args+12); + double ro= *(args+14); + double rf= *(args+15); + double GMvs; + double r= sqrt( r2 ); + double v2= vR * vR + vT * vT + vz * vz; + double v= sqrt( v2 ); + // Constant or variable Lambda + if ( lnLambda < 0 ) { + GMvs= ms/v/v; + if ( GMvs < rhm ) + lnLambda= 0.5 * log ( 1. + r2 / gamma2 / rhm / rhm ); + else + lnLambda= 0.5 * log ( 1. + r2 / gamma2 / GMvs / GMvs ); + } + d_ind= (r-ro)/(rf-ro); + d_ind= d_ind < 0 ? 0. : ( d_ind > 1 ? 1. : d_ind); + sr= gsl_spline_eval(*potentialArgs->spline1d,d_ind,*potentialArgs->acc1d); + X= M_SQRT1_2 * v / sr; + Xfactor= erf ( X ) - M_2_SQRTPI * X * exp ( - X * X ); + forceAmplitude= - amp * Xfactor * lnLambda / v2 / v \ + * calcDensity(R,z,phi,t,potentialArgs->nwrapped, + potentialArgs->wrappedPotentialArg); + // Caching + *(args + 1)= R; + *(args + 2)= z; + *(args + 3)= phi; + *(args + 4)= t; + *(args + 5)= vR; + *(args + 6)= vT; + *(args + 7)= vz; + *(args + 8)= forceAmplitude; + return forceAmplitude; +} +double ChandrasekharDynamicalFrictionForceRforce(double R,double z, double phi, + double t, + struct potentialArg * potentialArgs, + double vR,double vT, + double vz){ + double forceAmplitude; + double * args= potentialArgs->args; + double r2= R * R + z * z; + if ( r2 < *(args+13) ) // r < minr, don't bother caching + return 0.; + //Get args + double cached_R= *(args + 1); + double cached_z= *(args + 2); + double cached_phi= *(args + 3); + double cached_t= *(args + 4); + double cached_vR= *(args + 5); + double cached_vT= *(args + 6); + double cached_vz= *(args + 7); + if ( R != cached_R || phi != cached_phi || z != cached_z || t != cached_t \ + || vR != cached_vR || vT != cached_vT || vz != cached_vz ) + forceAmplitude= ChandrasekharDynamicalFrictionForceAmplitude(R,z,phi,t,r2, + potentialArgs, + vR,vT,vz); + else + forceAmplitude= *(args + 8); + return forceAmplitude * vR; +} +double ChandrasekharDynamicalFrictionForcezforce(double R,double z, double phi, + double t, + struct potentialArg * potentialArgs, + double vR,double vT, + double vz){ + double forceAmplitude; + double * args= potentialArgs->args; + double r2= R * R + z * z; + if ( r2 < *(args+13) ) // r < minr, don't bother caching + return 0.; + //Get args + double cached_R= *(args + 1); + double cached_z= *(args + 2); + double cached_phi= *(args + 3); + double cached_t= *(args + 4); + double cached_vR= *(args + 5); + double cached_vT= *(args + 6); + double cached_vz= *(args + 7); + if ( R != cached_R || phi != cached_phi || z != cached_z || t != cached_t \ + || vR != cached_vR || vT != cached_vT || vz != cached_vz ) + //LCOV_EXCL_START + forceAmplitude= ChandrasekharDynamicalFrictionForceAmplitude(R,z,phi,t,r2, + potentialArgs, + vR,vT,vz); + //LCOV_EXCL_STOP + else + forceAmplitude= *(args + 8); + return forceAmplitude * vz; +} +double ChandrasekharDynamicalFrictionForcephiforce(double R,double z, + double phi,double t, + struct potentialArg * potentialArgs, + double vR,double vT, + double vz){ + double forceAmplitude; + double * args= potentialArgs->args; + double r2= R * R + z * z; + if ( r2 < *(args+13) ) // r < minr, don't bother caching + return 0.; + //Get args + double cached_R= *(args + 1); + double cached_z= *(args + 2); + double cached_phi= *(args + 3); + double cached_t= *(args + 4); + double cached_vR= *(args + 5); + double cached_vT= *(args + 6); + double cached_vz= *(args + 7); + if ( R != cached_R || phi != cached_phi || z != cached_z || t != cached_t \ + || vR != cached_vR || vT != cached_vT || vz != cached_vz ) + //LCOV_EXCL_START + forceAmplitude= ChandrasekharDynamicalFrictionForceAmplitude(R,z,phi,t,r2, + potentialArgs, + vR,vT,vz); + //LCOV_EXCL_STOP + else + forceAmplitude= *(args + 8); + return forceAmplitude * vT * R; +} + diff -Nru galpy-1.5/galpy/potential/potential_c_ext/DehnenCorePotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/DehnenCorePotential.c --- galpy-1.5/galpy/potential/potential_c_ext/DehnenCorePotential.c 1970-01-01 00:00:00.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/DehnenCorePotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -0,0 +1,69 @@ +#include +#include "galpy_potentials.h" +//CoreDehnenPotential +//2 arguments: amp, a +double DehnenCoreSphericalPotentialEval(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + double amp= *args++; + double a= *args++; + //Calculate Rforce + double sqrtRz= pow(R*R+Z*Z,0.5); + return -amp * (1. - pow(sqrtRz/(sqrtRz+a), 2.)) / (6. * a); +} + +double DehnenCoreSphericalPotentialRforce(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + double amp= *args++; + double a= *args++; + //Calculate Rforce + double sqrtRz= pow(R*R+Z*Z,0.5); + return - amp * (R / pow(a+sqrtRz,3.) / 3.); +} + +double DehnenCoreSphericalPotentialPlanarRforce(double R,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args++; + //Calculate Rforce + return - amp * (R / pow(a+R, 3.) / 3.); +} + +double DehnenCoreSphericalPotentialzforce(double R,double Z,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args++; + //Calculate Rforce + double sqrtRz= pow(R*R+Z*Z,0.5); + return - amp * (Z / pow(a+sqrtRz, 3.) / 3.); +} + +double DehnenCoreSphericalPotentialPlanarR2deriv(double R,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args++; + // return + return -amp * (pow(a+R, -4.) * (2.*R - a)) / 3.; +} +double DehnenCoreSphericalPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + double amp= *args++; + double a= *args++; + //Calculate Rforce + double r= sqrt ( R * R + Z * Z ); + return amp * M_1_PI / 4. * pow ( 1. + r / a, -4.) * pow (a, - 3.); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/DehnenPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/DehnenPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/DehnenPotential.c 1970-01-01 00:00:00.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/DehnenPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -0,0 +1,78 @@ +#include +#include "galpy_potentials.h" +//DehnenPotential +//3 arguments: amp, a, alpha +double DehnenSphericalPotentialEval(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + double amp= *args++; + double a= *args++; + double alpha= *args; + //Calculate Rforce + double sqrtRz= pow(R*R+Z*Z,0.5); + // if (alpha == 2.) {return -amp * R * pow( sqrtRz , -3. ) / ( 1. + a / sqrtRz );} // not needed b/c Jaffe + return -amp * (1. - pow(sqrtRz/(sqrtRz+a), 2.-alpha)) / (a * (2. - alpha) * (3. - alpha)); +} + +double DehnenSphericalPotentialRforce(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + double amp= *args++; + double a= *args++; + double alpha= *args; + //Calculate Rforce + double sqrtRz= pow(R*R+Z*Z,0.5); + return - amp * (R * pow(1.+a/sqrtRz, alpha) / pow(a+sqrtRz,3.) / (3.-alpha)); +} + +double DehnenSphericalPotentialPlanarRforce(double R,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args++; + double alpha= *args; + //Calculate Rforce + return - amp * (R * pow(1.+a/R, alpha) / pow(a+R, 3.) / (3.-alpha)); +} + +double DehnenSphericalPotentialzforce(double R,double Z,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args++; + double alpha= *args; + //Calculate Rforce + double sqrtRz= pow(R*R+Z*Z,0.5); + return - amp * (Z * pow(1. + a/sqrtRz, alpha) / pow(a+sqrtRz, 3.) / (3.-alpha)); +} + +double DehnenSphericalPotentialPlanarR2deriv(double R,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args++; + double alpha= *args; + // return + return -amp * (pow(1.+a/R, alpha) * pow(a+R, -4.) * (2.*R + a*(alpha-1.))) / (3.-alpha); +} +double DehnenSphericalPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + double amp= *args++; + double a= *args++; + double alpha= *args; + //Calculate density + double r= sqrt ( R * R + Z * Z ); + return amp * M_1_PI / 4. * pow (r,-alpha ) * pow ( 1. + r / a, alpha-4.) \ + * pow (a, alpha - 3.); +} + diff -Nru galpy-1.5/galpy/potential/potential_c_ext/DiskSCFPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/DiskSCFPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/DiskSCFPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/DiskSCFPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -54,8 +54,6 @@ } return -1; // LCOV_EXCL_LINE } -//LCOV_EXCL_START -// Not currently used, bc only in 2nd derivatives double d2SigmadR2(double R,double * Sigma_args){ int Sigma_type= (int) *Sigma_args; switch ( Sigma_type ) { @@ -83,7 +81,6 @@ } return -1; // LCOV_EXCL_LINE } -//LCOV_EXCL_STOP double Hz(double z,double * hz_args){ int hz_type= (int) *hz_args; double fz= fabs(z); @@ -158,3 +155,18 @@ return -dSigmadR(r,Sigma_args) * Hz(Z,hz_args) * Z / r \ -Sigma(r,Sigma_args) * dHzdz(Z,hz_args); } +double DiskSCFPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + int nsigma_args= (int) *args; + double * Sigma_args= args+1; + double * hz_args= args+1+nsigma_args; + //Calculate Rforce + double r= sqrt( R * R + Z * Z ); + return M_1_PI / 4. * (Sigma(r,Sigma_args) * hz(Z,hz_args) + + d2SigmadR2(r,Sigma_args) * Hz(Z,hz_args) + + 2. / r * dSigmadR(r,Sigma_args) \ + * ( Hz(Z,hz_args) + Z * dHzdz(Z,hz_args) ) ); + } diff -Nru galpy-1.5/galpy/potential/potential_c_ext/DoubleExponentialDiskPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/DoubleExponentialDiskPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/DoubleExponentialDiskPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/DoubleExponentialDiskPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -175,3 +175,14 @@ else return amp * 2 * M_PI * alpha * beta * out; } +double DoubleExponentialDiskPotentialDens(double R,double z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double alpha= *args++; + double beta= *args; + // calculate density + return amp * exp ( - alpha * R - beta * fabs ( z ) ); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/EllipsoidalPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/EllipsoidalPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/EllipsoidalPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/EllipsoidalPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -179,6 +179,26 @@ struct potentialArg * potentialArgs){ return EllipsoidalPotentialphiforce(R,0.,phi,t,potentialArgs); } +double EllipsoidalPotentialDens(double R,double z, double phi, + double t, + struct potentialArg * potentialArgs){ + //Get args + double * args= potentialArgs->args; + double amp= *args; + double * ellipargs= args + 8 + (int) *(args+7); // *(args+7) = num. arguments psi + double b2= *ellipargs++; + double c2= *ellipargs++; + bool aligned= (bool) *ellipargs++; + double * rot= ellipargs; + ellipargs+= 9; + //Calculate density + double x, y; + cyl_to_rect(R,phi,&x,&y); + if ( !aligned ) + rotate(&x,&y,&z,rot); + return amp * potentialArgs->mdens ( sqrt (x * x + y * y / b2 + z * z / c2 ), + args+8); +} /* diff -Nru galpy-1.5/galpy/potential/potential_c_ext/FlattenedPowerPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/FlattenedPowerPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/FlattenedPowerPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/FlattenedPowerPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -90,3 +90,24 @@ return - amp * pow(m2,-0.5 * alpha - 1.) * ( (alpha + 1.) * R*R/m2 -1.); } } +double FlattenedPowerPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double alpha= *(args+1); + double q2= *(args+2); + double core2= *(args+3); + //Calculate density + if ( alpha == 0. ) + return amp * M_1_PI / 4. / q2 * ( ( 2. * q2 + 1. ) * core2 + R * R \ + + ( 2. - 1. / q2 ) * Z * Z ) \ + * pow ( R * R + Z * Z / q2 + core2 ,-2.); + else { + return amp * M_1_PI / 4. / q2 * ( ( 2. * q2 + 1. ) * core2 + R * R \ + * ( 1. - alpha * q2 ) + Z * Z \ + * ( 2. - ( 1. +alpha ) / q2 ) ) \ + * pow( R * R + Z * Z / q2 + core2, -alpha / 2. - 2. ); + } +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/galpy_potentials.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/galpy_potentials.c --- galpy-1.5/galpy/potential/potential_c_ext/galpy_potentials.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/galpy_potentials.c 2020-04-24 19:48:38.000000000 +0000 @@ -5,7 +5,6 @@ (potentialArgs+ii)->i2d= NULL; (potentialArgs+ii)->accx= NULL; (potentialArgs+ii)->accy= NULL; - (potentialArgs+ii)->accz= NULL; (potentialArgs+ii)->i2drforce= NULL; (potentialArgs+ii)->accxrforce= NULL; (potentialArgs+ii)->accyrforce= NULL; @@ -13,13 +12,12 @@ (potentialArgs+ii)->accxzforce= NULL; (potentialArgs+ii)->accyzforce= NULL; (potentialArgs+ii)->wrappedPotentialArg= NULL; - (potentialArgs+ii)->xSpline= NULL; - (potentialArgs+ii)->ySpline= NULL; - (potentialArgs+ii)->zSpline= NULL; + (potentialArgs+ii)->spline1d= NULL; + (potentialArgs+ii)->acc1d= NULL; } } void free_potentialArgs(int npot, struct potentialArg * potentialArgs){ - int ii; + int ii, jj; for (ii=0; ii < npot; ii++) { if ( (potentialArgs+ii)->i2d ) interp_2d_free((potentialArgs+ii)->i2d) ; @@ -27,8 +25,6 @@ gsl_interp_accel_free ((potentialArgs+ii)->accx); if ( (potentialArgs+ii)->accy ) gsl_interp_accel_free ((potentialArgs+ii)->accy); - if ( (potentialArgs+ii)->accz ) - gsl_interp_accel_free ((potentialArgs+ii)->accz); if ( (potentialArgs+ii)->i2drforce ) interp_2d_free((potentialArgs+ii)->i2drforce) ; if ( (potentialArgs+ii)->accxrforce ) @@ -46,12 +42,16 @@ (potentialArgs+ii)->wrappedPotentialArg); free((potentialArgs+ii)->wrappedPotentialArg); } - if ( (potentialArgs+ii)->xSpline ) - gsl_spline_free((potentialArgs+ii)->xSpline); - if ( (potentialArgs+ii)->ySpline ) - gsl_spline_free ((potentialArgs+ii)->ySpline); - if ( (potentialArgs+ii)->zSpline ) - gsl_spline_free ((potentialArgs+ii)->zSpline); + if ( (potentialArgs+ii)->spline1d ) { + for (jj=0; jj < (potentialArgs+ii)->nspline1d; jj++) + gsl_spline_free(*((potentialArgs+ii)->spline1d+jj)); + free((potentialArgs+ii)->spline1d); + } + if ( (potentialArgs+ii)->acc1d ) { + for (jj=0; jj < (potentialArgs+ii)->nspline1d; jj++) + gsl_interp_accel_free (*((potentialArgs+ii)->acc1d+jj)); + free((potentialArgs+ii)->acc1d); + } free((potentialArgs+ii)->args); } } @@ -67,37 +67,50 @@ potentialArgs-= nargs; return pot; } -double calcRforce(double R, double Z, double phi, double t, - int nargs, struct potentialArg * potentialArgs){ +// function name in parentheses, because actual function defined by macro +// in galpy_potentials.h and parentheses are necessary to avoid macro expansion +double (calcRforce)(double R, double Z, double phi, double t, + int nargs, struct potentialArg * potentialArgs, + double vR, double vT, double vZ){ int ii; double Rforce= 0.; for (ii=0; ii < nargs; ii++){ - Rforce+= potentialArgs->Rforce(R,Z,phi,t, - potentialArgs); + if ( potentialArgs->requiresVelocity ) + Rforce+= potentialArgs->RforceVelocity(R,Z,phi,t,potentialArgs,vR,vT,vZ); + else + Rforce+= potentialArgs->Rforce(R,Z,phi,t, + potentialArgs); potentialArgs++; } potentialArgs-= nargs; return Rforce; } -double calczforce(double R, double Z, double phi, double t, - int nargs, struct potentialArg * potentialArgs){ +double (calczforce)(double R, double Z, double phi, double t, + int nargs, struct potentialArg * potentialArgs, + double vR, double vT, double vZ){ int ii; double zforce= 0.; for (ii=0; ii < nargs; ii++){ - zforce+= potentialArgs->zforce(R,Z,phi,t, - potentialArgs); + if ( potentialArgs->requiresVelocity ) + zforce+= potentialArgs->zforceVelocity(R,Z,phi,t,potentialArgs,vR,vT,vZ); + else + zforce+= potentialArgs->zforce(R,Z,phi,t,potentialArgs); potentialArgs++; } potentialArgs-= nargs; return zforce; } -double calcPhiforce(double R, double Z, double phi, double t, - int nargs, struct potentialArg * potentialArgs){ +double (calcPhiforce)(double R, double Z, double phi, double t, + int nargs, struct potentialArg * potentialArgs, + double vR, double vT, double vZ){ int ii; double phiforce= 0.; for (ii=0; ii < nargs; ii++){ - phiforce+= potentialArgs->phiforce(R,Z,phi,t, - potentialArgs); + if ( potentialArgs->requiresVelocity ) + phiforce+= potentialArgs->phiforceVelocity(R,Z,phi,t,potentialArgs, + vR,vT,vZ); + else + phiforce+= potentialArgs->phiforce(R,Z,phi,t,potentialArgs); potentialArgs++; } potentialArgs-= nargs; @@ -215,3 +228,14 @@ potentialArgs-= nargs; return force; } +double calcDensity(double R, double Z, double phi, double t, + int nargs, struct potentialArg * potentialArgs){ + int ii; + double dens= 0.; + for (ii=0; ii < nargs; ii++){ + dens+= potentialArgs->dens(R,Z,phi,t,potentialArgs); + potentialArgs++; + } + potentialArgs-= nargs; + return dens; +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/galpy_potentials.h galpy-1.6.0.post0/galpy/potential/potential_c_ext/galpy_potentials.h --- galpy-1.5/galpy/potential/potential_c_ext/galpy_potentials.h 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/galpy_potentials.h 2020-04-24 19:48:38.000000000 +0000 @@ -7,7 +7,11 @@ #ifdef __cplusplus extern "C" { #endif +#include #include +#ifndef M_1_PI +#define M_1_PI 0.31830988618379069122 +#endif struct potentialArg{ double (*potentialEval)(double R, double Z, double phi, double t, struct potentialArg *); @@ -35,15 +39,26 @@ struct potentialArg *); double (*linearForce)(double x, double t, struct potentialArg *); + double (*dens)(double R, double Z, double phi, double t, + struct potentialArg *); + // For forces that require velocity input (e.g., dynam fric) + bool requiresVelocity; + double (*RforceVelocity)(double R, double Z, double phi, double t, + struct potentialArg *,double,double,double); + double (*zforceVelocity)(double R, double Z, double phi, double t, + struct potentialArg *,double,double,double); + double (*phiforceVelocity)(double R, double Z, double phi, double t, + struct potentialArg *,double,double,double); int nargs; double * args; + // To allow 1D interpolation for an arbitrary number of splines + int nspline1d; + gsl_interp_accel ** acc1d; + gsl_spline ** spline1d; + // 2D interpolation interp_2d * i2d; gsl_interp_accel * accx; gsl_interp_accel * accy; - gsl_interp_accel * accz; - gsl_spline * xSpline; - gsl_spline * ySpline; - gsl_spline * zSpline; interp_2d * i2drforce; gsl_interp_accel * accxrforce; gsl_interp_accel * accyrforce; @@ -65,10 +80,39 @@ void free_potentialArgs(int,struct potentialArg *); //Potential and force evaluation double evaluatePotentials(double,double,int, struct potentialArg *); -double calcRforce(double,double,double,double,int,struct potentialArg *); -double calczforce(double,double,double,double,int,struct potentialArg *); -double calcPhiforce(double, double,double, double, - int, struct potentialArg *); +// Hack to allow optional velocity for dissipative forces +// https://stackoverflow.com/a/52610204/10195320 +// Reason to use ##__VA_ARGS__ is that when no optional velocity is supplied, +// there is a comma left in the argument list and ## absorbs that for gcc/icc +// MSVC supposedly does this automatically for regular __VA_ARGS__, at least +// for now, but I can't get this to work locally or on AppVeyor +// https://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=vs-2019#comma-elision-in-variadic-macros +// Therefore, I use an alternative where all arguments are variadic, such +// that there should always be many. Final subtlety is that we have to define +// the EXPAND macro to expand the __VA_ARGS__ into multiple arguments, +// otherwise it's treated as a single argument in the next function call +// calll (e.g., CALCRFORCE would get R = __VA_ARGS = R,Z,phi,...) +#ifdef _MSC_VER +#define EXPAND(x) x +#define calcRforce(...) EXPAND(CALCRFORCE(__VA_ARGS__,0.,0.,0.)) +#define calczforce(...) EXPAND(CALCZFORCE(__VA_ARGS__,0.,0.,0.)) +#define calcPhiforce(...) EXPAND(CALCPHIFORCE(__VA_ARGS__,0.,0.,0.)) +#else +#define calcRforce(R,Z,phi,t,nargs,potentialArgs,...) CALCRFORCE(R,Z,phi,t,nargs,potentialArgs,##__VA_ARGS__,0.,0.,0.) +#define calczforce(R,Z,phi,t,nargs,potentialArgs,...) CALCZFORCE(R,Z,phi,t,nargs,potentialArgs,##__VA_ARGS__,0.,0.,0.) +#define calcPhiforce(R,Z,phi,t,nargs,potentialArgs,...) CALCPHIFORCE(R,Z,phi,t,nargs,potentialArgs,##__VA_ARGS__,0.,0.,0.) +#endif +#define CALCRFORCE(R,Z,phi,t,nargs,potentialArgs,vR,vT,vZ,...) calcRforce(R,Z,phi,t,nargs,potentialArgs,vR,vT,vZ) +#define CALCZFORCE(R,Z,phi,t,nargs,potentialArgs,vR,vT,vZ,...) calczforce(R,Z,phi,t,nargs,potentialArgs,vR,vT,vZ) +#define CALCPHIFORCE(R,Z,phi,t,nargs,potentialArgs,vR,vT,vZ,...) calcPhiforce(R,Z,phi,t,nargs,potentialArgs,vR,vT,vZ) +double (calcRforce)(double,double,double,double,int,struct potentialArg *, + double,double,double); +double (calczforce)(double,double,double,double,int,struct potentialArg *, + double,double,double); +double (calcPhiforce)(double, double,double, double, + int, struct potentialArg *, + double,double,double); +// end hack double calcR2deriv(double, double, double,double, int, struct potentialArg *); double calcphi2deriv(double, double, double,double, @@ -86,6 +130,7 @@ double calcPlanarRphideriv(double, double, double, int, struct potentialArg *); double calcLinearForce(double, double, int, struct potentialArg *); +double calcDensity(double, double, double,double, int, struct potentialArg *); //ZeroForce double ZeroPlanarForce(double,double,double, struct potentialArg *); @@ -112,6 +157,8 @@ struct potentialArg *); double LogarithmicHaloPotentialPlanarRphideriv(double ,double, double, struct potentialArg *); +double LogarithmicHaloPotentialDens(double ,double , double, double, + struct potentialArg *); //DehnenBarPotential double DehnenBarPotentialRforce(double,double,double,double, struct potentialArg *); @@ -161,6 +208,8 @@ struct potentialArg *); double MiyamotoNagaiPotentialPlanarR2deriv(double ,double, double, struct potentialArg *); +double MiyamotoNagaiPotentialDens(double ,double , double, double, + struct potentialArg *); //LopsidedDiskPotential double LopsidedDiskPotentialRforce(double,double,double, struct potentialArg *); @@ -183,6 +232,8 @@ struct potentialArg *); double PowerSphericalPotentialPlanarR2deriv(double ,double, double, struct potentialArg *); +double PowerSphericalPotentialDens(double ,double , double, double, + struct potentialArg *); //HernquistPotential double HernquistPotentialEval(double ,double , double, double, struct potentialArg *); @@ -194,6 +245,8 @@ struct potentialArg *); double HernquistPotentialPlanarR2deriv(double ,double, double, struct potentialArg *); +double HernquistPotentialDens(double ,double , double, double, + struct potentialArg *); //NFWPotential double NFWPotentialEval(double ,double , double, double, struct potentialArg *); @@ -205,6 +258,8 @@ struct potentialArg *); double NFWPotentialPlanarR2deriv(double ,double, double, struct potentialArg *); +double NFWPotentialDens(double ,double , double, double, + struct potentialArg *); //JaffePotential double JaffePotentialEval(double ,double , double, double, struct potentialArg *); @@ -216,6 +271,8 @@ struct potentialArg *); double JaffePotentialPlanarR2deriv(double ,double, double, struct potentialArg *); +double JaffePotentialDens(double ,double , double, double, + struct potentialArg *); //DoubleExponentialDiskPotential double DoubleExponentialDiskPotentialEval(double ,double , double, double, struct potentialArg *); @@ -225,6 +282,8 @@ struct potentialArg *); double DoubleExponentialDiskPotentialzforce(double,double, double,double, struct potentialArg *); +double DoubleExponentialDiskPotentialDens(double ,double , double, double, + struct potentialArg *); //FlattenedPowerPotential double FlattenedPowerPotentialEval(double,double,double,double, struct potentialArg *); @@ -236,6 +295,8 @@ struct potentialArg *); double FlattenedPowerPotentialPlanarR2deriv(double,double,double, struct potentialArg *); +double FlattenedPowerPotentialDens(double,double,double,double, + struct potentialArg *); //interpRZPotential double interpRZPotentialEval(double ,double , double, double, struct potentialArg *); @@ -254,6 +315,8 @@ struct potentialArg *); double IsochronePotentialPlanarR2deriv(double ,double, double, struct potentialArg *); +double IsochronePotentialDens(double ,double , double, double, + struct potentialArg *); //PowerSphericalPotentialwCutoff double PowerSphericalPotentialwCutoffEval(double ,double , double, double, struct potentialArg *); @@ -265,6 +328,8 @@ struct potentialArg *); double PowerSphericalPotentialwCutoffPlanarR2deriv(double ,double, double, struct potentialArg *); +double PowerSphericalPotentialwCutoffDens(double ,double , double, double, + struct potentialArg *); //KuzminKutuzovStaeckelPotential double KuzminKutuzovStaeckelPotentialEval(double,double,double,double, struct potentialArg *); @@ -299,6 +364,8 @@ struct potentialArg *); double PlummerPotentialPlanarR2deriv(double,double,double, struct potentialArg *); +double PlummerPotentialDens(double,double,double,double, + struct potentialArg *); //PseudoIsothermalPotential double PseudoIsothermalPotentialEval(double,double,double,double, struct potentialArg *); @@ -310,6 +377,8 @@ struct potentialArg *); double PseudoIsothermalPotentialPlanarR2deriv(double,double,double, struct potentialArg *); +double PseudoIsothermalPotentialDens(double,double,double,double, + struct potentialArg *); //BurkertPotential double BurkertPotentialEval(double,double,double,double, struct potentialArg *); @@ -321,6 +390,8 @@ struct potentialArg *); double BurkertPotentialPlanarR2deriv(double,double,double, struct potentialArg *); +double BurkertPotentialDens(double,double,double,double, + struct potentialArg *); //EllipsoidalPotential double EllipsoidalPotentialEval(double,double,double,double, struct potentialArg *); @@ -334,6 +405,8 @@ struct potentialArg *); double EllipsoidalPotentialzforce(double,double,double,double, struct potentialArg *); +double EllipsoidalPotentialDens(double,double,double,double, + struct potentialArg *); //TriaxialHernquistPotential: uses EllipsoidalPotential, only need psi, dens, densDeriv double TriaxialHernquistPotentialpsi(double,double *); double TriaxialHernquistPotentialmdens(double,double *); @@ -366,6 +439,8 @@ struct potentialArg *); double SCFPotentialPlanarRphideriv(double,double,double, struct potentialArg *); +double SCFPotentialDens(double,double,double,double, + struct potentialArg *); //SoftenedNeedleBarPotential double SoftenedNeedleBarPotentialEval(double,double,double,double, struct potentialArg *); @@ -388,6 +463,8 @@ struct potentialArg *); double DiskSCFPotentialPlanarRforce(double,double,double, struct potentialArg *); +double DiskSCFPotentialDens(double,double,double,double, + struct potentialArg *); // SpiralArmsPotential double SpiralArmsPotentialEval(double, double, double, double, @@ -430,6 +507,47 @@ //IsothermalDiskPotential double IsothermalDiskPotentialLinearForce(double,double,struct potentialArg *); +//DehnenSphericalPotential +double DehnenSphericalPotentialEval(double ,double , double, double, + struct potentialArg *); +double DehnenSphericalPotentialRforce(double ,double , double, double, + struct potentialArg *); +double DehnenSphericalPotentialPlanarRforce(double ,double, double, + struct potentialArg *); +double DehnenSphericalPotentialzforce(double,double,double,double, + struct potentialArg *); +double DehnenSphericalPotentialPlanarR2deriv(double ,double, double, + struct potentialArg *); +double DehnenSphericalPotentialDens(double ,double , double, double, + struct potentialArg *); +//DehnenCoreSphericalPotential +double DehnenCoreSphericalPotentialEval(double ,double , double, double, + struct potentialArg *); +double DehnenCoreSphericalPotentialRforce(double ,double , double, double, + struct potentialArg *); +double DehnenCoreSphericalPotentialPlanarRforce(double ,double, double, + struct potentialArg *); +double DehnenCoreSphericalPotentialzforce(double,double,double,double, + struct potentialArg *); +double DehnenCoreSphericalPotentialPlanarR2deriv(double ,double, double, + struct potentialArg *); +double DehnenCoreSphericalPotentialDens(double ,double , double, double, + struct potentialArg *); + +//HomogeneousSpherePotential +double HomogeneousSpherePotentialEval(double ,double , double, double, + struct potentialArg *); +double HomogeneousSpherePotentialRforce(double ,double , double, double, + struct potentialArg *); +double HomogeneousSpherePotentialPlanarRforce(double ,double, double, + struct potentialArg *); +double HomogeneousSpherePotentialzforce(double,double,double,double, + struct potentialArg *); +double HomogeneousSpherePotentialPlanarR2deriv(double ,double, double, + struct potentialArg *); +double HomogeneousSpherePotentialDens(double ,double , double, double, + struct potentialArg *); + //////////////////////////////// WRAPPERS ///////////////////////////////////// //DehnenSmoothWrapperPotential double DehnenSmoothWrapperPotentialEval(double,double,double,double, @@ -536,6 +654,16 @@ struct potentialArg *); double MovingObjectPotentialPlanarphiforce(double,double,double, struct potentialArg *); +//ChandrasekharDynamicalFrictionForce, takes vR,vT,vZ +double ChandrasekharDynamicalFrictionForceRforce(double,double,double,double, + struct potentialArg *, + double,double,double); +double ChandrasekharDynamicalFrictionForcephiforce(double,double,double,double, + struct potentialArg *, + double,double,double); +double ChandrasekharDynamicalFrictionForcezforce(double,double,double,double, + struct potentialArg *, + double,double,double); #ifdef __cplusplus } #endif diff -Nru galpy-1.5/galpy/potential/potential_c_ext/HernquistPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/HernquistPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/HernquistPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/HernquistPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -54,3 +54,13 @@ //Calculate R2deriv return -amp / a / a / a * pow(1. + R / a, -3. ); } +double HernquistPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + double amp= *args++; + double a= *args; + //Calculate density + double r= sqrt ( R * R + Z * Z ); + return amp * M_1_PI / 4. / a / a / r * pow ( 1. + r / a , -3. ); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/HomogeneousSpherePotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/HomogeneousSpherePotential.c --- galpy-1.5/galpy/potential/potential_c_ext/HomogeneousSpherePotential.c 1970-01-01 00:00:00.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/HomogeneousSpherePotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -0,0 +1,93 @@ +#include +#include +//HomogeneousSpherePotential +//3 arguments: amp, R2, R3 +double HomogeneousSpherePotentialEval(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double R2= *(args+1); + double R3= *(args+2); + //Calculate potential + double r2= R * R + Z * Z; + if ( r2 < R2 ) + return amp * ( r2 - 3. * R2 ); + else + return -2. * amp * R3 / sqrt( r2 ); +} +double HomogeneousSpherePotentialRforce(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double R2= *(args+1); + double R3= *(args+2); + //Calculate Rforce + double r2= R * R + Z * Z; + if ( r2 < R2 ) + return -2. * amp * R; + else + return -2. * amp * R3 * R / pow( r2 , 1.5 ); +} +double HomogeneousSpherePotentialPlanarRforce(double R,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double R2= *(args+1); + double R3= *(args+2); + //Calculate Rforce + double r2= R * R; + if ( r2 < R2 ) + return -2. * amp * R; + else + return -2. * amp * R3 / r2; +} +double HomogeneousSpherePotentialzforce(double R,double z,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double R2= *(args+1); + double R3= *(args+2); + //Calculate zforce + double r2= R * R + z * z; + if ( r2 < R2 ) + return -2. * amp * z; + else + return -2. * amp * R3 * z / pow ( r2 , 1.5 ); +} +double HomogeneousSpherePotentialPlanarR2deriv(double R,double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double R2= *(args+1); + double R3= *(args+2); + //Calculate R2deriv + double r2= R * R; + if ( r2 < R2 ) + return 2. * amp; + else + return -4. * amp * R3 / pow ( r2 , 1.5 ); +} +double HomogeneousSpherePotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double R2= *(args+1); + //Calculate potential + double r2= R * R + Z * Z; + if ( r2 < R2 ) + return 1.5 * amp * M_1_PI; + else + return 0.; +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/IsochronePotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/IsochronePotential.c --- galpy-1.5/galpy/potential/potential_c_ext/IsochronePotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/IsochronePotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -61,3 +61,18 @@ double rb= sqrt(r2 + b * b); return - amp * ( -pow(b,3.) - b * b * rb + 2. * r2 * rb ) * pow(rb * ( b + rb ),-3.); } +double IsochronePotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double b= *(args+1); + //Calculate potential + double r2= R * R + Z * Z; + double rb= sqrt ( r2 + b * b ); + double brbrb= ( b + rb ) * rb; + return amp * M_1_PI / 4. * ( 3. * brbrb * rb \ + - r2 * ( b + 3. * rb ) ) \ + * pow ( brbrb , -3.); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/JaffePotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/JaffePotential.c --- galpy-1.5/galpy/potential/potential_c_ext/JaffePotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/JaffePotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -55,3 +55,14 @@ //Calculate R2deriv return - amp * (a + 2. * R) * pow(R,-4.) * pow(1.+a/R,-2.); } +double JaffePotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args; + //Calculate density + double r= sqrt ( R * R + Z * Z ); + return amp * M_1_PI / 4. / a * pow ( r * ( 1. + r / a ), -2. ); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/LogarithmicHaloPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/LogarithmicHaloPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/LogarithmicHaloPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/LogarithmicHaloPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -154,3 +154,31 @@ } else return 0.; } +double LogarithmicHaloPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double q= *(args+1); + double c= *(args+2); + double onem1overb2= *(args+3); + //Calculate density + double zq= Z/q; + double R2, Rt2, denom, denom2; + double q2= q*q; + if ( onem1overb2 < 1 ) { + R2= R * R; + Rt2= R2 * (1. - onem1overb2 * pow(sin(phi),2)); + denom= 1. / ( Rt2 + zq * zq + c ); + denom2= denom * denom; + return amp * M_1_PI / 4. * ( 2. * Rt2 / R2 * ( denom - Rt2 * denom2 )\ + + denom / q2 - 2. * zq * zq * denom2 / q2 \ + - onem1overb2 \ + * ( 2. * R2 * pow ( sin ( 2. * phi ),2) / 4. * onem1overb2 \ + * denom2 + denom * cos( 2. * phi ) ) ); + } else + return amp * M_1_PI / 4. / q2 * ( ( 2. * q2 + 1. ) * c + R * R \ + + ( 2. - 1. / q2 ) * Z * Z )/ \ + pow( R * R + zq * zq + c ,2.); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/MiyamotoNagaiPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/MiyamotoNagaiPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/MiyamotoNagaiPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/MiyamotoNagaiPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -63,4 +63,24 @@ double denom= R*R+pow(a+b,2.); return amp * (pow(denom,-1.5) - 3. * R * R * pow(denom,-2.5)); } +double MiyamotoNagaiPotentialDens(double R,double z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args++; + double b= *args; + //Calculate density + double b2= b*b; + double sqrtbz= sqrt ( b2 + z * z ); + double asqrtbz= a+sqrtbz; + asqrtbz*= asqrtbz; + if ( a == 0. ) + return 3. * amp * M_1_PI / 4. * b2 * pow ( R * R + sqrtbz * sqrtbz, -2.5); + else + return amp * M_1_PI / 4. * b2 \ + * ( a * R * R + ( a + 3. * sqrtbz ) * asqrtbz ) \ + * pow ( R * R + asqrtbz,-2.5 ) * pow ( sqrtbz,-3.); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/MovingObjectPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/MovingObjectPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/MovingObjectPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/MovingObjectPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -23,9 +23,11 @@ y= R*sin(phi); constrain_range(&d_ind); // Interpolate x, y, z - obj_x= gsl_spline_eval(potentialArgs->xSpline, d_ind, potentialArgs->accx); - obj_y= gsl_spline_eval(potentialArgs->ySpline, d_ind, potentialArgs->accy); - obj_z= gsl_spline_eval(potentialArgs->zSpline, d_ind, potentialArgs->accz); + obj_x= gsl_spline_eval(*potentialArgs->spline1d,d_ind,*potentialArgs->acc1d); + obj_y= gsl_spline_eval(*(potentialArgs->spline1d+1),d_ind, + *(potentialArgs->acc1d+1)); + obj_z= gsl_spline_eval(*(potentialArgs->spline1d+2),d_ind, + *(potentialArgs->acc1d+2)); Rdist= pow(pow(x-obj_x, 2)+pow(y-obj_y, 2), 0.5); // Calculate R force RF= calcRforce(Rdist,(obj_z-z),phi,t,potentialArgs->nwrapped, @@ -47,9 +49,11 @@ y= R*sin(phi); constrain_range(&d_ind); // Interpolate x, y, z - obj_x= gsl_spline_eval(potentialArgs->xSpline, d_ind, potentialArgs->accx); - obj_y= gsl_spline_eval(potentialArgs->ySpline, d_ind, potentialArgs->accy); - obj_z= gsl_spline_eval(potentialArgs->zSpline, d_ind, potentialArgs->accz); + obj_x= gsl_spline_eval(*potentialArgs->spline1d,d_ind,*potentialArgs->acc1d); + obj_y= gsl_spline_eval(*(potentialArgs->spline1d+1),d_ind, + *(potentialArgs->acc1d+1)); + obj_z= gsl_spline_eval(*(potentialArgs->spline1d+2),d_ind, + *(potentialArgs->acc1d+2)); Rdist= pow(pow(x-obj_x, 2)+pow(y-obj_y, 2), 0.5); // Calculate z force return -amp * calczforce(Rdist,(obj_z-z),phi,t,potentialArgs->nwrapped, @@ -70,9 +74,11 @@ y= R*sin(phi); constrain_range(&d_ind); // Interpolate x, y, z - obj_x= gsl_spline_eval(potentialArgs->xSpline, d_ind, potentialArgs->accx); - obj_y= gsl_spline_eval(potentialArgs->ySpline, d_ind, potentialArgs->accy); - obj_z= gsl_spline_eval(potentialArgs->zSpline, d_ind, potentialArgs->accz); + obj_x= gsl_spline_eval(*potentialArgs->spline1d,d_ind,*potentialArgs->acc1d); + obj_y= gsl_spline_eval(*(potentialArgs->spline1d+1),d_ind, + *(potentialArgs->acc1d+1)); + obj_z= gsl_spline_eval(*(potentialArgs->spline1d+2),d_ind, + *(potentialArgs->acc1d+2)); Rdist= pow(pow(x-obj_x, 2)+pow(y-obj_y, 2), 0.5); // Calculate phiforce RF= calcRforce(Rdist,(obj_z-z),phi,t,potentialArgs->nwrapped, @@ -83,7 +89,7 @@ double MovingObjectPotentialPlanarRforce(double R, double phi, double t, struct potentialArg * potentialArgs){ - double amp,t0,tf,d_ind,x,y,obj_x,obj_y,obj_z, Rdist,RF; + double amp,t0,tf,d_ind,x,y,obj_x,obj_y,Rdist,RF; double * args= potentialArgs->args; //Get args amp= *args; @@ -94,8 +100,9 @@ y= R*sin(phi); constrain_range(&d_ind); // Interpolate x, y - obj_x= gsl_spline_eval(potentialArgs->xSpline, d_ind, potentialArgs->accx); - obj_y= gsl_spline_eval(potentialArgs->ySpline, d_ind, potentialArgs->accy); + obj_x= gsl_spline_eval(*potentialArgs->spline1d,d_ind,*potentialArgs->acc1d); + obj_y= gsl_spline_eval(*(potentialArgs->spline1d+1),d_ind, + *(potentialArgs->acc1d+1)); Rdist= pow(pow(x-obj_x, 2)+pow(y-obj_y, 2), 0.5); // Calculate R force RF= calcPlanarRforce(Rdist, phi, t, potentialArgs->nwrapped, @@ -106,7 +113,7 @@ double MovingObjectPotentialPlanarphiforce(double R, double phi, double t, struct potentialArg * potentialArgs){ - double amp,t0,tf,d_ind,x,y,obj_x,obj_y,obj_z, Rdist,RF; + double amp,t0,tf,d_ind,x,y,obj_x,obj_y,Rdist,RF; double * args= potentialArgs->args; // Get args amp= *args; @@ -117,8 +124,9 @@ y= R*sin(phi); constrain_range(&d_ind); // Interpolate x, y - obj_x= gsl_spline_eval(potentialArgs->xSpline, d_ind, potentialArgs->accx); - obj_y= gsl_spline_eval(potentialArgs->ySpline, d_ind, potentialArgs->accy); + obj_x= gsl_spline_eval(*potentialArgs->spline1d,d_ind,*potentialArgs->acc1d); + obj_y= gsl_spline_eval(*(potentialArgs->spline1d+1),d_ind, + *(potentialArgs->acc1d+1)); Rdist= pow(pow(x-obj_x, 2)+pow(y-obj_y, 2), 0.5); // Calculate phiforce RF= calcPlanarRforce(Rdist, phi, t, potentialArgs->nwrapped, diff -Nru galpy-1.5/galpy/potential/potential_c_ext/NFWPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/NFWPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/NFWPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/NFWPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -59,3 +59,15 @@ double aR2= aR*aR; return amp * (((R*(2.*a+3.*R))-2.*aR2*log(1.+R/a))/R/R/R/aR2); } +double NFWPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double a= *args; + //Calculate density + double sqrtRz= sqrt ( R * R + Z * Z ); + return amp * M_1_PI / 4. / a / a \ + / ( 1. + sqrtRz / a ) / ( 1. + sqrtRz / a ) / sqrtRz; +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/PlummerPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/PlummerPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/PlummerPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/PlummerPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -52,3 +52,13 @@ //Calculate Rforce return amp * (b2 - 2.*R*R)*pow(R*R+b2,-2.5); } +double PlummerPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double b2= *(args+1) * *(args+1); + //Calculate density + return 3. * amp *M_1_PI / 4. * b2 * pow ( R * R + Z * Z + b2 , -2.5 ); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/PowerSphericalPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/PowerSphericalPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/PowerSphericalPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/PowerSphericalPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -55,3 +55,13 @@ //Calculate R2deriv return amp * (1. - alpha ) * pow(R,-alpha); } +double PowerSphericalPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double alpha= *args; + //Calculate density + return amp * M_1_PI / 4. * ( 3. - alpha ) * pow (R*R + Z*Z, -0.5 * alpha); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/PowerSphericalPotentialwCutoff.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/PowerSphericalPotentialwCutoff.c --- galpy-1.5/galpy/potential/potential_c_ext/PowerSphericalPotentialwCutoff.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/PowerSphericalPotentialwCutoff.c 2020-04-24 19:48:38.000000000 +0000 @@ -74,3 +74,16 @@ //Calculate R2deriv return amp * ( 4. * M_PI * pow(r2,- 0.5 * alpha) * exp(-r2/rc/rc) - 2. * mass(r2,alpha,rc)/pow(r2,1.5) ); } +double PowerSphericalPotentialwCutoffDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args++; + double alpha= *args++; + double rc= *args; + //Radius + double r2= R * R + Z * Z; + double r= sqrt(r2); + return amp * pow(r,-alpha) * exp ( -r2 / rc / rc ); +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/PseudoIsothermalPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/PseudoIsothermalPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/PseudoIsothermalPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/PseudoIsothermalPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -62,3 +62,15 @@ return amp / R2 * (2. * a / R * atan(R / a) - ( 2. * a2 + R2)/(a2 + R2) ) / a; } +double PseudoIsothermalPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs){ + double * args= potentialArgs->args; + //Get args + double amp= *args; + double a= *(args+1); + double a2= a*a; + //Calculate potential + double r2= R*R+Z*Z; + return amp * M_1_PI / 4. / ( 1. + r2 / a2 ) / a2 / a; +} diff -Nru galpy-1.5/galpy/potential/potential_c_ext/SCFPotential.c galpy-1.6.0.post0/galpy/potential/potential_c_ext/SCFPotential.c --- galpy-1.5/galpy/potential/potential_c_ext/SCFPotential.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/potential_c_ext/SCFPotential.c 2020-04-24 19:48:38.000000000 +0000 @@ -42,6 +42,7 @@ //Potentials, forces, and derivative functions //LCOV_EXCL_START +// Also used for density, just with rhoTilde double computePhi(double Acos_val, double Asin_val, double mCos, double mSin, double P, double phiTilde, int m) { return (Acos_val*mCos + Asin_val*mSin)*P*phiTilde; @@ -152,6 +153,24 @@ } +//Compute rho_Tilde +void compute_rhoTilde(double r, double a, int N, int L, double* C, + double * rhoTilde) +{ + double xi; + calculateXi(r,a,&xi); + double rterms = a * pow(r + a,-3.) / r; + int n,l; + for (l = 0; l < L; l++) { + if (l != 0) + rterms *= r * a / ( ( a + r ) * ( a + r ) ); + for (n = 0; n < N; n++) + *(rhoTilde + l*N + n) = (0.5 * n * ( n + 4. * l + 3. ) + ( l + 1. ) \ + * ( 2. * l + 1. ) ) \ + * rterms*(*(C + n + l*N)); + } +} + //Compute phi_Tilde void compute_phiTilde(double r, double a, int N, int L, double* C, double * phiTilde) { @@ -813,3 +832,79 @@ computeDeriv(R, 0, phi, t,potentialArgs, &Farray[0]) ; return *(Farray + 2); } +//Compute the density +double SCFPotentialDens(double R,double Z, double phi, + double t, + struct potentialArg * potentialArgs) +{ + double * args= potentialArgs->args; + //Get args + double a = *args++; + int isNonAxi = (int)*args++; + int N = (int) *args++; + int L = (int) *args++; + int M = (int) *args++; + double* Acos = args; + double* Asin; + if (isNonAxi==1) + { + Asin = args + N*L*M; + } + //convert R,Z to r, theta + double r; + double theta; + cyl_to_spher(R, Z,&r, &theta); + double xi; + calculateXi(r, a, &xi); + + //Compute the gegenbauer polynomials and its derivative. + double *C= (double *) malloc ( N*L * sizeof(double) ); + double *rhoTilde= (double *) malloc ( N*L * sizeof(double) ); + + compute_C(xi, N, L, C); + + //Compute rhoTilde and its derivative + compute_rhoTilde(r, a, N, L, C, rhoTilde); + //Compute Associated Legendre Polynomials + int M_eff = M; + int size = 0; + + if (isNonAxi==0) { + M_eff = 1; + size = L; + } else + size = L*L - L*(L-1)/2; + + double *P= (double *) malloc ( size * sizeof(double) ); + + compute_P(cos(theta), L,M_eff, P); + + double density; + + double (*RhoTilde_Pointer[1]) = {rhoTilde}; + double (*P_Pointer[1]) = {P}; + + double Constant[1] = {1.}; + + if (isNonAxi==1) + { + double (*Eq[1])(double, double, double, double, double, double, int) = {&computePhi}; + equations e = {Eq,&RhoTilde_Pointer[0],&P_Pointer[0],&Constant[0]}; + computeNonAxi(a, N, L, M,r, theta, phi, Acos, Asin, 1, e, &density); + } + else + { + double (*Eq[1])(double, double, double) = {&computeAxiPhi}; + axi_equations e = {Eq,&RhoTilde_Pointer[0],&P_Pointer[0],&Constant[0]}; + compute(a, N, L, M,r, theta, phi, Acos, 1, e, &density); + } + + //Free memory + free(C); + free(rhoTilde); + free(P); + + return density / 2. / M_PI; + +} + diff -Nru galpy-1.5/galpy/potential/Potential.py galpy-1.6.0.post0/galpy/potential/Potential.py --- galpy-1.5/galpy/potential/Potential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/Potential.py 2020-04-24 19:48:38.000000000 +0000 @@ -19,15 +19,13 @@ import pickle from functools import wraps import warnings -import math -import numpy as nu +import numpy from scipy import optimize, integrate -import galpy.util.bovy_plot as plot -from galpy.util import bovy_coords +from ..util import bovy_plot as plot +from ..util import bovy_coords from ..util.bovy_conversion import velocity_in_kpcGyr, \ physical_conversion, potential_physical_input, freq_in_Gyr, \ get_physical -from ..util import config from ..util import galpyWarning from .plotRotcurve import plotRotcurve, vcirc from .plotEscapecurve import _INF, plotEscapecurve @@ -76,6 +74,7 @@ self.isNonAxi= False self.hasC= False self.hasC_dxdv= False + self.hasC_dens= False return None @potential_physical_input @@ -244,7 +243,7 @@ """ - r= nu.sqrt(R**2.+z**2.) + r= numpy.sqrt(R**2.+z**2.) return (self.R2deriv(R,z,phi=phi,t=t,use_physical=False)*R/r\ +self.Rzderiv(R,z,phi=phi,t=t,use_physical=False)*z/r)*R/r\ +(self.Rzderiv(R,z,phi=phi,t=t,use_physical=False)*R/r\ @@ -293,7 +292,7 @@ return (-self.Rforce(R,z,phi=phi,t=t,use_physical=False)/R +self.R2deriv(R,z,phi=phi,t=t,use_physical=False) +self.phi2deriv(R,z,phi=phi,t=t,use_physical=False)/R**2. - +self.z2deriv(R,z,phi=phi,t=t,use_physical=False))/4./nu.pi + +self.z2deriv(R,z,phi=phi,t=t,use_physical=False))/4./numpy.pi @potential_physical_input @physical_conversion('surfacedensity',pop=True) @@ -335,12 +334,12 @@ return self._amp*self._surfdens(R,z,phi=phi,t=t) except AttributeError: #Use the Poisson equation to get the surface density - return (-self.zforce(R,nu.fabs(z),phi=phi,t=t,use_physical=False) + return (-self.zforce(R,numpy.fabs(z),phi=phi,t=t,use_physical=False) +integrate.quad(\ lambda x: -self.Rforce(R,x,phi=phi,t=t,use_physical=False)/R +self.R2deriv(R,x,phi=phi,t=t,use_physical=False) +self.phi2deriv(R,x,phi=phi,t=t,use_physical=False)/R**2., - 0.,nu.fabs(z))[0])/2./nu.pi + 0.,numpy.fabs(z))[0])/2./numpy.pi def _surfdens(self,R,z,phi=0.,t=0.): """ @@ -409,19 +408,19 @@ "calculation...assuming spherical potential" " (for the mass of axisymmetric potentials" ", specify z)",galpyWarning) - return 4.*nu.pi\ + return 4.*numpy.pi\ *integrate.quad(lambda x: x**2.\ - *self.dens(x,0., + *self.dens(x,0.,t=t, use_physical=False), 0.,R)[0] else: - return 4.*nu.pi\ + return 4.*numpy.pi\ *integrate.dblquad(lambda y,x: x\ - *self.dens(x,y,use_physical=False), + *self.dens(x,y,t=t,use_physical=False), 0.,R,lambda x: 0., lambda x: z)[0] @physical_conversion('mass',pop=False) - def mvir(self,H=70.,Om=0.3,overdens=200.,wrtcrit=False, + def mvir(self,H=70.,Om=0.3,t=0.,overdens=200.,wrtcrit=False, forceint=False,ro=None,vo=None, use_physical=False): # use_physical necessary bc of pop=False, does nothing inside """ @@ -464,11 +463,11 @@ if vo is None: vo= self._vo #Evaluate the virial radius try: - rvir= self.rvir(H=H,Om=Om,overdens=overdens,wrtcrit=wrtcrit, + rvir= self.rvir(H=H,Om=Om,t=t,overdens=overdens,wrtcrit=wrtcrit, use_physical=False,ro=ro,vo=vo) except AttributeError: raise AttributeError("This potential does not have a '_scale' defined to base the concentration on or does not support calculating the virial radius") - return self.mass(rvir,forceint=forceint,use_physical=False,ro=ro,vo=vo) + return self.mass(rvir,t=t,forceint=forceint,use_physical=False,ro=ro,vo=vo) @potential_physical_input @physical_conversion('forcederivative',pop=True) @@ -578,7 +577,7 @@ except AttributeError: #pragma: no cover raise PotentialError("'_Rzderiv' function not implemented for this potential") - def normalize(self,norm,t=0.): + def normalize(self,norm): """ NAME: @@ -603,7 +602,7 @@ 2010-07-10 - Written - Bovy (NYU) """ - self._amp*= norm/nu.fabs(self.Rforce(1.,0.,t=t,use_physical=False)) + self._amp*= norm/numpy.fabs(self.Rforce(1.,0.,use_physical=False)) @potential_physical_input @physical_conversion('force',pop=True) @@ -746,7 +745,7 @@ unknown """ - from galpy.potential import toPlanarPotential + from ..potential import toPlanarPotential return toPlanarPotential(self) def toVertical(self,R,phi=None,t0=0.): @@ -776,7 +775,7 @@ unknown """ - from galpy.potential import toVerticalPotential + from ..potential import toVerticalPotential return toVerticalPotential(self,R,phi=phi,t0=t0) def plot(self,t=0.,rmin=0.,rmax=1.5,nrs=21,zmin=-0.5,zmax=0.5,nzs=21, @@ -861,9 +860,9 @@ else: if effective and Lz is None: raise RuntimeError("When effective=True, you need to specify Lz=") - Rs= nu.linspace(xrange[0],xrange[1],nrs) - zs= nu.linspace(yrange[0],yrange[1],nzs) - potRz= nu.zeros((nrs,nzs)) + Rs= numpy.linspace(xrange[0],xrange[1],nrs) + zs= numpy.linspace(yrange[0],yrange[1],nzs) + potRz= numpy.zeros((nrs,nzs)) for ii in range(nrs): for jj in range(nzs): if xy: @@ -876,10 +875,10 @@ if effective: potRz[ii,:]+= 0.5*Lz**2/Rs[ii]**2. #Don't plot outside of the desired range - potRz[Rs < rmin,:]= nu.nan - potRz[Rs > rmax,:]= nu.nan - potRz[:,zs < zmin]= nu.nan - potRz[:,zs > zmax]= nu.nan + potRz[Rs < rmin,:]= numpy.nan + potRz[Rs > rmax,:]= numpy.nan + potRz[:,zs < zmin]= numpy.nan + potRz[:,zs > zmax]= numpy.nan if not savefilename == None: print("Writing savefile "+savefilename+" ...") savefile= open(savefilename,'wb') @@ -894,7 +893,7 @@ xlabel=r"$R/R_0$" ylabel=r"$z/R_0$" if levels is None: - levels= nu.linspace(nu.nanmin(potRz),nu.nanmax(potRz),ncontours) + levels= numpy.linspace(numpy.nanmin(potRz),numpy.nanmax(potRz),ncontours) if cntrcolors is None: cntrcolors= 'k' return plot.bovy_dens2d(potRz.T,origin='lower',cmap='gist_gray',contours=True, @@ -905,7 +904,7 @@ cntrls='-', justcontours=justcontours, levels=levels,cntrcolors=cntrcolors) - + def plotDensity(self,t=0., rmin=0.,rmax=1.5,nrs=21,zmin=-0.5,zmax=0.5,nzs=21, phi=None,xy=False, @@ -965,7 +964,7 @@ @potential_physical_input @physical_conversion('velocity',pop=True) - def vcirc(self,R,phi=None): + def vcirc(self,R,phi=None,t=0.): """ NAME: @@ -982,6 +981,8 @@ phi= (None) azimuth to use for non-axisymmetric potentials + t - time (optional; can be Quantity) + OUTPUT: circular rotation velocity @@ -993,11 +994,11 @@ 2016-06-15 - Added phi= keyword for non-axisymmetric potential - Bovy (UofT) """ - return nu.sqrt(R*-self.Rforce(R,0.,phi=phi,use_physical=False)) + return numpy.sqrt(R*-self.Rforce(R,0.,phi=phi,t=t,use_physical=False)) @potential_physical_input @physical_conversion('frequency',pop=True) - def dvcircdR(self,R,phi=None): + def dvcircdR(self,R,phi=None,t=0.): """ NAME: @@ -1015,6 +1016,8 @@ phi= (None) azimuth to use for non-axisymmetric potentials + t - time (optional; can be Quantity) + OUTPUT: derivative of the circular rotation velocity wrt R @@ -1026,13 +1029,13 @@ 2016-06-28 - Added phi= keyword for non-axisymmetric potential - Bovy (UofT) """ - return 0.5*(-self.Rforce(R,0.,phi=phi,use_physical=False)\ - +R*self.R2deriv(R,0.,phi=phi,use_physical=False))\ - /self.vcirc(R,phi=phi,use_physical=False) + return 0.5*(-self.Rforce(R,0.,phi=phi,t=t,use_physical=False)\ + +R*self.R2deriv(R,0.,phi=phi,t=t,use_physical=False))\ + /self.vcirc(R,phi=phi,t=t,use_physical=False) @potential_physical_input @physical_conversion('frequency',pop=True) - def omegac(self,R): + def omegac(self,R,t=0.): """ NAME: @@ -1046,6 +1049,8 @@ INPUT: R - Galactocentric radius (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -1056,11 +1061,11 @@ 2011-10-09 - Written - Bovy (IAS) """ - return nu.sqrt(-self.Rforce(R,0.,use_physical=False)/R) + return numpy.sqrt(-self.Rforce(R,0.,t=t,use_physical=False)/R) @potential_physical_input @physical_conversion('frequency',pop=True) - def epifreq(self,R): + def epifreq(self,R,t=0.): """ NAME: @@ -1074,6 +1079,8 @@ INPUT: R - Galactocentric radius (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -1084,12 +1091,12 @@ 2011-10-09 - Written - Bovy (IAS) """ - return nu.sqrt(self.R2deriv(R,0.,use_physical=False)\ - -3./R*self.Rforce(R,0.,use_physical=False)) + return numpy.sqrt(self.R2deriv(R,0.,t=t,use_physical=False)\ + -3./R*self.Rforce(R,0.,t=t,use_physical=False)) @potential_physical_input @physical_conversion('frequency',pop=True) - def verticalfreq(self,R): + def verticalfreq(self,R,t=0.): """ NAME: @@ -1103,6 +1110,8 @@ INPUT: R - Galactocentric radius (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -1113,10 +1122,10 @@ 2012-07-25 - Written - Bovy (IAS@MPIA) """ - return nu.sqrt(self.z2deriv(R,0.,use_physical=False)) + return numpy.sqrt(self.z2deriv(R,0.,t=t,use_physical=False)) @physical_conversion('position',pop=True) - def lindbladR(self,OmegaP,m=2,**kwargs): + def lindbladR(self,OmegaP,m=2,t=0.,**kwargs): """ NAME: @@ -1134,6 +1143,8 @@ m= order of the resonance (as in m(O-Op)=kappa (negative m for outer) use m='corotation' for corotation +scipy.optimize.brentq xtol,rtol,maxiter kwargs + + t - time (optional; can be Quantity) OUTPUT: @@ -1146,11 +1157,11 @@ """ if _APY_LOADED and isinstance(OmegaP,units.Quantity): OmegaP= OmegaP.to(1/units.Gyr).value/freq_in_Gyr(self._vo,self._ro) - return lindbladR(self,OmegaP,m=m,use_physical=False,**kwargs) + return lindbladR(self,OmegaP,m=m,t=t,use_physical=False,**kwargs) @potential_physical_input @physical_conversion('velocity',pop=True) - def vesc(self,R): + def vesc(self,R,t=0.): """ NAME: @@ -1165,6 +1176,8 @@ R - Galactocentric radius (can be Quantity) + t - time (optional; can be Quantity) + OUTPUT: escape velocity @@ -1174,11 +1187,11 @@ 2011-10-09 - Written - Bovy (IAS) """ - return nu.sqrt(2.*(self(_INF,0.,use_physical=False)\ - -self(R,0.,use_physical=False))) + return numpy.sqrt(2.*(self(_INF,0.,t=t,use_physical=False)\ + -self(R,0.,t=t,use_physical=False))) @physical_conversion('position',pop=True) - def rl(self,lz): + def rl(self,lz,t=0.): """ NAME: @@ -1192,6 +1205,8 @@ lz - Angular momentum (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -1209,11 +1224,11 @@ """ if _APY_LOADED and isinstance(lz,units.Quantity): lz= lz.to(units.km/units.s*units.kpc).value/self._vo/self._ro - return rl(self,lz,use_physical=False) + return rl(self,lz,t=t,use_physical=False) @potential_physical_input @physical_conversion('dimensionless',pop=True) - def flattening(self,R,z): + def flattening(self,R,z,t=0.): """ NAME: @@ -1229,6 +1244,8 @@ R - Galactocentric radius (can be Quantity) z - height (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -1239,11 +1256,11 @@ 2012-09-13 - Written - Bovy (IAS) """ - return nu.sqrt(nu.fabs(z/R*self.Rforce(R,z,use_physical=False)\ - /self.zforce(R,z,use_physical=False))) + return numpy.sqrt(numpy.fabs(z/R*self.Rforce(R,z,t=t,use_physical=False)\ + /self.zforce(R,z,t=t,use_physical=False))) @physical_conversion('velocity',pop=True) - def vterm(self,l,deg=True): + def vterm(self,l,t=0.,deg=True): """ NAME: @@ -1258,6 +1275,8 @@ l - Galactic longitude [deg/rad; can be Quantity) + t - time (optional; can be Quantity) + deg= if True (default), l in deg OUTPUT: @@ -1273,11 +1292,11 @@ l= l.to(units.rad).value deg= False if deg: - sinl= nu.sin(l/180.*nu.pi) + sinl= numpy.sin(l/180.*numpy.pi) else: - sinl= nu.sin(l) - return sinl*(self.omegac(nu.fabs(sinl),use_physical=False)\ - -self.omegac(1.,use_physical=False)) + sinl= numpy.sin(l) + return sinl*(self.omegac(numpy.fabs(sinl),t=t,use_physical=False)\ + -self.omegac(1.,t=t,use_physical=False)) def plotRotcurve(self,*args,**kwargs): """ @@ -1343,7 +1362,7 @@ """ return plotEscapecurve(self.toPlanar(),*args,**kwargs) - def conc(self,H=70.,Om=0.3,overdens=200.,wrtcrit=False, + def conc(self,H=70.,Om=0.3,t=0.,overdens=200.,wrtcrit=False, ro=None,vo=None): """ NAME: @@ -1359,6 +1378,8 @@ H= (default: 70) Hubble constant in km/s/Mpc Om= (default: 0.3) Omega matter + + t - time (optional; can be Quantity) overdens= (200) overdensity which defines the virial radius @@ -1380,7 +1401,7 @@ if ro is None: ro= self._ro if vo is None: vo= self._vo try: - return self.rvir(H=H,Om=Om,overdens=overdens,wrtcrit=wrtcrit, + return self.rvir(H=H,Om=Om,t=t,overdens=overdens,wrtcrit=wrtcrit, ro=ro,vo=vo,use_physical=False)/self._scale except AttributeError: raise AttributeError("This potential does not have a '_scale' defined to base the concentration on or does not support calculating the virial radius") @@ -1486,7 +1507,7 @@ if M is None: #Make sure an object mass is given raise PotentialError("Mass parameter M= needs to be set to compute tidal radius") - r= nu.sqrt(R**2.+z**2.) + r= numpy.sqrt(R**2.+z**2.) omegac2= -self.rforce(R,z,phi=phi,t=t,use_physical=False)/r d2phidr2= self.r2deriv(R,z,phi=phi,t=t,use_physical=False) return (M/(omegac2-d2phidr2))**(1./3.) @@ -1537,8 +1558,8 @@ Rphideriv= self.Rphideriv(R,z,phi=phi,t=t,use_physical=False) #Temporarily set zphideriv to zero until zphideriv is added to Class zphideriv=0.0 - cosphi=nu.cos(phi) - sinphi=nu.sin(phi) + cosphi=numpy.cos(phi) + sinphi=numpy.sin(phi) cos2phi=cosphi**2.0 sin2phi=sinphi**2.0 R2=R**2.0 @@ -1557,9 +1578,9 @@ txz=tzx tyz=tzy tzz=z2deriv - tij=-nu.array([[txx,txy,txz],[tyx,tyy,tyz],[tzx,tzy,tzz]]) + tij=-numpy.array([[txx,txy,txz],[tyx,tyy,tyz],[tzx,tzy,tzz]]) if eigenval: - return nu.linalg.eigvals(tij) + return numpy.linalg.eigvals(tij) else: return tij @@ -2344,16 +2365,16 @@ else: if effective and Lz is None: raise RuntimeError("When effective=True, you need to specify Lz=") - Rs= nu.linspace(rmin,rmax,nrs) - zs= nu.linspace(zmin,zmax,nzs) - potRz= nu.zeros((nrs,nzs)) + Rs= numpy.linspace(rmin,rmax,nrs) + zs= numpy.linspace(zmin,zmax,nzs) + potRz= numpy.zeros((nrs,nzs)) for ii in range(nrs): for jj in range(nzs): if xy: R,phi,z= bovy_coords.rect_to_cyl(Rs[ii],zs[jj],0.) else: R,z= Rs[ii], zs[jj] - potRz[ii,jj]= evaluatePotentials(Pot,nu.fabs(R), + potRz[ii,jj]= evaluatePotentials(Pot,numpy.fabs(R), z,phi=phi,t=t, use_physical=False) if effective: @@ -2374,7 +2395,7 @@ xlabel=r"$R/R_0$" ylabel=r"$z/R_0$" if levels is None: - levels= nu.linspace(nu.nanmin(potRz),nu.nanmax(potRz),ncontours) + levels= numpy.linspace(numpy.nanmin(potRz),numpy.nanmax(potRz),ncontours) if cntrcolors is None: cntrcolors= 'k' return plot.bovy_dens2d(potRz.T,origin='lower',cmap='gist_gray',contours=True, @@ -2460,16 +2481,16 @@ zs= pickle.load(savefile) savefile.close() else: - Rs= nu.linspace(rmin,rmax,nrs) - zs= nu.linspace(zmin,zmax,nzs) - potRz= nu.zeros((nrs,nzs)) + Rs= numpy.linspace(rmin,rmax,nrs) + zs= numpy.linspace(zmin,zmax,nzs) + potRz= numpy.zeros((nrs,nzs)) for ii in range(nrs): for jj in range(nzs): if xy: R,phi,z= bovy_coords.rect_to_cyl(Rs[ii],zs[jj],0.) else: R,z= Rs[ii], zs[jj] - potRz[ii,jj]= evaluateDensities(Pot,nu.fabs(R),z,phi=phi, + potRz[ii,jj]= evaluateDensities(Pot,numpy.fabs(R),z,phi=phi, t=t, use_physical=False) if not savefilename == None: @@ -2482,7 +2503,7 @@ if aspect is None: aspect=.75*(rmax-rmin)/(zmax-zmin) if log: - potRz= nu.log(potRz) + potRz= numpy.log(potRz) if xy: xlabel= r'$x/R_0$' ylabel= r'$y/R_0$' @@ -2497,12 +2518,12 @@ yrange=[zmin,zmax], cntrls='-', justcontours=justcontours, - levels=nu.linspace(nu.nanmin(potRz),nu.nanmax(potRz), + levels=numpy.linspace(numpy.nanmin(potRz),numpy.nanmax(potRz), ncontours)) @potential_physical_input @physical_conversion('frequency',pop=True) -def epifreq(Pot,R): +def epifreq(Pot,R,t=0.): """ NAME: @@ -2518,6 +2539,8 @@ Pot - Potential instance or list thereof R - Galactocentric radius (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -2530,21 +2553,21 @@ """ from .planarPotential import planarPotential if isinstance(Pot,(Potential,planarPotential)): - return Pot.epifreq(R,use_physical=False) - from galpy.potential import evaluateplanarRforces, evaluateplanarR2derivs - from galpy.potential import PotentialError + return Pot.epifreq(R,t=t,use_physical=False) + from ..potential import evaluateplanarRforces, evaluateplanarR2derivs + from ..potential import PotentialError try: - return nu.sqrt(evaluateplanarR2derivs(Pot,R,use_physical=False) - -3./R*evaluateplanarRforces(Pot,R,use_physical=False)) + return numpy.sqrt(evaluateplanarR2derivs(Pot,R,t=t,use_physical=False) + -3./R*evaluateplanarRforces(Pot,R,t=t,use_physical=False)) except PotentialError: - from galpy.potential import RZToplanarPotential + from ..potential import RZToplanarPotential Pot= RZToplanarPotential(Pot) - return nu.sqrt(evaluateplanarR2derivs(Pot,R,use_physical=False) - -3./R*evaluateplanarRforces(Pot,R,use_physical=False)) + return numpy.sqrt(evaluateplanarR2derivs(Pot,R,t=t,use_physical=False) + -3./R*evaluateplanarRforces(Pot,R,t=t,use_physical=False)) @potential_physical_input @physical_conversion('frequency',pop=True) -def verticalfreq(Pot,R): +def verticalfreq(Pot,R,t=0.): """ NAME: @@ -2560,6 +2583,8 @@ Pot - Potential instance or list thereof R - Galactocentric radius (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -2572,12 +2597,12 @@ """ from .planarPotential import planarPotential if isinstance(Pot,(Potential,planarPotential)): - return Pot.verticalfreq(R,use_physical=False) - return nu.sqrt(evaluatez2derivs(Pot,R,0.,use_physical=False)) + return Pot.verticalfreq(R,t=t,use_physical=False) + return numpy.sqrt(evaluatez2derivs(Pot,R,0.,t=t,use_physical=False)) @potential_physical_input @physical_conversion('dimensionless',pop=True) -def flattening(Pot,R,z): +def flattening(Pot,R,z,t=0.): """ NAME: @@ -2595,6 +2620,8 @@ R - Galactocentric radius (can be Quantity) z - height (can be Quantity) + + t - time (optional; can be Quantity) OUTPUT: @@ -2605,11 +2632,11 @@ 2012-09-13 - Written - Bovy (IAS) """ - return nu.sqrt(nu.fabs(z/R*evaluateRforces(Pot,R,z,use_physical=False)\ - /evaluatezforces(Pot,R,z,use_physical=False))) + return numpy.sqrt(numpy.fabs(z/R*evaluateRforces(Pot,R,z,t=t,use_physical=False)\ + /evaluatezforces(Pot,R,z,t=t,use_physical=False))) @physical_conversion('velocity',pop=True) -def vterm(Pot,l,deg=True): +def vterm(Pot,l,t=0.,deg=True): """ NAME: @@ -2625,6 +2652,8 @@ Pot - Potential instance l - Galactic longitude [deg/rad; can be Quantity) + + t - time (optional; can be Quantity) deg= if True (default), l in deg @@ -2642,14 +2671,14 @@ l= l.to(units.rad).value deg= False if deg: - sinl= nu.sin(l/180.*nu.pi) + sinl= numpy.sin(l/180.*numpy.pi) else: - sinl= nu.sin(l) - return sinl*(omegac(Pot,sinl,use_physical=False) - -omegac(Pot,1.,use_physical=False)) + sinl= numpy.sin(l) + return sinl*(omegac(Pot,sinl,t=t,use_physical=False) + -omegac(Pot,1.,t=t,use_physical=False)) @physical_conversion('position',pop=True) -def rl(Pot,lz): +def rl(Pot,lz,t=0.): """ NAME: @@ -2665,6 +2694,8 @@ lz - Angular momentum (can be Quantity) + t - time (optional; can be Quantity) + OUTPUT: radius @@ -2686,32 +2717,33 @@ elif hasattr(Pot[0],'_ro'): lz= lz.to(units.km/units.s*units.kpc).value/Pot[0]._vo/Pot[0]._ro #Find interval - rstart= _rlFindStart(math.fabs(lz),#assumes vo=1. - math.fabs(lz), - Pot) + rstart= _rlFindStart(numpy.fabs(lz),#assumes vo=1. + numpy.fabs(lz), + Pot, t=t) try: return optimize.brentq(_rlfunc,10.**-5.,rstart, - args=(math.fabs(lz), - Pot), + args=(numpy.fabs(lz), + Pot, + t), maxiter=200,disp=False) except ValueError: #Probably lz small and starting lz to great rlower= _rlFindStart(10.**-5., - math.fabs(lz), - Pot,lower=True) + numpy.fabs(lz), + Pot,t=t,lower=True) return optimize.brentq(_rlfunc,rlower,rstart, - args=(math.fabs(lz), - Pot)) + args=(numpy.fabs(lz), + Pot,t)) -def _rlfunc(rl,lz,pot): +def _rlfunc(rl,lz,pot,t=0.): """Function that gives rvc-lz""" - thisvcirc= vcirc(pot,rl,use_physical=False) + thisvcirc= vcirc(pot,rl,t=t,use_physical=False) return rl*thisvcirc-lz -def _rlFindStart(rl,lz,pot,lower=False): +def _rlFindStart(rl,lz,pot,t=0.,lower=False): """find a starting interval for rl""" rtry= 2.*rl - while (2.*lower-1.)*_rlfunc(rtry,lz,pot) > 0.: + while (2.*lower-1.)*_rlfunc(rtry,lz,pot,t=t) > 0.: if lower: rtry/= 2. else: @@ -2719,7 +2751,7 @@ return rtry @physical_conversion('position',pop=True) -def lindbladR(Pot,OmegaP,m=2,**kwargs): +def lindbladR(Pot,OmegaP,m=2,t=0.,**kwargs): """ NAME: @@ -2739,6 +2771,8 @@ use m='corotation' for corotation +scipy.optimize.brentq xtol,rtol,maxiter kwargs + t - time (optional; can be Quantity) + OUTPUT: radius of Linblad resonance, None if there is no resonance @@ -2765,7 +2799,7 @@ if corotation: try: out= optimize.brentq(_corotationR_eq,0.0000001,1000., - args=(Pot,OmegaP),**kwargs) + args=(Pot,OmegaP,t),**kwargs) except ValueError: return None except RuntimeError: #pragma: no cover @@ -2774,22 +2808,22 @@ else: try: out= optimize.brentq(_lindbladR_eq,0.0000001,1000., - args=(Pot,OmegaP,m),**kwargs) + args=(Pot,OmegaP,m,t),**kwargs) except ValueError: return None except RuntimeError: #pragma: no cover raise return out -def _corotationR_eq(R,Pot,OmegaP): - return omegac(Pot,R,use_physical=False)-OmegaP -def _lindbladR_eq(R,Pot,OmegaP,m): - return m*(omegac(Pot,R,use_physical=False)-OmegaP)\ - -epifreq(Pot,R,use_physical=False) +def _corotationR_eq(R,Pot,OmegaP,t=0.): + return omegac(Pot,R,t=t,use_physical=False)-OmegaP +def _lindbladR_eq(R,Pot,OmegaP,m,t=0.): + return m*(omegac(Pot,R,t=t,use_physical=False)-OmegaP)\ + -epifreq(Pot,R,t=t,use_physical=False) @potential_physical_input @physical_conversion('frequency',pop=True) -def omegac(Pot,R): +def omegac(Pot,R,t=0.): """ NAME: @@ -2806,6 +2840,8 @@ R - Galactocentric radius (can be Quantity) + t - time (optional; can be Quantity) + OUTPUT: circular angular speed @@ -2815,13 +2851,13 @@ 2011-10-09 - Written - Bovy (IAS) """ - from galpy.potential import evaluateplanarRforces + from ..potential import evaluateplanarRforces try: - return nu.sqrt(-evaluateplanarRforces(Pot,R,use_physical=False)/R) + return numpy.sqrt(-evaluateplanarRforces(Pot,R,t=t,use_physical=False)/R) except PotentialError: - from galpy.potential import RZToplanarPotential + from ..potential import RZToplanarPotential Pot= RZToplanarPotential(Pot) - return nu.sqrt(-evaluateplanarRforces(Pot,R,use_physical=False)/R) + return numpy.sqrt(-evaluateplanarRforces(Pot,R,t=t,use_physical=False)/R) def nemo_accname(Pot): """ @@ -3040,7 +3076,7 @@ else: return Pot -def _check_c(Pot,dxdv=False): +def _check_c(Pot,dxdv=False,dens=False): """ NAME: @@ -3057,6 +3093,8 @@ dxdv= (False) check whether the potential has dxdv implementation + dens= (False) check whether the potential has its density implemented in C + OUTPUT: True if a C implementation exists, False otherwise @@ -3069,16 +3107,18 @@ """ Pot= flatten(Pot) - from galpy.potential import planarPotential, linearPotential + from ..potential import planarPotential, linearPotential if dxdv: hasC_attr= 'hasC_dxdv' + elif dens: hasC_attr= 'hasC_dens' else: hasC_attr= 'hasC' from .WrapperPotential import parentWrapperPotential if isinstance(Pot,list): - return nu.all(nu.array([_check_c(p,dxdv=dxdv) for p in Pot], + return numpy.all(numpy.array([_check_c(p,dxdv=dxdv,dens=dens) + for p in Pot], dtype='bool')) elif isinstance(Pot,parentWrapperPotential): return bool(Pot.__dict__[hasC_attr]*_check_c(Pot._pot)) - elif isinstance(Pot,Potential) or isinstance(Pot,planarPotential) \ + elif isinstance(Pot,Force) or isinstance(Pot,planarPotential) \ or isinstance(Pot,linearPotential): return Pot.__dict__[hasC_attr] @@ -3102,9 +3142,9 @@ 2016-04-19 - Written - Bovy (UofT) """ - from galpy.potential import planarPotential, linearPotential + from ..potential import planarPotential, linearPotential if isinstance(Pot,list): - return nu.amin(nu.array([_dim(p) for p in Pot],dtype='int')) + return numpy.amin(numpy.array([_dim(p) for p in Pot],dtype='int')) elif isinstance(Pot,(Potential,planarPotential,linearPotential, DissipativeForce)): return Pot.dim @@ -3135,7 +3175,7 @@ isList= isinstance(Pot,list) if isList: isAxis= [not _isNonAxi(p) for p in Pot] - nonAxi= not nu.prod(nu.array(isAxis)) + nonAxi= not numpy.prod(numpy.array(isAxis)) else: nonAxi= Pot.isNonAxi return nonAxi @@ -3193,7 +3233,7 @@ if M is None: #Make sure an object mass is given raise PotentialError("Mass parameter M= needs to be set to compute tidal radius") - r= nu.sqrt(R**2.+z**2.) + r= numpy.sqrt(R**2.+z**2.) omegac2=-evaluaterforces(Pot,R,z,phi=phi,t=t,use_physical=False)/r d2phidr2= evaluater2derivs(Pot,R,z,phi=phi,t=t,use_physical=False) return (M/(omegac2-d2phidr2))**(1./3.) @@ -3246,8 +3286,8 @@ Rphideriv= evaluateRphiderivs(Pot,R,z,phi=phi,t=t,use_physical=False) #Temporarily set zphideriv to zero until zphideriv is added to Class zphideriv=0.0 - cosphi=nu.cos(phi) - sinphi=nu.sin(phi) + cosphi=numpy.cos(phi) + sinphi=numpy.sin(phi) cos2phi=cosphi**2.0 sin2phi=sinphi**2.0 R2=R**2.0 @@ -3265,8 +3305,8 @@ txz= tzx tyz= tzy tzz=z2deriv - tij= -nu.array([[txx,txy,txz],[tyx,tyy,tyz],[tzx,tzy,tzz]]) + tij= -numpy.array([[txx,txy,txz],[tyx,tyy,tyz],[tzx,tzy,tzz]]) if eigenval: - return nu.linalg.eigvals(tij) + return numpy.linalg.eigvals(tij) else: return tij diff -Nru galpy-1.5/galpy/potential/PowerSphericalPotential.py galpy-1.6.0.post0/galpy/potential/PowerSphericalPotential.py --- galpy-1.5/galpy/potential/PowerSphericalPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/PowerSphericalPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -6,7 +6,7 @@ # rho(r)= --------- # r^\alpha ############################################################################### -import numpy as nu +import numpy from scipy import special from .Potential import Potential, _APY_LOADED if _APY_LOADED: @@ -57,13 +57,14 @@ self.alpha= alpha # Back to old definition if self.alpha != 3.: - self._amp*= r1**(self.alpha-3.)*4.*nu.pi/(3.-self.alpha) + self._amp*= r1**(self.alpha-3.)*4.*numpy.pi/(3.-self.alpha) if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): self.normalize(normalize) self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True def _evaluate(self,R,z,phi=0.,t=0.): """ @@ -82,7 +83,7 @@ 2010-07-10 - Started - Bovy (NYU) """ if self.alpha == 2.: - return nu.log(R**2.+z**2.)/2. + return numpy.log(R**2.+z**2.)/2. else: return -(R**2.+z**2.)**(1.-self.alpha/2.)/(self.alpha-2.) @@ -193,8 +194,8 @@ HISTORY: 2013-01-09 - Written - Bovy (IAS) """ - r= nu.sqrt(R**2.+z**2.) - return (3.-self.alpha)/4./nu.pi/r**self.alpha + r= numpy.sqrt(R**2.+z**2.) + return (3.-self.alpha)/4./numpy.pi/r**self.alpha def _surfdens(self,R,z,phi=0.,t=0.): """ @@ -212,7 +213,7 @@ HISTORY: 2018-08-19 - Written - Bovy (UofT) """ - return (3.-self.alpha)/2./nu.pi*z*R**-self.alpha\ + return (3.-self.alpha)/2./numpy.pi*z*R**-self.alpha\ *special.hyp2f1(0.5,self.alpha/2.,1.5,-(z/R)**2) class KeplerPotential(PowerSphericalPotential): diff -Nru galpy-1.5/galpy/potential/PowerSphericalPotentialwCutoff.py galpy-1.6.0.post0/galpy/potential/PowerSphericalPotentialwCutoff.py --- galpy-1.5/galpy/potential/PowerSphericalPotentialwCutoff.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/PowerSphericalPotentialwCutoff.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,8 +5,8 @@ # rho(r)= --------- e^{-(r/rc)^2} # r^\alpha ############################################################################### -import numpy as nu -from scipy import special, integrate +import numpy +from scipy import special from .Potential import Potential, kms_to_kpcGyrDecorator, \ _APY_LOADED if _APY_LOADED: @@ -70,6 +70,7 @@ self.normalize(normalize) self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True self._nemo_accname= 'PowSphwCut' def _evaluate(self,R,z,phi=0.,t=0.): @@ -88,8 +89,8 @@ HISTORY: 2013-06-28 - Started - Bovy (IAS) """ - r= nu.sqrt(R**2.+z**2.) - return 2.*nu.pi*self.rc**(3.-self.alpha)/r*(r/self.rc*special.gamma(1.-self.alpha/2.)*special.gammainc(1.-self.alpha/2.,(r/self.rc)**2.)-special.gamma(1.5-self.alpha/2.)*special.gammainc(1.5-self.alpha/2.,(r/self.rc)**2.)) + r= numpy.sqrt(R**2.+z**2.) + return 2.*numpy.pi*self.rc**(3.-self.alpha)/r*(r/self.rc*special.gamma(1.-self.alpha/2.)*special.gammainc(1.-self.alpha/2.,(r/self.rc)**2.)-special.gamma(1.5-self.alpha/2.)*special.gammainc(1.5-self.alpha/2.,(r/self.rc)**2.)) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -107,7 +108,7 @@ HISTORY: 2013-06-26 - Written - Bovy (IAS) """ - r= nu.sqrt(R*R+z*z) + r= numpy.sqrt(R*R+z*z) return -self._mass(r)*R/r**3. def _zforce(self,R,z,phi=0.,t=0.): @@ -126,7 +127,7 @@ HISTORY: 2013-06-26 - Written - Bovy (IAS) """ - r= nu.sqrt(R*R+z*z) + r= numpy.sqrt(R*R+z*z) return -self._mass(r)*z/r**3. def _R2deriv(self,R,z,phi=0.,t=0.): @@ -145,8 +146,8 @@ HISTORY: 2013-06-28 - Written - Bovy (IAS) """ - r= nu.sqrt(R*R+z*z) - return 4.*nu.pi*r**(-2.-self.alpha)*nu.exp(-(r/self.rc)**2.)*R**2.\ + r= numpy.sqrt(R*R+z*z) + return 4.*numpy.pi*r**(-2.-self.alpha)*numpy.exp(-(r/self.rc)**2.)*R**2.\ +self._mass(r)/r**5.*(z**2.-2.*R**2.) def _z2deriv(self,R,z,phi=0.,t=0.): @@ -165,8 +166,8 @@ HISTORY: 2013-06-28 - Written - Bovy (IAS) """ - r= nu.sqrt(R*R+z*z) - return 4.*nu.pi*r**(-2.-self.alpha)*nu.exp(-(r/self.rc)**2.)*z**2.\ + r= numpy.sqrt(R*R+z*z) + return 4.*numpy.pi*r**(-2.-self.alpha)*numpy.exp(-(r/self.rc)**2.)*z**2.\ +self._mass(r)/r**5.*(R**2.-2.*z**2.) def _Rzderiv(self,R,z,phi=0.,t=0.): @@ -185,8 +186,8 @@ HISTORY: 2013-08-28 - Written - Bovy (IAS) """ - r= nu.sqrt(R*R+z*z) - return R*z*(4.*nu.pi*r**(-2.-self.alpha)*nu.exp(-(r/self.rc)**2.) + r= numpy.sqrt(R*R+z*z) + return R*z*(4.*numpy.pi*r**(-2.-self.alpha)*numpy.exp(-(r/self.rc)**2.) -3.*self._mass(r)/r**5.) def _dens(self,R,z,phi=0.,t=0.): @@ -205,8 +206,8 @@ HISTORY: 2013-06-28 - Written - Bovy (IAS) """ - r= nu.sqrt(R**2.+z**2.) - return 1./r**self.alpha*nu.exp(-(r/self.rc)**2.) + r= numpy.sqrt(R**2.+z**2.) + return 1./r**self.alpha*numpy.exp(-(r/self.rc)**2.) def _mass(self,R,z=0.,t=0.): """ @@ -224,8 +225,8 @@ 2013-XX-XX - Written - Bovy (IAS) """ if z is None: r= R - else: r= nu.sqrt(R**2.+z**2.) - return 2.*nu.pi*self.rc**(3.-self.alpha)*special.gammainc(1.5-self.alpha/2.,(r/self.rc)**2.)*special.gamma(1.5-self.alpha/2.) + else: r= numpy.sqrt(R**2.+z**2.) + return 2.*numpy.pi*self.rc**(3.-self.alpha)*special.gammainc(1.5-self.alpha/2.,(r/self.rc)**2.)*special.gamma(1.5-self.alpha/2.) @kms_to_kpcGyrDecorator def _nemo_accpars(self,vo,ro): diff -Nru galpy-1.5/galpy/potential/PseudoIsothermalPotential.py galpy-1.6.0.post0/galpy/potential/PseudoIsothermalPotential.py --- galpy-1.5/galpy/potential/PseudoIsothermalPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/PseudoIsothermalPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -2,7 +2,7 @@ # PseudoIsothermalPotential.py: class that implements the pseudo-isothermal # halo potential ############################################################################### -import numpy as nu +import numpy from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units @@ -49,6 +49,7 @@ a= a.to(units.kpc).value/self._ro self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True self._a= a self._a2= a**2. self._a3= a**3. @@ -75,9 +76,9 @@ 2015-12-04 - Started - Bovy (UofT) """ r2= R**2.+z**2. - r= nu.sqrt(r2) - return (0.5*nu.log(1+r2/self._a2)\ - +self._a/r*nu.arctan(r/self._a))/self._a + r= numpy.sqrt(r2) + return (0.5*numpy.log(1+r2/self._a2)\ + +self._a/r*numpy.arctan(r/self._a))/self._a def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -96,8 +97,8 @@ 2015-12-04 - Started - Bovy (UofT) """ r2= R**2.+z**2. - r= nu.sqrt(r2) - return -(1./r-self._a/r2*nu.arctan(r/self._a))/self._a*R/r + r= numpy.sqrt(r2) + return -(1./r-self._a/r2*numpy.arctan(r/self._a))/self._a*R/r def _zforce(self,R,z,phi=0.,t=0.): """ @@ -116,8 +117,8 @@ 2015-12-04 - Started - Bovy (UofT) """ r2= R**2.+z**2. - r= nu.sqrt(r2) - return -(1./r-self._a/r2*nu.arctan(r/self._a))/self._a*z/r + r= numpy.sqrt(r2) + return -(1./r-self._a/r2*numpy.arctan(r/self._a))/self._a*z/r def _dens(self,R,z,phi=0.,t=0.): """ @@ -135,7 +136,7 @@ HISTORY: 2015-12-04 - Started - Bovy (UofT) """ - return 1./(1.+(R**2.+z**2.)/self._a2)/4./nu.pi/self._a3 + return 1./(1.+(R**2.+z**2.)/self._a2)/4./numpy.pi/self._a3 def _R2deriv(self,R,z,phi=0.,t=0.): """ @@ -154,9 +155,9 @@ 2011-10-09 - Written - Bovy (IAS) """ r2= R**2.+z**2. - r= nu.sqrt(r2) + r= numpy.sqrt(r2) return (1./r2*(1.-R**2./r2*(3.*self._a2+2.*r2)/(self._a2+r2))\ - +self._a/r2/r*(3.*R**2./r2-1.)*nu.arctan(r/self._a))\ + +self._a/r2/r*(3.*R**2./r2-1.)*numpy.arctan(r/self._a))\ /self._a def _z2deriv(self,R,z,phi=0.,t=0.): @@ -176,9 +177,9 @@ 2012-07-25 - Written - Bovy (IAS@MPIA) """ r2= R**2.+z**2. - r= nu.sqrt(r2) + r= numpy.sqrt(r2) return (1./r2*(1.-z**2./r2*(3.*self._a2+2.*r2)/(self._a2+r2))\ - +self._a/r2/r*(3.*z**2./r2-1.)*nu.arctan(r/self._a))\ + +self._a/r2/r*(3.*z**2./r2-1.)*numpy.arctan(r/self._a))\ /self._a def _Rzderiv(self,R,z,phi=0.,t=0.): @@ -198,8 +199,8 @@ 2013-08-28 - Written - Bovy (IAS) """ r2= R**2.+z**2. - r= nu.sqrt(r2) - return (3.*self._a/r2/r2*nu.arctan(r/self._a)\ + r= numpy.sqrt(r2) + return (3.*self._a/r2/r2*numpy.arctan(r/self._a)\ -1./r2/r*((3.*self._a2+2.*r2)/(r2+self._a2)))*R*z/r\ /self._a diff -Nru galpy-1.5/galpy/potential/RazorThinExponentialDiskPotential.py galpy-1.6.0.post0/galpy/potential/RazorThinExponentialDiskPotential.py --- galpy-1.5/galpy/potential/RazorThinExponentialDiskPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/RazorThinExponentialDiskPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -4,10 +4,8 @@ # # rho(R,z) = rho_0 e^-R/h_R delta(z) ############################################################################### -import numpy as nu -import warnings -from scipy import special, integrate -from galpy.util import galpyWarning +import numpy +from scipy import special from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units @@ -67,13 +65,13 @@ self._alpha= 1./self._hr self._maxiter= maxiter self._tol= tol - self._glx, self._glw= nu.polynomial.legendre.leggauss(self._glorder) + self._glx, self._glw= numpy.polynomial.legendre.leggauss(self._glorder) if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): #pragma: no cover self.normalize(normalize) #Load Kepler potential for large R - #self._kp= KeplerPotential(normalize=4.*nu.pi/self._alpha**2./self._beta) + #self._kp= KeplerPotential(normalize=4.*numpy.pi/self._alpha**2./self._beta) def _evaluate(self,R,z,phi=0.,t=0.): """ @@ -93,16 +91,16 @@ """ if self._new: #if R > 6.: return self._kp(R,z) - if nu.fabs(z) < 10.**-6.: + if numpy.fabs(z) < 10.**-6.: y= 0.5*self._alpha*R - return -nu.pi*R*(special.i0(y)*special.k1(y)-special.i1(y)*special.k0(y)) + return -numpy.pi*R*(special.i0(y)*special.k1(y)-special.i1(y)*special.k0(y)) kalphamax= 10. ks= kalphamax*0.5*(self._glx+1.) weights= kalphamax*self._glw - sqrtp= nu.sqrt(z**2.+(ks+R)**2.) - sqrtm= nu.sqrt(z**2.+(ks-R)**2.) - evalInt= nu.arcsin(2.*ks/(sqrtp+sqrtm))*ks*special.k0(self._alpha*ks) - return -2.*self._alpha*nu.sum(weights*evalInt) + sqrtp= numpy.sqrt(z**2.+(ks+R)**2.) + sqrtm= numpy.sqrt(z**2.+(ks-R)**2.) + evalInt= numpy.arcsin(2.*ks/(sqrtp+sqrtm))*ks*special.k0(self._alpha*ks) + return -2.*self._alpha*numpy.sum(weights*evalInt) raise NotImplementedError("Not new=True not implemented for RazorThinExponentialDiskPotential") def _Rforce(self,R,z,phi=0.,t=0.): @@ -123,26 +121,26 @@ """ if self._new: #if R > 6.: return self._kp(R,z) - if nu.fabs(z) < 10.**-6.: + if numpy.fabs(z) < 10.**-6.: y= 0.5*self._alpha*R - return -2.*nu.pi*y*(special.i0(y)*special.k0(y)-special.i1(y)*special.k1(y)) + return -2.*numpy.pi*y*(special.i0(y)*special.k0(y)-special.i1(y)*special.k1(y)) kalphamax1= R ks1= kalphamax1*0.5*(self._glx+1.) weights1= kalphamax1*self._glw - sqrtp= nu.sqrt(z**2.+(ks1+R)**2.) - sqrtm= nu.sqrt(z**2.+(ks1-R)**2.) - evalInt1= ks1**2.*special.k0(ks1*self._alpha)*((ks1+R)/sqrtp-(ks1-R)/sqrtm)/nu.sqrt(R**2.+z**2.-ks1**2.+sqrtp*sqrtm)/(sqrtp+sqrtm) + sqrtp= numpy.sqrt(z**2.+(ks1+R)**2.) + sqrtm= numpy.sqrt(z**2.+(ks1-R)**2.) + evalInt1= ks1**2.*special.k0(ks1*self._alpha)*((ks1+R)/sqrtp-(ks1-R)/sqrtm)/numpy.sqrt(R**2.+z**2.-ks1**2.+sqrtp*sqrtm)/(sqrtp+sqrtm) if R < 10.: kalphamax2= 10. ks2= (kalphamax2-kalphamax1)*0.5*(self._glx+1.)+kalphamax1 weights2= (kalphamax2-kalphamax1)*self._glw - sqrtp= nu.sqrt(z**2.+(ks2+R)**2.) - sqrtm= nu.sqrt(z**2.+(ks2-R)**2.) - evalInt2= ks2**2.*special.k0(ks2*self._alpha)*((ks2+R)/sqrtp-(ks2-R)/sqrtm)/nu.sqrt(R**2.+z**2.-ks2**2.+sqrtp*sqrtm)/(sqrtp+sqrtm) - return -2.*nu.sqrt(2.)*self._alpha*nu.sum(weights1*evalInt1 + sqrtp= numpy.sqrt(z**2.+(ks2+R)**2.) + sqrtm= numpy.sqrt(z**2.+(ks2-R)**2.) + evalInt2= ks2**2.*special.k0(ks2*self._alpha)*((ks2+R)/sqrtp-(ks2-R)/sqrtm)/numpy.sqrt(R**2.+z**2.-ks2**2.+sqrtp*sqrtm)/(sqrtp+sqrtm) + return -2.*numpy.sqrt(2.)*self._alpha*numpy.sum(weights1*evalInt1 +weights2*evalInt2) else: - return -2.*nu.sqrt(2.)*self._alpha*nu.sum(weights1*evalInt1) + return -2.*numpy.sqrt(2.)*self._alpha*numpy.sum(weights1*evalInt1) raise NotImplementedError("Not new=True not implemented for RazorThinExponentialDiskPotential") def _zforce(self,R,z,phi=0.,t=0.): @@ -163,25 +161,25 @@ """ if self._new: #if R > 6.: return self._kp(R,z) - if nu.fabs(z) < 10.**-6.: + if numpy.fabs(z) < 10.**-6.: return 0. kalphamax1= R ks1= kalphamax1*0.5*(self._glx+1.) weights1= kalphamax1*self._glw - sqrtp= nu.sqrt(z**2.+(ks1+R)**2.) - sqrtm= nu.sqrt(z**2.+(ks1-R)**2.) - evalInt1= ks1**2.*special.k0(ks1*self._alpha)*(1./sqrtp+1./sqrtm)/nu.sqrt(R**2.+z**2.-ks1**2.+sqrtp*sqrtm)/(sqrtp+sqrtm) + sqrtp= numpy.sqrt(z**2.+(ks1+R)**2.) + sqrtm= numpy.sqrt(z**2.+(ks1-R)**2.) + evalInt1= ks1**2.*special.k0(ks1*self._alpha)*(1./sqrtp+1./sqrtm)/numpy.sqrt(R**2.+z**2.-ks1**2.+sqrtp*sqrtm)/(sqrtp+sqrtm) if R < 10.: kalphamax2= 10. ks2= (kalphamax2-kalphamax1)*0.5*(self._glx+1.)+kalphamax1 weights2= (kalphamax2-kalphamax1)*self._glw - sqrtp= nu.sqrt(z**2.+(ks2+R)**2.) - sqrtm= nu.sqrt(z**2.+(ks2-R)**2.) - evalInt2= ks2**2.*special.k0(ks2*self._alpha)*(1./sqrtp+1./sqrtm)/nu.sqrt(R**2.+z**2.-ks2**2.+sqrtp*sqrtm)/(sqrtp+sqrtm) - return -z*2.*nu.sqrt(2.)*self._alpha*nu.sum(weights1*evalInt1 + sqrtp= numpy.sqrt(z**2.+(ks2+R)**2.) + sqrtm= numpy.sqrt(z**2.+(ks2-R)**2.) + evalInt2= ks2**2.*special.k0(ks2*self._alpha)*(1./sqrtp+1./sqrtm)/numpy.sqrt(R**2.+z**2.-ks2**2.+sqrtp*sqrtm)/(sqrtp+sqrtm) + return -z*2.*numpy.sqrt(2.)*self._alpha*numpy.sum(weights1*evalInt1 +weights2*evalInt2) else: - return -z*2.*nu.sqrt(2.)*self._alpha*nu.sum(weights1*evalInt1) + return -z*2.*numpy.sqrt(2.)*self._alpha*numpy.sum(weights1*evalInt1) raise NotImplementedError("Not new=True not implemented for RazorThinExponentialDiskPotential") @@ -202,10 +200,10 @@ 2012-12-27 - Written - Bovy (IAS) """ if self._new: - if nu.fabs(z) < 10.**-6.: + if numpy.fabs(z) < 10.**-6.: y= 0.5*self._alpha*R - return nu.pi*self._alpha*(special.i0(y)*special.k0(y)-special.i1(y)*special.k1(y)) \ - +nu.pi/4.*self._alpha**2.*R*(special.i1(y)*(3.*special.k0(y)+special.kn(2,y))-special.k1(y)*(3.*special.i0(y)+special.iv(2,y))) + return numpy.pi*self._alpha*(special.i0(y)*special.k0(y)-special.i1(y)*special.k1(y)) \ + +numpy.pi/4.*self._alpha**2.*R*(special.i1(y)*(3.*special.k0(y)+special.kn(2,y))-special.k1(y)*(3.*special.i0(y)+special.iv(2,y))) raise AttributeError("'R2deriv' for RazorThinExponentialDisk not implemented for z =/= 0") def _z2deriv(self,R,z,phi=0.,t=0.): #pragma: no cover @@ -224,7 +222,7 @@ HISTORY: 2012-12-27 - Written - Bovy (IAS) """ - return nu.infty + return numpy.infty def _surfdens(self,R,z,phi=0.,t=0.): """ @@ -242,4 +240,4 @@ HISTORY: 2018-08-19 - Written - Bovy (UofT) """ - return nu.exp(-self._alpha*R) + return numpy.exp(-self._alpha*R) diff -Nru galpy-1.5/galpy/potential/RingPotential.py galpy-1.6.0.post0/galpy/potential/RingPotential.py --- galpy-1.5/galpy/potential/RingPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/RingPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # RingPotential.py: The gravitational potential of a thin, circular ring ############################################################################### -import numpy as nu +import numpy from scipy import special from .Potential import Potential, _APY_LOADED if _APY_LOADED: @@ -49,7 +49,7 @@ a= a.to(units.kpc).value/self._ro self.a= a self.a2= self.a**2 - self._amp/= 2.*nu.pi*self.a + self._amp/= 2.*numpy.pi*self.a if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): @@ -76,7 +76,7 @@ 2018-08-04 - Written - Bovy (UofT) """ m= 4.*R*self.a/((R+self.a)**2+z**2) - return -4.*self.a/nu.sqrt((R+self.a)**2+z**2)*special.ellipk(m) + return -4.*self.a/numpy.sqrt((R+self.a)**2+z**2)*special.ellipk(m) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -95,7 +95,7 @@ 2018-08-04 - Written - Bovy (UofT) """ m= 4.*R*self.a/((R+self.a)**2+z**2) - return -2.*self.a/R/nu.sqrt((R+self.a)**2+z**2)\ + return -2.*self.a/R/numpy.sqrt((R+self.a)**2+z**2)\ *(m*(R**2-self.a2-z**2)/4./(1.-m)/self.a/R*special.ellipe(m) +special.ellipk(m)) @@ -135,7 +135,7 @@ 2018-08-04 - Written - Bovy (UofT) """ Raz2= (R+self.a)**2+z**2 - Raz= nu.sqrt(Raz2) + Raz= numpy.sqrt(Raz2) m= 4.*R*self.a/Raz2 R2ma2mz2o4aR1m= (R**2-self.a2-z**2)/4./self.a/R/(1.-m) return (2*R**2+self.a2+3*R*self.a+z**2)/R/Raz2*self._Rforce(R,z)\ diff -Nru galpy-1.5/galpy/potential/SCFPotential.py galpy-1.6.0.post0/galpy/potential/SCFPotential.py --- galpy-1.5/galpy/potential/SCFPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/SCFPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,17 +1,12 @@ - -import numpy as nu +import hashlib +import numpy +from numpy.polynomial.legendre import leggauss +from scipy.special import lpmn +from scipy.special import gammaln from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units - -from galpy.util import bovy_coords -from scipy.special import eval_gegenbauer, lpmn, gamma - -from numpy.polynomial.legendre import leggauss - -from scipy.special import gammaln - -import hashlib +from ..util import bovy_coords from .NumericalPotentialDerivativesMixin import \ NumericalPotentialDerivativesMixin @@ -49,7 +44,7 @@ and :math:`P_{lm}` is the Associated Legendre Polynomials whereas :math:`C_n^{\\alpha}` is the Gegenbauer polynomial. """ - def __init__(self, amp=1., Acos=nu.array([[[1]]]),Asin=None, a = 1., normalize=False, ro=None,vo=None): + def __init__(self, amp=1., Acos=numpy.array([[[1]]]),Asin=None, a = 1., normalize=False, ro=None,vo=None): """ NAME: @@ -96,7 +91,7 @@ errorMessage="The second and third dimension of the expansion coefficients must have the same length" elif Asin is None and not (shape[2] == 1 or shape[1] == shape[2]): errorMessage="The third dimension must have length=1 or equal to the length of the second dimension" - elif Asin is None and shape[1] > 1 and nu.any(Acos[:,:,1:] !=0): + elif Asin is None and shape[1] > 1 and numpy.any(Acos[:,:,1:] !=0): errorMessage="Acos has non-zero elements at indices m>0, which implies a non-axi symmetric potential.\n" +\ "Asin=None which implies an axi symmetric potential.\n" + \ "Contradiction." @@ -107,7 +102,7 @@ ##Warnings warningMessage=None - if nu.any(nu.triu(Acos,1) != 0) or (Asin is not None and nu.any(nu.triu(Asin,1) != 0)): + if numpy.any(numpy.triu(Acos,1) != 0) or (Asin is not None and numpy.any(numpy.triu(Asin,1) != 0)): warningMessage="Found non-zero values at expansion coefficients where m > l\n" + \ "The Mth and Lth dimension is expected to make a lower triangular matrix.\n" + \ "All values found above the diagonal will be ignored." @@ -116,7 +111,7 @@ ##Is non axi? self.isNonAxi= True - if Asin is None or shape[1] == 1 or (nu.all(Acos[:,:,1:] == 0) and nu.all(Asin[:,:,:]==0)): + if Asin is None or shape[1] == 1 or (numpy.all(Acos[:,:,1:] == 0) and numpy.all(Asin[:,:,:]==0)): self.isNonAxi = False @@ -125,14 +120,15 @@ NN = self._Nroot(Acos.shape[1], Acos.shape[2]) - self._Acos= Acos*NN[nu.newaxis,:,:] + self._Acos= Acos*NN[numpy.newaxis,:,:] if Asin is not None: - self._Asin = Asin*NN[nu.newaxis,:,:] + self._Asin = Asin*NN[numpy.newaxis,:,:] else: - self._Asin = nu.zeros_like(Acos) + self._Asin = numpy.zeros_like(Acos) self._force_hash= None self.hasC= True self.hasC_dxdv=True + self.hasC_dens=True if normalize or \ (isinstance(normalize,(int,float)) \ @@ -155,13 +151,13 @@ 2016-05-16 - Written - Aladdin """ if M is None: M =L - NN = nu.zeros((L,M),float) - l = nu.arange(0,L)[:,nu.newaxis] - m = nu.arange(0,M)[nu.newaxis, :] + NN = numpy.zeros((L,M),float) + l = numpy.arange(0,L)[:,numpy.newaxis] + m = numpy.arange(0,M)[numpy.newaxis, :] nLn = gammaln(l-m+1) - gammaln(l+m+1) - NN[:,:] = ((2*l+1.)/(4.*nu.pi) * nu.e**nLn)**.5 * 2 + NN[:,:] = ((2*l+1.)/(4.*numpy.pi) * numpy.e**nLn)**.5 * 2 NN[:,0] /= 2. - NN = nu.tril(NN) + NN = numpy.tril(NN) return NN def _calculateXi(self, r): @@ -197,11 +193,11 @@ xi = self._calculateXi(r) CC = _C(xi,N,L) a = self._a - rho = nu.zeros((N,L), float) - n = nu.arange(0,N, dtype=float)[:, nu.newaxis] - l = nu.arange(0, L, dtype=float)[nu.newaxis,:] + rho = numpy.zeros((N,L), float) + n = numpy.arange(0,N, dtype=float)[:, numpy.newaxis] + l = numpy.arange(0, L, dtype=float)[numpy.newaxis,:] K = 0.5 * n * (n + 4*l + 3) + (l + 1.)*(2*l + 1) - rho[:,:] = K * ((a*r)**l) / ((r/a)*(a + r)**(2*l + 3.)) * CC[:,:]* (nu.pi)**-0.5 + rho[:,:] = K * ((a*r)**l) / ((r/a)*(a + r)**(2*l + 3.)) * CC[:,:]* (numpy.pi)**-0.5 return rho def _phiTilde(self, r, N,L): @@ -222,10 +218,10 @@ xi = self._calculateXi(r) CC = _C(xi,N,L) a = self._a - phi = nu.zeros((N,L), float) - n = nu.arange(0,N)[:, nu.newaxis] - l = nu.arange(0, L)[nu.newaxis,:] - phi[:,:] = - (r*a)**l/ ((a + r)**(2*l + 1.)) * CC[:,:]* (4*nu.pi)**0.5 + phi = numpy.zeros((N,L), float) + n = numpy.arange(0,N)[:, numpy.newaxis] + l = numpy.arange(0, L)[numpy.newaxis,:] + phi[:,:] = - (r*a)**l/ ((a + r)**(2*l + 1.)) * CC[:,:]* (4*numpy.pi)**0.5 return phi def _compute(self, funcTilde, R, z, phi): @@ -250,14 +246,14 @@ - PP = lpmn(M-1,L-1,nu.cos(theta))[0].T ##Get the Legendre polynomials + PP = lpmn(M-1,L-1,numpy.cos(theta))[0].T ##Get the Legendre polynomials func_tilde = funcTilde(r, N, L) ## Tilde of the function of interest - func = nu.zeros((N,L,M), float) ## The function of interest (density or potential) + func = numpy.zeros((N,L,M), float) ## The function of interest (density or potential) - m = nu.arange(0, M)[nu.newaxis, nu.newaxis, :] - mcos = nu.cos(m*phi) - msin = nu.sin(m*phi) + m = numpy.arange(0, M)[numpy.newaxis, numpy.newaxis, :] + mcos = numpy.cos(m*phi) + msin = numpy.sin(m*phi) func = func_tilde[:,:,None]*(Acos[:,:,:]*mcos + Asin[:,:,:]*msin)*PP[None,:,:] return func @@ -278,18 +274,18 @@ HISTORY: 2016-06-02 - Written - Aladdin """ - R = nu.array(R,dtype=float); z = nu.array(z,dtype=float); phi = nu.array(phi,dtype=float); + R = numpy.array(R,dtype=float); z = numpy.array(z,dtype=float); phi = numpy.array(phi,dtype=float); shape = (R*z*phi).shape - if shape == (): return nu.sum(self._compute(funcTilde, R,z,phi)) - R = R*nu.ones(shape); z = z*nu.ones(shape); phi = phi*nu.ones(shape); - func = nu.zeros(shape, float) + if shape == (): return numpy.sum(self._compute(funcTilde, R,z,phi)) + R = R*numpy.ones(shape); z = z*numpy.ones(shape); phi = phi*numpy.ones(shape); + func = numpy.zeros(shape, float) li = _cartesian(shape) for i in range(li.shape[0]): - j = nu.split(li[i], li.shape[1]) - func[j] = nu.sum(self._compute(funcTilde, R[j][0],z[j][0],phi[j][0])) + j = numpy.split(li[i], li.shape[1]) + func[j] = numpy.sum(self._compute(funcTilde, R[j][0],z[j][0],phi[j][0])) return func def _dens(self, R, z, phi=0., t=0.): @@ -348,11 +344,11 @@ 2016-06-06 - Written - Aladdin """ a = self._a - l = nu.arange(0, L, dtype=float)[nu.newaxis, :] - n = nu.arange(0, N, dtype=float)[:, nu.newaxis] + l = numpy.arange(0, L, dtype=float)[numpy.newaxis, :] + n = numpy.arange(0, N, dtype=float)[:, numpy.newaxis] xi = self._calculateXi(r) dC = _dC(xi,N,L) - return -(4*nu.pi)**.5 * (nu.power(a*r, l)*(l*(a + r)*nu.power(r,-1) -(2*l + 1))/((a + r)**(2*l + 2))*_C(xi,N,L) + + return -(4*numpy.pi)**.5 * (numpy.power(a*r, l)*(l*(a + r)*numpy.power(r,-1) -(2*l + 1))/((a + r)**(2*l + 2))*_C(xi,N,L) + a**-1*(1 - xi)**2 * (a*r)**l / (a + r)**(2*l + 1) *dC/2.) @@ -375,7 +371,7 @@ Acos, Asin = self._Acos, self._Asin N, L, M = Acos.shape r, theta, phi = bovy_coords.cyl_to_spher(R,z,phi) - new_hash= hashlib.md5(nu.array([R, z,phi])).hexdigest() + new_hash= hashlib.md5(numpy.array([R, z,phi])).hexdigest() if new_hash == self._force_hash: dPhi_dr = self._cached_dPhi_dr @@ -383,18 +379,18 @@ dPhi_dphi = self._cached_dPhi_dphi else: - PP, dPP = lpmn(M-1,L-1,nu.cos(theta)) ##Get the Legendre polynomials + PP, dPP = lpmn(M-1,L-1,numpy.cos(theta)) ##Get the Legendre polynomials PP = PP.T[None,:,:] dPP = dPP.T[None,:,:] - phi_tilde = self._phiTilde(r, N, L)[:,:,nu.newaxis] - dphi_tilde = self._dphiTilde(r,N,L)[:,:,nu.newaxis] + phi_tilde = self._phiTilde(r, N, L)[:,:,numpy.newaxis] + dphi_tilde = self._dphiTilde(r,N,L)[:,:,numpy.newaxis] - m = nu.arange(0, M)[nu.newaxis, nu.newaxis, :] - mcos = nu.cos(m*phi) - msin = nu.sin(m*phi) - dPhi_dr = -nu.sum((Acos*mcos + Asin*msin)*PP*dphi_tilde) - dPhi_dtheta = -nu.sum((Acos*mcos + Asin*msin)*phi_tilde*dPP*(-nu.sin(theta))) - dPhi_dphi =-nu.sum(m*(Asin*mcos - Acos*msin)*phi_tilde*PP) + m = numpy.arange(0, M)[numpy.newaxis, numpy.newaxis, :] + mcos = numpy.cos(m*phi) + msin = numpy.sin(m*phi) + dPhi_dr = -numpy.sum((Acos*mcos + Asin*msin)*PP*dphi_tilde) + dPhi_dtheta = -numpy.sum((Acos*mcos + Asin*msin)*phi_tilde*dPP*(-numpy.sin(theta))) + dPhi_dphi =-numpy.sum(m*(Asin*mcos - Acos*msin)*phi_tilde*PP) self._force_hash = new_hash self._cached_dPhi_dr = dPhi_dr @@ -421,22 +417,22 @@ HISTORY: 2016-06-02 - Written - Aladdin """ - R = nu.array(R,dtype=float); z = nu.array(z,dtype=float); phi = nu.array(phi,dtype=float); + R = numpy.array(R,dtype=float); z = numpy.array(z,dtype=float); phi = numpy.array(phi,dtype=float); shape = (R*z*phi).shape if shape == (): dPhi_dr,dPhi_dtheta,dPhi_dphi = \ self._computeforce(R,z,phi) return dr_dx*dPhi_dr + dtheta_dx*dPhi_dtheta +dPhi_dphi*dphi_dx - R = R*nu.ones(shape); - z = z* nu.ones(shape); - phi = phi* nu.ones(shape); - force = nu.zeros(shape, float) - dr_dx = dr_dx*nu.ones(shape); dtheta_dx = dtheta_dx*nu.ones(shape);dphi_dx = dphi_dx*nu.ones(shape); + R = R*numpy.ones(shape); + z = z* numpy.ones(shape); + phi = phi* numpy.ones(shape); + force = numpy.zeros(shape, float) + dr_dx = dr_dx*numpy.ones(shape); dtheta_dx = dtheta_dx*numpy.ones(shape);dphi_dx = dphi_dx*numpy.ones(shape); li = _cartesian(shape) for i in range(li.shape[0]): - j = tuple(nu.split(li[i], li.shape[1])) + j = tuple(numpy.split(li[i], li.shape[1])) dPhi_dr,dPhi_dtheta,dPhi_dphi = \ self._computeforce(R[j][0],z[j][0],phi[j][0]) force[j] = dr_dx[j][0]*dPhi_dr + dtheta_dx[j][0]*dPhi_dtheta +dPhi_dphi*dphi_dx[j][0] @@ -461,7 +457,7 @@ phi= 0. r, theta, phi = bovy_coords.cyl_to_spher(R,z,phi) #x = R - dr_dR = nu.divide(R,r); dtheta_dR = nu.divide(z,r**2); dphi_dR = 0 + dr_dR = numpy.divide(R,r); dtheta_dR = numpy.divide(z,r**2); dphi_dR = 0 return self._computeforceArray(dr_dR, dtheta_dR, dphi_dR, R,z,phi) def _zforce(self, R, z, phi=0., t=0.): @@ -484,7 +480,7 @@ phi= 0. r, theta, phi = bovy_coords.cyl_to_spher(R,z,phi) #x = z - dr_dz = nu.divide(z,r); dtheta_dz = nu.divide(-R,r**2); dphi_dz = 0 + dr_dz = numpy.divide(z,r); dtheta_dz = numpy.divide(-R,r**2); dphi_dz = 0 return self._computeforceArray(dr_dz, dtheta_dz, dphi_dz, R,z,phi) def _phiforce(self, R,z,phi=0,t=0): @@ -515,7 +511,7 @@ def _xiToR(xi, a =1): - return a*nu.divide((1. + xi),(1. - xi)) + return a*numpy.divide((1. + xi),(1. - xi)) def _C(xi, N,L, alpha = lambda x: 2*x + 3./2): @@ -535,7 +531,7 @@ HISTORY: 2016-05-16 - Written - Aladdin """ - CC = nu.zeros((N,L), float) + CC = numpy.zeros((N,L), float) for l in range(L): for n in range(N): @@ -549,9 +545,9 @@ return CC def _dC(xi, N, L): - l = nu.arange(0,L)[nu.newaxis, :] + l = numpy.arange(0,L)[numpy.newaxis, :] CC = _C(xi,N + 1,L, alpha = lambda x: 2*x + 5./2) - CC = nu.roll(CC, 1, axis=0)[:-1,:] + CC = numpy.roll(CC, 1, axis=0)[:-1,:] CC[0, :] = 0 CC *= 2*(2*l + 3./2) return CC @@ -604,7 +600,7 @@ param[0] = R return a**3. * dens(*param)*(1 + xi)**2. * (1 - xi)**-3. * _C(xi, N, 1)[:,0] - Acos = nu.zeros((N,1,1), float) + Acos = numpy.zeros((N,1,1), float) Asin = None Ksample = [max(N + 1, 20)] @@ -613,8 +609,8 @@ Ksample[0] = radial_order integrated = _gaussianQuadrature(integrand, [[-1., 1.]], Ksample=Ksample) - n = nu.arange(0,N) - K = 16*nu.pi*(n + 3./2)/((n + 2)*(n + 1)*(1 + n*(n + 3.)/2.)) + n = numpy.arange(0,N) + K = 16*numpy.pi*(n + 3./2)/((n + 2)*(n + 1)*(1 + n*(n + 3.)/2.)) Acos[n,0,0] = 2*K*integrated return Acos, Asin @@ -658,19 +654,19 @@ numOfParam=3 param = [0]*numOfParam; def integrand(xi, costheta): - l = nu.arange(0, L)[nu.newaxis, :] + l = numpy.arange(0, L)[numpy.newaxis, :] r = _xiToR(xi,a) - R = r*nu.sqrt(1 - costheta**2.) + R = r*numpy.sqrt(1 - costheta**2.) z = r*costheta - Legandre = lpmn(0,L-1,costheta)[0].T[nu.newaxis,:,0] - dV = (1. + xi)**2. * nu.power(1. - xi, -4.) + Legandre = lpmn(0,L-1,costheta)[0].T[numpy.newaxis,:,0] + dV = (1. + xi)**2. * numpy.power(1. - xi, -4.) phi_nl = a**3*(1. + xi)**l * (1. - xi)**(l + 1.)*_C(xi, N, L)[:,:] * Legandre param[0] = R param[1] = z return phi_nl*dV * dens(*param) - Acos = nu.zeros((N,L,1), float) + Acos = numpy.zeros((N,L,1), float) Asin = None ##This should save us some computation time since we're only taking the double integral once, rather then L times @@ -681,14 +677,14 @@ Ksample[1] = costheta_order - integrated = _gaussianQuadrature(integrand, [[-1, 1], [-1, 1]], Ksample = Ksample)*(2*nu.pi) - n = nu.arange(0,N)[:,nu.newaxis] - l = nu.arange(0,L)[nu.newaxis,:] + integrated = _gaussianQuadrature(integrand, [[-1, 1], [-1, 1]], Ksample = Ksample)*(2*numpy.pi) + n = numpy.arange(0,N)[:,numpy.newaxis] + l = numpy.arange(0,L)[numpy.newaxis,:] K = .5*n*(n + 4*l + 3) + (l + 1)*(2*l + 1) - #I = -K*(4*nu.pi)/(2.**(8*l + 6)) * gamma(n + 4*l + 3)/(gamma(n + 1)*(n + 2*l + 3./2)*gamma(2*l + 3./2)**2) + #I = -K*(4*numpy.pi)/(2.**(8*l + 6)) * gamma(n + 4*l + 3)/(gamma(n + 1)*(n + 2*l + 3./2)*gamma(2*l + 3./2)**2) ##Taking the ln of I will allow bigger size coefficients - lnI = -(8*l + 6)*nu.log(2) + gammaln(n + 4*l + 3) - gammaln(n + 1) - nu.log(n + 2*l + 3./2) - 2*gammaln(2*l + 3./2) - I = -K*(4*nu.pi) * nu.e**(lnI) + lnI = -(8*l + 6)*numpy.log(2) + gammaln(n + 4*l + 3) - gammaln(n + 1) - numpy.log(n + 2*l + 3./2) - 2*gammaln(2*l + 3./2) + I = -K*(4*numpy.pi) * numpy.e**(lnI) constants = -2.**(-2*l)*(2*l + 1.)**.5 Acos[:,:,0] = 2*I**-1 * integrated*constants @@ -731,22 +727,22 @@ """ def integrand(xi, costheta, phi): - l = nu.arange(0, L)[nu.newaxis, :, nu.newaxis] - m = nu.arange(0, L)[nu.newaxis,nu.newaxis,:] + l = numpy.arange(0, L)[numpy.newaxis, :, numpy.newaxis] + m = numpy.arange(0, L)[numpy.newaxis,numpy.newaxis,:] r = _xiToR(xi, a) - R = r*nu.sqrt(1 - costheta**2.) + R = r*numpy.sqrt(1 - costheta**2.) z = r*costheta - Legandre = lpmn(L - 1,L-1,costheta)[0].T[nu.newaxis,:,:] - dV = (1. + xi)**2. * nu.power(1. - xi, -4.) + Legandre = lpmn(L - 1,L-1,costheta)[0].T[numpy.newaxis,:,:] + dV = (1. + xi)**2. * numpy.power(1. - xi, -4.) - phi_nl = - a**3*(1. + xi)**l * (1. - xi)**(l + 1.)*_C(xi, N, L)[:,:,nu.newaxis] * Legandre + phi_nl = - a**3*(1. + xi)**l * (1. - xi)**(l + 1.)*_C(xi, N, L)[:,:,numpy.newaxis] * Legandre - return dens(R,z, phi) * phi_nl[nu.newaxis, :,:,:]*nu.array([nu.cos(m*phi), nu.sin(m*phi)])*dV + return dens(R,z, phi) * phi_nl[numpy.newaxis, :,:,:]*numpy.array([numpy.cos(m*phi), numpy.sin(m*phi)])*dV - Acos = nu.zeros((N,L,L), float) - Asin = nu.zeros((N,L,L), float) + Acos = numpy.zeros((N,L,L), float) + Asin = numpy.zeros((N,L,L), float) Ksample = [max(N + 3*L//2 + 1,20), max(L + 1,20 ), max(L + 1,20)] @@ -756,23 +752,23 @@ Ksample[1] = costheta_order if phi_order != None: Ksample[2] = phi_order - integrated = _gaussianQuadrature(integrand, [[-1., 1.], [-1., 1.], [0, 2*nu.pi]], Ksample = Ksample) - n = nu.arange(0,N)[:,nu.newaxis, nu.newaxis] - l = nu.arange(0,L)[nu.newaxis,:, nu.newaxis] - m = nu.arange(0,L)[nu.newaxis,nu.newaxis,:] + integrated = _gaussianQuadrature(integrand, [[-1., 1.], [-1., 1.], [0, 2*numpy.pi]], Ksample = Ksample) + n = numpy.arange(0,N)[:,numpy.newaxis, numpy.newaxis] + l = numpy.arange(0,L)[numpy.newaxis,:, numpy.newaxis] + m = numpy.arange(0,L)[numpy.newaxis,numpy.newaxis,:] K = .5*n*(n + 4*l + 3) + (l + 1)*(2*l + 1) - Nln = .5*gammaln(l - m + 1) - .5*gammaln(l + m + 1) - (2*l)*nu.log(2) - NN = nu.e**(Nln) + Nln = .5*gammaln(l - m + 1) - .5*gammaln(l + m + 1) - (2*l)*numpy.log(2) + NN = numpy.e**(Nln) - NN[nu.where(NN == nu.inf)] = 0 ## To account for the fact that m cant be bigger than l + NN[numpy.where(NN == numpy.inf)] = 0 ## To account for the fact that m cant be bigger than l constants = NN*(2*l + 1.)**.5 - lnI = -(8*l + 6)*nu.log(2) + gammaln(n + 4*l + 3) - gammaln(n + 1) - nu.log(n + 2*l + 3./2) - 2*gammaln(2*l + 3./2) - I = -K*(4*nu.pi) * nu.e**(lnI) - Acos[:,:,:],Asin[:,:,:] = 2*(I**-1.)[nu.newaxis,:,:,:] * integrated * constants[nu.newaxis,:,:,:] + lnI = -(8*l + 6)*numpy.log(2) + gammaln(n + 4*l + 3) - gammaln(n + 1) - numpy.log(n + 2*l + 3./2) - 2*gammaln(2*l + 3./2) + I = -K*(4*numpy.pi) * numpy.e**(lnI) + Acos[:,:,:],Asin[:,:,:] = 2*(I**-1.)[numpy.newaxis,:,:,:] * integrated * constants[numpy.newaxis,:,:,:] return Acos, Asin @@ -794,17 +790,17 @@ """ arrays = [] for i in range(len(arraySizes)): - arrays.append(nu.arange(0, arraySizes[i])) + arrays.append(numpy.arange(0, arraySizes[i])) - arrays = [nu.asarray(x) for x in arrays] + arrays = [numpy.asarray(x) for x in arrays] dtype = arrays[0].dtype - n = nu.prod([x.size for x in arrays]) + n = numpy.prod([x.size for x in arrays]) if out is None: - out = nu.zeros([n, len(arrays)], dtype=dtype) + out = numpy.zeros([n, len(arrays)], dtype=dtype) m = n // arrays[0].size - out[:,0] = nu.repeat(arrays[0], m) + out[:,0] = numpy.repeat(arrays[0], m) if arrays[1:]: _cartesian(arraySizes[1:], out=out[0:m,1:]) for j in range(1, arrays[0].size): @@ -831,8 +827,8 @@ """ ##Maps the sample point and weights - xp = nu.zeros((len(bounds), nu.max(Ksample)), float) - wp = nu.zeros((len(bounds), nu.max(Ksample)), float) + xp = numpy.zeros((len(bounds), numpy.max(Ksample)), float) + wp = numpy.zeros((len(bounds), numpy.max(Ksample)), float) for i in range(len(bounds)): x,w = leggauss(Ksample[i]) ##Calculates the sample points and weights a,b = bounds[i] @@ -843,10 +839,10 @@ ##Determines the shape of the integrand s = 0. shape=None - s_temp = integrand(*nu.zeros(len(bounds))) - if type(s_temp).__name__ == nu.ndarray.__name__ : + s_temp = integrand(*numpy.zeros(len(bounds))) + if type(s_temp).__name__ == numpy.ndarray.__name__ : shape = s_temp.shape - s = nu.zeros(shape, float) + s = numpy.zeros(shape, float) @@ -856,13 +852,13 @@ ##Performs the actual integration for i in range(li.shape[0]): - index = (nu.arange(len(bounds)),li[i]) - s+= nu.prod(wp[index])*integrand(*xp[index]) + index = (numpy.arange(len(bounds)),li[i]) + s+= numpy.prod(wp[index])*integrand(*xp[index]) ##Rounds values that are less than roundoff to zero if shape!= None: - s[nu.where(nu.fabs(s) < roundoff)] = 0 - else: s *= nu.fabs(s) >roundoff + s[numpy.where(numpy.fabs(s) < roundoff)] = 0 + else: s *= numpy.fabs(s) >roundoff return s diff -Nru galpy-1.5/galpy/potential/SnapshotRZPotential.py galpy-1.6.0.post0/galpy/potential/SnapshotRZPotential.py --- galpy-1.5/galpy/potential/SnapshotRZPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/SnapshotRZPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,6 +1,6 @@ from os import system import hashlib -import numpy as np +import numpy from scipy import interpolate from .Potential import Potential from .interpRZPotential import scalarVectorDecorator, \ @@ -66,12 +66,12 @@ self._num_threads = num_threads # Set up azimuthal averaging self._naz= nazimuths - self._cosaz= np.cos(np.arange(self._naz,dtype='float')\ - /self._naz*2.*np.pi) - self._sinaz= np.sin(np.arange(self._naz,dtype='float')\ - /self._naz*2.*np.pi) - self._zones= np.ones(self._naz) - self._zzeros= np.zeros(self._naz) + self._cosaz= numpy.cos(numpy.arange(self._naz,dtype='float')\ + /self._naz*2.*numpy.pi) + self._sinaz= numpy.sin(numpy.arange(self._naz,dtype='float')\ + /self._naz*2.*numpy.pi) + self._zones= numpy.ones(self._naz) + self._zzeros= numpy.zeros(self._naz) return None @scalarVectorDecorator @@ -91,7 +91,7 @@ def _setup_potential(self, R, z, use_pkdgrav = False) : # compute the hash for the requested grid - new_hash = hashlib.md5(np.array([R,z])).hexdigest() + new_hash = hashlib.md5(numpy.array([R,z])).hexdigest() # if we computed for these points before, return; otherwise compute if new_hash in self._point_hash : @@ -102,10 +102,10 @@ else : # set up the four points per R,z pair to mimic axisymmetry - points = np.zeros((len(R),self._naz,3)) + points = numpy.zeros((len(R),self._naz,3)) for i in range(len(R)) : - points[i] = np.array([R[i]*self._cosaz,R[i]*self._sinaz, + points[i] = numpy.array([R[i]*self._cosaz,R[i]*self._sinaz, z[i]*self._zones]).T points_new = points.reshape(points.size//3,3) @@ -118,8 +118,8 @@ pot = pot.mean(axis=1) # get the radial accelerations - rz_acc = np.zeros((len(R),2)) - rvecs= np.array([self._cosaz,self._sinaz,self._zzeros]).T + rz_acc = numpy.zeros((len(R),2)) + rvecs= numpy.array([self._cosaz,self._sinaz,self._zzeros]).T for i in range(len(R)) : for j,rvec in enumerate(rvecs) : @@ -139,7 +139,7 @@ """ def __init__(self, s, ro=None,vo=None, - rgrid=(np.log(0.01),np.log(20.),101), + rgrid=(numpy.log(0.01),numpy.log(20.),101), zgrid=(0.,1.,101), interpepifreq = False, interpverticalfreq = False, interpPot = True, @@ -204,12 +204,12 @@ # Set up azimuthal averaging self._naz= nazimuths - self._cosaz= np.cos(np.arange(self._naz,dtype='float')\ - /self._naz*2.*np.pi) - self._sinaz= np.sin(np.arange(self._naz,dtype='float')\ - /self._naz*2.*np.pi) - self._zones= np.ones(self._naz) - self._zzeros= np.zeros(self._naz) + self._cosaz= numpy.cos(numpy.arange(self._naz,dtype='float')\ + /self._naz*2.*numpy.pi) + self._sinaz= numpy.sin(numpy.arange(self._naz,dtype='float')\ + /self._naz*2.*numpy.pi) + self._zones= numpy.ones(self._naz) + self._zzeros= numpy.zeros(self._naz) # the interpRZPotential class sets these flags self._enable_c = enable_c @@ -235,15 +235,15 @@ self._zsym = zsym self._logR = logR - self._rgrid = np.linspace(*rgrid) + self._rgrid = numpy.linspace(*rgrid) if logR : - self._rgrid = np.exp(self._rgrid) - self._logrgrid = np.log(self._rgrid) + self._rgrid = numpy.exp(self._rgrid) + self._logrgrid = numpy.log(self._rgrid) rs = self._logrgrid else : rs = self._rgrid - self._zgrid = np.linspace(*zgrid) + self._zgrid = numpy.linspace(*zgrid) # calculate the grids self._setup_potential(self._rgrid,self._zgrid,use_pkdgrav=use_pkdgrav) @@ -286,20 +286,20 @@ # setup the derived quantities if interpPot: - self._vcircGrid = np.sqrt(self._rgrid*(-self._rforceGrid[:,0])) + self._vcircGrid = numpy.sqrt(self._rgrid*(-self._rforceGrid[:,0])) self._vcircInterp = interpolate.InterpolatedUnivariateSpline(rs, self._vcircGrid, k=3) if interpepifreq: - self._epifreqGrid = np.sqrt(self._R2derivGrid[:,0] - 3./self._rgrid*self._rforceGrid[:,0]) - goodindx= True^np.isnan(self._epifreqGrid) + self._epifreqGrid = numpy.sqrt(self._R2derivGrid[:,0] - 3./self._rgrid*self._rforceGrid[:,0]) + goodindx= True^numpy.isnan(self._epifreqGrid) self._epifreqInterp=\ interpolate.InterpolatedUnivariateSpline(rs[goodindx], self._epifreqGrid[goodindx], k=3) self._epigoodindx= goodindx if interpverticalfreq: - self._verticalfreqGrid = np.sqrt(np.abs(self._z2derivGrid[:,0])) - goodindx= True^np.isnan(self._verticalfreqGrid) + self._verticalfreqGrid = numpy.sqrt(numpy.abs(self._z2derivGrid[:,0])) + goodindx= True^numpy.isnan(self._verticalfreqGrid) self._verticalfreqInterp=\ interpolate.InterpolatedUnivariateSpline(rs[goodindx], self._verticalfreqGrid[goodindx],k=3) @@ -328,19 +328,19 @@ """ # set up the four points per R,z pair to mimic axisymmetry - points = np.zeros((len(R),len(z),self._naz,3)) + points = numpy.zeros((len(R),len(z),self._naz,3)) for i in range(len(R)) : for j in range(len(z)) : - points[i,j] = np.array([R[i]*self._cosaz,R[i]*self._sinaz, + points[i,j] = numpy.array([R[i]*self._cosaz,R[i]*self._sinaz, z[j]*self._zones]).T points_new = points.reshape(points.size//3,3) self.points = points_new # set up the points to calculate the second derivatives - zgrad_points = np.zeros((len(points_new)*2,3)) - rgrad_points = np.zeros((len(points_new)*2,3)) + zgrad_points = numpy.zeros((len(points_new)*2,3)) + rgrad_points = numpy.zeros((len(points_new)*2,3)) for i,p in enumerate(points_new) : zgrad_points[i*2] = p zgrad_points[i*2][2] -= dr @@ -348,9 +348,9 @@ zgrad_points[i*2+1][2] += dr rgrad_points[i*2] = p - rgrad_points[i*2][:2] -= p[:2]/np.sqrt(np.dot(p[:2],p[:2]))*dr + rgrad_points[i*2][:2] -= p[:2]/numpy.sqrt(numpy.dot(p[:2],p[:2]))*dr rgrad_points[i*2+1] = p - rgrad_points[i*2+1][:2] += p[:2]/np.sqrt(np.dot(p[:2],p[:2]))*dr + rgrad_points[i*2+1][:2] += p[:2]/numpy.sqrt(numpy.dot(p[:2],p[:2]))*dr if use_pkdgrav : #pragma: no cover @@ -389,8 +389,8 @@ pot = pot.mean(axis=1) # get the radial accelerations - rz_acc = np.zeros((len(R)*len(z),2)) - rvecs= np.array([self._cosaz,self._sinaz,self._zzeros]).T + rz_acc = numpy.zeros((len(R)*len(z),2)) + rvecs= numpy.array([self._cosaz,self._sinaz,self._zzeros]).T # reshape the acc to make sure we have a leading index even # if we are only evaluating a single point, i.e. we have @@ -416,7 +416,7 @@ # two points to get the gradient across it. Compute the gradient by # using a finite difference - zgrad = np.zeros(len(points_new)) + zgrad = numpy.zeros(len(points_new)) # do a loop through the pairs of points -- reshape the array # so that each item is the pair of acceleration vectors @@ -430,21 +430,21 @@ # do the same for the radial component if self._interpepifreq: rgrad_pot, rgrad_acc = gravity.calc.direct(self._s,rgrad_points,num_threads=self._numcores) - rgrad = np.zeros(len(points_new)) + rgrad = numpy.zeros(len(points_new)) for i,racc in enumerate(rgrad_acc.reshape((len(rgrad_acc)//2,2,3))) : point = points_new[i] point[2] = 0.0 - rvec = point/np.sqrt(np.dot(point,point)) - rgrad_vec = (np.dot(racc[1],rvec)- - np.dot(racc[0],rvec)) / (dr*2.0) + rvec = point/numpy.sqrt(numpy.dot(point,point)) + rgrad_vec = (numpy.dot(racc[1],rvec)- + numpy.dot(racc[0],rvec)) / (dr*2.0) rgrad[i] = rgrad_vec self._R2derivGrid = -rgrad.reshape((len(rgrad)//self._naz,self._naz)).mean(axis=1).reshape((len(R),len(z))) # do the same for the mixed radial-vertical component if self._interpepifreq and self._interpverticalfreq: # re-use this - Rzgrad = np.zeros(len(points_new)) + Rzgrad = numpy.zeros(len(points_new)) for i,racc in enumerate(rgrad_acc.reshape((len(rgrad_acc)//2,2,3))) : Rzgrad[i] = ((racc[1]-racc[0])/(dr*2.0))[2] @@ -481,7 +481,7 @@ """ Vc0 = self.vcirc(R0) - Phi0 = np.abs(self.Rforce(R0,0.0)) + Phi0 = numpy.abs(self.Rforce(R0,0.0)) self._normR0 = R0 self._normVc0 = Vc0 @@ -502,7 +502,7 @@ # rescale the grid self._rgrid /= R0 if self._logR: - self._logrgrid -= np.log(R0) + self._logrgrid -= numpy.log(R0) rs = self._logrgrid else : rs = self._rgrid @@ -536,7 +536,7 @@ self._R2interp = interpolate.RectBivariateSpline(rs, self._zgrid, self._R2derivGrid, kx=3,ky=3,s=0.) - self._epifreqInterp = interpolate.InterpolatedUnivariateSpline(rs[self._epigoodindx], self._epifreqGrid[self._epigoodindx]/np.sqrt(Phi0/R0), k=3) + self._epifreqInterp = interpolate.InterpolatedUnivariateSpline(rs[self._epigoodindx], self._epifreqGrid[self._epigoodindx]/numpy.sqrt(Phi0/R0), k=3) if self._interpverticalfreq: self._savedsplines['z2deriv'] = self._z2interp @@ -545,7 +545,7 @@ self._zgrid, self._z2derivGrid, kx=3,ky=3,s=0.) - self._verticalfreqInterp = interpolate.InterpolatedUnivariateSpline(rs[self._verticalgoodindx], self._verticalfreqGrid[self._verticalgoodindx]/np.sqrt(Phi0/R0), k=3) + self._verticalfreqInterp = interpolate.InterpolatedUnivariateSpline(rs[self._verticalgoodindx], self._verticalfreqGrid[self._verticalgoodindx]/numpy.sqrt(Phi0/R0), k=3) def denormalize(self) : @@ -567,7 +567,7 @@ # rescale the grid self._rgrid *= R0 if self._logR: - self._logrgrid += np.log(R0) + self._logrgrid += numpy.log(R0) rs = self._logrgrid else : rs = self._rgrid diff -Nru galpy-1.5/galpy/potential/SoftenedNeedleBarPotential.py galpy-1.6.0.post0/galpy/potential/SoftenedNeedleBarPotential.py --- galpy-1.5/galpy/potential/SoftenedNeedleBarPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/SoftenedNeedleBarPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -7,7 +7,7 @@ from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units -from galpy.util import bovy_coords, bovy_conversion +from ..util import bovy_coords, bovy_conversion class SoftenedNeedleBarPotential(Potential): """Class that implements the softened needle bar potential from `Long & Murali (1992) `__ diff -Nru galpy-1.5/galpy/potential/SolidBodyRotationWrapperPotential.py galpy-1.6.0.post0/galpy/potential/SolidBodyRotationWrapperPotential.py --- galpy-1.5/galpy/potential/SolidBodyRotationWrapperPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/SolidBodyRotationWrapperPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -5,7 +5,7 @@ ############################################################################### from .WrapperPotential import parentWrapperPotential from .Potential import _APY_LOADED -from galpy.util import bovy_conversion +from ..util import bovy_conversion if _APY_LOADED: from astropy import units class SolidBodyRotationWrapperPotential(parentWrapperPotential): diff -Nru galpy-1.5/galpy/potential/SphericalShellPotential.py galpy-1.6.0.post0/galpy/potential/SphericalShellPotential.py --- galpy-1.5/galpy/potential/SphericalShellPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/SphericalShellPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -2,7 +2,7 @@ # SphericalShellPotential.py: The gravitational potential of a thin, # spherical shell ############################################################################### -import numpy as nu +import numpy from .Potential import Potential, _APY_LOADED if _APY_LOADED: from astropy import units @@ -78,7 +78,7 @@ if r2 <= self.a2: return -1./self.a else: - return -1./nu.sqrt(r2) + return -1./numpy.sqrt(r2) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -96,7 +96,7 @@ HISTORY: 2018-08-04 - Written - Bovy (UofT) """ - r= nu.sqrt(R**2+z**2) + r= numpy.sqrt(R**2+z**2) if r <= self.a: return 0. else: @@ -118,7 +118,7 @@ HISTORY: 2018-08-04 - Written - Bovy (UofT) """ - r= nu.sqrt(R**2+z**2) + r= numpy.sqrt(R**2+z**2) if r <= self.a: return 0. else: @@ -140,7 +140,7 @@ HISTORY: 2018-08-04 - Written - Bovy (UofT) """ - r= nu.sqrt(R**2+z**2) + r= numpy.sqrt(R**2+z**2) if r <= self.a: return 0. else: @@ -180,7 +180,7 @@ HISTORY: 2018-08-04 - Written - Bovy (UofT) """ - r= nu.sqrt(R**2+z**2) + r= numpy.sqrt(R**2+z**2) if r <= self.a: return 0. else: @@ -206,7 +206,7 @@ if r2 != self.a2: return 0. else: # pragma: no cover - return nu.infty + return numpy.infty def _surfdens(self,R,z,phi=0.,t=0.): """ @@ -225,6 +225,6 @@ 2018-08-04 - Written - Bovy (UofT) """ if R > self.a: return 0. - h= nu.sqrt(self.a2-R**2) + h= numpy.sqrt(self.a2-R**2) if z < h: return 0. - else: return 1./(2.*nu.pi*self.a*h) + else: return 1./(2.*numpy.pi*self.a*h) diff -Nru galpy-1.5/galpy/potential/SpiralArmsPotential.py galpy-1.6.0.post0/galpy/potential/SpiralArmsPotential.py --- galpy-1.5/galpy/potential/SpiralArmsPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/SpiralArmsPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -6,17 +6,12 @@ # # Phi(r, phi, z) = -4*pi*G*H*rho0*exp(-(r-r0)/Rs)*sum(Cn/(Kn*Dn)*cos(n*gamma)*sech(Kn*z/Bn)^Bn) ############################################################################### - from __future__ import division from .Potential import Potential, _APY_LOADED -from galpy.util import bovy_conversion -import numpy as np - +from ..util import bovy_conversion +import numpy if _APY_LOADED: from astropy import units - - - class SpiralArmsPotential(Potential): """Class that implements the spiral arms potential from (`Cox and Gomez 2002 `__). Should be used to modulate an existing potential (density is positive in the arms, negative outside). @@ -90,16 +85,16 @@ self._N = -N # trick to flip to left handed coordinate system; flips sign for phi and phi_ref, but also alpha. self._alpha = -alpha # we don't want sign for alpha to change, so flip alpha. (see eqn. 3 in the paper) - self._sin_alpha = np.sin(-alpha) - self._tan_alpha = np.tan(-alpha) + self._sin_alpha = numpy.sin(-alpha) + self._tan_alpha = numpy.tan(-alpha) self._r_ref = r_ref self._phi_ref = phi_ref self._Rs = Rs self._H = H - self._Cs = self._Cs0 = np.array(Cs) - self._ns = self._ns0 = np.arange(1, len(Cs) + 1) + self._Cs = self._Cs0 = numpy.array(Cs) + self._ns = self._ns0 = numpy.arange(1, len(Cs) + 1) self._omega = omega - self._rho0 = 1 / (4 * np.pi) + self._rho0 = 1 / (4 * numpy.pi) self._HNn = self._HNn0 = self._H * self._N * self._ns0 self.isNonAxi = True # Potential is not axisymmetric @@ -123,11 +118,11 @@ HISTORY: 2017-05-12 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 @@ -137,8 +132,8 @@ Bs = self._B(R) Ds = self._D(R) - return -self._H * np.exp(-(R-self._r_ref) / self._Rs) \ - * np.sum(self._Cs / Ks / Ds * np.cos(self._ns * self._gamma(R, phi - self._omega * t)) / np.cosh(Ks * z / Bs) ** Bs,axis=0) + return -self._H * numpy.exp(-(R-self._r_ref) / self._Rs) \ + * numpy.sum(self._Cs / Ks / Ds * numpy.cos(self._ns * self._gamma(R, phi - self._omega * t)) / numpy.cosh(Ks * z / Bs) ** Bs,axis=0) def _Rforce(self, R, z, phi=0, t=0): @@ -157,17 +152,17 @@ HISTORY: 2017-05-12 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 self._HNn=self._HNn0 - He = self._H * np.exp(-(R-self._r_ref)/self._Rs) + He = self._H * numpy.exp(-(R-self._r_ref)/self._Rs) Ks = self._K(R) Bs = self._B(R) @@ -180,15 +175,15 @@ g = self._gamma(R, phi - self._omega * t) dg_dR = self._dgamma_dR(R) - cos_ng = np.cos(self._ns * g) - sin_ng = np.sin(self._ns * g) + cos_ng = numpy.cos(self._ns * g) + sin_ng = numpy.sin(self._ns * g) zKB = z * Ks / Bs - sechzKB = 1 / np.cosh(zKB) + sechzKB = 1 / numpy.cosh(zKB) - return -He * np.sum(self._Cs * sechzKB**Bs / Ds * ((self._ns * dg_dR / Ks * sin_ng - + cos_ng * (z * np.tanh(zKB) * (dKs_dR/Ks - dBs_dR/Bs) - - dBs_dR / Ks * np.log(sechzKB) + return -He * numpy.sum(self._Cs * sechzKB**Bs / Ds * ((self._ns * dg_dR / Ks * sin_ng + + cos_ng * (z * numpy.tanh(zKB) * (dKs_dR/Ks - dBs_dR/Bs) + - dBs_dR / Ks * numpy.log(sechzKB) + dKs_dR / Ks**2 + dDs_dR / Ds / Ks)) + cos_ng / Ks / self._Rs),axis=0) @@ -210,11 +205,11 @@ HISTORY: 2017-05-25 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 @@ -225,9 +220,9 @@ Ds = self._D(R) zK_B = z * Ks / Bs - return -self._H * np.exp(-(R-self._r_ref) / self._Rs) \ - * np.sum(self._Cs / Ds * np.cos(self._ns * self._gamma(R, phi - self._omega * t)) - * np.tanh(zK_B) / np.cosh(zK_B)**Bs,axis=0) + return -self._H * numpy.exp(-(R-self._r_ref) / self._Rs) \ + * numpy.sum(self._Cs / Ds * numpy.cos(self._ns * self._gamma(R, phi - self._omega * t)) + * numpy.tanh(zK_B) / numpy.cosh(zK_B)**Bs,axis=0) def _phiforce(self, R, z, phi=0, t=0): @@ -246,11 +241,11 @@ HISTORY: 2017-05-25 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 @@ -261,8 +256,8 @@ Bs = self._B(R) Ds = self._D(R) - return -self._H * np.exp(-(R-self._r_ref) / self._Rs) \ - * np.sum(self._N * self._ns * self._Cs / Ds / Ks / np.cosh(z * Ks / Bs)**Bs * np.sin(self._ns * g),axis=0) + return -self._H * numpy.exp(-(R-self._r_ref) / self._Rs) \ + * numpy.sum(self._N * self._ns * self._Cs / Ds / Ks / numpy.cosh(z * Ks / Bs)**Bs * numpy.sin(self._ns * g),axis=0) def _R2deriv(self, R, z, phi=0, t=0): @@ -282,18 +277,18 @@ HISTORY: 2017-05-31 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 self._HNn=self._HNn0 Rs = self._Rs - He = self._H * np.exp(-(R-self._r_ref)/self._Rs) + He = self._H * numpy.exp(-(R-self._r_ref)/self._Rs) Ks = self._K(R) Bs = self._B(R) @@ -320,17 +315,17 @@ dg_dR = self._dgamma_dR(R) d2g_dR2 = self._N / R**2 / self._tan_alpha - sin_ng = np.sin(self._ns * g) - cos_ng = np.cos(self._ns * g) + sin_ng = numpy.sin(self._ns * g) + cos_ng = numpy.cos(self._ns * g) zKB = z * Ks / Bs - sechzKB = 1 / np.cosh(zKB) + sechzKB = 1 / numpy.cosh(zKB) sechzKB_Bs = sechzKB**Bs - log_sechzKB = np.log(sechzKB) - tanhzKB = np.tanh(zKB) + log_sechzKB = numpy.log(sechzKB) + tanhzKB = numpy.tanh(zKB) ztanhzKB = z * tanhzKB - return -He / Rs * (np.sum(self._Cs * sechzKB_Bs / Ds + return -He / Rs * (numpy.sum(self._Cs * sechzKB_Bs / Ds * ((self._ns * dg_dR / Ks * sin_ng + cos_ng * (ztanhzKB * (dKs_dR/Ks - dBs_dR/Bs) - dBs_dR / Ks * log_sechzKB @@ -381,11 +376,11 @@ HISTORY: 2017-05-26 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 @@ -396,10 +391,10 @@ Bs = self._B(R) Ds = self._D(R) zKB = z * Ks / Bs - tanh2_zKB = np.tanh(zKB)**2 + tanh2_zKB = numpy.tanh(zKB)**2 - return -self._H * np.exp(-(R-self._r_ref)/self._Rs) \ - * np.sum(self._Cs * Ks / Ds * ((tanh2_zKB - 1) / Bs + tanh2_zKB) * np.cos(self._ns * g) / np.cosh(zKB)**Bs,axis=0) + return -self._H * numpy.exp(-(R-self._r_ref)/self._Rs) \ + * numpy.sum(self._Cs * Ks / Ds * ((tanh2_zKB - 1) / Bs + tanh2_zKB) * numpy.cos(self._ns * g) / numpy.cosh(zKB)**Bs,axis=0) def _phi2deriv(self, R, z, phi=0, t=0): @@ -419,11 +414,11 @@ HISTORY: 2017-05-29 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 @@ -434,8 +429,8 @@ Bs = self._B(R) Ds = self._D(R) - return self._H * np.exp(-(R-self._r_ref) / self._Rs) \ - * np.sum(self._Cs * self._N**2. * self._ns**2. / Ds / Ks / np.cosh(z*Ks/Bs)**Bs * np.cos(self._ns*g),axis=0) + return self._H * numpy.exp(-(R-self._r_ref) / self._Rs) \ + * numpy.sum(self._Cs * self._N**2. * self._ns**2. / Ds / Ks / numpy.cosh(z*Ks/Bs)**Bs * numpy.cos(self._ns*g),axis=0) def _Rzderiv(self, R, z, phi=0., t=0.): @@ -455,18 +450,18 @@ HISTORY: 2017-05-12 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 self._HNn=self._HNn0 Rs = self._Rs - He = self._H * np.exp(-(R-self._r_ref)/self._Rs) + He = self._H * numpy.exp(-(R-self._r_ref)/self._Rs) Ks = self._K(R) Bs = self._B(R) @@ -479,16 +474,16 @@ g = self._gamma(R, phi - self._omega * t) dg_dR = self._dgamma_dR(R) - cos_ng = np.cos(self._ns * g) - sin_ng = np.sin(self._ns * g) + cos_ng = numpy.cos(self._ns * g) + sin_ng = numpy.sin(self._ns * g) zKB = z * Ks / Bs - sechzKB = 1 / np.cosh(zKB) + sechzKB = 1 / numpy.cosh(zKB) sechzKB_Bs = sechzKB**Bs - log_sechzKB = np.log(sechzKB) - tanhzKB = np.tanh(zKB) + log_sechzKB = numpy.log(sechzKB) + tanhzKB = numpy.tanh(zKB) - return - He * np.sum(sechzKB_Bs * self._Cs / Ds * (Ks * tanhzKB * (self._ns * dg_dR / Ks * sin_ng + return - He * numpy.sum(sechzKB_Bs * self._Cs / Ds * (Ks * tanhzKB * (self._ns * dg_dR / Ks * sin_ng + cos_ng * (z * tanhzKB * (dKs_dR/Ks - dBs_dR/Bs) - dBs_dR / Ks * log_sechzKB + dKs_dR / Ks**2 @@ -516,17 +511,17 @@ HISTORY: 2017-06-09 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 self._HNn=self._HNn0 - He = self._H * np.exp(-(R - self._r_ref) / self._Rs) + He = self._H * numpy.exp(-(R - self._r_ref) / self._Rs) Ks = self._K(R) Bs = self._B(R) @@ -539,16 +534,16 @@ g = self._gamma(R, phi - self._omega * t) dg_dR = self._dgamma_dR(R) - cos_ng = np.cos(self._ns * g) - sin_ng = np.sin(self._ns * g) + cos_ng = numpy.cos(self._ns * g) + sin_ng = numpy.sin(self._ns * g) zKB = z * Ks / Bs - sechzKB = 1 / np.cosh(zKB) + sechzKB = 1 / numpy.cosh(zKB) sechzKB_Bs = sechzKB ** Bs - return - He * np.sum(self._Cs * sechzKB_Bs / Ds * self._ns * self._N + return - He * numpy.sum(self._Cs * sechzKB_Bs / Ds * self._ns * self._N * (- self._ns * dg_dR / Ks * cos_ng - + sin_ng * (z * np.tanh(zKB) * (dKs_dR / Ks - dBs_dR / Bs) - + 1/Ks * (-dBs_dR * np.log(sechzKB) + + sin_ng * (z * numpy.tanh(zKB) * (dKs_dR / Ks - dBs_dR / Bs) + + 1/Ks * (-dBs_dR * numpy.log(sechzKB) + dKs_dR / Ks + dDs_dR / Ds + 1 / self._Rs))),axis=0) @@ -571,11 +566,11 @@ HISTORY: 2017-05-12 Jack Hong (UBC) """ - if isinstance(R,np.ndarray) or isinstance(z,np.ndarray): - nR= len(R) if isinstance(R,np.ndarray) else len(z) - self._Cs=np.transpose(np.array([self._Cs0,]*nR)) - self._ns=np.transpose(np.array([self._ns0,]*nR)) - self._HNn=np.transpose(np.array([self._HNn0,]*nR)) + if isinstance(R,numpy.ndarray) or isinstance(z,numpy.ndarray): + nR= len(R) if isinstance(R,numpy.ndarray) else len(z) + self._Cs=numpy.transpose(numpy.array([self._Cs0,]*nR)) + self._ns=numpy.transpose(numpy.array([self._ns0,]*nR)) + self._HNn=numpy.transpose(numpy.array([self._HNn0,]*nR)) else: self._Cs=self._Cs0 self._ns=self._ns0 @@ -589,9 +584,9 @@ ng = self._ns * g zKB = z * Ks / Bs - sech_zKB = 1 / np.cosh(zKB) - tanh_zKB = np.tanh(zKB) - log_sech_zKB = np.log(sech_zKB) + sech_zKB = 1 / numpy.cosh(zKB) + tanh_zKB = numpy.tanh(zKB) + log_sech_zKB = numpy.log(sech_zKB) # numpy of E as defined in the appendix of the paper. E = 1 + Ks * self._H / Ds * (1 - 0.3 / (1 + 0.3 * Ks * self._H) ** 2) - R / self._Rs \ @@ -605,10 +600,10 @@ - (0.4 * (Ks * self._H) ** 2 * zKB * sech_zKB) ** 2 / Bs \ + 1.2 * (Ks * self._H) ** 2 * zKB * tanh_zKB - return np.sum(self._Cs * self._rho0 * (self._H / (Ds * R)) * np.exp(-(R - self._r_ref) / self._Rs) - * sech_zKB**Bs * (np.cos(ng) * (Ks * R * (Bs + 1) / Bs * sech_zKB**2 + return numpy.sum(self._Cs * self._rho0 * (self._H / (Ds * R)) * numpy.exp(-(R - self._r_ref) / self._Rs) + * sech_zKB**Bs * (numpy.cos(ng) * (Ks * R * (Bs + 1) / Bs * sech_zKB**2 - 1 / Ks / R * (E**2 + rE)) - - 2 * np.sin(ng)* E * np.cos(self._alpha)),axis=0) + - 2 * numpy.sin(ng)* E * numpy.cos(self._alpha)),axis=0) def OmegaP(self): """ @@ -627,7 +622,7 @@ def _gamma(self, R, phi): """Return gamma. (eqn 3 in the paper)""" - return self._N * (phi - self._phi_ref - np.log(R / self._r_ref) / self._tan_alpha) + return self._N * (phi - self._phi_ref - numpy.log(R / self._r_ref) / self._tan_alpha) def _dgamma_dR(self, R): """Return the first derivative of gamma wrt R.""" diff -Nru galpy-1.5/galpy/potential/SteadyLogSpiralPotential.py galpy-1.6.0.post0/galpy/potential/SteadyLogSpiralPotential.py --- galpy-1.5/galpy/potential/SteadyLogSpiralPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/SteadyLogSpiralPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,12 +1,12 @@ ############################################################################### # SteadyLogSpiralPotential: a steady-state spiral potential ############################################################################### -import math -from galpy.util import bovy_conversion +import numpy +from ..util import bovy_conversion from .planarPotential import planarPotential, _APY_LOADED if _APY_LOADED: from astropy import units -_degtorad= math.pi/180. +_degtorad= numpy.pi/180. class SteadyLogSpiralPotential(planarPotential): """Class that implements a steady-state spiral potential @@ -19,7 +19,7 @@ """ def __init__(self,amp=1.,omegas=0.65,A=-0.035, - alpha=-7.,m=2,gamma=math.pi/4.,p=None, + alpha=-7.,m=2,gamma=numpy.pi/4.,p=None, tform=None,tsteady=None,ro=None,vo=None): """ NAME: @@ -77,10 +77,10 @@ self._m= m self._gamma= gamma if not p is None: - self._alpha= self._m/math.tan(p) + self._alpha= self._m/numpy.tan(p) else: self._alpha= alpha - self._ts= 2.*math.pi/self._omegas + self._ts= 2.*numpy.pi/self._omegas if not tform is None: self._tform= tform*self._ts else: @@ -118,7 +118,7 @@ smooth= 1. else: smooth= 1. - return smooth*self._A/self._alpha*math.cos(self._alpha*math.log(R) + return smooth*self._A/self._alpha*numpy.cos(self._alpha*numpy.log(R) -self._m*(phi-self._omegas*t -self._gamma)) @@ -148,7 +148,7 @@ smooth= 1. else: smooth= 1. - return smooth*self._A/R*math.sin(self._alpha*math.log(R) + return smooth*self._A/R*numpy.sin(self._alpha*numpy.log(R) -self._m*(phi-self._omegas*t -self._gamma)) @@ -178,7 +178,7 @@ smooth= 1. else: smooth= 1. - return -smooth*self._A/self._alpha*self._m*math.sin(self._alpha*math.log(R) + return -smooth*self._A/self._alpha*self._m*numpy.sin(self._alpha*numpy.log(R) -self._m*(phi -self._omegas*t -self._gamma)) diff -Nru galpy-1.5/galpy/potential/TransientLogSpiralPotential.py galpy-1.6.0.post0/galpy/potential/TransientLogSpiralPotential.py --- galpy-1.5/galpy/potential/TransientLogSpiralPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/TransientLogSpiralPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -1,12 +1,12 @@ ############################################################################### # TransientLogSpiralPotential: a transient spiral potential ############################################################################### -import math -from galpy.util import bovy_conversion +import numpy +from ..util import bovy_conversion from .planarPotential import planarPotential, _APY_LOADED if _APY_LOADED: from astropy import units -_degtorad= math.pi/180. +_degtorad= numpy.pi/180. class TransientLogSpiralPotential(planarPotential): """Class that implements a steady-state spiral potential @@ -22,7 +22,7 @@ """ def __init__(self,amp=1.,omegas=0.65,A=-0.035, - alpha=-7.,m=2,gamma=math.pi/4.,p=None, + alpha=-7.,m=2,gamma=numpy.pi/4.,p=None, sigma=1.,to=0.,ro=None,vo=None): """ NAME: @@ -89,7 +89,7 @@ self._to= to self._sigma2= sigma**2. if not p is None: - self._alpha= self._m/math.tan(p) + self._alpha= self._m/numpy.tan(p) else: self._alpha= alpha self.hasC= True @@ -109,8 +109,8 @@ HISTORY: 2011-03-27 - Started - Bovy (NYU) """ - return self._A*math.exp(-(t-self._to)**2./2./self._sigma2)\ - /self._alpha*math.cos(self._alpha*math.log(R) + return self._A*numpy.exp(-(t-self._to)**2./2./self._sigma2)\ + /self._alpha*numpy.cos(self._alpha*numpy.log(R) -self._m*(phi-self._omegas*t-self._gamma)) def _Rforce(self,R,phi=0.,t=0.): @@ -128,8 +128,8 @@ HISTORY: 2010-11-24 - Written - Bovy (NYU) """ - return self._A*math.exp(-(t-self._to)**2./2./self._sigma2)\ - /R*math.sin(self._alpha*math.log(R) + return self._A*numpy.exp(-(t-self._to)**2./2./self._sigma2)\ + /R*numpy.sin(self._alpha*numpy.log(R) -self._m*(phi-self._omegas*t-self._gamma)) def _phiforce(self,R,phi=0.,t=0.): @@ -147,8 +147,8 @@ HISTORY: 2010-11-24 - Written - Bovy (NYU) """ - return -self._A*math.exp(-(t-self._to)**2./2./self._sigma2)\ - /self._alpha*self._m*math.sin(self._alpha*math.log(R) + return -self._A*numpy.exp(-(t-self._to)**2./2./self._sigma2)\ + /self._alpha*self._m*numpy.sin(self._alpha*numpy.log(R) -self._m*(phi-self._omegas*t -self._gamma)) diff -Nru galpy-1.5/galpy/potential/TwoPowerSphericalPotential.py galpy-1.6.0.post0/galpy/potential/TwoPowerSphericalPotential.py --- galpy-1.5/galpy/potential/TwoPowerSphericalPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/TwoPowerSphericalPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -6,10 +6,9 @@ # rho(r)= ------------------------------------ # (r/a)^\alpha (1+r/a)^(\beta-\alpha) ############################################################################### -import math as m import numpy -from scipy import special, optimize, integrate -from galpy.util import bovy_conversion +from scipy import special, optimize +from ..util import bovy_conversion from .Potential import Potential, kms_to_kpcGyrDecorator, _APY_LOADED if _APY_LOADED: from astropy import units @@ -55,18 +54,27 @@ 2010-07-09 - Started - Bovy (NYU) """ - if alpha == round(alpha) and beta == round(beta): - Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') - integerSelf= TwoPowerIntegerSphericalPotential(amp=1.,a=a, - alpha=int(alpha), - beta=int(beta), - normalize=False) - self.integerSelf= integerSelf - else: - Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') - self.integerSelf= None + # Instantiate + Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') + # _specialSelf for special cases (Dehnen class, Dehnen core, Hernquist, Jaffe, NFW) + self._specialSelf= None + if ((self.__class__ == TwoPowerSphericalPotential) & + (alpha == round(alpha)) & (beta == round(beta))): + if int(alpha) == 0 and int(beta) == 4: + self._specialSelf=\ + DehnenCoreSphericalPotential(amp=1.,a=a, + normalize=False) + elif int(alpha) == 1 and int(beta) == 4: + self._specialSelf=\ + HernquistPotential(amp=1.,a=a,normalize=False) + elif int(alpha) == 2 and int(beta) == 4: + self._specialSelf= JaffePotential(amp=1.,a=a,normalize=False) + elif int(alpha) == 1 and int(beta) == 3: + self._specialSelf= NFWPotential(amp=1.,a=a,normalize=False) + # correcting quantities if _APY_LOADED and isinstance(a,units.Quantity): - a= a.to(units.kpc).value/self._ro + a= a.to_value(units.kpc)/self._ro + # setting properties self.a= a self._scale= self.a self.alpha= alpha @@ -77,7 +85,7 @@ self.normalize(normalize) return None - def _evaluate(self,R,z,phi=0.,t=0.,_forceFloatEval=False): + def _evaluate(self,R,z,phi=0.,t=0.): """ NAME: _evaluate @@ -93,8 +101,8 @@ HISTORY: 2010-07-09 - Started - Bovy (NYU) """ - if not _forceFloatEval and not self.integerSelf == None: - return self.integerSelf._evaluate(R,z,phi=phi,t=t) + if self._specialSelf is not None: + return self._specialSelf._evaluate(R,z,phi=phi,t=t) elif self.beta == 3.: r= numpy.sqrt(R**2.+z**2.) return (1./self.a)\ @@ -113,7 +121,7 @@ -self.a/r) -special.gamma(3.-self.alpha)/special.gamma(self.beta-self.alpha))/r - def _Rforce(self,R,z,phi=0.,t=0.,_forceFloatEval=False): + def _Rforce(self,R,z,phi=0.,t=0.): """ NAME: _Rforce @@ -129,8 +137,8 @@ HISTORY: 2010-07-09 - Written - Bovy (NYU) """ - if not _forceFloatEval and not self.integerSelf == None: - return self.integerSelf._Rforce(R,z,phi=phi,t=t) + if self._specialSelf is not None: + return self._specialSelf._Rforce(R,z,phi=phi,t=t) else: r= numpy.sqrt(R**2.+z**2.) return -R/r**self.alpha*self.a**(self.alpha-3.)/(3.-self.alpha)\ @@ -139,7 +147,7 @@ 4.-self.alpha, -r/self.a) - def _zforce(self,R,z,phi=0.,t=0.,_forceFloatEval=False): + def _zforce(self,R,z,phi=0.,t=0.): """ NAME: _zforce @@ -155,8 +163,8 @@ HISTORY: 2010-07-09 - Written - Bovy (NYU) """ - if not _forceFloatEval and not self.integerSelf == None: - return self.integerSelf._zforce(R,z,phi=phi,t=t) + if self._specialSelf is not None: + return self._specialSelf._zforce(R,z,phi=phi,t=t) else: r= numpy.sqrt(R**2.+z**2.) return -z/r**self.alpha*self.a**(self.alpha-3.)/(3.-self.alpha)\ @@ -182,7 +190,7 @@ 2010-08-08 - Written - Bovy (NYU) """ r= numpy.sqrt(R**2.+z**2.) - return (self.a/r)**self.alpha/(1.+r/self.a)**(self.beta-self.alpha)/4./m.pi/self.a**3. + return (self.a/r)**self.alpha/(1.+r/self.a)**(self.beta-self.alpha)/4./numpy.pi/self.a**3. def _z2deriv(self,R,z,phi=0.,t=0.): """ @@ -217,95 +225,309 @@ HISTORY: 2014-04-01 - Written - Erkal (IoA) """ - if z is None: r= R - else: r= numpy.sqrt(R**2.+z**2.) + r= R if z is None else numpy.sqrt(R**2.+z**2.) return (r/self.a)**(3.-self.alpha)/(3.-self.alpha)*special.hyp2f1(3.-self.alpha,-self.alpha+self.beta,4.-self.alpha,-r/self.a) -class TwoPowerIntegerSphericalPotential(TwoPowerSphericalPotential): - """Class that implements the two-power-density spherical potentials in - the case of integer powers""" - def __init__(self,amp=1.,a=1.,alpha=1,beta=3,normalize=False, - ro=None,vo=None): +class DehnenSphericalPotential(TwoPowerSphericalPotential): + """Class that implements the Dehnen Spherical Potential from `Dehnen (1993) `_ + + .. math:: + + \\rho(r) = \\frac{\\mathrm{amp}(3-\\alpha)}{4\\,\\pi\\,a^3}\\,\\frac{1}{(r/a)^{\\alpha}\\,(1+r/a)^{4-\\alpha}} + """ + + def __init__(self,amp=1.,a=1.,alpha=1.5,normalize=False,ro=None,vo=None): """ NAME: + __init__ + PURPOSE: - initialize a two-power-density potential for integer powers + + initialize a Dehnen Spherical Potential; note that the amplitude definitio used here does NOT match that of Dehnen (1993) + INPUT: + amp - amplitude to be applied to the potential (default: 1); can be a Quantity with units of mass or Gxmass + a - scale radius (can be Quantity) - alpha - inner power (default: NFW) - beta - outer power (default: NFW) - normalize - if True, normalize such that vc(1.,0.)=1., or, if - given as a number, such that the force is this fraction - of the force necessary to make vc(1.,0.)=1. + + alpha - inner power, restricted to [0, 3) + + normalize - if True, normalize such that vc(1.,0.)=1., or, if given as a number, such that the force is this fraction of the force necessary to make vc(1.,0.)=1. + ro=, vo= distance and velocity scales for translation into internal units (default from configuration file) + OUTPUT: + (none) + HISTORY: - 2010-07-09 - Started - Bovy (NYU) + + 2019-10-07 - Started - Starkman (UofT) + """ - if alpha == 1 and beta == 4: - Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') - HernquistSelf= HernquistPotential(amp=1.,a=a,normalize=False) - self.HernquistSelf= HernquistSelf - self.JaffeSelf= None - self.NFWSelf= None - elif alpha == 2 and beta == 4: - Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') - JaffeSelf= JaffePotential(amp=1.,a=a,normalize=False) - self.HernquistSelf= None - self.JaffeSelf= JaffeSelf - self.NFWSelf= None - elif alpha == 1 and beta == 3: - Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') - NFWSelf= NFWPotential(amp=1.,a=a,normalize=False) - self.HernquistSelf= None - self.JaffeSelf= None - self.NFWSelf= NFWSelf - else: - Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') - self.HernquistSelf= None - self.JaffeSelf= None - self.NFWSelf= None - if _APY_LOADED and isinstance(a,units.Quantity): - a= a.to(units.kpc).value/self._ro - self.alpha= alpha - self.beta= beta - self.a= a - self._scale= self.a - if normalize or \ - (isinstance(normalize,(int,float)) \ - and not isinstance(normalize,bool)): #pragma: no cover - self.normalize(normalize) + if (alpha < 0.) or (alpha >= 3.): + raise IOError('DehnenSphericalPotential requires 0 <= alpha < 3') + # instantiate + TwoPowerSphericalPotential.__init__( + self,amp=amp,a=a,alpha=alpha,beta=4, + normalize=normalize,ro=ro,vo=vo) + # make special-self and protect subclasses + self._specialSelf= None + if ((self.__class__ == DehnenSphericalPotential) & + (alpha == round(alpha))): + if round(alpha) == 0: + self._specialSelf=\ + DehnenCoreSphericalPotential(amp=1.,a=a, + normalize=False) + elif round(alpha) == 1: + self._specialSelf=\ + HernquistPotential(amp=1.,a=a,normalize=False) + elif round(alpha) == 2: + self._specialSelf= JaffePotential(amp=1.,a=a,normalize=False) + # set properties + self.hasC= True + self.hasC_dxdv= True + self.hasC_dens= True return None def _evaluate(self,R,z,phi=0.,t=0.): + """ + NAME: + _evaluate + PURPOSE: + evaluate the potential at R,z + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + Phi(R,z) + HISTORY: + 2019-11-20 - Written - Starkman (UofT) + """ + if self._specialSelf is not None: + return self._specialSelf._evaluate(R,z,phi=phi,t=t) + else: # valid for alpha != 2, 3 + r= numpy.sqrt(R**2.+z**2.) + return -((1.-(r/(r+self.a))**(2.-self.alpha))/ + (self.a * (2.-self.alpha) * (3.-self.alpha))) + + def _Rforce(self,R,z,phi=0.,t=0.): """ NAME: - _evaluate + _Rforce PURPOSE: - evaluate the potential at R,z + evaluate the radial force for this potential INPUT: R - Galactocentric cylindrical radius z - vertical height phi - azimuth t - time OUTPUT: - Phi(R,z) + the radial force HISTORY: - 2010-07-09 - Started - Bovy (NYU) + 2019-11-20 - Written - Starkman (UofT) """ - if not self.HernquistSelf == None: - return self.HernquistSelf._evaluate(R,z,phi=phi,t=t) - elif not self.JaffeSelf == None: - return self.JaffeSelf._evaluate(R,z,phi=phi,t=t) - elif not self.NFWSelf == None: - return self.NFWSelf._evaluate(R,z,phi=phi,t=t) + if self._specialSelf is not None: + return self._specialSelf._Rforce(R,z,phi=phi,t=t) else: - return TwoPowerSphericalPotential._evaluate(self,R,z, - phi=phi,t=t, - _forceFloatEval=True) + r= numpy.sqrt(R**2.+z**2.) + return -R/r**self.alpha*(self.a+r)**(self.alpha-3.)/(3.-self.alpha) + + def _R2deriv(self,R,z,phi=0.,t=0.): + """ + NAME: + _R2deriv + PURPOSE: + evaluate the second radial derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t- time + OUTPUT: + the second radial derivative + HISTORY: + 2019-10-11 - Written - Starkman (UofT) + """ + if self._specialSelf is not None: + return self._specialSelf._R2deriv(R, z, phi=phi, t=t) + a, alpha = self.a, self.alpha + r = numpy.sqrt(R**2. + z**2.) + # formula not valid for alpha=2,3, (integers?) + return (numpy.power(r, -2.-alpha)*numpy.power(r+a, alpha-4.)* + (-a*r**2. + (2.*R**2.-z**2.)*r + a*alpha*R**2.)/ + (alpha - 3.)) + + def _zforce(self,R,z,phi=0.,t=0.): + """ + NAME: + _zforce + PURPOSE: + evaluate the vertical force for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + the vertical force + HISTORY: + 2019-11-21 - Written - Starkman (UofT) + """ + if self._specialSelf is not None: + return self._specialSelf._zforce(R,z,phi=phi,t=t) + else: + r= numpy.sqrt(R**2.+z**2.) + return -z/r**self.alpha*(self.a+r)**(self.alpha-3.)/(3.-self.alpha) + + def _z2deriv(self,R,z,phi=0.,t=0.): + r""" + NAME: + _z2deriv + PURPOSE: + evaluate the second vertical derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t- time + OUTPUT: + the second vertical derivative + HISTORY: + 2019-10-20 - Written - Starkman (UofT) + """ + return self._R2deriv(z,R,phi=phi,t=t) + + def _Rzderiv(self,R,z,phi=0.,t=0.): + """ + NAME: + _Rzderiv + PURPOSE: + evaluate the mixed R,z derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t- time + OUTPUT: + d2phi/dR/dz + HISTORY: + 2019-10-11 - Written - Starkman (UofT) + """ + if self._specialSelf is not None: + return self._specialSelf._Rzderiv(R, z, phi=phi, t=t) + a, alpha= self.a, self.alpha + r= numpy.sqrt(R**2.+z**2.) + return ((R*z*numpy.power(r,-2.-alpha)*numpy.power(a+r,alpha-4.) + *(3*r+a*alpha))/(alpha-3)) + + def _dens(self,R,z,phi=0.,t=0.): + """ + NAME: + _dens + PURPOSE: + evaluate the density for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + the density + HISTORY: + 2019-11-20 - Written - Starkman (UofT) + """ + r= numpy.sqrt(R**2.+z**2.) + return (self.a/r)**self.alpha/(1.+r/self.a)**(4.-self.alpha)/4./numpy.pi/self.a**3. + + def _mass(self,R,z=0.,t=0.): + """ + NAME: + _mass + PURPOSE: + evaluate the mass within R for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + t - time + OUTPUT: + the mass enclosed + HISTORY: + 2019-11-20 - Written - Starkman (UofT) + """ + r= R if z is None else numpy.sqrt(R**2.+z**2.) + return (r/(r+self.a))**(3.-self.alpha)/(3.-self.alpha) + +class DehnenCoreSphericalPotential(DehnenSphericalPotential): + """Class that implements the Dehnen Spherical Potential from `Dehnen (1993) `_ with alpha=0 (corresponding to an inner core) + + .. math:: + + \\rho(r) = \\frac{\\mathrm{amp}}{12\\,\\pi\\,a^3}\\,\\frac{1}{(1+r/a)^{4}} + """ + + def __init__(self,amp=1.,a=1.,normalize=False,ro=None,vo=None): + """ + NAME: + + __init__ + + PURPOSE: + + initialize a cored Dehnen Spherical Potential; note that the amplitude definition used here does NOT match that of Dehnen (1993) + + INPUT: + + amp - amplitude to be applied to the potential (default: 1); can be a Quantity with units of mass or Gxmass + + a - scale radius (can be Quantity) + + alpha - inner power, restricted to [0, 3) + + normalize - if True, normalize such that vc(1.,0.)=1., or, if given as a number, such that the force is this fraction of the force necessary to make vc(1.,0.)=1. + + ro=, vo= distance and velocity scales for translation into internal units (default from configuration file) + + OUTPUT: + + (none) + + HISTORY: + + 2019-10-07 - Started - Starkman (UofT) + + """ + DehnenSphericalPotential.__init__( + self,amp=amp,a=a,alpha=0, + normalize=normalize,ro=ro,vo=vo) + # set properties explicitly + self.hasC= True + self.hasC_dxdv= True + self.hasC_dens= True + return None + + def _evaluate(self,R,z,phi=0.,t=0.): + """ + NAME: + _evaluate + PURPOSE: + evaluate the potential at R,z + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + Phi(R,z) + HISTORY: + 2019-11-20 - Written - Starkman (UofT) + """ + r= numpy.sqrt(R**2.+z**2.) + return -((1.-numpy.square(r/(r+self.a)))/(6.*self.a)) def _Rforce(self,R,z,phi=0.,t=0.): """ @@ -321,18 +543,28 @@ OUTPUT: the radial force HISTORY: - 2010-07-09 - Written - Bovy (NYU) + 2019-11-20 - Written - Starkman (UofT) """ - if not self.HernquistSelf == None: - return self.HernquistSelf._Rforce(R,z,phi=phi,t=t) - elif not self.JaffeSelf == None: - return self.JaffeSelf._Rforce(R,z,phi=phi,t=t) - elif not self.NFWSelf == None: - return self.NFWSelf._Rforce(R,z,phi=phi,t=t) - else: - return TwoPowerSphericalPotential._Rforce(self,R,z, - phi=phi,t=t, - _forceFloatEval=True) + return -R/numpy.power(numpy.sqrt(R**2.+z**2.)+self.a,3.)/3. + + def _R2deriv(self,R,z,phi=0.,t=0.): + """ + NAME: + _R2deriv + PURPOSE: + evaluate the second radial derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t- time + OUTPUT: + the second radial derivative + HISTORY: + 2019-10-11 - Written - Starkman (UofT) + """ + r = numpy.sqrt(R**2.+z**2.) + return -(((2.*R**2.-z**2.)-self.a*r)/(3.*r*numpy.power(r+self.a,4.))) def _zforce(self,R,z,phi=0.,t=0.): """ @@ -348,20 +580,87 @@ OUTPUT: the vertical force HISTORY: - 2010-07-09 - Written - Bovy (NYU) + 2019-11-21 - Written - Starkman (UofT) """ - if not self.HernquistSelf == None: - return self.HernquistSelf._zforce(R,z,phi=phi,t=t) - elif not self.JaffeSelf == None: - return self.JaffeSelf._zforce(R,z,phi=phi,t=t) - elif not self.NFWSelf == None: - return self.NFWSelf._zforce(R,z,phi=phi,t=t) - else: - return TwoPowerSphericalPotential._zforce(self,R,z, - phi=phi,t=t, - _forceFloatEval=True) + r= numpy.sqrt(R**2.+z**2.) + return -z/numpy.power(self.a+r,3.)/3. + + def _z2deriv(self,R,z,phi=0.,t=0.): + r""" + NAME: + _z2deriv + PURPOSE: + evaluate the second vertical derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t- time + OUTPUT: + the second vertical derivative + HISTORY: + 2019-10-20 - Written - Starkman (UofT) + """ + return self._R2deriv(z,R,phi=phi,t=t) + + def _Rzderiv(self,R,z,phi=0.,t=0.): + """ + NAME: + _Rzderiv + PURPOSE: + evaluate the mixed R,z derivative for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t- time + OUTPUT: + d2phi/dR/dz + HISTORY: + 2019-10-11 - Written - Starkman (UofT) + """ + a= self.a + r= numpy.sqrt(R**2.+z**2.) + return -(R * z/r/numpy.power(a+r,4.)) -class HernquistPotential(TwoPowerIntegerSphericalPotential): + def _dens(self,R,z,phi=0.,t=0.): + """ + NAME: + _dens + PURPOSE: + evaluate the density for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + phi - azimuth + t - time + OUTPUT: + the density + HISTORY: + 2019-11-20 - Written - Starkman (UofT) + """ + r= numpy.sqrt(R**2.+z**2.) + return 1./(1.+r/self.a)**4./4./numpy.pi/self.a**3. + + def _mass(self,R,z=0.,t=0.): + """ + NAME: + _mass + PURPOSE: + evaluate the mass within R for this potential + INPUT: + R - Galactocentric cylindrical radius + z - vertical height + t - time + OUTPUT: + the mass enclosed + HISTORY: + 2019-11-20 - Written - Starkman (UofT) + """ + r= R if z is None else numpy.sqrt(R**2.+z**2.) + return (r/(r+self.a))**3./3. + +class HernquistPotential(DehnenSphericalPotential): """Class that implements the Hernquist potential .. math:: @@ -382,7 +681,7 @@ INPUT: - amp - amplitude to be applied to the potential (default: 1); can be a Quantity with units of mass or Gxmass + amp - amplitude to be applied to the potential (default: 1); can be a Quantity with units of mass or Gxmass (note that amp is 2 x [total mass] for the chosen definition of the Hernquist potential) a - scale radius (can be Quantity) @@ -399,20 +698,14 @@ 2010-07-09 - Written - Bovy (NYU) """ - Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') - if _APY_LOADED and isinstance(a,units.Quantity): - a= a.to(units.kpc).value/self._ro - self.a= a - self._scale= self.a - self.alpha= 1 - self.beta= 4 - if normalize or \ - (isinstance(normalize,(int,float)) \ - and not isinstance(normalize,bool)): - self.normalize(normalize) + DehnenSphericalPotential.__init__( + self,amp=amp,a=a,alpha=1, + normalize=normalize,ro=ro,vo=vo) + self._nemo_accname= 'Dehnen' + # set properties explicitly self.hasC= True self.hasC_dxdv= True - self._nemo_accname= 'Dehnen' + self.hasC_dens= True return None def _evaluate(self,R,z,phi=0.,t=0.): @@ -555,8 +848,7 @@ HISTORY: 2014-01-29 - Written - Bovy (IAS) """ - if z is None: r= R - else: r= numpy.sqrt(R**2.+z**2.) + r= R if z is None else numpy.sqrt(R**2.+z**2.) return (r/self.a)**2./2./(1.+r/self.a)**2. @kms_to_kpcGyrDecorator @@ -588,7 +880,7 @@ GM= self._amp*vo**2.*ro/2. return "0,1,%s,%s,0" % (GM,self.a*ro) -class JaffePotential(TwoPowerIntegerSphericalPotential): +class JaffePotential(DehnenSphericalPotential): """Class that implements the Jaffe potential .. math:: @@ -639,6 +931,7 @@ self.normalize(normalize) self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True return None def _evaluate(self,R,z,phi=0.,t=0.): @@ -782,11 +1075,10 @@ HISTORY: 2014-01-29 - Written - Bovy (IAS) """ - if z is None: r= R - else: r= numpy.sqrt(R**2.+z**2.) + r= R if z is None else numpy.sqrt(R**2.+z**2.) return r/self.a/(1.+r/self.a) -class NFWPotential(TwoPowerIntegerSphericalPotential): +class NFWPotential(TwoPowerSphericalPotential): """Class that implements the NFW potential .. math:: @@ -872,6 +1164,7 @@ self._scale= self.a self.hasC= True self.hasC_dxdv= True + self.hasC_dens= True self._nemo_accname= 'NFW' return None @@ -1018,12 +1311,11 @@ HISTORY: 2014-01-29 - Written - Bovy (IAS) """ - if z is None: r= R - else: r= numpy.sqrt(R**2.+z**2.) + r= R if z is None else numpy.sqrt(R**2.+z**2.) return numpy.log(1+r/self.a)-r/self.a/(1.+r/self.a) @bovy_conversion.physical_conversion('position',pop=False) - def rvir(self,H=70.,Om=0.3,overdens=200.,wrtcrit=False,ro=None,vo=None, + def rvir(self,H=70.,Om=0.3,t=0.,overdens=200.,wrtcrit=False,ro=None,vo=None, use_physical=False): # use_physical necessary bc of pop=False, does nothing inside """ NAME: @@ -1064,7 +1356,7 @@ else: od= overdens/bovy_conversion.dens_in_meanmatterdens(vo,ro, H=H,Om=Om) - dc= 12.*self.dens(self.a,0.,use_physical=False)/od + dc= 12.*self.dens(self.a,0.,t=t,use_physical=False)/od x= optimize.brentq(lambda y: (numpy.log(1.+y)-y/(1.+y))/y**3.-1./dc, 0.01,100.) return x*self.a diff -Nru galpy-1.5/galpy/potential/TwoPowerTriaxialPotential.py galpy-1.6.0.post0/galpy/potential/TwoPowerTriaxialPotential.py --- galpy-1.5/galpy/potential/TwoPowerTriaxialPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/TwoPowerTriaxialPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -207,6 +207,7 @@ self.normalize(normalize) self.hasC= not self._glorder is None self.hasC_dxdv= False + self.hasC_dens= self.hasC # works if mdens is defined, necessary for hasC return None def _psi(self,m): @@ -295,6 +296,7 @@ self.normalize(normalize) self.hasC= not self._glorder is None self.hasC_dxdv= False + self.hasC_dens= self.hasC # works if mdens is defined, necessary for hasC return None def _psi(self,m): @@ -395,7 +397,7 @@ if conc is None: self.a= a else: - from galpy.potential import NFWPotential + from ..potential import NFWPotential dum= NFWPotential(mvir=mvir,conc=conc,ro=self._ro,vo=self._vo, H=H,Om=Om,wrtcrit=wrtcrit,overdens=overdens) self.a= dum.a @@ -403,6 +405,7 @@ self._scale= self.a self.hasC= not self._glorder is None self.hasC_dxdv= False + self.hasC_dens= self.hasC # works if mdens is defined, necessary for hasC # Adjust amp self.a3= self.a**3 self._amp/= (4.*numpy.pi*self.a3) diff -Nru galpy-1.5/galpy/potential/verticalPotential.py galpy-1.6.0.post0/galpy/potential/verticalPotential.py --- galpy-1.5/galpy/potential/verticalPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/verticalPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -2,6 +2,7 @@ from .linearPotential import linearPotential from .planarPotential import planarPotential from .Potential import PotentialError, Potential, flatten +from .DissipativeForce import _isDissipative from ..util import bovy_conversion _APY_LOADED= True try: @@ -109,6 +110,8 @@ """ RZPot= flatten(RZPot) + if _isDissipative(RZPot): + raise NotImplementedError("Converting dissipative forces to 1D vertical potentials is currently not supported") if _APY_LOADED and isinstance(R,units.Quantity): if hasattr(RZPot,'_ro'): R= R.to(units.kpc).value/RZPot._ro @@ -165,6 +168,8 @@ """ Pot= flatten(Pot) + if _isDissipative(Pot): + raise NotImplementedError("Converting dissipative forces to 1D vertical potentials is currently not supported") if _APY_LOADED: if isinstance(R,units.Quantity): if hasattr(Pot,'_ro'): diff -Nru galpy-1.5/galpy/potential/WrapperPotential.py galpy-1.6.0.post0/galpy/potential/WrapperPotential.py --- galpy-1.5/galpy/potential/WrapperPotential.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/potential/WrapperPotential.py 2020-04-24 19:48:38.000000000 +0000 @@ -3,14 +3,14 @@ ############################################################################### from .Potential import Potential, _isNonAxi, _dim from .planarPotential import planarPotential -from .Potential import evaluatePotentials, \ - evaluateRforces, evaluatephiforces, evaluatezforces, \ +from .Potential import _evaluatePotentials, \ + _evaluateRforces, _evaluatephiforces, _evaluatezforces, \ evaluateR2derivs, evaluatez2derivs, \ evaluateRzderivs, evaluateDensities -from .planarPotential import evaluateplanarPotentials, \ - evaluateplanarRforces, evaluateplanarphiforces, \ +from .planarPotential import _evaluateplanarPotentials, \ + _evaluateplanarRforces, _evaluateplanarphiforces, \ evaluateplanarR2derivs - +from ..util.bovy_conversion import physical_compatible, get_physical def _new_obj(cls, kwargs, args): """Maps kwargs to cls.__new__""" return cls.__new__(cls, *args, **kwargs) @@ -73,6 +73,22 @@ Potential.__init__(self,amp=amp,ro=ro,vo=vo) self._pot= pot self.isNonAxi= _isNonAxi(self._pot) + # Check whether units are consistent between the wrapper and the + # wrapped potential + assert physical_compatible(self,self._pot), \ + """Physical unit conversion parameters (ro,vo) are not """\ + """compatible between this wrapper and the wrapped potential""" + # Transfer unit system if set for wrapped potential, but not here + phys_wrapped= get_physical(self._pot,include_set=True) + if not self._roSet and phys_wrapped['roSet']: + self.turn_physical_on(ro=phys_wrapped['ro'],vo=False) + if not self._voSet and phys_wrapped['voSet']: + self.turn_physical_on(vo=phys_wrapped['vo'],ro=False) + + def __repr__(self): + wrapped_repr= repr(self._pot) + return Potential.__repr__(self) + ', wrapper of' \ + + ''.join(['\n\t{}'.format(s) for s in wrapped_repr.split('\n')]) def __getattr__(self,attribute): if attribute == '_evaluate' \ @@ -88,27 +104,35 @@ def _wrap_pot_func(self,attribute): if attribute == '_evaluate': - return evaluatePotentials + return lambda p,R,Z,phi=0.,t=0.: \ + _evaluatePotentials(p,R,Z,phi=phi,t=t) elif attribute == '_dens': - return evaluateDensities + return lambda p,R,Z,phi=0.,t=0.: \ + evaluateDensities(p,R,Z,phi=phi,t=t,use_physical=False) elif attribute == '_Rforce': - return evaluateRforces + return lambda p,R,Z,phi=0.,t=0.: \ + _evaluateRforces(p,R,Z,phi=phi,t=t) elif attribute == '_zforce': - return evaluatezforces + return lambda p,R,Z,phi=0.,t=0.: \ + _evaluatezforces(p,R,Z,phi=phi,t=t) elif attribute == '_phiforce': - return evaluatephiforces + return lambda p,R,Z,phi=0.,t=0.: \ + _evaluatephiforces(p,R,Z,phi=phi,t=t) elif attribute == '_R2deriv': - return evaluateR2derivs + return lambda p,R,Z,phi=0.,t=0.: \ + evaluateR2derivs(p,R,Z,phi=phi,t=t,use_physical=False) elif attribute == '_z2deriv': - return evaluatez2derivs + return lambda p,R,Z,phi=0.,t=0.: \ + evaluatez2derivs(p,R,Z,phi=phi,t=t,use_physical=False) elif attribute == '_Rzderiv': - return evaluateRzderivs + return lambda p,R,Z,phi=0.,t=0.: \ + evaluateRzderivs(p,R,Z,phi=phi,t=t,use_physical=False) elif attribute == '_phi2deriv': return lambda p,R,Z,phi=0.,t=0.: \ - evaluatePotentials(p,R,Z,phi=phi,t=t,dphi=2) + _evaluatePotentials(p,R,Z,phi=phi,t=t,dphi=2) elif attribute == '_Rphideriv': return lambda p,R,Z,phi=0.,t=0.: \ - evaluatePotentials(p,R,Z,phi=phi,t=t,dR=1,dphi=1) + _evaluatePotentials(p,R,Z,phi=phi,t=t,dR=1,dphi=1) else: #pragma: no cover raise AttributeError("Attribute %s not found in for this WrapperPotential" % attribute) @@ -142,6 +166,22 @@ planarPotential.__init__(self,amp=amp,ro=ro,vo=vo) self._pot= pot self.isNonAxi= _isNonAxi(self._pot) + # Check whether units are consistent between the wrapper and the + # wrapped potential + assert physical_compatible(self,self._pot), \ + """Physical unit conversion parameters (ro,vo) are not """\ + """compatible between this wrapper and the wrapped potential""" + # Transfer unit system if set for wrapped potential, but not here + phys_wrapped= get_physical(self._pot,include_set=True) + if not self._roSet and phys_wrapped['roSet']: + self.turn_physical_on(ro=phys_wrapped['ro'],vo=False) + if not self._voSet and phys_wrapped['voSet']: + self.turn_physical_on(vo=phys_wrapped['vo'],ro=False) + + def __repr__(self): + wrapped_repr= repr(self._pot) + return Potential.__repr__(self) + ', wrapper of' \ + + ''.join(['\n\t{}'.format(s) for s in wrapped_repr.split('\n')]) def __getattr__(self,attribute): if attribute == '_evaluate' \ @@ -157,19 +197,23 @@ def _wrap_pot_func(self,attribute): if attribute == '_evaluate': - return evaluateplanarPotentials + return lambda p,R,phi=0.,t=0.: \ + _evaluateplanarPotentials(p,R,phi=phi,t=t) elif attribute == '_Rforce': - return evaluateplanarRforces + return lambda p,R,phi=0.,t=0.: \ + _evaluateplanarRforces(p,R,phi=phi,t=t) elif attribute == '_phiforce': - return evaluateplanarphiforces + return lambda p,R,phi=0.,t=0.: \ + _evaluateplanarphiforces(p,R,phi=phi,t=t) elif attribute == '_R2deriv': - return evaluateplanarR2derivs + return lambda p,R,phi=0.,t=0.: \ + evaluateplanarR2derivs(p,R,phi=phi,t=t,use_physical=False) elif attribute == '_phi2deriv': return lambda p,R,phi=0.,t=0.: \ - evaluateplanarPotentials(p,R,phi=phi,t=t,dphi=2) + _evaluateplanarPotentials(p,R,phi=phi,t=t,dphi=2) elif attribute == '_Rphideriv': return lambda p,R,phi=0.,t=0.: \ - evaluateplanarPotentials(p,R,phi=phi,t=t,dR=1,dphi=1) + _evaluateplanarPotentials(p,R,phi=phi,t=t,dR=1,dphi=1) else: #pragma: no cover raise AttributeError("Attribute %s not found in for this WrapperPotential" % attribute) diff -Nru galpy-1.5/galpy/util/bovy_ars.py galpy-1.6.0.post0/galpy/util/bovy_ars.py --- galpy-1.5/galpy/util/bovy_ars.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/bovy_ars.py 2020-04-24 19:48:38.000000000 +0000 @@ -26,9 +26,8 @@ #WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #POSSIBILITY OF SUCH DAMAGE. ############################################################################# -import scipy as sc +import numpy import scipy.stats as stats -import math as m #TO DO: #Throw errors in the sample_hull routine @@ -110,14 +109,14 @@ """ nx= len(abcissae) #Create the output arrays - xs= sc.zeros(nx) - hxs= sc.zeros(nx) - hpxs= sc.zeros(nx) - zs= sc.zeros(nx-1) - scum= sc.zeros(nx-1) - hus= sc.zeros(nx-1) + xs= numpy.zeros(nx) + hxs= numpy.zeros(nx) + hpxs= numpy.zeros(nx) + zs= numpy.zeros(nx-1) + scum= numpy.zeros(nx-1) + hus= numpy.zeros(nx-1) #Function evaluations - xs= sc.sort(abcissae) + xs= numpy.sort(abcissae) for ii in range(nx): hxs[ii]= hx(xs[ii],hxparams) hpxs[ii]= hpx(xs[ii],hxparams) @@ -132,23 +131,23 @@ hus[jj]= hpxs[jj]*(zs[jj]-xs[jj])+hxs[jj] #Calculate cu and scum if isDomainFinite[0]: - scum[0]= 1./hpxs[0]*(m.exp(hus[0])-m.exp( + scum[0]= 1./hpxs[0]*(numpy.exp(hus[0])-numpy.exp( hpxs[0]*(domain[0]-xs[0])+hxs[0])) else: - scum[0]= 1./hpxs[0]*m.exp(hus[0]) + scum[0]= 1./hpxs[0]*numpy.exp(hus[0]) if nx > 2: for jj in range(nx-2): if hpxs[jj+1] == 0.: - scum[jj+1]= (zs[jj+1]-zs[jj])*m.exp(hxs[jj+1]) + scum[jj+1]= (zs[jj+1]-zs[jj])*numpy.exp(hxs[jj+1]) else: - scum[jj+1]=1./hpxs[jj+1]*(m.exp(hus[jj+1])-m.exp(hus[jj])) + scum[jj+1]=1./hpxs[jj+1]*(numpy.exp(hus[jj+1])-numpy.exp(hus[jj])) if isDomainFinite[1]: - cu=1./hpxs[nx-1]*(m.exp(hpxs[nx-1]*( - domain[1]-xs[nx-1])+hxs[nx-1]) - m.exp(hus[nx-2])) + cu=1./hpxs[nx-1]*(numpy.exp(hpxs[nx-1]*( + domain[1]-xs[nx-1])+hxs[nx-1]) - numpy.exp(hus[nx-2])) else: - cu=- 1./hpxs[nx-1]*m.exp(hus[nx-2]) - cu= cu+sc.sum(scum) - scum= sc.cumsum(scum)/cu + cu=- 1./hpxs[nx-1]*numpy.exp(hus[nx-2]) + cu= cu+numpy.sum(scum) + scum= numpy.cumsum(scum)/cu out=[] out.append(cu) out.append(xs) @@ -188,12 +187,12 @@ candidate= sample_hull(thishull,domain,isDomainFinite) thishux, thishlx= evaluate_hull(candidate,thishull) u= stats.uniform.rvs() - if u < m.exp(thishlx-thishux): + if u < numpy.exp(thishlx-thishux): thissample= candidate noSampleYet= False else: thishx= hx(candidate,hxparams) - if u < m.exp(thishx-thishux): + if u < numpy.exp(thishx-thishux): thissample= candidate noSampleYet= False if nupdates < maxn: @@ -227,7 +226,7 @@ else: thissample= 100000000 #Throw some kind of error else: - thissample= hull[4][0]+1./hull[3][0]*m.log(1.-hull[3][0]*hull[0]*(hull[5][0]-u)/m.exp(hull[6][0])) + thissample= hull[4][0]+1./hull[3][0]*numpy.log(1.-hull[3][0]*hull[0]*(hull[5][0]-u)/numpy.exp(hull[6][0])) else: if len(hull[5]) == 1: indx= 0 @@ -236,7 +235,7 @@ while indx < len(hull[5]) and hull[5][indx] < u: indx= indx+1 indx= indx-1 - if m.fabs(hull[3][indx+1]) == 0: + if numpy.fabs(hull[3][indx+1]) == 0: if indx != (len(hull[5])-1): thissample= hull[4][indx]+(u-hull[5][indx])/(hull[5][indx+1]-hull[5][indx])*(hull[4][indx+1]-hull[4][indx]) else: @@ -245,7 +244,7 @@ else: thissample= 100000 #Throw some kind of error else: - thissample= hull[4][indx]+1./hull[3][indx+1]*m.log(1.+hull[3][indx+1]*hull[0]*(u-hull[5][indx])/m.exp(hull[6][indx])) + thissample= hull[4][indx]+1./hull[3][indx+1]*numpy.log(1.+hull[3][indx+1]*hull[0]*(u-hull[5][indx])/numpy.exp(hull[6][indx])) return thissample def evaluate_hull(x,hull): @@ -277,7 +276,7 @@ indx= indx-1 hux= hull[3][indx]*(x-hull[1][indx])+hull[2][indx] #Now evaluate hlx - neginf= sc.finfo(sc.dtype(sc.float64)).min + neginf= numpy.finfo(numpy.dtype(numpy.float64)).min if x < hull[1][0] or x > hull[1][-1]: hlx= neginf else: @@ -311,61 +310,61 @@ #BOVY: Perhaps add a check that newx is sufficiently far from any existing point #Find where newx fits in with the other xs if newx > hull[1][-1]: - newxs= sc.append(hull[1],newx) - newhxs= sc.append(hull[2],newhx) - newhpxs= sc.append(hull[3],newhpx) + newxs= numpy.append(hull[1],newx) + newhxs= numpy.append(hull[2],newhx) + newhpxs= numpy.append(hull[3],newhpx) #new z newz= ( newhx - hull[2][-1] - newx*newhpx + hull[1][-1]*hull[3][-1])/( hull[3][-1] - newhpx) - newzs= sc.append(hull[4],newz) + newzs= numpy.append(hull[4],newz) #New hu newhu= hull[3][-1]*(newz-hull[1][-1]) + hull[2][-1] - newhus= sc.append(hull[6],newhu) + newhus= numpy.append(hull[6],newhu) else: indx= 0 while newx > hull[1][indx]: indx=indx+1 - newxs= sc.insert(hull[1],indx,newx) - newhxs= sc.insert(hull[2],indx,newhx) - newhpxs= sc.insert(hull[3],indx,newhpx) + newxs= numpy.insert(hull[1],indx,newx) + newhxs= numpy.insert(hull[2],indx,newhx) + newhpxs= numpy.insert(hull[3],indx,newhpx) #Replace old z with new zs if newx < hull[1][0]: newz= (hull[2][0]-newhx-hull[1][0]*hull[3][0]+newx*newhpx)/(newhpx-hull[3][0]) - newzs= sc.insert(hull[4],0,newz) + newzs= numpy.insert(hull[4],0,newz) #Also add the new hu newhu= newhpx*(newz-newx)+newhx - newhus= sc.insert(hull[6],0,newhu) + newhus= numpy.insert(hull[6],0,newhu) else: newz1= (newhx-hull[2][indx-1] - newx*newhpx+hull[1][indx-1]*hull[3][indx-1])/(hull[3][indx-1]-newhpx) newz2= (hull[2][indx]-newhx - hull[1][indx]*hull[3][indx]+newx*newhpx)/(newhpx-hull[3][indx]) #Insert newz1 and replace z_old - newzs= sc.insert(hull[4],indx-1,newz1) + newzs= numpy.insert(hull[4],indx-1,newz1) newzs[indx]= newz2 #Update the hus newhu1= hull[3][indx-1]*(newz1-hull[1][indx-1])+hull[2][indx-1] newhu2= newhpx*(newz2-newx)+newhx - newhus= sc.insert(hull[6],indx-1,newhu1) + newhus= numpy.insert(hull[6],indx-1,newhu1) newhus[indx]= newhu2 #Recalculate the cumulative sum nx= len(newxs) - newscum= sc.zeros(nx-1) + newscum= numpy.zeros(nx-1) if isDomainFinite[0]: - newscum[0]= 1./newhpxs[0]*(m.exp(newhus[0])-m.exp( + newscum[0]= 1./newhpxs[0]*(numpy.exp(newhus[0])-numpy.exp( newhpxs[0]*(domain[0]-newxs[0])+newhxs[0])) else: - newscum[0]= 1./newhpxs[0]*m.exp(newhus[0]) + newscum[0]= 1./newhpxs[0]*numpy.exp(newhus[0]) if nx > 2: for jj in range(nx-2): if newhpxs[jj+1] == 0.: - newscum[jj+1]= (newzs[jj+1]-newzs[jj])*m.exp(newhxs[jj+1]) + newscum[jj+1]= (newzs[jj+1]-newzs[jj])*numpy.exp(newhxs[jj+1]) else: - newscum[jj+1]=1./newhpxs[jj+1]*(m.exp(newhus[jj+1])-m.exp(newhus[jj])) + newscum[jj+1]=1./newhpxs[jj+1]*(numpy.exp(newhus[jj+1])-numpy.exp(newhus[jj])) if isDomainFinite[1]: - newcu=1./newhpxs[nx-1]*(m.exp(newhpxs[nx-1]*( - domain[1]-newxs[nx-1])+newhxs[nx-1]) - m.exp(newhus[nx-2])) + newcu=1./newhpxs[nx-1]*(numpy.exp(newhpxs[nx-1]*( + domain[1]-newxs[nx-1])+newhxs[nx-1]) - numpy.exp(newhus[nx-2])) else: - newcu=- 1./newhpxs[nx-1]*m.exp(newhus[nx-2]) - newcu= newcu+sc.sum(newscum) - newscum= sc.cumsum(newscum)/newcu + newcu=- 1./newhpxs[nx-1]*numpy.exp(newhus[nx-2]) + newcu= newcu+numpy.sum(newscum) + newscum= numpy.cumsum(newscum)/newcu newhull=[] newhull.append(newcu) newhull.append(newxs) diff -Nru galpy-1.5/galpy/util/bovy_conversion.py galpy-1.6.0.post0/galpy/util/bovy_conversion.py --- galpy-1.5/galpy/util/bovy_conversion.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/bovy_conversion.py 2020-04-24 19:48:38.000000000 +0000 @@ -8,8 +8,7 @@ import warnings import copy import math as m -from galpy.util import galpyWarning -from galpy.util.config import __config__ +from ..util.config import __config__ _APY_UNITS= __config__.getboolean('astropy','astropy-units') _APY_LOADED= True try: @@ -443,7 +442,7 @@ """ return vo*_kmsInPcMyr -def get_physical(obj): +def get_physical(obj,include_set=False): """ NAME: @@ -457,6 +456,8 @@ obj - a galpy object or list of such objects (e.g., a Potential, list of Potentials, Orbit, actionAngle instance, DF instance) + include_set= (False) if True, also include roSet and voSet, flags of whether the unit is explicitly set in the object + OUTPUT: Dictionary {'ro':length unit in kpc,'vo':velocity unit in km/s}; note that this routine will *always* return these conversion units, even if the obj you provide does not have units turned on @@ -479,9 +480,49 @@ and isinstance(new_obj[0],(Force,planarPotential,linearPotential))): obj= new_obj if isinstance(obj,list): - return {'ro':obj[0]._ro,'vo':obj[0]._vo} + out_obj= obj[0] else: - return {'ro':obj._ro,'vo':obj._vo} + out_obj= obj + out= {'ro':out_obj._ro,'vo':out_obj._vo} + if include_set: + out.update({'roSet':out_obj._roSet,'voSet':out_obj._voSet}) + return out + +def physical_compatible(obj,other_obj): + """ + NAME: + + physical_compatible + + PURPOSE: + + test whether the velocity and length units for converting between physical and internal units are compatible for two galpy objects + + INPUT: + + obj - a galpy object or list of such objects (e.g., a Potential, list of Potentials, Orbit, actionAngle instance, DF instance) + + other_obj - another galpy object or list of such objects (e.g., a Potential, list of Potentials, Orbit, actionAngle instance, DF instance) + + OUTPUT: + + True if the units are compatible, False if not (compatible means that the units are the same when they are set for both objects) + + HISTORY: + + 2020-04-22 - Written - Bovy (UofT) + + """ + if obj is None or other_obj is None: # if one is None, just state compat + return True + phys= get_physical(obj,include_set=True) + other_phys= get_physical(other_obj,include_set=True) + out= True + if phys['roSet'] and other_phys['roSet']: + out= out and m.fabs((phys['ro']-other_phys['ro'])/phys['ro']) < 1e-8 + if phys['voSet'] and other_phys['voSet']: + out= out and m.fabs((phys['vo']-other_phys['vo'])/phys['vo']) < 1e-8 + return out #Decorator to apply these transformations # NOTE: names with underscores in them signify return values that *always* have @@ -567,7 +608,7 @@ if use_physical and \ not (_voNecessary[quantity.lower()] and vo is None) and \ not (_roNecessary[quantity.lower()] and ro is None): - from galpy.orbit import Orbit + from ..orbit import Orbit if quantity.lower() == 'time': fac= time_in_Gyr(vo,ro) if _apy_units: @@ -695,7 +736,7 @@ to internal coordinates""" @wraps(method) def wrapper(*args,**kwargs): - from galpy.potential import flatten as flatten_potential + from ..potential import flatten as flatten_potential Pot= flatten_potential(args[0]) ro= kwargs.get('ro',None) if ro is None and hasattr(Pot,'_ro'): diff -Nru galpy-1.5/galpy/util/bovy_coords.py galpy-1.6.0.post0/galpy/util/bovy_coords.py --- galpy-1.5/galpy/util/bovy_coords.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/bovy_coords.py 2020-04-24 19:48:38.000000000 +0000 @@ -45,7 +45,7 @@ # ############################################################################## ############################################################################# -#Copyright (c) 2010 - 2018, Jo Bovy +#Copyright (c) 2010 - 2019, Jo Bovy #All rights reserved. # #Redistribution and use in source and binary forms, with or without @@ -73,11 +73,9 @@ #POSSIBILITY OF SUCH DAMAGE. ############################################################################# from functools import wraps -import math as m -import numpy as nu -import scipy as sc -from galpy.util import _rotate_to_arbitrary_vector -from galpy.util.config import __config__ +import numpy +from ..util import _rotate_to_arbitrary_vector +from ..util.config import __config__ _APY_COORDS= __config__.getboolean('astropy','astropy-coords') _APY_LOADED= True try: @@ -86,7 +84,7 @@ except ImportError: _APY_LOADED= False _APY_COORDS*= _APY_LOADED -_DEGTORAD= m.pi/180. +_DEGTORAD= numpy.pi/180. if _APY_LOADED: _K= (1.*units.mas/units.yr).to(units.km/units.s/units.kpc, equivalencies=units.dimensionless_angles())\ @@ -95,7 +93,7 @@ _K=4.74047 # numpy 1.14 einsum bug causes astropy conversions to fail in py2.7 -> turn off if _APY_COORDS: - ra, dec= nu.array([192.25*_DEGTORAD]), nu.array([27.4*_DEGTORAD]) + ra, dec= numpy.array([192.25*_DEGTORAD]), numpy.array([27.4*_DEGTORAD]) c= apycoords.SkyCoord(ra*units.rad,dec*units.rad, equinox='B1950',frame='fk4') # This conversion fails bc of einsum bug @@ -107,11 +105,11 @@ """Decorator to return scalar outputs as a set""" @wraps(func) def scalar_wrapper(*args,**kwargs): - if nu.array(args[0]).shape == (): + if numpy.array(args[0]).shape == (): scalarOut= True newargs= () for ii in range(len(args)): - newargs= newargs+(nu.array([args[ii]]),) + newargs= newargs+(numpy.array([args[ii]]),) args= newargs else: scalarOut= False @@ -154,12 +152,12 @@ def wrapped(*args, **kwargs): isdeg = kwargs.get('degree', False) if isdeg: - args = [arg * nu.pi / 180 if i in inDegrees else arg + args = [arg * numpy.pi / 180 if i in inDegrees else arg for i, arg in enumerate(args)] out = func(*args, **kwargs) if isdeg: for i in outDegrees: - out[:, i] *= 180. / nu.pi + out[:, i] *= 180. / numpy.pi return out return wrapped return wrapper @@ -207,21 +205,21 @@ c= apycoords.SkyCoord(ra*units.rad,dec*units.rad, equinox=epoch,frame=frame) c= c.transform_to(apycoords.Galactic) - return nu.array([c.l.to(units.rad).value,c.b.to(units.rad).value]).T + return numpy.array([c.l.to(units.rad).value,c.b.to(units.rad).value]).T #First calculate the transformation matrix T theta,dec_ngp,ra_ngp= get_epoch_angles(epoch) - T= sc.dot(sc.array([[sc.cos(theta),sc.sin(theta),0.],[sc.sin(theta),-sc.cos(theta),0.],[0.,0.,1.]]),sc.dot(sc.array([[-sc.sin(dec_ngp),0.,sc.cos(dec_ngp)],[0.,1.,0.],[sc.cos(dec_ngp),0.,sc.sin(dec_ngp)]]),sc.array([[sc.cos(ra_ngp),sc.sin(ra_ngp),0.],[-sc.sin(ra_ngp),sc.cos(ra_ngp),0.],[0.,0.,1.]]))) + T= numpy.dot(numpy.array([[numpy.cos(theta),numpy.sin(theta),0.],[numpy.sin(theta),-numpy.cos(theta),0.],[0.,0.,1.]]),numpy.dot(numpy.array([[-numpy.sin(dec_ngp),0.,numpy.cos(dec_ngp)],[0.,1.,0.],[numpy.cos(dec_ngp),0.,numpy.sin(dec_ngp)]]),numpy.array([[numpy.cos(ra_ngp),numpy.sin(ra_ngp),0.],[-numpy.sin(ra_ngp),numpy.cos(ra_ngp),0.],[0.,0.,1.]]))) #Whether to use degrees and scalar input is handled by decorators - XYZ= nu.array([nu.cos(dec)*nu.cos(ra), - nu.cos(dec)*nu.sin(ra), - nu.sin(dec)]) - galXYZ= nu.dot(T,XYZ) + XYZ= numpy.array([numpy.cos(dec)*numpy.cos(ra), + numpy.cos(dec)*numpy.sin(ra), + numpy.sin(dec)]) + galXYZ= numpy.dot(T,XYZ) galXYZ[2][galXYZ[2] > 1.]= 1. galXYZ[2][galXYZ[2] < -1.]= -1. - b= nu.arcsin(galXYZ[2]) - l= nu.arctan2(galXYZ[1]/sc.cos(b),galXYZ[0]/sc.cos(b)) - l[l<0.]+= 2.*nu.pi - out= nu.array([l,b]) + b= numpy.arcsin(galXYZ[2]) + l= numpy.arctan2(galXYZ[1]/numpy.cos(b),galXYZ[0]/numpy.cos(b)) + l[l<0.]+= 2.*numpy.pi + out= numpy.array([l,b]) return out.T @scalarDecorator @@ -270,19 +268,19 @@ c= c.transform_to(apycoords.FK4(equinox=epoch)) else: c= c.transform_to(apycoords.ICRS) - return nu.array([c.ra.to(units.rad).value,c.dec.to(units.rad).value]).T + return numpy.array([c.ra.to(units.rad).value,c.dec.to(units.rad).value]).T #First calculate the transformation matrix T' theta,dec_ngp,ra_ngp= get_epoch_angles(epoch) - T= sc.dot(sc.array([[sc.cos(ra_ngp),-sc.sin(ra_ngp),0.],[sc.sin(ra_ngp),sc.cos(ra_ngp),0.],[0.,0.,1.]]),sc.dot(sc.array([[-sc.sin(dec_ngp),0.,sc.cos(dec_ngp)],[0.,1.,0.],[sc.cos(dec_ngp),0.,sc.sin(dec_ngp)]]),sc.array([[sc.cos(theta),sc.sin(theta),0.],[sc.sin(theta),-sc.cos(theta),0.],[0.,0.,1.]]))) + T= numpy.dot(numpy.array([[numpy.cos(ra_ngp),-numpy.sin(ra_ngp),0.],[numpy.sin(ra_ngp),numpy.cos(ra_ngp),0.],[0.,0.,1.]]),numpy.dot(numpy.array([[-numpy.sin(dec_ngp),0.,numpy.cos(dec_ngp)],[0.,1.,0.],[numpy.cos(dec_ngp),0.,numpy.sin(dec_ngp)]]),numpy.array([[numpy.cos(theta),numpy.sin(theta),0.],[numpy.sin(theta),-numpy.cos(theta),0.],[0.,0.,1.]]))) #Whether to use degrees and scalar input is handled by decorators - XYZ= nu.array([nu.cos(b)*nu.cos(l), - nu.cos(b)*nu.sin(l), - nu.sin(b)]) - eqXYZ= nu.dot(T,XYZ) - dec= nu.arcsin(eqXYZ[2]) - ra= nu.arctan2(eqXYZ[1],eqXYZ[0]) - ra[ra<0.]+= 2.*nu.pi - return nu.array([ra,dec]).T + XYZ= numpy.array([numpy.cos(b)*numpy.cos(l), + numpy.cos(b)*numpy.sin(l), + numpy.sin(b)]) + eqXYZ= numpy.dot(T,XYZ) + dec= numpy.arcsin(eqXYZ[2]) + ra= numpy.arctan2(eqXYZ[1],eqXYZ[0]) + ra[ra<0.]+= 2.*numpy.pi + return numpy.array([ra,dec]).T @scalarDecorator @degreeDecorator([0,1],[]) @@ -320,9 +318,9 @@ """ #Whether to use degrees and scalar input is handled by decorators - return nu.array([d*nu.cos(b)*nu.cos(l), - d*nu.cos(b)*nu.sin(l), - d*nu.sin(b)]).T + return numpy.array([d*numpy.cos(b)*numpy.cos(l), + d*numpy.cos(b)*numpy.sin(l), + d*numpy.sin(b)]).T def rectgal_to_sphergal(X,Y,Z,vx,vy,vz,degree=False): """ @@ -361,10 +359,10 @@ """ lbd= XYZ_to_lbd(X,Y,Z,degree=degree) vrpmllpmbb= vxvyvz_to_vrpmllpmbb(vx,vy,vz,X,Y,Z,XYZ=True) - if sc.array(X).shape == (): - return sc.array([lbd[0],lbd[1],lbd[2],vrpmllpmbb[0],vrpmllpmbb[1],vrpmllpmbb[2]]) + if numpy.array(X).shape == (): + return numpy.array([lbd[0],lbd[1],lbd[2],vrpmllpmbb[0],vrpmllpmbb[1],vrpmllpmbb[2]]) else: - out=sc.zeros((len(X),6)) + out=numpy.zeros((len(X),6)) out[:,0:3]= lbd out[:,3:6]= vrpmllpmbb return out @@ -406,10 +404,10 @@ """ XYZ= lbd_to_XYZ(l,b,d,degree=degree) vxvyvz= vrpmllpmbb_to_vxvyvz(vr,pmll,pmbb,l,b,d,XYZ=False,degree=degree) - if sc.array(l).shape == (): - return sc.array([XYZ[0],XYZ[1],XYZ[2],vxvyvz[0],vxvyvz[1],vxvyvz[2]]) + if numpy.array(l).shape == (): + return numpy.array([XYZ[0],XYZ[1],XYZ[2],vxvyvz[0],vxvyvz[1],vxvyvz[2]]) else: - out=sc.zeros((len(l),6)) + out=numpy.zeros((len(l),6)) out[:,0:3]= XYZ out[:,3:6]= vxvyvz return out @@ -460,22 +458,22 @@ #Whether to use degrees and scalar input is handled by decorators if XYZ: #undo the incorrect conversion that the decorator did if degree: - l*= 180./nu.pi - b*= 180./nu.pi + l*= 180./numpy.pi + b*= 180./numpy.pi lbd= XYZ_to_lbd(l,b,d,degree=False) l= lbd[:,0] b= lbd[:,1] d= lbd[:,2] - R=nu.zeros((3,3,len(l))) - R[0,0]= nu.cos(l)*nu.cos(b) - R[1,0]= -nu.sin(l) - R[2,0]= -nu.cos(l)*nu.sin(b) - R[0,1]= nu.sin(l)*nu.cos(b) - R[1,1]= nu.cos(l) - R[2,1]= -nu.sin(l)*nu.sin(b) - R[0,2]= nu.sin(b) - R[2,2]= nu.cos(b) - invr= nu.array([[vr,vr,vr], + R=numpy.zeros((3,3,len(l))) + R[0,0]= numpy.cos(l)*numpy.cos(b) + R[1,0]= -numpy.sin(l) + R[2,0]= -numpy.cos(l)*numpy.sin(b) + R[0,1]= numpy.sin(l)*numpy.cos(b) + R[1,1]= numpy.cos(l) + R[2,1]= -numpy.sin(l)*numpy.sin(b) + R[0,2]= numpy.sin(b) + R[2,2]= numpy.cos(b) + invr= numpy.array([[vr,vr,vr], [d*pmll*_K,d*pmll*_K,d*pmll*_K], [d*pmbb*_K,d*pmbb*_K,d*pmbb*_K]]) return (R.T*invr.T).sum(-1) @@ -526,22 +524,22 @@ #Whether to use degrees and scalar input is handled by decorators if XYZ: #undo the incorrect conversion that the decorator did if degree: - l*= 180./nu.pi - b*= 180./nu.pi + l*= 180./numpy.pi + b*= 180./numpy.pi lbd= XYZ_to_lbd(l,b,d,degree=False) l= lbd[:,0] b= lbd[:,1] d= lbd[:,2] - R=nu.zeros((3,3,len(l))) - R[0,0]= nu.cos(l)*nu.cos(b) - R[0,1]= -nu.sin(l) - R[0,2]= -nu.cos(l)*nu.sin(b) - R[1,0]= nu.sin(l)*nu.cos(b) - R[1,1]= nu.cos(l) - R[1,2]= -nu.sin(l)*nu.sin(b) - R[2,0]= nu.sin(b) - R[2,2]= nu.cos(b) - invxyz= nu.array([[vx,vx,vx], + R=numpy.zeros((3,3,len(l))) + R[0,0]= numpy.cos(l)*numpy.cos(b) + R[0,1]= -numpy.sin(l) + R[0,2]= -numpy.cos(l)*numpy.sin(b) + R[1,0]= numpy.sin(l)*numpy.cos(b) + R[1,1]= numpy.cos(l) + R[1,2]= -numpy.sin(l)*numpy.sin(b) + R[2,0]= numpy.sin(b) + R[2,2]= numpy.cos(b) + invxyz= numpy.array([[vx,vx,vx], [vy,vy,vy], [vz,vz,vz]]) vrvlvb= (R.T*invxyz.T).sum(-1) @@ -585,14 +583,14 @@ """ #Whether to use degrees and scalar input is handled by decorators - d= nu.sqrt(X**2.+Y**2.+Z**2.) - b=nu.arcsin(Z/d) - cosl= X/d/nu.cos(b) - sinl= Y/d/nu.cos(b) - l= nu.arcsin(sinl) - l[cosl < 0.]= nu.pi-l[cosl < 0.] - l[(cosl >= 0.)*(sinl < 0.)]+= 2.*nu.pi - out= nu.empty((len(l),3)) + d= numpy.sqrt(X**2.+Y**2.+Z**2.) + b=numpy.arcsin(Z/d) + cosl= X/d/numpy.cos(b) + sinl= Y/d/numpy.cos(b) + l= numpy.arcsin(sinl) + l[cosl < 0.]= numpy.pi-l[cosl < 0.] + l[(cosl >= 0.)*(sinl < 0.)]+= 2.*numpy.pi + out= numpy.empty((len(l),3)) out[:,0]= l out[:,1]= b out[:,2]= d @@ -638,22 +636,22 @@ theta,dec_ngp,ra_ngp= get_epoch_angles(epoch) #Whether to use degrees and scalar input is handled by decorators dec[dec == dec_ngp]+= 10.**-16 #deal w/ pole. - sindec_ngp= nu.sin(dec_ngp) - cosdec_ngp= nu.cos(dec_ngp) - sindec= nu.sin(dec) - cosdec= nu.cos(dec) - sinrarangp= nu.sin(ra-ra_ngp) - cosrarangp= nu.cos(ra-ra_ngp) + sindec_ngp= numpy.sin(dec_ngp) + cosdec_ngp= numpy.cos(dec_ngp) + sindec= numpy.sin(dec) + cosdec= numpy.cos(dec) + sinrarangp= numpy.sin(ra-ra_ngp) + cosrarangp= numpy.cos(ra-ra_ngp) #These were replaced by Poleski (2013)'s equivalent form that is better at the poles #cosphi= (sindec_ngp-sindec*sinb)/cosdec/cosb #sinphi= sinrarangp*cosdec_ngp/cosb cosphi= sindec_ngp*cosdec-cosdec_ngp*sindec*cosrarangp sinphi= sinrarangp*cosdec_ngp - norm= nu.sqrt(cosphi**2.+sinphi**2.) + norm= numpy.sqrt(cosphi**2.+sinphi**2.) cosphi/= norm sinphi/= norm - return (nu.array([[cosphi,-sinphi],[sinphi,cosphi]]).T\ - *nu.array([[pmra,pmra],[pmdec,pmdec]]).T).sum(-1) + return (numpy.array([[cosphi,-sinphi],[sinphi,cosphi]]).T\ + *numpy.array([[pmra,pmra],[pmdec,pmdec]]).T).sum(-1) @scalarDecorator @degreeDecorator([2,3],[]) @@ -698,22 +696,22 @@ ra= radec[:,0] dec= radec[:,1] dec[dec == dec_ngp]+= 10.**-16 #deal w/ pole. - sindec_ngp= nu.sin(dec_ngp) - cosdec_ngp= nu.cos(dec_ngp) - sindec= nu.sin(dec) - cosdec= nu.cos(dec) - sinrarangp= nu.sin(ra-ra_ngp) - cosrarangp= nu.cos(ra-ra_ngp) + sindec_ngp= numpy.sin(dec_ngp) + cosdec_ngp= numpy.cos(dec_ngp) + sindec= numpy.sin(dec) + cosdec= numpy.cos(dec) + sinrarangp= numpy.sin(ra-ra_ngp) + cosrarangp= numpy.cos(ra-ra_ngp) #These were replaced by Poleski (2013)'s equivalent form that is better at the poles #cosphi= (sindec_ngp-sindec*sinb)/cosdec/cosb #sinphi= sinrarangp*cosdec_ngp/cosb cosphi= sindec_ngp*cosdec-cosdec_ngp*sindec*cosrarangp sinphi= sinrarangp*cosdec_ngp - norm= nu.sqrt(cosphi**2.+sinphi**2.) + norm= numpy.sqrt(cosphi**2.+sinphi**2.) cosphi/= norm sinphi/= norm - return (nu.array([[cosphi,sinphi],[-sinphi,cosphi]]).T\ - *nu.array([[pmll,pmll],[pmbb,pmbb]]).T).sum(-1) + return (numpy.array([[cosphi,sinphi],[-sinphi,cosphi]]).T\ + *numpy.array([[pmll,pmll],[pmbb,pmbb]]).T).sum(-1) def cov_pmrapmdec_to_pmllpmbb(cov_pmradec,ra,dec,degree=False,epoch=2000.0): """ @@ -747,7 +745,7 @@ """ if len(cov_pmradec.shape) == 3: - out= sc.zeros(cov_pmradec.shape) + out= numpy.zeros(cov_pmradec.shape) ndata= out.shape[0] lb = radec_to_lb(ra,dec,degree=degree,epoch=epoch) for ii in range(ndata): @@ -780,29 +778,29 @@ """ theta,dec_ngp,ra_ngp= get_epoch_angles(epoch) if degree: - sindec_ngp= m.sin(dec_ngp) - cosdec_ngp= m.cos(dec_ngp) - sindec= m.sin(dec*_DEGTORAD) - cosdec= m.cos(dec*_DEGTORAD) - sinrarangp= m.sin(ra*_DEGTORAD-ra_ngp) - cosrarangp= m.cos(ra*_DEGTORAD-ra_ngp) + sindec_ngp= numpy.sin(dec_ngp) + cosdec_ngp= numpy.cos(dec_ngp) + sindec= numpy.sin(dec*_DEGTORAD) + cosdec= numpy.cos(dec*_DEGTORAD) + sinrarangp= numpy.sin(ra*_DEGTORAD-ra_ngp) + cosrarangp= numpy.cos(ra*_DEGTORAD-ra_ngp) else: - sindec_ngp= m.sin(dec_ngp) - cosdec_ngp= m.cos(dec_ngp) - sindec= m.sin(dec) - cosdec= m.cos(dec) - sinrarangp= m.sin(ra-ra_ngp) - cosrarangp= m.cos(ra-ra_ngp) + sindec_ngp= numpy.sin(dec_ngp) + cosdec_ngp= numpy.cos(dec_ngp) + sindec= numpy.sin(dec) + cosdec= numpy.cos(dec) + sinrarangp= numpy.sin(ra-ra_ngp) + cosrarangp= numpy.cos(ra-ra_ngp) #These were replaced by Poleski (2013)'s equivalent form that is better at the poles #cosphi= (sindec_ngp-sindec*sinb)/cosdec/cosb #sinphi= sinrarangp*cosdec_ngp/cosb cosphi= sindec_ngp*cosdec-cosdec_ngp*sindec*cosrarangp sinphi= sinrarangp*cosdec_ngp - norm= m.sqrt(cosphi**2.+sinphi**2.) + norm= numpy.sqrt(cosphi**2.+sinphi**2.) cosphi/= norm sinphi/= norm - P= sc.array([[cosphi,sinphi],[-sinphi,cosphi]]) - return sc.dot(P,sc.dot(cov_pmradec,P.T)) + P= numpy.array([[cosphi,sinphi],[-sinphi,cosphi]]) + return numpy.dot(P,numpy.dot(cov_pmradec,P.T)) def cov_dvrpmllbb_to_vxyz(d,e_d,e_vr,pmll,pmbb,cov_pmllbb,l,b, plx=False,degree=False): @@ -854,12 +852,12 @@ if degree: l*= _DEGTORAD b*= _DEGTORAD - if sc.array(d).shape == (): + if numpy.array(d).shape == (): return cov_dvrpmllbb_to_vxyz_single(d,e_d,e_vr,pmll,pmbb,cov_pmllbb, l,b) else: ndata= len(d) - out= sc.zeros((ndata,3,3)) + out= numpy.zeros((ndata,3,3)) for ii in range(ndata): out[ii,:,:]= cov_dvrpmllbb_to_vxyz_single(d[ii],e_d[ii],e_vr[ii], pmll[ii],pmbb[ii], @@ -889,18 +887,18 @@ HISTORY: 2010-04-12 - Written - Bovy (NYU) """ - M= _K*sc.array([[pmll,d,0.],[pmbb,0.,d]]) - cov_dpmllbb= sc.zeros((3,3)) + M= _K*numpy.array([[pmll,d,0.],[pmbb,0.,d]]) + cov_dpmllbb= numpy.zeros((3,3)) cov_dpmllbb[0,0]= e_d**2. cov_dpmllbb[1:3,1:3]= cov_pmllbb - cov_vlvb= sc.dot(M,sc.dot(cov_dpmllbb,M.T)) - cov_vrvlvb= sc.zeros((3,3)) + cov_vlvb= numpy.dot(M,numpy.dot(cov_dpmllbb,M.T)) + cov_vrvlvb= numpy.zeros((3,3)) cov_vrvlvb[0,0]= e_vr**2. cov_vrvlvb[1:3,1:3]= cov_vlvb - R= sc.array([[m.cos(l)*m.cos(b), m.sin(l)*m.cos(b), m.sin(b)], - [-m.sin(l),m.cos(l),0.], - [-m.cos(l)*m.sin(b),-m.sin(l)*m.sin(b), m.cos(b)]]) - return sc.dot(R.T,sc.dot(cov_vrvlvb,R)) + R= numpy.array([[numpy.cos(l)*numpy.cos(b), numpy.sin(l)*numpy.cos(b), numpy.sin(b)], + [-numpy.sin(l),numpy.cos(l),0.], + [-numpy.cos(l)*numpy.sin(b),-numpy.sin(l)*numpy.sin(b), numpy.cos(b)]]) + return numpy.dot(R.T,numpy.dot(cov_vrvlvb,R)) @scalarDecorator def XYZ_to_galcenrect(X,Y,Z,Xsun=1.,Zsun=0.,_extra_rot=True): @@ -941,13 +939,13 @@ """ if _extra_rot: - X,Y,Z= nu.dot(galcen_extra_rot,nu.array([X,Y,Z])) - dgc= nu.sqrt(Xsun**2.+Zsun**2.) + X,Y,Z= numpy.dot(galcen_extra_rot,numpy.array([X,Y,Z])) + dgc= numpy.sqrt(Xsun**2.+Zsun**2.) costheta, sintheta= Xsun/dgc, Zsun/dgc - return nu.dot(nu.array([[costheta,0.,-sintheta], + return numpy.dot(numpy.array([[costheta,0.,-sintheta], [0.,1.,0.], [sintheta,0.,costheta]]), - nu.array([-X+dgc,Y,nu.sign(Xsun)*Z])).T + numpy.array([-X+dgc,Y,numpy.sign(Xsun)*Z])).T @scalarDecorator def galcenrect_to_XYZ(X,Y,Z,Xsun=1.,Zsun=0.,_extra_rot=True): @@ -985,25 +983,25 @@ 2018-04-18 - Tweaked to be consistent with astropy's Galactocentric frame - Bovy (UofT) """ - dgc= nu.sqrt(Xsun**2.+Zsun**2.) + dgc= numpy.sqrt(Xsun**2.+Zsun**2.) costheta, sintheta= Xsun/dgc, Zsun/dgc - if isinstance(Xsun,nu.ndarray): - zero= nu.zeros(len(Xsun)) - one= nu.ones(len(Xsun)) - Carr= nu.rollaxis(nu.array([[-costheta,zero,-sintheta], + if isinstance(Xsun,numpy.ndarray): + zero= numpy.zeros(len(Xsun)) + one= numpy.ones(len(Xsun)) + Carr= numpy.rollaxis(numpy.array([[-costheta,zero,-sintheta], [zero,one,zero], - [-nu.sign(Xsun)*sintheta,zero, - nu.sign(Xsun)*costheta]]),2) - out= ((Carr*nu.array([[X,X,X],[Y,Y,Y],[Z,Z,Z]]).T).sum(-1) - +nu.array([dgc,zero,zero]).T) + [-numpy.sign(Xsun)*sintheta,zero, + numpy.sign(Xsun)*costheta]]),2) + out= ((Carr*numpy.array([[X,X,X],[Y,Y,Y],[Z,Z,Z]]).T).sum(-1) + +numpy.array([dgc,zero,zero]).T) else: - out= nu.dot(nu.array([[-costheta,0.,-sintheta], + out= numpy.dot(numpy.array([[-costheta,0.,-sintheta], [0.,1.,0.], - [-nu.sign(Xsun)*sintheta,0., - nu.sign(Xsun)*costheta]]), - nu.array([X,Y,Z])).T+nu.array([dgc,0.,0.]) + [-numpy.sign(Xsun)*sintheta,0., + numpy.sign(Xsun)*costheta]]), + numpy.array([X,Y,Z])).T+numpy.array([dgc,0.,0.]) if _extra_rot: - return nu.dot(galcen_extra_rot.T,out.T).T + return numpy.dot(galcen_extra_rot.T,out.T).T else: return out @@ -1032,7 +1030,7 @@ 2019-06-21 - Changed such that phi in [-pi,pi] - Bovy (UofT) """ - return (sc.sqrt(X**2.+Y**2.),sc.arctan2(Y,X),Z) + return (numpy.sqrt(X**2.+Y**2.),numpy.arctan2(Y,X),Z) def cyl_to_rect(R,phi,Z): """ @@ -1057,7 +1055,7 @@ 2011-02-23 - Written - Bovy (NYU) """ - return (R*sc.cos(phi),R*sc.sin(phi),Z) + return (R*numpy.cos(phi),R*numpy.sin(phi),Z) def cyl_to_spher(R,Z, phi): """ @@ -1082,7 +1080,7 @@ 2016-05-16 - Written - Aladdin """ - theta = nu.arctan2(R, Z) + theta = numpy.arctan2(R, Z) r = (R**2 + Z**2)**.5 return (r,theta, phi) @@ -1109,8 +1107,8 @@ 2016-05-20 - Written - Aladdin """ - R = r*nu.sin(theta) - z = r*nu.cos(theta) + R = r*numpy.sin(theta) + z = r*numpy.cos(theta) return (R,z, phi) @scalarDecorator @@ -1147,9 +1145,9 @@ 2010-09-24 - Written - Bovy (NYU) """ - XYZ= nu.atleast_2d(XYZ_to_galcenrect(X,Y,Z,Xsun=Xsun,Zsun=Zsun, + XYZ= numpy.atleast_2d(XYZ_to_galcenrect(X,Y,Z,Xsun=Xsun,Zsun=Zsun, _extra_rot=_extra_rot)) - return nu.array(rect_to_cyl(XYZ[:,0],XYZ[:,1],XYZ[:,2])).T + return numpy.array(rect_to_cyl(XYZ[:,0],XYZ[:,1],XYZ[:,2])).T @scalarDecorator def galcencyl_to_XYZ(R,phi,Z,Xsun=1.,Zsun=0.,_extra_rot=True): @@ -1229,13 +1227,13 @@ """ if _extra_rot: - vx,vy,vz= nu.dot(galcen_extra_rot,nu.array([vx,vy,vz])) - dgc= nu.sqrt(Xsun**2.+Zsun**2.) + vx,vy,vz= numpy.dot(galcen_extra_rot,numpy.array([vx,vy,vz])) + dgc= numpy.sqrt(Xsun**2.+Zsun**2.) costheta, sintheta= Xsun/dgc, Zsun/dgc - return nu.dot(nu.array([[costheta,0.,-sintheta], + return numpy.dot(numpy.array([[costheta,0.,-sintheta], [0.,1.,0.], [sintheta,0.,costheta]]), - nu.array([-vx,vy,nu.sign(Xsun)*vz])).T+nu.array(vsun) + numpy.array([-vx,vy,numpy.sign(Xsun)*vz])).T+numpy.array(vsun) @scalarDecorator def vxvyvz_to_galcencyl(vx,vy,vz,X,Y,Z,vsun=[0.,1.,0.],Xsun=1.,Zsun=0., @@ -1284,7 +1282,7 @@ """ vxyz= vxvyvz_to_galcenrect(vx,vy,vz,vsun=vsun,Xsun=Xsun,Zsun=Zsun, _extra_rot=_extra_rot) - return nu.array(\ + return numpy.array(\ rect_to_cyl_vec(vxyz[:,0],vxyz[:,1],vxyz[:,2],X,Y,Z,cyl=galcen)).T @scalarDecorator @@ -1330,27 +1328,27 @@ 2018-04-18 - Tweaked to be consistent with astropy's Galactocentric frame - Bovy (UofT) """ - dgc= nu.sqrt(Xsun**2.+Zsun**2.) + dgc= numpy.sqrt(Xsun**2.+Zsun**2.) costheta, sintheta= Xsun/dgc, Zsun/dgc - if isinstance(Xsun,nu.ndarray): - zero= nu.zeros(len(Xsun)) - one= nu.ones(len(Xsun)) - Carr= nu.rollaxis(nu.array([[-costheta,zero,-sintheta], + if isinstance(Xsun,numpy.ndarray): + zero= numpy.zeros(len(Xsun)) + one= numpy.ones(len(Xsun)) + Carr= numpy.rollaxis(numpy.array([[-costheta,zero,-sintheta], [zero,one,zero], - [-nu.sign(Xsun)*sintheta,zero, - nu.sign(Xsun)*costheta]]),2) + [-numpy.sign(Xsun)*sintheta,zero, + numpy.sign(Xsun)*costheta]]),2) out= ((Carr - *nu.array([[vXg-vsun[0],vXg-vsun[0],vXg-vsun[0]], + *numpy.array([[vXg-vsun[0],vXg-vsun[0],vXg-vsun[0]], [vYg-vsun[1],vYg-vsun[1],vYg-vsun[1]], [vZg-vsun[2],vZg-vsun[2],vZg-vsun[2]]]).T).sum(-1)) else: - out= nu.dot(nu.array([[-costheta,0.,-sintheta], + out= numpy.dot(numpy.array([[-costheta,0.,-sintheta], [0.,1.,0.], - [-nu.sign(Xsun)*sintheta,0., - nu.sign(Xsun)*costheta]]), - nu.array([vXg-vsun[0],vYg-vsun[1],vZg-vsun[2]])).T + [-numpy.sign(Xsun)*sintheta,0., + numpy.sign(Xsun)*costheta]]), + numpy.array([vXg-vsun[0],vYg-vsun[1],vZg-vsun[2]])).T if _extra_rot: - return nu.dot(galcen_extra_rot.T,out.T).T + return numpy.dot(galcen_extra_rot.T,out.T).T else: return out @@ -1438,8 +1436,8 @@ R,phi,Z= rect_to_cyl(X,Y,Z) else: phi= Y - vr=+vx*sc.cos(phi)+vy*sc.sin(phi) - vt= -vx*sc.sin(phi)+vy*sc.cos(phi) + vr=+vx*numpy.cos(phi)+vy*numpy.sin(phi) + vt= -vx*numpy.sin(phi)+vy*numpy.cos(phi) return (vr,vt,vz) def cyl_to_rect_vec(vr,vt,vz,phi): @@ -1471,8 +1469,8 @@ 2011-02-24 - Written - Bovy (NYU) """ - vx= vr*sc.cos(phi)-vt*sc.sin(phi) - vy= vr*sc.sin(phi)+vt*sc.cos(phi) + vx= vr*numpy.cos(phi)-vt*numpy.sin(phi) + vy= vr*numpy.sin(phi)+vt*numpy.cos(phi) return (vx,vy,vz) def cyl_to_rect_jac(*args): @@ -1504,16 +1502,16 @@ 2013-12-09 - Written - Bovy (IAS) """ - out= sc.zeros((6,6)) + out= numpy.zeros((6,6)) if len(args) == 3: R, phi, Z= args vR, vT, vZ= 0., 0., 0. - outIndx= sc.array([True,False,False,True,False,True],dtype='bool') + outIndx= numpy.array([True,False,False,True,False,True],dtype='bool') elif len(args) == 6: R, vR, vT, Z, vZ, phi= args - outIndx= sc.ones(6,dtype='bool') - cp= sc.cos(phi) - sp= sc.sin(phi) + outIndx= numpy.ones(6,dtype='bool') + cp= numpy.cos(phi) + sp= numpy.sin(phi) out[0,0]= cp out[0,5]= -R*sp out[1,0]= sp @@ -1564,20 +1562,20 @@ """ Xsun= kwargs.get('Xsun',1.) - dgc= nu.sqrt(Xsun**2.+kwargs.get('Zsun',0.)**2.) + dgc= numpy.sqrt(Xsun**2.+kwargs.get('Zsun',0.)**2.) costheta, sintheta= Xsun/dgc, kwargs.get('Zsun',0.)/dgc - out= sc.zeros((6,6)) + out= numpy.zeros((6,6)) out[0,0]= -costheta out[0,2]= -sintheta out[1,1]= 1. - out[2,0]= -nu.sign(Xsun)*sintheta - out[2,2]= nu.sign(Xsun)*costheta + out[2,0]= -numpy.sign(Xsun)*sintheta + out[2,2]= numpy.sign(Xsun)*costheta if len(args) == 3: return out[:3,:3] out[3,3]= -costheta out[3,5]= -sintheta out[4,4]= 1. - out[5,3]= -nu.sign(Xsun)*sintheta - out[5,5]= nu.sign(Xsun)*costheta + out[5,3]= -numpy.sign(Xsun)*sintheta + out[5,5]= numpy.sign(Xsun)*costheta return out def lbd_to_XYZ_jac(*args,**kwargs): @@ -1611,7 +1609,7 @@ 2013-12-09 - Written - Bovy (IAS) """ - out= sc.zeros((6,6)) + out= numpy.zeros((6,6)) if len(args) == 3: l,b,D= args vlos, pmll, pmbb= 0., 0., 0. @@ -1620,10 +1618,10 @@ if kwargs.get('degree',False): l*= _DEGTORAD b*= _DEGTORAD - cl= sc.cos(l) - sl= sc.sin(l) - cb= sc.cos(b) - sb= sc.sin(b) + cl= numpy.cos(l) + sl= numpy.sin(l) + cb= numpy.cos(b) + sb= numpy.sin(b) out[0,0]= -D*cb*sl out[0,1]= -D*sb*cl out[0,2]= cb*cl @@ -1693,21 +1691,21 @@ """ scalarOut, listOut= False, False if isinstance(d,(int,float)): - d= sc.array([d]) + d= numpy.array([d]) scalarOut= True elif isinstance(d,list): - d= sc.array(d) + d= numpy.array(d) listOut= True if isinstance(l,(int,float)): - l= sc.array([l]) + l= numpy.array([l]) elif isinstance(l,list): - l= sc.array(l) + l= numpy.array(l) if degree: l*= _DEGTORAD - R= sc.sqrt(ro**2.+d**2.-2.*d*ro*sc.cos(l)) - phi= sc.arcsin(d/R*sc.sin(l)) - indx= (ro/sc.cos(l) < d)*(sc.cos(l) > 0.) - phi[indx]= sc.pi-sc.arcsin(d[indx]/R[indx]*sc.sin(l[indx])) + R= numpy.sqrt(ro**2.+d**2.-2.*d*ro*numpy.cos(l)) + phi= numpy.arcsin(d/R*numpy.sin(l)) + indx= (ro/numpy.cos(l) < d)*(numpy.cos(l) > 0.) + phi[indx]= numpy.pi-numpy.arcsin(d[indx]/R[indx]*numpy.sin(l[indx])) if degree: phi/= _DEGTORAD phi+= phio @@ -1753,22 +1751,22 @@ """ scalarOut, listOut= False, False if isinstance(R,(int,float)): - R= sc.array([R]) + R= numpy.array([R]) scalarOut= True elif isinstance(R,list): - R= sc.array(R) + R= numpy.array(R) listOut= True if isinstance(phi,(int,float)): - phi= sc.array([phi]) + phi= numpy.array([phi]) elif isinstance(phi,list): - phi= sc.array(phi) + phi= numpy.array(phi) phi-= phio if degree: phi*= _DEGTORAD - d= sc.sqrt(R**2.+ro**2.-2.*R*ro*sc.cos(phi)) - l= sc.arcsin(R/d*sc.sin(phi)) - indx= (ro/sc.cos(phi) < R)*(sc.cos(phi) > 0.) - l[indx]= sc.pi-sc.arcsin(R[indx]/d[indx]*sc.sin(phi[indx])) + d= numpy.sqrt(R**2.+ro**2.-2.*R*ro*numpy.cos(phi)) + l= numpy.arcsin(R/d*numpy.sin(phi)) + indx= (ro/numpy.cos(phi) < R)*(numpy.cos(phi) > 0.) + l[indx]= numpy.pi-numpy.arcsin(R[indx]/d[indx]*numpy.sin(phi[indx])) if degree: l/= _DEGTORAD if scalarOut: @@ -1814,10 +1812,10 @@ else: d12= (z+delta)**2.+R**2. d22= (z-delta)**2.+R**2. - coshu= 0.5/delta*(sc.sqrt(d12)+sc.sqrt(d22)) - cosv= 0.5/delta*(sc.sqrt(d12)-sc.sqrt(d22)) + coshu= 0.5/delta*(numpy.sqrt(d12)+numpy.sqrt(d22)) + cosv= 0.5/delta*(numpy.sqrt(d12)-numpy.sqrt(d22)) if oblate: # cosv is currently really sinv - cosv= sc.sqrt(1.-cosv**2.) + cosv= numpy.sqrt(1.-cosv**2.) return (coshu,cosv) def Rz_to_uv(R,z,delta=1.,oblate=False): @@ -1852,8 +1850,8 @@ """ coshu, cosv= Rz_to_coshucosv(R,z,delta,oblate=oblate) - u= sc.arccosh(coshu) - v= sc.arccos(cosv) + u= numpy.arccosh(coshu) + v= numpy.arccos(cosv) return (u,v) def uv_to_Rz(u,v,delta=1.,oblate=False): @@ -1888,11 +1886,11 @@ """ if oblate: - R= delta*sc.cosh(u)*sc.sin(v) - z= delta*sc.sinh(u)*sc.cos(v) + R= delta*numpy.cosh(u)*numpy.sin(v) + z= delta*numpy.sinh(u)*numpy.cos(v) else: - R= delta*sc.sinh(u)*sc.sin(v) - z= delta*sc.cosh(u)*sc.cos(v) + R= delta*numpy.sinh(u)*numpy.sin(v) + z= delta*numpy.cosh(u)*numpy.cos(v) return (R,z) def vRvz_to_pupv(vR,vz,R,z,delta=1.,oblate=False,uv=False): @@ -1935,11 +1933,11 @@ else: u,v= R,z if oblate: - pu= delta*(vR*sc.sinh(u)*sc.sin(v)+vz*sc.cosh(u)*sc.cos(v)) - pv= delta*(vR*sc.cosh(u)*sc.cos(v)-vz*sc.sinh(u)*sc.sin(v)) + pu= delta*(vR*numpy.sinh(u)*numpy.sin(v)+vz*numpy.cosh(u)*numpy.cos(v)) + pv= delta*(vR*numpy.cosh(u)*numpy.cos(v)-vz*numpy.sinh(u)*numpy.sin(v)) else: - pu= delta*(vR*sc.cosh(u)*sc.sin(v)+vz*sc.sinh(u)*sc.cos(v)) - pv= delta*(vR*sc.sinh(u)*sc.cos(v)-vz*sc.cosh(u)*sc.sin(v)) + pu= delta*(vR*numpy.cosh(u)*numpy.sin(v)+vz*numpy.sinh(u)*numpy.cos(v)) + pv= delta*(vR*numpy.sinh(u)*numpy.cos(v)-vz*numpy.cosh(u)*numpy.sin(v)) return (pu,pv) def pupv_to_vRvz(pu,pv,u,v,delta=1.,oblate=False): @@ -1977,13 +1975,13 @@ """ if oblate: - denom= delta*(sc.sinh(u)**2.+sc.cos(v)**2.) - vR= (pu*sc.sinh(u)*sc.sin(v)+pv*sc.cosh(u)*sc.cos(v))/denom - vz= (pu*sc.cosh(u)*sc.cos(v)-pv*sc.sinh(u)*sc.sin(v))/denom + denom= delta*(numpy.sinh(u)**2.+numpy.cos(v)**2.) + vR= (pu*numpy.sinh(u)*numpy.sin(v)+pv*numpy.cosh(u)*numpy.cos(v))/denom + vz= (pu*numpy.cosh(u)*numpy.cos(v)-pv*numpy.sinh(u)*numpy.sin(v))/denom else: - denom= delta*(sc.sinh(u)**2.+sc.sin(v)**2.) - vR= (pu*sc.cosh(u)*sc.sin(v)+pv*sc.sinh(u)*sc.cos(v))/denom - vz= (pu*sc.sinh(u)*sc.cos(v)-pv*sc.cosh(u)*sc.sin(v))/denom + denom= delta*(numpy.sinh(u)**2.+numpy.sin(v)**2.) + vR= (pu*numpy.cosh(u)*numpy.sin(v)+pv*numpy.sinh(u)*numpy.cos(v))/denom + vz= (pu*numpy.sinh(u)*numpy.cos(v)-pv*numpy.cosh(u)*numpy.sin(v))/denom return (vR,vz) def Rz_to_lambdanu(R,z,ac=5.,Delta=1.): @@ -2023,14 +2021,14 @@ a = g - Delta**2 term = R**2 + z**2 - a - g discr = (R**2 + z**2 - Delta**2)**2 + (4. * Delta**2 * R**2) - l = 0.5 * (term + nu.sqrt(discr)) - n = 0.5 * (term - nu.sqrt(discr)) + l = 0.5 * (term + numpy.sqrt(discr)) + n = 0.5 * (term - numpy.sqrt(discr)) if isinstance(z,float) and z == 0.: l = R**2 - a n = -g - elif isinstance(z,nu.ndarray) and nu.sum(z == 0.) > 0: + elif isinstance(z,numpy.ndarray) and numpy.sum(z == 0.) > 0: if isinstance(R,float): l[z==0.] = R**2 - a - if isinstance(R,sc.ndarray): l[z==0.] = R[z==0.]**2 - a + if isinstance(R,numpy.ndarray): l[z==0.] = R[z==0.]**2 - a n[z==0.] = -g return (l,n) @@ -2062,14 +2060,14 @@ """ discr = (R**2 + z**2 - Delta**2)**2 + (4. * Delta**2 * R**2) - dldR = R * (1. + (R**2 + z**2 + Delta**2) / nu.sqrt(discr)) - dndR = R * (1. - (R**2 + z**2 + Delta**2) / nu.sqrt(discr)) - dldz = z * (1. + (R**2 + z**2 - Delta**2) / nu.sqrt(discr)) - dndz = z * (1. - (R**2 + z**2 - Delta**2) / nu.sqrt(discr)) + dldR = R * (1. + (R**2 + z**2 + Delta**2) / numpy.sqrt(discr)) + dndR = R * (1. - (R**2 + z**2 + Delta**2) / numpy.sqrt(discr)) + dldz = z * (1. + (R**2 + z**2 - Delta**2) / numpy.sqrt(discr)) + dndz = z * (1. - (R**2 + z**2 - Delta**2) / numpy.sqrt(discr)) dim = 1 - if isinstance(R,nu.ndarray): dim = len(R) - elif isinstance(z,nu.ndarray): dim = len(z) - jac = nu.zeros((2,2,dim)) + if isinstance(R,numpy.ndarray): dim = len(R) + elif isinstance(z,numpy.ndarray): dim = len(z) + jac = numpy.zeros((2,2,dim)) jac[0,0,:] = dldR jac[0,1,:] = dldz jac[1,0,:] = dndR @@ -2116,9 +2114,9 @@ d2ldRdz = 2.*R*z/discr**0.5 * ( 1. - ((R2+z2)**2-D**4)/discr) d2ndRdz = 2.*R*z/discr**0.5 * (-1. + ((R2+z2)**2-D**4)/discr) dim = 1 - if isinstance(R,nu.ndarray): dim = len(R) - elif isinstance(z,nu.ndarray): dim = len(z) - hess = nu.zeros((2,2,2,dim)) + if isinstance(R,numpy.ndarray): dim = len(R) + elif isinstance(z,numpy.ndarray): dim = len(z) + hess = numpy.zeros((2,2,2,dim)) #Hessian for lambda: hess[0,0,0,:] = d2ldR2 hess[0,0,1,:] = d2ldRdz @@ -2167,14 +2165,14 @@ r2 = (l + a) * (n + a) / (a - g) z2 = (l + g) * (n + g) / (g - a) index = (r2 < 0.) * ((n+a) > 0.) * ((n+a) < 1e-10) - if nu.any(index): - if isinstance(r2,nu.ndarray): r2[index] = 0. + if numpy.any(index): + if isinstance(r2,numpy.ndarray): r2[index] = 0. else: r2 = 0. index = (z2 < 0.) * ((n+g) < 0.) * ((n+g) > -1e-10) - if nu.any(index): - if isinstance(z2,nu.ndarray): z2[index] = 0. + if numpy.any(index): + if isinstance(z2,numpy.ndarray): z2[index] = 0. else: z2 = 0. - return (nu.sqrt(r2),nu.sqrt(z2)) + return (numpy.sqrt(r2),numpy.sqrt(z2)) @scalarDecorator @@ -2216,14 +2214,14 @@ """ if T is None: raise ValueError("Must set T= for radec_to_custom") #Whether to use degrees and scalar input is handled by decorators - XYZ= nu.array([nu.cos(dec)*nu.cos(ra), - nu.cos(dec)*nu.sin(ra), - nu.sin(dec)]) - galXYZ= nu.dot(T,XYZ) - b= nu.arcsin(galXYZ[2]) # [-pi/2, pi/2] - l= nu.arctan2(galXYZ[1], galXYZ[0]) - l[l<0] += 2 * nu.pi # fix range to [0, 2 pi] - out= nu.array([l,b]) + XYZ= numpy.array([numpy.cos(dec)*numpy.cos(ra), + numpy.cos(dec)*numpy.sin(ra), + numpy.sin(dec)]) + galXYZ= numpy.dot(T,XYZ) + b= numpy.arcsin(galXYZ[2]) # [-pi/2, pi/2] + l= numpy.arctan2(galXYZ[1], galXYZ[0]) + l[l<0] += 2 * numpy.pi # fix range to [0, 2 pi] + out= numpy.array([l,b]) return out.T @@ -2266,22 +2264,22 @@ """ if T is None: raise ValueError("Must set T= for pmrapmdec_to_custom") # Need to figure out ra_ngp and dec_ngp for this custom set of sky coords - ra_ngp, dec_ngp= custom_to_radec(0., nu.pi/2, T=T) + ra_ngp, dec_ngp= custom_to_radec(0., numpy.pi/2, T=T) #Whether to use degrees and scalar input is handled by decorators dec[dec == dec_ngp]+= 10.**-16 #deal w/ pole. - sindec_ngp= nu.sin(dec_ngp) - cosdec_ngp= nu.cos(dec_ngp) - sindec= nu.sin(dec) - cosdec= nu.cos(dec) - sinrarangp= nu.sin(ra-ra_ngp) - cosrarangp= nu.cos(ra-ra_ngp) + sindec_ngp= numpy.sin(dec_ngp) + cosdec_ngp= numpy.cos(dec_ngp) + sindec= numpy.sin(dec) + cosdec= numpy.cos(dec) + sinrarangp= numpy.sin(ra-ra_ngp) + cosrarangp= numpy.cos(ra-ra_ngp) cosphi= sindec_ngp*cosdec-cosdec_ngp*sindec*cosrarangp sinphi= sinrarangp*cosdec_ngp - norm= nu.sqrt(cosphi**2.+sinphi**2.) + norm= numpy.sqrt(cosphi**2.+sinphi**2.) cosphi/= norm sinphi/= norm - return (nu.array([[cosphi,-sinphi],[sinphi,cosphi]]).T\ - *nu.array([[pmra,pmra],[pmdec,pmdec]]).T).sum(-1) + return (numpy.array([[cosphi,-sinphi],[sinphi,cosphi]]).T\ + *numpy.array([[pmra,pmra],[pmdec,pmdec]]).T).sum(-1) def custom_to_radec(phi1,phi2,T=None,degree=False): @@ -2315,7 +2313,7 @@ """ if T is None: raise ValueError("Must set T= for custom_to_radec") return radec_to_custom(phi1, phi2, - T=nu.transpose(T), # T.T = inv(T) + T=numpy.transpose(T), # T.T = inv(T) degree=degree) @@ -2356,7 +2354,7 @@ """ if T is None: raise ValueError("Must set T= for custom_to_pmrapmdec") return pmrapmdec_to_custom(pmphi1, pmphi2, phi1, phi2, - T=nu.transpose(T), # T.T = inv(T) + T=numpy.transpose(T), # T.T = inv(T) degree=degree) @@ -2388,13 +2386,13 @@ """ if epoch == 2000.0: # Following astropy's definition here - theta= 122.9319185680026/180.*sc.pi - dec_ngp= 27.12825118085622/180.*sc.pi - ra_ngp= 192.8594812065348/180.*sc.pi + theta= 122.9319185680026/180.*numpy.pi + dec_ngp= 27.12825118085622/180.*numpy.pi + ra_ngp= 192.8594812065348/180.*numpy.pi elif epoch == 1950.0: - theta= 123./180.*sc.pi - dec_ngp= 27.4/180.*sc.pi - ra_ngp= 192.25/180.*sc.pi + theta= 123./180.*numpy.pi + dec_ngp= 27.4/180.*numpy.pi + ra_ngp= 192.25/180.*numpy.pi elif epoch == None: # obtained below theta= theta_icrs dec_ngp= dec_ngp_icrs @@ -2450,34 +2448,34 @@ # so we rotate Bovy (2011) such that we agree; for that we compute what NGP # goes to using astropy's transformations theta,dec_ngp,ra_ngp= get_epoch_angles(None) # None = ICRS, basis for astropy -dec_gc,ra_gc= -28.936175/180.*nu.pi,266.4051/180.*nu.pi # from apy def. -eta= 58.5986320306/180.*nu.pi # astropy 'roll' angle -gc_vec= nu.array(\ - [nu.cos(theta)*(-nu.sin(dec_ngp)*nu.cos(dec_gc)*nu.cos(ra_gc-ra_ngp) - +nu.cos(dec_ngp)*nu.sin(dec_gc)) - +nu.sin(theta)*nu.cos(dec_gc)*nu.sin(ra_gc-ra_ngp), - nu.sin(theta)*(-nu.sin(dec_ngp)*nu.cos(dec_gc)*nu.cos(ra_gc-ra_ngp) - +nu.cos(dec_ngp)*nu.sin(dec_gc)) - -nu.cos(theta)*nu.cos(dec_gc)*nu.sin(ra_gc-ra_ngp), - nu.cos(dec_ngp)*nu.cos(dec_gc)*nu.cos(ra_gc-ra_ngp) - +nu.sin(dec_ngp)*nu.sin(dec_gc)]) -galcen_extra_rot1= _rotate_to_arbitrary_vector(nu.atleast_2d(gc_vec), - nu.array([1.,0.,0.]), +dec_gc,ra_gc= -28.936175/180.*numpy.pi,266.4051/180.*numpy.pi # from apy def. +eta= 58.5986320306/180.*numpy.pi # astropy 'roll' angle +gc_vec= numpy.array(\ + [numpy.cos(theta)*(-numpy.sin(dec_ngp)*numpy.cos(dec_gc)*numpy.cos(ra_gc-ra_ngp) + +numpy.cos(dec_ngp)*numpy.sin(dec_gc)) + +numpy.sin(theta)*numpy.cos(dec_gc)*numpy.sin(ra_gc-ra_ngp), + numpy.sin(theta)*(-numpy.sin(dec_ngp)*numpy.cos(dec_gc)*numpy.cos(ra_gc-ra_ngp) + +numpy.cos(dec_ngp)*numpy.sin(dec_gc)) + -numpy.cos(theta)*numpy.cos(dec_gc)*numpy.sin(ra_gc-ra_ngp), + numpy.cos(dec_ngp)*numpy.cos(dec_gc)*numpy.cos(ra_gc-ra_ngp) + +numpy.sin(dec_ngp)*numpy.sin(dec_gc)]) +galcen_extra_rot1= _rotate_to_arbitrary_vector(numpy.atleast_2d(gc_vec), + numpy.array([1.,0.,0.]), inv=False,_dontcutsmall=True)[0] -ngp_vec= nu.dot(galcen_extra_rot1,nu.array(\ - [-nu.cos(dec_gc)*nu.cos(dec_ngp)*nu.cos(ra_ngp-ra_gc) - -nu.sin(dec_gc)*nu.sin(dec_ngp), - nu.cos(eta)*nu.cos(dec_ngp)*nu.sin(ra_ngp-ra_gc) - +nu.sin(eta)*(-nu.sin(dec_gc)*nu.cos(dec_ngp)*nu.cos(ra_ngp-ra_gc) - +nu.cos(dec_gc)*nu.sin(dec_ngp)), - -nu.sin(eta)*nu.cos(dec_ngp)*nu.sin(ra_ngp-ra_gc) - +nu.cos(eta)*(-nu.sin(dec_gc)*nu.cos(dec_ngp)*nu.cos(ra_ngp-ra_gc) - +nu.cos(dec_gc)*nu.sin(dec_ngp))])) -galcen_extra_rot2= _rotate_to_arbitrary_vector(nu.atleast_2d(ngp_vec), - nu.array([0.,0.,1.]), +ngp_vec= numpy.dot(galcen_extra_rot1,numpy.array(\ + [-numpy.cos(dec_gc)*numpy.cos(dec_ngp)*numpy.cos(ra_ngp-ra_gc) + -numpy.sin(dec_gc)*numpy.sin(dec_ngp), + numpy.cos(eta)*numpy.cos(dec_ngp)*numpy.sin(ra_ngp-ra_gc) + +numpy.sin(eta)*(-numpy.sin(dec_gc)*numpy.cos(dec_ngp)*numpy.cos(ra_ngp-ra_gc) + +numpy.cos(dec_gc)*numpy.sin(dec_ngp)), + -numpy.sin(eta)*numpy.cos(dec_ngp)*numpy.sin(ra_ngp-ra_gc) + +numpy.cos(eta)*(-numpy.sin(dec_gc)*numpy.cos(dec_ngp)*numpy.cos(ra_ngp-ra_gc) + +numpy.cos(dec_gc)*numpy.sin(dec_ngp))])) +galcen_extra_rot2= _rotate_to_arbitrary_vector(numpy.atleast_2d(ngp_vec), + numpy.array([0.,0.,1.]), inv=True,_dontcutsmall=True)[0] # Leave x axis alone, because in place by rot1 galcen_extra_rot2[0,0]= 1. galcen_extra_rot2[0,1:]= 0. galcen_extra_rot2[1:,0]= 0. -galcen_extra_rot= nu.dot(galcen_extra_rot2,galcen_extra_rot1) +galcen_extra_rot= numpy.dot(galcen_extra_rot2,galcen_extra_rot1) diff -Nru galpy-1.5/galpy/util/bovy_plot.py galpy-1.6.0.post0/galpy/util/bovy_plot.py --- galpy-1.5/galpy/util/bovy_plot.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/bovy_plot.py 2020-04-24 19:48:38.000000000 +0000 @@ -17,7 +17,7 @@ # ############################################################################# ############################################################################# -#Copyright (c) 2010 - 2013, Jo Bovy +#Copyright (c) 2010 - 2019, Jo Bovy #All rights reserved. # #Redistribution and use in source and binary forms, with or without @@ -45,12 +45,10 @@ #POSSIBILITY OF SUCH DAMAGE. ############################################################################# import re -import math as m -import scipy as sc +import numpy from scipy import special from scipy import interpolate from scipy import ndimage -import matplotlib import matplotlib.pyplot as pyplot import matplotlib.ticker as ticker import matplotlib.cm as cm @@ -58,8 +56,8 @@ from matplotlib.ticker import NullFormatter from matplotlib.projections import PolarAxes, register_projection from matplotlib.transforms import Affine2D, Bbox, IdentityTransform -from mpl_toolkits.mplot3d import Axes3D -from galpy.util.config import __config__ +from mpl_toolkits.mplot3d import Axes3D # Necessary for 3D plotting (projection = '3d') +from ..util.config import __config__ if __config__.getboolean('plot','seaborn-bovy-defaults'): try: import seaborn as sns @@ -70,7 +68,7 @@ 'ytick.direction': u'in', 'axes.labelsize': 18.0, 'axes.titlesize': 18.0, - 'figure.figsize': sc.array([ 6.64, 4. ]), + 'figure.figsize': numpy.array([ 6.64, 4. ]), 'grid.linewidth': 2.0, 'legend.fontsize': 18.0, 'lines.linewidth': 2.0, @@ -170,7 +168,7 @@ _add_axislabels(xlabel,ylabel) if not 'range' in kwargs and not xrangeSet: if isinstance(x,list): - xlimits=(sc.array(x).min(),sc.array(x).max()) + xlimits=(numpy.array(x).min(),numpy.array(x).max()) else: pyplot.xlim(x.min(),x.max()) elif xrangeSet: @@ -257,10 +255,10 @@ bins= kwargs['bins'] kwargs.pop('bins') elif onedhists: - if isinstance(args[0],sc.ndarray): - bins= round(0.3*sc.sqrt(args[0].shape[0])) + if isinstance(args[0],numpy.ndarray): + bins= round(0.3*numpy.sqrt(args[0].shape[0])) elif isinstance(args[0],list): - bins= round(0.3*sc.sqrt(len(args[0]))) + bins= round(0.3*numpy.sqrt(len(args[0]))) else: bins= 30 if onedhists: @@ -292,19 +290,19 @@ xlimits= kwargs.pop('xrange',None) if xlimits is None: if isinstance(args[0],list): - xlimits=(sc.array(args[0]).min(),sc.array(args[0]).max()) + xlimits=(numpy.array(args[0]).min(),numpy.array(args[0]).max()) else: xlimits=(args[0].min(),args[0].max()) ylimits= kwargs.pop('yrange',None) if ylimits is None: if isinstance(args[1],list): - ylimits=(sc.array(args[1]).min(),sc.array(args[1]).max()) + ylimits=(numpy.array(args[1]).min(),numpy.array(args[1]).max()) else: ylimits=(args[1].min(),args[1].max()) climits= kwargs.pop('crange',None) if climits is None and scatter: if 'c' in kwargs and isinstance(kwargs['c'],list): - climits=(sc.array(kwargs['c']).min(),sc.array(kwargs['c']).max()) + climits=(numpy.array(kwargs['c']).min(),numpy.array(kwargs['c']).max()) elif 'c' in kwargs: climits=(kwargs['c'].min(),kwargs['c'].max()) else: @@ -367,8 +365,8 @@ ec=onedhistec) axHistx.set_xlim( axScatter.get_xlim() ) axHisty.set_ylim( axScatter.get_ylim() ) - axHistx.set_ylim( 0, 1.2*sc.amax(histx)) - axHisty.set_xlim( 0, 1.2*sc.amax(histy)) + axHistx.set_ylim( 0, 1.2*numpy.amax(histx)) + axHisty.set_xlim( 0, 1.2*numpy.amax(histy)) return (axScatter,axHistx,axHisty) def bovy_plot3d(*args,**kwargs): @@ -413,21 +411,21 @@ xlimits= kwargs.pop('xrange') else: if isinstance(args[0],list): - xlimits=(sc.array(args[0]).min(),sc.array(args[0]).max()) + xlimits=(numpy.array(args[0]).min(),numpy.array(args[0]).max()) else: xlimits=(args[0].min(),args[0].max()) if 'yrange' in kwargs: ylimits= kwargs.pop('yrange') else: if isinstance(args[1],list): - ylimits=(sc.array(args[1]).min(),sc.array(args[1]).max()) + ylimits=(numpy.array(args[1]).min(),numpy.array(args[1]).max()) else: ylimits=(args[1].min(),args[1].max()) if 'zrange' in kwargs: zlimits= kwargs.pop('zrange') else: if isinstance(args[2],list): - zlimits=(sc.array(args[2]).min(),sc.array(args[2]).max()) + zlimits=(numpy.array(args[2]).min(),numpy.array(args[2]).max()) else: zlimits=(args[1].min(),args[2].max()) out= pyplot.plot(*args,**kwargs) @@ -559,11 +557,11 @@ kwargs.pop('levels') elif contours: if 'cntrmass' in kwargs and kwargs['cntrmass']: - levels= sc.linspace(0.,1.,_DEFAULTNCNTR) - elif True in sc.isnan(sc.array(X)): - levels= sc.linspace(sc.nanmin(X),sc.nanmax(X),_DEFAULTNCNTR) + levels= numpy.linspace(0.,1.,_DEFAULTNCNTR) + elif True in numpy.isnan(numpy.array(X)): + levels= numpy.linspace(numpy.nanmin(X),numpy.nanmax(X),_DEFAULTNCNTR) else: - levels= sc.linspace(sc.amin(X),sc.amax(X),_DEFAULTNCNTR) + levels= numpy.linspace(numpy.amin(X),numpy.amax(X),_DEFAULTNCNTR) cntrmass= kwargs.pop('cntrmass',False) conditional= kwargs.pop('conditional',False) cntrcolors= kwargs.pop('cntrcolors','k') @@ -604,7 +602,7 @@ ax=pyplot.gca() ax.set_autoscale_on(False) if conditional: - plotthis= X/sc.tile(sc.sum(X,axis=0),(X.shape[1],1)) + plotthis= X/numpy.tile(numpy.sum(X,axis=0),(X.shape[1],1)) else: plotthis= X if not justcontours: @@ -616,7 +614,7 @@ #Add colorbar if cb and not justcontours: if shrink is None: - shrink= sc.amin([float(kwargs.pop('aspect',1.))*0.87,1.]) + shrink= numpy.amin([float(kwargs.pop('aspect',1.))*0.87,1.]) CB1= pyplot.colorbar(out,shrink=shrink) if not zlabel is None: if zlabel[0] != '$': @@ -629,12 +627,12 @@ origin= kwargs.get('origin',None) if cntrmass: #Sum from the top down! - plotthis[sc.isnan(plotthis)]= 0. - sortindx= sc.argsort(plotthis.flatten())[::-1] - cumul= sc.cumsum(sc.sort(plotthis.flatten())[::-1])/sc.sum(plotthis.flatten()) - cntrThis= sc.zeros(sc.prod(plotthis.shape)) + plotthis[numpy.isnan(plotthis)]= 0. + sortindx= numpy.argsort(plotthis.flatten())[::-1] + cumul= numpy.cumsum(numpy.sort(plotthis.flatten())[::-1])/numpy.sum(plotthis.flatten()) + cntrThis= numpy.zeros(numpy.prod(plotthis.shape)) cntrThis[sortindx]= cumul - cntrThis= sc.reshape(cntrThis,plotthis.shape) + cntrThis= numpy.reshape(cntrThis,plotthis.shape) else: cntrThis= plotthis if contours: @@ -662,20 +660,20 @@ return cntrThis else: return out - histx= sc.nansum(X.T,axis=1)*m.fabs(ylimits[1]-ylimits[0])/X.shape[1] #nansum bc nan is *no dens value* - histy= sc.nansum(X.T,axis=0)*m.fabs(xlimits[1]-xlimits[0])/X.shape[0] - histx[sc.isnan(histx)]= 0. - histy[sc.isnan(histy)]= 0. + histx= numpy.nansum(X.T,axis=1)*numpy.fabs(ylimits[1]-ylimits[0])/X.shape[1] #nansum bc nan is *no dens value* + histy= numpy.nansum(X.T,axis=0)*numpy.fabs(xlimits[1]-xlimits[0])/X.shape[0] + histx[numpy.isnan(histx)]= 0. + histy[numpy.isnan(histy)]= 0. dx= (extent[1]-extent[0])/float(len(histx)) - axHistx.plot(sc.linspace(extent[0]+dx,extent[1]-dx,len(histx)),histx, + axHistx.plot(numpy.linspace(extent[0]+dx,extent[1]-dx,len(histx)),histx, drawstyle='steps-mid',color=onedhistcolor) dy= (extent[3]-extent[2])/float(len(histy)) - axHisty.plot(histy,sc.linspace(extent[2]+dy,extent[3]-dy,len(histy)), + axHisty.plot(histy,numpy.linspace(extent[2]+dy,extent[3]-dy,len(histy)), drawstyle='steps-mid',color=onedhistcolor) axHistx.set_xlim( axScatter.get_xlim() ) axHisty.set_ylim( axScatter.get_ylim() ) - axHistx.set_ylim( 0, 1.2*sc.amax(histx)) - axHisty.set_xlim( 0, 1.2*sc.amax(histy)) + axHistx.set_ylim( 0, 1.2*numpy.amax(histx)) + axHisty.set_xlim( 0, 1.2*numpy.amax(histy)) if retCumImage: return cntrThis elif retAxes: @@ -883,17 +881,17 @@ if 'xrange' in kwargs: xrange= kwargs.pop('xrange') else: - if isinstance(x,list): xrange=[sc.amin(x),sc.amax(x)] + if isinstance(x,list): xrange=[numpy.amin(x),numpy.amax(x)] else: xrange=[x.min(),x.max()] if 'yrange' in kwargs: yrange= kwargs.pop('yrange') else: - if isinstance(y,list): yrange=[sc.amin(y),sc.amax(y)] + if isinstance(y,list): yrange=[numpy.amin(y),numpy.amax(y)] else: yrange=[y.min(),y.max()] ndata= len(x) - bins= kwargs.pop('bins',round(0.3*sc.sqrt(ndata))) + bins= kwargs.pop('bins',round(0.3*numpy.sqrt(ndata))) weights= kwargs.pop('weights',None) - levels= kwargs.pop('levels',special.erf(sc.arange(1,4)/sc.sqrt(2.))) + levels= kwargs.pop('levels',special.erf(numpy.arange(1,4)/numpy.sqrt(2.))) aspect= kwargs.pop('aspect',(xrange[1]-xrange[0])/(yrange[1]-yrange[0])) conditional= kwargs.pop('conditional',False) contours= kwargs.pop('contours',True) @@ -911,7 +909,7 @@ onedhistec= kwargs.pop('onedhistec','k') onedhistls= kwargs.pop('onedhistls','solid') onedhistlw= kwargs.pop('onedhistlw',None) - onedhistsbins= kwargs.pop('onedhistsbins',round(0.3*sc.sqrt(ndata))) + onedhistsbins= kwargs.pop('onedhistsbins',round(0.3*numpy.sqrt(ndata))) overplot= kwargs.pop('overplot',False) gcf= kwargs.pop('gcf',False) cmap= kwargs.pop('cmap',cm.gist_yarg) @@ -943,14 +941,14 @@ axHisty.xaxis.set_major_formatter(nullfmt) axHisty.yaxis.set_major_formatter(nullfmt) fig.sca(axScatter) - data= sc.array([x,y]).T + data= numpy.array([x,y]).T if 'hist' in kwargs and 'edges' in kwargs: hist=kwargs['hist'] kwargs.pop('hist') edges=kwargs['edges'] kwargs.pop('edges') else: - hist, edges= sc.histogramdd(data,bins=bins,range=[xrange,yrange], + hist, edges= numpy.histogramdd(data,bins=bins,range=[xrange,yrange], weights=weights) if contours: cumimage= bovy_dens2d(hist.T,contours=contours,levels=levels, @@ -982,18 +980,18 @@ xedge= edges[0] for ii in range(len(xedge)-1): binxs.append((xedge[ii]+xedge[ii+1])/2.) - binxs= sc.array(binxs) + binxs= numpy.array(binxs) binys= [] yedge= edges[1] for ii in range(len(yedge)-1): binys.append((yedge[ii]+yedge[ii+1])/2.) - binys= sc.array(binys) + binys= numpy.array(binys) cumInterp= interpolate.RectBivariateSpline(binxs,binys,cumimage.T, kx=1,ky=1) cums= [] for ii in range(len(x)): cums.append(cumInterp(x[ii],y[ii])[0,0]) - cums= sc.array(cums) + cums= numpy.array(cums) plotx= x[cums > levels[-1]] ploty= y[cums > levels[-1]] if not len(plotx) == 0: @@ -1031,10 +1029,10 @@ lw=onedhistlw) if onedhistx and not overplot: axHistx.set_xlim( axScatter.get_xlim() ) - axHistx.set_ylim( 0, 1.2*sc.amax(histx)) + axHistx.set_ylim( 0, 1.2*numpy.amax(histx)) if onedhisty and not overplot: axHisty.set_ylim( axScatter.get_ylim() ) - axHisty.set_xlim( 0, 1.2*sc.amax(histy)) + axHisty.set_xlim( 0, 1.2*numpy.amax(histy)) if not onedhistx: axHistx= None if not onedhisty: axHisty= None if retAxes: @@ -1122,13 +1120,13 @@ class GalPolarTransform(PolarAxes.PolarTransform): def transform(self, tr): - xy = sc.zeros(tr.shape, sc.float_) + xy = numpy.zeros(tr.shape, numpy.float_) t = tr[:, 0:1] r = tr[:, 1:2] x = xy[:, 0:1] y = xy[:, 1:2] - x[:] = r * sc.cos(t) - y[:] = -r * sc.sin(t) + x[:] = r * numpy.cos(t) + y[:] = -r * numpy.sin(t) return xy transform_non_affine = transform @@ -1140,9 +1138,9 @@ def transform(self, xy): x = xy[:, 0:1] y = xy[:, 1:] - r = sc.sqrt(x*x + y*y) - theta = sc.arctan2(y, x) - return sc.concatenate((theta, r), 1) + r = numpy.sqrt(x*x + y*y) + theta = numpy.arctan2(y, x) + return numpy.concatenate((theta, r), 1) def inverted(self): return GalPolarAxes.GalPolarTransform() @@ -1162,7 +1160,7 @@ self._theta_label1_position + self._xaxis_transform) self._yaxis_transform = ( - Affine2D().scale(sc.pi * 2.0, 1.0) + + Affine2D().scale(numpy.pi * 2.0, 1.0) + self.transData) self._yaxis_text1_transform = ( self._r_label1_position + diff -Nru galpy-1.5/galpy/util/bovy_rk.c galpy-1.6.0.post0/galpy/util/bovy_rk.c --- galpy-1.5/galpy/util/bovy_rk.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/bovy_rk.c 2020-04-24 19:48:38.000000000 +0000 @@ -104,7 +104,12 @@ if ( interrupted ) { *err= -10; interrupted= 0; // need to reset, bc library and vars stay in memory +#ifdef USING_COVERAGE + __gcov_flush(); +#endif +// LCOV_EXCL_START break; +// LCOV_EXCL_STOP } for (jj=0; jj < (ndt-1); jj++) { bovy_rk4_onestep(func,dim,yn,yn1,to,dt,nargs,potentialArgs,ynk,a); @@ -208,7 +213,12 @@ if ( interrupted ) { *err= -10; interrupted= 0; // need to reset, bc library and vars stay in memory +#ifdef USING_COVERAGE + __gcov_flush(); +#endif +// LCOV_EXCL_START break; +// LCOV_EXCL_STOP } for (jj=0; jj < (ndt-1); jj++) { bovy_rk6_onestep(func,dim,yn,yn1,to,dt,nargs,potentialArgs,ynk,a, @@ -534,7 +544,12 @@ if ( interrupted ) { *err= -10; interrupted= 0; // need to reset, bc library and vars stay in memory +#ifdef USING_COVERAGE + __gcov_flush(); +#endif +// LCOV_EXCL_START break; +// LCOV_EXCL_STOP } bovy_dopr54_onestep(func,dim,yn,dt,&to,&dt_one, nargs,potentialArgs,rtol,atol, diff -Nru galpy-1.5/galpy/util/bovy_symplecticode.c galpy-1.6.0.post0/galpy/util/bovy_symplecticode.c --- galpy-1.5/galpy/util/bovy_symplecticode.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/bovy_symplecticode.c 2020-04-24 19:48:38.000000000 +0000 @@ -146,7 +146,12 @@ if ( interrupted ) { *err= -10; interrupted= 0; // need to reset, bc library and vars stay in memory +#ifdef USING_COVERAGE + __gcov_flush(); +#endif +// LCOV_EXCL_START break; +// LCOV_EXCL_STOP } //drift half leapfrog_leapq(dim,qo,po,dt/2.,q12); @@ -266,7 +271,12 @@ if ( interrupted ) { *err= -10; interrupted= 0; // need to reset, bc library and vars stay in memory +#ifdef USING_COVERAGE + __gcov_flush(); +#endif +// LCOV_EXCL_START break; +// LCOV_EXCL_STOP } //drift for c1*dt leapfrog_leapq(dim,qo,po,c1*dt,q12); @@ -421,7 +431,12 @@ if ( interrupted ) { *err= -10; interrupted= 0; // need to reset, bc library and vars stay in memory +#ifdef USING_COVERAGE + __gcov_flush(); +#endif +// LCOV_EXCL_START break; +// LCOV_EXCL_STOP } //drift for c1*dt leapfrog_leapq(dim,qo,po,c1*dt,q12); diff -Nru galpy-1.5/galpy/util/bovy_symplecticode.py galpy-1.6.0.post0/galpy/util/bovy_symplecticode.py --- galpy-1.5/galpy/util/bovy_symplecticode.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/bovy_symplecticode.py 2020-04-24 19:48:38.000000000 +0000 @@ -30,7 +30,7 @@ #WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #POSSIBILITY OF SUCH DAMAGE. ############################################################################# -import numpy as nu +import numpy _MAX_DT_REDUCE= 10000. def leapfrog(func,yo,t,args=(),rtol=1.49012e-12,atol=1.49012e-12): """ @@ -53,7 +53,7 @@ #Initialize qo= yo[0:len(yo)//2] po= yo[len(yo)//2:len(yo)] - out= nu.zeros((len(t),len(yo))) + out= numpy.zeros((len(t),len(yo))) out[0,:]= yo #Estimate necessary step size dt= t[1]-t[0] #assumes that the steps are equally spaced @@ -86,9 +86,9 @@ def _leapfrog_estimate_step(func,qo,po,dt,to,args,rtol,atol): init_dt= dt - qmax= nu.amax(nu.fabs(qo))+nu.zeros(len(qo)) - pmax= nu.amax(nu.fabs(po))+nu.zeros(len(po)) - scale= atol+rtol*nu.array([qmax,pmax]).flatten() + qmax= numpy.amax(numpy.fabs(qo))+numpy.zeros(len(qo)) + pmax= numpy.amax(numpy.fabs(po))+numpy.zeros(len(po)) + scale= atol+rtol*numpy.array([qmax,pmax]).flatten() err= 2. dt*= 2. while err > 1. and init_dt/dt < _MAX_DT_REDUCE: @@ -107,8 +107,8 @@ p12= leapfrog_leapp(ptmp,dt/2.,force) q12= leapfrog_leapq(qtmp,p12,dt/4.) #Norm - delta= nu.array([nu.fabs(q11-q12),nu.fabs(p11-p12)]).flatten() - err= nu.sqrt(nu.mean((delta/scale)**2.)) + delta= numpy.array([numpy.fabs(q11-q12),numpy.fabs(p11-p12)]).flatten() + err= numpy.sqrt(numpy.mean((delta/scale)**2.)) dt/= 2. return dt diff -Nru galpy-1.5/galpy/util/__init__.py galpy-1.6.0.post0/galpy/util/__init__.py --- galpy-1.5/galpy/util/__init__.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/__init__.py 2020-04-24 19:48:38.000000000 +0000 @@ -6,7 +6,7 @@ import pickle import numpy import scipy.linalg as linalg -from galpy.util.config import __config__ +from ..util.config import __config__ _SHOW_WARNINGS= __config__.getboolean('warnings','verbose') class galpyWarning(Warning): pass diff -Nru galpy-1.5/galpy/util/leung_dop853.c galpy-1.6.0.post0/galpy/util/leung_dop853.c --- galpy-1.5/galpy/util/leung_dop853.c 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/leung_dop853.c 2020-04-24 19:48:38.000000000 +0000 @@ -337,7 +337,12 @@ if (interrupted) { *err_ = -10; interrupted = 0; // need to reset, bc library and vars stay in memory +#ifdef USING_COVERAGE + __gcov_flush(); +#endif +// LCOV_EXCL_START break; +// LCOV_EXCL_STOP } h = pos_neg * max(fabs(h), 1e3 * uround); // keep time step not too small @@ -508,4 +513,4 @@ free(rcont2); free(rcont1); //We're done -} \ No newline at end of file +} diff -Nru galpy-1.5/galpy/util/leung_dop853.py galpy-1.6.0.post0/galpy/util/leung_dop853.py --- galpy-1.5/galpy/util/leung_dop853.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/leung_dop853.py 2020-04-24 19:48:38.000000000 +0000 @@ -30,9 +30,7 @@ # WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. ############################################################################# - -import numpy as np - +import numpy # time increment coefficients c2 = 0.526001519587677318785587544488e-1 c3 = 0.789002279381515978178381316732e-1 @@ -200,40 +198,40 @@ er12 = -0.2235530786388629525884427845e-1 # machine limit related info from numpy -unsigned_int_max = np.iinfo(np.int32).max -uround = np.finfo(np.float).eps +unsigned_int_max = numpy.iinfo(numpy.int32).max +uround = numpy.finfo(numpy.float).eps def custom_sign(a, b): - return np.fabs(a) if b > 0.0 else -np.fabs(a) + return numpy.fabs(a) if b > 0.0 else -numpy.fabs(a) def hinit(func, x, t, pos_neg, f0, iord, hmax, rtol, atol, args): """ Estimate initial step size """ - sk = atol + rtol * np.fabs(x) - dnf = np.sum(np.square(f0 / sk), axis=0) - dny = np.sum(np.square(x / sk), axis=0) + sk = atol + rtol * numpy.fabs(x) + dnf = numpy.sum(numpy.square(f0 / sk), axis=0) + dny = numpy.sum(numpy.square(x / sk), axis=0) - h = np.sqrt(dny / dnf) * 0.01 + h = numpy.sqrt(dny / dnf) * 0.01 - h = np.min([h, np.fabs(hmax)]) + h = numpy.min([h, numpy.fabs(hmax)]) h = custom_sign(h, pos_neg) # perform an explicit Euler step xx1 = x + h * f0 - f1 = np.array(func(xx1, t[0] + h, *args)) + f1 = numpy.array(func(xx1, t[0] + h, *args)) # estimate the second derivative of the solution - der2 = np.sum(np.square((f1 - f0) / sk), axis=0) - der2 = np.sqrt(der2) / h + der2 = numpy.sum(numpy.square((f1 - f0) / sk), axis=0) + der2 = numpy.sqrt(der2) / h # step size is computed such that h ** iord * max_d(norm(f0), norm(der2)) = 0.01 - der12 = np.max([np.fabs(der2), np.sqrt(dnf)]) - h1 = np.power(0.01 / der12, 1.0 / iord) + der12 = numpy.max([numpy.fabs(der2), numpy.sqrt(dnf)]) + h1 = numpy.power(0.01 / der12, 1.0 / iord) - h = np.min([100.0 * np.fabs(h), np.min([np.fabs(h1), np.fabs(hmax)])]) + h = numpy.min([100.0 * numpy.fabs(h), numpy.min([numpy.fabs(h1), numpy.fabs(hmax)])]) return custom_sign(h, pos_neg), f0, f1, xx1 @@ -255,7 +253,7 @@ Core of DOP8(5, 3) integration """ # array to store the result - result = np.zeros((len(t), n)) + result = numpy.zeros((len(t), n)) # initial preparations facold = 1.0e-4 @@ -263,8 +261,8 @@ facc1 = 1.0 / fac1 facc2 = 1.0 / fac2 - k1 = np.array(func(x, t[0], *args)) - hmax = np.fabs(hmax) + k1 = numpy.array(func(x, t[0], *args)) + hmax = numpy.fabs(hmax) iord = 8 if h == 0.0: # estimate initial time step @@ -280,83 +278,83 @@ # basic integration step while finished_user_t_ii < len(t) - 1: # check if the current computed time indices less than total inices needed # keep time step not too small - h = pos_neg * np.max([np.fabs(h), 1e3 * uround]) + h = pos_neg * numpy.max([numpy.fabs(h), 1e3 * uround]) # the twelve stages xx1 = x + h * a21 * k1 - k2 = np.array(func(xx1, t_current + c2 * h, *args)) + k2 = numpy.array(func(xx1, t_current + c2 * h, *args)) xx1 = x + h * (a31 * k1 + a32 * k2) - k3 = np.array(func(xx1, t_current + c3 * h, *args)) + k3 = numpy.array(func(xx1, t_current + c3 * h, *args)) xx1 = x + h * (a41 * k1 + a43 * k3) - k4 = np.array(func(xx1, t_current + c4 * h, *args)) + k4 = numpy.array(func(xx1, t_current + c4 * h, *args)) xx1 = x + h * (a51 * k1 + a53 * k3 + a54 * k4) - k5 = np.array(func(xx1, t_current + c5 * h, *args)) + k5 = numpy.array(func(xx1, t_current + c5 * h, *args)) xx1 = x + h * (a61 * k1 + a64 * k4 + a65 * k5) - k6 = np.array(func(xx1, t_current + c6 * h, *args)) + k6 = numpy.array(func(xx1, t_current + c6 * h, *args)) xx1 = x + h * (a71 * k1 + a74 * k4 + a75 * k5 + a76 * k6) - k7 = np.array(func(xx1, t_current + c7 * h, *args)) + k7 = numpy.array(func(xx1, t_current + c7 * h, *args)) xx1 = x + h * (a81 * k1 + a84 * k4 + a85 * k5 + a86 * k6 + a87 * k7) - k8 = np.array(func(xx1, t_current + c8 * h, *args)) + k8 = numpy.array(func(xx1, t_current + c8 * h, *args)) xx1 = x + h * (a91 * k1 + a94 * k4 + a95 * k5 + a96 * k6 + a97 * k7 + a98 * k8) - k9 = np.array(func(xx1, t_current + c9 * h, *args)) + k9 = numpy.array(func(xx1, t_current + c9 * h, *args)) xx1 = x + h * (a101 * k1 + a104 * k4 + a105 * k5 + a106 * k6 + a107 * k7 + a108 * k8 + a109 * k9) - k10 = np.array(func(xx1, t_current + c10 * h, *args)) + k10 = numpy.array(func(xx1, t_current + c10 * h, *args)) xx1 = x + h * (a111 * k1 + a114 * k4 + a115 * k5 + a116 * k6 + a117 * k7 + a118 * k8 + a119 * k9 + a1110 * k10) - k2 = np.array(func(xx1, t_current + c11 * h, *args)) + k2 = numpy.array(func(xx1, t_current + c11 * h, *args)) xx1 = x + h * ( a121 * k1 + a124 * k4 + a125 * k5 + a126 * k6 + a127 * k7 + a128 * k8 + a129 * k9 + a1210 * k10 + a1211 * k2) - t_old_older = np.copy(t_old) - t_old = np.copy(t_current) + t_old_older = numpy.copy(t_old) + t_old = numpy.copy(t_current) t_current += h - k3 = np.array(func(xx1, t_current, *args)) + k3 = numpy.array(func(xx1, t_current, *args)) k4 = b1 * k1 + b6 * k6 + b7 * k7 + b8 * k8 + b9 * k9 + b10 * k10 + b11 * k2 + b12 * k3 k5 = x + h * k4 # error estimation - sk = atol + rtol * np.max([np.fabs(x), np.fabs(k5)], axis=0) + sk = atol + rtol * numpy.max([numpy.fabs(x), numpy.fabs(k5)], axis=0) erri = k4 - bhh1 * k1 - bhh2 * k9 - bhh3 * k3 - err2 = np.sum(np.square(erri / sk), axis=0) + err2 = numpy.sum(numpy.square(erri / sk), axis=0) erri = er1 * k1 + er6 * k6 + er7 * k7 + er8 * k8 + er9 * k9 + er10 * k10 + er11 * k2 + er12 * k3 - err = np.sum(np.square(erri / sk), axis=0) + err = numpy.sum(numpy.square(erri / sk), axis=0) deno = err + 0.01 * err2 deno = 1.0 if deno <= 0.0 else deno - err = np.fabs(h) * err * np.sqrt(1.0 / (deno * n)) + err = numpy.fabs(h) * err * numpy.sqrt(1.0 / (deno * n)) # computation of hnew - fac11 = np.power(err, expo1) + fac11 = numpy.power(err, expo1) # Lund-stabilization fac = fac11 / pow(facold, beta) # we require fac1 <= hnew / h <= fac2 - fac = np.max([facc2, np.min([facc1, fac / safe])]) + fac = numpy.max([facc2, numpy.min([facc1, fac / safe])]) hnew = h / fac if err <= 1.0: # step accepted - facold = np.max([err, 1.0e-4]) - k4 = np.array(func(k5, t_current, *args)) + facold = numpy.max([err, 1.0e-4]) + k4 = numpy.array(func(k5, t_current, *args)) # final preparation for dense output - rcont1 = np.copy(x) + rcont1 = numpy.copy(x) xdiff = k5 - x rcont2 = xdiff bspl = h * k1 - xdiff - rcont3 = np.copy(bspl) + rcont3 = numpy.copy(bspl) rcont4 = xdiff - h * k4 - bspl rcont5 = d41 * k1 + d46 * k6 + d47 * k7 + d48 * k8 + d49 * k9 + d410 * k10 + d411 * k2 + d412 * k3 rcont6 = d51 * k1 + d56 * k6 + d57 * k7 + d58 * k8 + d59 * k9 + d510 * k10 + d511 * k2 + d512 * k3 @@ -366,13 +364,13 @@ # the next three function evaluations xx1 = x + h * ( a141 * k1 + a147 * k7 + a148 * k8 + a149 * k9 + a1410 * k10 + a1411 * k2 + a1412 * k3 + a1413 * k4) - k10 = np.array(func(xx1, t_old + c14 * h, *args)) + k10 = numpy.array(func(xx1, t_old + c14 * h, *args)) xx1 = x + h * ( a151 * k1 + a156 * k6 + a157 * k7 + a158 * k8 + a1511 * k2 + a1512 * k3 + a1513 * k4 + a1514 * k10) - k2 = np.array(func(xx1, t_old + c15 * h, *args)) + k2 = numpy.array(func(xx1, t_old + c15 * h, *args)) xx1 = x + h * ( a161 * k1 + a166 * k6 + a167 * k7 + a168 * k8 + a169 * k9 + a1613 * k4 + a1614 * k10 + a1615 * k2) - k3 = np.array(func(xx1, t_old + c16 * h, *args)) + k3 = numpy.array(func(xx1, t_old + c16 * h, *args)) # final preparation rcont5 = h * (rcont5 + d413 * k4 + d414 * k10 + d415 * k2 + d416 * k3) @@ -380,8 +378,8 @@ rcont7 = h * (rcont7 + d613 * k4 + d614 * k10 + d615 * k2 + d616 * k3) rcont8 = h * (rcont8 + d713 * k4 + d714 * k10 + d715 * k2 + d716 * k3) - k1 = np.copy(k4) - x = np.copy(k5) + k1 = numpy.copy(k4) + x = numpy.copy(k5) # loop for dense output in this time slot while (finished_user_t_ii < len(t) - 1) and (pos_neg * t[finished_user_t_ii + 1] < pos_neg * t_current): @@ -391,22 +389,22 @@ rcont8]) finished_user_t_ii += 1 - if np.fabs(hnew) > hmax: + if numpy.fabs(hnew) > hmax: hnew = pos_neg * hmax if reject: - hnew = pos_neg * np.min([np.fabs(hnew), np.fabs(h)]) + hnew = pos_neg * numpy.min([numpy.fabs(hnew), numpy.fabs(h)]) reject = 0 else: # step rejected since error too big - hnew = h / np.min([facc1, fac11 / safe]) + hnew = h / numpy.min([facc1, fac11 / safe]) reject = 1 # reverse time increment since error rejected - t_current = np.copy(t_old) - t_old = np.copy(t_old_older) + t_current = numpy.copy(t_old) + t_old = numpy.copy(t_old_older) - h = np.copy(hnew) # current h + h = numpy.copy(hnew) # current h return result diff -Nru galpy-1.5/galpy/util/_load_extension_libs.py galpy-1.6.0.post0/galpy/util/_load_extension_libs.py --- galpy-1.5/galpy/util/_load_extension_libs.py 1970-01-01 00:00:00.000000000 +0000 +++ galpy-1.6.0.post0/galpy/util/_load_extension_libs.py 2020-04-24 19:48:38.000000000 +0000 @@ -0,0 +1,86 @@ +# _load_extension_libs.py: centralized place to load the C extensions +import os +import sys +import distutils.sysconfig as sysconfig +import warnings +import ctypes +from ..util import galpyWarning, galpyWarningVerbose + +PY3= sys.version > '3' +if PY3: + _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') +else: #pragma: no cover + _ext_suffix= '.so' + +_libgalpy= None +_libgalpy_loaded= None + +_libgalpy_actionAngleTorus= None +_libgalpy_actionAngleTorus_loaded= None + +def load_libgalpy(): + global _libgalpy + global _libgalpy_loaded + if _libgalpy_loaded is False or not _libgalpy is None: + return (_libgalpy,_libgalpy_loaded) + outerr= None + for path in sys.path: + if not os.path.isdir(path): continue + try: + if sys.platform == 'win32' and sys.version_info >= (3,8): # pragma: no cover + # winmode=0x008 is easy-going way to call LoadLibraryExA + _lib = ctypes.CDLL(os.path.join(path,'libgalpy%s' % _ext_suffix),winmode=0x008) + else: + _lib = ctypes.CDLL(os.path.join(path,'libgalpy%s' % _ext_suffix)) + except OSError as e: + if os.path.exists(os.path.join(path,'libgalpy%s' % _ext_suffix)): #pragma: no cover + outerr= e + _lib = None + else: + break + if _lib is None: #pragma: no cover + if not outerr is None: + warnings.warn("libgalpy C extension module not loaded, because of error '%s' " % outerr, + galpyWarning) + else: + warnings.warn("libgalpy C extension module not loaded, because libgalpy%s image was not found" % _ext_suffix, + galpyWarning) + _libgalpy_loaded= False + else: + _libgalpy_loaded= True + _libgalpy= _lib + return (_libgalpy,_libgalpy_loaded) + +def load_libgalpy_actionAngleTorus(): + global _libgalpy_actionAngleTorus + global _libgalpy_actionAngleTorus_loaded + if _libgalpy_actionAngleTorus_loaded is False \ + or not _libgalpy_actionAngleTorus is None: + return (_libgalpy_actionAngleTorus,_libgalpy_actionAngleTorus_loaded) + outerr= None + for path in sys.path: + if not os.path.isdir(path): continue + try: + if sys.platform == 'win32' and sys.version_info >= (3,8): # pragma: no cover + # winmode=0x008 is easy-going way to call LoadLibraryExA + _lib = ctypes.CDLL(os.path.join(path,'libgalpy_actionAngleTorus%s' % _ext_suffix),winmode=0x008) + else: + _lib = ctypes.CDLL(os.path.join(path,'libgalpy_actionAngleTorus%s' % _ext_suffix)) + except OSError as e: + if os.path.exists(os.path.join(path,'libgalpy_actionAngleTorus%s' % _ext_suffix)): #pragma: no cover + outerr= e + _lib = None + else: + break + if _lib is None: #pragma: no cover + if not outerr is None: + warnings.warn("libgalpy_actionAngleTorus C extension module not loaded, because of error '%s' " % outerr, + galpyWarningVerbose) + else: + warnings.warn("libgalpy_actionAngleTorus C extension module not loaded, because libgalpy%s image was not found" % _ext_suffix, + galpyWarningVerbose) + _libgalpy_actionAngleTorus_loaded= False + else: + _libgalpy_actionAngleTorus_loaded= True + _libgalpy_actionAngleTorus= _lib + return (_libgalpy_actionAngleTorus,_libgalpy_actionAngleTorus_loaded) diff -Nru galpy-1.5/galpy.egg-info/PKG-INFO galpy-1.6.0.post0/galpy.egg-info/PKG-INFO --- galpy-1.5/galpy.egg-info/PKG-INFO 2019-09-12 20:35:42.000000000 +0000 +++ galpy-1.6.0.post0/galpy.egg-info/PKG-INFO 2020-04-24 19:48:48.000000000 +0000 @@ -1,118 +1,108 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: galpy -Version: 1.5 +Version: 1.6.0.post0 Summary: Galactic Dynamics in python Home-page: http://github.com/jobovy/galpy Author: Jo Bovy Author-email: bovy@astro.utoronto.ca License: New BSD -Description: galpy - ====== - - **Galactic Dynamics in python** - - - - - - - - - - +Description:

+ Galactic Dynamics in python +

+ [galpy](http://www.galpy.org) is a Python 2 and 3 package for galactic dynamics. It supports orbit integration in a variety of potentials, evaluating and sampling various distribution functions, and the calculation of action-angle coordinates for all static potentials. `galpy` is an [astropy](http://www.astropy.org/) [affiliated package](http://www.astropy.org/affiliated/) and provides full support for astropy’s [Quantity](http://docs.astropy.org/en/stable/api/astropy.units.Quantity.html) framework for variables with units. AUTHOR - ------- + ====== Jo Bovy - bovy at astro dot utoronto dot ca - See `AUTHORS.txt - `__ for a - full list of contributors. - - If you find this code useful in your research, please let me - know. **If you use galpy in a publication, please cite** `Bovy (2015) - `__ **and link to - http://github.com/jobovy/galpy**. See `the acknowledgement documentation section - `__ - for a more detailed guide to citing parts of the code. Please also - send me a reference to the paper or send a pull request including your - paper in the list of galpy papers on `this page - `__ (this page is at + See + [AUTHORS.txt](https://github.com/jobovy/galpy/blob/master/AUTHORS.txt) + for a full list of contributors. + + If you find this code useful in your research, please let me know. **If + you use galpy in a publication, please cite** [Bovy + (2015)](http://adsabs.harvard.edu/abs/2015ApJS..216...29B) **and link to + http://github.com/jobovy/galpy**. See [the acknowledgement documentation + section](http://docs.galpy.org/en/latest/index.html#acknowledging-galpy) + for a more detailed guide to citing parts of the code. Please also send + me a reference to the paper or send a pull request including your paper + in the list of galpy papers on [this + page](http://docs.galpy.org/en/latest/) (this page is at doc/source/index.rst). Thanks! - LOOKING FOR HELP? - ----------------- - - The latest documentation can be found `here `__. You can also join the `galpy slack community `__ for any questions related to `galpy`; join `here `__. + ================= - If you find *any* bug in the code, please report these using the `Issue Tracker `__ or by joining the `galpy slack community `__. - - If you are having issues with the installation of ``galpy``, please first consult the `Installation FAQ `__. + The latest documentation can be found + [here](http://docs.galpy.org/en/latest/). You can also join the + [galpy slack community](https://galpy.slack.com/) for any questions + related to `galpy`; join + [here](https://slackin-galpy.herokuapp.com). + + If you find *any* bug in the code, please report these using the [Issue + Tracker](http://github.com/jobovy/galpy/issues) or by joining the [galpy + slack community](https://galpy.slack.com/). + + If you are having issues with the installation of `galpy`, please first + consult the [Installation + FAQ](http://docs.galpy.org/en/latest/installation.html#installation-faq). PYTHON VERSIONS AND DEPENDENCIES - --------------------------------- + ================================ - ``galpy`` supports both Python 2 and 3. Specifically, galpy supports - Python 2.7 and Python 3.6 and 3.7. It should also work on earlier - Python 3.* versions, but this is not extensively tested on an ongoing - basis. Travis CI builds regularly check support for Python 2.7 and 3.7 - (and of 3.6 using a more limited, core set of tests) and Appveyor - builds regularly check support for Python 3.7 on Windows. - - This package requires `Numpy `__, `Scipy - `__, and `Matplotlib - `__. Certain advanced features - require the GNU Scientific Library (`GSL - `__), with action calculations - requiring version 1.14 or higher. Use of ``SnapshotRZPotential`` and - ``InterpSnapshotRZPotential`` requires `pynbody - `__. Support for providing inputs - and getting outputs as Quantities with units is provided through - `astropy `__. + `galpy` supports both Python 2 and 3. Specifically, galpy supports + Python 2.7 and Python 3.6 and 3.7. It should also work on earlier Python + 3.\* versions, but this is not extensively tested on an ongoing basis. + Travis CI builds regularly check support for Python 2.7 and 3.7 (and of + 3.6 using a more limited, core set of tests) and Appveyor builds + regularly check support for Python 3.7 on Windows. + + This package requires [Numpy](https://numpy.org/), + [Scipy](http://www.scipy.org/), and + [Matplotlib](http://matplotlib.sourceforge.net/). Certain advanced + features require the GNU Scientific Library + ([GSL](http://www.gnu.org/software/gsl/)), with action calculations + requiring version 1.14 or higher. Use of `SnapshotRZPotential` and + `InterpSnapshotRZPotential` requires + [pynbody](https://github.com/pynbody/pynbody). Support for providing + inputs and getting outputs as Quantities with units is provided through + [astropy](http://www.astropy.org/). CONTRIBUTING TO GALPY - ---------------------- - - If you are interested in contributing to galpy's development, take a look at `this brief guide `__ on the wiki. This will hopefully help you get started! + ===================== - Some further development notes can be found on the `wiki - `__. This includes a list of - small and larger extensions of galpy that would be useful `here - `__ as - well as a longer-term roadmap `here - `__. Please let the main + If you are interested in contributing to galpy\'s development, take a + look at [this brief + guide](https://github.com/jobovy/galpy/wiki/Guide-for-new-contributors) + on the wiki. This will hopefully help you get started! + + Some further development notes can be found on the + [wiki](http://github.com/jobovy/galpy/wiki/). This includes a list of + small and larger extensions of galpy that would be useful + [here](http://github.com/jobovy/galpy/wiki/Possible-galpy-extensions) as + well as a longer-term roadmap + [here](http://github.com/jobovy/galpy/wiki/Roadmap). Please let the main developer know if you need any help contributing! - - - - - - - - - - - - DISK DF CORRECTIONS - -------------------- + =================== The dehnendf and shudf disk distribution functions can be corrected to follow the desired surface-mass density and radial-velocity-dispersion - profiles more closely (see `1999AJ....118.1201D - `__). Calculating - these corrections is expensive, and a large set of precalculated - corrections can be found `here - `__ - \[tar.gz archive\]. Install these by downloading them and unpacking them into the galpy/df/data directory before running the setup.py installation. E.g.:: + profiles more closely (see + [1999AJ\....118.1201D](http://adsabs.harvard.edu/abs/1999AJ....118.1201D)). + Calculating these corrections is expensive, and a large set of + precalculated corrections can be found + [here](http://github.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz) + \[tar.gz archive\]. Install these by downloading them and unpacking them + into the galpy/df/data directory before running the setup.py + installation. E.g.: - curl -O https://github.s3.amazonaws.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz - tar xvzf galpy-dfcorrections.tar.gz -C ./galpy/df/data/ + curl -O https://github.s3.amazonaws.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz + tar xvzf galpy-dfcorrections.tar.gz -C ./galpy/df/data/ Platform: UNKNOWN Classifier: Development Status :: 6 - Mature @@ -128,3 +118,4 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Scientific/Engineering :: Astronomy Classifier: Topic :: Scientific/Engineering :: Physics +Description-Content-Type: text/markdown diff -Nru galpy-1.5/galpy.egg-info/requires.txt galpy-1.6.0.post0/galpy.egg-info/requires.txt --- galpy-1.5/galpy.egg-info/requires.txt 2019-09-12 20:35:42.000000000 +0000 +++ galpy-1.6.0.post0/galpy.egg-info/requires.txt 2020-04-24 19:48:48.000000000 +0000 @@ -4,3 +4,4 @@ pytest six future +setuptools diff -Nru galpy-1.5/galpy.egg-info/SOURCES.txt galpy-1.6.0.post0/galpy.egg-info/SOURCES.txt --- galpy-1.5/galpy.egg-info/SOURCES.txt 2019-09-12 20:35:42.000000000 +0000 +++ galpy-1.6.0.post0/galpy.egg-info/SOURCES.txt 2020-04-24 19:48:48.000000000 +0000 @@ -3,8 +3,8 @@ LICENSE MANIFEST.in README.dev +README.md README.nemo -README.rst gsl-config.bat setup.py galpy/__init__.py @@ -81,6 +81,7 @@ galpy/potential/Force.py galpy/potential/GaussianAmplitudeWrapperPotential.py galpy/potential/HenonHeilesPotential.py +galpy/potential/HomogeneousSpherePotential.py galpy/potential/Irrgang13.py galpy/potential/IsochronePotential.py galpy/potential/IsothermalDiskPotential.py @@ -124,9 +125,12 @@ galpy/potential/verticalPotential.py galpy/potential/interppotential_c_ext/interppotential_calc_potential.c galpy/potential/potential_c_ext/BurkertPotential.c +galpy/potential/potential_c_ext/ChandrasekharDynamicalFrictionForce.c galpy/potential/potential_c_ext/CorotatingRotationWrapperPotential.c galpy/potential/potential_c_ext/CosmphiDiskPotential.c galpy/potential/potential_c_ext/DehnenBarPotential.c +galpy/potential/potential_c_ext/DehnenCorePotential.c +galpy/potential/potential_c_ext/DehnenPotential.c galpy/potential/potential_c_ext/DehnenSmoothWrapperPotential.c galpy/potential/potential_c_ext/DiskSCFPotential.c galpy/potential/potential_c_ext/DoubleExponentialDiskPotential.c @@ -136,6 +140,7 @@ galpy/potential/potential_c_ext/GaussianAmplitudeWrapperPotential.c galpy/potential/potential_c_ext/HenonHeilesPotential.c galpy/potential/potential_c_ext/HernquistPotential.c +galpy/potential/potential_c_ext/HomogeneousSpherePotential.c galpy/potential/potential_c_ext/IsochronePotential.c galpy/potential/potential_c_ext/IsothermalDiskPotential.c galpy/potential/potential_c_ext/JaffePotential.c @@ -171,6 +176,7 @@ galpy/snapshot/nemo_util.py galpy/snapshot/snapshotMovies.py galpy/util/__init__.py +galpy/util/_load_extension_libs.py galpy/util/bovy_ars.py galpy/util/bovy_conversion.py galpy/util/bovy_coords.c diff -Nru galpy-1.5/galpy.egg-info/top_level.txt galpy-1.6.0.post0/galpy.egg-info/top_level.txt --- galpy-1.5/galpy.egg-info/top_level.txt 2019-09-12 20:35:42.000000000 +0000 +++ galpy-1.6.0.post0/galpy.egg-info/top_level.txt 2020-04-24 19:48:48.000000000 +0000 @@ -5,6 +5,4 @@ galpy/potential galpy/snapshot galpy/util -galpy_actionAngle_c -galpy_integrate_c -galpy_interppotential_c +libgalpy diff -Nru galpy-1.5/HISTORY.txt galpy-1.6.0.post0/HISTORY.txt --- galpy-1.5/HISTORY.txt 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/HISTORY.txt 2020-04-24 19:48:38.000000000 +0000 @@ -1,3 +1,47 @@ +v1.6 (2020-04-24) +================= + +- Added HomogeneousSpherePotential, the potential of a constant + density sphere out to some radius R. + +- Added DehnenSphericalPotential and DehnenCoreSphericalPotential, the + general potential from Dehnen (1993) and its cored special case + (#403). + +- Standardized the way packages are imported: numpy as 'import numpy', + avoid use of math, don't use scipy's numpy interface, internal + imports for all galpy imports. + +- Implemented ChandrasekharDynamicalFrictionForce in C, introducing a + general scheme for easily implementing velocity-dependent forces in + C without requiring all forces to take velocity arguments (#420). + +- Fixed AMUSE compatibility with Potentials instantiated with physical + inputs (#405). + +- Fix how DiskSCFPotential instances with a hole in the surface + density get passed to C (was wrong when type == 'exp', but 'Rhole' + was in the list of parameters, hole was not passed; meant that + McMillan17 was wrong in C in v1.5). + +- Add time dependence to all relevant Potential functions and method + (#404). + +- Raise warning when r < minr (where dynamical friction gets turned + off) in an orbit integration that includes dynamical friction (to + avoid silent turning off of the dynamical friction force; #356). + +- Improve performance of orbit animations (#414). + +- Fixed compilation issue for Intel compilers: no need to include + 'lgomp' in the linking step (#416). + +- Compile all main galpy C extensions into a single shared-object + library libgalpy. + +- Automatically build Linux, Mac, and Windows wheels with GitHub + Actions and upload them to PyPI upon release creation (#421). + v1.5 (2019-09-12) ================= diff -Nru galpy-1.5/MANIFEST.in galpy-1.6.0.post0/MANIFEST.in --- galpy-1.5/MANIFEST.in 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/MANIFEST.in 2020-04-24 19:48:38.000000000 +0000 @@ -1,4 +1,4 @@ -include README.rst README.dev README.nemo LICENSE HISTORY.txt AUTHORS.txt +include README.md README.dev README.nemo LICENSE HISTORY.txt AUTHORS.txt include gsl-config.bat include galpy/df/data/*.sav include galpy/orbit/named_objects.json diff -Nru galpy-1.5/PKG-INFO galpy-1.6.0.post0/PKG-INFO --- galpy-1.5/PKG-INFO 2019-09-12 20:35:42.000000000 +0000 +++ galpy-1.6.0.post0/PKG-INFO 2020-04-24 19:48:48.421674000 +0000 @@ -1,118 +1,108 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: galpy -Version: 1.5 +Version: 1.6.0.post0 Summary: Galactic Dynamics in python Home-page: http://github.com/jobovy/galpy Author: Jo Bovy Author-email: bovy@astro.utoronto.ca License: New BSD -Description: galpy - ====== - - **Galactic Dynamics in python** - - - - - - - - - - +Description:

+ Galactic Dynamics in python +

+ [galpy](http://www.galpy.org) is a Python 2 and 3 package for galactic dynamics. It supports orbit integration in a variety of potentials, evaluating and sampling various distribution functions, and the calculation of action-angle coordinates for all static potentials. `galpy` is an [astropy](http://www.astropy.org/) [affiliated package](http://www.astropy.org/affiliated/) and provides full support for astropy’s [Quantity](http://docs.astropy.org/en/stable/api/astropy.units.Quantity.html) framework for variables with units. AUTHOR - ------- + ====== Jo Bovy - bovy at astro dot utoronto dot ca - See `AUTHORS.txt - `__ for a - full list of contributors. - - If you find this code useful in your research, please let me - know. **If you use galpy in a publication, please cite** `Bovy (2015) - `__ **and link to - http://github.com/jobovy/galpy**. See `the acknowledgement documentation section - `__ - for a more detailed guide to citing parts of the code. Please also - send me a reference to the paper or send a pull request including your - paper in the list of galpy papers on `this page - `__ (this page is at + See + [AUTHORS.txt](https://github.com/jobovy/galpy/blob/master/AUTHORS.txt) + for a full list of contributors. + + If you find this code useful in your research, please let me know. **If + you use galpy in a publication, please cite** [Bovy + (2015)](http://adsabs.harvard.edu/abs/2015ApJS..216...29B) **and link to + http://github.com/jobovy/galpy**. See [the acknowledgement documentation + section](http://docs.galpy.org/en/latest/index.html#acknowledging-galpy) + for a more detailed guide to citing parts of the code. Please also send + me a reference to the paper or send a pull request including your paper + in the list of galpy papers on [this + page](http://docs.galpy.org/en/latest/) (this page is at doc/source/index.rst). Thanks! - LOOKING FOR HELP? - ----------------- - - The latest documentation can be found `here `__. You can also join the `galpy slack community `__ for any questions related to `galpy`; join `here `__. + ================= - If you find *any* bug in the code, please report these using the `Issue Tracker `__ or by joining the `galpy slack community `__. - - If you are having issues with the installation of ``galpy``, please first consult the `Installation FAQ `__. + The latest documentation can be found + [here](http://docs.galpy.org/en/latest/). You can also join the + [galpy slack community](https://galpy.slack.com/) for any questions + related to `galpy`; join + [here](https://slackin-galpy.herokuapp.com). + + If you find *any* bug in the code, please report these using the [Issue + Tracker](http://github.com/jobovy/galpy/issues) or by joining the [galpy + slack community](https://galpy.slack.com/). + + If you are having issues with the installation of `galpy`, please first + consult the [Installation + FAQ](http://docs.galpy.org/en/latest/installation.html#installation-faq). PYTHON VERSIONS AND DEPENDENCIES - --------------------------------- + ================================ - ``galpy`` supports both Python 2 and 3. Specifically, galpy supports - Python 2.7 and Python 3.6 and 3.7. It should also work on earlier - Python 3.* versions, but this is not extensively tested on an ongoing - basis. Travis CI builds regularly check support for Python 2.7 and 3.7 - (and of 3.6 using a more limited, core set of tests) and Appveyor - builds regularly check support for Python 3.7 on Windows. - - This package requires `Numpy `__, `Scipy - `__, and `Matplotlib - `__. Certain advanced features - require the GNU Scientific Library (`GSL - `__), with action calculations - requiring version 1.14 or higher. Use of ``SnapshotRZPotential`` and - ``InterpSnapshotRZPotential`` requires `pynbody - `__. Support for providing inputs - and getting outputs as Quantities with units is provided through - `astropy `__. + `galpy` supports both Python 2 and 3. Specifically, galpy supports + Python 2.7 and Python 3.6 and 3.7. It should also work on earlier Python + 3.\* versions, but this is not extensively tested on an ongoing basis. + Travis CI builds regularly check support for Python 2.7 and 3.7 (and of + 3.6 using a more limited, core set of tests) and Appveyor builds + regularly check support for Python 3.7 on Windows. + + This package requires [Numpy](https://numpy.org/), + [Scipy](http://www.scipy.org/), and + [Matplotlib](http://matplotlib.sourceforge.net/). Certain advanced + features require the GNU Scientific Library + ([GSL](http://www.gnu.org/software/gsl/)), with action calculations + requiring version 1.14 or higher. Use of `SnapshotRZPotential` and + `InterpSnapshotRZPotential` requires + [pynbody](https://github.com/pynbody/pynbody). Support for providing + inputs and getting outputs as Quantities with units is provided through + [astropy](http://www.astropy.org/). CONTRIBUTING TO GALPY - ---------------------- - - If you are interested in contributing to galpy's development, take a look at `this brief guide `__ on the wiki. This will hopefully help you get started! + ===================== - Some further development notes can be found on the `wiki - `__. This includes a list of - small and larger extensions of galpy that would be useful `here - `__ as - well as a longer-term roadmap `here - `__. Please let the main + If you are interested in contributing to galpy\'s development, take a + look at [this brief + guide](https://github.com/jobovy/galpy/wiki/Guide-for-new-contributors) + on the wiki. This will hopefully help you get started! + + Some further development notes can be found on the + [wiki](http://github.com/jobovy/galpy/wiki/). This includes a list of + small and larger extensions of galpy that would be useful + [here](http://github.com/jobovy/galpy/wiki/Possible-galpy-extensions) as + well as a longer-term roadmap + [here](http://github.com/jobovy/galpy/wiki/Roadmap). Please let the main developer know if you need any help contributing! - - - - - - - - - - - - DISK DF CORRECTIONS - -------------------- + =================== The dehnendf and shudf disk distribution functions can be corrected to follow the desired surface-mass density and radial-velocity-dispersion - profiles more closely (see `1999AJ....118.1201D - `__). Calculating - these corrections is expensive, and a large set of precalculated - corrections can be found `here - `__ - \[tar.gz archive\]. Install these by downloading them and unpacking them into the galpy/df/data directory before running the setup.py installation. E.g.:: + profiles more closely (see + [1999AJ\....118.1201D](http://adsabs.harvard.edu/abs/1999AJ....118.1201D)). + Calculating these corrections is expensive, and a large set of + precalculated corrections can be found + [here](http://github.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz) + \[tar.gz archive\]. Install these by downloading them and unpacking them + into the galpy/df/data directory before running the setup.py + installation. E.g.: - curl -O https://github.s3.amazonaws.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz - tar xvzf galpy-dfcorrections.tar.gz -C ./galpy/df/data/ + curl -O https://github.s3.amazonaws.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz + tar xvzf galpy-dfcorrections.tar.gz -C ./galpy/df/data/ Platform: UNKNOWN Classifier: Development Status :: 6 - Mature @@ -128,3 +118,4 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Scientific/Engineering :: Astronomy Classifier: Topic :: Scientific/Engineering :: Physics +Description-Content-Type: text/markdown diff -Nru galpy-1.5/README.md galpy-1.6.0.post0/README.md --- galpy-1.5/README.md 1970-01-01 00:00:00.000000000 +0000 +++ galpy-1.6.0.post0/README.md 2020-04-24 19:48:38.000000000 +0000 @@ -0,0 +1,99 @@ +

+
+ Galactic Dynamics in python +

+ +[galpy](http://www.galpy.org) is a Python 2 and 3 package for galactic dynamics. It supports orbit integration in a variety of potentials, evaluating and sampling various distribution functions, and the calculation of action-angle coordinates for all static potentials. `galpy` is an [astropy](http://www.astropy.org/) [affiliated package](http://www.astropy.org/affiliated/) and provides full support for astropy’s [Quantity](http://docs.astropy.org/en/stable/api/astropy.units.Quantity.html) framework for variables with units. + +[![image](https://travis-ci.org/jobovy/galpy.svg?branch=master)](http://travis-ci.org/jobovy/galpy) [![image](https://ci.appveyor.com/api/projects/status/wmgs1sq3i7tbtap2/branch/master?svg=true)](https://ci.appveyor.com/project/jobovy/galpy) [![image](https://img.shields.io/coveralls/jobovy/galpy.svg)](https://coveralls.io/r/jobovy/galpy?branch=master) [![image](http://codecov.io/github/jobovy/galpy/coverage.svg?branch=master)](http://codecov.io/github/jobovy/galpy?branch=master) [![image](https://readthedocs.org/projects/galpy/badge/?version=latest)](http://docs.galpy.org/en/latest/) [![image](http://img.shields.io/pypi/v/galpy.svg)](https://pypi.python.org/pypi/galpy/) [![image](https://anaconda.org/conda-forge/galpy/badges/installer/conda.svg)](https://anaconda.org/conda-forge/galpy) [![image](http://img.shields.io/badge/license-New%20BSD-brightgreen.svg)](https://github.com/jobovy/galpy/blob/master/LICENSE) [![image](http://img.shields.io/badge/DOI-10.1088/0067%2D%2D0049/216/2/29-blue.svg)](http://dx.doi.org/10.1088/0067-0049/216/2/29) [![image](http://img.shields.io/badge/powered%20by-AstroPy-orange.svg?style=flat)](http://www.astropy.org/) [![image](https://slackin-galpy.herokuapp.com/badge.svg)](https://galpy.slack.com/) [![image](https://img.shields.io/badge/join-slack-E01563.svg?style=flat&logo=slack&logoWidth=10)](https://slackin-galpy.herokuapp.com) + +AUTHOR +====== + +Jo Bovy - bovy at astro dot utoronto dot ca + +See +[AUTHORS.txt](https://github.com/jobovy/galpy/blob/master/AUTHORS.txt) +for a full list of contributors. + +If you find this code useful in your research, please let me know. **If +you use galpy in a publication, please cite** [Bovy +(2015)](http://adsabs.harvard.edu/abs/2015ApJS..216...29B) **and link to +http://github.com/jobovy/galpy**. See [the acknowledgement documentation +section](http://docs.galpy.org/en/latest/index.html#acknowledging-galpy) +for a more detailed guide to citing parts of the code. Please also send +me a reference to the paper or send a pull request including your paper +in the list of galpy papers on [this +page](http://docs.galpy.org/en/latest/) (this page is at +doc/source/index.rst). Thanks! + +LOOKING FOR HELP? +================= + +The latest documentation can be found +[here](http://docs.galpy.org/en/latest/). You can also join the +[galpy slack community](https://galpy.slack.com/) for any questions +related to `galpy`; join +[here](https://slackin-galpy.herokuapp.com). + +If you find *any* bug in the code, please report these using the [Issue +Tracker](http://github.com/jobovy/galpy/issues) or by joining the [galpy +slack community](https://galpy.slack.com/). + +If you are having issues with the installation of `galpy`, please first +consult the [Installation +FAQ](http://docs.galpy.org/en/latest/installation.html#installation-faq). + +PYTHON VERSIONS AND DEPENDENCIES +================================ + +`galpy` supports both Python 2 and 3. Specifically, galpy supports +Python 2.7 and Python 3.6 and 3.7. It should also work on earlier Python +3.\* versions, but this is not extensively tested on an ongoing basis. +Travis CI builds regularly check support for Python 2.7 and 3.7 (and of +3.6 using a more limited, core set of tests) and Appveyor builds +regularly check support for Python 3.7 on Windows. + +This package requires [Numpy](https://numpy.org/), +[Scipy](http://www.scipy.org/), and +[Matplotlib](http://matplotlib.sourceforge.net/). Certain advanced +features require the GNU Scientific Library +([GSL](http://www.gnu.org/software/gsl/)), with action calculations +requiring version 1.14 or higher. Use of `SnapshotRZPotential` and +`InterpSnapshotRZPotential` requires +[pynbody](https://github.com/pynbody/pynbody). Support for providing +inputs and getting outputs as Quantities with units is provided through +[astropy](http://www.astropy.org/). + +CONTRIBUTING TO GALPY +===================== + +If you are interested in contributing to galpy\'s development, take a +look at [this brief +guide](https://github.com/jobovy/galpy/wiki/Guide-for-new-contributors) +on the wiki. This will hopefully help you get started! + +Some further development notes can be found on the +[wiki](http://github.com/jobovy/galpy/wiki/). This includes a list of +small and larger extensions of galpy that would be useful +[here](http://github.com/jobovy/galpy/wiki/Possible-galpy-extensions) as +well as a longer-term roadmap +[here](http://github.com/jobovy/galpy/wiki/Roadmap). Please let the main +developer know if you need any help contributing! + +DISK DF CORRECTIONS +=================== + +The dehnendf and shudf disk distribution functions can be corrected to +follow the desired surface-mass density and radial-velocity-dispersion +profiles more closely (see +[1999AJ\....118.1201D](http://adsabs.harvard.edu/abs/1999AJ....118.1201D)). +Calculating these corrections is expensive, and a large set of +precalculated corrections can be found +[here](http://github.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz) +\[tar.gz archive\]. Install these by downloading them and unpacking them +into the galpy/df/data directory before running the setup.py +installation. E.g.: + + curl -O https://github.s3.amazonaws.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz + tar xvzf galpy-dfcorrections.tar.gz -C ./galpy/df/data/ diff -Nru galpy-1.5/README.rst galpy-1.6.0.post0/README.rst --- galpy-1.5/README.rst 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/README.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -galpy -====== - -**Galactic Dynamics in python** - -.. image:: https://travis-ci.org/jobovy/galpy.svg?branch=master - :target: http://travis-ci.org/jobovy/galpy - -.. image:: https://ci.appveyor.com/api/projects/status/wmgs1sq3i7tbtap2/branch/master?svg=true - :target: https://ci.appveyor.com/project/jobovy/galpy - -.. image:: https://img.shields.io/coveralls/jobovy/galpy.svg - :target: https://coveralls.io/r/jobovy/galpy?branch=master - -.. image:: http://codecov.io/github/jobovy/galpy/coverage.svg?branch=master - :target: http://codecov.io/github/jobovy/galpy?branch=master - -.. image:: https://readthedocs.org/projects/galpy/badge/?version=latest - :target: http://galpy.readthedocs.io/en/latest/ - -.. image:: http://img.shields.io/pypi/v/galpy.svg - :target: https://pypi.python.org/pypi/galpy/ - -.. image:: https://anaconda.org/conda-forge/galpy/badges/installer/conda.svg - :target: https://anaconda.org/conda-forge/galpy - -.. image:: http://img.shields.io/badge/license-New%20BSD-brightgreen.svg - :target: https://github.com/jobovy/galpy/blob/master/LICENSE - -.. image:: http://img.shields.io/badge/DOI-10.1088/0067%2D%2D0049/216/2/29-blue.svg - :target: http://dx.doi.org/10.1088/0067-0049/216/2/29 - -.. image:: http://img.shields.io/badge/powered%20by-AstroPy-orange.svg?style=flat - :target: http://www.astropy.org/ - -.. image:: https://slackin-galpy.herokuapp.com/badge.svg - :target: https://galpy.slack.com/ - -.. image:: https://img.shields.io/badge/join-slack-E01563.svg?style=flat&logo=slack&logoWidth=10 - :target: https://slackin-galpy.herokuapp.com - -AUTHOR -------- - -Jo Bovy - bovy at astro dot utoronto dot ca - -See `AUTHORS.txt -`__ for a -full list of contributors. - -If you find this code useful in your research, please let me -know. **If you use galpy in a publication, please cite** `Bovy (2015) -`__ **and link to -http://github.com/jobovy/galpy**. See `the acknowledgement documentation section -`__ -for a more detailed guide to citing parts of the code. Please also -send me a reference to the paper or send a pull request including your -paper in the list of galpy papers on `this page -`__ (this page is at -doc/source/index.rst). Thanks! - - -LOOKING FOR HELP? ------------------ - -The latest documentation can be found `here `__. You can also join the `galpy slack community `__ for any questions related to `galpy`; join `here `__. - -If you find *any* bug in the code, please report these using the `Issue Tracker `__ or by joining the `galpy slack community `__. - -If you are having issues with the installation of ``galpy``, please first consult the `Installation FAQ `__. - -PYTHON VERSIONS AND DEPENDENCIES ---------------------------------- - -``galpy`` supports both Python 2 and 3. Specifically, galpy supports -Python 2.7 and Python 3.6 and 3.7. It should also work on earlier -Python 3.* versions, but this is not extensively tested on an ongoing -basis. Travis CI builds regularly check support for Python 2.7 and 3.7 -(and of 3.6 using a more limited, core set of tests) and Appveyor -builds regularly check support for Python 3.7 on Windows. - -This package requires `Numpy `__, `Scipy -`__, and `Matplotlib -`__. Certain advanced features -require the GNU Scientific Library (`GSL -`__), with action calculations -requiring version 1.14 or higher. Use of ``SnapshotRZPotential`` and -``InterpSnapshotRZPotential`` requires `pynbody -`__. Support for providing inputs -and getting outputs as Quantities with units is provided through -`astropy `__. - -CONTRIBUTING TO GALPY ----------------------- - -If you are interested in contributing to galpy's development, take a look at `this brief guide `__ on the wiki. This will hopefully help you get started! - -Some further development notes can be found on the `wiki -`__. This includes a list of -small and larger extensions of galpy that would be useful `here -`__ as -well as a longer-term roadmap `here -`__. Please let the main -developer know if you need any help contributing! - -DETAILED BUILD, COVERAGE, AND DOCUMENTATION STATUS ---------------------------------------------------- - -**master**: - -.. image:: https://travis-ci.org/jobovy/galpy.svg?branch=master - :target: http://travis-ci.org/jobovy/galpy - -.. image:: https://img.shields.io/coveralls/jobovy/galpy.svg - :target: https://coveralls.io/r/jobovy/galpy?branch=master - -.. image:: http://codecov.io/github/jobovy/galpy/coverage.svg?branch=master - :target: http://codecov.io/github/jobovy/galpy?branch=master - -.. image:: https://readthedocs.org/projects/galpy/badge/?branch=master?version=latest - :target: http://galpy.readthedocs.io/en/master/ - - -**development branch** (if it exists): - -.. image:: https://travis-ci.org/jobovy/galpy.svg?branch=dev - :target: http://travis-ci.org/jobovy/galpy/branches - -.. image:: https://img.shields.io/coveralls/jobovy/galpy.svg?branch=dev - :target: https://coveralls.io/r/jobovy/galpy?branch=dev - -.. image:: http://codecov.io/github/jobovy/galpy/coverage.svg?branch=dev - :target: http://codecov.io/github/jobovy/galpy?branch=dev - -.. image:: https://readthedocs.org/projects/galpy/badge/?branch=master?version=latest - :target: http://galpy.readthedocs.io/en/dev/ - -DISK DF CORRECTIONS --------------------- - -The dehnendf and shudf disk distribution functions can be corrected to -follow the desired surface-mass density and radial-velocity-dispersion -profiles more closely (see `1999AJ....118.1201D -`__). Calculating -these corrections is expensive, and a large set of precalculated -corrections can be found `here -`__ -\[tar.gz archive\]. Install these by downloading them and unpacking them into the galpy/df/data directory before running the setup.py installation. E.g.:: - - curl -O https://github.s3.amazonaws.com/downloads/jobovy/galpy/galpy-dfcorrections.tar.gz - tar xvzf galpy-dfcorrections.tar.gz -C ./galpy/df/data/ diff -Nru galpy-1.5/setup.py galpy-1.6.0.post0/setup.py --- galpy-1.5/setup.py 2019-09-12 20:35:12.000000000 +0000 +++ galpy-1.6.0.post0/setup.py 2020-04-24 19:48:38.000000000 +0000 @@ -16,7 +16,7 @@ long_description= '' previous_line= '' -with open('README.rst') as dfile: +with open('README.md') as dfile: for line in dfile: if not 'image' in line and not 'target' in line \ and not 'DETAILED' in line and not '**master**' in line \ @@ -28,15 +28,33 @@ # Parse options; current options # --no-openmp: compile without OpenMP support # --coverage: compile with gcov support +# --compiler= set the compiler by hand # --single_ext: compile all of the C code into a single extension (just for testing, do not use this) -# --orbit_ext: just compile the orbit extension (for use w/ --coverage) -# --actionAngle_ext: just compile the actionAngle extension (for use w/ --coverage) -# --interppotential_ext: just compile the interppotential extension (for use w/ --coverage) -pot_libraries = ['m','gsl','gslcblas','gomp'] +galpy_c_libraries = ['m','gsl','gslcblas','gomp'] -if WIN32: # windows does not need 'gomp' whether compiled with OpenMP or not - pot_libraries.remove('gomp') +if WIN32: + # On Windows it's unnecessary and erroneous to include m + galpy_c_libraries.remove('m') + # Windows does not need 'gomp' whether compiled with OpenMP or not + galpy_c_libraries.remove('gomp') + +#Option to use Intel compilers +try: + compiler_option_pos = ['--compiler=' in opt for opt in sys.argv]\ + .index(True) +except ValueError: + use_intel_compiler= False +else: + use_intel_compiler= 'intel' in sys.argv[compiler_option_pos].split('=')[1] + +if use_intel_compiler and not WIN32: + import numpy.distutils.intelccompiler +elif use_intel_compiler and WIN32: + import __intelcompiler + +if use_intel_compiler: # OpenMP by default included for Intel, see #416 + galpy_c_libraries.remove('gomp') #Option to forego OpenMP try: @@ -47,7 +65,7 @@ del sys.argv[openmp_pos] extra_compile_args= ["-DNO_OMP"] if not WIN32: # Because windows guarantee do not have 'gomp' in the list - pot_libraries.remove('gomp') + galpy_c_libraries.remove('gomp') #Option to track coverage try: @@ -56,7 +74,7 @@ extra_link_args= [] else: del sys.argv[coverage_pos] - extra_compile_args.extend(["-O0","--coverage"]) + extra_compile_args.extend(["-O0","--coverage","-D USING_COVERAGE"]) extra_link_args= ["--coverage"] #Option to compile everything into a single extension @@ -68,57 +86,17 @@ del sys.argv[single_ext_pos] single_ext= True -#Option to just compile the orbit extension -try: - orbit_ext_pos = sys.argv.index('--orbit_ext') -except ValueError: - orbit_ext= False -else: - del sys.argv[orbit_ext_pos] - orbit_ext= True - -#Option to just compile the actionAngle extension -try: - actionAngle_ext_pos = sys.argv.index('--actionAngle_ext') -except ValueError: - actionAngle_ext= False -else: - del sys.argv[actionAngle_ext_pos] - actionAngle_ext= True - -#Option to just compile the interppotential extension -try: - interppotential_ext_pos = sys.argv.index('--interppotential_ext') -except ValueError: - interppotential_ext= False -else: - del sys.argv[interppotential_ext_pos] - interppotential_ext= True - -#Option to use Intel compilers -try: - compiler_option_pos = ['--compiler=' in opt for opt in sys.argv]\ - .index(True) -except ValueError: - use_intel_compiler= False -else: - use_intel_compiler= 'intel' in sys.argv[compiler_option_pos].split('=')[1] - -if use_intel_compiler and not WIN32: - import numpy.distutils.intelccompiler -elif use_intel_compiler and WIN32: - import __intelcompiler - #code to check the GSL version; list cmd w/ shell=True only works on Windows # (https://docs.python.org/3/library/subprocess.html#converting-argument-sequence) -cmd= ['gsl-config', - '--version'] +cmd= ['gsl-config','--version'] try: if sys.version_info < (2,7): #subprocess.check_output does not exist gsl_version= subprocess.Popen(cmd,shell=sys.platform.startswith('win'), stdout=subprocess.PIPE).communicate()[0] else: - gsl_version= subprocess.check_output(cmd,shell=sys.platform.startswith('win')) + gsl_version= \ + subprocess.check_output(cmd, + shell=sys.platform.startswith('win')) except (OSError,subprocess.CalledProcessError): gsl_version= ['0','0'] else: @@ -146,27 +124,21 @@ extra_compile_args.append("-DGSL_DLL") extra_compile_args.append("-DWIN32") -#Orbit integration C extension -orbit_int_c_src= ['galpy/util/bovy_symplecticode.c', 'galpy/util/bovy_rk.c', 'galpy/util/leung_dop853.c','galpy/util/bovy_coords.c'] -orbit_int_c_src.extend(glob.glob('galpy/potential/potential_c_ext/*.c')) -orbit_int_c_src.extend(glob.glob('galpy/orbit/orbit_c_ext/*.c')) -orbit_int_c_src.extend(glob.glob('galpy/util/interp_2d/*.c')) - -orbit_libraries=['m'] -if float(gsl_version[0]) >= 1.: - orbit_libraries.extend(['gsl','gslcblas']) -if 'gomp' in pot_libraries: - orbit_libraries.append('gomp') - -# On Windows it's unnecessary and erroneous to include m -if WIN32: - orbit_libraries.remove('m') - pot_libraries.remove('m') - -orbit_include_dirs= ['galpy/util', - 'galpy/util/interp_2d', - 'galpy/orbit/orbit_c_ext', - 'galpy/potential/potential_c_ext'] +#main C extension +galpy_c_src= ['galpy/util/bovy_symplecticode.c', 'galpy/util/bovy_rk.c', + 'galpy/util/leung_dop853.c','galpy/util/bovy_coords.c'] +galpy_c_src.extend(glob.glob('galpy/potential/potential_c_ext/*.c')) +galpy_c_src.extend(glob.glob('galpy/potential/interppotential_c_ext/*.c')) +galpy_c_src.extend(glob.glob('galpy/util/interp_2d/*.c')) +galpy_c_src.extend(glob.glob('galpy/orbit/orbit_c_ext/*.c')) +galpy_c_src.extend(glob.glob('galpy/actionAngle/actionAngle_c_ext/*.c')) + +galpy_c_include_dirs= ['galpy/util', + 'galpy/util/interp_2d', + 'galpy/potential/potential_c_ext', + 'galpy/potential/interppotential_c_ext', + 'galpy/orbit/orbit_c_ext', + 'galpy/actionAngle/actionAngle_c_ext'] #actionAngleTorus C extension (files here, so we can compile a single extension if so desidered) actionAngleTorus_c_src= \ @@ -196,132 +168,55 @@ 'galpy/orbit/orbit_c_ext', 'galpy/potential/potential_c_ext'] -if single_ext: #add the code and libraries for the other extensions - #src - orbit_int_c_src.extend(glob.glob('galpy/actionAngle/actionAngle_c_ext/*.c')) - orbit_int_c_src.extend(glob.glob('galpy/potential/interppotential_c_ext/*.c')) +if single_ext: #add the code and libraries for the actionAngleTorus extensions if os.path.exists('galpy/actionAngle/actionAngleTorus_c_ext/torus/src'): - # Add Torus code - orbit_int_c_src.extend(actionAngleTorus_c_src) - orbit_int_c_src= list(set(orbit_int_c_src)) - #libraries - for lib in pot_libraries: - if not lib in orbit_libraries: - orbit_libraries.append(lib) - #includes - orbit_include_dirs.extend(['galpy/actionAngle/actionAngle_c_ext', - 'galpy/util/interp_2d', - 'galpy/orbit/orbit_c_ext', - 'galpy/potential/potential_c_ext']) - orbit_include_dirs.extend(['galpy/potential/potential_c_ext', - 'galpy/util/interp_2d', - 'galpy/util/', - 'galpy/actionAngle/actionAngle_c_ext', - 'galpy/orbit/orbit_c_ext', - 'galpy/potential/interppotential_c_ext']) - # Add Torus code - orbit_include_dirs.extend(actionAngleTorus_include_dirs) - orbit_include_dirs= list(set(orbit_include_dirs)) + galpy_c_src.extend(actionAngleTorus_c_src) + galpy_c_src= list(set(galpy_c_src)) + galpy_c_include_dirs.extend(actionAngleTorus_include_dirs) + galpy_c_include_dirs= list(set(galpy_c_include_dirs)) -orbit_int_c= Extension('galpy_integrate_c', - sources=orbit_int_c_src, - libraries=orbit_libraries, - include_dirs=orbit_include_dirs, - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args) -ext_modules=[] -if float(gsl_version[0]) >= 1. and \ - not actionAngle_ext and not interppotential_ext: - orbit_int_c_incl= True - ext_modules.append(orbit_int_c) -else: - orbit_int_c_incl= False - -#actionAngle C extension -actionAngle_c_src= glob.glob('galpy/actionAngle/actionAngle_c_ext/*.c') -actionAngle_c_src.extend(glob.glob('galpy/potential/potential_c_ext/*.c')) -actionAngle_c_src.extend(glob.glob('galpy/util/interp_2d/*.c')) -actionAngle_c_src.extend(['galpy/util/bovy_symplecticode.c', 'galpy/util/bovy_rk.c', 'galpy/util/leung_dop853.c','galpy/util/bovy_coords.c']) -actionAngle_c_src.append('galpy/orbit/orbit_c_ext/integrateFullOrbit.c') -actionAngle_include_dirs= ['galpy/actionAngle/actionAngle_c_ext', - 'galpy/orbit/orbit_c_ext', - 'galpy/util/', - 'galpy/util/interp_2d', - 'galpy/potential/potential_c_ext'] - #Installation of this extension using the GSL may (silently) fail, if the GSL #is built for the wrong architecture, on Mac you can install the GSL correctly #using #brew install gsl --universal -actionAngle_c= Extension('galpy_actionAngle_c', - sources=actionAngle_c_src, - libraries=pot_libraries, - include_dirs=actionAngle_include_dirs, - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args) -if float(gsl_version[0]) >= 1. \ - and (float(gsl_version[0]) >= 2. or float(gsl_version[1]) >= 14.) and \ - not orbit_ext and not interppotential_ext and not single_ext: - actionAngle_c_incl= True - ext_modules.append(actionAngle_c) -else: - actionAngle_c_incl= False - -#interppotential C extension -interppotential_c_src= glob.glob('galpy/potential/potential_c_ext/*.c') -interppotential_c_src.extend(glob.glob('galpy/potential/interppotential_c_ext/*.c')) -interppotential_c_src.extend(['galpy/util/bovy_symplecticode.c', 'galpy/util/bovy_rk.c', 'galpy/util/leung_dop853.c','galpy/util/bovy_coords.c']) -interppotential_c_src.append('galpy/orbit/orbit_c_ext/integrateFullOrbit.c') -interppotential_c_src.extend(glob.glob('galpy/util/interp_2d/*.c')) - -interppotential_include_dirs= ['galpy/potential/potential_c_ext', - 'galpy/util/interp_2d', - 'galpy/util/', - 'galpy/actionAngle/actionAngle_c_ext', - 'galpy/orbit/orbit_c_ext', - 'galpy/potential/interppotential_c_ext'] - -interppotential_c= Extension('galpy_interppotential_c', - sources=interppotential_c_src, - libraries=pot_libraries, - include_dirs=interppotential_include_dirs, - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args) +galpy_c= Extension('libgalpy', + sources=galpy_c_src, + libraries=galpy_c_libraries, + include_dirs=galpy_c_include_dirs, + extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args) +ext_modules=[] if float(gsl_version[0]) >= 1. \ - and (float(gsl_version[0]) >= 2. or float(gsl_version[1]) >= 14.) \ - and not orbit_ext and not actionAngle_ext and not single_ext: - interppotential_c_incl= True - ext_modules.append(interppotential_c) + and (float(gsl_version[0]) >= 2. or float(gsl_version[1]) >= 14.): + galpy_c_incl= True + ext_modules.append(galpy_c) else: - interppotential_c_incl= False + galpy_c_incl= False # Add the actionAngleTorus extension (src and include specified above) -#Installation of this extension using the GSL may (silently) fail, if the GSL -#is built for the wrong architecture, on Mac you can install the GSL correctly -#using -#brew install gsl --universal -actionAngleTorus_c= Extension('galpy_actionAngleTorus_c', +actionAngleTorus_c= Extension('libgalpy_actionAngleTorus', sources=actionAngleTorus_c_src, - libraries=pot_libraries, + libraries=galpy_c_libraries, include_dirs=actionAngleTorus_include_dirs, extra_compile_args=extra_compile_args, extra_link_args=extra_link_args) if float(gsl_version[0]) >= 1. \ and (float(gsl_version[0]) >= 2. or float(gsl_version[1]) >= 14.) and \ - os.path.exists('galpy/actionAngle/actionAngleTorus_c_ext/torus/src') and \ - not orbit_ext and not interppotential_ext and not single_ext: + os.path.exists('galpy/actionAngle/actionAngleTorus_c_ext/torus/src') \ + and not single_ext: actionAngleTorus_c_incl= True ext_modules.append(actionAngleTorus_c) else: actionAngleTorus_c_incl= False setup(name='galpy', - version='1.5', + version='1.6.0.post0', description='Galactic Dynamics in python', author='Jo Bovy', author_email='bovy@astro.utoronto.ca', license='New BSD', long_description=long_description, + long_description_content_type='text/markdown', url='http://github.com/jobovy/galpy', package_dir = {'galpy/': ''}, packages=['galpy','galpy/orbit','galpy/potential', @@ -329,10 +224,10 @@ 'galpy/actionAngle'], package_data={'galpy/orbit':['named_objects.json'], 'galpy/df':['data/*.sav'], - "": ["README.rst","README.dev","LICENSE","AUTHORS.rst"]}, + "": ["README.md","README.dev","LICENSE","AUTHORS.rst"]}, include_package_data=True, install_requires=['numpy>=1.7','scipy','matplotlib','pytest','six', - 'future'], + 'future','setuptools'], ext_modules=ext_modules if not no_compiler else None, classifiers=[ "Development Status :: 6 - Mature", @@ -358,19 +253,13 @@ print('If you believe that %s should have worked, make sure\n(1) that the GSL include/ directory can be found by the compiler (you might have to edit CFLAGS for this: export CFLAGS="$CFLAGS -I/path/to/gsl/include/", or equivalent for C-type shells; replace /path/to/gsl/include/ with the actual path to the include directory),\n(2) that the GSL library can be found by the linker (you might have to edit LDFLAGS for this: export LDFLAGS="$LDFLAGS -L/path/to/gsl/lib/", or equivalent for C-type shells; replace /path/to/gsl/lib/ with the actual path to the lib directory),\n(3) and that `gsl-config --version` returns the correct version' % this_str) num_gsl_warn= 0 -if not orbit_int_c_incl: +if not galpy_c_incl: num_gsl_warn+= 1 - print('\033[91;1m'+'WARNING: orbit-integration C library not installed because your GSL version < 1'+'\033[0m') + print('\033[91;1m'+'WARNING: galpy C library not installed because your GSL version < 1.14'+'\033[0m') -if not actionAngle_c_incl and not single_ext: - num_gsl_warn+= 1 - print('\033[91;1m'+'WARNING: action-angle C library not installed because your GSL version < 1.14'+'\033[0m') -if not interppotential_c_incl and not single_ext: - num_gsl_warn+= 1 - print('\033[91;1m'+'WARNING: Potential-interpolation C library not installed because your GSL version < 1.14'+'\033[0m') if not actionAngleTorus_c_incl and not single_ext: num_gsl_warn+= 1 - print('\033[91;1m'+'WARNING: action-angle-torus C library not installed because your GSL version < 1.14 or because you did not first download the torus code as explained in the installation guide in the html documentation'+'\033[0m') + print('\033[91;1m'+'WARNING: galpy action-angle-torus C library not installed because your GSL version < 1.14 or because you did not first download the torus code as explained in the installation guide in the html documentation'+'\033[0m') if num_gsl_warn > 0: print_gsl_message(num_messages=num_gsl_warn) @@ -378,19 +267,13 @@ print('\033[1m'+'Finished installing galpy'+'\033[0m') print('You can run the test suite using `pytest -v tests/` to check the installation (but note that the test suite currently takes about 50 minutes to run)') -#if single_ext, symlink the other (non-compiled) extensions to galpy_integrate_c.so (use EXT_SUFFIX for python3 compatibility) +#if single_ext, symlink the other (non-compiled) extensions to libgalpy.so (use EXT_SUFFIX for python3 compatibility) if PY3: _ext_suffix= sysconfig.get_config_var('EXT_SUFFIX') else: _ext_suffix= '.so' if single_ext: - if not os.path.exists('galpy_actionAngle_c%s' % _ext_suffix): - os.symlink('galpy_integrate_c%s' % _ext_suffix, - 'galpy_actionAngle_c%s' % _ext_suffix) - if not os.path.exists('galpy_interppotential_c%s' % _ext_suffix): - os.symlink('galpy_integrate_c%s' % _ext_suffix, - 'galpy_interppotential_c%s' % _ext_suffix) - if not os.path.exists('galpy_actionAngleTorus_c%s' % _ext_suffix) \ + if not os.path.exists('libgalpy_actionAngleTorus%s' % _ext_suffix) \ and os.path.exists('galpy/actionAngle/actionAngleTorus_c_ext/torus/src'): - os.symlink('galpy_integrate_c%s' % _ext_suffix, - 'galpy_actionAngleTorus_c%s' % _ext_suffix) + os.symlink('libgalpy%s' % _ext_suffix, + 'libgalpy_actionAngleTorus%s' % _ext_suffix)