Files
Jyotisha/scripts/nakshatra_advanced.py
T
732642856 0178dfb3e8 v3.7.0: 新增7大模块 - BPHS十六分盘/精确相位/Jaimini/高级Nakshatra/Argala门闩/Tajika年运/合盘分析
- varga.py: D2-D60 BPHS十六分盘完整计算
- aspects.py: 度数精确相位系统(tight/moderate/loose)
- jaimini.py: Chara Karaka 7/8 + Chara Dasha + Karakamsha
- nakshatra_advanced.py: Tara Bala + Sub-Lord KP系统
- argala.py: Argala门闩 + Virodha反干预
- tajika.py: Muntha/YearLord/Mudda Dasha/Tri-Pataka
- synastry.py: Ashta Koota 36分制 + Mangal Dosha + Papasamya

引擎升级至v3.7.0, 21个子命令全链路验证通过
2026-04-25 00:34:21 +08:00

233 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
高级星宿分析模块 v1.0
Nakshatra深度分析系统
支持:
- Tara Bala(星宿力量匹配)
- Sub-Lord体系(KP占星)
- 精确Vimshottari起始点计算
- Nakshatra兼容性分析
- Navatara9星宿组)分类
"""
from typing import Dict, List, Tuple
import math
NAK_LIST = [
("Ashwini","Ketu",7),("Bharani","Venus",20),("Krittika","Sun",6),
("Rohini","Moon",10),("Mrigashira","Mars",7),("Ardra","Rahu",18),
("Punarvasu","Jupiter",16),("Pushya","Saturn",19),("Ashlesha","Mercury",17),
("Magha","Ketu",7),("Purva Phalguni","Venus",20),("Uttara Phalguni","Sun",6),
("Hasta","Moon",10),("Chitra","Mars",7),("Swati","Rahu",18),
("Vishakha","Jupiter",16),("Anuradha","Saturn",19),("Jyeshtha","Mercury",17),
("Mula","Ketu",7),("Purva Ashadha","Venus",20),("Uttara Ashadha","Sun",6),
("Shravana","Moon",10),("Dhanishta","Mars",7),("Shatabhisha","Rahu",18),
("Purva Bhadrapada","Jupiter",16),("Uttara Bhadrapada","Saturn",19),("Revati","Mercury",17),
]
NAK_NAMES = [n[0] for n in NAK_LIST]
NAK_LORDS = [n[1] for n in NAK_LIST]
NAK_YEARS = [n[2] for n in NAK_LIST]
# Navatara分组(从月亮星宿开始的9个星宿循环)
TARA_NAMES = ['Janma(生命)','Sampat(财富)','Vipat(危险)','Kshema(安全)',
'Pratyak(障碍)','Sadhana(成就)','Vadha(毁灭)','Mitra(友好)','ParamaMitra(至友)']
TARA_CN = {0:'生命Tara',1:'财富Tara',2:'危险Tara',3:'安全Tara',
4:'障碍Tara',5:'成就Tara',6:'毁灭Tara',7:'友好Tara',8:'至友Tara'}
# Nakshatra元素和属性
NAK_GANA = { # 气质类型
0:'Dev(神圣)',1:'Manushya(人类)',2:'Rakshasa(罗刹)',
3:'Dev',4:'Dev',5:'Manushya',6:'Dev',7:'Dev',8:'Rakshasa',
9:'Rakshasa',10:'Manushya',11:'Manushya',12:'Dev',13:'Rakshasa',14:'Dev',
15:'Rakshasa',16:'Dev',17:'Rakshasa',18:'Rakshasa',19:'Manushya',20:'Manushya',
21:'Dev',22:'Rakshasa',23:'Rakshasa',24:'Manushya',25:'Manushya',26:'Dev',
}
NAK_ELEMENT = {
0:'',1:'',2:'',3:'',4:'',5:'',6:'',7:'',8:'',
9:'',10:'',11:'',12:'',13:'',14:'',15:'',16:'',17:'',
18:'',19:'',20:'',21:'',22:'',23:'',24:'',25:'',26:'',
}
def find_nakshatra(longitude: float) -> Dict:
"""从恒星黄道经度精确计算Nakshatra"""
nak_span = 360.0 / 27 # 每个星宿13.333...°
nak_idx = int(longitude / nak_span) % 27
nak_start = nak_idx * nak_span
deg_in_nak = longitude - nak_start
pada_span = nak_span / 4 # 每个Pada 3.333...°
pada = int(deg_in_nak / pada_span) + 1
deg_in_pada = deg_in_nak - (pada - 1) * pada_span
return {
'nakshatra': NAK_NAMES[nak_idx],
'nakshatra_idx': nak_idx,
'nakshatra_lord': NAK_LORDS[nak_idx],
'dasha_years': NAK_YEARS[nak_idx],
'pada': pada,
'degree_in_nakshatra': round(deg_in_nak, 4),
'degree_in_pada': round(deg_in_pada, 4),
'gana': NAK_GANA.get(nak_idx, ''),
'element': NAK_ELEMENT.get(nak_idx, ''),
}
def calc_tara_bala(moon_nak_idx: int, target_nak_idx: int) -> Dict:
"""
Tara Bala计算:月亮星宿到目标星宿的9星宿循环关系
用于判断某个行星/事件星宿与月亮星宿的关系
0=Janma(中性), 1=Sampat(吉), 2=Vipat(凶), 3=Kshema(吉),
4=Pratyak(凶), 5=Sadhana(吉), 6=Vadha(凶), 7=Mitra(吉), 8=ParamaMitra(大吉)
"""
distance = (target_nak_idx - moon_nak_idx) % 9
tara_name = TARA_NAMES[distance]
tara_cn = TARA_CN[distance]
is_auspicious = distance in (1, 3, 5, 7, 8)
is_dangerous = distance in (2, 4, 6)
return {
'tara_index': distance,
'tara_name': tara_name,
'tara_cn': tara_cn,
'is_auspicious': is_auspicious,
'is_dangerous': is_dangerous,
'quality': 'auspicious' if is_auspicious else 'dangerous' if is_dangerous else 'neutral',
'interpretation': _tara_interp(distance),
}
def calc_all_tara_balas(moon_nak_idx: int, planet_lons: Dict[str, float]) -> Dict:
"""计算所有行星相对于月亮的Tara Bala"""
results = {}
for pname, lon in planet_lons.items():
p_nak = find_nakshatra(lon)
tara = calc_tara_bala(moon_nak_idx, p_nak['nakshatra_idx'])
results[pname] = {
'nakshatra': p_nak['nakshatra'],
'tara': tara,
}
return results
def calc_vimshottari_start(moon_longitude: float) -> Dict:
"""
精确计算Vimshottari Dasha的起始点
返回月亮所在星宿的守护星、已用度数比例、剩余年数
"""
nak = find_nakshatra(moon_longitude)
nak_idx = nak['nakshatra_idx']
nak_lord = NAK_LORDS[nak_idx]
total_years = NAK_YEARS[nak_idx]
# 已用比例
nak_span = 360.0 / 27
nak_start = nak_idx * nak_span
deg_in_nak = moon_longitude - nak_start
used_ratio = deg_in_nak / nak_span
remaining_ratio = 1 - used_ratio
# 第一个Mahadasha的剩余年数
first_mahadasha_remaining = total_years * remaining_ratio
first_mahadasha_elapsed = total_years * used_ratio
return {
'moon_nakshatra': nak['nakshatra'],
'moon_nakshatra_lord': nak_lord,
'moon_pada': nak['pada'],
'total_dasha_years': total_years,
'used_ratio': round(used_ratio, 6),
'remaining_ratio': round(remaining_ratio, 6),
'first_mahadasha_remaining_years': round(first_mahadasha_remaining, 4),
'first_mahadasha_elapsed_years': round(first_mahadasha_elapsed, 4),
'first_mahadasha_lord': nak_lord,
}
def calc_sub_lord(longitude: float, division: int = 9) -> Dict:
"""
Sub-Lord计算(KP占星体系)
将星宿进一步细分为Sub-Lord和Sub-Sub-Lord
参数:
longitude: 恒星黄道经度
division: 细分层级(9=Sub-Lord, 81=Sub-Sub-Lord
"""
# 主星宿
nak = find_nakshatra(longitude)
nak_span = 360.0 / 27
# Sub-Lord: 将星宿按守护星的大运年数比例细分
total_dasha_years = sum(NAK_YEARS) # 120年
nak_lord = NAK_NAMES[nak['nakshatra_idx']]
# 计算Sub-Lord
deg_in_nak = nak['degree_in_nakshatra']
sub_lord_span = nak_span * (NAK_YEARS[NAK_LORDS.index(NAK_LORDS[nak['nakshatra_idx']])]) / total_dasha_years
# 简化版:直接按9等分
sub_span = nak_span / 9
sub_idx = int(deg_in_nak / sub_span) % 9
# Sub-Lord是第sub_idx个行星(从星宿守护星开始的大运顺序)
DASHA_ORDER = ["Ketu","Venus","Sun","Moon","Mars","Rahu","Jupiter","Saturn","Mercury"]
nak_lord_idx = DASHA_ORDER.index(NAK_LORDS[nak['nakshatra_idx']])
sub_lord = DASHA_ORDER[(nak_lord_idx + sub_idx) % 9]
return {
'nakshatra': nak['nakshatra'],
'nakshatra_lord': nak_lord,
'sub_lord': sub_lord,
'sub_index': sub_idx,
'pada': nak['pada'],
'degree_in_nakshatra': round(deg_in_nak, 4),
}
def nakshatra_compatibility(nak1_idx: int, nak2_idx: int) -> Dict:
"""
Nakshatra兼容性分析(Koota系统中的星宿匹配部分)
基于Tara Bala和Nakshatra元素匹配
"""
# Tara匹配
tara = calc_tara_bala(nak1_idx, nak2_idx)
tara_score = 3 if tara['is_auspicious'] else 0 if tara['is_dangerous'] else 1.5
# 元素匹配
el1 = NAK_ELEMENT.get(nak1_idx, '')
el2 = NAK_ELEMENT.get(nak2_idx, '')
el_compatible = el1 == el2 or (el1 in ('','') and el2 in ('','')) or (el1 in ('','') and el2 in ('',''))
# Gana匹配
g1 = NAK_GANA.get(nak1_idx, '')
g2 = NAK_GANA.get(nak2_idx, '')
gana_score = 6 if g1 == g2 else 3 if ('Dev' in g1 and 'Manushya' in g2) or ('Manushya' in g1 and 'Dev' in g2) else 0
return {
'nak1': NAK_NAMES[nak1_idx],
'nak2': NAK_NAMES[nak2_idx],
'tara_bala': tara,
'tara_score': tara_score,
'element_match': {'e1': el1, 'e2': el2, 'compatible': el_compatible},
'gana_match': {'g1': g1, 'g2': g2, 'score': gana_score},
'overall': 'compatible' if tara_score >= 1.5 and el_compatible else 'challenging' if tara['is_dangerous'] else 'moderate',
}
def _tara_interp(idx):
interps = {
0: '生命Tara—中性,代表自我,不吉不凶',
1: '财富Tara—吉,带来物质和精神增长',
2: '危险Tara—凶,需要谨慎,可能带来损失',
3: '安全Tara—吉,提供保护和稳定',
4: '障碍Tara—凶,可能面临困难和延误',
5: '成就Tara—吉,有利于实现目标',
6: '毁灭Tara—凶,最大凶Tara,需特别注意',
7: '友好Tara—吉,提供支持和帮助',
8: '至友Tara—大吉,最强吉Tara',
}
return interps.get(idx, '')