Utilities to calculate kinematic distances and kinematic distance uncertainties. See Wenger et al. (2018). An on-line tool which uses this code to compute kinematic distances is available here (http://www.treywenger.com/kd/). If you use this work, please reference https://zenodo.org/record/1166001
flat_rotcurve
rotcurve_kd
and parallax
This package depends on pyqt-fit
, which is apparently no longer
maintained. For the time being, I have forked the repository and am attempting
to keep it working with the latest version of python.
Installation via conda
:
conda create --name kd -c conda-forge "python<3.12" "numpy<2.0.0" scipy matplotlib pip
conda activate kd
# install pyqt-fit with cython support (faster)
pip install git+https://github.com/tvwenger/pyqt-fit.git#egg=pyqt-fit[cython]
# install pyqt-fit without cython support (slower)
pip install git+https://github.com/tvwenger/pyqt-fit.git
# install kd
pip install git+https://github.com/tvwenger/kd.git
N.B. If you install pyqt-fit
with cython support, then you will get a bunch of warning
messages the first time you import pyqt_fit
. These warnings can be safely
ignored.
The script kd_utils.py
includes several functions relevant to computing kinematic distances:
calc_Rgal(glong, glat, dist)
computes the Galactocentric radius for a given Galactic longitude, glong
, latitude, glat
, and distance, dist
calc_az(glong, glat, dist)
computes the Galactocentric azimuth for a given Galactic longitude, glong
, latitude, glat
, and distance, dist
calc_dist(az, Rgal, Z)
computes the distance of a given Galactocentric radius, Rgal
, azimuth, az
, and height above the plane, Z
calc_glong(az, Rgal)
computes the Galactic longitude of a given Galactocentric radius, Rgal
, and azimuth, az
correct_vlsr(glong, glat, vlsr)
computes the corrected LSR velocity given updated solar motion parameters.calc_anderson2012_uncertainty(glong, vlsr)
returns the Anderson et al. (2012) kinematic distance uncertainties.calc_hpd(samples, kdetype)
returns the kernel density estimator (KDE) fit to some samples, as well as the mode (most likely value) and bounds of the minimum width Bayesian Credible Interval (BCI).Each of these functions may be invoked to compute the value at a given position or multiple positions at once:
import numpy as np
from kd import kd_utils
glong = np.array([30.0, 130.0])
glat = np.array([-0.5, 0.5])
dist = np.array([3.0, 5.0])
Rgal = kd_utils.calc_Rgal(glong, glat, dist)
print(Rgal)
# array([ 5.75106815, 11.99190525]) (kpc)
This module includes three rotation curves:
brand_rotcurve.py
)reid14_rotcurve.py
)reid19_rotcurve.py
)flat_rotcurve.py
)These rotation curve scripts, and any new rotation curve scripts you wish to add, must include the following four functions:
params_nominal()
which returns the nominal rotation curve parameters as a dictionaryresample_params(size)
which returns resampled rotation curve parameters as a dictionarycalc_theta(R)
which returns the circular orbital speed, theta
, at a given Galactocentric radius, R
calc_vlsr(glong, glat, dist)
which returns the LSR velocity at a given Galactic longitude, glong
, latitude, glat
, and distance, dist
These scripts may be invoked to compute the circular orbit speed or LSR velocity for a single position or multiple positions at once:
import numpy as np
from kd import reid14_rotcurve
R = np.array([4.0, 6.0])
reid14_rotcurve.calc_theta(R) # array([ 223.40500419, 238.51262935]) (km/s)
glong = np.array([30.0, 130.0])
glat = np.array([-0.5, 0.5])
dist = np.array([3.0, 5.0])
vlsr = reid14_rotcurve.calc_vlsr(glong, glat, dist)
print(vlsr)
# array([ 46.94322475 -58.84833578]) (km/s)
The traditional kinematic distance is derived by finding the minimum difference between the rotation curve LSR velocity and the measured LSR velocity of an object. The script rotcurve_kd.py
computes this traditional kinematic distance. The syntax is
from kd import rotcurve_kd
glong = 30.0 # Galactic longitude, degrees
glat = 1.0 # Galactic latitude, degrees
velo = 20.0 # measured LSR velocity, km/s
velo_tol = 0.1 # tolerance to determine a "match" between rotation curve and measured LSR velocity (km/s)
rotcurve = 'reid14_rotcurve' # the name of the script containing the rotation curve
dist = rotcurve_kd.rotcurve_kd(glong, glat, velo, velo_tol=velo_tol, rotcurve=rotcurve)
print(dist)
# {'Rgal': 7.142123830153435, Galactocentric radius (kpc)
# 'Rtan': 4.170000007367579, Galactocentric radius of the tangent point (kpc)
# 'near': 1.4249999999999998, Near kinematic distance (kpc)
# 'far': 13.023, Far kinematic distance (kpc)
# 'tangent': 7.224, Distance of the tangent point (kpc)
# 'vlsr_tangent': 105.15736451845413} LSR velocity of the tangent point (km/s)
The returned value is a dictionary, which can be accessed like print(dist['near'])
.
The Monte Carlo kinematic distance is derived by resampling the measured LSR velocity and rotation curve parameters within their uncertainties. The script pdf_kd.py
computes the Monte Carlo kinematic distance. The syntax is
from kd import pdf_kd
glong = 30.0 # Galactic longitude, degrees
glat = 1.0 # Galactic latitude, degrees
velo = 20.0 # measured LSR velocity, km/s
velo_err = 5.0 # measured LSR velocity uncertainty, km/s
rotcurve = 'reid14_rotcurve' # the name of the script containing the rotation curve
num_samples = 10000 # number of re-samples
dist = pdf_kd.pdf_kd(glong, glat, velo, velo_err=velo_err, rotcurve=rotcurve, num_samples=num_samples)
print(dist)
# {'Rgal': 7.1124726106671012, Galactocentric radius (kpc)
# 'Rgal_err_neg': 0.27321259042889601, Galactocentric radius uncertainty toward the Galactic Center (kpc)
# 'Rgal_err_pos': 0.34151573803611868, Galactocentric radius uncertainty away from the Galactic Center (kpc)
# 'Rgal_kde': <pyqt_fit.kde.KDE1D at 0x7fc41ee2fa90>, Kernel Density Estimator (KDE) fit to the Rgal probability distribution function (PDF)
# 'Rtan': 4.1813677581628541, Galactocentric radius of the tangent point (kpc)
# 'Rtan_err_neg': 0.090269992563094092, Uncertainty toward the Galactic Center (kpc)
# 'Rtan_err_pos': 0.067702494422319681, Uncertainty away from the Galactic Center (kpc)
# 'Rtan_kde': <pyqt_fit.kde.KDE1D at 0x7fc41ee2fa58>, KDE fit to the Rtan PDF
# 'far': 12.977444444444433, Far kinematic distance (kpc)
# 'far_err_neg': 0.3764848484848482, Uncertainty toward the Sun (kpc)
# 'far_err_pos': 0.47060606060606069, Uncertainty away from the Sun (kpc)
# 'far_kde': <pyqt_fit.kde.KDE1D at 0x7fc41ee2f898>, KDE fit to the far PDF
# 'near': 1.4793636363636349, Near kinematic distance (kpc)
# 'near_err_neg': 0.40581818181818141, Uncertainty toward the Sun (kpc)
# 'near_err_pos': 0.30436363636363617, Uncertainty away from the Sun (kpc)
# 'near_kde': <pyqt_fit.kde.KDE1D at 0x7fc41ee2fcc0>, KDE fit to the near PDF
# 'tangent': 7.2519999999999936, Distance of the tangent point (kpc)
# 'tangent_err_neg': 0.16622222222222227, Uncertainty toward the Sun (kpc)
# 'tangent_err_pos': 0.10755555555555496, Uncertainty away from the Sun (kpc)
# 'tangent_kde': <pyqt_fit.kde.KDE1D at 0x7fc41ee2f6d8>, KDE fit to the tangent PDF
# 'vlsr_tangent': 103.2468359294412, LSR velocity of the tangent point (km/s)
# 'vlsr_tangent_err_neg': 7.8548626921567717, Uncertainty toward negative LSR velocity (km/s)
# 'vlsr_tangent_err_pos': 12.084404141779657, Uncertainty toward positive LSR velocity (km/s)
# 'vlsr_tangent_kde': <scipy.stats.kde.gaussian_kde at 0x7fc41ee2f828>} KDE fit to vlsr_tangent PDF
The returned value is a dictionary, which can be accessed like print(dist['near'])
.