cosmo/backend/scripts/add_binary_systems.py

488 lines
17 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env python3
"""
补全高价值双星/多星系统数据
包含8-10个科学价值最高的多恒星系统
"""
import asyncio
import asyncpg
import json
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 数据库连接配置
DB_CONFIG = {
"host": "localhost",
"port": 5432,
"user": "postgres",
"password": "postgres",
"database": "cosmo_db"
}
# 高价值多恒星系统数据(基于天文学资料)
MULTI_STAR_SYSTEMS = {
# 1. Alpha Centauri (比邻星系统) - 已完成,保留用于验证
479: {
"stars": [
{
"id": "star-479-primary",
"name": "Alpha Centauri A",
"name_zh": "南门二A",
"description": "该恒星系主序星,光谱类型: G2V, 表面温度: 5790K",
"extra_data": {
"spectral_type": "G2V",
"mass_solar": 1.1,
"radius_solar": 1.22,
"temperature_k": 5790
}
},
{
"id": "star-479-secondary",
"name": "Alpha Centauri B",
"name_zh": "南门二B",
"description": "与南门二A相互绕转的明亮双星是该系统的主体。",
"extra_data": {
"spectral_type": "K1V",
"mass_solar": 0.93,
"radius_solar": 0.86,
"temperature_k": 5260
}
},
{
"id": "star-479-tertiary",
"name": "Proxima Centauri",
"name_zh": "比邻星",
"description": "一颗质量小、光度弱的红矮星距离南门二A/B约0.2光年,围绕它们公转。",
"extra_data": {
"spectral_type": "M5.5V",
"mass_solar": 0.12,
"radius_solar": 0.14,
"temperature_k": 2900
}
}
]
},
# 2. 55 Cancri (巨蟹座55) - 双星系统
11: {
"stars": [
{
"id": "star-11-primary",
"name": "55 Cancri A",
"name_zh": "巨蟹座55A",
"description": "类太阳黄矮星拥有5颗已确认行星包括著名的超级地球55 Cnc e。",
"extra_data": {
"spectral_type": "G8V",
"mass_solar": 0.95,
"radius_solar": 0.94,
"temperature_k": 5196
}
},
{
"id": "star-11-secondary",
"name": "55 Cancri B",
"name_zh": "巨蟹座55B",
"description": "红矮星伴星距离A星约1065 AU轨道周期约1000年。",
"extra_data": {
"spectral_type": "M4V",
"mass_solar": 0.13,
"radius_solar": 0.30,
"temperature_k": 3200,
"separation_au": 1065,
"orbital_period_years": 1000
}
}
]
},
# 3. 16 Cygni (天鹅座16) - 双星系统
5: {
"stars": [
{
"id": "star-5-primary",
"name": "16 Cygni A",
"name_zh": "天鹅座16A",
"description": "类太阳黄矮星,该双星系统的主星。",
"extra_data": {
"spectral_type": "G1.5V",
"mass_solar": 1.11,
"radius_solar": 1.24,
"temperature_k": 5825
}
},
{
"id": "star-5-secondary",
"name": "16 Cygni B",
"name_zh": "天鹅座16B",
"description": "类太阳黄矮星拥有一颗高偏心率轨道的行星16 Cyg B b展示了双星引力对行星轨道的影响。",
"extra_data": {
"spectral_type": "G2.5V",
"mass_solar": 1.07,
"radius_solar": 1.14,
"temperature_k": 5750,
"separation_au": 850,
"orbital_period_years": 18200
}
}
]
},
# 4. Epsilon Indi (天园增四) - 三体系统 (1恒星 + 2棕矮星)
40: {
"stars": [
{
"id": "star-40-primary",
"name": "Epsilon Indi A",
"name_zh": "天园增四A",
"description": "橙矮星第五近的恒星系统伴有两颗棕矮星Ba和Bb",
"extra_data": {
"spectral_type": "K5V",
"mass_solar": 0.76,
"radius_solar": 0.73,
"temperature_k": 4630
}
},
{
"id": "star-40-secondary",
"name": "Epsilon Indi Ba",
"name_zh": "天园增四Ba",
"description": "T1V型棕矮星距离A星约1460 AU与Bb组成棕矮星双星系统。",
"extra_data": {
"spectral_type": "T1V",
"mass_jupiter": 47,
"radius_jupiter": 0.91,
"temperature_k": 1300,
"separation_from_A_au": 1460,
"is_brown_dwarf": True
}
},
{
"id": "star-40-tertiary",
"name": "Epsilon Indi Bb",
"name_zh": "天园增四Bb",
"description": "T6V型棕矮星与Ba互绕周期约15年是最近的棕矮星双星系统。",
"extra_data": {
"spectral_type": "T6V",
"mass_jupiter": 28,
"radius_jupiter": 0.80,
"temperature_k": 880,
"orbital_period_years": 15,
"is_brown_dwarf": True
}
}
]
},
# 5. Gamma Cephei (仙王座γ) - 双星系统
49: {
"stars": [
{
"id": "star-49-primary",
"name": "Gamma Cephei A",
"name_zh": "仙王座γA",
"description": "亚巨星最早被怀疑有行星的恒星之一1988年拥有一颗类木行星。",
"extra_data": {
"spectral_type": "K1IV",
"mass_solar": 1.59,
"radius_solar": 4.9,
"temperature_k": 4800
}
},
{
"id": "star-49-secondary",
"name": "Gamma Cephei B",
"name_zh": "仙王座γB",
"description": "红矮星伴星距离A星约20 AU轨道周期约66年形成紧密双星系统。",
"extra_data": {
"spectral_type": "M4V",
"mass_solar": 0.4,
"radius_solar": 0.40,
"temperature_k": 3200,
"separation_au": 20,
"orbital_period_years": 66
}
}
]
},
# 6. Upsilon Andromedae (仙女座υ) - 双星系统
572: {
"stars": [
{
"id": "star-572-primary",
"name": "Upsilon Andromedae A",
"name_zh": "仙女座υA",
"description": "黄白主序星第一个被发现有多颗行星的主序星1999年拥有4颗已确认行星。",
"extra_data": {
"spectral_type": "F8V",
"mass_solar": 1.27,
"radius_solar": 1.63,
"temperature_k": 6212
}
},
{
"id": "star-572-secondary",
"name": "Upsilon Andromedae B",
"name_zh": "仙女座υB",
"description": "红矮星伴星距离A星约750 AU。",
"extra_data": {
"spectral_type": "M4.5V",
"mass_solar": 0.25,
"radius_solar": 0.28,
"temperature_k": 3100,
"separation_au": 750
}
}
]
},
# 7. HD 41004 - 双星系统两个独立的system_id需要合并
347: {
"stars": [
{
"id": "star-347-primary",
"name": "HD 41004 A",
"name_zh": "HD 41004 A",
"description": "橙矮星拥有一颗类木行星HD 41004 A b。",
"extra_data": {
"spectral_type": "K1V",
"mass_solar": 0.70,
"radius_solar": 0.67,
"temperature_k": 5000
}
},
{
"id": "star-347-secondary",
"name": "HD 41004 B",
"name_zh": "HD 41004 B",
"description": "红矮星伴星距离A星约23 AU可能拥有棕矮星伴星。",
"extra_data": {
"spectral_type": "M2V",
"mass_solar": 0.40,
"radius_solar": 0.39,
"temperature_k": 3400,
"separation_au": 23
}
}
]
},
# 8. GJ 86 (格利泽86) - 双星系统(橙矮星 + 白矮星)
128: {
"stars": [
{
"id": "star-128-primary",
"name": "GJ 86 A",
"name_zh": "格利泽86A",
"description": "橙矮星拥有一颗类木行星GJ 86 b伴星是罕见的白矮星。",
"extra_data": {
"spectral_type": "K1V",
"mass_solar": 0.79,
"radius_solar": 0.77,
"temperature_k": 5100
}
},
{
"id": "star-128-secondary",
"name": "GJ 86 B",
"name_zh": "格利泽86B",
"description": "白矮星伴星距离A星约21 AU是研究恒星演化对行星影响的重要案例。",
"extra_data": {
"spectral_type": "DA (白矮星)",
"mass_solar": 0.55,
"radius_solar": 0.01,
"temperature_k": 8000,
"separation_au": 21,
"is_white_dwarf": True
}
}
]
},
# 9. HD 196885 - 双星系统
267: {
"stars": [
{
"id": "star-267-primary",
"name": "HD 196885 A",
"name_zh": "HD 196885 A",
"description": "黄白主序星拥有一颗行星HD 196885 A b。",
"extra_data": {
"spectral_type": "F8V",
"mass_solar": 1.33,
"radius_solar": 1.68,
"temperature_k": 6172
}
},
{
"id": "star-267-secondary",
"name": "HD 196885 B",
"name_zh": "HD 196885 B",
"description": "红矮星伴星距离A星约25 AU。",
"extra_data": {
"spectral_type": "M",
"mass_solar": 0.45,
"radius_solar": 0.43,
"temperature_k": 3500,
"separation_au": 25
}
}
]
}
}
async def add_missing_stars(conn):
"""添加缺失的恒星"""
logger.info("=" * 80)
logger.info("开始补全多恒星系统数据")
logger.info("=" * 80)
added_count = 0
skipped_count = 0
for system_id, system_data in MULTI_STAR_SYSTEMS.items():
# 检查系统是否存在
system = await conn.fetchrow(
"SELECT id, name, name_zh FROM star_systems WHERE id = $1",
system_id
)
if not system:
logger.warning(f"\n⚠️ 系统ID={system_id}不存在,跳过")
continue
logger.info(f"\n{'='*80}")
logger.info(f"处理恒星系统: {system['name_zh'] or system['name']} (ID={system_id})")
logger.info(f"{'='*80}")
for star in system_data["stars"]:
# 检查是否已存在
existing = await conn.fetchrow(
"SELECT id FROM celestial_bodies WHERE id = $1",
star["id"]
)
if existing:
logger.info(f" ✓ 恒星已存在: {star['name_zh']} ({star['id']})")
skipped_count += 1
else:
# 插入新恒星
await conn.execute("""
INSERT INTO celestial_bodies
(id, name, name_zh, type, system_id, description, is_active, extra_data, created_at, updated_at)
VALUES
($1, $2, $3, 'star', $4, $5, TRUE, $6::jsonb, NOW(), NOW())
""",
star["id"],
star["name"],
star["name_zh"],
system_id,
star["description"],
json.dumps(star["extra_data"])
)
logger.info(f" ✅ 添加恒星: {star['name_zh']} ({star['id']})")
added_count += 1
logger.info(f"\n{'='*80}")
logger.info(f"恒星数据补全完成!")
logger.info(f" 新增: {added_count}")
logger.info(f" 跳过: {skipped_count}颗(已存在)")
logger.info(f"{'='*80}")
async def verify_results(conn):
"""验证结果"""
logger.info("\n" + "=" * 80)
logger.info("验证多星系统数据")
logger.info("=" * 80)
system_ids = list(MULTI_STAR_SYSTEMS.keys())
rows = await conn.fetch("""
SELECT
s.id,
s.name,
s.name_zh,
COUNT(CASE WHEN cb.type = 'star' THEN 1 END) as star_count,
COUNT(CASE WHEN cb.type = 'planet' THEN 1 END) as planet_count,
COUNT(CASE WHEN cb.is_active = TRUE THEN 1 END) as active_count,
string_agg(
CASE WHEN cb.type = 'star' THEN cb.name_zh || ' (' || cb.id || ')' END,
', '
ORDER BY cb.id
) as star_names
FROM star_systems s
LEFT JOIN celestial_bodies cb ON s.id = cb.system_id
WHERE s.id = ANY($1)
GROUP BY s.id, s.name, s.name_zh
ORDER BY s.id
""", system_ids)
print(f"\n{'系统ID':<8} {'系统名称':<30} {'恒星数':<8} {'行星数':<8} {'启用数':<8}")
print("=" * 100)
for row in rows:
system_name = row['name_zh'] or row['name']
print(f"{row['id']:<8} {system_name:<30} {row['star_count']:<8} {row['planet_count']:<8} {row['active_count']:<8}")
# 详细显示每个系统的恒星
print(f"\n{'='*100}")
print("各系统恒星详情:")
print(f"{'='*100}")
for row in rows:
system_name = row['name_zh'] or row['name']
stars = await conn.fetch("""
SELECT id, name, name_zh, extra_data
FROM celestial_bodies
WHERE system_id = $1 AND type = 'star'
ORDER BY id
""", row['id'])
print(f"\n{system_name} (ID={row['id']}):")
for star in stars:
# Handle both dict and JSON string
extra = star['extra_data']
if isinstance(extra, str):
extra = json.loads(extra) if extra else {}
elif extra is None:
extra = {}
spectral = extra.get('spectral_type', 'N/A')
mass = extra.get('mass_solar', extra.get('mass_jupiter'))
mass_unit = 'M☉' if 'mass_solar' in extra else ('MJ' if 'mass_jupiter' in extra else '')
print(f"{star['name_zh']:<25} | 光谱: {spectral:<10} | 质量: {mass}{mass_unit if mass else 'N/A'}")
async def main():
"""主函数"""
print("\n" + "=" * 80)
print("多恒星系统数据补全脚本 v2.0")
print("将补全8-10个高价值双星/多星系统")
print("=" * 80)
conn = await asyncpg.connect(**DB_CONFIG)
try:
# 1. 添加缺失的恒星
await add_missing_stars(conn)
# 2. 验证结果
await verify_results(conn)
print("\n" + "=" * 80)
print("✅ 所有操作完成!")
print("=" * 80)
except Exception as e:
logger.error(f"❌ 发生错误: {e}")
import traceback
traceback.print_exc()
finally:
await conn.close()
if __name__ == "__main__":
asyncio.run(main())