PYTHON实时跟踪天体的观测位置
from https://chaossky.com/post/1815

我们平时观测天体的时候一般都要提前做好功课,了解天体近段时间的运行位置,而且无法做到实时跟踪,虽然手机上有了很多精美的app,但要同时跟踪多个天体,或者要具体的经纬信息,这些app还是无法胜任。混沌天文为此制作了一个简易的开源工具“planet-az”,可以实时标记要观测的天体位置,给出具体的地平坐标系下的高度角(Altitude, Alt),方位角(Azimuth, Az),赤道坐标系下的赤纬(Dec),赤经(Ra)。方便天文爱好者观测。
先说一下赤道坐标系和地平坐标系这两个常用的观测坐标系,熟悉的观众可以跳过我们把地球的赤道平面平面无限扩展,与天球相割,就会得到一个大圆圈,这个大圆圈就是天球赤道,简称天赤道,并把天赤道作为天球上的“纬度”的基圈。我们把这个天球上的“纬度”叫做“赤纬”。这个坐标系,我们叫做“赤道坐标系”。

地平坐标系,是天球坐标系统中的一种,以观测者所在地为中心点,所在地的地平线作为基础平面,将天球适当的分成能看见的上半球和看不见(被地球本身遮蔽)的下半球。上半球的顶点(最高点)称为天顶,下半球的顶点(最低点)称为地底。地平坐标系统有高度角和方位角两个变量,高度角(Altitude, Alt)或仰角又称地平纬度,是天体和观测者所在地的地平线的夹角,有时就称为高度或海拔标高(elevation, geometric height)。方位角(Azimuth, Az)又称地平经度,是沿着地平线测量的角度(由正北方为起点向东方测量)。因此地平坐标系有时也被称为高度/方位(Alt/Az)坐标系统。

天体在上面两个坐标系中的位置就是我们要跟踪的目标。planet-az运行起来很方便,先按说明安装相关的pip包,然后修改config.yaml文件,填入观测者的经纬度,例如:

然后运行起来
python planet_az.py -c config.yaml跑起来后会弹出一个图像界面和文字界面,图像界面每隔一段时间会刷新太阳,月亮和太阳系八大行星+冥王星的az和alt,文字界面则会每隔一段时间刷新以上天体最新的赤道坐标和地平坐标。如果天体处于地平以下会提示“不可见”,如果天体仰角较小会提示“较低”或“观测警告”。


要停止的话在文字界面按Ctrl+c组合键即可。如果不是仅仅想看太阳系几个天体,而是想跟踪某个特定天体咋办?这也是没问题的。我们以跟踪著名的巨蟹座星云(M1)为例,先在维基百科找到M1的赤经赤纬

将M1的名字,赤经Ra,赤纬Dec按特定格式填入config.yaml文件中,如下:

然后重新运行就可以实时跟踪M1位置了。

