Python 天文计算库 ephem 使用
引言
ephem
是一个强大的 Python 天文计算库,专门用于计算各种天体的位置、天文现象以及进行相关的天文计算。它基于美国海军天文台(USNO)的算法,提供了高精度的天文计算功能。
ephem
的主要特点包括:
计算太阳、月亮、行星等天体的精确位置
确定日出、日落、月出、月落等时间
计算月相、日食、月食等天文现象
支持多种坐标系统转换
提供恒星和深空天体的位置计算
轻量级且易于使用
本教程将详细介绍 ephem
库的各种功能和用法,从基础概念到高级应用,帮助您掌握这个强大的天文计算工具。
安装与基本使用
安装
ephem
可以通过 pip 轻松安装:
pip install ephem
对于某些系统,可能需要使用以下命令:
python -m pip install ephem
基本导入
使用 ephem
前,首先需要导入库:
import ephem
第一个示例
让我们从一个简单的例子开始,计算当前日期的太阳位置:
import ephem
import datetime# 创建观察者对象(默认位置)
observer = ephem.Observer()# 设置观察者为当前时间和地点(默认为格林尼治时间)
observer.date = datetime.datetime.now()# 创建太阳对象
sun = ephem.Sun()# 计算太阳位置
sun.compute(observer)# 打印结果
print(f"太阳的赤经: {sun.ra}")
print(f"太阳的赤纬: {sun.dec}")
print(f"太阳的方位角: {sun.az}")
print(f"太阳的高度角: {sun.alt}")
这个简单的例子展示了 ephem
的基本用法:创建观察者对象,设置日期,创建天体对象,计算位置,然后获取各种天文数据。
观察者(Observer)对象
观察者对象是 ephem
中的核心概念之一,它代表了一个特定的观测位置和时间。通过设置观察者的属性,我们可以模拟在地球上任何地点、任何时间的观测条件。
创建观察者
创建观察者非常简单:
observer = ephem.Observer()
主要属性
观察者对象有许多可以设置的属性,主要包括:
位置相关属性:
lat
: 纬度(字符串,如 '39.9' 或 '39.900442')lon
: 经度(字符串,如 '116.4' 或 '116.407408')elevation
: 海拔高度(米)horizon
: 地平线角度(默认为 '-0:34',约 0.5667 度)
时间相关属性:
date
: 观测日期和时间epoch
: 计算使用的历元
其他属性:
temp
: 温度(摄氏度,默认 20°C)pressure
: 气压(毫巴,默认 1010 mb)horizon
: 地平线仰角(影响日出日落计算)
设置位置
# 设置北京的位置
beijing = ephem.Observer()
beijing.lat = '39.9042' # 纬度
beijing.lon = '116.4074' # 经度
beijing.elevation = 43 # 海拔高度(米)
设置时间
from datetime import datetime, timedelta# 设置为当前时间
beijing.date = datetime.now()# 设置为特定日期和时间
specific_time = datetime(2023, 6, 21, 12, 0, 0) # 2023年6月21日中午12点
beijing.date = specific_time# 设置为未来的某个时间(例如明天)
tomorrow = datetime.now() + timedelta(days=1)
beijing.date = tomorrow
设置观测条件
# 设置温度和气压(影响大气折射计算)
beijing.temp = 15 # 15摄氏度
beijing.pressure = 1013 # 1013毫巴# 设置地平线角度(影响日出日落计算)
# 默认是 '-0:34',约 0.5667 度
# 对于天文观测,可以使用更高的地平线(如 '-6' 度)
beijing.horizon = '-6'
获取计算结果的时间
# 获取计算后的时间(已转换为当地时区)
local_date = beijing.date
print(f"计算时间: {local_date}")
观察者对象是连接实际观测条件和天文计算的桥梁。通过正确设置观察者的位置、时间和环境条件,我们可以获得准确的计算结果。
天体对象
ephem
提供了多种预定义的天体对象,包括太阳系内的主要天体以及一些常用的恒星。这些对象代表了真实的天体,我们可以计算它们在特定时间和地点的位置。
预定义的天体
ephem
包含以下主要预定义天体:
太阳系天体:
ephem.Sun()
- 太阳ephem.Moon()
- 月亮ephem.Mercury()
- 水星ephem.Venus()
- 金星ephem.Mars()
- 火星ephem.Jupiter()
- 木星ephem.Saturn()
- 土星ephem.Uranus()
- 天王星ephem.Neptune()
- 海王星ephem.Pluto()
- 冥王星
恒星和深空天体:
ephem.Star()
- 自定义恒星一些常用恒星也有预定义对象(通过名称访问)
创建天体对象
创建天体对象非常简单,只需调用相应的构造函数:
sun = ephem.Sun()
moon = ephem.Moon()
mars = ephem.Mars()
jupiter = ephem.Jupiter()
计算天体位置
要计算天体在特定观察者和时间的位置,需要调用 compute()
方法:
# 创建观察者(例如北京)
beijing = ephem.Observer()
beijing.lat = '39.9042'
beijing.lon = '116.4074'
beijing.date = datetime.now()# 计算太阳位置
sun = ephem.Sun()
sun.compute(beijing)# 获取位置信息
print(f"太阳赤经: {sun.ra}")
print(f"太阳赤纬: {sun.dec}")
print(f"太阳方位角: {sun.az}")
print(f"太阳高度角: {sun.alt}")
主要位置属性
计算后,天体对象包含多个属性,提供其在天球上的位置信息:
赤道坐标:
ra
: 赤经 (Right Ascension),单位为弧度或时角dec
: 赤纬 (Declination),单位为弧度ra_str
: 赤经的字符串表示dec_str
: 赤纬的字符串表示
地平坐标:
az
: 方位角 (Azimuth),从北向东测量,单位为弧度alt
: 高度角 (Altitude),从地平线向上测量,单位为弧度
距离:
EarthDistance
: 到地球的距离(天文单位 AU)SunDistance
: 到太阳的距离(天文单位 AU)(对行星有用)其他距离属性取决于具体天体
其他属性:
mag
: 星等(亮度)radius
: 角半径(对于太阳和月亮)phase
: 月相(对于月亮)
坐标单位
ephem
中的角度通常以弧度表示。如果需要更易读的格式,可以使用以下方法转换:
# 将弧度转换为度
import mathaltitude_deg = math.degrees(sun.alt)
azimuth_deg = math.degrees(sun.az)print(f"太阳高度角: {altitude_deg:.2f}°")
print(f"太阳方位角: {azimuth_deg:.2f}°")# 赤经和赤纬也可以转换为字符串
print(f"太阳赤经: {sun.ra_str}")
print(f"太阳赤纬: {sun.dec_str}")
自定义恒星
除了预定义的天体,您还可以创建自定义恒星:
# 创建自定义恒星
vega = ephem.readdb("Vega,f|V|A0,18:36:56.34,38:47:01.29,0.03,2000")
vega.compute(beijing)print(f"织女星赤经: {vega.ra}")
print(f"织女星赤纬: {vega.dec}")
print(f"织女星方位角: {vega.az}")
print(f"织女星高度角: {vega.alt}")
readdb()
函数允许您使用类似星表中的格式定义恒星。
日期与时间处理
在 ephem
中,日期和时间的处理是非常重要的,因为所有天文计算都依赖于准确的时间和地点信息。
日期格式
ephem
使用自己的日期格式,但可以很好地与 Python 的 datetime
对象交互。
设置日期:
from datetime import datetimeobserver = ephem.Observer()# 使用 datetime 对象 now = datetime.now() observer.date = now# 使用字符串 observer.date = '2023/06/21 12:00:00'# 使用 ephem.Date 对象 specific_date = ephem.Date('2023/06/21 12:00:00') observer.date = specific_date
获取日期:
current_date = observer.date print(current_date) # 输出为 ephem.Date 对象# 转换为字符串 print(str(current_date))# 转换为 datetime 对象 import datetime dt = datetime.datetime.strptime(str(current_date), '%Y/%m/%d %H:%M:%S')
ephem.Date
对象
ephem.Date
是 ephem
库中用于处理日期和时间的特殊类。它基于儒略日(Julian Date),但提供了更友好的接口。
创建
ephem.Date
对象:d1 = ephem.Date('2023/06/21 12:00:00') # 字符串格式 d2 = ephem.Date(datetime.datetime.now()) # datetime 对象 d3 = ephem.Date(2460123.5) # 儒略日
日期运算:
# 加减天数 tomorrow = observer.date + 1 yesterday = observer.date - 1# 加减小时 in_6_hours = observer.date + 6/24
获取儒略日:
julian_date = float(observer.date) print(f"儒略日: {julian_date}")
时间格式转换
ephem
日期对象可以轻松转换为各种格式:
转换为字符串:
date_str = str(observer.date) print(date_str) # 格式如 '2023/06/21 12:00:00'
转换为 datetime 对象:
import datetimedate_str = str(observer.date) dt = datetime.datetime.strptime(date_str, '%Y/%m/%d %H:%M:%S') print(dt)
获取各个时间部分:
year = observer.date.datetime().year month = observer.date.datetime().month day = observer.date.datetime().day hour = observer.date.datetime().hour minute = observer.date.datetime().minute second = observer.date.datetime().secondprint(f"{year}-{month}-{day} {hour}:{minute}:{second}")
时区处理
ephem
默认使用 UTC 时间,但通过观察者对象可以处理本地时间:
import datetime
import pytz# 设置本地时区(例如北京时区)
beijing_tz = pytz.timezone('Asia/Shanghai')
local_now = datetime.datetime.now(beijing_tz)# 创建观察者并设置日期
observer = ephem.Observer()
observer.date = local_now# 注意:ephem 内部会将时间转换为 UTC 进行计算
# 但观察者的 date 属性会根据您设置的本地时间进行调整
需要注意的是,ephem
在内部使用 UTC 进行所有计算,但通过正确设置观察者的日期,可以确保计算对应于所需的本地时间。
计算天体位置
计算天体在特定时间和地点的位置是 ephem
最基本也是最重要的功能。通过观察者对象和天体对象的结合,我们可以获得精确的天体位置信息。
基本计算流程
计算天体位置的基本步骤如下:
创建观察者对象并设置其位置和时间
创建天体对象
调用天体对象的
compute()
方法,传入观察者对象从天体对象中获取位置信息
import ephem
from datetime import datetime# 1. 创建观察者并设置位置和时间
observer = ephem.Observer()
observer.lat = '39.9042' # 北京纬度
observer.lon = '116.4074' # 北京经度
observer.date = datetime.now() # 当前时间# 2. 创建天体对象(以太阳为例)
sun = ephem.Sun()# 3. 计算太阳位置
sun.compute(observer)# 4. 获取位置信息
print(f"赤经 (RA): {sun.ra}")
print(f"赤纬 (Dec): {sun.dec}")
print(f"方位角 (Az): {sun.az}")
print(f"高度角 (Alt): {sun.alt}")# 转换为更可读的格式
import math
print(f"赤经 (时:分:秒): {ephem.hours(sun.ra)}")
print(f"赤纬 (度:分:秒): {ephem.degrees(sun.dec)}")
print(f"方位角 (度): {math.degrees(sun.az):.2f}°")
print(f"高度角 (度): {math.degrees(sun.alt):.2f}°")
位置属性详解
计算后,天体对象包含多个属性,提供不同坐标系下的位置信息:
赤道坐标系 (Equatorial Coordinates):
ra
: 赤经 (Right Ascension),单位为弧度dec
: 赤纬 (Declination),单位为弧度ra_str
: 赤经的字符串表示(如 '13:45:23.2')dec_str
: 赤纬的字符串表示(如 '+10:30:45.0')
地平坐标系 (Horizontal Coordinates):
az
: 方位角 (Azimuth),从北向东测量,单位为弧度alt
: 高度角 (Altitude),从地平线向上测量,单位为弧度
其他坐标和属性:
azstr
: 方位角的字符串表示altstr
: 高度角的字符串表示EarthDistance
: 到地球的距离(天文单位 AU)SunDistance
: 到太阳的距离(天文单位 AU)(对行星有用)mag
: 星等(亮度)
坐标转换与格式化
由于 ephem
中的角度以弧度表示,我们通常需要将其转换为更易读的格式:
import math# 将弧度转换为度
altitude_deg = math.degrees(sun.alt)
azimuth_deg = math.degrees(sun.az)print(f"高度角: {altitude_deg:.2f}°")
print(f"方位角: {azimuth_deg:.2f}°")# 将赤经和赤纬转换为时:分:秒和度:分:秒格式
print(f"赤经: {ephem.hours(sun.ra)}")
print(f"赤纬: {ephem.degrees(sun.dec)}")# 使用字符串表示
print(f"赤经 (字符串): {sun.ra_str}")
print(f"赤纬 (字符串): {sun.dec_str}")
print(f"方位角 (字符串): {sun.azstr}")
print(f"高度角 (字符串): {sun.altstr}")
计算多个天体的位置
您可以同时计算多个天体的位置:
# 创建观察者
observer = ephem.Observer()
observer.lat = '39.9042'
observer.lon = '116.4074'
observer.date = datetime.now()# 创建多个天体
sun = ephem.Sun()
moon = ephem.Moon()
mars = ephem.Mars()# 计算位置
sun.compute(observer)
moon.compute(observer)
mars.compute(observer)# 打印结果
print("太阳:")
print(f" 方位角: {math.degrees(sun.az):.2f}°, 高度角: {math.degrees(sun.alt):.2f}°")print("月亮:")
print(f" 方位角: {math.degrees(moon.az):.2f}°, 高度角: {math.degrees(moon.alt):.2f}°")print("火星:")
print(f" 方位角: {math.degrees(mars.az):.2f}°, 高度角: {math.degrees(mars.alt):.2f}°")
特定时间的计算
您可以计算过去或未来某个时间的天体位置:
# 设置特定日期和时间
specific_time = datetime(2023, 12, 25, 18, 0, 0) # 2023年12月25日 18:00:00
observer.date = specific_time# 计算太阳位置
sun.compute(observer)print(f"在 {specific_time} 的太阳位置:")
print(f" 方位角: {math.degrees(sun.az):.2f}°, 高度角: {math.degrees(sun.alt):.2f}°")
通过这种方式,您可以预测未来或回顾过去的天文现象,如日食、月食、行星合相等。
日出日落与晨昏蒙影
计算日出、日落以及晨昏蒙影时间是天文学中常见的需求,ephem
提供了简单而强大的方法来计算这些时间。
基本日出日落计算
计算日出和日落的基本步骤如下:
设置观察者的位置和时间
使用
next_rising()
和next_setting()
方法计算下一个日出和日落时间或者使用
previous_rising()
和previous_setting()
方法计算上一个日出和日落时间
import ephem
from datetime import datetime# 创建观察者并设置位置
observer = ephem.Observer()
observer.lat = '39.9042' # 北京纬度
observer.lon = '116.4074' # 北京经度
observer.elevation = 43 # 海拔高度(米)
observer.pressure = 0 # 不考虑大气折射
observer.temp = 15 # 温度(摄氏度)# 设置日期为今天
observer.date = datetime.now()# 计算日出和日落时间
sun = ephem.Sun()# 下一个日出时间
next_sunrise = observer.next_rising(sun)
# 下一个日落时间
next_sunset = observer.next_setting(sun)# 转换为可读格式
print(f"下一个日出时间: {next_sunrise}")
print(f"下一个日落时间: {next_sunset}")# 转换为本地时间(字符串格式转换为 datetime)
import datetime as dtdef ephem_to_datetime(ephem_date):return dt.datetime.strptime(str(ephem_date), '%Y/%m/%d %H:%M:%S')sunrise_dt = ephem_to_datetime(next_sunrise)
sunset_dt = ephem_to_datetime(next_sunset)print(f"下一个日出时间 (本地): {sunrise_dt}")
print(f"下一个日落时间 (本地): {sunset_dt}")
晨昏蒙影(Twilight)计算
晨昏蒙影是指太阳在地平线下一定角度时,天空仍然明亮的现象。ephem
提供了几种不同类型的晨昏蒙影计算:
民用晨昏蒙影 (Civil Twilight):太阳在地平线下 6 度
航海晨昏蒙影 (Nautical Twilight):太阳在地平线下 12 度
天文晨昏蒙影 (Astronomical Twilight):太阳在地平线下 18 度
可以通过设置观察者的 horizon
属性来计算不同类型的晨昏蒙影:
# 设置观察者
observer = ephem.Observer()
observer.lat = '39.9042'
observer.lon = '116.4074'
observer.date = datetime.now()# 民用晨昏蒙影 (太阳在地平线下 6 度)
observer.horizon = '-6'
civil_twilight_begin = observer.next_rising(sun, use_center=True)
civil_twilight_end = observer.next_setting(sun, use_center=True)print(f"民用晨昏蒙影开始: {civil_twilight_begin}")
print(f"民用晨昏蒙影结束: {civil_twilight_end}")# 航海晨昏蒙影 (太阳在地平线下 12 度)
observer.horizon = '-12'
nautical_twilight_begin = observer.next_rising(sun, use_center=True)
nautical_twilight_end = observer.next_setting(sun, use_center=True)print(f"航海晨昏蒙影开始: {nautical_twilight_begin}")
print(f"航海晨昏蒙影结束: {nautical_twilight_end}")# 天文晨昏蒙影 (太阳在地平线下 18 度)
observer.horizon = '-18'
astronomical_twilight_begin = observer.next_rising(sun, use_center=True)
astronomical_twilight_end = observer.next_setting(sun, use_center=True)print(f"天文晨昏蒙影开始: {astronomical_twilight_begin}")
print(f"天文晨昏蒙影结束: {astronomical_twilight_end}")
使用 use_center
参数
对于更精确的计算,特别是对于太阳和月亮,可以使用 use_center=True
参数,这将考虑天体的中心而不是边缘:
# 使用天体中心计算日出日落
observer.horizon = '0'
sunrise_center = observer.next_rising(sun, use_center=True)
sunset_center = observer.next_setting(sun, use_center=True)print(f"使用中心计算的日出: {sunrise_center}")
print(f"使用中心计算的日落: {sunset_center}")
计算全天的日出日落时间
您可以计算一天中的所有日出日落时间,或者特定时间范围内的天文事件:
# 计算一天中的日出日落
observer.date = datetime.now()
observer.horizon = '0'# 日出
sunrise = observer.next_rising(sun)
# 日落
sunset = observer.next_setting(sun)print(f"今日日出: {sunrise}")
print(f"今日日落: {sunset}")# 如果需要计算明天的日出日落
tomorrow = observer.date + 1
observer.date = tomorrow
sunrise_tomorrow = observer.next_rising(sun)
sunset_tomorrow = observer.next_setting(sun)print(f"明日日出: {sunrise_tomorrow}")
print(f"明日日落: {sunset_tomorrow}")
计算多个地点的日出日落
通过创建多个观察者对象,您可以计算不同地点的日出日落时间:
# 北京
beijing = ephem.Observer()
beijing.lat = '39.9042'
beijing.lon = '116.4074'
beijing.date = datetime.now()
beijing.horizon = '0'# 上海
shanghai = ephem.Observer()
shanghai.lat = '31.2304'
shanghai.lon = '121.4737'
shanghai.date = datetime.now()
shanghai.horizon = '0'sun = ephem.Sun()# 计算北京的日出日落
beijing_sunrise = beijing.next_rising(sun)
beijing_sunset = beijing.next_setting(sun)# 计算上海的日出日落
shanghai_sunrise = shanghai.next_rising(sun)
shanghai_sunset = shanghai.next_setting(sun)print(f"北京日出: {beijing_sunrise}, 日落: {beijing_sunset}")
print(f"上海日出: {shanghai_sunrise}, 日落: {shanghai_sunset}")
通过这些方法,您可以精确地计算各种天文事件的时间,帮助规划天文观测、摄影等活动。