#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Special Lagnas Calculator - 特殊上升点计算器 印度占星特殊上升点(Bhava/Hora/Ghati/Arudha/Upapada Lagna) 核心功能: - Bhava Lagna(宫位上升):反映物质层面的实际状况 - Hora Lagna(时辰上升):财富和物质收益的指示器 - Ghati Lagna(Ghati上升):基于Ghati单位的精确上升点 - Arudha Lagna(映像上升):公众形象和社会地位 - Upapada Lagna(配偶映像上升):配偶和婚姻的公众形象 """ from typing import Dict, Tuple from datetime import datetime, timedelta class SpecialLagnasCalculator: """特殊上升点计算器""" SIGNS = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"] def __init__(self): pass def calculate_all_lagnas(self, asc_degree: float, sun_degree: float, moon_degree: float, birth_time: datetime, sunrise_time: datetime) -> Dict[str, Dict]: """ 计算所有特殊上升点 Args: asc_degree: 上升点度数(0-360) sun_degree: 太阳度数(0-360) moon_degree: 月亮度数(0-360) birth_time: 出生时间 sunrise_time: 当天日出时间 Returns: 所有特殊上升点的字典 """ result = {} # 1. Bhava Lagna result["Bhava_Lagna"] = self.calculate_bhava_lagna(asc_degree, sun_degree, moon_degree) # 2. Hora Lagna result["Hora_Lagna"] = self.calculate_hora_lagna(asc_degree, sun_degree, birth_time, sunrise_time) # 3. Ghati Lagna result["Ghati_Lagna"] = self.calculate_ghati_lagna(asc_degree, birth_time, sunrise_time) # 4/5. Arudha Lagna、Upapada Lagna 只有一个来源 jaimini.calc_arudha_padas(BUG-1190), # 由 full reading 用它覆盖这两个占位。 result["Arudha_Lagna"] = {"note": "Computed by jaimini.calc_arudha_padas"} result["Upapada_Lagna"] = {"note": "Computed by jaimini.calc_arudha_padas"} return result def calculate_bhava_lagna(self, asc_degree: float, sun_degree: float, moon_degree: float) -> Dict: """ 计算Bhava Lagna(宫位上升) 公式:Bhava Lagna = Asc + (Sun - Moon) 含义: - 反映物质层面的实际状况 - 显示真实的生活环境和物质条件 - 与上升点的差异揭示表象与实质的差距 """ # 计算太阳-月亮的度数差 sun_moon_diff = sun_degree - moon_degree # 如果差值为负,加360度 if sun_moon_diff < 0: sun_moon_diff += 360 # 计算Bhava Lagna bhava_lagna = (asc_degree + sun_moon_diff) % 360 # 转换为星座和度数 sign_index = int(bhava_lagna // 30) sign_degree = bhava_lagna % 30 return { "degree": round(bhava_lagna, 4), "sign": self.SIGNS[sign_index], "sign_degree": round(sign_degree, 4), "house": ((sign_index - int(asc_degree // 30)) % 12) + 1, "formula": "Asc + (Sun - Moon)", "meaning": "物质层面的实际状况,真实的生活环境" } def calculate_hora_lagna(self, asc_degree: float, sun_degree: float, birth_time: datetime, sunrise_time: datetime) -> Dict: """ 计算Hora Lagna(时辰上升) 公式:Hora Lagna = Asc + (出生时间距日出的Hora数 × 15度) 含义: - 财富和物质收益的指示器 - 显示金钱来源和财富积累方式 - 与2宫(财富宫)密切相关 """ # 计算出生时间距日出的小时数 time_diff = birth_time - sunrise_time hours_from_sunrise = time_diff.total_seconds() / 3600 # 计算Hora数(每个Hora = 1小时) hora_count = hours_from_sunrise # 计算Hora Lagna(每个Hora推进15度) hora_lagna = (asc_degree + (hora_count * 15)) % 360 # 转换为星座和度数 sign_index = int(hora_lagna // 30) sign_degree = hora_lagna % 30 return { "degree": round(hora_lagna, 4), "sign": self.SIGNS[sign_index], "sign_degree": round(sign_degree, 4), "house": ((sign_index - int(asc_degree // 30)) % 12) + 1, "hours_from_sunrise": round(hours_from_sunrise, 2), "formula": "Asc + (Hora数 × 15°)", "meaning": "财富和物质收益的指示器" } def calculate_ghati_lagna(self, asc_degree: float, birth_time: datetime, sunrise_time: datetime) -> Dict: """ 计算Ghati Lagna(Ghati上升) 公式:Ghati Lagna = Asc + (Ghati数 × 6度) Ghati单位: - 1 Ghati = 24分钟 - 1天 = 60 Ghati - 每个Ghati推进6度(360度 / 60 Ghati = 6度) 含义: - 基于Ghati单位的精确上升点 - 用于精确的时间矫正和事件预测 - 在Prashna(问事占星)中特别重要 """ # 计算出生时间距日出的分钟数 time_diff = birth_time - sunrise_time minutes_from_sunrise = time_diff.total_seconds() / 60 # 计算Ghati数(1 Ghati = 24分钟) ghati_count = minutes_from_sunrise / 24 # 计算Ghati Lagna(每个Ghati推进6度) ghati_lagna = (asc_degree + (ghati_count * 6)) % 360 # 转换为星座和度数 sign_index = int(ghati_lagna // 30) sign_degree = ghati_lagna % 30 return { "degree": round(ghati_lagna, 4), "sign": self.SIGNS[sign_index], "sign_degree": round(sign_degree, 4), "house": ((sign_index - int(asc_degree // 30)) % 12) + 1, "ghati_count": round(ghati_count, 2), "formula": "Asc + (Ghati数 × 6°)", "meaning": "基于Ghati单位的精确上升点,用于精确预测" } def calculate_arudha_pada(self, asc_degree: float, source_house: int, source_lord_degree: float, label: str = "Arudha_Pada") -> Dict: """ 计算任意宫位的 Arudha Pada(A1-A12)。 Args: asc_degree: 上升点度数(0-360) source_house: 源宫位(1-12);例如 10 = A10 / Karma Pada / Rajya Pada source_lord_degree: 源宫主星度数(0-360) label: 输出标签 Formula: 1. 找到源宫位星座。 2. 计算源宫主星距离源宫位的星座数。 3. 从源宫主星再数同样距离得到 Pada。 4. 若 Pada 落回源宫或源宫第7宫,按 Jaimini 例外规则改取该位置第10宫。 """ if source_house < 1 or source_house > 12: raise ValueError("source_house must be between 1 and 12") asc_sign = int(asc_degree // 30) source_sign = (asc_sign + source_house - 1) % 12 lord_sign = int(source_lord_degree // 30) distance = (lord_sign - source_sign) % 12 pada_sign = (lord_sign + distance) % 12 exception_applied = False if pada_sign == source_sign or pada_sign == (source_sign + 6) % 12: pada_sign = (pada_sign + 9) % 12 exception_applied = True pada_degree = (pada_sign * 30 + (source_lord_degree % 30)) % 360 return { "label": label, "source_house": source_house, "degree": round(pada_degree, 4), "sign": self.SIGNS[pada_sign], "sign_degree": round(pada_degree % 30, 4), "house": ((pada_sign - asc_sign) % 12) + 1, "source_sign": self.SIGNS[source_sign], "source_lord_sign": self.SIGNS[lord_sign], "distance_from_source": distance if distance != 0 else 12, "exception_applied": exception_applied, "formula": f"A{source_house}: from house lord count the same distance from source house; apply 1/7 exception", "meaning": "Arudha Pada:该宫位主题在外界/社会层面的显化" } def calculate_a10(self, asc_degree: float, tenth_lord_degree: float) -> Dict: """计算 A10 / Karma Pada / Rajya Pada:事业名声、职业可见度、社会身份。""" result = self.calculate_arudha_pada(asc_degree, 10, tenth_lord_degree, "A10_Karma_Pada") result["meaning"] = "A10/Karma Pada/Rajya Pada:事业名声、职业可见度、社会身份与公众层面的职业结果" return result def format_output(self, lagnas: Dict) -> str: """格式化输出所有特殊上升点""" lines = ["=" * 60, "Special Lagnas Calculation", "=" * 60, ""] for lagna_name, data in lagnas.items(): lines.append(f"{lagna_name}:") if "note" in data: lines.append(f" {data['note']}") else: lines.append(f" Position: {data['sign']} {data['sign_degree']:.2f}° ({data['degree']:.2f}°)") lines.append(f" Formula: {data['formula']}") lines.append(f" Meaning: {data['meaning']}") lines.append("") lines.append("=" * 60) return "\n".join(lines) def main(): """命令行接口""" import argparse from datetime import datetime parser = argparse.ArgumentParser(description="Calculate Special Lagnas") parser.add_argument("--asc", type=float, required=True, help="Ascendant degree (0-360)") parser.add_argument("--sun", type=float, required=True, help="Sun degree (0-360)") parser.add_argument("--moon", type=float, required=True, help="Moon degree (0-360)") parser.add_argument("--birth-time", type=str, help="Birth time (YYYY-MM-DD HH:MM:SS)") parser.add_argument("--sunrise-time", type=str, help="Sunrise time (YYYY-MM-DD HH:MM:SS)") parser.add_argument("--tenth-lord", type=float, help="10th house lord degree (for A10/Karma Pada)") args = parser.parse_args() calc = SpecialLagnasCalculator() # 解析时间 birth_time = datetime.strptime(args.birth_time, "%Y-%m-%d %H:%M:%S") if args.birth_time else datetime.now() sunrise_time = datetime.strptime(args.sunrise_time, "%Y-%m-%d %H:%M:%S") if args.sunrise_time else birth_time.replace(hour=6, minute=0, second=0) # 计算所有特殊上升点 lagnas = calc.calculate_all_lagnas(args.asc, args.sun, args.moon, birth_time, sunrise_time) # 如果提供了10宫主星位置,计算A10/Karma Pada if args.tenth_lord is not None: lagnas["A10_Karma_Pada"] = calc.calculate_a10(args.asc, args.tenth_lord) # 输出结果 print(calc.format_output(lagnas)) if __name__ == "__main__": main()