首页 > 编程问答 >用赤道坐标系绘制星图

用赤道坐标系绘制星图

时间:2024-07-23 15:03:38浏览次数:12  
标签:python matplotlib astropy skyfield

我正在尝试使用赤道坐标系(RAJ2000 和 DEJ2000)生成星图。然而,我只得到一个网格系统,其中经线和平行线是平行的,而纬线应该是弯曲的,经线应该会聚到北天极和南天极。

我正在使用一些Python模块:matplotlib、skyfield (用于立体投影)、astroquery(因此我可以瞄准深空中的任何物体)和 astropy。

这是我的代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Generate a skymap with equatorial grid"""

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
from skyfield.api import Star, load
from skyfield.data import hipparcos, stellarium
from skyfield.projections import build_stereographic_projection
from astroquery.simbad import Simbad
from astropy.coordinates import SkyCoord
import astropy.units as u
from astropy.wcs import WCS
from astropy.visualization.wcsaxes import WCSAxes

# Design
plt.style.use("dark_background")
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['Times New Roman']

# Query object from Simbad
OBJECT = "Polaris"
FOV = 30.0
MAG = 6.5

TABLE = Simbad.query_object(OBJECT)
RA = TABLE['RA'][0]
DEC = TABLE['DEC'][0]
COORD = SkyCoord(f"{RA} {DEC}", unit=(u.hourangle, u.deg), frame='fk5')

print("RA is", RA)
print("DEC is", DEC)

ts = load.timescale()
t = ts.now()

# An ephemeris from the JPL provides Sun and Earth positions.
eph = load('de421.bsp')
earth = eph['earth']

# Load constellation outlines from Stellarium
url = ('https://raw.githubusercontent.com/Stellarium/stellarium/master'
       '/skycultures/modern_st/constellationship.fab')

with load.open(url) as f:
    constellations = stellarium.parse_constellations(f)

edges = [edge for name, edges in constellations for edge in edges]
edges_star1 = [star1 for star1, star2 in edges]
edges_star2 = [star2 for star1, star2 in edges]

# The Hipparcos mission provides our star catalog.
with load.open(hipparcos.URL) as f:
    stars = hipparcos.load_dataframe(f)

# Center the chart on the specified object's position.
center = earth.at(t).observe(Star(ra_hours=COORD.ra.hour, dec_degrees=COORD.dec.degree))
projection = build_stereographic_projection(center)

# Compute the x and y coordinates that each star will have on the plot.
star_positions = earth.at(t).observe(Star.from_dataframe(stars))
stars['x'], stars['y'] = projection(star_positions)

# Create a True/False mask marking the stars bright enough to be included in our plot.
bright_stars = (stars.magnitude <= MAG)
magnitude = stars['magnitude'][bright_stars]
marker_size = (0.5 + MAG - magnitude) ** 2.0

# The constellation lines will each begin at the x,y of one star and end at the x,y of another.
xy1 = stars[['x', 'y']].loc[edges_star1].values
xy2 = stars[['x', 'y']].loc[edges_star2].values
lines_xy = np.rollaxis(np.array([xy1, xy2]), 1)

# Define the limit for the plotting area
angle = np.deg2rad(FOV / 2.0)
limit = np.tan(angle)  # Calculate limit based on the field of view

# Build the figure with WCS axes
fig = plt.figure(figsize=[6, 6])
wcs = WCS(naxis=2)
wcs.wcs.crpix = [1, 1]
wcs.wcs.cdelt = np.array([-FOV / 360, FOV / 360])
wcs.wcs.crval = [COORD.ra.deg, COORD.dec.deg]
wcs.wcs.ctype = ["RA---STG", "DEC--STG"]

ax = fig.add_subplot(111, projection=wcs)

# Draw the constellation lines
ax.add_collection(LineCollection(lines_xy, colors='#ff7f2a', linewidths=1, linestyle='-'))

# Draw the stars
ax.scatter(stars['x'][bright_stars], stars['y'][bright_stars],
           s=marker_size, color='white', zorder=2)

ax.scatter(RA, DEC, marker='*', color='red', zorder=3)

angle = np.pi - FOV / 360.0 * np.pi
limit = np.sin(angle) / (1.0 - np.cos(angle))

# Set plot limits
ax.set_xlim(-limit, limit)
ax.set_ylim(-limit, limit)
ax.set_aspect('equal')

# Add RA/Dec grid lines
ax.coords.grid(True, color='white', linestyle='dotted')

# Set the coordinate grid
ax.coords[0].set_axislabel('RA (hours)')
ax.coords[1].set_axislabel('Dec (degrees)')
ax.coords[0].set_major_formatter('hh:mm:ss')
ax.coords[1].set_major_formatter('dd:mm:ss')

# Title
ax.set_title(f'Sky map centered on {OBJECT}', color='white', y=1.04)

# Save the image
FILE = "chart.png"
plt.savefig(FILE, dpi=100, facecolor='#1a1a1a')

这是生成的图像:

enter image description here

我的目标是实现像这样的图像,在 RA 和 Dec 中正确标记了轴。

enter image description here


问题在于你将矩形赤道坐标系与想要显示这些坐标的立体投影混淆了。你正在正确地计算立体投影,但是,你使用 wcs.wcs.ctype = ["RA---STG", "DEC--STG"] 错误地告诉 Matplotlib 你想使用立体投影。

不要使用 WCSAxes 类来创建坐标轴。该类用于绘制 基于 天球坐标的图像数据(例如 FITS 图像)。你试图自己 生成 这样的图像,因此你只需要使用 Matplotlib 的常规绘图方法,并在最后用赤道网格装饰结果。

以下是你修改后的代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Generate a skymap with equatorial grid"""

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
from skyfield.api import Star, load
from skyfield.data import hipparcos, stellarium
from skyfield.projections import build_stereographic_projection
from astroquery.simbad import Simbad
from astropy.coordinates import SkyCoord
import astropy.units as u

