Python for Astronomy

AstroPy

何勃亮
中国科学院国家天文台 中国虚拟天文台 (China-VO)

AstroPy 项目

首先区分两个概念,Astropy Projectastropy 包,前者是一个宏大的计划,后者则特指前者的核心软件包。

Astropy Projectastropy核心包和附属包组成。

Astropy Project项目自2011年开始发起,得到了多个国家的研究单位的支持,并且以开源社区的模式运行,目前的最新版本是v1.2。项目网站 http://www.astropy.org

AstroPy 核心

AstroPy 核心包由一系列的基础组件组成,比如核心数据结构与算法、文件与数据I/O单位、天文计算与工具以及软件开发配置相关等。

核心数据结构与算法

  • 天文常数 astropy.constants
  • 单位与数量 astropy.units
  • N维数据集 astropy.nddata
  • 数据表格 astropy.table
  • 时间与日期 astropy.time
  • 天文坐标系统 astropy.coordinates
  • 世界坐标系统 astropy.wcs
  • 模型与拟合 astropy.modeling
  • 数据分析程序 astropy.analytic_functions

文件与数据 I/O

  • 通用文件读写接口
  • FITS 文件操作 astropy.io.fits
  • ASCII 表格操作 astropy.io.ascii
  • VOTable 文件操作 astropy.io.votable
  • I/O 杂项 astropy.io.misc

天文计算与工具

  • 卷积与滤波 astropy.convolution
  • 数据可视化 astropy.visualization
  • 宇宙学计算 astropy.cosmology
  • 天文统计学工具 astropy.stats
  • 虚拟天文台访问工具 astropy.vo

软件开发配置相关

  • 配置系统 astropy.config
  • I/O注册 astropy.io.registry
  • 日志系统
  • Python 告警系统
  • AstroPy 核心包工具集 astropy.utils
  • AstroPy 测试助手 astropy.tests.helper

AstroPy 附属包

AstroPy成员包是指遵循 AstroPy开发、互操作和接口标准规范的一系列附属包,这些包有些是有一定历史的软件包,还有一些是在 AstroPy 基础上新开发出来的软件包,适合在不同场景下使用。在 http://www.astropy.org/affiliated/ 可以查阅完整的附属包目录。

In [9]:
import astropy

天文常数

AstroPy天文常数包:astropy.constants

常数值列表

名称 单位 描述
G $6.67384 \times 10^{-11}$ $m^3 kg^{-1} s^{-2}$ 重力常数
L_sun $3.846 \times 10^{26}$ $W$ 太阳光度
M_earth $5.9742 \times 10^{24}$ $kg$ 地球质量
M_jup $1.8987 \times 10^{27}$ $kg$ 木星质量
M_sun $1.9891 \times 10^{30}$ $kg$ 太阳质量
N_A $6.02214129 \times 10^{23}$ ${mol}^{-1}$ 阿伏伽德罗常数
R $8.3144621$ $JK^{-1}{mol}^{-1}$ 气体常数
R_earth $6378136$ $m$ 地球赤道半径
R_jup $71492000$ $m$ 木星赤道半径
R_sun $695508000$ $m$ 太阳赤道半径
Ryd $10973731.6$ $m^{-1}$ 里德伯常数 Rydberg constant
a0 $5.29177211 \times 10^{-11}$ $m$ 玻尔半径 Bohr radius
alpha $0.00729735257$ 精细结构常数
atmosphere $101325$ $Pa$ 大气压
au $1.49597871 \times 10^{11}$ $m$ 天文单位
b_wien $0.0028977721$ $mK$ 维恩位移定律常数
c $299792458$ $ms^{-1}$ 真空光速
e $1.60217657 \times 10^{-19}$ $C$ 电子电荷
eps0 $8.85418782 \times 10^{-12}$ $Fm^{-1}$ 介电常数
g0 $9.80665$ $ms^{-2}$ 标准重力加速度
h $6.62606957 \times 10^{-34}$ $J s$ 普朗克常数
hbar $1.05457173 \times 10^{-34}$ $J s$ 约化普朗克常数
k_B $1.3806488 \times 10^{-23}$ $J K^{-1}$ 玻尔兹曼常数
kpc $3.08567758 \times 10^{19}$ $m$ 千秒差距
m_e $9.10938291 \times 10^{-31}$ $kg$ 电子质量
m_n $1.67492735 \times 10^{-27}$ $kg$ 中子质量
m_p $1.67262178 \times 10^{-27}$ $kg$ 质子质量
mu0 $1.25663706 \times 10^{-6}$ $N A^{-2}$ 磁性常数
muB $9.27400968 \times 10^{-24}$ $J T^{-1}$ 玻尔磁子
pc $3.08567758 \times 10^{16}$ $m$ 秒差距
sigma_T $6.65245873 \times 10^{-29}$ $m^2$ 汤姆逊散射截面
sigma_sb $5.670373 \times 10^{-8}$ $WK^{-4}m^{-2}$ 斯蒂芬 - 玻尔兹曼常数
u $1.66053892 \times 10^{-27}$ $kg$ 原子质量单位

