kundali-chart-mcp 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -0
- package/azure-function/function_app.py +93 -0
- package/azure-function/host.json +15 -0
- package/azure-function/kundali_bridge.py +952 -0
- package/azure-function/python/kundali_lib/__init__.py +1 -0
- package/azure-function/python/kundali_lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/__pycache__/ephemeris.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/__pycache__/geocoder.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/__pycache__/vedicastro_bridge.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/ephemeris.py +30 -0
- package/azure-function/python/kundali_lib/geocoder.py +82 -0
- package/azure-function/python/kundali_lib/vedic/__init__.py +1 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/__init__.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/arishta.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/ashtakavarga.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/avasthas.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/ayanamsa.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/bhava_chalit.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/char_dasha.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/chart.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/chart_types.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/compatibility.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/constants.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/dasha_extended.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/dasha_systems.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/doshas.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/gandanta.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/gochara.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/hora.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/houses.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/jaimini.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/kalachakra.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/kartari.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/kurmachakra.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/lunar_return.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/muhurta.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/nabhasha.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/nakshatra_details.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/panchanga.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/planets.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/shadbala.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/special_conditions.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/sudarshana.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/tajaka.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/upagrahas.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/varshaphal.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/yogas.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/__pycache__/zodiac.cpython-313.pyc +0 -0
- package/azure-function/python/kundali_lib/vedic/arishta.py +465 -0
- package/azure-function/python/kundali_lib/vedic/ashtakavarga.py +213 -0
- package/azure-function/python/kundali_lib/vedic/avasthas.py +292 -0
- package/azure-function/python/kundali_lib/vedic/ayanamsa.py +106 -0
- package/azure-function/python/kundali_lib/vedic/bhava_chalit.py +137 -0
- package/azure-function/python/kundali_lib/vedic/char_dasha.py +308 -0
- package/azure-function/python/kundali_lib/vedic/chart.py +126 -0
- package/azure-function/python/kundali_lib/vedic/chart_types.py +338 -0
- package/azure-function/python/kundali_lib/vedic/compatibility.py +705 -0
- package/azure-function/python/kundali_lib/vedic/constants.py +108 -0
- package/azure-function/python/kundali_lib/vedic/dasha_extended.py +262 -0
- package/azure-function/python/kundali_lib/vedic/dasha_systems.py +439 -0
- package/azure-function/python/kundali_lib/vedic/doshas.py +453 -0
- package/azure-function/python/kundali_lib/vedic/gandanta.py +213 -0
- package/azure-function/python/kundali_lib/vedic/gochara.py +277 -0
- package/azure-function/python/kundali_lib/vedic/hora.py +263 -0
- package/azure-function/python/kundali_lib/vedic/houses.py +30 -0
- package/azure-function/python/kundali_lib/vedic/jaimini.py +361 -0
- package/azure-function/python/kundali_lib/vedic/kalachakra.py +226 -0
- package/azure-function/python/kundali_lib/vedic/kartari.py +243 -0
- package/azure-function/python/kundali_lib/vedic/kurmachakra.py +383 -0
- package/azure-function/python/kundali_lib/vedic/lunar_return.py +402 -0
- package/azure-function/python/kundali_lib/vedic/muhurta.py +414 -0
- package/azure-function/python/kundali_lib/vedic/nabhasha.py +349 -0
- package/azure-function/python/kundali_lib/vedic/nakshatra_details.py +945 -0
- package/azure-function/python/kundali_lib/vedic/panchanga.py +297 -0
- package/azure-function/python/kundali_lib/vedic/planets.py +55 -0
- package/azure-function/python/kundali_lib/vedic/shadbala.py +500 -0
- package/azure-function/python/kundali_lib/vedic/special_conditions.py +319 -0
- package/azure-function/python/kundali_lib/vedic/sudarshana.py +232 -0
- package/azure-function/python/kundali_lib/vedic/tajaka.py +482 -0
- package/azure-function/python/kundali_lib/vedic/upagrahas.py +229 -0
- package/azure-function/python/kundali_lib/vedic/varshaphal.py +185 -0
- package/azure-function/python/kundali_lib/vedic/yogas.py +935 -0
- package/azure-function/python/kundali_lib/vedic/zodiac.py +42 -0
- package/azure-function/python/kundali_lib/vedicastro_bridge.py +198 -0
- package/azure-function/requirements.txt +9 -0
- package/index.js +747 -0
- package/kundali-chart-mcp.js +159 -0
- package/kundali_bridge.py +952 -0
- package/package.json +41 -0
- package/python/kundali_lib/__init__.py +1 -0
- package/python/kundali_lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/python/kundali_lib/__pycache__/ephemeris.cpython-313.pyc +0 -0
- package/python/kundali_lib/__pycache__/geocoder.cpython-313.pyc +0 -0
- package/python/kundali_lib/__pycache__/vedicastro_bridge.cpython-313.pyc +0 -0
- package/python/kundali_lib/ephemeris.py +30 -0
- package/python/kundali_lib/geocoder.py +82 -0
- package/python/kundali_lib/vedic/__init__.py +1 -0
- package/python/kundali_lib/vedic/__pycache__/__init__.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/arishta.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/ashtakavarga.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/avasthas.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/ayanamsa.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/bhava_chalit.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/char_dasha.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/chart.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/chart_types.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/compatibility.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/constants.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/dasha_extended.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/dasha_systems.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/doshas.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/gandanta.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/gochara.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/hora.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/houses.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/jaimini.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/kalachakra.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/kartari.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/kurmachakra.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/lunar_return.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/muhurta.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/nabhasha.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/nakshatra_details.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/panchanga.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/planets.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/shadbala.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/special_conditions.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/sudarshana.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/tajaka.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/upagrahas.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/varshaphal.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/yogas.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/__pycache__/zodiac.cpython-313.pyc +0 -0
- package/python/kundali_lib/vedic/arishta.py +465 -0
- package/python/kundali_lib/vedic/ashtakavarga.py +213 -0
- package/python/kundali_lib/vedic/avasthas.py +292 -0
- package/python/kundali_lib/vedic/ayanamsa.py +106 -0
- package/python/kundali_lib/vedic/bhava_chalit.py +137 -0
- package/python/kundali_lib/vedic/char_dasha.py +308 -0
- package/python/kundali_lib/vedic/chart.py +126 -0
- package/python/kundali_lib/vedic/chart_types.py +338 -0
- package/python/kundali_lib/vedic/compatibility.py +705 -0
- package/python/kundali_lib/vedic/constants.py +108 -0
- package/python/kundali_lib/vedic/dasha_extended.py +262 -0
- package/python/kundali_lib/vedic/dasha_systems.py +439 -0
- package/python/kundali_lib/vedic/doshas.py +453 -0
- package/python/kundali_lib/vedic/gandanta.py +213 -0
- package/python/kundali_lib/vedic/gochara.py +277 -0
- package/python/kundali_lib/vedic/hora.py +263 -0
- package/python/kundali_lib/vedic/houses.py +30 -0
- package/python/kundali_lib/vedic/jaimini.py +361 -0
- package/python/kundali_lib/vedic/kalachakra.py +226 -0
- package/python/kundali_lib/vedic/kartari.py +243 -0
- package/python/kundali_lib/vedic/kurmachakra.py +383 -0
- package/python/kundali_lib/vedic/lunar_return.py +402 -0
- package/python/kundali_lib/vedic/muhurta.py +414 -0
- package/python/kundali_lib/vedic/nabhasha.py +349 -0
- package/python/kundali_lib/vedic/nakshatra_details.py +945 -0
- package/python/kundali_lib/vedic/panchanga.py +297 -0
- package/python/kundali_lib/vedic/planets.py +55 -0
- package/python/kundali_lib/vedic/shadbala.py +500 -0
- package/python/kundali_lib/vedic/special_conditions.py +319 -0
- package/python/kundali_lib/vedic/sudarshana.py +232 -0
- package/python/kundali_lib/vedic/tajaka.py +482 -0
- package/python/kundali_lib/vedic/upagrahas.py +229 -0
- package/python/kundali_lib/vedic/varshaphal.py +185 -0
- package/python/kundali_lib/vedic/yogas.py +935 -0
- package/python/kundali_lib/vedic/zodiac.py +42 -0
- package/python/kundali_lib/vedicastro_bridge.py +198 -0
- package/remote-server.js +590 -0
- package/requirements.txt +8 -0
- package/setup.sh +218 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
"""Jaimini astrology: Chara Karakas, Jaimini aspects, and Atmakaraka analysis."""
|
|
2
|
+
|
|
3
|
+
# ---------------------------------------------------------------------------
|
|
4
|
+
# Constant tables
|
|
5
|
+
# ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
KARAKA_NAMES = [
|
|
8
|
+
"Atmakaraka",
|
|
9
|
+
"Amatyakaraka",
|
|
10
|
+
"Bhratrukaraka",
|
|
11
|
+
"Matrukaraka",
|
|
12
|
+
"Putrakaraka",
|
|
13
|
+
"Gnatikaraka",
|
|
14
|
+
"Darakaraka",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
# Planets used for Chara Karaka calculation (7-karaka system)
|
|
18
|
+
KARAKA_PLANETS = [
|
|
19
|
+
"Sun",
|
|
20
|
+
"Moon",
|
|
21
|
+
"Mars",
|
|
22
|
+
"Mercury",
|
|
23
|
+
"Jupiter",
|
|
24
|
+
"Venus",
|
|
25
|
+
"Saturn",
|
|
26
|
+
"Rahu",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
# Sign type classification
|
|
30
|
+
MOVABLE_SIGNS = ["Aries", "Cancer", "Libra", "Capricorn"]
|
|
31
|
+
FIXED_SIGNS = ["Taurus", "Leo", "Scorpio", "Aquarius"]
|
|
32
|
+
DUAL_SIGNS = ["Gemini", "Virgo", "Sagittarius", "Pisces"]
|
|
33
|
+
|
|
34
|
+
# Jaimini aspects: each sign's aspect list (all signs it aspects)
|
|
35
|
+
# Movable aspects Fixed (except adjacent); Fixed aspects Movable (except adjacent);
|
|
36
|
+
# Dual aspects all other Dual signs.
|
|
37
|
+
_JAIMINI_ASPECTS: dict = {
|
|
38
|
+
"Aries": ["Leo", "Scorpio", "Aquarius"],
|
|
39
|
+
"Taurus": ["Cancer", "Libra", "Capricorn"],
|
|
40
|
+
"Gemini": ["Virgo", "Sagittarius", "Pisces"],
|
|
41
|
+
"Cancer": ["Taurus", "Leo", "Scorpio"],
|
|
42
|
+
"Leo": ["Aries", "Cancer", "Libra"],
|
|
43
|
+
"Virgo": ["Gemini", "Sagittarius", "Pisces"],
|
|
44
|
+
"Libra": ["Taurus", "Leo", "Scorpio"],
|
|
45
|
+
"Scorpio": ["Aries", "Cancer", "Libra"],
|
|
46
|
+
"Sagittarius": ["Gemini", "Virgo", "Pisces"],
|
|
47
|
+
"Capricorn": ["Taurus", "Leo", "Scorpio"],
|
|
48
|
+
"Aquarius": ["Aries", "Cancer", "Libra"],
|
|
49
|
+
"Pisces": ["Gemini", "Virgo", "Sagittarius"],
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Navamsha (D9) start rashi for each D1 sign index (0=Aries…11=Pisces)
|
|
53
|
+
# Fire signs (Aries=0, Leo=4, Sagittarius=8) start from Aries (0)
|
|
54
|
+
# Earth signs (Taurus=1, Virgo=5, Capricorn=9) start from Capricorn (9)
|
|
55
|
+
# Air signs (Gemini=2, Libra=6, Aquarius=10) start from Libra (6)
|
|
56
|
+
# Water signs(Cancer=3, Scorpio=7, Pisces=11) start from Cancer (3)
|
|
57
|
+
_NAVAMSHA_START = {
|
|
58
|
+
0: 0,
|
|
59
|
+
1: 9,
|
|
60
|
+
2: 6,
|
|
61
|
+
3: 3,
|
|
62
|
+
4: 0,
|
|
63
|
+
5: 9,
|
|
64
|
+
6: 6,
|
|
65
|
+
7: 3,
|
|
66
|
+
8: 0,
|
|
67
|
+
9: 9,
|
|
68
|
+
10: 6,
|
|
69
|
+
11: 3,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
RASHIS = [
|
|
73
|
+
"Aries",
|
|
74
|
+
"Taurus",
|
|
75
|
+
"Gemini",
|
|
76
|
+
"Cancer",
|
|
77
|
+
"Leo",
|
|
78
|
+
"Virgo",
|
|
79
|
+
"Libra",
|
|
80
|
+
"Scorpio",
|
|
81
|
+
"Sagittarius",
|
|
82
|
+
"Capricorn",
|
|
83
|
+
"Aquarius",
|
|
84
|
+
"Pisces",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
# Atmakaraka interpretations keyed by planet
|
|
88
|
+
_AK_INTERPRETATIONS = {
|
|
89
|
+
"Sun": (
|
|
90
|
+
"Sun as Atmakaraka indicates a soul driven by authority, recognition, and leadership. "
|
|
91
|
+
"The native is here to cultivate ego-transcendence through positions of power. "
|
|
92
|
+
"Lessons around pride, father figures, and governance are central to the life path."
|
|
93
|
+
),
|
|
94
|
+
"Moon": (
|
|
95
|
+
"Moon as Atmakaraka points to a soul whose deepest lessons revolve around the mind, "
|
|
96
|
+
"emotions, and nurturing. The native is drawn to healing, home, and the cycles of life. "
|
|
97
|
+
"Emotional mastery and compassion are the primary spiritual aims."
|
|
98
|
+
),
|
|
99
|
+
"Mars": (
|
|
100
|
+
"Mars as Atmakaraka signifies a warrior soul whose journey involves courage, discipline, "
|
|
101
|
+
"and the right use of energy. Past-life themes of conflict and protection emerge. "
|
|
102
|
+
"The native must channel ambition into dharmic action."
|
|
103
|
+
),
|
|
104
|
+
"Mercury": (
|
|
105
|
+
"Mercury as Atmakaraka indicates an intellectual soul whose path centers on communication, "
|
|
106
|
+
"discernment, and adaptability. The native is here to master the spoken and written word "
|
|
107
|
+
"and to use intelligence in service of truth."
|
|
108
|
+
),
|
|
109
|
+
"Jupiter": (
|
|
110
|
+
"Jupiter as Atmakaraka reflects a soul with strong dharmic inclinations toward wisdom, "
|
|
111
|
+
"teaching, and spiritual guidance. The native is here to expand consciousness, share "
|
|
112
|
+
"knowledge, and uphold righteousness."
|
|
113
|
+
),
|
|
114
|
+
"Venus": (
|
|
115
|
+
"Venus as Atmakaraka suggests a soul whose evolution is tied to relationships, beauty, "
|
|
116
|
+
"and creative expression. Themes of love, pleasure, and aesthetic refinement recur. "
|
|
117
|
+
"The lesson is learning to love without attachment."
|
|
118
|
+
),
|
|
119
|
+
"Saturn": (
|
|
120
|
+
"Saturn as Atmakaraka is the mark of a soul undergoing deep purification through "
|
|
121
|
+
"discipline, hardship, and service. The native must cultivate patience, humility, "
|
|
122
|
+
"and endurance to fulfill a karmic contract of dutiful responsibility."
|
|
123
|
+
),
|
|
124
|
+
"Rahu": (
|
|
125
|
+
"Rahu as Atmakaraka (rare) indicates an intensely karmic soul carrying unfulfilled "
|
|
126
|
+
"desires across lifetimes. The native's path involves confronting obsessions and "
|
|
127
|
+
"illusions in order to achieve liberation through transcending material cravings."
|
|
128
|
+
),
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
_DK_INTERPRETATIONS = {
|
|
132
|
+
"Sun": "Sun as Darakaraka suggests a partner who is authoritative, proud, and leadership-oriented.",
|
|
133
|
+
"Moon": "Moon as Darakaraka indicates a partner who is nurturing, emotional, and family-focused.",
|
|
134
|
+
"Mars": "Mars as Darakaraka points to a partner who is energetic, assertive, and action-driven.",
|
|
135
|
+
"Mercury": "Mercury as Darakaraka suggests a communicative, intellectual, and versatile partner.",
|
|
136
|
+
"Jupiter": "Jupiter as Darakaraka indicates a wise, generous, and dharmic partner.",
|
|
137
|
+
"Venus": "Venus as Darakaraka (uncommon) points to a highly artistic, charming partner.",
|
|
138
|
+
"Saturn": "Saturn as Darakaraka suggests a disciplined, serious, or much older/younger partner.",
|
|
139
|
+
"Rahu": "Rahu as Darakaraka indicates an unconventional, foreign, or karmic partner relationship.",
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
# ---------------------------------------------------------------------------
|
|
144
|
+
# Helper: navamsha sign from absolute sidereal longitude
|
|
145
|
+
# ---------------------------------------------------------------------------
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _navamsha_rashi(lon: float) -> str:
|
|
149
|
+
lon = lon % 360
|
|
150
|
+
rashi_idx = int(lon / 30)
|
|
151
|
+
degree_in_sign = lon - rashi_idx * 30
|
|
152
|
+
nav_num = min(int(degree_in_sign / (10.0 / 3.0)), 8)
|
|
153
|
+
d9_idx = (_NAVAMSHA_START[rashi_idx] + nav_num) % 12
|
|
154
|
+
return RASHIS[d9_idx]
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _sign_type(sign: str) -> str:
|
|
158
|
+
if sign in MOVABLE_SIGNS:
|
|
159
|
+
return "Movable"
|
|
160
|
+
if sign in FIXED_SIGNS:
|
|
161
|
+
return "Fixed"
|
|
162
|
+
if sign in DUAL_SIGNS:
|
|
163
|
+
return "Dual"
|
|
164
|
+
return "Unknown"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# ---------------------------------------------------------------------------
|
|
168
|
+
# Chara Karakas
|
|
169
|
+
# ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def get_jaimini_karakas(planetary_positions: list) -> dict:
|
|
173
|
+
"""
|
|
174
|
+
Determine the seven Chara Karakas using the Jaimini 7-karaka system.
|
|
175
|
+
|
|
176
|
+
Parameters
|
|
177
|
+
----------
|
|
178
|
+
planetary_positions : list
|
|
179
|
+
List of planet dicts from ``build_chart()``.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
dict
|
|
184
|
+
``karakas`` mapping karaka name → planet details,
|
|
185
|
+
``atmakaraka_analysis``, and ``darakaraka_analysis``.
|
|
186
|
+
"""
|
|
187
|
+
# Collect degree-in-sign for each karaka planet
|
|
188
|
+
planet_degrees: list[tuple[str, float, str, int]] = []
|
|
189
|
+
|
|
190
|
+
pos_map = {p["name"]: p for p in planetary_positions}
|
|
191
|
+
|
|
192
|
+
for planet in KARAKA_PLANETS:
|
|
193
|
+
p = pos_map.get(planet)
|
|
194
|
+
if p is None:
|
|
195
|
+
continue
|
|
196
|
+
|
|
197
|
+
degree_in_sign = p["degree"] % 30 # degree within the sign
|
|
198
|
+
|
|
199
|
+
# Rahu moves backwards → invert degree for ranking
|
|
200
|
+
if planet == "Rahu":
|
|
201
|
+
degree_in_sign = 30.0 - degree_in_sign
|
|
202
|
+
|
|
203
|
+
planet_degrees.append(
|
|
204
|
+
(planet, degree_in_sign, p.get("rashi", ""), p.get("house", 0))
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Sort descending by degree_in_sign
|
|
208
|
+
planet_degrees.sort(key=lambda x: x[1], reverse=True)
|
|
209
|
+
|
|
210
|
+
# Assign karakas
|
|
211
|
+
karakas: dict = {}
|
|
212
|
+
for i, karaka_name in enumerate(KARAKA_NAMES):
|
|
213
|
+
if i >= len(planet_degrees):
|
|
214
|
+
break
|
|
215
|
+
planet_name, deg, rashi, house = planet_degrees[i]
|
|
216
|
+
karakas[karaka_name] = {
|
|
217
|
+
"karaka": karaka_name,
|
|
218
|
+
"planet": planet_name,
|
|
219
|
+
"degree_in_sign": round(deg, 3),
|
|
220
|
+
"rashi": rashi,
|
|
221
|
+
"house": house,
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
# Interpretations
|
|
225
|
+
ak_planet = karakas.get("Atmakaraka", {}).get("planet", "Sun")
|
|
226
|
+
dk_planet = karakas.get("Darakaraka", {}).get("planet", "Venus")
|
|
227
|
+
|
|
228
|
+
ak_analysis = _AK_INTERPRETATIONS.get(
|
|
229
|
+
ak_planet,
|
|
230
|
+
f"{ak_planet} as Atmakaraka shapes the soul's core lessons in this lifetime.",
|
|
231
|
+
)
|
|
232
|
+
dk_analysis = _DK_INTERPRETATIONS.get(
|
|
233
|
+
dk_planet,
|
|
234
|
+
f"{dk_planet} as Darakaraka describes the nature of the destined partner.",
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
"karakas": karakas,
|
|
239
|
+
"atmakaraka_analysis": ak_analysis,
|
|
240
|
+
"darakaraka_analysis": dk_analysis,
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# ---------------------------------------------------------------------------
|
|
245
|
+
# Jaimini Aspects
|
|
246
|
+
# ---------------------------------------------------------------------------
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def get_jaimini_aspects(base_chart: dict) -> dict:
|
|
250
|
+
"""
|
|
251
|
+
Calculate Jaimini sign-based aspects for each planet.
|
|
252
|
+
|
|
253
|
+
Parameters
|
|
254
|
+
----------
|
|
255
|
+
base_chart : dict
|
|
256
|
+
Output of ``build_chart()``.
|
|
257
|
+
|
|
258
|
+
Returns
|
|
259
|
+
-------
|
|
260
|
+
dict
|
|
261
|
+
Keyed by planet name; each value contains sign, sign_type,
|
|
262
|
+
aspected_signs, and aspected_by.
|
|
263
|
+
"""
|
|
264
|
+
positions: list = base_chart.get("planetary_positions", [])
|
|
265
|
+
|
|
266
|
+
# Build rashi → planets mapping
|
|
267
|
+
sign_to_planets: dict[str, list[str]] = {}
|
|
268
|
+
planet_sign: dict[str, str] = {}
|
|
269
|
+
|
|
270
|
+
for p in positions:
|
|
271
|
+
rashi = p.get("rashi", "")
|
|
272
|
+
name = p["name"]
|
|
273
|
+
planet_sign[name] = rashi
|
|
274
|
+
sign_to_planets.setdefault(rashi, []).append(name)
|
|
275
|
+
|
|
276
|
+
result: dict = {}
|
|
277
|
+
|
|
278
|
+
for p in positions:
|
|
279
|
+
name = p["name"]
|
|
280
|
+
sign = p.get("rashi", "")
|
|
281
|
+
aspected_signs = _JAIMINI_ASPECTS.get(sign, [])
|
|
282
|
+
|
|
283
|
+
# Which planets aspect this planet's sign?
|
|
284
|
+
aspected_by: list[str] = []
|
|
285
|
+
for other_sign, aspects in _JAIMINI_ASPECTS.items():
|
|
286
|
+
if sign in aspects:
|
|
287
|
+
aspected_by.extend(sign_to_planets.get(other_sign, []))
|
|
288
|
+
|
|
289
|
+
result[name] = {
|
|
290
|
+
"planet": name,
|
|
291
|
+
"sign": sign,
|
|
292
|
+
"sign_type": _sign_type(sign),
|
|
293
|
+
"aspected_signs": aspected_signs,
|
|
294
|
+
"aspected_by": [x for x in aspected_by if x != name],
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return result
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
# ---------------------------------------------------------------------------
|
|
301
|
+
# Karakamsha
|
|
302
|
+
# ---------------------------------------------------------------------------
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def get_karakamsha(planetary_positions: list, d9_positions: list) -> dict:
|
|
306
|
+
"""
|
|
307
|
+
Find the Karakamsha — the sign occupied by the Atmakaraka in the Navamsha (D9).
|
|
308
|
+
|
|
309
|
+
Parameters
|
|
310
|
+
----------
|
|
311
|
+
planetary_positions : list
|
|
312
|
+
D1 (birth chart) planet list from ``build_chart()``.
|
|
313
|
+
d9_positions : list
|
|
314
|
+
D9 (Navamsha) planet list. If not available, D9 sign is computed
|
|
315
|
+
from the Atmakaraka's D1 longitude.
|
|
316
|
+
|
|
317
|
+
Returns
|
|
318
|
+
-------
|
|
319
|
+
dict
|
|
320
|
+
Atmakaraka details, Karakamsha sign, Swamsha flag, and interpretation.
|
|
321
|
+
"""
|
|
322
|
+
karaka_data = get_jaimini_karakas(planetary_positions)
|
|
323
|
+
ak_info = karaka_data["karakas"].get("Atmakaraka", {})
|
|
324
|
+
ak_planet = ak_info.get("planet", "Sun")
|
|
325
|
+
ak_d1_sign = ak_info.get("rashi", "")
|
|
326
|
+
|
|
327
|
+
# Try to get D9 sign from d9_positions if provided
|
|
328
|
+
ak_d9_sign = ""
|
|
329
|
+
if d9_positions:
|
|
330
|
+
d9_map = {p["name"]: p for p in d9_positions}
|
|
331
|
+
ak_d9_sign = d9_map.get(ak_planet, {}).get("rashi", "")
|
|
332
|
+
|
|
333
|
+
# Fallback: compute D9 sign from D1 longitude
|
|
334
|
+
if not ak_d9_sign:
|
|
335
|
+
pos_map = {p["name"]: p for p in planetary_positions}
|
|
336
|
+
ak_lon = pos_map.get(ak_planet, {}).get("longitude", 0.0)
|
|
337
|
+
ak_d9_sign = _navamsha_rashi(ak_lon)
|
|
338
|
+
|
|
339
|
+
swamsha = ak_d1_sign == ak_d9_sign
|
|
340
|
+
|
|
341
|
+
if swamsha:
|
|
342
|
+
interp = (
|
|
343
|
+
f"Swamsha — {ak_planet} occupies the same sign ({ak_d1_sign}) in both D1 and D9. "
|
|
344
|
+
"This is exceptionally powerful, conferring spiritual depth, self-mastery, and "
|
|
345
|
+
"heightened manifestation of the Atmakaraka's qualities throughout the life."
|
|
346
|
+
)
|
|
347
|
+
else:
|
|
348
|
+
interp = (
|
|
349
|
+
f"Karakamsha falls in {ak_d9_sign}. This sign and its lord become a supplementary "
|
|
350
|
+
f"Lagna for predicting career, spirituality, and the fruits of past-life deeds. "
|
|
351
|
+
f"The {ak_d9_sign} energy colors how the soul's purpose ({ak_planet} as AK) "
|
|
352
|
+
"expresses in the outer world."
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
return {
|
|
356
|
+
"atmakaraka": ak_planet,
|
|
357
|
+
"atmakaraka_d1_sign": ak_d1_sign,
|
|
358
|
+
"atmakaraka_d9_sign": ak_d9_sign,
|
|
359
|
+
"swamsha": swamsha,
|
|
360
|
+
"interpretation": interp,
|
|
361
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""Kalachakra Dasha: the 9-cycle, 112-year sign-based dasha system.
|
|
2
|
+
|
|
3
|
+
One of the most powerful and complex dasha systems in Vedic astrology.
|
|
4
|
+
Based on birth nakshatra pada position within the 9-group Kalachakra wheel.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from datetime import datetime, timedelta
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
# ── Constants ─────────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
RASHIS = [
|
|
15
|
+
"Aries",
|
|
16
|
+
"Taurus",
|
|
17
|
+
"Gemini",
|
|
18
|
+
"Cancer",
|
|
19
|
+
"Leo",
|
|
20
|
+
"Virgo",
|
|
21
|
+
"Libra",
|
|
22
|
+
"Scorpio",
|
|
23
|
+
"Sagittarius",
|
|
24
|
+
"Capricorn",
|
|
25
|
+
"Aquarius",
|
|
26
|
+
"Pisces",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
# Standard Kalachakra dasha years per sign
|
|
30
|
+
KALACHAKRA_YEARS: dict[str, int] = {
|
|
31
|
+
"Aries": 7,
|
|
32
|
+
"Taurus": 16,
|
|
33
|
+
"Gemini": 9,
|
|
34
|
+
"Cancer": 21,
|
|
35
|
+
"Leo": 5,
|
|
36
|
+
"Virgo": 9,
|
|
37
|
+
"Libra": 16,
|
|
38
|
+
"Scorpio": 7,
|
|
39
|
+
"Sagittarius": 10,
|
|
40
|
+
"Capricorn": 4,
|
|
41
|
+
"Aquarius": 4,
|
|
42
|
+
"Pisces": 4,
|
|
43
|
+
}
|
|
44
|
+
KALACHAKRA_TOTAL = 112 # years per full cycle
|
|
45
|
+
|
|
46
|
+
# Savya (forward) sign sequence
|
|
47
|
+
_SAVYA = RASHIS[:] # Aries → Pisces
|
|
48
|
+
|
|
49
|
+
# Apasavya (reverse) sign sequence
|
|
50
|
+
_APASAVYA = list(reversed(RASHIS)) # Pisces → Aries
|
|
51
|
+
|
|
52
|
+
# The 9 groups, each containing 12 sign slots mapped by pada index 1-12 within group.
|
|
53
|
+
# Groups alternate Savya / Apasavya.
|
|
54
|
+
# Pada index within group (1-based) selects the sign.
|
|
55
|
+
_GROUPS: list[list[str]] = [
|
|
56
|
+
_SAVYA, # Group 1 (padas 1-12) : Aries…Pisces
|
|
57
|
+
_APASAVYA, # Group 2 (padas 13-24) : Pisces…Aries
|
|
58
|
+
_SAVYA, # Group 3 (padas 25-36)
|
|
59
|
+
_APASAVYA, # Group 4 (padas 37-48)
|
|
60
|
+
_SAVYA, # Group 5 (padas 49-60)
|
|
61
|
+
_APASAVYA, # Group 6 (padas 61-72)
|
|
62
|
+
_SAVYA, # Group 7 (padas 73-84)
|
|
63
|
+
_APASAVYA, # Group 8 (padas 85-96)
|
|
64
|
+
_SAVYA, # Group 9 (padas 97-108)
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
# 27 nakshatras in order
|
|
68
|
+
NAKSHATRAS = [
|
|
69
|
+
"Ashwini",
|
|
70
|
+
"Bharani",
|
|
71
|
+
"Krittika",
|
|
72
|
+
"Rohini",
|
|
73
|
+
"Mrigashira",
|
|
74
|
+
"Ardra",
|
|
75
|
+
"Punarvasu",
|
|
76
|
+
"Pushya",
|
|
77
|
+
"Ashlesha",
|
|
78
|
+
"Magha",
|
|
79
|
+
"Purva Phalguni",
|
|
80
|
+
"Uttara Phalguni",
|
|
81
|
+
"Hasta",
|
|
82
|
+
"Chitra",
|
|
83
|
+
"Swati",
|
|
84
|
+
"Vishakha",
|
|
85
|
+
"Anuradha",
|
|
86
|
+
"Jyeshtha",
|
|
87
|
+
"Mula",
|
|
88
|
+
"Purva Ashadha",
|
|
89
|
+
"Uttara Ashadha",
|
|
90
|
+
"Shravana",
|
|
91
|
+
"Dhanishta",
|
|
92
|
+
"Shatabhisha",
|
|
93
|
+
"Purva Bhadrapada",
|
|
94
|
+
"Uttara Bhadrapada",
|
|
95
|
+
"Revati",
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _pada_global_index(moon_lon: float) -> tuple[int, int, float]:
|
|
100
|
+
"""Return (global_pada 1-108, pada_within_nakshatra 1-4, fraction_elapsed 0-1)."""
|
|
101
|
+
nakshatra_span = 360.0 / 27
|
|
102
|
+
pada_span = nakshatra_span / 4
|
|
103
|
+
|
|
104
|
+
nak_idx = int(moon_lon / nakshatra_span) # 0-26
|
|
105
|
+
pos_in_nak = moon_lon % nakshatra_span
|
|
106
|
+
pada_in_nak = int(pos_in_nak / pada_span) # 0-3 within nakshatra
|
|
107
|
+
fraction = (pos_in_nak % pada_span) / pada_span # 0-1 elapsed within current pada
|
|
108
|
+
|
|
109
|
+
global_pada = nak_idx * 4 + pada_in_nak + 1 # 1-108
|
|
110
|
+
return global_pada, pada_in_nak + 1, fraction
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _starting_sign_and_sequence(global_pada: int) -> tuple[str, list[str]]:
|
|
114
|
+
"""Return (starting_sign, full_sequence_of_12_signs_for_this_group)."""
|
|
115
|
+
group_idx = (global_pada - 1) // 12 # 0-8
|
|
116
|
+
pos_in_group = (global_pada - 1) % 12 # 0-11
|
|
117
|
+
|
|
118
|
+
group_sequence = _GROUPS[group_idx]
|
|
119
|
+
starting_sign = group_sequence[pos_in_group]
|
|
120
|
+
|
|
121
|
+
# Dasha sequence from starting_sign wraps within the group sequence
|
|
122
|
+
sequence = group_sequence[pos_in_group:] + group_sequence[:pos_in_group]
|
|
123
|
+
return starting_sign, sequence
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _fmt(dt: datetime) -> str:
|
|
127
|
+
return dt.strftime("%d-%m-%Y")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _days(years: float) -> float:
|
|
131
|
+
return years * 365.25
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ── Public API ─────────────────────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def get_kalachakra_dasha(
|
|
138
|
+
birth_dt: datetime, moon_longitude: float, moon_nakshatra: str
|
|
139
|
+
) -> dict[str, Any]:
|
|
140
|
+
"""Calculate Kalachakra Dasha for a birth chart.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
birth_dt : timezone-aware birth datetime
|
|
145
|
+
moon_longitude: sidereal Moon longitude (0-360)
|
|
146
|
+
moon_nakshatra: Moon's nakshatra name string
|
|
147
|
+
"""
|
|
148
|
+
global_pada, pada_in_nak, fraction_elapsed = _pada_global_index(moon_longitude)
|
|
149
|
+
starting_sign, sign_sequence = _starting_sign_and_sequence(global_pada)
|
|
150
|
+
|
|
151
|
+
# Remaining time in birth (starting) sign's dasha
|
|
152
|
+
birth_sign_years = KALACHAKRA_YEARS[starting_sign]
|
|
153
|
+
remaining_years = (1.0 - fraction_elapsed) * birth_sign_years
|
|
154
|
+
remaining_days = _days(remaining_years)
|
|
155
|
+
|
|
156
|
+
# First MD ends at birth + remaining days
|
|
157
|
+
current_end = birth_dt + timedelta(days=remaining_days)
|
|
158
|
+
|
|
159
|
+
mahadashas: dict[str, Any] = {}
|
|
160
|
+
current_start = birth_dt
|
|
161
|
+
|
|
162
|
+
for i, sign in enumerate(sign_sequence):
|
|
163
|
+
years = KALACHAKRA_YEARS[sign]
|
|
164
|
+
if i == 0:
|
|
165
|
+
# birth sign — only remaining portion
|
|
166
|
+
md_days = remaining_days
|
|
167
|
+
else:
|
|
168
|
+
md_days = _days(years)
|
|
169
|
+
|
|
170
|
+
md_end = current_start + timedelta(days=md_days)
|
|
171
|
+
|
|
172
|
+
# ── Antardashas within this MD ────────────────────────────────────
|
|
173
|
+
# Sub-signs rotate starting from the same sign, same direction as group
|
|
174
|
+
# Duration: (ad_sign_years / KALACHAKRA_TOTAL) * md_duration_years
|
|
175
|
+
antardashas: dict[str, Any] = {}
|
|
176
|
+
ad_start = current_start
|
|
177
|
+
for j, ad_sign in enumerate(sign_sequence):
|
|
178
|
+
ad_years_full = KALACHAKRA_YEARS[ad_sign]
|
|
179
|
+
if i == 0 and j == 0:
|
|
180
|
+
# first sub within first MD — only remaining fraction of AD too
|
|
181
|
+
ad_proportion = 1.0 - fraction_elapsed
|
|
182
|
+
ad_days = _days(
|
|
183
|
+
(ad_proportion * ad_years_full * remaining_years) / birth_sign_years
|
|
184
|
+
)
|
|
185
|
+
else:
|
|
186
|
+
ad_days = _days(
|
|
187
|
+
(ad_years_full / KALACHAKRA_TOTAL)
|
|
188
|
+
* (years if i > 0 else remaining_years)
|
|
189
|
+
)
|
|
190
|
+
ad_end = ad_start + timedelta(days=ad_days)
|
|
191
|
+
antardashas[ad_sign] = {
|
|
192
|
+
"start": _fmt(ad_start),
|
|
193
|
+
"end": _fmt(ad_end),
|
|
194
|
+
"duration_days": round(ad_days, 1),
|
|
195
|
+
}
|
|
196
|
+
ad_start = ad_end
|
|
197
|
+
|
|
198
|
+
mahadashas[sign] = {
|
|
199
|
+
"start": _fmt(current_start),
|
|
200
|
+
"end": _fmt(md_end),
|
|
201
|
+
"duration_years": round(remaining_years if i == 0 else years, 2),
|
|
202
|
+
"antardashas": antardashas,
|
|
203
|
+
}
|
|
204
|
+
current_start = md_end
|
|
205
|
+
|
|
206
|
+
# After one full 112-year cycle, it repeats — annotate
|
|
207
|
+
second_cycle_start = current_start
|
|
208
|
+
second_cycle_note = (
|
|
209
|
+
f"Second cycle starts {_fmt(second_cycle_start)} (repeats from {starting_sign})"
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
"system": "Kalachakra Dasha",
|
|
214
|
+
"total_years_per_cycle": KALACHAKRA_TOTAL,
|
|
215
|
+
"birth_nakshatra": moon_nakshatra,
|
|
216
|
+
"birth_pada": pada_in_nak,
|
|
217
|
+
"global_pada_number": global_pada,
|
|
218
|
+
"kalachakra_group": ((global_pada - 1) // 12) + 1,
|
|
219
|
+
"group_direction": "Savya (forward)"
|
|
220
|
+
if ((global_pada - 1) // 12) % 2 == 0
|
|
221
|
+
else "Apasavya (reverse)",
|
|
222
|
+
"starting_sign": starting_sign,
|
|
223
|
+
"sign_sequence": sign_sequence,
|
|
224
|
+
"mahadashas": mahadashas,
|
|
225
|
+
"second_cycle_note": second_cycle_note,
|
|
226
|
+
}
|