def test_setup_diffsetups(): #Test the different ways to setup a qdf object #Test errors try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., aA=aAS,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/o pot set did not raise exception") try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/o aA set did not raise exception") from galpy.potential import LogarithmicHaloPotential try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=LogarithmicHaloPotential(), aA=aAS,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/ aA potential different from pot= did not raise exception") #qdf setup with an actionAngleIsochrone instance (issue #190) from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleIsochrone ip= IsochronePotential(normalize=1.,b=2.) try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=ip, aA=actionAngleIsochrone(ip=ip),cutcounter=True) except: raise raise AssertionError('quasi-isothermaldf setup w/ an actionAngleIsochrone instance failed') #qdf setup with an actionAngleIsochrone instance should raise error if potentials are not the same ip= IsochronePotential(normalize=1.,b=2.) try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=ip, aA=actionAngleIsochrone(ip=IsochronePotential(normalize=1.,b=2.5)), cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/ aA potential different from pot= did not raise exception") #precompute qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True, _precomputerg=True) qdfnpc= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True, _precomputerg=False) assert numpy.fabs(qdf.rg(1.1)-qdfnpc.rg(1.1)) < 10.**-5., 'rg calculated from qdf instance w/ precomputerg set is not the same as that computed from an instance w/o it set'
def test_actionAngleTorus_Isochrone_actions(): from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochrone ip = IsochronePotential(normalize=1., b=1.2) aAI = actionAngleIsochrone(ip=ip) tol = -6. aAT = actionAngleTorus(pot=ip, tol=tol) jr, jphi, jz = 0.075, 1.1, 0.05 angler = numpy.array([0.]) anglephi = numpy.array([numpy.pi]) anglez = numpy.array([numpy.pi / 2.]) # Calculate position from aAT RvR = aAT(jr, jphi, jz, angler, anglephi, anglez).T # Calculate actions from aAI ji = aAI(*RvR) djr = numpy.fabs((ji[0] - jr) / jr) dlz = numpy.fabs((ji[1] - jphi) / jphi) djz = numpy.fabs((ji[2] - jz) / jz) assert djr < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % ( djr * 100.) assert dlz < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % ( dlz * 100.) assert djz < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % ( djz * 100.) return None
def test_adinvariance(): from galpy.potential import IsochronePotential from galpy.orbit import Orbit from galpy.actionAngle import actionAngleIsochrone # Initialize two different IsochronePotentials ip1= IsochronePotential(normalize=1.,b=1.) ip2= IsochronePotential(normalize=0.5,b=1.) # Use TimeInterpPotential to interpolate smoothly tip= TimeInterpPotential(ip1,ip2,dt=100.,tform=50.) # Integrate: 1) Orbit in the first isochrone potential o1= Orbit([1.,0.1,1.1,0.0,0.1,0.]) ts= numpy.linspace(0.,50.,1001) o1.integrate(ts,tip) o1.plot(d1='x',d2='y',xrange=[-1.6,1.6],yrange=[-1.6,1.6], color='b') # 2) Orbit in the transition o2= o1(ts[-1]) # Last time step => initial time step ts2= numpy.linspace(50.,150.,1001) o2.integrate(ts2,tip) o2.plot(d1='x',d2='y',overplot=True,color='g') # 3) Orbit in the second isochrone potential o3= o2(ts2[-1]) ts3= numpy.linspace(150.,200.,1001) o3.integrate(ts3,tip) o3.plot(d1='x',d2='y',overplot=True,color='r') # Now we calculate energy, maximum height, and mean radius print(o1.E(pot=ip1), (o1.rperi()+o1.rap())/2, o1.zmax()) assert numpy.fabs(o1.E(pot=ip1)+2.79921356237) < 10.**-4., 'Energy in the adiabatic invariance test is different' assert numpy.fabs((o1.rperi()+o1.rap())/2-1.07854158141) < 10.**-4., 'mean radius in the adiabatic invariance test is different' assert numpy.fabs(o1.zmax()-0.106331362938) < 10.**-4., 'zmax in the adiabatic invariance test is different' print(o3.E(pot=ip2), (o3.rperi()+o3.rap())/2, o3.zmax()) assert numpy.fabs(o3.E(pot=ip2)+1.19677002624) < 10.**-4., 'Energy in the adiabatic invariance test is different' assert numpy.fabs((o3.rperi()+o3.rap())/2-1.39962036137) < 10.**-4., 'mean radius in the adiabatic invariance test is different' assert numpy.fabs(o3.zmax()-0.138364269321) < 10.**-4., 'zmax in the adiabatic invariance test is different' # The orbit has clearly moved to larger radii, # the actions are however conserved from beginning to end aAI1= actionAngleIsochrone(ip=ip1); print(aAI1(o1)) js= aAI1(o1) assert numpy.fabs(js[0]-numpy.array([ 0.00773779])) < 10.**-4., 'action in the adiabatic invariance test is different' assert numpy.fabs(js[1]-numpy.array([ 1.1])) < 10.**-4., 'action in the adiabatic invariance test is different' assert numpy.fabs(js[2]-numpy.array([ 0.0045361])) < 10.**-4., 'action in the adiabatic invariance test is different' aAI2= actionAngleIsochrone(ip=ip2); print(aAI2(o3)) js= aAI2(o3) assert numpy.fabs(js[0]-numpy.array([ 0.00773812])) < 10.**-4., 'action in the adiabatic invariance test is different' assert numpy.fabs(js[1]-numpy.array([ 1.1])) < 10.**-4., 'action in the adiabatic invariance test is different' assert numpy.fabs(js[2]-numpy.array([ 0.0045361])) < 10.**-4., 'action in the adiabatic invariance test is different' return None
def test_actionAngleTorus_Isochrone_freqsAngles(): from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochrone ip = IsochronePotential(normalize=1., b=1.2) aAI = actionAngleIsochrone(ip=ip) tol = -6. aAT = actionAngleTorus(pot=ip, tol=tol) jr, jphi, jz = 0.075, 1.1, 0.05 angler = numpy.array([0.1]) + numpy.linspace(0., numpy.pi, 101) angler = angler % (2. * numpy.pi) anglephi = numpy.array([numpy.pi]) + numpy.linspace(0., numpy.pi, 101) anglephi = anglephi % (2. * numpy.pi) anglez = numpy.array([numpy.pi / 2.]) + numpy.linspace(0., numpy.pi, 101) anglez = anglez % (2. * numpy.pi) # Calculate position from aAT RvRom = aAT.xvFreqs(jr, jphi, jz, angler, anglephi, anglez) # Calculate actions, frequencies, and angles from aAI ws = aAI.actionsFreqsAngles(*RvRom[0].T) dOr = numpy.fabs((ws[3] - RvRom[1])) dOp = numpy.fabs((ws[4] - RvRom[2])) dOz = numpy.fabs((ws[5] - RvRom[3])) dar = numpy.fabs((ws[6] - angler)) dap = numpy.fabs((ws[7] - anglephi)) daz = numpy.fabs((ws[8] - anglez)) dar[dar > numpy.pi] -= 2. * numpy.pi dar[dar < -numpy.pi] += 2. * numpy.pi dap[dap > numpy.pi] -= 2. * numpy.pi dap[dap < -numpy.pi] += 2. * numpy.pi daz[daz > numpy.pi] -= 2. * numpy.pi daz[daz < -numpy.pi] += 2. * numpy.pi assert numpy.all( dOr < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Or at %f%%' % ( numpy.nanmax(dOr) * 100.) assert numpy.all( dOp < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Ophi at %f%%' % ( numpy.nanmax(dOp) * 100.) assert numpy.all( dOz < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Oz at %f%%' % ( numpy.nanmax(dOz) * 100.) assert numpy.all( dar < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for ar at %f' % ( numpy.nanmax(dar)) assert numpy.all( dap < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for aphi at %f' % ( numpy.nanmax(dap)) assert numpy.all( daz < 10.**tol ), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for az at %f' % ( numpy.nanmax(daz)) return None
def illustrate_adiabatic_invariance(plotfilename1,plotfilename2): # Initialize two different IsochronePotentials ip1= IsochronePotential(normalize=1.,b=1.) ip2= IsochronePotential(normalize=0.5,b=1.) # Use TimeInterpPotential to interpolate smoothly between the two tip= TimeInterpPotential(ip1,ip2,dt=100.,tform=50.) # Integrate the orbit, in three parts # 1) Orbit in the first isochrone potential o1= Orbit([1.,0.1,1.1,0.0,0.1,0.]) ts= numpy.linspace(0.,50.,1001) o1.integrate(ts,tip) bovy_plot.bovy_print() o1.plot(d1='x',d2='y',xrange=[-1.6,1.6],yrange=[-1.6,1.6],color='b', gcf=True) # 2) Orbit in the transition o2= o1(ts[-1]) # Last time step = initial time step of the next integration ts2= numpy.linspace(50.,150.,1001) o2.integrate(ts2,tip) o2.plot(d1='x',d2='y',overplot=True,color='g') # 3) Orbit in the second isochrone potential o3= o2(ts2[-1]) ts3= numpy.linspace(150.,200.,1001) o3.integrate(ts3,ip2) o3.plot(d1='x',d2='y',overplot=True,color='r') bovy_plot.bovy_end_print(plotfilename1) # Also plot the R,z projection bovy_plot.bovy_print(fig_height=2.3333) o1.plot(d1='R',d2='z',xrange=[0.9,1.65],yrange=[-.175,.175],color='b', gcf=True) o2.plot(d1='R',d2='z',overplot=True,color='g') o3.plot(d1='R',d2='z',overplot=True,color='r') bovy_plot.bovy_end_print(plotfilename2) # Now we calculate the energy, eccentricity, mean radius, and maximum height print o1.E(pot=ip1), o1.e(), 0.5*(o1.rperi()+o1.rap()), o1.zmax() print o3.E(pot=ip2), o3.e(), 0.5*(o3.rperi()+o3.rap()), o3.zmax() # The orbit has clearly moved to larger radii, the actions are however conserved aAI1= actionAngleIsochrone(ip=ip1) aAI2= actionAngleIsochrone(ip=ip2) print aAI1(o1) print aAI2(o3) return None
def test_actionAngleTorus_Isochrone_freqsAngles(): from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochrone ip= IsochronePotential(normalize=1.,b=1.2) aAI= actionAngleIsochrone(ip=ip) tol= -6. aAT= actionAngleTorus(pot=ip,tol=tol) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.1])+numpy.linspace(0.,numpy.pi,101) angler= angler % (2.*numpy.pi) anglephi= numpy.array([numpy.pi])+numpy.linspace(0.,numpy.pi,101) anglephi= anglephi % (2.*numpy.pi) anglez= numpy.array([numpy.pi/2.])+numpy.linspace(0.,numpy.pi,101) anglez= anglez % (2.*numpy.pi) # Calculate position from aAT RvRom= aAT.xvFreqs(jr,jphi,jz,angler,anglephi,anglez) # Calculate actions, frequencies, and angles from aAI ws= aAI.actionsFreqsAngles(*RvRom[0].T) dOr= numpy.fabs((ws[3]-RvRom[1])) dOp= numpy.fabs((ws[4]-RvRom[2])) dOz= numpy.fabs((ws[5]-RvRom[3])) dar= numpy.fabs((ws[6]-angler)) dap= numpy.fabs((ws[7]-anglephi)) daz= numpy.fabs((ws[8]-anglez)) dar[dar > numpy.pi]-= 2.*numpy.pi dar[dar < -numpy.pi]+= 2.*numpy.pi dap[dap > numpy.pi]-= 2.*numpy.pi dap[dap < -numpy.pi]+= 2.*numpy.pi daz[daz > numpy.pi]-= 2.*numpy.pi daz[daz < -numpy.pi]+= 2.*numpy.pi assert numpy.all(dOr < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Or at %f%%' % (numpy.nanmax(dOr)*100.) assert numpy.all(dOp < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Ophi at %f%%' % (numpy.nanmax(dOp)*100.) assert numpy.all(dOz < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Oz at %f%%' % (numpy.nanmax(dOz)*100.) assert numpy.all(dar < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for ar at %f' % (numpy.nanmax(dar)) assert numpy.all(dap < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for aphi at %f' % (numpy.nanmax(dap)) assert numpy.all(daz < 10.**tol), 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for az at %f' % (numpy.nanmax(daz)) return None
def test_actionAngleTorus_Isochrone_actions(): from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleTorus, \ actionAngleIsochrone ip= IsochronePotential(normalize=1.,b=1.2) aAI= actionAngleIsochrone(ip=ip) tol= -6. aAT= actionAngleTorus(pot=ip,tol=tol) jr,jphi,jz= 0.075,1.1,0.05 angler= numpy.array([0.]) anglephi= numpy.array([numpy.pi]) anglez= numpy.array([numpy.pi/2.]) # Calculate position from aAT RvR= aAT(jr,jphi,jz,angler,anglephi,anglez).T # Calculate actions from aAI ji= aAI(*RvR) djr= numpy.fabs((ji[0]-jr)/jr) dlz= numpy.fabs((ji[1]-jphi)/jphi) djz= numpy.fabs((ji[2]-jz)/jz) assert djr < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % (djr*100.) assert dlz < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % (dlz*100.) assert djz < 10.**tol, 'actionAngleTorus and actionAngleIsochrone applied to isochrone potential disagree for Jr at %f%%' % (djz*100.) return None
def plot_aaspher_conservation(plotfilename1,plotfilename2): #Setup orbit E, Lz= -1.25, 0.6 o= Orbit([0.8,0.3,Lz/0.8,0.,numpy.sqrt(2.*(E-evalPot(0.8,0.,MWPotential2014)-(Lz/0.8)**2./2.-0.3**2./2.)),0.]) #Integrate the orbit to estimate an equivalent b nt= 1001 ts= numpy.linspace(0.,20.,nt) o.integrate(ts,MWPotential2014,method='symplec4_c') b= estimateBIsochrone(o.R(ts),o.z(ts),pot=MWPotential2014) print b b= 0.3 #Now integrate the orbit in the isochronePotential ip= IsochronePotential(normalize=1.,b=b) aAI= actionAngleIsochrone(ip=ip) orbt= 2.*numpy.pi/aAI.actionsFreqs(o)[4] norb= 200. nt= 20001 ts= numpy.linspace(0.,norb*orbt,nt) o.integrate(ts,ip,method='symplec4_c') #Calculate actions, frequencies, and angles jfa= aAI.actionsFreqsAngles(o.R(ts),o.vR(ts),o.vT(ts), o.z(ts),o.vz(ts),o.phi(ts)) dJs= numpy.fabs((jfa[0]-numpy.mean(jfa[0]))/numpy.mean(jfa[0])) dOrs= numpy.fabs((jfa[3]-numpy.mean(jfa[3]))/numpy.mean(jfa[3])) dOzs= numpy.fabs((jfa[5]-numpy.mean(jfa[5]))/numpy.mean(jfa[5])) print "frequencies", numpy.mean(dOrs), numpy.mean(dOzs) ar= dePeriod(numpy.reshape(jfa[6],(1,len(ts)))).flatten() az= dePeriod(numpy.reshape(jfa[8],(1,len(ts)))).flatten() danglers= numpy.fabs(ar-numpy.mean(jfa[3])*ts-jfa[6][0])/2./numpy.pi danglezs= numpy.fabs(az-numpy.mean(jfa[5])*ts-jfa[8][0])/2./numpy.pi #Break up breakt= 50. pts= parse_break(ts,ts < breakt) pdJs= parse_break(dJs,ts < breakt) pdanglers= parse_break(danglers,ts < breakt) pdanglezs= parse_break(danglezs,ts < breakt) #dAngles bovy_plot.bovy_print() pyplot.subplot(2,1,1) bovy_plot.bovy_plot(pts/orbt, pdJs, color='k',loglog=True,gcf=True, xrange=[0.5,norb], yrange=[10.**-12.,1.]) bovy_plot.bovy_text(r'$\texttt{actionAngleIsochrone}$', top_left=True,size=14.) ax= pyplot.gca() ax.yaxis.set_ticks([10.**-12.,10.**-8.,10.**-4.,1.]) nullfmt = NullFormatter() # no labels ax.xaxis.set_major_formatter(nullfmt) #Same for actionAngleSpherical aAS= actionAngleSpherical(pot=ip) tts= ts[::1] jfa= aAS.actionsFreqsAngles(o.R(tts),o.vR(tts),o.vT(tts), o.z(tts),o.vz(tts),o.phi(tts), fixed_quad=True) #dJr dJs= numpy.fabs((jfa[0]-numpy.mean(jfa[0]))/numpy.mean(jfa[0])) dOrs= numpy.fabs((jfa[3]-numpy.mean(jfa[3]))/numpy.mean(jfa[3])) dOzs= numpy.fabs((jfa[5]-numpy.mean(jfa[5]))/numpy.mean(jfa[5])) print "frequencies", numpy.mean(dOrs), numpy.mean(dOzs) #dAngles ar= dePeriod(numpy.reshape(jfa[6],(1,len(tts)))).flatten() az= dePeriod(numpy.reshape(jfa[8],(1,len(tts)))).flatten() danglers= numpy.fabs(ar-numpy.mean(jfa[3])*tts-jfa[6][0])/2./numpy.pi danglezs= numpy.fabs(az-numpy.mean(jfa[5])*tts-jfa[8][0])/2./numpy.pi print numpy.mean(danglers) print numpy.mean(danglezs) ptts= parse_break(tts,tts < breakt) pdJs= parse_break(dJs,tts < breakt) pyplot.subplot(2,1,2) bovy_plot.bovy_plot(ptts/orbt, pdJs, color='k',loglog=True,gcf=True, xrange=[0.5,norb], yrange=[10.**-12.,1.], xlabel=r'$\mathrm{Number\ of\ orbital\ periods}$') bovy_plot.bovy_text(r'$\texttt{actionAngleSpherical}$', top_left=True,size=14.) bovy_plot.bovy_text(0.175,10.**2.,r'$\left|\Delta J_R / J_R\right|$', fontsize=16., rotation='vertical') ax= pyplot.gca() ax.xaxis.set_major_formatter(ticker.FormatStrFormatter(r'$%0.f$')) ax.yaxis.set_ticks([10.**-12.,10.**-8.,10.**-4.,1.]) bovy_plot.bovy_end_print(plotfilename1) #Now plot the deviations in the angles bovy_plot.bovy_print() pyplot.subplot(2,1,1) liner= bovy_plot.bovy_plot(pts/orbt, pdanglers, color='k',ls='-',loglog=True,gcf=True, xrange=[0.5,norb], yrange=[10.**-12.,1.]) linez= bovy_plot.bovy_plot(pts/orbt, pdanglezs, color='k',ls='--',overplot=True) legend1= pyplot.legend((liner[0],linez[0]), (r'$\theta_R$', r'$\theta_z$'), loc='lower right',#bbox_to_anchor=(.91,.375), numpoints=2, prop={'size':14}, frameon=False) bovy_plot.bovy_text(r'$\texttt{actionAngleIsochrone}$', top_left=True,size=14.) ax= pyplot.gca() ax.yaxis.set_ticks([10.**-12.,10.**-8.,10.**-4.,1.]) nullfmt = NullFormatter() # no labels ax.xaxis.set_major_formatter(nullfmt) #Same for Spherical pdanglers= parse_break(danglers,tts < breakt) pdanglezs= parse_break(danglezs,tts < breakt) pyplot.subplot(2,1,2) bovy_plot.bovy_plot(ptts/orbt, pdanglers, color='k',ls='-',loglog=True,gcf=True, xrange=[0.5,norb], yrange=[10.**-12.,1.], xlabel=r'$\mathrm{Number\ of\ orbital\ periods}$') bovy_plot.bovy_plot(ptts/orbt, pdanglezs, color='k',ls='--',overplot=True) bovy_plot.bovy_text(r'$\texttt{actionAngleSpherical}$', top_left=True,size=14.) bovy_plot.bovy_text(0.175,10.**4.,r'$\left|\Delta \theta_{R,z} / 2\,\pi\right|$', fontsize=16., rotation='vertical') ax= pyplot.gca() ax.xaxis.set_major_formatter(ticker.FormatStrFormatter(r'$%0.f$')) ax.yaxis.set_ticks([10.**-12.,10.**-8.,10.**-4.,1.]) bovy_plot.bovy_end_print(plotfilename2) return None
def create_frames(basefilename): """Create Frames. Parameters ---------- basefilename : str Returns ------- None """ pot = IsochronePotential(normalize=1.0, b=1.2) aAT = actionAngleIsochrone(ip=pot) bmock = 0.8 aAF = actionAngleIsochrone(b=bmock) o = Orbit([1.0, 0.3, 0.9, 0.2, 1.0, 0.1]) tfac, skip = 10, 1 ndesired = 30 * 25 times = numpy.linspace(0.0, 7.0, tfac * ndesired) * u.Gyr # Subsample otimesIndices = (numpy.arange(len(times)) / float(len(times) - 1))**10 * (len(times) - 2) otimesIndices = numpy.unique(numpy.floor(otimesIndices).astype("int")) if len(otimesIndices) > ndesired: sfac = int(numpy.floor(len(otimesIndices) / float(ndesired))) otimesIndices = otimesIndices[::sfac] otimes = times[otimesIndices] o.integrate(times, pot) # Compute all actions in the wrong potential acfs = aAF.actionsFreqsAngles( o.R(times), o.vR(times), o.vT(times), o.z(times), o.vz(times), o.phi(times), ) js = (acfs[0], acfs[1], acfs[2]) danglerI = ((numpy.roll(acfs[6], -1) - acfs[6]) % (2.0 * numpy.pi))[:-1] jrC = numpy.cumsum(acfs[0][:-1] * danglerI) / numpy.cumsum(danglerI) # And also the actions in the true potential jsT = aAT(o.R(times), o.vR(times), o.vT(times), o.z(times), o.vz(times)) jrT = numpy.median(jsT[0]) * _RO * _VO # --------------------------------------------------------------- # Plotting # Setup gridspec gs = gridspec.GridSpec(1, 3, wspace=0.325, bottom=0.2, left=0.075) # For each time step, plot: orbit, Jr, <Jr> for ii in tqdm(range(len(otimes))): bovy_plot.bovy_print( fig_width=11.2, fig_height=4.0, axes_labelsize=17.0, text_fontsize=12.0, xtick_labelsize=13.0, ytick_labelsize=13.0, ) pyplot.figure() pyplot.subplot(gs[0]) minIndx = otimesIndices[ii] - 100 if minIndx < 0: minIndx = 0 bovy_plot.bovy_plot( [o.x(otimes[ii:ii + 1]) * _RO], [o.z(otimes[ii:ii + 1]) * _RO], "o", ms=15.0, gcf=True, xrange=[-19.0, 19.0], yrange=[-19.0, 19.0], xlabel=r"$X\,(\mathrm{kpc})$", ylabel=r"$z\,(\mathrm{kpc})$", ) if ii > 0: bovy_plot.bovy_plot( o.x(times[minIndx:otimesIndices[ii]:skip]) * _RO, o.z(times[minIndx:otimesIndices[ii]:skip]) * _RO, "-", overplot=True, ) pyplot.subplot(gs[1]) bovy_plot.bovy_plot( [times[otimesIndices[ii]].value], [js[0][otimesIndices[ii]] * _RO * _VO], "o", ms=15.0, gcf=True, xrange=[0.0, 1.0 + times[otimesIndices[ii]].value], yrange=[0.0, 349.0], xlabel=r"$\mathrm{time}\,(\mathrm{Gyr})$", ylabel=r"$J_R\,(\mathrm{kpc\,km\,s}^{-1})$", ) if ii > 0: bovy_plot.bovy_plot( times[:otimesIndices[ii]:skip].value, js[0][:otimesIndices[ii]:skip] * _RO * _VO, "-", overplot=True, ) pyplot.axhline(jrT, ls="--", color="k") pyplot.subplot(gs[2]) bovy_plot.bovy_plot( [otimes[ii].value], [jrC[otimesIndices[ii]] * _RO * _VO], "o", ms=15.0, gcf=True, xrange=[0.0, 1.0 + times[otimesIndices[ii]].value], yrange=[ (otimes[ii] / times[-1])**0.3 * (jrT - 3), 349.0 + (otimes[ii] / times[-1])**0.3 * (jrT + 3 - 349.0), ], xlabel=r"$\mathrm{time}\,(\mathrm{Gyr})$", ylabel=r"$J_R\,(\mathrm{kpc\,km\,s}^{-1})$", ) if ii > 0: bovy_plot.bovy_plot( times[:otimesIndices[ii]:skip].value, jrC[:otimesIndices[ii]:skip] * _RO * _VO, "-", overplot=True, ) pyplot.axhline(jrT, ls="--", color="k") bovy_plot.bovy_end_print(basefilename + "_%05d.png" % ii) return None