Files
Jyotisha/references/open_source_sources/dashaflow/dignity.py
T
732642856 f83db2fac1 Enhance Jyotish validation and Jaimini modules
- add external validation reports and open-source comparison references

- integrate Jaimini arudha/graha pada, enhanced argala, and additional synastry kutas

- update skill docs and capability matrices

- add smoke tests for open-source integrations
2026-06-10 20:50:52 +08:00

149 lines
4.9 KiB
Python

from .constants import (
EXALTATION, DEBILITATION, OWN_SIGNS, MOOLTRIKONA,
SIGN_LORDS, NATURAL_FRIENDS, NATURAL_ENEMIES, NATURAL_NEUTRALS,
COMBUSTION_ORBS, ZODIAC_SIGNS,
)
def get_dignity(planet_name, sign, degree_in_sign, planets_in_signs=None):
"""
Determine a planet's dignity in a given sign per BPHS.
Returns one of: exalted, mooltrikona, own_sign, friend, neutral, enemy, debilitated.
Rahu/Ketu get a simplified check (exalt/debilit/own or neutral).
"""
if planet_name in EXALTATION and EXALTATION[planet_name][0] == sign:
if planet_name in MOOLTRIKONA:
mt_sign, mt_start, mt_end = MOOLTRIKONA[planet_name]
if mt_sign == sign and mt_start <= degree_in_sign <= mt_end:
return "mooltrikona"
return "exalted"
if planet_name in DEBILITATION and DEBILITATION[planet_name][0] == sign:
return "debilitated"
if planet_name in OWN_SIGNS and sign in OWN_SIGNS[planet_name]:
if planet_name in MOOLTRIKONA:
mt_sign, mt_start, mt_end = MOOLTRIKONA[planet_name]
if mt_sign == sign and mt_start <= degree_in_sign <= mt_end:
return "mooltrikona"
return "own_sign"
if planet_name in MOOLTRIKONA:
mt_sign, mt_start, mt_end = MOOLTRIKONA[planet_name]
if mt_sign == sign and mt_start <= degree_in_sign <= mt_end:
return "mooltrikona"
if planet_name in ("Rahu", "Ketu"):
return "neutral"
sign_lord = SIGN_LORDS.get(sign)
if not sign_lord:
return "neutral"
if planets_in_signs:
return get_compound_relationship(planet_name, sign, planets_in_signs)
if sign_lord in NATURAL_FRIENDS.get(planet_name, []):
return "friend"
if sign_lord in NATURAL_ENEMIES.get(planet_name, []):
return "enemy"
return "neutral"
def get_compound_relationship(planet_name, sign, planets_in_signs):
"""
Compute Panchadha Maitri (5-fold compound relationship).
Combines natural relationship with temporary friendship.
Temporary friend = any planet in signs 2,3,4,10,11,12 from the planet.
Temporary enemy = any planet in signs 1,5,6,7,8,9 (same sign counts as 1).
Parameters
----------
planet_name : str
sign : str - the sign the planet occupies
planets_in_signs : dict - {planet_name: sign_index} for all planets
Returns one of: great_friend, friend, neutral, enemy, great_enemy
"""
sign_lord = SIGN_LORDS.get(sign)
if not sign_lord or planet_name in ("Rahu", "Ketu"):
return "neutral"
natural = _natural_relationship(planet_name, sign_lord)
planet_sign_idx = ZODIAC_SIGNS.index(sign)
sign_lord_idx = None
for p, idx in planets_in_signs.items():
if p == sign_lord:
sign_lord_idx = idx
break
if sign_lord_idx is None:
return natural
dist = (sign_lord_idx - planet_sign_idx) % 12
# Houses 2,3,4,10,11,12 from planet are temporary friends (BPHS)
# dist values {1,2,3,9,10,11} map to these houses (0-indexed)
temp_friend_positions = {1, 2, 3, 9, 10, 11}
is_temp_friend = dist in temp_friend_positions
compound = _combine_relationships(natural, is_temp_friend)
return compound
def _natural_relationship(planet, other):
if other in NATURAL_FRIENDS.get(planet, []):
return "friend"
if other in NATURAL_ENEMIES.get(planet, []):
return "enemy"
return "neutral"
def _combine_relationships(natural, is_temp_friend):
"""Panchadha Maitri combination table."""
if natural == "friend" and is_temp_friend:
return "great_friend"
if natural == "friend" and not is_temp_friend:
return "neutral"
if natural == "neutral" and is_temp_friend:
return "friend"
if natural == "neutral" and not is_temp_friend:
return "enemy"
if natural == "enemy" and is_temp_friend:
return "neutral"
if natural == "enemy" and not is_temp_friend:
return "great_enemy"
return "neutral"
def check_combustion(planet_name, planet_lon, sun_lon, is_retrograde=False):
"""
Check if a planet is combust (too close to the Sun).
Sun, Rahu, Ketu cannot be combust.
"""
if planet_name in ("Sun", "Rahu", "Ketu"):
return False
orb_data = COMBUSTION_ORBS.get(planet_name)
if orb_data is None:
return False
if isinstance(orb_data, dict):
orb = orb_data["retrograde"] if is_retrograde else orb_data["direct"]
else:
orb = orb_data
angular_dist = abs(planet_lon - sun_lon)
if angular_dist > 180:
angular_dist = 360 - angular_dist
return angular_dist <= orb
def get_digbala(planet_name, house):
"""Check if a planet has directional strength in its current house."""
from .constants import DIGBALA_HOUSES
ideal_house = DIGBALA_HOUSES.get(planet_name)
if ideal_house is None:
return False
return house == ideal_house