# Design
plt.style.use("dark_background")
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['Times New Roman']

# Query object from Simbad
OBJECT = "Polaris"
FOV = 30.0
MAG = 6.5

TABLE = Simbad.query_object(OBJECT)
RA = TABLE['RA'][0]
DEC = TABLE['DEC'][0]
COORD = SkyCoord(f"{RA} {DEC}", unit=(u.hourangle, u.deg), frame='fk5')

print("RA is", RA)
print("DEC is", DEC)

ts = load.timescale()
t = ts.now()

# An ephemeris from the JPL provides Sun and Earth positions.
eph = load('de421.bsp')
earth = eph['earth']

# Load constellation outlines from Stellarium
url = ('https://raw.githubusercontent.com/Stellarium/stellarium/master'
       '/skycultures/modern_st/constellationship.fab')

with load.open(url) as f:
    constellations = stellarium.parse_constellations(f)

edges = [edge for name, edges in constellations for edge in edges]
edges_star1 = [star1 for star1, star2 in edges]
edges_star2 = [star2 for star1, star2 in edges]

# The Hipparcos mission provides our star catalog.
with load.open(hipparcos.URL) as f:
    stars = hipparcos.load_dataframe(f)

# Center the chart on the specified object's position.
center = earth.at(t).observe(Star(ra_hours=COORD.ra.hour, dec_degrees=COORD.dec.degree))
projection = build_stereographic_projection(center)

# Compute the x and y coordinates that each star will have on the plot.
star_positions = earth.at(t).observe(Star.from_dataframe(stars))
stars['x'], stars['y'] = projection(star_positions)

# Create a True/False mask marking the stars bright enough to be included in our plot.
bright_stars = (stars.magnitude <= MAG)
magnitude = stars['magnitude'][bright_stars]
marker_size = (0.5 + MAG - magnitude) ** 2.0

# The constellation lines will each begin at the x,y of one star and end at the x,y of another.
xy1 = stars[['x', 'y']].loc[edges_star1].values
xy2 = stars[['x', 'y']].loc[edges_star2].values
lines_xy = np.rollaxis(np.array([xy1, xy2]), 1)

# Define the limit for the plotting area
angle = np.deg2rad(FOV / 2.0)
limit = np.tan(angle)  # Calculate limit based on the field of view

# Build the figure
fig = plt.figure(figsize=[6, 6])
ax = fig.add_subplot(111)

# Draw the constellation lines
ax.add_collection(LineCollection(lines_xy, colors='#ff7f2a', linewidths=1, linestyle='-'))

# Draw the stars
ax.scatter(stars['x'][bright_stars], stars['y'][bright_stars],
           s=marker_size, color='white', zorder=2)

ax.scatter(0, 0, marker='*', color='red', zorder=3)

# Set plot limits
ax.set_xlim(-limit, limit)
ax.set_ylim(-limit, limit)
ax.set_aspect('equal')