简单使用:

In [5]:
from astropy.constants import M_earth, M_sun, R_earth, R_sun
In [6]:
M_sun / M_earth
Out[6]:
$332948.34 \; \mathrm{}$
In [7]:
R_sun / R_earth
Out[7]:
$109.04565 \; \mathrm{}$
In [8]:
print(M_earth)
  Name   = Earth mass
  Value  = 5.9742e+24
  Uncertainty  = 5e+19
  Unit  = kg
  Reference = Allen's Astrophysical Quantities 4th Ed.
In [10]:
print(M_earth.cgs) # cgs格式

# 关于`Quantity`将在`astropy.units`中介绍,`constants`包搭配`unit`包,可以进行一些基本的计算转换。
5.9742e+27 g

Unit

AstroPy Unitastropy.units

astropy.units定义物理量的单位,并可实现物理量的一些转换,比如KMScgs的转换等。

  • astropy.units.si SI Unit
  • astropy.units.cgs CGS Unit
  • astropy.units.astrophys 天体物理相关单位
  • astropy.units.function.units
  • astropy.units.imperial
  • astropy.units.cds CDS format unit
  • astropy.units.equivalencies 一组标准的天文等价公式
In [10]:
from astropy import units as u

Quantity

In [18]:
k = 100 * u.AU

type(k)
Out[18]:
astropy.units.quantity.Quantity
In [19]:
k.value, k.unit
Out[19]:
(100.0, Unit("AU"))
In [24]:
# 单位转化

k.to(u.km)
Out[24]:
$1.4959787 \times 10^{10} \; \mathrm{km}$
In [20]:
15.1 * u.meter / (32.0 * u.second) 
Out[20]:
$0.471875 \; \mathrm{\frac{m}{s}}$
In [21]:
3.0 * u.kilometer / (130.51 * u.meter / u.second)  
Out[21]:
$0.022986744 \; \mathrm{\frac{km\,s}{m}}$
In [22]:
(3.0 * u.kilometer / (130.51 * u.meter / u.second)).decompose() 
Out[22]:
$22.986744 \; \mathrm{s}$
In [25]:
# 自定义单位,并进行转换

from astropy.units import imperial

cms = u.cm / u.s

mph = imperial.mile / u.hour

q = 42.0 * cms

q.to(mph)
Out[25]:
$0.93951324 \; \mathrm{\frac{mi}{h}}$
In [26]:
# 分析量纲

(u.s ** -1).compose() 
Out[26]:
[Unit("Bq"), Unit("Hz"), Unit("2.7027e-11 Ci")]
In [29]:
# SI , CGS

k.si, k.cgs
Out[29]:
(<Quantity 14959787070000.0 m>, <Quantity 1495978707000000.0 cm>)
In [30]:
# 天文学等价公式

(1000 * u.nm).to(u.Hz)
---------------------------------------------------------------------------
UnitConversionError                       Traceback (most recent call last)
<ipython-input-30-65e17937747d> in <module>()
      1 # 天文学等价公式
      2 
----> 3 (1000 * u.nm).to(u.Hz)

/usr/local/lib/python3.5/site-packages/astropy/units/quantity.py in to(self, unit, equivalencies)
    651         unit = Unit(unit)
    652         new_val = self.unit.to(unit, self.view(np.ndarray),
--> 653                                equivalencies=equivalencies)
    654         return self._new_view(new_val, unit)
    655 

