def modelLikelihood(self, params): ''' Compute the likelihood of model (df+potential specified by scaled params) against the data (array of Nx6 position/velocity coordinates of tracer particles). This is the function to be maximized; if parameters are outside the allowed range, it returns -infinity ''' prior = self.model.prior(params) if prior == -numpy.inf: print "Out of range" return prior try: # Compute log-likelihood of DF with given params against an array of actions pot = self.model.createPotential(params) df = self.model.createDF(params) if phase_space_info_mode == 6: # actions of tracer particles if self.particles.shape[ 0] > 2000: # create an action finder object for a faster evaluation actions = agama.ActionFinder(pot)(self.particles) else: actions = agama.actions(self.particles, pot) df_val = df(actions) # values of DF for these actions else: # have full phase space info for resampled input particles (missing components are filled in) af = agama.ActionFinder(pot) actions = af( self.samples) # actions of resampled tracer particles # compute values of DF for these actions, multiplied by sample weights df_val = df(actions) * self.weights # compute the weighted sum of likelihoods of all samples for a single particle, # replacing the improbable samples (with NaN as likelihood) with zeroes df_val = numpy.sum(numpy.nan_to_num( df_val.reshape(-1, num_subsamples)), axis=1) loglike = numpy.sum(numpy.log(df_val)) if numpy.isnan(loglike): loglike = -numpy.inf loglike += prior print "LogL=%.8g" % loglike return loglike except ValueError as err: print "Exception ", err return -numpy.inf
def modelLikelihood(self, params): ''' Compute the likelihood of model (df+potential specified by scaled params) against the data (array of Nx6 position/velocity coordinates of tracer particles). This is the function to be maximized; if parameters are outside the allowed range, it returns -infinity ''' prior = self.model.prior(params) if prior == -numpy.inf: print "Out of range" return prior try: # Compute log-likelihood of DF with given params against an array of actions pot = self.model.createPotential(params) df = self.model.createDF(params) if phase_space_info_mode == 6: # actions of tracer particles if self.particles.shape[0] > 2000: # create an action finder object for a faster evaluation actions = agama.ActionFinder(pot)(self.particles) else: actions = agama.actions(self.particles, pot) df_val = df(actions) # values of DF for these actions else: # have full phase space info for resampled input particles (missing components are filled in) af = agama.ActionFinder(pot) actions = af(self.samples) # actions of resampled tracer particles # compute values of DF for these actions, multiplied by sample weights df_val = df(actions) * self.weights # compute the weighted sum of likelihoods of all samples for a single particle, # replacing the improbable samples (with NaN as likelihood) with zeroes df_val = numpy.sum(numpy.nan_to_num(df_val.reshape(-1, num_subsamples)), axis=1) loglike = numpy.sum( numpy.log( df_val ) ) if numpy.isnan(loglike): loglike = -numpy.inf loglike += prior print "LogL=%.8g" % loglike return loglike except ValueError as err: print "Exception ", err return -numpy.inf
def compare(ic, inttime, numsteps): g_orb_obj = galpy.orbit.Orbit([ic[0],ic[3],ic[5],ic[1],ic[4],ic[2]]) times = numpy.linspace(0, inttime, numsteps) dt = time.time() g_orb_obj.integrate(times, g_pot) g_orb = g_orb_obj.getOrbit() print 'Time to integrate orbit in galpy: %s s' % (time.time()-dt) dt = time.time() c_orb_car = agama.orbit(ic=[ic[0],0,ic[1],ic[3],ic[5],ic[4]], pot=w_pot._pot, time=inttime, step=inttime/numsteps) print 'Time to integrate orbit in Agama: %s s' % (time.time()-dt) times_c = numpy.linspace(0,inttime,len(c_orb_car[:,0])) ### make it compatible with galpy's convention (native output is in cartesian coordinates) c_orb = c_orb_car*1.0 c_orb[:,0] = (c_orb_car[:,0]**2+c_orb_car[:,1]**2)**0.5 c_orb[:,3] = c_orb_car[:,2] ### in galpy, this is the only tool that can estimate interfocal distance, ### but it requires the orbit to be computed first delta = estimateDeltaStaeckel(g_orb[:,0], g_orb[:,3], pot=g_pot) print "interfocal distance Delta=",delta ### plot the orbit(s) in R,z plane, along with the prolate spheroidal coordinate grid plt.axes([0.05, 0.55, 0.45, 0.45]) plotCoords(delta, 1.5) plt.plot(g_orb[:,0],g_orb[:,3], 'b', label='galpy') # R,z plt.plot(c_orb[:,0],c_orb[:,3], 'g', label='Agama') # R,z plt.xlabel("R/8kpc") plt.ylabel("z/8kpc") plt.xlim(0, 1.2) plt.ylim(-1,1) plt.legend() ### plot R(t), z(t) plt.axes([0.55, 0.55, 0.45, 0.45]) plt.plot(times, g_orb[:,0], label='R') plt.plot(times, g_orb[:,3], label='z') plt.xlabel("t") plt.ylabel("R,z") plt.legend() plt.xlim(0,50) ### create galpy action/angle finder for the given value of Delta ### note: using c=False in the routine below is much slower but apparently more accurate, ### comparable to the Agama for the same value of delta g_actfinder = galpy.actionAngle.actionAngleStaeckel(pot=g_pot, delta=delta, c=True) ### find the actions for each point of the orbit dt = time.time() g_act = g_actfinder(g_orb[:,0],g_orb[:,1],g_orb[:,2],g_orb[:,3],g_orb[:,4],fixed_quad=True) print 'Time to compute actions in galpy: %s s' % (time.time()-dt) ### use the Agama action routine for the same value of Delta as in galpy dt = time.time() c_act = agama.actions(point=c_orb_car, pot=w_pot._pot, ifd=delta) # explicitly specify interfocal distance print 'Time to compute actions in Agama: %s s' % (time.time()-dt) ### use the Agama action finder (initialized at the beginning) that automatically determines the best value of Delta dt = time.time() a_act = c_actfinder(c_orb_car) # use the interfocal distance estimated by action finder print 'Time to compute actions in Agama: %s s' % (time.time()-dt) ### plot Jr vs Jz plt.axes([0.05, 0.05, 0.45, 0.45]) plt.plot(g_act[0],g_act[2], label='galpy') plt.plot(c_act[:,0],c_act[:,1], label=r'Agama,$\Delta='+str(delta)+'$') plt.plot(a_act[:,0],a_act[:,1], label=r'Agama,$\Delta=$auto') plt.xlabel("$J_r$") plt.ylabel("$J_z$") plt.legend() ### plot Jr(t) and Jz(t) plt.axes([0.55, 0.05, 0.45, 0.45]) plt.plot(times, g_act[0], label='galpy', c='b') plt.plot(times, g_act[2], c='b') plt.plot(times_c, c_act[:,0], label='Agama,$\Delta='+str(delta)+'$', c='g') plt.plot(times_c, c_act[:,1], c='g') plt.plot(times_c, a_act[:,0], label='Agama,$\Delta=$auto', c='r') plt.plot(times_c, a_act[:,1], c='r') plt.text(0, c_act[0,0], '$J_r$', fontsize=16) plt.text(0, c_act[0,1], '$J_z$', fontsize=16) plt.xlabel("t") plt.ylabel("$J_r, J_z$") plt.legend(loc='center right') plt.xlim(0,50) plt.show()
def compare(ic, inttime, numsteps): g_orb_obj = galpy.orbit.Orbit([ic[0],ic[3],ic[5],ic[1],ic[4],ic[2]]) times = numpy.linspace(0, inttime, numsteps) dt = time.time() g_orb_obj.integrate(times, g_pot) g_orb = g_orb_obj.getOrbit() print 'Time to integrate orbit in galpy: %s s' % (time.time()-dt) dt = time.time() times_c, c_orb_car = agama.orbit(ic=[ic[0],0,ic[1],ic[3],ic[5],ic[4]], potential=w_pot._pot, time=inttime, trajsize=numsteps) print 'Time to integrate orbit in Agama: %s s' % (time.time()-dt) ### make it compatible with galpy's convention (native output is in cartesian coordinates) c_orb = c_orb_car*1.0 c_orb[:,0] = (c_orb_car[:,0]**2+c_orb_car[:,1]**2)**0.5 c_orb[:,3] = c_orb_car[:,2] ### in galpy, this is the only tool that can estimate focal distance, ### but it requires the orbit to be computed first delta = estimateDeltaStaeckel(g_pot, g_orb[:,0], g_orb[:,3]) print "interfocal distance Delta=",delta ### plot the orbit(s) in R,z plane, along with the prolate spheroidal coordinate grid plt.axes([0.05, 0.55, 0.45, 0.45]) plotCoords(delta, 1.5) plt.plot(g_orb[:,0],g_orb[:,3], 'b', label='galpy') # R,z plt.plot(c_orb[:,0],c_orb[:,3], 'g', label='Agama') # R,z plt.xlabel("R/8kpc") plt.ylabel("z/8kpc") plt.xlim(0, 1.2) plt.ylim(-1,1) plt.legend() ### plot R(t), z(t) plt.axes([0.55, 0.55, 0.45, 0.45]) plt.plot(times, g_orb[:,0], label='R') plt.plot(times, g_orb[:,3], label='z') plt.xlabel("t") plt.ylabel("R,z") plt.legend() plt.xlim(0,50) ### create galpy action/angle finder for the given value of Delta ### note: using c=False in the routine below is much slower but apparently more accurate, ### comparable to the Agama for the same value of delta g_actfinder = galpy.actionAngle.actionAngleStaeckel(pot=g_pot, delta=delta, c=True) ### find the actions for each point of the orbit dt = time.time() g_act = g_actfinder(g_orb[:,0],g_orb[:,1],g_orb[:,2],g_orb[:,3],g_orb[:,4],fixed_quad=True) print 'Time to compute actions in galpy: %s s' % (time.time()-dt) ### use the Agama action routine for the same value of Delta as in galpy dt = time.time() c_act = agama.actions(point=c_orb_car, potential=w_pot._pot, fd=delta) # explicitly specify focal distance print 'Time to compute actions in Agama using Galpy-estimated focal distance: %s s' % (time.time()-dt) ### use the Agama action finder (initialized at the beginning) that automatically determines the best value of Delta dt = time.time() a_act = c_actfinder(c_orb_car) # use the focal distance estimated by action finder print 'Time to compute actions in Agama using pre-initialized focal distance: %s s' % (time.time()-dt) ### use the interpolated Agama action finder (initialized at the beginning) - less accurate but faster dt = time.time() i_act = i_actfinder(c_orb_car) print 'Time to compute actions in Agama with interpolated action finder: %s s' % (time.time()-dt) ### plot Jr vs Jz plt.axes([0.05, 0.05, 0.45, 0.45]) plt.plot(g_act[0],g_act[2], label='galpy') plt.plot(c_act[:,0],c_act[:,1], label=r'Agama,$\Delta='+str(delta)+'$') plt.plot(a_act[:,0],a_act[:,1], label=r'Agama,$\Delta=$auto') plt.plot(i_act[:,0],i_act[:,1], label=r'Agama,interpolated') plt.xlabel("$J_r$") plt.ylabel("$J_z$") plt.legend(loc='lower left') ### plot Jr(t) and Jz(t) plt.axes([0.55, 0.05, 0.45, 0.45]) plt.plot(times, g_act[0], label='galpy', c='b') plt.plot(times, g_act[2], c='b') plt.plot(times_c, c_act[:,0], label='Agama,$\Delta='+str(delta)+'$', c='g') plt.plot(times_c, c_act[:,1], c='g') plt.plot(times_c, a_act[:,0], label='Agama,$\Delta=$auto', c='r') plt.plot(times_c, a_act[:,1], c='r') plt.plot(times_c, i_act[:,0], label='Agama,interpolated', c='c') plt.plot(times_c, i_act[:,1], c='c') plt.text(0, c_act[0,0], '$J_r$', fontsize=16) plt.text(0, c_act[0,1], '$J_z$', fontsize=16) plt.xlabel("t") plt.ylabel("$J_r, J_z$") plt.legend(loc='center right') plt.ylim(0.14,0.25) plt.xlim(0,50) plt.show()
def compare(ic, inttime, numsteps): times = numpy.linspace(0, inttime, numsteps) ### integrate the orbit in galpy using MWPotential2014 from galpy g_orb_obj = galpy.orbit.Orbit([ic[0], ic[3], ic[5], ic[1], ic[4], ic[2]]) dt = time.time() g_orb_obj.integrate(times, g_pot) g_orb = g_orb_obj.getOrbit() print('Time to integrate orbit in galpy: %.4g s' % (time.time() - dt)) ### integrate the orbit with the galpy routine, but using Agama potential instead ### (much slower because of repeated transfer of control between C++ and Python dt = time.time() g_orb_obj.integrate(times[:numsteps // 10], a_pot) a_orb = g_orb_obj.getOrbit() print( 'Time to integrate 1/10th of the orbit in galpy using Agama potential: %.4g s' % (time.time() - dt)) ### integrate the same orbit (note different calling conventions - cartesian coordinates as input) ### using both the orbit integration routine and the potential from Agama - much faster dt = time.time() times_c, c_orb_car = agama.orbit(ic=[ic[0],0,ic[1],ic[3],ic[5],ic[4]], \ potential=a_pot, time=inttime, trajsize=numsteps) print('Time to integrate orbit in Agama: %.4g s' % (time.time() - dt)) ### make it compatible with galpy's convention (native output is in cartesian coordinates) c_orb = c_orb_car * 1.0 c_orb[:, 0] = (c_orb_car[:, 0]**2 + c_orb_car[:, 1]**2)**0.5 c_orb[:, 3] = c_orb_car[:, 2] ### in galpy, this is the only tool that can estimate focal distance, ### but it requires the orbit to be computed first delta = float( galpy.actionAngle.estimateDeltaStaeckel(g_pot, g_orb[:, 0], g_orb[:, 3])) print('Focal distance estimated from the entire trajectory: Delta=%.4g' % delta) ### plot the orbit(s) in R,z plane, along with the prolate spheroidal coordinate grid plt.figure(figsize=(12, 8)) plt.axes([0.04, 0.54, 0.45, 0.45]) plotCoords(delta, 1.5) plt.plot(g_orb[:, 0], g_orb[:, 3], 'b', label='galpy') # R,z plt.plot(c_orb[:, 0], c_orb[:, 3], 'g', label='Agama') plt.plot(a_orb[:, 0], a_orb[:, 3], 'r', label='galpy using Agama potential') plt.xlabel("R/8kpc") plt.ylabel("z/8kpc") plt.xlim(0, 1.2) plt.ylim(-1, 1) plt.legend(loc='lower left', frameon=False) ### create galpy action/angle finder for the given value of Delta ### note: using c=False in the routine below is much slower but apparently more accurate, ### comparable to the Agama for the same value of delta g_actfinder = galpy.actionAngle.actionAngleStaeckel(pot=g_pot, delta=delta, c=True) ### find the actions for each point of the orbit using galpy action finder dt = time.time() g_act = g_actfinder(g_orb[:, 0], g_orb[:, 1], g_orb[:, 2], g_orb[:, 3], g_orb[:, 4], fixed_quad=True) print('Time to compute actions in galpy: %.4g s' % (time.time() - dt)) print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \ (numpy.mean(g_act[0]), numpy.std(g_act[0]), numpy.mean(g_act[2]), numpy.std(g_act[2]))) ### use the Agama action routine for the same value of Delta as in galpy - ### the result is almost identical but computed much faster dt = time.time() c_act = agama.actions(point=c_orb_car, potential=a_pot, fd=delta) # explicitly specify focal distance print( 'Time to compute actions in Agama using Galpy-estimated focal distance: %.4g s' % (time.time() - dt)) print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \ (numpy.mean(c_act[:,0]), numpy.std(c_act[:,0]), numpy.mean(c_act[:,1]), numpy.std(c_act[:,1]))) ### use the Agama action finder (initialized at the beginning) that automatically determines ### the best value of Delta (same computational cost as the previous one) dt = time.time() a_act = a_actfinder( c_orb_car) # use the focal distance estimated by action finder print( 'Time to compute actions in Agama using pre-initialized focal distance: %.4g s' % (time.time() - dt)) print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \ (numpy.mean(a_act[:,0]), numpy.std(a_act[:,0]), numpy.mean(a_act[:,1]), numpy.std(a_act[:,1]))) ### use the interpolated Agama action finder (initialized at the beginning) - less accurate but faster dt = time.time() i_act = i_actfinder(c_orb_car) print( 'Time to compute actions in Agama with interpolated action finder: %.4g s' % (time.time() - dt)) print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \ (numpy.mean(i_act[:,0]), numpy.std(i_act[:,0]), numpy.mean(i_act[:,1]), numpy.std(i_act[:,1]))) ### plot Jr vs Jz plt.axes([0.54, 0.54, 0.45, 0.45]) plt.plot(g_act[0], g_act[2], c='b', label='galpy') plt.plot(c_act[:, 0], c_act[:, 1], c='g', label=r'Agama,$\Delta=%.4f$' % delta) plt.plot(a_act[:, 0], a_act[:, 1], c='r', label=r'Agama,$\Delta=$auto') plt.plot(i_act[:, 0], i_act[:, 1], c='c', label=r'Agama,interpolated') plt.xlabel("$J_r$") plt.ylabel("$J_z$") plt.legend(loc='lower left', frameon=False) ### plot Jr(t) and Jz(t) plt.axes([0.04, 0.04, 0.95, 0.45]) plt.plot(times, g_act[0], c='b', label='galpy') plt.plot(times, g_act[2], c='b') plt.plot(times_c, c_act[:, 0], c='g', label='Agama,$\Delta=%.4f$' % delta) plt.plot(times_c, c_act[:, 1], c='g') plt.plot(times_c, a_act[:, 0], c='r', label='Agama,$\Delta=$auto') plt.plot(times_c, a_act[:, 1], c='r') plt.plot(times_c, i_act[:, 0], c='c', label='Agama,interpolated') plt.plot(times_c, i_act[:, 1], c='c') plt.text(0, c_act[0, 0], '$J_r$', fontsize=16) plt.text(0, c_act[0, 1], '$J_z$', fontsize=16) plt.xlabel("t") plt.ylabel("$J_r, J_z$") plt.legend(loc='center right', ncol=2, frameon=False) #plt.ylim(0.14,0.25) plt.xlim(0, 50) plt.show()
def compare(ic, inttime, numsteps): times = numpy.linspace(0, inttime, numsteps) times1 = times[:numsteps // 10] # compute only 1/10th of the orbit to save time in galpy ### integrate the orbit in galpy using the native MWPotential2014 from galpy g_orb_obj = galpy.orbit.Orbit(ic) dt = time.time() g_orb_obj.integrate(times, g_pot_native) g_orb_g_native = g_orb_obj.getOrbit() print( 'Time to integrate the orbit in galpy, using galpy-native potential [1]: %.4g s' % (time.time() - dt)) ### integrate the orbit again with the galpy routine, but now using the chimera potential ### representing a galpy-native underlying potential. ### since galpy has no idea that this potential has a C implementation, it switches to a slower ### pure-Python integration algorithm, so to save time, we compute only 1/10th of the orbit dt = time.time() g_orb_obj.integrate(times1, g_pot_hybrid) g_orb_g_hybrid = g_orb_obj.getOrbit() print( 'Time to integrate 1/10th of the orbit in galpy, using galpy-hybrid potential [2]: %.4g s' % (time.time() - dt)) ### integrate the orbit with the galpy routine, but using the chimera potential ### representing an agama-native underlying potential instead ### (also much slower because of repeated transfer of control between C++ and Python) dt = time.time() g_orb_obj.integrate(times1, a_pot_hybrid) g_orb_a_hybrid = g_orb_obj.getOrbit() print( 'Time to integrate 1/10th of the orbit in galpy, using agama-hybrid potential [3]: %.4g s' % (time.time() - dt)) ### integrate the orbit with the agama routine, using the galpy-native potential through the chimera ### (note different calling conventions and the use of cartesian coordinates) dt = time.time() a_orb_g_hybrid = agama.orbit(potential=g_pot_hybrid, time=inttime, trajsize=numsteps, ic=toCar(ic))[1] print( 'Time to integrate the orbit in agama, using galpy-hybrid potential [4]: %.4g s' % (time.time() - dt)) ### integrate the orbit in a native agama potential approximation constructed from the galpy potential dt = time.time() a_orb_g_approx = agama.orbit(potential=g_pot_approx, time=inttime, trajsize=numsteps, ic=toCar(ic))[1] print( 'Time to integrate the orbit in agama, using galpy-approx potential [5]: %.4g s' % (time.time() - dt)) ### using both the orbit integration routine and the native potential from agama - much faster dt = time.time() a_orb_a_native = agama.orbit(potential=a_pot_native, time=inttime, trajsize=numsteps, ic=toCar(ic))[1] print( 'Time to integrate the orbit in agama, using agama-native potential [6]: %.4g s' % (time.time() - dt)) ### the same but with the chimera potential representing an agama-native potential ### (should be identical to the above, since in both cases the same underlying C++ object is used) dt = time.time() a_orb_a_hybrid = agama.orbit(potential=a_pot_hybrid, time=inttime, trajsize=numsteps, ic=toCar(ic))[1] print( 'Time to integrate the orbit in agama, using agama-hybrid potential [7]: %.4g s' % (time.time() - dt)) ### compare the differences between the orbits computed in different ways ### (both the potentials and integration routines are not exactly equivalent); ### use only common initial segment (1/10th of the orbit) for comparison print('Differences between orbits: ' + '[1]-[2]=%g, ' % numpy.max( numpy.abs(toCar(g_orb_g_native[:len(times1)]) - toCar(g_orb_g_hybrid)) ) + '[1]-[3]=%g, ' % numpy.max( numpy.abs(toCar(g_orb_g_native[:len(times1)]) - toCar(g_orb_a_hybrid))) + '[1]-[4]=%g, ' % numpy.max( numpy.abs(toCar(g_orb_g_native) - a_orb_g_hybrid)[:len(times1)]) + '[1]-[5]=%g, ' % numpy.max( numpy.abs(toCar(g_orb_g_native) - a_orb_g_approx)[:len(times1)]) + '[1]-[6]=%g, ' % numpy.max( numpy.abs(toCar(g_orb_g_native) - a_orb_a_native)[:len(times1)]) + '[6]-[4]=%g, ' % numpy.max(numpy.abs(a_orb_a_native - a_orb_g_hybrid)[:len(times1)]) + '[6]-[7]=%g' % numpy.max(numpy.abs(a_orb_a_native - a_orb_a_hybrid)[:len(times1)]) ) # should be zero ### convert the orbits to the same galpy coordinate convention gg_orb = g_orb_g_native # it's already in this convention ga_orb = g_orb_a_hybrid ag_orb = toCyl(a_orb_g_hybrid) aa_orb = toCyl(a_orb_a_native) ### in galpy, this is the only tool that can estimate focal distance, ### but it requires the orbit to be computed first delta = float( galpy.actionAngle.estimateDeltaStaeckel(g_pot_hybrid, gg_orb[:, 0], gg_orb[:, 3])) print('Focal distance estimated from the entire trajectory: Delta=%.4g' % delta) ### plot the orbit(s) in R,z plane, along with the prolate spheroidal coordinate grid plt.figure(figsize=(12, 8)) plt.axes([0.06, 0.56, 0.43, 0.43]) plotCoords(delta, 1.5) plt.plot(gg_orb[:, 0], gg_orb[:, 3], 'b', label='galpy native') # R,z plt.plot(aa_orb[:, 0], aa_orb[:, 3], 'g', label='agama native', dashes=[4, 2]) plt.plot(ag_orb[:, 0], ag_orb[:, 3], 'y', label='agama using galpy potential', dashes=[1, 1]) plt.plot(ga_orb[:, 0], ga_orb[:, 3], 'r', label='galpy using agama potential') plt.xlabel("R/8kpc") plt.ylabel("z/8kpc") plt.xlim(0, 1.2) plt.ylim(-1, 1) plt.legend(loc='lower left', ncol=2) ### create galpy action/angle finder for the given value of Delta ### note: using c=False in the routine below is much slower but apparently more accurate, ### comparable to the agama for the same value of delta g_actfinder = galpy.actionAngle.actionAngleStaeckel(pot=g_pot_native, delta=delta, c=True) ### find the actions for each point of the orbit using galpy action finder dt = time.time() g_act = g_actfinder(gg_orb[:, 0], gg_orb[:, 1], gg_orb[:, 2], gg_orb[:, 3], gg_orb[:, 4], fixed_quad=True) print('Time to compute actions in galpy: %.4g s' % (time.time() - dt)) print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \ (numpy.mean(g_act[0]), numpy.std(g_act[0]), numpy.mean(g_act[2]), numpy.std(g_act[2]))) ### use the agama action routine for the same value of Delta as in galpy (explicity specify focal distance): ### the result is almost identical but computed much faster dt = time.time() c_act = agama.actions(point=a_orb_a_hybrid, potential=a_pot_hybrid, fd=delta) print( 'Time to compute actions in agama using galpy-estimated focal distance: %.4g s' % (time.time() - dt)) print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \ (numpy.mean(c_act[:,0]), numpy.std(c_act[:,0]), numpy.mean(c_act[:,1]), numpy.std(c_act[:,1]))) ### use the agama action finder (initialized at the beginning) that automatically determines ### the best value of Delta (same computational cost as the previous one) dt = time.time() a_act = a_actfinder( a_orb_a_hybrid) # use the focal distance estimated by action finder print( 'Time to compute actions in agama using pre-initialized focal distance: %.4g s' % (time.time() - dt)) print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \ (numpy.mean(a_act[:,0]), numpy.std(a_act[:,0]), numpy.mean(a_act[:,1]), numpy.std(a_act[:,1]))) ### use the interpolated agama action finder (initialized at the beginning) - less accurate but faster dt = time.time() i_act = i_actfinder(a_orb_a_hybrid) print( 'Time to compute actions in agama with interpolated action finder: %.4g s' % (time.time() - dt)) print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \ (numpy.mean(i_act[:,0]), numpy.std(i_act[:,0]), numpy.mean(i_act[:,1]), numpy.std(i_act[:,1]))) ### plot Jr vs Jz plt.axes([0.55, 0.56, 0.43, 0.43]) plt.plot(g_act[0], g_act[2], c='b', label='galpy') plt.plot(c_act[:, 0], c_act[:, 1], c='g', label=r'agama, $\Delta=%.4f$' % delta, dashes=[4, 2]) plt.plot(a_act[:, 0], a_act[:, 1], c='r', label=r'agama, $\Delta=$auto') plt.plot(i_act[:, 0], i_act[:, 1], c='c', label=r'agama, interpolated') plt.xlabel("$J_r$") plt.ylabel("$J_z$") plt.legend(loc='lower left', frameon=False) ### plot Jr(t) and Jz(t) plt.axes([0.06, 0.06, 0.92, 0.43]) plt.plot(times, g_act[0], c='b', label='galpy') plt.plot(times, g_act[2], c='b') plt.plot(times, c_act[:, 0], c='g', label='agama, $\Delta=%.4f$' % delta, dashes=[4, 2]) plt.plot(times, c_act[:, 1], c='g', dashes=[4, 2]) plt.plot(times, a_act[:, 0], c='r', label='agama, $\Delta=$auto') plt.plot(times, a_act[:, 1], c='r') plt.plot(times, i_act[:, 0], c='c', label='agama, interpolated') plt.plot(times, i_act[:, 1], c='c') plt.text(0, c_act[0, 0], '$J_r$', fontsize=16) plt.text(0, c_act[0, 1], '$J_z$', fontsize=16) plt.xlabel("t") plt.ylabel("$J_r, J_z$") plt.legend(loc='center right', ncol=2, frameon=False) #plt.ylim(0.14,0.25) plt.xlim(0, 50) plt.show()