# Add RA/Dec grid lines
overlay = ax.get_xaxis_transform()
for ra in np.arange(0, 360, 15):
    x = np.linspace(-limit, limit, 100)
    y = np.tan(np.deg2rad(ra - COORD.ra.deg)) * x
    ax.plot(x, y, color='white', linestyle='dotted', transform=overlay)
for dec in np.arange(-90, 90, 15):
    x = np.linspace(-limit, limit, 100)
    y = (x + np.tan(np.deg2rad(dec))) / np.tan(np.deg2rad(dec)) * limit
    ax.plot(x, y, color='white', linestyle='dotted')

# Title
ax.set_title(f'Sky map centered on {OBJECT}', color='white', y=1.04)

# Save the image
FILE = "chart.png"
plt.savefig(FILE, dpi=100, facecolor='#1a1a1a')

这将创建一个星图,其中中心是指定的物体,并且赤经和赤纬网格正确地投影到立体投影上。

标签:python,matplotlib,astropy,skyfield
From: 78778792

相关文章

  • Python-深度学习算法实用指南-全-
    Python深度学习算法实用指南(全)原文:zh.annas-archive.org/md5/844a6ce45a119d3197c33a6b5db2d7b1译者:飞龙协议:CCBY-NC-SA4.0前言深度学习是人工智能领域最受欢迎的领域之一,允许你开发复杂程度各异的多层模型。本书介绍了从基础到高级的流行深度学习算法,并展示了如何使用......
  • 三种语言实现归并排序(C++/Python/Java)
    题目给定你一个长度为......
  • Python中如何实现字符串的查询和替换?
    在Python中,字符串的查询和替换是编程中常见的任务,它们可以通过Python的内置方法和库来高效实现。这些操作对于文本处理、数据清洗、日志分析等场景尤为重要。下面,我将详细阐述如何在Python中实现字符串的查询和替换,包括基础方法、高级技巧以及在实际应用中的注意事项。字符......
  • Python中的`range()`函数及其用法
    range()函数是Python中的一个内置函数,它用于生成一个数字序列。这个函数在循环结构中尤其有用,因为它允许我们迭代一系列的数字,而无需显式地创建这些数字的列表。range()函数通过指定起始值、结束值(不包括)和步长(可选)来工作,返回一个可迭代对象,通常用于for循环中。下面将......
  • python 的注释(例如数据类)可以扩展到它生成的代码中吗?
    能看出python的注释扩展成​​什么吗?例如,对于与数据类相关的错误,有时试图找出它实际生成的代码有点棘手。例如:@dataclass(order=True)classPerson:name:strage:int=0classPerson:def__init__(self,name:str,age=0):self.name=name......
  • Docker:无法在 docker 映像中使用 pythonnet 和 |无法创建默认的 .NET 运行时,该运行时
    我正在尝试使用clrfromPythonnet使用.DLL引用将一种文件类型转换为另一种文件类型。这就是我的代码的样子-importclrclr.AddReference(dll_path)importRxLibrary#ConverttoASCFormat-----------input_file=f"./{filename}.rxd"......
  • 在 Python 中以非常高的质量保存图像
    如何以非常高的质量保存Python绘图?也就是说,当我不断放大PDF文件中保存的对象时,为什么没有任何模糊?另外,什么是最好的模式将其保存在?png,eps?或者其他的?我不能pdf,因为有一个隐藏的数字会扰乱Latexmk编译。要以非常高的质量保存Py......
  • Python字符串:提取重复和随机合并的子字符串
    重复和合并字符串的示例:16.01068.0%08p%.a.p.a.要提取的所需子字符串:16.008%p.a.完整示例:CCoonnttiinnggeennttCCoouuppoonn16.01068.0%08p%.a.p(.Ma.o(nMtholyn)thly)所需子字符串:ContingentCoupon16.008%p.a.(Monthly)我的问题是当原始......
  • Python Pandas 从使用第 3 部分 API 自动生成的 Excel 文件中读取不一致的日期格式
    我正在使用PDF4meAPI将PDF发票转换为Excel文件。API可以正确读取日期。但是,当我打开Excel文件时,日期显示不一致:某些日期以正确的格式(dd/mm/yyyy)显示,而其他日期以错误的mm/dd/yyyy格式显示。当该月的某天小于或等于12时,似乎会出现这种不一致。......
  • python-input键盘输入
     str=input("请输入:")#用户键盘输入#str表示一个字符串类型的变量,input会将读取到的字符串放入str中print(str) aa='请输入:'str=input(aa)#用户键盘输入#str表示一个字符串类型的变量,input会将读取到的字符串放入str中print(str)      ......