Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
jobovy committed Jan 7, 2018
2 parents b89e52f + 8ea0570 commit a8945d3
Show file tree
Hide file tree
Showing 39 changed files with 2,874 additions and 436 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -84,7 +84,7 @@ after_success:
- lcov --capture --base-directory . --directory build/temp.linux-x86_64-2.7/galpy/ --no-external --output-file coverage_full.info
- lcov --remove coverage_full.info 'galpy/actionAngle_src/actionAngleTorus_c_ext/torus/*' -o coverage.info
# Codecov
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then bash <(curl -s https://codecov.io/bash); fi
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then bash <(curl -s https://codecov.io/bash) -X gcov; fi
# coveralls: combine, generate json, and upload
- coveralls-lcov -v -n coverage.info > coverage.c.json
- coveralls-merge coverage.c.json
Expand Down
16 changes: 16 additions & 0 deletions HISTORY.txt
@@ -1,6 +1,12 @@
v1.3 (2017-XX-XX)
==================

- Added a fast and precise method for approximating an orbit's
eccentricity, peri- and apocenter radii, and maximum height above
the midplane using the Staeckel approximation (see Mackereth & Bovy
2018); available as an actionAngle method EccZmaxRperiRap and for
Orbit instances through the e, rperi, rap, and zmax methods.

- Added support for potential wrappers---classes that wrap existing
potentials to modify their behavior (#307). See the documentation on
potentials and the potential API for more information on these.
Expand Down Expand Up @@ -52,6 +58,16 @@ v1.3 (2017-XX-XX)
which the radial dependence of the potential changes from R^p to
R^-p; also added C implementation of CosmphiDiskPotential.

- Changed default method for computing actions, frequencies, and
angles for Orbit instances to be the Staeckel approximation with an
automatically-estimated delta parameter.

- Generalized actionAngleStaeckel to allow for different focal lengths
delta for different phase-space points. Also allowed the order of
the Gauss-Legendre integration to be specified (default: 10, which
is good enough when using actionAngleStaeckel to compute approximate
actions etc. for an axisymmetric potential).

- Allow transformations of (ra,dec) and (pmra,pmdec) to custom
coordinate systems.

Expand Down
27 changes: 17 additions & 10 deletions doc/source/actionAngle.rst
@@ -1,3 +1,5 @@
.. _actionangle:

Action-angle coordinates
=========================

Expand Down Expand Up @@ -379,6 +381,8 @@ vertical action to approximately five percent.
.. WARNING::
Frequencies and angles using the adiabatic approximation are not implemented at this time.

.. _actionanglestaeckel:

Action-angle coordinates using the Staeckel approximation
-----------------------------------------------------------

Expand Down Expand Up @@ -839,29 +843,32 @@ instance
>>> from galpy.potential import MWPotential2014
>>> o= Orbit([1.,0.1,1.1,0.,0.25,0.])

and we can then calculate the actions (default is to use the adiabatic
approximation)
and we can then calculate the actions (default is to use the staeckel
approximation with an automatically-estimated delta parameter, but
this can be adjusted)

>>> o.jr(MWPotential2014), o.jp(MWPotential2014), o.jz(MWPotential2014)
# (0.01685643005901713, 1.1, 0.015897730620467752)
# (0.018194068808944613,1.1,0.01540155584446606)

``o.jp`` here gives the azimuthal action (which is the *z* component
of the angular momentum for axisymmetric potentials). We can also use
the other methods described above, but note that these require extra
parameters related to the approximation to be specified (see above):
the other methods described above or adjust the parameters of the
approximation (see above):

>>> o.jr(MWPotential2014,type='staeckel',delta=0.4), o.jp(MWPotential2014,type='staeckel',delta=0.4), o.jz(MWPotential2014,type='staeckel',delta=0.4)
# (array([ 0.01922167]), array([ 1.1]), array([ 0.01527683]))
# (0.019221672966336707, 1.1, 0.015276825017286827)
>>> o.jr(MWPotential2014,type='adiabatic'), o.jp(MWPotential2014,type='adiabatic'), o.jz(MWPotential2014,type='adiabatic')
# (0.016856430059017123, 1.1, 0.015897730620467752)
>>> o.jr(MWPotential2014,type='isochroneApprox',b=0.8), o.jp(MWPotential2014,type='isochroneApprox',b=0.8), o.jz(MWPotential2014,type='isochroneApprox',b=0.8)
# (array([ 0.01906609]), array([ 1.1]), array([ 0.01528049]))
# (0.019066091295488922, 1.1, 0.015280492319332751)

These two methods give very precise actions for this orbit (both are
converged to about 1%) and they agree very well

>>> (o.jr(MWPotential2014,type='staeckel',delta=0.4)-o.jr(MWPotential2014,type='isochroneApprox',b=0.8))/o.jr(MWPotential2014,type='isochroneApprox',b=0.8)
# array([ 0.00816012])
>>> (o.jz(MWPotential2014,type='staeckel',delta=0.4)-o.jz(MWPotential2014,type='isochroneApprox',b=0.8))/o.jz(MWPotential2014,type='isochroneApprox',b=0.8)
# array([-0.00024])
# 0.00816012408818143
>>> (o.jz(MWPotential2014,type='staeckel',delta=0.4)-o.jz(MWPotential2014,type='isochroneApprox',b=0.8))/o.jz(MWPotential2014,type='isochroneApprox',b=0.8)
# 0.00023999894566772273

.. WARNING:: Once an action, frequency, or angle is calculated for a given type of calculation (e.g., staeckel), the parameters for that type are fixed in the Orbit instance. Call o.resetaA() to reset the action-angle instance used when using different parameters (i.e., different ``delta=`` for staeckel or different ``b=`` for isochroneApprox.

Expand Down
191 changes: 191 additions & 0 deletions doc/source/examples/dierickx_eccentricities.py
@@ -0,0 +1,191 @@
import os, os.path
import subprocess
from astropy.io import fits, ascii
from astropy import units
import numpy as np
from optparse import OptionParser
import sys
import tempfile
from ftplib import FTP
import shutil
import pickle
from tqdm import tqdm
from galpy.potential import LogarithmicHaloPotential
from galpy.potential import evaluatePotentials as evalPot
from galpy.orbit import Orbit
from galpy.actionAngle import estimateDeltaStaeckel, actionAngleStaeckel, UnboundError
from galpy.util import bovy_coords
import matplotlib.pyplot as plt
import numpy

_ERASESTR= " "

def calc_eccentricity(args, options):
table = os.path.join(args[0],'table2.dat')
readme = os.path.join(args[0],'ReadMe')
dierickx = ascii.read(table, readme=readme)
vxvv = np.dstack([dierickx['RAdeg'], dierickx['DEdeg'], dierickx['Dist']/1e3, dierickx['pmRA'], dierickx['pmDE'], dierickx['HRV']])[0]
ro, vo, zo = 8., 220., 0.025
ra, dec= vxvv[:,0], vxvv[:,1]
lb= bovy_coords.radec_to_lb(ra,dec,degree=True)
pmra, pmdec= vxvv[:,3], vxvv[:,4]
pmllpmbb= bovy_coords.pmrapmdec_to_pmllpmbb(pmra,pmdec,ra,dec,degree=True)
d, vlos= vxvv[:,2], vxvv[:,5]
rectgal= bovy_coords.sphergal_to_rectgal(lb[:,0],lb[:,1],d,vlos,pmllpmbb[:,0], pmllpmbb[:,1],degree=True)
vsolar= np.array([-10.1,4.0,6.7])
vsun= np.array([0.,1.,0.,])+vsolar/vo
X = rectgal[:,0]/ro
Y = rectgal[:,1]/ro
Z = rectgal[:,2]/ro
vx = rectgal[:,3]/vo
vy = rectgal[:,4]/vo
vz = rectgal[:,5]/vo
vsun= np.array([0.,1.,0.,])+vsolar/vo
Rphiz= bovy_coords.XYZ_to_galcencyl(X,Y,Z,Zsun=zo/ro)
vRvTvz= bovy_coords.vxvyvz_to_galcencyl(vx,vy,vz,Rphiz[:,0],Rphiz[:,1],Rphiz[:,2],vsun=vsun,Xsun=1.,Zsun=zo/ro,galcen=True)
#do the integration and individual analytic estimate for each object
ts= np.linspace(0.,20.,10000)
lp= LogarithmicHaloPotential(normalize=1.)
e_ana = numpy.zeros(len(vxvv))
e_int = numpy.zeros(len(vxvv))
print('Performing orbit integration and analytic parameter estimates for Dierickx et al. sample...')
for i in tqdm(range(len(vxvv))):
try:
orbit = Orbit(vxvv[i], radec=True, vo=220., ro=8.)
e_ana[i] = orbit.e(analytic=True, pot=lp, c=True)
except UnboundError:
e_ana[i] = np.nan
orbit.integrate(ts, lp)
e_int[i] = orbit.e(analytic=False)
fig = plt.figure()
fig.set_size_inches(1.5*columnwidth, 1.5*columnwidth)
plt.scatter(e_int, e_ana, s=1, color='Black', lw=0.)
plt.xlabel(r'$\mathrm{galpy\ integrated}\ e$')
plt.ylabel(r'$\mathrm{galpy\ analytic}\ e$')
plt.xlim(0.,1.)
plt.ylim(0.,1.)
fig.tight_layout()
plt.savefig(os.path.join(args[0],'dierickx-integratedeanalytice.png'), format='png', dpi=200)
fig = plt.figure()
fig.set_size_inches(1.5*columnwidth, 1.5*columnwidth)
plt.hist(e_int, bins=30)
plt.xlim(0.,1.)
plt.xlabel(r'$\mathrm{galpy}\ e$')
fig.tight_layout()
plt.savefig(os.path.join(args[0], 'dierickx-integratedehist.png'), format='png', dpi=200)
fig = plt.figure()
fig.set_size_inches(1.5*columnwidth, 1.5*columnwidth)
plt.scatter(dierickx['e'], e_int, s=1, color='Black', lw=0.)
plt.xlabel(r'$\mathrm{Dierickx\ et\ al.}\ e$')
plt.ylabel(r'$\mathrm{galpy\ integrated}\ e$')
plt.xlim(0.,1.)
plt.ylim(0.,1.)
fig.tight_layout()
plt.savefig(os.path.join(args[0],'dierickx-integratedee.png'), format='png', dpi=200)
fig = plt.figure()
fig.set_size_inches(1.5*columnwidth, 1.5*columnwidth)
plt.scatter(dierickx['e'], e_ana, s=1, color='Black', lw=0.)
plt.xlabel(r'$\mathrm{Dierickx\ et\ al.}\ e$')
plt.ylabel(r'$\mathrm{galpy\ estimated}\ e$')
plt.xlim(0.,1.)
plt.ylim(0.,1.)
fig.tight_layout()
plt.savefig(os.path.join(args[0],'dierickx-analyticee.png'), format='png', dpi=200)
arr = numpy.recarray(len(e_ana), dtype=[('analytic_e', float), ('integrated_e', float)])
arr['analytic_e'] = e_ana
arr['integrated_e'] = e_int
with open(os.path.join(args[0],'eccentricities.dat'), 'w') as file:
pickle.dump(arr, file)
file.close()

def get_table(args,options):
cat = 'J/ApJ/725/L186/'
tab2name = 'table2.dat.gz'
tab2readme = 'ReadMe'
out = args[0]
ensure_dir(os.path.join(out,tab2name))
vizier(cat, os.path.join(out,tab2name), os.path.join(out,tab2readme), catalogname=tab2name, readmename=tab2readme)
subprocess.call(['gunzip', os.path.join(out,tab2name)])

def vizier(cat,filePath,ReadMePath,
catalogname='catalog.dat',readmename='ReadMe'):
"""
NAME:
vizier
PURPOSE:
download a catalog and its associated ReadMe from Vizier
INPUT:
cat - name of the catalog (e.g., 'III/272' for RAVE, or J/A+A/... for journal-specific catalogs)
filePath - path of the file where you want to store the catalog (note: you need to keep the name of the file the same as the catalogname to be able to read the file with astropy.io.ascii)
ReadMePath - path of the file where you want to store the ReadMe file
catalogname= (catalog.dat) name of the catalog on the Vizier server
readmename= (ReadMe) name of the ReadMe file on the Vizier server
OUTPUT:
(nothing, just downloads)
HISTORY:
2016-09-12 - Written - Bovy (UofT)
"""
_download_file_vizier(cat,filePath,catalogname=catalogname)
_download_file_vizier(cat,ReadMePath,catalogname=readmename)
return None


def _download_file_vizier(cat,filePath,catalogname='catalog.dat'):
'''
Stolen from Jo Bovy's gaia_tools package!
'''
sys.stdout.write('\r'+"Downloading file %s ...\r" \
% (os.path.basename(filePath)))
sys.stdout.flush()
try:
# make all intermediate directories
os.makedirs(os.path.dirname(filePath))
except OSError: pass
# Safe way of downloading
downloading= True
interrupted= False
file, tmp_savefilename= tempfile.mkstemp()
os.close(file) #Easier this way
ntries= 1
while downloading:
try:
ftp= FTP('cdsarc.u-strasbg.fr')
ftp.login('anonymous', 'test')
ftp.cwd(os.path.join('pub','cats',cat))
with open(tmp_savefilename,'wb') as savefile:
ftp.retrbinary('RETR %s' % catalogname,savefile.write)
shutil.move(tmp_savefilename,filePath)
downloading= False
if interrupted:
raise KeyboardInterrupt
except:
raise
if not downloading: #Assume KeyboardInterrupt
raise
elif ntries > _MAX_NTRIES:
raise IOError('File %s does not appear to exist on the server ...' % (os.path.basename(filePath)))
finally:
if os.path.exists(tmp_savefilename):
os.remove(tmp_savefilename)
ntries+= 1
sys.stdout.write('\r'+_ERASESTR+'\r')
sys.stdout.flush()
return None

def ensure_dir(f):
""" Ensure a a file exists and if not make the relevant path """
d = os.path.dirname(f)
if not os.path.exists(d):
os.makedirs(d)

def get_options():
#no options yet - probably none needed?
usage = "usage: %prog [options] <outpath>"
parser = OptionParser(usage=usage)
return parser

if __name__ == '__main__':
parser = get_options()
options, args= parser.parse_args()
get_table(args,options)
calc_eccentricity(args, options)
Binary file added doc/source/images/dierickx-analyticee.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/source/images/dierickx-integratedee.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/source/images/dierickx-integratedehist.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/source/images/lp-orbit-integration-et.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion doc/source/index.rst
Expand Up @@ -237,10 +237,16 @@ The following is a list of publications using ``galpy``; please let me (bovy at
Uses ``galpy.orbit`` integration in ``MWPotential2014`` to investigate the orbit and its uncertainty of 2MASS J151113.24–213003.0, an extremely metal-poor field star with measureable r-process abundances, and of other similar metal-poor stars. The authors find that all of these stars are on highly eccentric orbits, possibly indicating that they originated in dwarf galaxies.
#. *The Gaia-ESO Survey: Churning through the Milky Way*, M. R. Hayden, A. Recio-Blanco, P. de Laverny, et al. (2017) *Astron. & Astrophys.*, in press (`arXiv/1711.05751 <http://arxiv.org/abs/1711.05751>`_):
Employs ``galpy.orbit`` integration in ``MWPotential2014`` to study the orbital characteristics (eccentricity, pericentric radius) of a sample of 2,364 stars observed in the Milky Way as part of the Gaia-ESO survey.
#. *The Evolution of the Galactic Thick Disk with the LAMOST Survey*, Chengdong Li & Gang Zhao (2017) *Astrophys. J.*, **850**, 25s (`2017ApJ...850...25L <http://adsabs.harvard.edu/abs/2017ApJ...850...25L>`_):
#. *The Evolution of the Galactic Thick Disk with the LAMOST Survey*, Chengdong Li & Gang Zhao (2017) *Astrophys. J.*, **850**, 25 (`2017ApJ...850...25L <http://adsabs.harvard.edu/abs/2017ApJ...850...25L>`_):
Uses ``galpy.orbit`` integration in ``MWPotential2014`` to investigate the orbital characteristics (eccentricity, maximum height above the plane, angular momentum) of a sample of about 2,000 stars in the thicker-disk component of the Milky Way.
#. *The Orbit and Origin of the Ultra-faint Dwarf Galaxy Segue 1*, T. K. Fritz, M. Lokken, N. Kallivayalil, A. Wetzel, S. T. Linden, P. Zivick, & E. J. Tollerud (2017) *Astrophys. J.*, submitted (`arXiv/1711.09097 <http://arxiv.org/abs/1711.09097>`_):
Employs ``galpy.orbit`` integration in ``MWPotential2014`` and a version of this potential with a more massive dark-matter halo to investigate the orbit and origin of the dwarf-spheroidal galaxy Segue 1 using a newly measured proper motion with SDSS and LBC data.
#. *Prospects for detection of hypervelocity stars with Gaia*, T. Marchetti, O. Contigiani, E. M. Rossi, J. G. Albert, A. G. A. Brown, & A. Sesana (2017) *Mon. Not. Roy. Astron. Soc.*, submitted (`arXiv/1711.11397 <http://arxiv.org/abs/1711.11397>`_):
Uses ``galpy.orbit`` integration in a custom Milky-Way-like potential built from ``galpy.potential`` models to create mock catalogs of hypervelocity stars in the Milky Way for different ejection mechanisms and study the prospects of their detection with *Gaia*.
#. *The AMBRE project: The thick thin disk and thin thick disk of the Milky Way*, Hayden, M. R., Recio-Blanco, A., de Laverny, P., Mikolaitis, S., & Worley, C. C. (2017) *Astron. & Astrophys.*, **608**, L1 (`arXiv/1712.02358 <http://arxiv.org/abs/1712.02358>`_):
Employs ``galpy.orbit`` integration in ``MWPotential2014`` to characterize the orbits of 494 nearby stars analyzed as part of the AMBRE project to learn about their distribution within the Milky Way.
#. *KELT-21b: A Hot Jupiter Transiting the Rapidly-Rotating Metal-Poor Late-A Primary of a Likely Hierarchical Triple System*, Marshall C. Johnson, Joseph E. Rodriguez, George Zhou, et al. (2017) *Astrophys. J.*, submitted (`arXiv/1712.03241 <http://arxiv.org/abs/1712.03241>`_):
Uses ``galpy.orbit`` integration in ``MWPotential2014`` to investigate the Galactic orbit of KELT-21b, a hot jupiter around a low-metallicity A-type star.


Indices and tables
Expand Down

0 comments on commit a8945d3

Please sign in to comment.