libaditya 0.3.4__py2.py3-none-any.whl
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.
- libaditya/__init__.py +46 -0
- libaditya/_version.py +29 -0
- libaditya/calc/__init__.py +9 -0
- libaditya/calc/api.py +30 -0
- libaditya/calc/avasthas.py +346 -0
- libaditya/calc/docs/jaimini-get-arch.md +95 -0
- libaditya/calc/hellenistic.py +37 -0
- libaditya/calc/jaimini.py +335 -0
- libaditya/calc/jaimini_get.py +240 -0
- libaditya/calc/kala.py +73 -0
- libaditya/calc/panchanga.py +422 -0
- libaditya/calc/rashi.py +612 -0
- libaditya/calc/returns.py +50 -0
- libaditya/calc/swe_functions.py +118 -0
- libaditya/calc/varga.py +287 -0
- libaditya/calc/vimshottari.py +431 -0
- libaditya/cards/__init__.py +5 -0
- libaditya/cards/card.py +90 -0
- libaditya/cards/cards_constants.py +115 -0
- libaditya/cards/cards_of_truth.py +323 -0
- libaditya/cards/cot.py +142 -0
- libaditya/cards/deck.py +52 -0
- libaditya/charts/__init__.py +6 -0
- libaditya/charts/api.py +36 -0
- libaditya/charts/bodygraph.py +80 -0
- libaditya/charts/chart.py +286 -0
- libaditya/charts/jaimini.py +83 -0
- libaditya/charts/tajika.py +36 -0
- libaditya/constants.py +1776 -0
- libaditya/draw/__init__.py +20 -0
- libaditya/draw/draw_bodygraph.py +489 -0
- libaditya/draw/draw_sbc.py +712 -0
- libaditya/draw/themes/default-theme.hd +53 -0
- libaditya/ephe/ast0/se00010s.se1 +0 -0
- libaditya/ephe/seas_00.se1 +0 -0
- libaditya/ephe/seas_06.se1 +0 -0
- libaditya/ephe/seas_12.se1 +0 -0
- libaditya/ephe/seas_18.se1 +0 -0
- libaditya/ephe/seas_24.se1 +0 -0
- libaditya/ephe/seas_30.se1 +0 -0
- libaditya/ephe/seas_36.se1 +0 -0
- libaditya/ephe/seas_42.se1 +0 -0
- libaditya/ephe/seas_48.se1 +0 -0
- libaditya/ephe/seasm06.se1 +0 -0
- libaditya/ephe/seasm12.se1 +0 -0
- libaditya/ephe/seasm18.se1 +0 -0
- libaditya/ephe/seasm24.se1 +0 -0
- libaditya/ephe/seasm30.se1 +0 -0
- libaditya/ephe/seasm36.se1 +0 -0
- libaditya/ephe/seasm42.se1 +0 -0
- libaditya/ephe/seasm48.se1 +0 -0
- libaditya/ephe/seasm54.se1 +0 -0
- libaditya/ephe/sefstars.txt +4245 -0
- libaditya/ephe/semo_00.se1 +0 -0
- libaditya/ephe/semo_06.se1 +0 -0
- libaditya/ephe/semo_12.se1 +0 -0
- libaditya/ephe/semo_18.se1 +0 -0
- libaditya/ephe/semo_24.se1 +0 -0
- libaditya/ephe/semo_30.se1 +0 -0
- libaditya/ephe/semo_36.se1 +0 -0
- libaditya/ephe/semo_42.se1 +0 -0
- libaditya/ephe/semo_48.se1 +0 -0
- libaditya/ephe/semom06.se1 +0 -0
- libaditya/ephe/semom12.se1 +0 -0
- libaditya/ephe/semom18.se1 +0 -0
- libaditya/ephe/semom24.se1 +0 -0
- libaditya/ephe/semom30.se1 +0 -0
- libaditya/ephe/semom36.se1 +0 -0
- libaditya/ephe/semom42.se1 +0 -0
- libaditya/ephe/semom48.se1 +0 -0
- libaditya/ephe/semom54.se1 +0 -0
- libaditya/ephe/sepl_00.se1 +0 -0
- libaditya/ephe/sepl_06.se1 +0 -0
- libaditya/ephe/sepl_12.se1 +0 -0
- libaditya/ephe/sepl_18.se1 +0 -0
- libaditya/ephe/sepl_24.se1 +0 -0
- libaditya/ephe/sepl_30.se1 +0 -0
- libaditya/ephe/sepl_36.se1 +0 -0
- libaditya/ephe/sepl_42.se1 +0 -0
- libaditya/ephe/sepl_48.se1 +0 -0
- libaditya/ephe/seplm06.se1 +0 -0
- libaditya/ephe/seplm12.se1 +0 -0
- libaditya/ephe/seplm18.se1 +0 -0
- libaditya/ephe/seplm24.se1 +0 -0
- libaditya/ephe/seplm30.se1 +0 -0
- libaditya/ephe/seplm36.se1 +0 -0
- libaditya/ephe/seplm42.se1 +0 -0
- libaditya/ephe/seplm48.se1 +0 -0
- libaditya/ephe/seplm54.se1 +0 -0
- libaditya/hd/__init__.py +8 -0
- libaditya/hd/calc.py +55 -0
- libaditya/hd/constants.py +127 -0
- libaditya/hd/longitude.py +271 -0
- libaditya/objects/__init__.py +19 -0
- libaditya/objects/celestial_object.py +206 -0
- libaditya/objects/context.py +133 -0
- libaditya/objects/cusps.py +259 -0
- libaditya/objects/julian_day.py +265 -0
- libaditya/objects/location.py +167 -0
- libaditya/objects/longitude.py +987 -0
- libaditya/objects/nakshatras.py +285 -0
- libaditya/objects/planets.py +2059 -0
- libaditya/objects/shadbala.py +398 -0
- libaditya/objects/signs.py +690 -0
- libaditya/objects/swe_functions.py +75 -0
- libaditya/print_functions.py +548 -0
- libaditya/read.py +665 -0
- libaditya/stars/__init__.py +4 -0
- libaditya/stars/fixed_star.py +216 -0
- libaditya/stars/make_swe_stars.py +407 -0
- libaditya/stars/star-sign-boundaries +44 -0
- libaditya/stars/stellarium/__init__.py +6 -0
- libaditya/stars/stellarium/remote_control/__init__.py +22 -0
- libaditya/stars/stellarium/remote_control/location.py +82 -0
- libaditya/stars/stellarium/remote_control/locationsearch.py +35 -0
- libaditya/stars/stellarium/remote_control/main.py +165 -0
- libaditya/stars/stellarium/remote_control/objects.py +63 -0
- libaditya/stars/stellarium/remote_control/scripts.py +81 -0
- libaditya/stars/stellarium/remote_control/simbad.py +20 -0
- libaditya/stars/stellarium/remote_control/stelaction.py +31 -0
- libaditya/stars/stellarium/remote_control/stelproperty.py +30 -0
- libaditya/stars/stellarium/remote_control/view.py +85 -0
- libaditya/stars/stellarium/stellarium.py +92 -0
- libaditya/stars/the_stars.py +522 -0
- libaditya/stars/utilities.py +539 -0
- libaditya/utils.py +431 -0
- libaditya/write.py +67 -0
- libaditya-0.3.4.dist-info/METADATA +588 -0
- libaditya-0.3.4.dist-info/RECORD +131 -0
- libaditya-0.3.4.dist-info/WHEEL +5 -0
- libaditya-0.3.4.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# This file is part of libaditya.
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2025 Josh Harper <humanhaven@substack.com>
|
|
4
|
+
#
|
|
5
|
+
# libaditya is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# libaditya is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU Affero General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
# along with libaditya. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
from functools import cmp_to_key
|
|
19
|
+
|
|
20
|
+
from more_itertools import collapse
|
|
21
|
+
|
|
22
|
+
from libaditya import utils
|
|
23
|
+
|
|
24
|
+
from libaditya.objects import Planet, Planets, Sign
|
|
25
|
+
|
|
26
|
+
class Jaimini:
|
|
27
|
+
"""
|
|
28
|
+
this is calc.Jaimini, it inherits unto calc.Varga
|
|
29
|
+
|
|
30
|
+
it is really a Varga, even though Varga inherits from here
|
|
31
|
+
|
|
32
|
+
these are calculations that can happen on any varga, in that varga
|
|
33
|
+
|
|
34
|
+
this class is a "Mixin"
|
|
35
|
+
it has no __init__ functions and cannot instantiate anything
|
|
36
|
+
it inherits unto Varga, giving Varga all of Jaimini capabilities
|
|
37
|
+
|
|
38
|
+
can use any Varga.methods()
|
|
39
|
+
|
|
40
|
+
this is really just to keep Varga from being humongeous by itself, so the functionality
|
|
41
|
+
will be split in modules that inherit into Varga
|
|
42
|
+
|
|
43
|
+
do not confuse with charts.Jaimini, which provides API functionality through Chart
|
|
44
|
+
that is the frontend
|
|
45
|
+
this is the backend
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def pada(self) -> Sign:
|
|
50
|
+
"""
|
|
51
|
+
the "foot" of the lagna
|
|
52
|
+
find how many signs the lagna lord is from the lagna
|
|
53
|
+
from the lord that many signs is the pada
|
|
54
|
+
if the lord is in the 4th or 10th from lagna, pada is in the 4th
|
|
55
|
+
if the lord is in the 1st or 7th from lagna, pada is in the 10th
|
|
56
|
+
|
|
57
|
+
return Sign class of the pada
|
|
58
|
+
"""
|
|
59
|
+
lagna = self.signs().lagna()
|
|
60
|
+
return self._get_pada(lagna)
|
|
61
|
+
|
|
62
|
+
def upapada(self) -> Sign:
|
|
63
|
+
"""
|
|
64
|
+
the "foot" of the 10th cusp
|
|
65
|
+
find how many signs the lagna lord is from the lagna
|
|
66
|
+
from the lord that many signs is the pada
|
|
67
|
+
if the lord is in the 4th or 10th from lagna, pada is in the 4th
|
|
68
|
+
if the lord is in the 1st or 7th from lagna, pada is in the 10th
|
|
69
|
+
|
|
70
|
+
return Sign class of the pada
|
|
71
|
+
"""
|
|
72
|
+
# we need to find the Sign that has the 10th cusp
|
|
73
|
+
tenth = self.signs().where_is(10) # 10 means the 10th cusp
|
|
74
|
+
return self._get_pada(tenth)
|
|
75
|
+
|
|
76
|
+
def padas(self) -> {Sign:Sign}:
|
|
77
|
+
"""
|
|
78
|
+
return a dictionary of all the padas
|
|
79
|
+
key is the Sign, value is the Sign of the pada
|
|
80
|
+
"""
|
|
81
|
+
padas = {}
|
|
82
|
+
for sign in self.signs():
|
|
83
|
+
padas[sign] = self._get_pada(sign)
|
|
84
|
+
return padas
|
|
85
|
+
|
|
86
|
+
def _get_pada(self, sign: Sign) -> Sign:
|
|
87
|
+
"""
|
|
88
|
+
a generic helper to get the pada Sign of Sign sign
|
|
89
|
+
"""
|
|
90
|
+
# Planet class of the lord
|
|
91
|
+
lord = self.planets()[sign.lord()]
|
|
92
|
+
signs_apart = sign.astrological_signs_apart(lord.sign())
|
|
93
|
+
|
|
94
|
+
# check special pada rules
|
|
95
|
+
if signs_apart == 4 or signs_apart == 10:
|
|
96
|
+
return self.signs()[sign.astrological_signs_forward(4)]
|
|
97
|
+
if signs_apart == 1 or signs_apart == 7:
|
|
98
|
+
return self.signs()[sign.astrological_signs_forward(10)]
|
|
99
|
+
# otherwise signs_apart forward from lagna lord is the pada
|
|
100
|
+
lords_sign = self.signs()[lord.sign()]
|
|
101
|
+
return self.signs()[lords_sign.astrological_signs_forward(signs_apart)]
|
|
102
|
+
|
|
103
|
+
def bandhana_yogas(self) -> [([Planet],[Planet])]:
|
|
104
|
+
"""
|
|
105
|
+
return a list of tuples of Planet lists that are forming bandhana yogas
|
|
106
|
+
tuple[0] and tuple[1] are planets are that in bandhana relationship to each other from the ascendant
|
|
107
|
+
if, in:
|
|
108
|
+
2-12
|
|
109
|
+
3-11
|
|
110
|
+
4-10
|
|
111
|
+
5-9
|
|
112
|
+
6-8
|
|
113
|
+
relationship as signs from the ascedant
|
|
114
|
+
"""
|
|
115
|
+
# pairs=((2,12),(3,11),(4,10),(5,9),(6,8))
|
|
116
|
+
# we go forwards and backwards by the same amount
|
|
117
|
+
|
|
118
|
+
pairs = (2,3,4,5,6)
|
|
119
|
+
lagna = self.lagna()
|
|
120
|
+
|
|
121
|
+
ret = []
|
|
122
|
+
|
|
123
|
+
for pair in pairs:
|
|
124
|
+
one = self.signs()[lagna.astrological_signs_forward(pair)]
|
|
125
|
+
two = self.signs()[lagna.astrological_signs_backward(pair)]
|
|
126
|
+
if one.how_many_grahas() == two.how_many_grahas():
|
|
127
|
+
if one.how_many_grahas() == 0:
|
|
128
|
+
continue
|
|
129
|
+
s1ls = []
|
|
130
|
+
s2ls = []
|
|
131
|
+
for sign1, sign2 in zip(one.grahas(),two.grahas()):
|
|
132
|
+
s1ls.append(sign1)
|
|
133
|
+
s2ls.append(sign2)
|
|
134
|
+
ret.append((s1ls,s2ls))
|
|
135
|
+
|
|
136
|
+
return ret
|
|
137
|
+
|
|
138
|
+
def argala(self, rashi: Sign) -> [[Planet], [Planet], [Planet]]:
|
|
139
|
+
"""
|
|
140
|
+
get argala to rashi in this varga
|
|
141
|
+
|
|
142
|
+
returns three lists
|
|
143
|
+
[Planet classes forming argala from/to rashi]
|
|
144
|
+
[malefic Planet classes forming argala to 3rd from rashi]
|
|
145
|
+
[Planet classes being obstructed from/to rashi]
|
|
146
|
+
"""
|
|
147
|
+
# will need the first strength of all the signs to determine argala
|
|
148
|
+
fs = self.jaimini_first_strength()
|
|
149
|
+
# if ketu is in this sign, we could backwards for argala
|
|
150
|
+
sign = -1 if self.where_is("Ketu").sign() == rashi.sign() else 1
|
|
151
|
+
# find our Sign classes of argala-virodhina pairs
|
|
152
|
+
# 2-12
|
|
153
|
+
# 11-3
|
|
154
|
+
# 4-10
|
|
155
|
+
# 9-5
|
|
156
|
+
# check third for more malefics than benefics
|
|
157
|
+
second = self.signs()[rashi.astrological_signs_forward(sign*2)]
|
|
158
|
+
twelfth = self.signs()[rashi.astrological_signs_forward(sign*12)]
|
|
159
|
+
eleventh = self.signs()[rashi.astrological_signs_forward(sign*11)]
|
|
160
|
+
third = self.signs()[rashi.astrological_signs_forward(sign*3)]
|
|
161
|
+
fourth = self.signs()[rashi.astrological_signs_forward(sign*4)]
|
|
162
|
+
tenth = self.signs()[rashi.astrological_signs_forward(sign*10)]
|
|
163
|
+
ninth = self.signs()[rashi.astrological_signs_forward(sign*9)]
|
|
164
|
+
fifth = self.signs()[rashi.astrological_signs_forward(sign*5)]
|
|
165
|
+
argala = []
|
|
166
|
+
obstructed = []
|
|
167
|
+
pairs = [(second,twelfth),(eleventh,third),(fourth,tenth),(ninth,fifth)]
|
|
168
|
+
|
|
169
|
+
# now we can loop on these pairs
|
|
170
|
+
for arg,vir in pairs:
|
|
171
|
+
if arg.how_many_grahas() > vir.how_many_grahas():
|
|
172
|
+
# if there are more grahas in arg, then they cause argala
|
|
173
|
+
# cant be obstructed by vir, so add them to argala list
|
|
174
|
+
argala.append(arg.grahas())
|
|
175
|
+
if arg.how_many_grahas() < vir.how_many_grahas():
|
|
176
|
+
# virodhina house has fewer planets, but are they are also weaker?
|
|
177
|
+
# if they are weaker than cannot obstruct; if not weaker, can obstruct
|
|
178
|
+
# how to determine how weak? sign strength
|
|
179
|
+
if fs.index(vir) > fs.index(arg):
|
|
180
|
+
# vir has a higher index, it is weaker, so it cannot obstruct
|
|
181
|
+
# argala sign is stronger, so the planets form argala
|
|
182
|
+
argala.append(arg.grahas())
|
|
183
|
+
else:
|
|
184
|
+
# if vir has a lower index, it is stronger, so it does obstruct
|
|
185
|
+
obstructed.append(arg.grahas())
|
|
186
|
+
if arg.how_many_grahas() == vir.how_many_grahas():
|
|
187
|
+
obstructed.append(arg.grahas())
|
|
188
|
+
|
|
189
|
+
# check malefic argala in 3rd
|
|
190
|
+
mal = [] # how many malefics in Three
|
|
191
|
+
ben = [] # how many benefics in Three
|
|
192
|
+
for graha in third.grahas():
|
|
193
|
+
if graha.nature() == "Malefic":
|
|
194
|
+
mal.append(graha)
|
|
195
|
+
else:
|
|
196
|
+
ben.append(graha)
|
|
197
|
+
third_argala = []
|
|
198
|
+
if len(mal) > len(ben):
|
|
199
|
+
# if there are more malefics in the 3rd than benefics, these malefics causes a special argala
|
|
200
|
+
third_argala.append(mal)
|
|
201
|
+
|
|
202
|
+
return list(collapse(argala)),list(collapse(third_argala)),list(collapse(obstructed))
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _compare_strength(self, sign1, sign2, kn_rao=False) -> int:
|
|
206
|
+
"""
|
|
207
|
+
compare two signs by Jaimini first source of strength
|
|
208
|
+
returns 1 if sign1 is stronger, -1 if sign2 is stronger, 0 if equal
|
|
209
|
+
|
|
210
|
+
8 tiebreaker levels per the Jaimini sutras:
|
|
211
|
+
0: planet count in sign
|
|
212
|
+
1: highest dignity among occupying planets (sorted comparison)
|
|
213
|
+
2: modality (dual > fixed > movable)
|
|
214
|
+
3: planet count in the lord's sign
|
|
215
|
+
4: highest dignity in the lord's sign
|
|
216
|
+
5: modality of the lord's sign
|
|
217
|
+
6: distance from sign to its lord (greater distance wins)
|
|
218
|
+
7: final tiebreaker (standard: higher rashi number; KN Rao: lord's degree in sign)
|
|
219
|
+
"""
|
|
220
|
+
dignities = self.dignities()
|
|
221
|
+
|
|
222
|
+
# Level 0: planet count in sign
|
|
223
|
+
c1, c2 = sign1.how_many_karakas(), sign2.how_many_karakas()
|
|
224
|
+
if c1 != c2:
|
|
225
|
+
return 1 if c1 > c2 else -1
|
|
226
|
+
|
|
227
|
+
# Level 1: dignity comparison among occupying planets
|
|
228
|
+
result = utils.compare_signs_dignities(sign1, sign2, dignities)
|
|
229
|
+
if result == 1: return 1
|
|
230
|
+
if result == 2: return -1
|
|
231
|
+
|
|
232
|
+
# Level 2: modality
|
|
233
|
+
result = utils.compare_signs_modalities(sign1, sign2)
|
|
234
|
+
if result == 1: return 1
|
|
235
|
+
if result == 2: return -1
|
|
236
|
+
|
|
237
|
+
# Levels 3-5: same three checks on the lord's rashi
|
|
238
|
+
lord1 = self.planets()[sign1.lord()]
|
|
239
|
+
lord2 = self.planets()[sign2.lord()]
|
|
240
|
+
lord1_rashi = self.signs().where_is(sign1.lord())
|
|
241
|
+
lord2_rashi = self.signs().where_is(sign2.lord())
|
|
242
|
+
|
|
243
|
+
# Level 3: planet count in lord's sign
|
|
244
|
+
c1, c2 = lord1_rashi.how_many_karakas(), lord2_rashi.how_many_karakas()
|
|
245
|
+
if c1 != c2:
|
|
246
|
+
return 1 if c1 > c2 else -1
|
|
247
|
+
|
|
248
|
+
# Level 4: dignity comparison in lord's sign
|
|
249
|
+
result = utils.compare_signs_dignities(lord1_rashi, lord2_rashi, dignities)
|
|
250
|
+
if result == 1: return 1
|
|
251
|
+
if result == 2: return -1
|
|
252
|
+
|
|
253
|
+
# Level 5: modality of lord's sign
|
|
254
|
+
result = utils.compare_signs_modalities(lord1_rashi, lord2_rashi)
|
|
255
|
+
if result == 1: return 1
|
|
256
|
+
if result == 2: return -1
|
|
257
|
+
|
|
258
|
+
# Level 6: distance from sign to its lord (greater distance wins)
|
|
259
|
+
d1 = sign1.astrological_signs_apart(lord1.sign())
|
|
260
|
+
d2 = sign2.astrological_signs_apart(lord2.sign())
|
|
261
|
+
if d1 != d2:
|
|
262
|
+
return 1 if d1 > d2 else -1
|
|
263
|
+
|
|
264
|
+
# Level 7: final tiebreaker
|
|
265
|
+
if kn_rao:
|
|
266
|
+
deg1 = lord1.real_in_sign_longitude()
|
|
267
|
+
deg2 = lord2.real_in_sign_longitude()
|
|
268
|
+
if deg1 != deg2:
|
|
269
|
+
return 1 if deg1 > deg2 else -1
|
|
270
|
+
return 0
|
|
271
|
+
else:
|
|
272
|
+
# standard: higher rashi number wins
|
|
273
|
+
if sign1.sign() != sign2.sign():
|
|
274
|
+
return 1 if sign1.sign() > sign2.sign() else -1
|
|
275
|
+
return 0
|
|
276
|
+
|
|
277
|
+
def jaimini_first_strength(self, kn_rao=False) -> [Sign]:
|
|
278
|
+
"""
|
|
279
|
+
calculate Jaiminis first source of strength for all signs
|
|
280
|
+
return a list of Sign classes from strongest (index 0) to weakest (index 11)
|
|
281
|
+
|
|
282
|
+
kn_rao=True uses KN Rao's tiebreaker at level 7 (lord's degree in sign)
|
|
283
|
+
kn_rao=False (default) uses standard tiebreaker (higher rashi number wins)
|
|
284
|
+
"""
|
|
285
|
+
signs = list(self.signs())
|
|
286
|
+
signs.sort(key=cmp_to_key(lambda a, b: self._compare_strength(a, b, kn_rao)), reverse=True)
|
|
287
|
+
return signs
|
|
288
|
+
|
|
289
|
+
def jaimini_second_strength(self) -> {Sign: [Planets]}:
|
|
290
|
+
"""
|
|
291
|
+
calculate Jaiminis second source of strength for all signs
|
|
292
|
+
return a dictionary of Sign: [Planet]
|
|
293
|
+
[Planet] is a list of Planet classes that provide a source of strength to Sign
|
|
294
|
+
due either to conjunctino or rashi aspect
|
|
295
|
+
this be either Mercury, Jupiter, or the Lord of Sign
|
|
296
|
+
"""
|
|
297
|
+
sss = {}
|
|
298
|
+
|
|
299
|
+
jupiter_Sign = self.signs()[self.planets().jupiter().sign()]
|
|
300
|
+
mercury_Sign = self.signs()[self.planets().mercury().sign()]
|
|
301
|
+
|
|
302
|
+
for sign in self.signs():
|
|
303
|
+
sourcels = [] # list to hold Planet-s that are conjunct or aspect this sign
|
|
304
|
+
jup_aspects = self.signs().rashi_aspect_from_to(jupiter_Sign,sign)
|
|
305
|
+
# 1 means jupiter aspects sign from jupiter_Sign; 0 not
|
|
306
|
+
mer_aspects = self.signs().rashi_aspect_from_to(mercury_Sign,sign)
|
|
307
|
+
lord = self.planets()[sign.lord()]
|
|
308
|
+
lords_Sign = self.signs()[lord.sign()]
|
|
309
|
+
lord_aspects = self.signs().rashi_aspect_from_to(lords_Sign,sign)
|
|
310
|
+
if jupiter_Sign == sign or jup_aspects: # the object itself should be the same; means they are in the same sign
|
|
311
|
+
sourcels.append(self.planets().jupiter())
|
|
312
|
+
if mercury_Sign == sign or mer_aspects: # the object itself should be the same
|
|
313
|
+
sourcels.append(self.planets().mercury())
|
|
314
|
+
if lords_Sign == sign or lord_aspects:
|
|
315
|
+
sourcels.append(lord)
|
|
316
|
+
sss[sign] = sourcels
|
|
317
|
+
return sss
|
|
318
|
+
|
|
319
|
+
def jaimini_third_strength(self) -> {Sign: (int, str)}:
|
|
320
|
+
"""
|
|
321
|
+
calculate Jaiminis third source of strength for all signs
|
|
322
|
+
classifies each sign by the distance from sign to its lord:
|
|
323
|
+
Kendra (distance % 3 == 1) = 2 (strong)
|
|
324
|
+
Panapara (distance % 3 == 2) = 1 (moderate)
|
|
325
|
+
Apoklima (distance % 3 == 0) = 0 (weak)
|
|
326
|
+
|
|
327
|
+
return a dictionary of Sign: (value, category_name)
|
|
328
|
+
"""
|
|
329
|
+
categories = {1: (2, "Kendra"), 2: (1, "Panapara"), 0: (0, "Apoklima")}
|
|
330
|
+
ret = {}
|
|
331
|
+
for sign in self.signs():
|
|
332
|
+
lord = self.planets()[sign.lord()]
|
|
333
|
+
distance = sign.astrological_signs_apart(lord.sign())
|
|
334
|
+
ret[sign] = categories[distance % 3]
|
|
335
|
+
return ret
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# This file is part of libaditya.
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2025 Josh Harper <humanhaven@substack.com>
|
|
4
|
+
#
|
|
5
|
+
# libaditya is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# libaditya is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU Affero General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
# along with libaditya. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Gets:
|
|
21
|
+
"""
|
|
22
|
+
factor-s are all signs
|
|
23
|
+
|
|
24
|
+
it is the planets that are conjunct or aspect that provide the effect
|
|
25
|
+
but that is interpretive, what effect and to what extent
|
|
26
|
+
|
|
27
|
+
"gets" are just about calculations
|
|
28
|
+
|
|
29
|
+
to do the interpretation, we need to know which planets are conjunct or aspecting the ak,
|
|
30
|
+
which sign the ak is in in various vargas, etc.
|
|
31
|
+
|
|
32
|
+
that is what we are doing here.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
karakamshas = {
|
|
36
|
+
# AK, i.e.,s the sign of the AK
|
|
37
|
+
"factor": ["AK"],
|
|
38
|
+
"vargas": ["9","1","7"]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
spirituality = {
|
|
42
|
+
"factor": ["12 away AK"],
|
|
43
|
+
"vargas": ["9","24","1"]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
mundane_deity = {
|
|
47
|
+
"factor": ["6 away AmK"],
|
|
48
|
+
"vargas": ["30","9","1"]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
home = {
|
|
52
|
+
"factor": ["4 away AK"],
|
|
53
|
+
"vargas": ["4","16","1"]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
dharma = {
|
|
57
|
+
"factor": ["9 away AK"],
|
|
58
|
+
# 12 for seeing if parental influence supports innate dharma
|
|
59
|
+
"vargas": ["9","1","12"]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
farmer = {
|
|
63
|
+
"factor": ["3", "6", "9"],
|
|
64
|
+
# others?
|
|
65
|
+
"vargas": ["1"]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# this is interpretive actually
|
|
69
|
+
# this is will be covered by "karamashas" near the top
|
|
70
|
+
# adultery = {
|
|
71
|
+
# "factor": ["AK in Mars or AK in Venus"],
|
|
72
|
+
# "vargas": ["9","7","1"]
|
|
73
|
+
# }
|
|
74
|
+
|
|
75
|
+
spouse = {
|
|
76
|
+
"factor": ["7 away AK"],
|
|
77
|
+
"vargas": ["9","7","1"]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
might = {
|
|
81
|
+
"factor": ["3 away AK"],
|
|
82
|
+
"vargas": ["9","3","1"]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
conjurer = {
|
|
86
|
+
"factor": ["5 away AK", "9 away AK"],
|
|
87
|
+
"vargas": ["9","1"]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
capability = {
|
|
91
|
+
# 1.2.40-42: how capable/successful a person is at their livelihood
|
|
92
|
+
"factor": ["10 away AK"],
|
|
93
|
+
"vargas": ["9","1","10"]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
disease_foundation = {
|
|
97
|
+
# 1.2.88-90: chronic/glandular/skin disease (vitiligo, leprosy)
|
|
98
|
+
# same factor as home but different vargas — D30 changes the reading
|
|
99
|
+
"factor": ["4 away AK"],
|
|
100
|
+
"vargas": ["9","30","1"]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
disease_vitality = {
|
|
104
|
+
# 1.2.91-95: bodily wasting, boils, water disease, poison
|
|
105
|
+
"factor": ["AK", "5 away AK"],
|
|
106
|
+
"vargas": ["9","30","1"]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
authorship = {
|
|
110
|
+
# 1.2.102-104: writing ability (Moon+Jupiter = author, etc.)
|
|
111
|
+
"factor": ["AK", "5 away AK"],
|
|
112
|
+
"vargas": ["9","1","10"]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
intelligence = {
|
|
116
|
+
# 1.2.105-114: type of intelligence (poet, logician, mathematician, etc.)
|
|
117
|
+
"factor": ["AK", "5 away AK"],
|
|
118
|
+
"vargas": ["9","24","1"]
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
speech = {
|
|
122
|
+
# 1.2.116-118: secondary skills; Ketu+malefic = speech problems
|
|
123
|
+
"factor": ["2 away AK"],
|
|
124
|
+
"vargas": ["9","1"]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
# dont forget const.multi_vargas
|
|
128
|
+
|
|
129
|
+
# karaka abbreviations in jaimini_karakas() order
|
|
130
|
+
KARAKA_ORDER = ["AK", "AmK", "BK", "MK", "PiK", "GK", "DK"]
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class JaiminiGet:
|
|
134
|
+
"""
|
|
135
|
+
a inheritor for calc.Rashi
|
|
136
|
+
defines functions that get certain sets of planets
|
|
137
|
+
|
|
138
|
+
these are functions that may use any varga, so they are in the Rashi, which has access to all vargas
|
|
139
|
+
|
|
140
|
+
functions that work on the vargas themselves are defined in calc.Varga/calc.Jaimini
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
# default varga overrides: when a Gets spec says "24", use -240 (siddhamsha) by default
|
|
144
|
+
DEFAULT_VARGA_OVERRIDES = {"24": "-240"}
|
|
145
|
+
|
|
146
|
+
def _parse_factor(self, factor_str):
|
|
147
|
+
"""
|
|
148
|
+
parse a factor string into (offset, karaka_abbrev) or (cusp_number, None)
|
|
149
|
+
|
|
150
|
+
"12 away AK" -> (12, "AK")
|
|
151
|
+
"AK" -> (0, "AK")
|
|
152
|
+
"6 away AmK" -> (6, "AmK")
|
|
153
|
+
"3" -> (3, None) # raw cusp number
|
|
154
|
+
"""
|
|
155
|
+
parts = factor_str.split()
|
|
156
|
+
if len(parts) == 3 and parts[1] == "away":
|
|
157
|
+
return int(parts[0]), parts[2]
|
|
158
|
+
elif factor_str in Gets.KARAKA_ORDER:
|
|
159
|
+
return 0, factor_str
|
|
160
|
+
else:
|
|
161
|
+
return int(factor_str), None
|
|
162
|
+
|
|
163
|
+
def _resolve_vargas(self, spec_vargas, varga_overrides=None):
|
|
164
|
+
"""
|
|
165
|
+
apply varga overrides to the spec's varga list
|
|
166
|
+
|
|
167
|
+
varga_overrides is a dict like {"24": "-240"} that replaces
|
|
168
|
+
varga numbers with alternate divisional chart variants
|
|
169
|
+
"""
|
|
170
|
+
overrides = dict(self.DEFAULT_VARGA_OVERRIDES)
|
|
171
|
+
if varga_overrides:
|
|
172
|
+
overrides.update(varga_overrides)
|
|
173
|
+
return [overrides.get(v, v) for v in spec_vargas]
|
|
174
|
+
|
|
175
|
+
def _get_influences(self, varga, sign):
|
|
176
|
+
"""
|
|
177
|
+
given a varga and a Sign, return the conjunction and aspect planets
|
|
178
|
+
"""
|
|
179
|
+
aspecting = varga.rashi_aspects_given_to(sign)
|
|
180
|
+
aspecting = [this_one.grahas() for this_one in aspecting]
|
|
181
|
+
conjunction = [p.jaimini_info() for p in sign.grahas()]
|
|
182
|
+
aspect_list = []
|
|
183
|
+
for sign_planets in aspecting:
|
|
184
|
+
aspect_list.append([p.jaimini_info() for p in sign_planets])
|
|
185
|
+
return {"conjunction": conjunction, "aspecting": aspect_list}
|
|
186
|
+
|
|
187
|
+
def _find_factor_sign(self, varga, factor_str, karakas):
|
|
188
|
+
"""
|
|
189
|
+
given a varga, a factor string, and the karaka list,
|
|
190
|
+
return the Sign that the factor points to
|
|
191
|
+
"""
|
|
192
|
+
offset, karaka_abbrev = self._parse_factor(factor_str)
|
|
193
|
+
|
|
194
|
+
if karaka_abbrev is None:
|
|
195
|
+
# raw cusp number
|
|
196
|
+
cusp_sign_num = varga.cusps()[offset].sign()
|
|
197
|
+
return varga.signs()[cusp_sign_num]
|
|
198
|
+
|
|
199
|
+
karaka_index = Gets.KARAKA_ORDER.index(karaka_abbrev)
|
|
200
|
+
karaka = karakas[karaka_index]
|
|
201
|
+
karaka_sign = varga.where_is(karaka.identity())
|
|
202
|
+
|
|
203
|
+
if offset == 0:
|
|
204
|
+
return karaka_sign
|
|
205
|
+
|
|
206
|
+
direction = 1 if karaka_sign.sign() % 2 == 1 else -1
|
|
207
|
+
return varga.signs()[karaka_sign.astrological_signs_forward(offset * direction)]
|
|
208
|
+
|
|
209
|
+
def jaimini_get(self, spec, varga_overrides=None):
|
|
210
|
+
"""
|
|
211
|
+
general method to get influences for any Gets spec
|
|
212
|
+
|
|
213
|
+
spec is a dict from Gets, e.g. Gets.spirituality, Gets.karakamshas
|
|
214
|
+
varga_overrides is an optional dict like {"24": "-240"} to choose
|
|
215
|
+
alternate varga variants
|
|
216
|
+
|
|
217
|
+
returns a dictionary that can be converted to toml
|
|
218
|
+
"""
|
|
219
|
+
factors = spec["factor"]
|
|
220
|
+
vargas = self._resolve_vargas(spec["vargas"], varga_overrides)
|
|
221
|
+
karakas = self.planets().jaimini_karakas()
|
|
222
|
+
|
|
223
|
+
ret = {
|
|
224
|
+
"aspect_type": self.context.rashi_aspects,
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
for factor_str in factors:
|
|
228
|
+
factor_ret = {}
|
|
229
|
+
for amsha in vargas:
|
|
230
|
+
varga = self.master.varga(int(amsha))
|
|
231
|
+
sign = self._find_factor_sign(varga, factor_str, karakas)
|
|
232
|
+
factor_ret[amsha] = self._get_influences(varga, sign)
|
|
233
|
+
ret[factor_str] = factor_ret
|
|
234
|
+
|
|
235
|
+
return ret
|
|
236
|
+
|
|
237
|
+
def get_spiritual_planets(self, d24=-240):
|
|
238
|
+
"""get spiritual planets using the general get() method"""
|
|
239
|
+
return self.jaimini_get(Gets.spirituality, varga_overrides={"24": str(d24)})
|
|
240
|
+
|
libaditya/calc/kala.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# This file is part of libaditya.
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2025 Josh Harper <humanhaven@substack.com>
|
|
4
|
+
#
|
|
5
|
+
# libaditya is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# libaditya is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU Affero General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
# along with libaditya. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
import swisseph as swe
|
|
19
|
+
|
|
20
|
+
from libaditya.objects import JulianDay, Sun, EphContext
|
|
21
|
+
from libaditya.calc import Panchanga
|
|
22
|
+
|
|
23
|
+
def lunar_new_year(year) -> Panchanga:
|
|
24
|
+
"""
|
|
25
|
+
find chinese lunar new year in calendar year "year"
|
|
26
|
+
chinese lunar new year is the second new moon after the winter solstice
|
|
27
|
+
so the lunar new year in 2026 is after the solstice in 2025
|
|
28
|
+
year can be an integer or a JulianDay class
|
|
29
|
+
"""
|
|
30
|
+
if isinstance(year,JulianDay):
|
|
31
|
+
year = year.year()
|
|
32
|
+
# get january 1st of the previous year so we can find the winter solstice of that year
|
|
33
|
+
solstice_yearJD = JulianDay(swe.julday(year-1,1,1))
|
|
34
|
+
solsticeSun = Sun(EphContext(timeJD=solstice_yearJD)).ingress(270)
|
|
35
|
+
|
|
36
|
+
# now get a Panchanga for this time
|
|
37
|
+
panch = Panchanga(solsticeSun.context)
|
|
38
|
+
|
|
39
|
+
new_year = panch.next_new_moon().next_new_moon()
|
|
40
|
+
|
|
41
|
+
return new_year
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def cardinal_points(year) -> [JulianDay]:
|
|
46
|
+
"""
|
|
47
|
+
return the cardinal points of the year in order
|
|
48
|
+
i.e., ascending equinox, northern solstice, descedending equinox, southern solstice
|
|
49
|
+
"""
|
|
50
|
+
year_jd = swe.julday(year,1,1,0)
|
|
51
|
+
s=Sun(EphContext(timeJD=JulianDay(year_jd)))
|
|
52
|
+
return [s.ingress(0), s.ingress(90), s.ingress(180), s.ingress(270)]
|
|
53
|
+
|
|
54
|
+
def print_cardinal_points(year: int | JulianDay) -> None:
|
|
55
|
+
"""
|
|
56
|
+
print four cardinal points of year
|
|
57
|
+
year can be specified as either integer or JulianDay
|
|
58
|
+
"""
|
|
59
|
+
# get january 1 of year
|
|
60
|
+
if isinstance(year,JulianDay):
|
|
61
|
+
year = year.year()
|
|
62
|
+
points = cardinal_points(year)
|
|
63
|
+
|
|
64
|
+
print(f"Cardinal points for {year}\n")
|
|
65
|
+
|
|
66
|
+
print("Ascending equinox:")
|
|
67
|
+
print(points[0])
|
|
68
|
+
print("Northern solstice:")
|
|
69
|
+
print(points[1])
|
|
70
|
+
print("Descending equinox:")
|
|
71
|
+
print(points[2])
|
|
72
|
+
print("Southern solstice:")
|
|
73
|
+
print(points[3])
|