def test_estimate_hsz(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) assert numpy.fabs((qdf.estimate_hsz(0.9,z=0.)-1.0)/1.0) < 0.25, 'estimated vertical-dispersion scale length deviates more from input scale length than expected' #Another one qdf= quasiisothermaldf(1./2.,0.2,0.1,1.,2., pot=MWPotential,aA=aAS,cutcounter=True) assert numpy.fabs((qdf.estimate_hsz(0.9,z=0.05)-2.0)/2.0) < 0.25, 'estimated vertical-dispersion scale length deviates more from input scale length than expected' return None
def test_estimate_hr(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) assert numpy.fabs((qdf.estimate_hr(0.9,z=0.)-0.25)/0.25) < 0.1, 'estimated scale length deviates more from input scale length than expected' #Another one qdf= quasiisothermaldf(1./2.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) assert numpy.fabs((qdf.estimate_hr(0.9,z=None)-0.5)/0.5) < 0.15, 'estimated scale length deviates more from input scale length than expected' #Another one qdf= quasiisothermaldf(1.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) assert numpy.fabs((qdf.estimate_hr(0.9,z=None,fixed_quad=False)-1.0)/1.0) < 0.3, 'estimated scale length deviates more from input scale length than expected' return None
def test_call_diffinoutputs(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #when specifying rg etc., first get these from a previous output val, trg, tkappa, tnu, tOmega= qdf((0.03,0.9,0.02),_return_freqs=True) #First check that just supplying these again works assert numpy.fabs(val-qdf((0.03,0.9,0.02),rg=trg,kappa=tkappa,nu=tnu, Omega=tOmega)) < 10.**-8., 'qdf calls w/ rg, and frequencies specified and w/ not specified do not agrees' #Also calculate the frequencies assert numpy.fabs(val-qdf((0.03,0.9,0.02),rg=trg, kappa=epifreq(MWPotential,trg), nu=verticalfreq(MWPotential,trg), Omega=omegac(MWPotential,trg))) < 10.**-8., 'qdf calls w/ rg, and frequencies specified and w/ not specified do not agrees' #Also test _return_actions val, jr,lz,jz= qdf(0.9,0.1,0.95,0.1,0.08,_return_actions=True) assert numpy.fabs(val-qdf((jr,lz,jz))) < 10.**-8., 'qdf call w/ R,vR,... and actions specified do not agree' acs= aAS(0.9,0.1,0.95,0.1,0.08) assert numpy.fabs(acs[0]-jr) < 10.**-8., 'direct calculation of jr and that returned from qdf.__call__ does not agree' assert numpy.fabs(acs[1]-lz) < 10.**-8., 'direct calculation of lz and that returned from qdf.__call__ does not agree' assert numpy.fabs(acs[2]-jz) < 10.**-8., 'direct calculation of jz and that returned from qdf.__call__ does not agree' #Test unbound orbits #Find unbound orbit, new qdf s.t. we can get UnboundError (only with taAS= actionAngleStaeckel(pot=MWPotential,c=False,delta=0.5) qdfnc= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential, aA=taAS, cutcounter=True) from galpy.actionAngle import UnboundError try: acs= taAS(0.9,10.,-20.,0.1,10.) except UnboundError: pass else: print(acs) raise AssertionError('Test orbit in qdf that is supposed to be unbound is not') assert qdfnc(0.9,10.,-20.,0.1,10.) < 10.**-10., 'unbound orbit does not return qdf equal to zero' #Test negative lz assert qdf((0.03,-0.1,0.02)) < 10.**-8., 'qdf w/ cutcounter=True and negative lz does not return 0' assert qdf((0.03,-0.1,0.02),log=True) <= numpy.finfo(numpy.dtype(numpy.float64)).min+1., 'qdf w/ cutcounter=True and negative lz does not return 0' #Test func val= qdf((0.03,0.9,0.02)) fval= qdf((0.03,0.9,0.02),func=lambda x,y,z: numpy.sin(x)*numpy.cos(y)\ *numpy.exp(z)) assert numpy.fabs(val*numpy.sin(0.03)*numpy.cos(0.9)*numpy.exp(0.02)- fval) < 10.**-8, 'qdf __call__ w/ func does not work as expected' lfval= qdf((0.03,0.9,0.02),func=lambda x,y,z: numpy.sin(x)*numpy.cos(y)\ *numpy.exp(z),log=True) assert numpy.fabs(numpy.log(val)+numpy.log(numpy.sin(0.03)\ *numpy.cos(0.9)\ *numpy.exp(0.02))- lfval) < 10.**-8, 'qdf __call__ w/ func does not work as expected' return None
def test_pvz_staeckel_arrayin(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) R,z= 0.8, 0.1 pvz= qdf.pvz(0.05,R*numpy.ones(2),z*numpy.ones(2)) assert numpy.all(numpy.log(pvz)-numpy.log(qdf.pvz(0.05,R,z))) < 10.**-10., 'pvz calculated with R and z array input does not equal to calculated with scalar input' return None
def test_qdf(): from galpy.df import quasiisothermaldf from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleStaeckel # Setup actionAngle instance for action calcs aAS= actionAngleStaeckel(pot=MWPotential2014,delta=0.45, c=True) # Quasi-iso df w/ hr=1/3, hsr/z=1, sr(1)=0.2, sz(1)=0.1 df= quasiisothermaldf(1./3.,0.2,0.1,1.,1.,aA=aAS, pot=MWPotential2014) # Evaluate DF w/ R,vR,vT,z,vz df(0.9,0.1,0.8,0.05,0.02) assert numpy.fabs(df(0.9,0.1,0.8,0.05,0.02)-numpy.array([ 123.57158928])) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF w/ Orbit instance, return ln from galpy.orbit import Orbit df(Orbit([0.9,0.1,0.8,0.05,0.02]),log=True) assert numpy.fabs(df(Orbit([0.9,0.1,0.8,0.05,0.02]),log=True)-numpy.array([ 4.81682066])) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF marginalized over vz df.pvRvT(0.1,0.9,0.9,0.05) assert numpy.fabs(df.pvRvT(0.1,0.9,0.9,0.05)-23.273310451852243) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF marginalized over vR,vT df.pvz(0.02,0.9,0.05) assert numpy.fabs(df.pvz(0.02,0.9,0.05)-50.949586235238172) < 10.**-4., 'qdf does not behave as expected' # Calculate the density df.density(0.9,0.05) assert numpy.fabs(df.density(0.9,0.05)-12.73725936526167) < 10.**-4., 'qdf does not behave as expected' # Estimate the DF's actual density scale length at z=0 df.estimate_hr(0.9,0.) assert numpy.fabs(df.estimate_hr(0.9,0.)-0.322420336223) < 10.**-2., 'qdf does not behave as expected' # Estimate the DF's actual surface-density scale length df.estimate_hr(0.9,None) assert numpy.fabs(df.estimate_hr(0.9,None)-0.38059909132766462) < 10.**-4., 'qdf does not behave as expected' # Estimate the DF's density scale height df.estimate_hz(0.9,0.02) assert numpy.fabs(df.estimate_hz(0.9,0.02)-0.064836202345657207) < 10.**-4., 'qdf does not behave as expected' # Calculate the mean velocities df.meanvR(0.9,0.05), df.meanvT(0.9,0.05), df.meanvz(0.9,0.05) assert numpy.fabs(df.meanvR(0.9,0.05)-3.8432265354618213e-18) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(df.meanvT(0.9,0.05)-0.90840425173325279) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(df.meanvz(0.9,0.05)+4.3579787517991084e-19) < 10.**-4., 'qdf does not behave as expected' # Calculate the velocity dispersions from numpy import sqrt sqrt(df.sigmaR2(0.9,0.05)), sqrt(df.sigmaz2(0.9,0.05)) assert numpy.fabs(sqrt(df.sigmaR2(0.9,0.05))-0.22695537077102387) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(sqrt(df.sigmaz2(0.9,0.05))-0.094215523962105044) < 10.**-4., 'qdf does not behave as expected' # Calculate the tilt of the velocity ellipsoid # 2017/10-28: CHANGED bc tilt now returns angle in rad, no longer in deg df.tilt(0.9,0.05) assert numpy.fabs(df.tilt(0.9,0.05)-2.5166061974413765/180.*numpy.pi) < 10.**-4., 'qdf does not behave as expected' # Calculate a higher-order moment of the velocity DF df.vmomentdensity(0.9,0.05,6.,2.,2.,gl=True) assert numpy.fabs(df.vmomentdensity(0.9,0.05,6.,2.,2.,gl=True)-0.0001591100892366438) < 10.**-4., 'qdf does not behave as expected' # Sample velocities at given R,z, check mean numpy.random.seed(1) vs= df.sampleV(0.9,0.05,n=500); mvt= numpy.mean(vs[:,1]) assert numpy.fabs(numpy.mean(vs[:,0])) < 0.05 # vR assert numpy.fabs(mvt-df.meanvT(0.9,0.05)) < 0.01 #vT assert numpy.fabs(numpy.mean(vs[:,2])) < 0.05 # vz return None
def test_sigmarz_staeckel_mc(): numpy.random.seed(1) qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #In the mid-plane, should be zero assert numpy.fabs(qdf.sigmaRz(0.9,0.,mc=True)) < 0.05, "qdf's sigmaRz deviates more than expected from zero in the mid-plane for staeckel approx." return None
def test_qdf(): from galpy.df import quasiisothermaldf from galpy.potential import MWPotential2014 from galpy.actionAngle import actionAngleStaeckel # Setup actionAngle instance for action calcs aAS= actionAngleStaeckel(pot=MWPotential2014,delta=0.45, c=True) # Quasi-iso df w/ hr=1/3, hsr/z=1, sr(1)=0.2, sz(1)=0.1 df= quasiisothermaldf(1./3.,0.2,0.1,1.,1.,aA=aAS, pot=MWPotential2014) # Evaluate DF w/ R,vR,vT,z,vz df(0.9,0.1,0.8,0.05,0.02) assert numpy.fabs(df(0.9,0.1,0.8,0.05,0.02)-numpy.array([ 123.57158928])) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF w/ Orbit instance, return ln from galpy.orbit import Orbit df(Orbit([0.9,0.1,0.8,0.05,0.02]),log=True) assert numpy.fabs(df(Orbit([0.9,0.1,0.8,0.05,0.02]),log=True)-numpy.array([ 4.81682066])) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF marginalized over vz df.pvRvT(0.1,0.9,0.9,0.05) assert numpy.fabs(df.pvRvT(0.1,0.9,0.9,0.05)-23.273310451852243) < 10.**-4., 'qdf does not behave as expected' # Evaluate DF marginalized over vR,vT df.pvz(0.02,0.9,0.05) assert numpy.fabs(df.pvz(0.02,0.9,0.05)-50.949586235238172) < 10.**-4., 'qdf does not behave as expected' # Calculate the density df.density(0.9,0.05) assert numpy.fabs(df.density(0.9,0.05)-12.73725936526167) < 10.**-4., 'qdf does not behave as expected' # Estimate the DF's actual density scale length at z=0 df.estimate_hr(0.9,0.) assert numpy.fabs(df.estimate_hr(0.9,0.)-0.322420336223) < 10.**-2., 'qdf does not behave as expected' # Estimate the DF's actual surface-density scale length df.estimate_hr(0.9,None) assert numpy.fabs(df.estimate_hr(0.9,None)-0.38059909132766462) < 10.**-4., 'qdf does not behave as expected' # Estimate the DF's density scale height df.estimate_hz(0.9,0.02) assert numpy.fabs(df.estimate_hz(0.9,0.02)-0.064836202345657207) < 10.**-4., 'qdf does not behave as expected' # Calculate the mean velocities df.meanvR(0.9,0.05), df.meanvT(0.9,0.05), df.meanvz(0.9,0.05) assert numpy.fabs(df.meanvR(0.9,0.05)-3.8432265354618213e-18) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(df.meanvT(0.9,0.05)-0.90840425173325279) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(df.meanvz(0.9,0.05)+4.3579787517991084e-19) < 10.**-4., 'qdf does not behave as expected' # Calculate the velocity dispersions from numpy import sqrt sqrt(df.sigmaR2(0.9,0.05)), sqrt(df.sigmaz2(0.9,0.05)) assert numpy.fabs(sqrt(df.sigmaR2(0.9,0.05))-0.22695537077102387) < 10.**-4., 'qdf does not behave as expected' assert numpy.fabs(sqrt(df.sigmaz2(0.9,0.05))-0.094215523962105044) < 10.**-4., 'qdf does not behave as expected' # Calculate the tilt of the velocity ellipsoid df.tilt(0.9,0.05) assert numpy.fabs(df.tilt(0.9,0.05)-2.5166061974413765) < 10.**-4., 'qdf does not behave as expected' # Calculate a higher-order moment of the velocity DF df.vmomentdensity(0.9,0.05,6.,2.,2.,gl=True) assert numpy.fabs(df.vmomentdensity(0.9,0.05,6.,2.,2.,gl=True)-0.0001591100892366438) < 10.**-4., 'qdf does not behave as expected' # Sample velocities at given R,z, check mean numpy.random.seed(1) vs= df.sampleV(0.9,0.05,n=500); mvt= numpy.mean(vs[:,1]) assert numpy.fabs(numpy.mean(vs[:,0])) < 0.05 # vR assert numpy.fabs(mvt-df.meanvT(0.9,0.05)) < 0.01 #vT assert numpy.fabs(numpy.mean(vs[:,2])) < 0.05 # vz return None
def test_tilt_adiabatic_gl(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAA,cutcounter=True) #should be zero everywhere assert numpy.fabs(qdf.tilt(0.9,0.,gl=True)) < 0.05, "qdf's tilt deviates more than expected from zero for adiabatic approx." assert numpy.fabs(qdf.tilt(0.9,0.2,gl=True)) < 0.05, "qdf's tilt deviates more than expected from zero for adiabatic approx." assert numpy.fabs(qdf.tilt(0.9,-0.25,gl=True)) < 0.05, "qdf's tilt deviates more than expected from zero for adiabatic approx." return None
def test_jmomentdensity_physical(): # Test physical output of jmomentdensity qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) ro,vo= 7.,230. assert numpy.fabs(qdf.jmomentdensity(1.1,0.1,0,0,0,nmc=100000,ro=ro,vo=vo)-qdf.jmomentdensity(1.1,0.1,0,0,0,nmc=100000)/ro**3*(ro*vo)**0) < 10.**-4., 'quasiisothermaldf method jmomentdensity does not return correct Quantity' assert numpy.fabs(qdf.jmomentdensity(1.1,0.1,1,0,0,nmc=100000,ro=ro,vo=vo,use_physical=True)-qdf.jmomentdensity(1.1,0.1,1,0,0,nmc=100000)/ro**3*(ro*vo)**1) < 10.**-2., 'quasiisothermaldf method jmomentdensity does not return correct Quantity' return None
def test_tilt_staeckel_mc(): numpy.random.seed(1) qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #should be zero in the mid-plane and roughly toward the GC elsewhere assert numpy.fabs(qdf.tilt(0.9,0.,mc=True)) < 1., "qdf's tilt deviates more than expected from zero in the mid-plane for staeckel approx." #this is tough assert numpy.fabs(qdf.tilt(0.9,0.1,mc=True)-numpy.arctan(0.1/0.9)/numpy.pi*180.) < 3., "qdf's tilt deviates more than expected from expected for staeckel approx." return None
def test_sigmar_staeckel_gl(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #In the mid-plane assert numpy.fabs(numpy.log(qdf.sigmaR2(0.9,0.,gl=True))-2.*numpy.log(0.2)-0.2) < 0.2, "qdf's sigmaR2 deviates more than expected from input for staeckel approx." #higher up, also w/ different ngl assert numpy.fabs(numpy.log(qdf.sigmaR2(0.9,0.2,gl=True,ngl=20))-2.*numpy.log(0.2)-0.2) < 0.3, "qdf's sigmaR2 deviates more than expected from input for staeckel approx." assert numpy.fabs(numpy.log(qdf.sigmaR2(0.9,-0.25,gl=True,ngl=24))-2.*numpy.log(0.2)-0.2) < 0.3, "qdf's sigmaR2 deviates more than expected from input for staeckel approx." return None
def test_vmomentdensity_physical(): # Test physical output of vmomentdensity qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) R, z= 0.8, 0.1 ro,vo= 7.,230. assert numpy.fabs(qdf.vmomentdensity(R,z,0,0,0,gl=True,ngl=12,ro=ro,vo=vo)-qdf.vmomentdensity(R,z,0,0,0,gl=True,ngl=12)/ro**3) < 10.**-8., 'vmomentdensity with use_physical does not correspond to vmomentdensity without physical' assert numpy.fabs(qdf.vmomentdensity(R,z,0,1,0,gl=True,ngl=12,ro=ro,vo=vo)-qdf.vmomentdensity(R,z,0,1,0,gl=True,ngl=12)*vo/ro**3) < 10.**-8., 'vmomentdensity with use_physical does not correspond to vmomentdensity without physical' return None
def test_tilt_staeckel_gl(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #should be zero in the mid-plane and roughly toward the GC elsewhere assert numpy.fabs(qdf.tilt(0.9,0.,gl=True)) < 0.05, "qdf's tilt deviates more than expected from zero in the mid-plane for staeckel approx." assert numpy.fabs(qdf.tilt(0.9,0.1,gl=True)-numpy.arctan(0.1/0.9)/numpy.pi*180.) < 2., "qdf's tilt deviates more than expected from expected for staeckel approx." assert numpy.fabs(qdf.tilt(0.9,-0.15,gl=True)-numpy.arctan(-0.15/0.9)/numpy.pi*180.) < 2.5, "qdf's tilt deviates more than expected from expected for staeckel approx." assert numpy.fabs(qdf.tilt(0.9,-0.25,gl=True)-numpy.arctan(-0.25/0.9)/numpy.pi*180.) < 4., "qdf's tilt deviates more than expected from expected for staeckel approx." return None
def test_estimate_hz(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) from scipy import integrate from galpy.potential import evaluateDensities expec_hz= 0.1**2./2.\ /integrate.quad(lambda x: evaluateDensities(0.9,x,MWPotential), 0.,0.125)[0]/2./numpy.pi assert numpy.fabs((qdf.estimate_hz(0.9,z=0.125)-expec_hz)/expec_hz) < 0.1, 'estimated scale height not as expected' assert qdf.estimate_hz(0.9,z=0.) > 1., 'estimated scale height at z=0 not very large' #Another one qdf= quasiisothermaldf(1./4.,0.3,0.2,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) expec_hz= 0.2**2./2.\ /integrate.quad(lambda x: evaluateDensities(0.9,x,MWPotential), 0.,0.125)[0]/2./numpy.pi assert numpy.fabs((qdf.estimate_hz(0.9,z=0.125)-expec_hz)/expec_hz) < 0.15, 'estimated scale height not as expected' return None
def test_meanvR_staeckel_gl(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #In the mid-plane assert numpy.fabs(qdf.meanvR(0.9,0.,gl=True)) < 0.01, "qdf's meanvr is not equal to zero for staeckel approx." #higher up assert numpy.fabs(qdf.meanvR(0.9,0.2,gl=True)) < 0.01, "qdf's meanvr is not equal to zero for staeckel approx." assert numpy.fabs(qdf.meanvR(0.9,-0.25,gl=True)) < 0.01, "qdf's meanvr is not equal to zero for staeckel approx." return None
def test_sigmar_staeckel_mc(): numpy.random.seed(1) qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #In the mid-plane assert numpy.fabs(numpy.log(qdf.sigmaR2(0.9,0.,mc=True))-2.*numpy.log(0.2)-0.2) < 0.2, "qdf's sigmaR2 deviates more than expected from input for staeckel approx." #higher up assert numpy.fabs(numpy.log(qdf.sigmaR2(0.9,0.2,mc=True))-2.*numpy.log(0.2)-0.2) < 0.4, "qdf's sigmaR2 deviates more than expected from input for staeckel approx." assert numpy.fabs(numpy.log(qdf.sigmaR2(0.9,-0.25,mc=True))-2.*numpy.log(0.2)-0.2) < 0.3, "qdf's sigmaR2 deviates more than expected from input for staeckel approx." return None
def test_sigmat_staeckel_mc(): numpy.random.seed(2) qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #In the mid-plane gamma= 2.*omegac(MWPotential,0.9)/epifreq(MWPotential,0.9) assert numpy.fabs(numpy.log(qdf.sigmaT2(0.9,0.,mc=True)/qdf.sigmaR2(0.9,0.,mc=True))+2.*numpy.log(gamma)) < 0.3, "qdf's sigmaT2/sigmaR2 deviates more than expected from input for staeckel approx." #higher up assert numpy.fabs(numpy.log(qdf.sigmaT2(0.9,0.2,mc=True)/qdf.sigmaR2(0.9,0.2,mc=True))+2.*numpy.log(gamma)) < 0.3, "qdf's sigmaT2/sigmaR2 deviates more than expected from input for staeckel approx." return None
def test_meanvR_adiabatic_mc(): numpy.random.seed(1) qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAA,cutcounter=True) #In the mid-plane assert numpy.fabs(qdf.meanvR(0.9,0.,mc=True)) < 0.01, "qdf's meanvr is not equal to zero for adiabatic approx." #higher up assert numpy.fabs(qdf.meanvR(0.9,0.2,mc=True)) < 0.05, "qdf's meanvr is not equal to zero for adiabatic approx." assert numpy.fabs(qdf.meanvR(0.9,-0.25,mc=True)) < 0.05, "qdf's meanvr is not equal to zero for adiabatic approx." return None
def test_meanjr(): #This is a *very* rough test against a rough estimate of the mean qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) assert numpy.fabs(numpy.log(qdf.meanjr(0.9,0.,mc=True))\ -2.*numpy.log(0.2)-0.2 +numpy.log(epifreq(MWPotential,0.9))) < 0.4, 'meanjr is not what is expected' assert numpy.fabs(numpy.log(qdf.meanjr(0.5,0.,mc=True))\ -2.*numpy.log(0.2)-1. +numpy.log(epifreq(MWPotential,0.5))) < 0.4, 'meanjr is not what is expected' return None
def test_meanlz(): #This is a *very* rough test against a rough estimate of the mean qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) from galpy.df import dehnendf #baseline dfc= dehnendf(profileParams=(1./4.,1.0, 0.2), beta=0.,correct=False) assert numpy.fabs(numpy.log(qdf.meanlz(0.9,0.,mc=True))\ -numpy.log(0.9*dfc.meanvT(0.9))) < 0.1, 'meanlz is not what is expected' assert numpy.fabs(numpy.log(qdf.meanlz(0.5,0.,mc=True))\ -numpy.log(0.5*dfc.meanvT(0.5))) < 0.2, 'meanlz is not what is expected' return None
def test_pvT_staeckel(): # Test pvT by calculating its mean and stddev by Riemann sum qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) R,z= 0.8, 0.1 vTs= numpy.linspace(0.,1.5,101) pvT= numpy.array([qdf.pvT(vt,R,z) for vt in vTs]) mvT= numpy.sum(vTs*pvT)/numpy.sum(pvT) svT= numpy.sqrt(numpy.sum(vTs**2.*pvT)/numpy.sum(pvT)-mvT**2.) assert numpy.fabs(mvT-qdf.meanvT(R,z)) < 0.01, 'mean vT calculated from pvT not equal to zero for staeckel actions' assert numpy.fabs(numpy.log(svT)-0.5*numpy.log(qdf.sigmaT2(R,z))) < 0.01, 'sigma vT calculated from pvT not equal to that from sigmaT2 for staeckel actions' return None
def test_meanjz_noaac_issue300(): # Test of issue 300 reported by Ruth Angus: failure of qdf.meanjz when not using C integration for action-angle calculations taA= actionAngleAdiabatic(pot=MWPotential,c=False) hr= 1/3. sr= .2 sz= .1 hsr= 1. hsz= 1. qdf= quasiisothermaldf(hr,sr,sz,hsr,hsz,pot=MWPotential,aA=taA, cutcounter=True) assert numpy.fabs(qdf.meanjz(1.,0.125,nmc=100)-0.0157468008111) < 0.01, 'Mean Jz computed using MC with Python actionAngleAdiabatic integration fails' return None
def test_pvz_adiabatic(): # Test pvz by calculating its mean and stddev by Riemann sum qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAA,cutcounter=True) R,z= 0.8, 0.1 vzs= numpy.linspace(-1.,1.,51) pvz= numpy.array([qdf.pvz(vz,R,z) for vz in vzs]) mvz= numpy.sum(vzs*pvz)/numpy.sum(pvz) svz= numpy.sqrt(numpy.sum(vzs**2.*pvz)/numpy.sum(pvz)-mvz**2.) assert numpy.fabs(mvz) < 0.01, 'mean vz calculated from pvz not equal to zero for adiabatic actions' assert numpy.fabs(numpy.log(svz)-0.5*numpy.log(qdf.sigmaz2(R,z))) < 0.01, 'sigma vz calculated from pvz not equal to that from sigmaz2 for adiabatic actions' return None
def test_meanjz(): #This is a *very* rough test against a rough estimate of the mean qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) ldiff= numpy.log(qdf.meanjz(0.9,0.,mc=True))-2.*numpy.log(0.1)-0.2\ +numpy.log(verticalfreq(MWPotential,0.9)) #expect this to be smaller than the rough estimate, but not by more than an order of magnitude assert ldiff > -1. and ldiff < 0., 'meanjz is not what is expected' ldiff= numpy.log(qdf.meanjz(0.5,0.,mc=True))-2.*numpy.log(0.1)-1.0\ +numpy.log(verticalfreq(MWPotential,0.5)) assert ldiff > -1. and ldiff < 0., 'meanjz is not what is expected' return None
def test_pvR_staeckel(): # Test pvR by calculating its mean and stddev by Riemann sum qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) R,z= 0.8, 0.1 vRs= numpy.linspace(-1.,1.,51) pvR= numpy.array([qdf.pvR(vr,R,z) for vr in vRs]) mvR= numpy.sum(vRs*pvR)/numpy.sum(pvR) svR= numpy.sqrt(numpy.sum(vRs**2.*pvR)/numpy.sum(pvR)-mvR**2.) assert numpy.fabs(mvR) < 0.01, 'mean vR calculated from pvR not equal to zero for staeckel actions' assert numpy.fabs(numpy.log(svR)-0.5*numpy.log(qdf.sigmaR2(R,z))) < 0.01, 'sigma vR calculated from pvR not equal to that from sigmaR2 for staeckel actions' return None
def test_jmomentdensity_diffinoutputs(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #Some tests of mc=True R,z= 0.8, 0.1 jr2surfmass, vrs, vts, vzs= qdf.jmomentdensity(R,z,2.,0.,0.,mc=True, _returnmc=True) assert numpy.fabs(numpy.log(jr2surfmass)-numpy.log(qdf.jmomentdensity(R,z,2.,0.,0., mc=True, _vrs=vrs, _vts=vts, _vzs=vzs))) < 0.0001, 'qdf.jmomentdensity w/ rawgausssamples and mc=True does not agree with that w/o rawgausssamples' return None
def quasiisothermal(samples, params=[1./0.3,0.2,0.1,1./1.,1./1.]): qdf= quasiisothermaldf(1./3.,params[1],params[2],1./params[3],1./params[4], pot=MWPotential2014,aA=aAS,cutcounter=True) mask = np.all(np.isfinite(samples), axis=1) samples = samples[mask] dens = qdf(samples[:,0], samples[:,1], samples[:,2], samples[:,3], samples[:,4]) dens[dens < 1e-30] = 1e-30 out = np.sum(np.log(dens)) print(out) print(params) return out
def test_sigmaz_staeckel_gl(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #In the mid-plane assert numpy.fabs(numpy.log(qdf.sigmaz2(0.9,0.,gl=True))-2.*numpy.log(0.1)-0.2) < 0.5, "qdf's sigmaz2 deviates more than expected from input for staeckel approx." #from Bovy & Rix 2013, we know that this has to be smaller assert numpy.log(qdf.sigmaz2(0.9,0.,gl=True)) < 2.*numpy.log(0.1)+0.2 < 0.5, "qdf's sigmaz2 deviates more than expected from input for staeckel approx." #higher up assert numpy.fabs(numpy.log(qdf.sigmaz2(0.9,0.2,gl=True))-2.*numpy.log(0.1)-0.2) < 0.5, "qdf's sigmaz2 deviates more than expected from input for staeckel approx." assert numpy.log(qdf.sigmaz2(0.9,0.2,gl=True)) < 2.*numpy.log(0.1)+0.2 < 0.5, "qdf's sigmaz2 deviates more than expected from input for staeckel approx." assert numpy.fabs(numpy.log(qdf.sigmaz2(0.9,-0.25,gl=True))-2.*numpy.log(0.1)-0.2) < 0.5, "qdf's sigmaz2 deviates more than expected from input for staeckel approx." assert numpy.log(qdf.sigmaz2(0.9,-0.25,gl=True)) < 2.*numpy.log(0.1)+0.2 < 0.5, "qdf's sigmaz2 deviates more than expected from input for staeckel approx." return None
def test_meanvT_staeckel_gl(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) from galpy.df import dehnendf #baseline dfc= dehnendf(profileParams=(1./4.,1.0, 0.2), beta=0.,correct=False) #In the mid-plane vtp9= qdf.meanvT(0.9,0.,gl=True) assert numpy.fabs(vtp9-dfc.meanvT(0.9)) < 0.05, "qdf's meanvT is not close to that of dehnendf" assert vtp9 < vcirc(MWPotential,0.9), "qdf's meanvT is not less than the circular velocity (which we expect)" #higher up assert qdf.meanvR(0.9,0.2,gl=True) < vtp9, "qdf's meanvT above the plane is not less than in the plane (which we expect)" assert qdf.meanvR(0.9,-0.25,gl=True) < vtp9, "qdf's meanvT above the plane is not less than in the plane (which we expect)" return None
def test_sampleV(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) numpy.random.seed(1) samples= qdf.sampleV(0.8,0.1,n=1000) #test vR assert numpy.fabs(numpy.mean(samples[:,0])) < 0.02, 'sampleV vR mean is not zero' assert numpy.fabs(numpy.log(numpy.std(samples[:,0]))-0.5*numpy.log(qdf.sigmaR2(0.8,0.1))) < 0.05, 'sampleV vR stddev is not equal to sigmaR' #test vT assert numpy.fabs(numpy.mean(samples[:,1]-qdf.meanvT(0.8,0.1))) < 0.015, 'sampleV vT mean is not equal to meanvT' assert numpy.fabs(numpy.log(numpy.std(samples[:,1]))-0.5*numpy.log(qdf.sigmaT2(0.8,0.1))) < 0.05, 'sampleV vT stddev is not equal to sigmaT' #test vz assert numpy.fabs(numpy.mean(samples[:,2])) < 0.01, 'sampleV vz mean is not zero' assert numpy.fabs(numpy.log(numpy.std(samples[:,2]))-0.5*numpy.log(qdf.sigmaz2(0.8,0.1))) < 0.05, 'sampleV vz stddev is not equal to sigmaz' return None
def test_overview(): from galpy.potential import NFWPotential np= NFWPotential(normalize=1.) from galpy.orbit import Orbit o= Orbit(vxvv=[1.,0.1,1.1,0.1,0.02,0.]) from galpy.actionAngle import actionAngleSpherical aA= actionAngleSpherical(pot=np) js= aA(o) assert numpy.fabs((js[0]-0.00980542)/js[0]) < 10.**-3., 'Action calculation in the overview section has changed' assert numpy.fabs((js[1]-1.1)/js[0]) < 10.**-3., 'Action calculation in the overview section has changed' assert numpy.fabs((js[2]-0.00553155)/js[0]) < 10.**-3., 'Action calculation in the overview section has changed' from galpy.df import quasiisothermaldf qdf= quasiisothermaldf(1./3.,0.2,0.1,1.,1., pot=np,aA=aA) assert numpy.fabs((qdf(o)-61.57476085)/61.57476085) < 10.**-3., 'qdf calculation in the overview section has changed' return None
def test_vmomentdensity_diffinoutputs(): qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True) #Test that we can input use different ngl R, z= 0.8, 0.1 sigmar2= qdf.sigmaR2(R,z,gl=True) assert numpy.fabs(numpy.log(qdf.sigmaR2(R,z,gl=True,_sigmaR1=0.95*numpy.sqrt(qdf.sigmaR2(R,z)),_sigmaz1=0.95*numpy.sqrt(qdf.sigmaz2(R,z))))-numpy.log(sigmar2)) < 0.01, 'sigmaR2 calculated w/ explicit sigmaR1 and sigmaz1 do not agree' #Test ngl inputs further try: qdf.vmomentdensity(R,z,0,0,0,gl=True,ngl=11) except ValueError: pass else: raise AssertionError('qdf.vmomentdensity w/ ngl == odd does not raise ValueError') surfmass, glqeval= qdf.vmomentdensity(R,z,0.,0.,0., gl=True, _returngl=True) #This shouldn't reuse gleval, but should work nonetheless assert numpy.fabs(numpy.log(surfmass)\ -numpy.log(qdf.vmomentdensity(R,z,0.,0.,0., gl=True, _glqeval=glqeval, ngl=30))) < 0.05, 'vmomentsurfmass w/ wrong glqeval input does not work' #Test that we can re-use jr, etc. surfmass, jr,lz,jz= qdf.vmomentdensity(R,z,0.,0.,0.,gl=True, _return_actions=True) assert numpy.fabs(numpy.log(surfmass)\ -numpy.log(qdf.vmomentdensity(R,z,0.,0.,0.,gl=True, _jr=jr,_lz=lz,_jz=jz))) < 0.01, 'surfacemass calculated from re-used actions does not agree with that before' surfmass, jr,lz,jz, rg, kappa, nu, Omega=\ qdf.vmomentdensity(R,z,0.,0.,0.,gl=True, _return_actions=True, _return_freqs=True) assert numpy.fabs(numpy.log(surfmass)\ -numpy.log(qdf.vmomentdensity(R,z,0.,0.,0.,gl=True, _jr=jr,_lz=lz,_jz=jz, _rg=rg,_kappa=kappa, _nu=nu,_Omega=Omega))) < 0.01, 'surfacemass calculated from re-used actions does not agree with that before' #Some tests of mc=True surfmass, vrs, vts, vzs= qdf.vmomentdensity(R,z,0.,0.,0.,mc=True,gl=False, _rawgausssamples=True, _returnmc=True) assert numpy.fabs(numpy.log(surfmass)-numpy.log(qdf.vmomentdensity(R,z,0.,0.,0., mc=True,gl=False, _rawgausssamples=True, _vrs=vrs, _vts=vts, _vzs=vzs))) < 0.0001, 'qdf.vmomentdensity w/ rawgausssamples and mc=True does not agree with that w/o rawgausssamples' return None