以上就是planet-az小工具的使用方法,猛戳混沌天文代码库下载吧=>混沌天文代码库
from https://github.com/hunduntianwen/planet-az/blob/master/planet_az.py
| import datetime | |
| import time | |
| import os, sys | |
| import yaml | |
| import numpy as np | |
| import ephem | |
| import argparse | |
| from prettytable import PrettyTable | |
| import matplotlib | |
| matplotlib.use('TkAgg') | |
| import matplotlib.pyplot as plt | |
| def reflash_table(table): | |
| table.clear_rows() | |
| all_object = {**Stars, **Planets} | |
| for name, s in all_object.items(): | |
| ra = "%.4f" % (s.ra * 180 / np.pi) | |
| dec = "%.4f" % (s.dec * 180 / np.pi) | |
| az = "%.4f" % (s.az * 180 / np.pi) | |
| alt = "%.4f" % (s.alt * 180 / np.pi) | |
| if float(alt) < 0: | |
| obs = "不可见" | |
| elif 0 <= float(alt) < 10: | |
| obs = "较低" | |
| elif 0 <= float(alt) < 30: | |
| obs = "观测警告" | |
| elif 0 <= float(az) < 45 or 315 <= float(az) <=360: | |
| obs = "北" | |
| elif 45 <= float(az) < 135: | |
| obs = "东" | |
| elif 135 <= float(az) < 225: | |
| obs = "南" | |
| elif 225 <= float(az) < 315: | |
| obs = "西" | |
| table.add_row([name, ra, dec, az, alt, obs]) | |
| #清屏操作 | |
| os.system('cls' if os.name == 'nt' else 'clear') | |
| #输出 | |
| sys.stdout.write(table.get_string()) | |
| sys.stdout.flush() | |
| sys.stdout.write("\n") | |
| def reflash_paint(): | |
| plt.cla() | |
| ax.axis([0, 360, -90, 90]) | |
| plt.xlabel('Azimuth') | |
| plt.ylabel('Altitude') | |
| ax.axhline(y=0,ls="-") # 水平直线 | |
| for name, p in Planets.items(): | |
| az = p.az * 180 / np.pi | |
| alt = p.alt * 180 / np.pi | |
| ax.annotate(name, (az+3, alt+3)) | |
| if name == "Sun": | |
| ax.scatter(az, alt, s=100, c="r", alpha=0.8, marker="o") | |
| elif name == "Moon": | |
| ax.scatter(az, alt, s=80, c="y", alpha=0.8, marker="o") | |
| elif name == "Jupiter": | |
| ax.scatter(az, alt, s=30, c="b", alpha=0.8, marker="o") | |
| else: | |
| ax.scatter(az, alt, s=50, c="b", alpha=0.8, marker=".") | |
| for name, s in Stars.items(): | |
| az = s.az * 180 / np.pi | |
| alt = s.alt * 180 / np.pi | |
| ax.annotate(name, (az+3, alt+3)) | |
| ax.scatter(az, alt, s=50, c="m", alpha=0.8, marker="*") | |
| figure.canvas.draw() | |
| figure.canvas.flush_events() | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("-c", "--config", required=True) | |
| args = parser.parse_args() | |
| with open(args.config, "r", encoding="utf-8") as f: | |
| config = yaml.load(f.read(), Loader=yaml.FullLoader) | |
| # 太阳系 | |
| Planets = { | |
| "Sun": ephem.Sun(), | |
| "Moon": ephem.Moon(), | |
| "Mercury": ephem.Mercury(), | |
| "Venus": ephem.Venus(), | |
| "Mars": ephem.Mars(), | |
| "Jupiter": ephem.Jupiter(), | |
| "Saturn": ephem.Saturn(), | |
| "Uranus": ephem.Uranus(), | |
| "Neptune": ephem.Neptune(), | |
| "Pluto": ephem.Pluto(), | |
| } | |
| # 自定义天体 | |
| Stars = {} | |
| for body in config["stars"]: | |
| name = body["name"] | |
| ra = body["Ra"] | |
| dec = body["Dec"] | |
| fixbody = ephem.FixedBody() | |
| fixbody._ra = ra | |
| fixbody._dec = dec | |
| Stars[name] = fixbody | |
| # 观察者 | |
| Observer = ephem.Observer() | |
| Observer.lon = config["observer"]["longitude"] | |
| Observer.lat = config["observer"]["latitude"] | |
| Observer.elevation = config["observer"]["elevation"] | |
| Observer.pressure = config["observer"]["pressure"] | |
| # 表格 | |
| table = PrettyTable(['Source','Ra赤经','Dec赤纬','Az方位', 'Alt仰角', '观测']) | |
| table.padding_width = 5 | |
| # 图 | |
| plt.ion() | |
| figure, ax = plt.subplots() | |
| # 刷新 | |
| while True: | |
| try: | |
| Observer.date = "%s"%datetime.datetime.utcnow() #观察时间 | |
| for name, p in Planets.items(): | |
| p.compute(Observer) | |
| for name, s in Stars.items(): | |
| s.compute(Observer) | |
| reflash_table(table) | |
| reflash_paint() | |
| plt.pause(1) | |
| time.sleep(4) | |
| except KeyboardInterrupt: | |
| break | |
| plt.close() |
from https://www.cnpython.com/pypi/ephem
pyephem提供的功能包括:
- 找到行星、彗星或小行星在天空中的位置。
- 高精度轨道程序已被证实 对于月球、太阳、行星和主要行星卫星。
- 用户可以提供彗星小行星的轨道元素, 或地球轨道卫星,并计算其位置。
- 94颗明亮恒星的位置是内置的, 用户可以根据需要创建更多的固定对象 为了他们的计算。
- 确定某个特定观察者在天空中出现的物体位置。
- 用户可以提供经度、纬度和高度 他们将要观察的地点。
- 为了方便起见,一个小型的经纬度数据库 包括122个世界城市。
- 对于规定的天气条件(温度和压力); pyephem将补偿大气折射 通过调整物体在地平线附近的位置。
- 计算一个物体何时升起,何时在头顶上移动,何时设置 从一个特定的地点。
- 解析和使用传统Xephem文件格式的轨道数据, 或者用于跟踪地球轨道卫星的标准TLE格式。
- 确定分点和至点的日期。
- 计算月球不同阶段的日期。
- 从格林威治时间(更准确地说,是星历时间)转换而来 pyephem使用到用户的本地时间。
- 转换赤道、黄道和银河系之间的位置 坐标系。
- 确定在哪一页的铀量表或千年星图 一颗特别的星星应该出现。
- 返回与任何日历日期对应的儒略日期。
留言
張貼留言