astropy.cosmology 宇宙学计算完全指南:内置模型、距离/时间/密度换算与红移逆推(scientific-agent-skills 技能解析)
astropy.cosmology 是 Astropy 生态中专用于宇宙学计算的子包,它基于标准宇宙学模型(ΛCDM 及其变体)为距离、年龄、哈勃参数、密度参数、巡天体积累计等提供统一且带单位的 API。本文是 scientific-agent-skills 仓库中 astropy 技能 的参考文档 cosmology.md 的深度展开,面向需要"把观测红移换算成物理量"的天文数据处理与 Agent 编程场景。读完本文,你将掌握:直接使用 Planck/WMAP 内置宇宙学、手工构造 FlatLambdaCDM/w0wzCDM 等自定义模型、调用全套距离与时间方法、用 z_at_value 反解红移,以及大规模数组运算与中微子参数的正确打开方式。
适用场景:何时需要用到这一子包
在 Astropy 技能定义的典型天文工作流中(见 SKILL.md),凡是任务涉及下列环节,都应该优先想到 astropy.cosmology:
- 把谱线红移、星系退行速度换算为光度距离、同动距离等物理距离;
- 由红移计算宇宙年龄、回溯时间(lookback time)等时间量;
- 求某红移处的哈勃参数
H(z)与各密度参数随红移的演化; - 为巡天项目估算两个红移面之间的宇宙学体积(如单位化为
Gpc³); - 用测光红移 + 视星等反推绝对星等,或由角大小估算天体物理尺度。
换句话说,只要代码里出现"给定 z,我需要一个带单位的距离/年龄/体积",这个子包就是标准答案。它输出的所有量都是 astropy.units.Quantity(带物理单位),天然与仓库中另一份参考 units.md 描述的单位系统无缝衔接,避免手工换算和维度错误。
安装与环境约定
astropy.cosmology 随 Astropy 主包一起分发,因此安装即用。仓库当前调研到的稳定版本约束如下(见 SKILL.md):
# 可复现安装:锁定当前稳定版本 7.2.0
uv pip install "astropy==7.2.0"
# 推荐可选依赖(绘图与常见科学工作流)
uv pip install "astropy[recommended]==7.2.0"
# 完整可选依赖(宽泛天文工作流)
uv pip install "astropy[all]==7.2.0"
环境要求是 Python 3.11+,并依赖 NumPy、PyERFA、PyYAML、packaging 等底层库;建议在独立虚拟环境中安装,不要用提权方式安装。注意 [recommended] 与 [all] 会带入 matplotlib、scipy 等传递依赖且不锁版本,生产环境建议用 uv lock / uv pip compile 固定整棵依赖树。
关于导入路径的重要提示
astropy.cosmology 的公开类与函数在旧版本中散落在 astropy.cosmology.flrw、.core、.funcs、.connect、.parameter 等子模块。这些旧子模块导入路径自 Astropy 7.1 起被弃用,并将在 Astropy 8.0 中被正式移除(仓库文档在 SKILL.md 的版本说明中明确标注了 8.0 的移除计划)。因此,本参考文档中的所有示例都坚持一种写法:
# 正确:一律从顶层 astropy.cosmology 导入
from astropy.cosmology import FlatLambdaCDM, Planck18, z_at_value
新代码不要再写 from astropy.cosmology.flrw import FlatLambdaCDM 之类的旧路径,否则迁移到 8.x 时会直接报导入错误。
直接使用内置宇宙学:Planck18 与 WMAP 系列
无需自己指定任何参数,astropy.cosmology 预置了基于 WMAP 与 Planck 观测结果的常用宇宙学实例,开箱即用:
from astropy.cosmology import Planck18, Planck15, Planck13
from astropy.cosmology import WMAP9, WMAP7, WMAP5
from astropy import units as u
# 选用 Planck 2018 结果作为默认宇宙学
cosmo = Planck18
# 计算 z=4 处的光度距离
d = cosmo.luminosity_distance(4)
print(f"Luminosity distance at z=4: {d}")
# 当前宇宙年龄(z=0)
age = cosmo.age(0)
print(f"Current age of universe: {age.to(u.Gyr)}")
这些实例各自封装了一组具体的实测参数(哈勃常数、物质密度等)。实际项目里,不同论文、不同数据版本(Planck 2013/2015/2018,或 WMAP 5/7/9 年)采用的宇宙学参数并不相同,直接选用对应实例能在比较不同研究结果时保持口径一致。当你只是"想算一个距离",应优先用这些内置实例,而不是手写参数。
构建自定义宇宙学模型
当内置实例不满足需求(例如采用你自己的 H0、Om0,或需要暗能量状态方程参数)时,可以用模型类构造自定义实例。
FlatLambdaCDM(最常用):平坦 + 宇宙学常数
假定宇宙空间平坦(曲率项为 0),暗能量为宇宙学常数:
from astropy.cosmology import FlatLambdaCDM
from astropy import units as u
cosmo = FlatLambdaCDM(
H0=70 * u.km / u.s / u.Mpc, # z=0 时的哈勃常数(必填)
Om0=0.3, # z=0 时的物质密度参数(必填)
Tcmb0=2.725 * u.K # 当前 CMB 温度(可选,默认即 2.725 K)
)
参数语义:
H0:红移 0 处的哈勃常数,量纲为速度/距离,通常写为70*u.km/u.s/u.Mpc。它决定了宇宙的膨胀标度,直接影响所有距离与年龄的数值。Om0:当前物质(重子 + 暗物质)总密度参数 Ωm0,无量纲。Tcmb0(可选):当前 CMB 温度,默认 2.725 K;提供它后模型才会计算光子与中微子密度项(见下文Ogamma/Onu)。- 在平坦模型中,暗能量密度参数由平坦性条件
Ode0 = 1 - Om0隐含决定,无需也不能再传Ode0。
LambdaCDM(非平坦):显式给定暗能量密度
若允许曲率不为零,则需同时显式给出物质与暗能量密度:
from astropy.cosmology import LambdaCDM
cosmo = LambdaCDM(
H0=70 * u.km / u.s / u.Mpc,
Om0=0.3,
Ode0=0.7 # 当前暗能量密度参数;此时曲率密度由 1 - Om0 - Ode0 隐含
)
wCDM 与 w0wzCDM:带状态方程的暗能量
当需要把暗能量建模为"非宇宙学常数"(状态方程参数 w ≠ -1)时:
from astropy.cosmology import FlatwCDM, w0wzCDM
# 恒定 w:暗能量状态方程 p = w·ρc²,w 不随红移变化
cosmo_w = FlatwCDM(H0=70 * u.km / u.s / u.Mpc, Om0=0.3, w0=-0.9)
# w 随红移线性演化:w(z) = w0 + wz * z
cosmo_wz = w0wzCDM(H0=70 * u.km / u.s / u.Mpc, Om0=0.3, Ode0=0.7,
w0=-1.0, wz=0.1)
要点:
w0:z=0 处的状态方程参数。w = -1 时退化为宇宙学常数;w > -1(如 -0.9)代表"精质"型暗能量,w < -1 对应"幻影"型。wz:w0wzCDM的演化斜率,给出w(z) = w0 + wz·z的线性模型。- 注意
w0wzCDM在平坦场景中构造方式类似(用Flatw0waCDM等变体承接平坦约束),文档示例给出的非平坦形式要求同时传Ode0,与LambdaCDM的约束逻辑一致。
无论哪类模型,一旦实例化,下面所有距离、时间、密度方法均可统一调用——这是该子包最重要的设计:方法接口与模型实现解耦。
距离计算全家桶
观测宇宙学的核心任务之一就是做距离换算。模型对象对每个 z 都能给出多个定义不同的"距离",各自服务于不同物理场景。以下方法均接受标量或数组 z,返回带单位的量。
同动距离(Comoving Distance)
沿视线方向的同动距离,是其他大多数距离的基础:
d_c = cosmo.comoving_distance(z)
它度量的是"如果宇宙今天停止膨胀,光走过的路径长度",红移只源于膨胀本身。
光度距离(Luminosity Distance)
由观测通量反推天体光度时使用,是超新星 Ia 测距、绝对星等计算的标准距离:
d_L = cosmo.luminosity_distance(z)
# 由视星等求绝对星等:M = m - 5·log10(d_L/pc) + 5
M = m - 5*np.log10(d_L.to(u.pc).value) + 5
公式中 d_L 必须先转换到 pc(秒差距)再取 value 参与对数运算——这正是带单位 Quantity 的便利之处:.to(u.pc) 完成单位换算,.value 取出纯数值。
角直径距离(Angular Diameter Distance)
由角大小估算物理尺寸时使用。它描述"同一固有尺度在不同红移处看起来多大":
d_A = cosmo.angular_diameter_distance(z)
# 由角大小求物理尺寸(弧度制乘法)
theta = 10 * u.arcsec # 角大小
physical_size = d_A * theta.to(u.radian).value
注意角大小必须先转到弧度(theta.to(u.radian))再与距离相乘。在任意几何中,角直径距离与同动距离满足 D_A = D_M/(1+z)(D_M 为同动横向距离),因此高红移处角直径距离会"由增转减",这是宇宙学角直径关系的著名特征。
同动横向距离(Comoving Transverse Distance)
在平坦宇宙中它与同动距离相等;非平坦模型中则需要它来正确描述横向尺度:
d_M = cosmo.comoving_transverse_distance(z)
angular_diameter_distance 正是由它除以 (1+z) 得到。
距离模数(Distance Modulus)
dm = cosmo.distmod(z)
# 满足 m - M = dm(视星等 - 绝对星等)
distmod 返回 Quantity(单位为星等 mag),直接写成 m_app - cosmo.distmod(z).value 即可从视星等得到绝对星等,比手动写 5*log10(...) + 25 更不易错。
尺度与体积换算
巡天设计、透镜统计、团簇丰度研究常需要"角尺度 ↔ 物理尺度""单位红移厚度内有多少体积"这类换算:
# 某红移处 1 角分对应的物理 kpc(估算角分辨率对应尺度非常常用)
scale = cosmo.kpc_proper_per_arcmin(z)
# 例:z=1 附近输出形如 "≈50 kpc/arcmin" 的物理量
# 到红移 z 为止的累计同动体积
vol = cosmo.comoving_volume(z)
# 微分同动体积 dV/dz(单位红移厚度的体积)
vol_element = cosmo.differential_comoving_volume(z)
kpc_proper_per_arcmin 返回的是"某时刻该红移处的固有尺度";而 comoving_volume 把整个视锥体积累加出来,是巡天完备性计算与数密度估计的基础。二者都直接返回带单位量,后续单位化(如转 Gpc³)只需 .to(u.Gpc**3)。
时间计算:宇宙年龄与回溯时间
宇宙年龄(Age of Universe)
任意红移处宇宙的年龄(即从大爆炸到该红移时刻所经历的时间):
age = cosmo.age(z) # 红移 z 处的宇宙年龄
age_now = cosmo.age(0) # 当前年龄
age_at_z1 = cosmo.age(1) # z=1 时的年龄
回溯时间(Lookback Time)
光子从发射到被我们接收"走过了多少宇宙时间",即 z 与 0 之间的年龄差:
t_lookback = cosmo.lookback_time(z)
# 数值上约等于 age(0) - age(z)
lookback_time 是星系演化研究中最常用的量——观测高红移天体等于"回看"宇宙更年轻的时期,把观测到的红移 z 换成回溯时间,能直观给出"我们看到的是多少亿年前的光"。
哈勃参数与无量纲膨胀因子
任意红移处的膨胀速率:
H_z = cosmo.H(z) # H(z),单位 km/s/Mpc
E_z = cosmo.efunc(z) # E(z) = H(z)/H0(无量纲,H0 已折出)
efunc 在数值积分中大量使用:因为 H(z) = H0·E(z),把 E(z) 提出来可以显著改善积分条件数,也是代码中手写弗里德曼方程、验证距离积分正确性的好抓手。
密度参数随红移的演化
模型可以给出各组分密度参数在任何 z 处的取值,用于检查某红移处宇宙的组分构成(例如物质主导期、暗能量主导期的划分):
Om_z = cosmo.Om(z) # 物质(重子+暗物质)密度参数
Ode_z = cosmo.Ode(z) # 暗能量密度参数
Ok_z = cosmo.Ok(z) # 曲率密度参数(平坦宇宙恒为 0)
Ogamma_z = cosmo.Ogamma(z) # 光子(辐射)密度参数
Onu_z = cosmo.Onu(z) # 中微子密度参数
这些方法对任一组分都保证 Om+Ode+Ok+Ogamma+Onu = 1(误差范围内)。Ogamma、Onu 只有在构造时给出 Tcmb0(以及 Neff/m_nu,见下文)才会是可靠的非零值——因此构造模型时别省略 Tcmb0=2.725*u.K 这一行。
临界密度与物质密度
rho_c = cosmo.critical_density(z) # 临界密度 ρc(z)
rho_m = cosmo.critical_density(z) * cosmo.Om(z) # 物质密度 = ρc · Ωm
临界密度是区分宇宙几何"开/平/闭"的标尺;乘以对应密度参数即得绝对质量密度。比如估算暗物质晕的质量函数、把数密度换算成质量密度时,critical_density 是必经中间量。
红移逆推:z_at_value
正向方法都是"给 z 求物理量"。反过来,当已知目标物理量(如某个回溯时间、某段光度距离)需要求对应的红移 z 时,用 z_at_value:
from astropy.cosmology import z_at_value
# 找到回溯时间为 10 Gyr 对应的 z
z = z_at_value(cosmo.lookback_time, 10*u.Gyr)
# 找到光度距离为 1000 Mpc 对应的 z
z = z_at_value(cosmo.luminosity_distance, 1000*u.Mpc)
# 找到宇宙年龄为 1 Gyr 对应的 z(即"宇宙只有 10 亿岁时对应红移多少")
z = z_at_value(cosmo.age, 1*u.Gyr)
用法要点:
- 第一个参数传方法对象本身(如
cosmo.lookback_time),第二个参数传目标量(务必带单位); - 由于距离/时间随 z 单调(大部分区间),该方法通过数值求根定位 z,因此要求目标值落在该函数取值范围内;
- 属于相对昂贵的数值运算,若要在循环中反复调用,建议先算好再复用(与 SKILL.md 中"缓存频繁使用的昂贵计算结果"的最佳实践一致)。
数组运算:一次性处理整批红移
所有方法都对 NumPy 数组原生支持且已向量化,不必写 Python 循环:
import numpy as np
z_array = np.linspace(0, 5, 100) # 0 到 5 之间均匀取 100 个红移
d_L_array = cosmo.luminosity_distance(z_array) # 光度距离数组
H_array = cosmo.H(z_array) # 哈勃参数数组
age_array = cosmo.age(z_array) # 年龄数组
输入标量返回标量 Quantity,输入数组返回同形状的 Quantity 数组。画 D_L(z)、H(z)、age(z) 关系曲线、或对一批测光红移做批量换算时,这种用法既简洁又高效。
中微子效应:Neff 与 m_nu
当精度要求高(例如拟合 CMB 或做高精度距离比较)时,可以纳入大质量中微子的影响:
from astropy.cosmology import FlatLambdaCDM
from astropy import units as u
cosmo = FlatLambdaCDM(
H0=70 * u.km/u.s/u.Mpc,
Om0=0.3,
Tcmb0=2.725 * u.K,
Neff=3.04, # 有效中微子代数(标准值 3.04)
m_nu=[0., 0., 0.06] * u.eV # 三种味中微子的质量
)
参数说明:
Neff:有效相对论性自由度,标准模型取 3.04(略大于 3 源于微小的非瞬时退耦效应)。m_nu:三味(电子、μ、τ)中微子质量数组,必须用u.eV标注单位。非零质量使中微子从辐射样演化为物质样,从而微调各 z 处的距离与年龄。
性能权衡:纳入大质量中微子后,模型中的若干积分需要处理更复杂的动量/质量依赖,据参考文档的经验提示,计算速度会下降约 3–4 倍,但换来更精确的结果。取舍策略是:常规工程估算用无质量中微子;只有需要与精密宇宙学数据对齐时才开启 m_nu。
不可变性:克隆并修改模型
模型对象是不可变的——构造后不能原地改 H0 等参数。需要参数微调时用 clone 生成副本:
# 复制并更换 H0
cosmo_new = cosmo.clone(H0=72 * u.km/u.s/u.Mpc)
# 复制并重命名(便于日志与结果标注)
cosmo_named = cosmo.clone(name="My Custom Cosmology")
clone 只会改动传入的关键字参数,其余沿用原模型。做参数扫描(如检验 H0 不确定性对距离的影响)时,这一模式比反复从零构造更清晰。
高频实战案例组合
由视星等与红移计算绝对星等
z = 1.5
m_app = 24.5 # 视星等
d_L = cosmo.luminosity_distance(z)
M_abs = m_app - cosmo.distmod(z).value # 绝对星等(星等单位做减法,取纯数值)
巡天体积估算(两红移面之间)
z_min, z_max = 0.5, 1.5
volume = cosmo.comoving_volume(z_max) - cosmo.comoving_volume(z_min) # 壳体体积
# 单位化为 Gpc³ 便于报告
volume_gpc3 = volume.to(u.Gpc**3)
由角大小求物理尺寸
theta = 1 * u.arcsec # 角大小
z = 2.0
d_A = cosmo.angular_diameter_distance(z)
size_kpc = (d_A * theta.to(u.radian)).to(u.kpc) # 直接得到带单位尺寸
(注意与上文中使用 .value 的写法对比:若想保持全程带单位,就做量纲相乘后用 .to(u.kpc);若中途要进入对数/标量公式,则先 .value。两种风格各有适用场景。)
天体形成以来经过的时间
z_formation = 6
age_at_formation = cosmo.age(z_formation) # 该红移处宇宙年龄
time_since_formation = cosmo.age(0) - age_at_formation # 从形成到现在的时间
不同模型结果对比
from astropy.cosmology import Planck18, WMAP9
z = 1.0
print(f"Planck18 d_L: {Planck18.luminosity_distance(z)}")
print(f"WMAP9 d_L: {WMAP9.luminosity_distance(z)}")
把多个内置实例并排调用同一方法,即可量化宇宙学参数选择带来的系统差(例如 Planck18 与 WMAP9 的 H0 取值不同,会导致距离差若干百分点)。这类对比是研究论文中"宇宙学假设影响"讨论的标准写法。
性能要点与有效范围
综合参考文档与技能最佳实践,使用时请注意:
- 常规计算很快:对大多数单点 z 计算,开销可忽略;整套接口面向交互与批量场景设计。
- 中微子是主要减速项:开启
m_nu后慢 3–4 倍,批量大数组时尤其明显。 - 数组已向量化:优先把
z组织成数组一次算完,而不是在 Python 循环里逐点调用。 - 结果有效范围:各方法在 z ≲ 5000–6000 内有效(具体上限依模型而定,辐射主导极早期的高 z 外推需谨慎)。超出范围或需要极高精度时,应核对官方 API 说明与数值积分假设。
- 昂贵结果值得缓存:若同一 z 集合会被多处复用(重复画图、多次对比),先算好
Quantity数组缓存起来,避免重复积分。
与技能内其他参考的配合使用
astropy.cosmology 通常不是孤立使用的:真实工作流往往是"读表/读 FITS → 坐标变换 → 用单位做量纲换算 → 宇宙学距离/时间换算"。在 scientific-agent-skills 的 astropy 技能内部,本文对应的参考文档与以下文件配合可覆盖完整链路:
- units.md:本文所有返回值的单位换算、
.to()、星等/对数单位等底层能力; - coordinates.md:天球坐标与红移观测量的坐标变换;
- tables.md:批量星表(含红移列)的读写、过滤与匹配,是"对一列 z 批量算距离"的常见前置;
- fits.md:从 FITS 星表/图像读出红移或距离相关数据;
- SKILL.md:技能入口,含完整快速上手示例、安装与环境、网络访问注意事项与版本说明。
版本方面再次提醒:以 Astropy 7.2.0 为准(Python 3.11+),并关注 8.0 发布后对旧 astropy.cosmology.* 子模块 shim 的移除——从现在起坚持从 astropy.cosmology 顶层导入,即可平滑迁移到未来版本。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python08
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00