v6.2.0: 全面技法宝库升级 — 16个新模块 + 12个文件优化
## 新增模块 (16个) ### P0 精度修复 - ashtakavarga: calc_prastara_av() + calc_sodhita_av() - kakshya.py: Kakshya评分系统 (8区间×3.75°) - shadbala.py: Sputa Drishti + Yuddha Bala ### P1 核心升级 - bhava_bala.py: 宫位三元力量 (jyotishganit MIT) - pancha_mahapurusha.py: PMC完整检测含4层失效条件 - sade_sati.py: Sade Sati+Kantaka Shani - sudarshana_chakra.py: 三参考点盘+收敛分析 - tajika.py: Sahams 7→36 + Tajika Yogas 10种 - birth_time_rectifier.py: 生时矫正 ### P2 覆盖扩展 - kp_system.py: KP Sublord+ABCD Significator (diliprk/VedicAstro MIT) - synastry.py: 16因子合盘36分制 (dashaflow MIT) - muhurtha_election.py: 6活动选举 (dashaflow MIT) - career_analysis.py: 结构化事业引擎 - relationship_analysis.py: 结构化感情引擎 - conditional_dashas.py: Dwisaptati+Shattrimsa+Dwadashottari - divisional_charts_extended: D81/D108/D144 - remedies.py: 5类补救系统 ## 修改文件 jaimini/dasha_calculator/shadbala/SKILL.md/COVERAGE_AUDIT等12个 ## 开源复用: 4个MIT项目
This commit is contained in:
+177
-243
@@ -1,269 +1,203 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Sudarshana Chakra(三轮盘同参) v1.0
|
||||
参考:PyJHora sudharsana_chakra.py 算法思路 + BPHS标准
|
||||
License: MIT
|
||||
Sudarshana Chakra(苏达沙那轮)模块
|
||||
基于BPHS传统三参考点盘系统
|
||||
|
||||
Sudarshana Chakra 是结合三个"盘"的综合分析:
|
||||
内圈 = 本命盘(以Lagna为第1宫)
|
||||
中圈 = 月亮盘(以Moon星座为第1宫)
|
||||
外圈 = 太阳盘(以Sun星座为第1宫)
|
||||
三个参考点:
|
||||
1. Lagna (上升) → 自我、身体
|
||||
2. Chandra (月亮) → 情感、心理
|
||||
3. Surya (太阳) → 灵魂、生命力
|
||||
|
||||
核心分析:三环汇聚 — 同一宫位编号在三圈中有相同行星或主题
|
||||
当三个参考点中同一宫位/行星配置一致时,事件确认度高。
|
||||
"""
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
from typing import Dict, List
|
||||
|
||||
SIGNS = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo',
|
||||
'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces']
|
||||
|
||||
SIGN_LORDS = {
|
||||
'Aries': 'Mars', 'Taurus': 'Venus', 'Gemini': 'Mercury', 'Cancer': 'Moon',
|
||||
'Leo': 'Sun', 'Virgo': 'Mercury', 'Libra': 'Venus', 'Scorpio': 'Mars',
|
||||
'Sagittarius': 'Jupiter', 'Capricorn': 'Saturn', 'Aquarius': 'Saturn', 'Pisces': 'Jupiter'
|
||||
}
|
||||
|
||||
|
||||
def build_rotated_chart(raw_planets: Dict, anchor_sign_idx: int) -> Dict:
|
||||
def _build_reference_chart(planet_positions: Dict, reference_sign_idx: int) -> Dict:
|
||||
"""
|
||||
以指定星座为第1宫,构建旋转后的12宫宫位映射
|
||||
|
||||
基于指定参考点构建重新排列的星盘。
|
||||
|
||||
以reference_sign_idx为第1宫,重新计算所有行星的宫位。
|
||||
|
||||
Args:
|
||||
raw_planets: {planet_name: {"sign_idx": int, "degree": float, ...}}
|
||||
anchor_sign_idx: 作为第1宫的星座索引
|
||||
|
||||
Returns:
|
||||
{planet_name: house_1to12}
|
||||
"""
|
||||
result = {}
|
||||
for pname, data in raw_planets.items():
|
||||
sign_idx = data.get("sign_idx", 0)
|
||||
house = ((sign_idx - anchor_sign_idx) % 12) + 1
|
||||
result[pname] = house
|
||||
return result
|
||||
planet_positions: {planet: {'sign_idx': int, 'degree': float}}
|
||||
reference_sign_idx: 参考星座索引(作为第1宫)
|
||||
|
||||
|
||||
def calculate_sudarshana_chakra(raw_planets: Dict, lagna_sign_idx: int,
|
||||
moon_sign_idx: int, sun_sign_idx: int) -> Dict:
|
||||
"""
|
||||
Sudarshana Chakra 三轮盘同参计算
|
||||
|
||||
Args:
|
||||
raw_planets: 行星数据 {name: {sign_idx, degree, ...}}
|
||||
lagna_sign_idx: Lagna所在星座索引
|
||||
moon_sign_idx: 月亮所在星座索引
|
||||
sun_sign_idx: 太阳所在星座索引
|
||||
|
||||
Returns:
|
||||
{
|
||||
"charts": {
|
||||
"lagna_chart": {planet: house}, # 内圈
|
||||
"moon_chart": {planet: house}, # 中圈
|
||||
"sun_chart": {planet: house}, # 外圈
|
||||
},
|
||||
"convergences": {house_index: {"planets": [names], "circles": int}},
|
||||
"triple_convergences": [house_indices], # 三环汇聚
|
||||
"dual_convergences": [house_indices], # 双环汇聚
|
||||
}
|
||||
重新排列的星盘 {planet: {'house': int, 'sign': str, ...}}
|
||||
"""
|
||||
# 构建三个圈
|
||||
lagna_chart = build_rotated_chart(raw_planets, lagna_sign_idx)
|
||||
moon_chart = build_rotated_chart(raw_planets, moon_sign_idx)
|
||||
sun_chart = build_rotated_chart(raw_planets, sun_sign_idx)
|
||||
|
||||
# 分析每宫的汇聚情况
|
||||
convergences = {}
|
||||
chart = {
|
||||
'reference_sign': SIGNS[reference_sign_idx],
|
||||
'houses': {},
|
||||
'planets': {},
|
||||
}
|
||||
|
||||
# 计算每个宫位对应的星座
|
||||
for house_num in range(1, 13):
|
||||
# 找出三个圈中落入该宫的行星
|
||||
planets_in = {}
|
||||
for pname in raw_planets:
|
||||
if pname in ('Rahu', 'Ketu'):
|
||||
continue
|
||||
houses = (
|
||||
lagna_chart.get(pname, 0),
|
||||
moon_chart.get(pname, 0),
|
||||
sun_chart.get(pname, 0)
|
||||
)
|
||||
circles = sum(1 for h in houses if h == house_num)
|
||||
if circles >= 2:
|
||||
planets_in[pname] = circles
|
||||
|
||||
if planets_in:
|
||||
convergences[house_num] = {
|
||||
"planets": list(planets_in.keys()),
|
||||
"max_circles": max(planets_in.values()),
|
||||
"details": planets_in,
|
||||
}
|
||||
|
||||
# 三环汇聚(最强)
|
||||
triple = [h for h, data in convergences.items()
|
||||
if data["max_circles"] == 3]
|
||||
|
||||
# 双环汇聚
|
||||
dual = [h for h, data in convergences.items()
|
||||
if data["max_circles"] == 2]
|
||||
|
||||
return {
|
||||
"charts": {
|
||||
"lagna_chart": lagna_chart,
|
||||
"moon_chart": moon_chart,
|
||||
"sun_chart": sun_chart,
|
||||
},
|
||||
"convergences": convergences,
|
||||
"triple_convergences": triple,
|
||||
"dual_convergences": dual,
|
||||
"triple_count": len(triple),
|
||||
"dual_count": len(dual),
|
||||
"summary": _generate_summary(triple, dual, lagna_chart, moon_chart, sun_chart),
|
||||
}
|
||||
|
||||
|
||||
def calculate_sd_chakra_with_vargas(raw_planets: Dict,
|
||||
chart_d1: Dict,
|
||||
chart_d9: Dict,
|
||||
chart_d10: Dict,
|
||||
lagna_d1: int,
|
||||
lagna_d9: int,
|
||||
lagna_d10: int) -> Dict:
|
||||
"""
|
||||
Sudarshana Chakra 现代变体:D1 × D9 × D10 三角形分析
|
||||
|
||||
Args:
|
||||
chart_d1/d9/d10: 各盘的行星宫位数据
|
||||
lagna_d1/d9/d10: 各盘的Lagna宫位索引
|
||||
|
||||
Returns:
|
||||
三盘跨盘分析结果
|
||||
"""
|
||||
# 对各盘以各自Lagna为第1宫旋转
|
||||
d1_rotated = build_rotated_chart(chart_d1, lagna_d1)
|
||||
d9_rotated = build_rotated_chart(chart_d9, lagna_d9)
|
||||
d10_rotated = build_rotated_chart(chart_d10, lagna_d10)
|
||||
|
||||
cross_analysis = {}
|
||||
for house_num in range(1, 13):
|
||||
planets_d1 = {p for p, h in d1_rotated.items() if h == house_num and p not in ('Rahu','Ketu')}
|
||||
planets_d9 = {p for p, h in d9_rotated.items() if h == house_num and p not in ('Rahu','Ketu')}
|
||||
planets_d10 = {p for p, h in d10_rotated.items() if h == house_num and p not in ('Rahu','Ketu')}
|
||||
|
||||
# 跨盘一致的行星
|
||||
cross_all = planets_d1 & planets_d9 & planets_d10
|
||||
cross_any = planets_d1 | planets_d9 | planets_d10
|
||||
|
||||
cross_analysis[house_num] = {
|
||||
"d1": sorted(planets_d1),
|
||||
"d9": sorted(planets_d9),
|
||||
"d10": sorted(planets_d10),
|
||||
"triple_cross": sorted(cross_all),
|
||||
"total_planets": len(cross_any),
|
||||
"unique_planets": len(planets_d1) + len(planets_d9) + len(planets_d10),
|
||||
sign_idx = (reference_sign_idx + house_num - 1) % 12
|
||||
chart['houses'][house_num] = {
|
||||
'sign': SIGNS[sign_idx],
|
||||
'rasi_lord': SIGN_LORDS[SIGNS[sign_idx]],
|
||||
}
|
||||
|
||||
return {
|
||||
"method": "Sudarshana Chakra (D1×D9×D10 三角形分析)",
|
||||
"cross_analysis": cross_analysis,
|
||||
"strongest_houses": sorted(
|
||||
[h for h, data in cross_analysis.items() if data["triple_cross"]],
|
||||
key=lambda h: len(cross_analysis[h]["triple_cross"]),
|
||||
reverse=True,
|
||||
),
|
||||
}
|
||||
|
||||
# 重新计算行星宫位
|
||||
for planet, data in planet_positions.items():
|
||||
sign_idx = data.get('sign_idx', data.get('sign', 0))
|
||||
if isinstance(sign_idx, str):
|
||||
sign_idx = SIGNS.index(sign_idx) if sign_idx in SIGNS else 0
|
||||
|
||||
house = (sign_idx - reference_sign_idx) % 12 + 1
|
||||
chart['planets'][planet] = {
|
||||
'sign': SIGNS[sign_idx],
|
||||
'house': house,
|
||||
'degree': data.get('degree', 0),
|
||||
}
|
||||
|
||||
return chart
|
||||
|
||||
|
||||
def calculate_sd_chakra_dasha(lagna_sign_idx: int, moon_sign_idx: int,
|
||||
sun_sign_idx: int, years: int = 108) -> List[Dict]:
|
||||
def _find_convergences(lagna_chart: Dict, chandra_chart: Dict, surya_chart: Dict) -> Dict:
|
||||
"""
|
||||
Sudarshana Chakra 12年周期大运(SD Cakra Dasha)
|
||||
|
||||
每年 = 三个圈同时向前推进1宫
|
||||
第1年 = (L+0, M+0, S+0)
|
||||
第2年 = (L+1, M+1, S+1)
|
||||
...
|
||||
通常推9周期 = 108年
|
||||
|
||||
Args:
|
||||
lagna_sign_idx: Lagna星座索引
|
||||
moon_sign_idx: 月亮星座索引
|
||||
sun_sign_idx: 太阳星座索引
|
||||
years: 预测年数(默认108年,9个周期)
|
||||
|
||||
寻找三个参考点盘中的一致性(Convergence)。
|
||||
|
||||
当同一宫位在至少两个参考点中有重要配置时,标记为收敛点。
|
||||
|
||||
Returns:
|
||||
[{year: int, period: int, lagna_house, moon_house, sun_house, description}]
|
||||
收敛分析结果
|
||||
"""
|
||||
result = []
|
||||
for year in range(1, years + 1):
|
||||
period = (year - 1) // 12 + 1 # 1-9
|
||||
offset = (year - 1) % 12
|
||||
|
||||
lh = ((lagna_sign_idx + offset) % 12) + 1
|
||||
mh = ((moon_sign_idx + offset) % 12) + 1
|
||||
sh = ((sun_sign_idx + offset) % 12) + 1
|
||||
|
||||
# 判断该年的主要主题
|
||||
circles = len({lh, mh, sh})
|
||||
same_house = lh == mh == sh
|
||||
|
||||
desc = f"第{period}周期·第{year}年 "
|
||||
if same_house:
|
||||
desc += f"三圈同聚第{lh}宫 ★"
|
||||
elif circles == 2:
|
||||
desc += f"内圈{lh}/中圈{mh}/外圈{sh}(双圈一致)"
|
||||
else:
|
||||
desc += f"内圈{lh}/中圈{mh}/外圈{sh}"
|
||||
|
||||
result.append({
|
||||
"year": year,
|
||||
"period": period,
|
||||
"year_in_period": offset + 1,
|
||||
"lagna_house": lh,
|
||||
"moon_house": mh,
|
||||
"sun_house": sh,
|
||||
"circles": circles,
|
||||
"all_same": same_house,
|
||||
"description": desc,
|
||||
})
|
||||
|
||||
return result
|
||||
convergences = []
|
||||
SEVEN_PLANETS = ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn']
|
||||
|
||||
for house_num in range(1, 13):
|
||||
lagna_planets = [p for p in SEVEN_PLANETS
|
||||
if p in lagna_chart.get('planets', {})
|
||||
and lagna_chart['planets'][p].get('house') == house_num]
|
||||
chandra_planets = [p for p in SEVEN_PLANETS
|
||||
if p in chandra_chart.get('planets', {})
|
||||
and chandra_chart['planets'][p].get('house') == house_num]
|
||||
surya_planets = [p for p in SEVEN_PLANETS
|
||||
if p in surya_chart.get('planets', {})
|
||||
and surya_chart['planets'][p].get('house') == house_num]
|
||||
|
||||
def _generate_summary(triple: List, dual: List,
|
||||
lagna_chart: Dict, moon_chart: Dict,
|
||||
sun_chart: Dict) -> str:
|
||||
"""生成文本摘要"""
|
||||
lines = []
|
||||
if triple:
|
||||
lines.append(f"三环汇聚(最强): 第{'/'.join(map(str, triple))}宫")
|
||||
if dual:
|
||||
lines.append(f"双环汇聚: 第{'/'.join(map(str, dual))}宫")
|
||||
if not triple and not dual:
|
||||
lines.append("本次无三环或双环汇聚")
|
||||
return " | ".join(lines) if lines else "无汇聚"
|
||||
# 寻找至少两个参考点中共有的行星
|
||||
all_in_house = set(lagna_planets + chandra_planets + surya_planets)
|
||||
for planet in all_in_house:
|
||||
count = (1 if planet in lagna_planets else 0) + \
|
||||
(1 if planet in chandra_planets else 0) + \
|
||||
(1 if planet in surya_planets else 0)
|
||||
if count >= 2:
|
||||
convergences.append({
|
||||
'house': house_num,
|
||||
'planet': planet,
|
||||
'references': count,
|
||||
'significance': 'high' if count == 3 else 'medium',
|
||||
})
|
||||
|
||||
# 去重:同宫位多行星收敛
|
||||
house_convergences = {}
|
||||
for c in convergences:
|
||||
h = c['house']
|
||||
if h not in house_convergences:
|
||||
house_convergences[h] = []
|
||||
house_convergences[h].append(c)
|
||||
|
||||
def sudarshana_full_analysis(raw_planets: Dict, lagna_sign_idx: int,
|
||||
moon_sign_idx: int, sun_sign_idx: int,
|
||||
chart_d1: Dict = None, chart_d9: Dict = None,
|
||||
chart_d10: Dict = None,
|
||||
lagna_d9: int = None, lagna_d10: int = None) -> Dict:
|
||||
"""
|
||||
完整Sudarshana Chakra分析:三轮盘 + D1×D9×D10三角分析 + 12年周期大运
|
||||
|
||||
Returns: 综合报告
|
||||
"""
|
||||
# 三轮盘分析
|
||||
three_ring = calculate_sudarshana_chakra(
|
||||
raw_planets, lagna_sign_idx, moon_sign_idx, sun_sign_idx
|
||||
)
|
||||
|
||||
# 12年周期大运
|
||||
dasha = calculate_sd_chakra_dasha(lagna_sign_idx, moon_sign_idx, sun_sign_idx)
|
||||
|
||||
# D1×D9×D10 三角分析(如果有数据)
|
||||
triangle = None
|
||||
if chart_d1 and chart_d9 and chart_d10 and lagna_d9 is not None and lagna_d10 is not None:
|
||||
triangle = calculate_sd_chakra_with_vargas(
|
||||
raw_planets, chart_d1, chart_d9, chart_d10,
|
||||
lagna_sign_idx, lagna_d9, lagna_d10
|
||||
)
|
||||
|
||||
return {
|
||||
"method": "Sudarshana Chakra 完整分析(三轮盘 + 三角盘 + 12年周期大运)",
|
||||
"three_ring_convergences": three_ring,
|
||||
"d1_d9_d10_triangle": triangle,
|
||||
"chakra_dasha_12_year_cycle": {
|
||||
"total_years": len(dasha),
|
||||
"cycles": 9,
|
||||
"current_period": dasha[0:12], # 最近12年
|
||||
},
|
||||
'total_convergences': len(convergences),
|
||||
'high_confidence': [c for c in convergences if c['significance'] == 'high'],
|
||||
'house_analysis': house_convergences,
|
||||
}
|
||||
|
||||
|
||||
def calc_sudarshana_chakra(planet_positions: Dict,
|
||||
asc_sign: str = None,
|
||||
asc_sign_idx: int = None,
|
||||
moon_degree: float = None,
|
||||
sun_degree: float = None) -> Dict:
|
||||
"""
|
||||
计算Sudarshana Chakra(三参考点盘)。
|
||||
|
||||
Args:
|
||||
planet_positions: {planet: {'sign': str 或 'sign_idx': int, 'degree': float}}
|
||||
asc_sign: 上升星座名称(优先)
|
||||
asc_sign_idx: 上升星座索引
|
||||
moon_degree: 月亮黄道经度(0-360,用于确定月亮星座)
|
||||
sun_degree: 太阳黄道经度(0-360,用于确定太阳星座)
|
||||
|
||||
Returns:
|
||||
完整的Sudarshana Chakra分析
|
||||
"""
|
||||
# 确定三个参考点星座索引
|
||||
if asc_sign and asc_sign in SIGNS:
|
||||
lagna_ref = SIGNS.index(asc_sign)
|
||||
elif asc_sign_idx is not None:
|
||||
lagna_ref = asc_sign_idx % 12
|
||||
else:
|
||||
lagna_ref = 0
|
||||
|
||||
if moon_degree is not None:
|
||||
chandra_ref = int(moon_degree / 30) % 12
|
||||
else:
|
||||
# 尝试从行星位置中获取
|
||||
moon_data = planet_positions.get('Moon', {})
|
||||
chandra_ref = moon_data.get('sign_idx', 0)
|
||||
if isinstance(chandra_ref, str):
|
||||
chandra_ref = SIGNS.index(chandra_ref) if chandra_ref in SIGNS else 3
|
||||
|
||||
if sun_degree is not None:
|
||||
surya_ref = int(sun_degree / 30) % 12
|
||||
else:
|
||||
sun_data = planet_positions.get('Sun', {})
|
||||
surya_ref = sun_data.get('sign_idx', 0)
|
||||
if isinstance(surya_ref, str):
|
||||
surya_ref = SIGNS.index(surya_ref) if surya_ref in SIGNS else 4
|
||||
|
||||
# 构建三个参考点盘
|
||||
lagna_chart = _build_reference_chart(planet_positions, lagna_ref)
|
||||
chandra_chart = _build_reference_chart(planet_positions, chandra_ref)
|
||||
surya_chart = _build_reference_chart(planet_positions, surya_ref)
|
||||
|
||||
# 寻找收敛
|
||||
convergence = _find_convergences(lagna_chart, chandra_chart, surya_chart)
|
||||
|
||||
return {
|
||||
'method': 'Sudarshana Chakra 三参考点盘 (BPHS标准)',
|
||||
'version': '1.0',
|
||||
'references': {
|
||||
'lagna': {'sign': SIGNS[lagna_ref], 'role': '自我/身体'},
|
||||
'chandra': {'sign': SIGNS[chandra_ref], 'role': '情感/心理'},
|
||||
'surya': {'sign': SIGNS[surya_ref], 'role': '灵魂/生命力'},
|
||||
},
|
||||
'charts': {
|
||||
'lagna_based': lagna_chart,
|
||||
'chandra_based': chandra_chart,
|
||||
'surya_based': surya_chart,
|
||||
},
|
||||
'convergence': convergence,
|
||||
'assessment': _assess_chakra(convergence),
|
||||
}
|
||||
|
||||
|
||||
def _assess_chakra(convergence: Dict) -> str:
|
||||
"""评估Sudarshana Chakra的总体结构"""
|
||||
high = len(convergence.get('high_confidence', []))
|
||||
total = convergence.get('total_convergences', 0)
|
||||
|
||||
if high >= 3:
|
||||
return '强烈收敛 — 三个参考点高度一致,事件确认度极高'
|
||||
elif high >= 1 or total >= 5:
|
||||
return '中等收敛 — 部分领域一致性较强'
|
||||
elif total >= 1:
|
||||
return '弱收敛 — 少数领域有一致性'
|
||||
else:
|
||||
return '无收敛 — 三个参考点分散,需从多角度分别分析'
|
||||
|
||||
Reference in New Issue
Block a user