/usr/local/lib/python3.5/site-packages/astropy/units/core.py in to(self, other, value, equivalencies)
    987             If units are inconsistent
    988         """
--> 989         return self._get_converter(other, equivalencies=equivalencies)(value)
    990 
    991     def in_units(self, other, value=1.0, equivalencies=[]):

/usr/local/lib/python3.5/site-packages/astropy/units/core.py in _get_converter(self, other, equivalencies)
    889                             pass
    890 
--> 891             raise exc
    892 
    893     @deprecated('1.0')

/usr/local/lib/python3.5/site-packages/astropy/units/core.py in _get_converter(self, other, equivalencies)
    875         try:
    876             return self._apply_equivalencies(
--> 877                 self, other, self._normalize_equivalencies(equivalencies))
    878         except UnitsError as exc:
    879             # Last hope: maybe other knows how to do it?

/usr/local/lib/python3.5/site-packages/astropy/units/core.py in _apply_equivalencies(self, unit, other, equivalencies)
    859         raise UnitConversionError(
    860             "{0} and {1} are not convertible".format(
--> 861                 unit_str, other_str))
    862 
    863     def _get_converter(self, other, equivalencies=[]):

UnitConversionError: 'nm' (length) and 'Hz' (frequency) are not convertible
In [31]:
 (1000 * u.nm).to(u.Hz, equivalencies=u.spectral())
Out[31]:
$2.9979246 \times 10^{14} \; \mathrm{Hz}$
In [32]:
# 格式化

q = 15.1 * u.meter / (32.0 * u.second)

"{0.value:0.03f} {0.unit:FITS}".format(q)
Out[32]:
'0.472 m s-1'

N-dimensional datasets (astropy.nddata

numpyndarray类似,是对其的一个针对天文学应该的高级包装。

In [3]:
from astropy.nddata import NDData

array = np.zeros((12, 12, 12))

ndd1 = NDData(array)

ndd1
Out[3]:
NDData([[[ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         ..., 
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.]],

        [[ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         ..., 
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.]],

        [[ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         ..., 
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.]],

        ..., 
        [[ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         ..., 
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.]],

        [[ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         ..., 
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.]],

        [[ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         ..., 
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.],
         [ 0.,  0.,  0., ...,  0.,  0.,  0.]]])
In [5]:
ndd1.meta
Out[5]:
OrderedDict()
In [6]:
ndd1.unit
In [7]:
ndd1.uncertainty
In [8]:
ndd1.wcs
In [11]:
ndd = NDData([1, 2, 3, 4], unit="meter")
ndd.unit
Out[11]:
$\mathrm{m}$
In [12]:
ndd.meta['exposure_time'] = 340.

ndd.meta
Out[12]:
OrderedDict([('exposure_time', 340.0)])

Time

from astropy.time import Time

In [13]:
from astropy.time import Time
In [14]:
times = ['2016-01-01T00:00:00.123456789', '2015-01-01T00:00:00']

t = Time(times, format='isot', scale='utc')

t
Out[14]:
<Time object: scale='utc' format='isot' value=['2016-01-01T00:00:00.123' '2015-01-01T00:00:00.000']>

Format

Format Class Example argument
byear TimeBesselianEpoch 1950.0
byear_str TimeBesselianEpochString ‘B1950.0’
cxcsec TimeCxcSec 63072064.184
datetime TimeDatetime datetime(2000, 1, 2, 12, 0, 0)
decimalyear TimeDecimalYear 2000.45
fits TimeFITS ‘2000-01-01T00:00:00.000(TAI)’
gps TimeGPS 630720013.0
iso TimeISO ‘2000-01-01 00:00:00.000’
isot TimeISOT ‘2000-01-01T00:00:00.000’
jd TimeJD 2451544.5
jyear TimeJulianEpoch 2000.0
jyear_str TimeJulianEpochString ‘J2000.0’
mjd TimeMJD 51544.0
plot_date TimePlotDate 730120.0003703703
unix TimeUnix 946684800.0
yday TimeYearDayTime 2000:001:00:00:00.000
In [18]:
from datetime import datetime

time2 = datetime.now()

t = Time(time2, format='datetime', scale='utc')
In [19]:
t
Out[19]:
<Time object: scale='utc' format='datetime' value=2016-06-28 06:55:07.811364>
In [27]:
t = Time.now()
t
Out[27]:
<Time object: scale='utc' format='datetime' value=2016-06-27 23:00:00.794208>
In [20]:
t.iso
Out[20]:
'2016-06-28 06:55:07.811'
In [21]:
t.jd
Out[21]:
2457567.7882848536
In [22]:
t.mjd
Out[22]:
57567.28828485375
In [23]:
t.yday
Out[23]:
'2016:180:06:55:07.811'
In [24]:
t.byear
Out[24]:
2016.4911253597104
In [25]:
t.format
Out[25]:
'datetime'
In [26]:
t.format = 'mjd'
t
Out[26]:
<Time object: scale='utc' format='mjd' value=57567.28828485375>

Time Scale (Time standard)

Scale Description
tai International Atomic Time (TAI)
tcb Barycentric Coordinate Time (TCB)
tcg Geocentric Coordinate Time (TCG)
tdb Barycentric Dynamical Time (TDB)
tt Terrestrial Time (TT)
ut1 Universal Time (UT1)
utc Coordinated Universal Time (UTC)