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.
Files changed (131) hide show
  1. libaditya/__init__.py +46 -0
  2. libaditya/_version.py +29 -0
  3. libaditya/calc/__init__.py +9 -0
  4. libaditya/calc/api.py +30 -0
  5. libaditya/calc/avasthas.py +346 -0
  6. libaditya/calc/docs/jaimini-get-arch.md +95 -0
  7. libaditya/calc/hellenistic.py +37 -0
  8. libaditya/calc/jaimini.py +335 -0
  9. libaditya/calc/jaimini_get.py +240 -0
  10. libaditya/calc/kala.py +73 -0
  11. libaditya/calc/panchanga.py +422 -0
  12. libaditya/calc/rashi.py +612 -0
  13. libaditya/calc/returns.py +50 -0
  14. libaditya/calc/swe_functions.py +118 -0
  15. libaditya/calc/varga.py +287 -0
  16. libaditya/calc/vimshottari.py +431 -0
  17. libaditya/cards/__init__.py +5 -0
  18. libaditya/cards/card.py +90 -0
  19. libaditya/cards/cards_constants.py +115 -0
  20. libaditya/cards/cards_of_truth.py +323 -0
  21. libaditya/cards/cot.py +142 -0
  22. libaditya/cards/deck.py +52 -0
  23. libaditya/charts/__init__.py +6 -0
  24. libaditya/charts/api.py +36 -0
  25. libaditya/charts/bodygraph.py +80 -0
  26. libaditya/charts/chart.py +286 -0
  27. libaditya/charts/jaimini.py +83 -0
  28. libaditya/charts/tajika.py +36 -0
  29. libaditya/constants.py +1776 -0
  30. libaditya/draw/__init__.py +20 -0
  31. libaditya/draw/draw_bodygraph.py +489 -0
  32. libaditya/draw/draw_sbc.py +712 -0
  33. libaditya/draw/themes/default-theme.hd +53 -0
  34. libaditya/ephe/ast0/se00010s.se1 +0 -0
  35. libaditya/ephe/seas_00.se1 +0 -0
  36. libaditya/ephe/seas_06.se1 +0 -0
  37. libaditya/ephe/seas_12.se1 +0 -0
  38. libaditya/ephe/seas_18.se1 +0 -0
  39. libaditya/ephe/seas_24.se1 +0 -0
  40. libaditya/ephe/seas_30.se1 +0 -0
  41. libaditya/ephe/seas_36.se1 +0 -0
  42. libaditya/ephe/seas_42.se1 +0 -0
  43. libaditya/ephe/seas_48.se1 +0 -0
  44. libaditya/ephe/seasm06.se1 +0 -0
  45. libaditya/ephe/seasm12.se1 +0 -0
  46. libaditya/ephe/seasm18.se1 +0 -0
  47. libaditya/ephe/seasm24.se1 +0 -0
  48. libaditya/ephe/seasm30.se1 +0 -0
  49. libaditya/ephe/seasm36.se1 +0 -0
  50. libaditya/ephe/seasm42.se1 +0 -0
  51. libaditya/ephe/seasm48.se1 +0 -0
  52. libaditya/ephe/seasm54.se1 +0 -0
  53. libaditya/ephe/sefstars.txt +4245 -0
  54. libaditya/ephe/semo_00.se1 +0 -0
  55. libaditya/ephe/semo_06.se1 +0 -0
  56. libaditya/ephe/semo_12.se1 +0 -0
  57. libaditya/ephe/semo_18.se1 +0 -0
  58. libaditya/ephe/semo_24.se1 +0 -0
  59. libaditya/ephe/semo_30.se1 +0 -0
  60. libaditya/ephe/semo_36.se1 +0 -0
  61. libaditya/ephe/semo_42.se1 +0 -0
  62. libaditya/ephe/semo_48.se1 +0 -0
  63. libaditya/ephe/semom06.se1 +0 -0
  64. libaditya/ephe/semom12.se1 +0 -0
  65. libaditya/ephe/semom18.se1 +0 -0
  66. libaditya/ephe/semom24.se1 +0 -0
  67. libaditya/ephe/semom30.se1 +0 -0
  68. libaditya/ephe/semom36.se1 +0 -0
  69. libaditya/ephe/semom42.se1 +0 -0
  70. libaditya/ephe/semom48.se1 +0 -0
  71. libaditya/ephe/semom54.se1 +0 -0
  72. libaditya/ephe/sepl_00.se1 +0 -0
  73. libaditya/ephe/sepl_06.se1 +0 -0
  74. libaditya/ephe/sepl_12.se1 +0 -0
  75. libaditya/ephe/sepl_18.se1 +0 -0
  76. libaditya/ephe/sepl_24.se1 +0 -0
  77. libaditya/ephe/sepl_30.se1 +0 -0
  78. libaditya/ephe/sepl_36.se1 +0 -0
  79. libaditya/ephe/sepl_42.se1 +0 -0
  80. libaditya/ephe/sepl_48.se1 +0 -0
  81. libaditya/ephe/seplm06.se1 +0 -0
  82. libaditya/ephe/seplm12.se1 +0 -0
  83. libaditya/ephe/seplm18.se1 +0 -0
  84. libaditya/ephe/seplm24.se1 +0 -0
  85. libaditya/ephe/seplm30.se1 +0 -0
  86. libaditya/ephe/seplm36.se1 +0 -0
  87. libaditya/ephe/seplm42.se1 +0 -0
  88. libaditya/ephe/seplm48.se1 +0 -0
  89. libaditya/ephe/seplm54.se1 +0 -0
  90. libaditya/hd/__init__.py +8 -0
  91. libaditya/hd/calc.py +55 -0
  92. libaditya/hd/constants.py +127 -0
  93. libaditya/hd/longitude.py +271 -0
  94. libaditya/objects/__init__.py +19 -0
  95. libaditya/objects/celestial_object.py +206 -0
  96. libaditya/objects/context.py +133 -0
  97. libaditya/objects/cusps.py +259 -0
  98. libaditya/objects/julian_day.py +265 -0
  99. libaditya/objects/location.py +167 -0
  100. libaditya/objects/longitude.py +987 -0
  101. libaditya/objects/nakshatras.py +285 -0
  102. libaditya/objects/planets.py +2059 -0
  103. libaditya/objects/shadbala.py +398 -0
  104. libaditya/objects/signs.py +690 -0
  105. libaditya/objects/swe_functions.py +75 -0
  106. libaditya/print_functions.py +548 -0
  107. libaditya/read.py +665 -0
  108. libaditya/stars/__init__.py +4 -0
  109. libaditya/stars/fixed_star.py +216 -0
  110. libaditya/stars/make_swe_stars.py +407 -0
  111. libaditya/stars/star-sign-boundaries +44 -0
  112. libaditya/stars/stellarium/__init__.py +6 -0
  113. libaditya/stars/stellarium/remote_control/__init__.py +22 -0
  114. libaditya/stars/stellarium/remote_control/location.py +82 -0
  115. libaditya/stars/stellarium/remote_control/locationsearch.py +35 -0
  116. libaditya/stars/stellarium/remote_control/main.py +165 -0
  117. libaditya/stars/stellarium/remote_control/objects.py +63 -0
  118. libaditya/stars/stellarium/remote_control/scripts.py +81 -0
  119. libaditya/stars/stellarium/remote_control/simbad.py +20 -0
  120. libaditya/stars/stellarium/remote_control/stelaction.py +31 -0
  121. libaditya/stars/stellarium/remote_control/stelproperty.py +30 -0
  122. libaditya/stars/stellarium/remote_control/view.py +85 -0
  123. libaditya/stars/stellarium/stellarium.py +92 -0
  124. libaditya/stars/the_stars.py +522 -0
  125. libaditya/stars/utilities.py +539 -0
  126. libaditya/utils.py +431 -0
  127. libaditya/write.py +67 -0
  128. libaditya-0.3.4.dist-info/METADATA +588 -0
  129. libaditya-0.3.4.dist-info/RECORD +131 -0
  130. libaditya-0.3.4.dist-info/WHEEL +5 -0
  131. libaditya-0.3.4.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,431 @@
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 import constants as const
21
+ from libaditya import utils
22
+ from libaditya.objects import Moon, JulianDay
23
+
24
+ # to make code more readable
25
+ lord = 0
26
+ length = 1
27
+
28
+ def print_vimshottari_dasha(planet=Moon(),dlevels=1,yrlen=365.2422):
29
+ """
30
+ print vimshottari dasha based on the position of planet
31
+ to levels = dlevels
32
+ using year lenght yrlen; default is 365.2422, a saura year
33
+ this prints the dashas as it calculates them
34
+ """
35
+
36
+ print("\n\nVimshottari Dasha\n")
37
+
38
+ # this is for the year length
39
+ for key,value in const.dasha_years.items():
40
+ if yrlen == value:
41
+ yrstr = key.capitalize()
42
+
43
+ print(f"Based on the position of {planet.name()}")
44
+ print(f"Using {planet.ayanamsa_name()}")
45
+ print(f"Using {yrstr} year length")
46
+
47
+
48
+ # long is the sidereal longitude
49
+ # nindex is the index of the nakhsatra into pglob.nakshatra
50
+ long = planet.nakshatra().ashvini_longitude()
51
+ nindex = planet.nakshatra().index()
52
+
53
+ # how far into the nakshatra the moon is
54
+ elapsed = long-(nindex*planet.nakshatra().naksize())
55
+ elapsedfraction = elapsed/planet.nakshatra().naksize()
56
+
57
+ # find which dasha is the first mahadasha
58
+ first_dasha = nindex%9
59
+ # dont actually need years_left
60
+ # years_left = const.vimshottari_dashas[first_dasha][length]-dashas[first_dasha][length]*elapsedfraction
61
+ years_elapsed = const.vimshottari_dashas[first_dasha][length]*elapsedfraction
62
+ # age when the mahadasha started, which was probably before birth
63
+ age = -years_elapsed
64
+
65
+ #print(f"Moon is nakshatra {pglob.nakshatra[nindex]}, at {elapsed} degrees out of 13.33")
66
+ #print(f"First mahadasha is of {dashas[first_dasha][0]}, {dashas[first_dasha][1]*elapsedfraction} years into the dasha")
67
+
68
+ # print(f"\n{dashas[first_dasha][lord]} mahadasha: {putil.dec2ymd(age)}")
69
+ # planet.context.timeJD.indent_print(level)
70
+ # next_dasha_starts = panch.shift('f','d', years_left*yrlen)
71
+ # age += dashas[first_dasha%9][length]
72
+ dasha_starts = planet.timeJD.shift('b','d',-age*yrlen)
73
+ level = 0
74
+ for d in range(0,9):
75
+ this_dasha = (first_dasha+d)%9
76
+ # the following is the list of dasha lords
77
+ # we pass to the function that prints the next dasha level
78
+ # in order to calculate the time in that dasha
79
+ dlist = []
80
+ dlist.append(this_dasha)
81
+ print(f"\n{const.vimshottari_dashas[this_dasha][lord]} mahadasha: {utils.dec2ymd(age)}")
82
+ print(f"Duration: {const.vimshottari_dashas[(first_dasha+d)%9][length]} years")
83
+ dasha_starts.indent_print(level)
84
+ if level+1 < dlevels:
85
+ print_next_dasha_level(dlist,dasha_starts,level+1,dlevels,yrlen,age)
86
+ # the other dashas after the first get their full time
87
+ dasha_starts = dasha_starts.shift('f','d', (const.vimshottari_dashas[(first_dasha+d)%9][length])*yrlen)
88
+ age += const.vimshottari_dashas[(first_dasha+d)%9][length]
89
+
90
+ def print_next_dasha_level(dlist,dasha_time,level,dlevels,yrlen,age):
91
+ # if dlevels is 3 and level is 3, we want to print this level, else just return
92
+ if level <= dlevels:
93
+ this_dasha = (dlist[level-1])%9
94
+ # how many tabs to indent printing, based on the level
95
+ tab = utils.mktab(level)
96
+ # how many "sub" dashas
97
+ sub = utils.mksub(level)
98
+ for d in range(0,9):
99
+ lordstr = utils.mk_dasha_lord(dlist+[this_dasha])
100
+ # now we figure out how long this dasha runs
101
+ # then we shift forward to that time, so that on the next loop, we print that information first
102
+ # length of this dasha
103
+ dlen = 1
104
+ #print(f"{dlist=}")
105
+ # dlist has all the dasha level before this one, so multiply all of those
106
+ for lord in dlist:
107
+ dlen = dlen * const.vimshottari_dashas[lord][length]
108
+ # then multiply the lenght of this one
109
+ dlen = dlen * const.vimshottari_dashas[this_dasha][length]
110
+ #print(f"{dlen=}")
111
+ # this gives the decimal value in years for this dasha
112
+ # for two levels, divided by 120, for 3 levels, divide by (120*120), etc.
113
+ # since we start at level 0 in the first function, here level=1 for the second level
114
+ # level=2 for the 3rd level, etc.
115
+ divfac = 120**level
116
+ #print(f"{divfac=}")
117
+ dlen = dlen / divfac
118
+ #print(f"{dlen=} {dlen*yrlen}")
119
+ #print(f"{dlen=}")
120
+ # this print the starts time, date, and age for the current dasha
121
+ print(f"\n{tab}{lordstr} {sub}dasha: {utils.dec2ymd(age)}")
122
+ print(f"{tab}Duration: {utils.dec2ymd(dlen)}")
123
+ dasha_time.indent_print(level)
124
+ if level+1 < dlevels:
125
+ print_next_dasha_level(dlist+[this_dasha],dasha_time,level+1,dlevels,yrlen,age)
126
+ # now shift forward to the next dasha on this level
127
+ # this sets up all the needed information in the next loop
128
+ dasha_time = dasha_time.shift('f','d', dlen*yrlen)
129
+ age += dlen
130
+ this_dasha = (this_dasha+1)%9
131
+
132
+
133
+ def calculate_vimshottari_dasha(planet=Moon(),dlevels=1,yrlen=const.dasha_years["saura"]):
134
+ """
135
+ calculate vimshottari dasha
136
+ first initilaze the base condition
137
+ time is a JulianDay class
138
+ then call calc_vdasha, which is a recursive function that does
139
+ the acutal calculations
140
+ return a list [[dasha1jd,dasha1length,subdasha],etc.,first_dasha_lord,beginning_age]
141
+ """
142
+
143
+ # initialization
144
+
145
+ # long is the sidereal longitude
146
+ # nindex is the index of the nakhsatra into pglob.nakshatra
147
+
148
+ long = planet.nakshatra().ashvini_longitude()
149
+ nindex = planet.nakshatra().index()
150
+
151
+ # how far into the nakshatra the moon is
152
+ elapsed = long-(nindex*planet.nakshatra().naksize())
153
+ elapsedfraction = elapsed/planet.nakshatra().naksize()
154
+
155
+ # find which dasha is the first mahadasha
156
+ first_dasha = nindex%9
157
+ # dont actually need years_left
158
+ # years_left = const.vimshottari_dashas[first_dasha][length]-dashas[first_dasha][length]*elapsedfraction
159
+ years_elapsed = const.vimshottari_dashas[first_dasha][length]*elapsedfraction
160
+ # age when the mahadasha started, which was probably before birth
161
+ age = -years_elapsed
162
+
163
+ dasha_starts_jd = planet.timeJD.shift('b','d',-age*yrlen)
164
+ level = 0
165
+ dlist = [first_dasha]
166
+ vdasha = calc_vdasha(dlist,dasha_starts_jd,level,dlevels,yrlen)
167
+
168
+ return vdasha + [first_dasha] + [age]
169
+
170
+ def period_duration(lords,yrlen=const.dasha_years["saura"]):
171
+ """
172
+ duration in days of a vimshottari period defined by lord indices
173
+ lords = [maha, bhukti, pratyantar, ...]
174
+ e.g. [2,4,5] for Sun-Mars-Rahu pratyantar dasha
175
+ """
176
+ years = 1.0
177
+ for lord_idx in lords:
178
+ years *= const.vimshottari_dashas[lord_idx][length]
179
+ n = len(lords)
180
+ years /= 120 ** (n - 1)
181
+ return years * yrlen
182
+
183
+ def calculate_specific_period(planet=Moon(),lords=[],yrlen=const.dasha_years["saura"]):
184
+ """
185
+ calculate start time and duration of a specific vimshottari period
186
+ without computing the entire dasha tree
187
+
188
+ lords: list of lord indices, e.g. [2, 4, 5] for Sun mahadasha,
189
+ Mars bhukti, Rahu pratyantar
190
+ indices into const.vimshottari_dashas:
191
+ 0=Ketu, 1=Venus, 2=Sun, 3=Moon, 4=Mars, 5=Rahu,
192
+ 6=Jupiter, 7=Saturn, 8=Mercury
193
+
194
+ returns (start_jd, duration_days)
195
+ """
196
+ if not lords:
197
+ return None
198
+
199
+ # initialization (same as calculate_vimshottari_dasha)
200
+ long = planet.nakshatra().ashvini_longitude()
201
+ nindex = planet.nakshatra().index()
202
+ elapsed = long - (nindex * planet.nakshatra().naksize())
203
+ elapsedfraction = elapsed / planet.nakshatra().naksize()
204
+ first_dasha = nindex % 9
205
+ years_elapsed = const.vimshottari_dashas[first_dasha][length] * elapsedfraction
206
+ age = -years_elapsed
207
+ current_jd = planet.timeJD.shift('b','d',-age*yrlen)
208
+
209
+ # walk each level, skipping to the requested lord
210
+ for level in range(len(lords)):
211
+ target = lords[level]
212
+
213
+ # which lord starts this level's sequence?
214
+ if level == 0:
215
+ start_lord = first_dasha
216
+ else:
217
+ start_lord = lords[level - 1] # sub-periods start from parent lord
218
+
219
+ # skip past all periods before the target lord
220
+ this_lord = start_lord
221
+ count = 0
222
+ while this_lord != target and count < 9:
223
+ trial_lords = lords[:level] + [this_lord]
224
+ dur = period_duration(trial_lords, yrlen)
225
+ current_jd = current_jd.shift('f','d', dur)
226
+ this_lord = (this_lord + 1) % 9
227
+ count += 1
228
+
229
+ duration = period_duration(lords, yrlen)
230
+ return (current_jd, duration)
231
+
232
+ def calc_vdasha(dlist,dasha_time,level,dlevels,yrlen):
233
+ this_dasha_list = []
234
+ next_dasha_list = []
235
+ # if dlevels is 3 and level is 3, we want to print this level, else just return
236
+ if level+1 <= dlevels:
237
+ this_dasha = (dlist[level])%9
238
+ for d in range(0,9):
239
+ # find the length of this (sub)dasha
240
+ dlen = 1
241
+ for lord in range(1,len(dlist)):
242
+ dlen = dlen * const.vimshottari_dashas[dlist[lord]][length]
243
+ dlen = dlen * const.vimshottari_dashas[this_dasha][length]
244
+ divfac = 120**level
245
+ dlen = dlen / divfac
246
+ #print(f"{dlen=} {dlen*yrlen}")
247
+ # now dlen is the length of the dasha in years
248
+ if level+1 < dlevels:
249
+ next_dasha_list = calc_vdasha(dlist+[this_dasha],dasha_time,level+1,dlevels,yrlen)
250
+ this_dasha_list.append([dasha_time,dlen*yrlen,next_dasha_list])
251
+ dasha_time = dasha_time.shift('f','d', dlen*yrlen)
252
+ this_dasha = (this_dasha+1)%9
253
+ return this_dasha_list
254
+
255
+ def print_calculated_vimshottari_dasha(dasha):
256
+ """
257
+ print the dasha given in the list dasha
258
+ dasha has the form:
259
+ [[dasha1jd,dasha1length,subdasha],etc.,first_dasha_lord,beginning_age]
260
+ """
261
+ # these initialize what we need to recurse down the dasha list
262
+ age = dasha.pop()
263
+ first_dasha = dasha.pop()
264
+ level = 0
265
+
266
+ pd([first_dasha],dasha,level,age)
267
+
268
+ def pd(dlist,dasha,level,age):
269
+ # how many tabs to indent printing, based on the level
270
+ tab = utils.mktab(level)
271
+ # how many "sub" dashas
272
+ sub = utils.mksub(level)
273
+
274
+ this_dasha = dlist[len(dlist)-1]
275
+
276
+ for d in range(0,len(dasha)):
277
+ lordstr = utils.mk_dasha_lord(dlist[1:]+[this_dasha])
278
+ print(f"\n{tab}{lordstr} {sub}dasha: {utils.dec2ymd(age)}")
279
+ print(f"{tab}Duration: {utils.dec2ymd(dasha[d][1]/365.2422)}")
280
+ dasha[d][0].indent_print(level)
281
+ if dasha[d][2] != []:
282
+ pd(dlist+[this_dasha],dasha[d][2],level+1,age)
283
+ age += dasha[d][1]/365.2422
284
+ this_dasha = (this_dasha+1)%9
285
+
286
+ def current_vimshottari_dasha(planet=Moon(),nowtimeJD=JulianDay(),dlevels=3,yrlen=const.dasha_years["saura"]):
287
+ """
288
+ find the dasha at nowtime for the dashas of someone born at btime down to dlevels levels
289
+ returns a list [lord,lord,lord,...,next_dasha_startsJD]
290
+ """
291
+ # first we need to find where the dashas start
292
+
293
+ # long is the sidereal longitude
294
+ # nindex is the index of the nakhsatra into pglob.nakshatra
295
+ long = planet.nakshatra().ashvini_longitude()
296
+ nindex = planet.nakshatra().index()
297
+
298
+ # how far into the nakshatra the moon is
299
+ elapsed = long-(nindex*planet.nakshatra().naksize())
300
+ elapsedfraction = elapsed/planet.nakshatra().naksize()
301
+
302
+ # find which dasha is the first mahadasha
303
+ first_dasha = nindex%9
304
+ years_elapsed = const.vimshottari_dashas[first_dasha][length]*elapsedfraction
305
+ # age when the mahadasha started, which was probably before birth
306
+ age = -years_elapsed
307
+
308
+ dasha_startsJD = planet.timeJD.shift('b','d',-age*yrlen)
309
+ level = 0
310
+ dlist = [first_dasha]
311
+ # returns a list
312
+ # [[current,dasha,lords], [next,dasha,lords], time_next_dasha_starts]
313
+ result = calc_current(dlist,dasha_startsJD,nowtimeJD,level,dlevels,yrlen)
314
+
315
+ return result
316
+
317
+ def calc_current(dlist,this_dasha_startsJD,nowtimeJD,level,dlevels,yrlen):
318
+ this_dasha = (dlist[level])%9
319
+ next_dasha = (this_dasha+1)%9
320
+
321
+ if level+1<=dlevels:
322
+ for n in range(0,9):
323
+ # find the length of the current dasha
324
+ dlen = 1
325
+ for lord in range(1,len(dlist)):
326
+ dlen = dlen * const.vimshottari_dashas[dlist[lord]][length]
327
+ dlen = dlen * const.vimshottari_dashas[this_dasha][length]
328
+ divfac = 120**level
329
+ dlen = dlen / divfac # the length of this dasha in years
330
+ next_dasha_startsJD = this_dasha_startsJD.shift('f','d',dlen*yrlen)
331
+ # if next_dasha starts after current time, then we are in this dasha
332
+ if next_dasha_startsJD > nowtimeJD:
333
+ next_dasha = calc_current(dlist+[this_dasha],this_dasha_startsJD,nowtimeJD,level+1,dlevels,yrlen)
334
+ if next_dasha == []:
335
+ return [this_dasha] + [next_dasha_startsJD]
336
+ else:
337
+ return [this_dasha] + next_dasha # next_dasha is a list
338
+ # return [this_dasha] + calc_current(dlist+[this_dasha],this_dasha_startsJD,nowtimeJD,level+1,dlevels,yrlen)
339
+ this_dasha = next_dasha
340
+ next_dasha = (this_dasha+1)%9
341
+ this_dasha_startsJD = next_dasha_startsJD
342
+ return []
343
+
344
+ def get_next_lord(lord: int) -> int:
345
+ """
346
+ lord is an integer
347
+ """
348
+ return (lord+1)%9
349
+
350
+ def next_dasha_lords(lords):
351
+ """
352
+ lords is list of dasha lords
353
+ it finds the next dasha lords to the same number of levels
354
+
355
+ only works properly down to 5 levels
356
+
357
+ in this function, we reverse the list
358
+ "first_lord" is actually the last lord in the dasha scheme, etc.
359
+ """
360
+ lords = list(lords.__reversed__())
361
+
362
+ if len(lords) == 1:
363
+ return [get_next_lord(lords[0])]
364
+
365
+ length = len(lords)
366
+
367
+ first_lord = lords[0]
368
+ next_lord = lords[1]
369
+ if get_next_lord(first_lord) == next_lord:
370
+ if length > 2:
371
+ next_next_lord = lords[2]
372
+ if get_next_lord(next_lord) == next_next_lord:
373
+ if length > 3:
374
+ next_next_next_lord = lords[3]
375
+ if get_next_lord(next_next_lord) == next_next_next_lord:
376
+ if length > 4:
377
+ mahadasha_lord = lords[4]
378
+ if get_next_lord(next_next_next_lord) == mahadasha_lord:
379
+ mahadasha_lord = get_next_lord(mahadasha_lord)
380
+ lords[0] = lords[1] = lords[2] = lords[3] = lords[4] = mahadasha_lord
381
+ else:
382
+ next_next_next_lord = get_next_lord(next_next_next_lord)
383
+ lords[0] = lords[1] = lords[2] = lords[3] = next_next_next_lord
384
+ else:
385
+ next_next_lord = get_next_lord(next_next_lord)
386
+ lords[0] = lords[1] = lords[2] = next_next_lord
387
+ else:
388
+ next_lord = get_next_lord(next_lord)
389
+ first_lord = next_lord
390
+ lords[0] = lords[1] = next_lord
391
+ else:
392
+ next_lord = get_next_lord(next_lord)
393
+ lords[0] = lords[1] = next_lord
394
+ else:
395
+ lords[0]=get_next_lord(lords[0])
396
+
397
+ return list(lords.__reversed__())
398
+
399
+ def print_current_vdasha(context,yrlen,levels):
400
+ """
401
+ print information on current vimshottari dasha
402
+ levels is a list of levels, e.g., [1,2,3]
403
+ it will print the information for all these levels
404
+ """
405
+ print("\n\nCurrent Vimshottari Dasha\n")
406
+
407
+ # this is for the year length
408
+ yrstr=""
409
+ for key,value in const.dasha_years.items():
410
+ if yrlen == key:
411
+ yrlen = const.dasha_years[key]
412
+ yrstr = key.capitalize()
413
+
414
+ planet = Moon(context)
415
+ now = JulianDay("now")
416
+
417
+ print(f"Based on the position of {planet.name()}")
418
+ print(f"Using {planet.ayanamsa_name()}")
419
+ print(f"Using {yrstr} year length\n")
420
+
421
+ levels = [x for x in range(1,levels+1)]
422
+
423
+ for level in levels:
424
+ current_dasha = current_vimshottari_dasha(planet,now,level,yrlen)
425
+ next_dasha_startsJD = current_dasha.pop()
426
+
427
+ print(f"Current dasha: {utils.mk_dasha_lord(current_dasha)}")
428
+ print(f"Next dasha: {utils.mk_dasha_lord(next_dasha_lords(current_dasha))}, starts at:")
429
+ print(f"{next_dasha_startsJD}")
430
+ print(f"in {utils.dec2ymd((next_dasha_startsJD.jd_number()-now.jd_number())/365.2422)}\n")
431
+ return
@@ -0,0 +1,5 @@
1
+ from .deck import Deck
2
+ from .cards_of_truth import CardsOfTruth
3
+ from .cot import CoT
4
+
5
+ from libaditya.cards import cards_constants as cardsc
@@ -0,0 +1,90 @@
1
+ #
2
+ # Copyright (c) 2025 Josh Harper <humanhaven@substack.com>
3
+ #
4
+ # libaditya is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # libaditya is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with libaditya. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+ from rich import box
18
+ from rich.table import Table
19
+ from rich.console import Console
20
+
21
+ from libaditya import constants as const
22
+
23
+ from libaditya.cards import cards_constants as cardsc
24
+
25
+ class Card:
26
+
27
+ def __init__(self, card, index, planet="", deck_type="52 playing card"):
28
+ self._card = card
29
+ self._deck_type = deck_type
30
+ self._index = index
31
+ self._planet = planet
32
+ self.attributes = {
33
+ "planets": [],
34
+ "cusps": []
35
+ }
36
+
37
+ def set_attribute(self,attrs):
38
+ """
39
+ attrs is a tuple ("attribute",value)
40
+ add all of these to self.attributes
41
+ attritube is a string that will be a dictionary key for value
42
+ """
43
+ key,value=attrs
44
+ self.attributes[key].append(value)
45
+
46
+ def card(self):
47
+ return self._card
48
+
49
+ def index(self):
50
+ return self._index
51
+
52
+ def glyph(self):
53
+ return const.glyphs[self._planet]
54
+
55
+ def name(self):
56
+ return cardsc.name["number"][self.card()[0]] + " of " + cardsc.name["suit"][self.card()[1]]
57
+
58
+ def symbol(self):
59
+ """
60
+ returns, e.g., 9♥
61
+ """
62
+ return f"{self.card()[0]}{cardsc.symbols[self.card()[1]]}"
63
+
64
+ def planet(self):
65
+ return self._planet
66
+
67
+ def planets(self):
68
+ return self.attributes["planets"]
69
+
70
+ def cusps(self):
71
+ return self.attributes["cusps"]
72
+
73
+ def richDrawing(self):
74
+ """
75
+ return a rich.Table object representing this card
76
+ """
77
+ card = Table(box=box.ROUNDED)
78
+ color = "red" if (self.card()[1] == "H" or self.card()[1] == "D") else "white"
79
+ card.add_column(self.glyph(),justify="center",style="white")
80
+ card.add_row(self.symbol()+"\n",style=color)
81
+ for planet in self.planets():
82
+ card.add_row(planet.name(),style="white")
83
+ for cusp in self.cusps():
84
+ card.add_row(cusp.name(),style="white")
85
+ # do more, like add planets
86
+ return card
87
+
88
+ def rich(self):
89
+ console = Console()
90
+ console.print(self.richDrawing())
@@ -0,0 +1,115 @@
1
+ #
2
+ # Copyright (c) 2025 Josh Harper <humanhaven@substack.com>
3
+ #
4
+ # libaditya is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # libaditya is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with libaditya. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+
18
+ spades_symbol="♠"
19
+ hearts_symbol="♥"
20
+ clubs_symbol="♣"
21
+ diamonds_symbol="♦"
22
+
23
+ symbols = {
24
+ "S": spades_symbol,
25
+ "H": hearts_symbol,
26
+ "C": clubs_symbol,
27
+ "D": diamonds_symbol
28
+ }
29
+
30
+ planet_order = {
31
+ "vedic": ["Base","Sun","Moon","Mars","Mercury","Jupiter","Venus","Saturn","Rahu","Ketu","Ecliptic","Uranus","Neptune","Pluto"],
32
+ "solar_system": ["Base","Sun","Moon","Mercury","Venus","Mars","Jupiter","Saturn","Rahu","Ketu","Ecliptic","Uranus","Neptune","Pluto"]
33
+ }
34
+
35
+ cards = ['AH', '2H', '3H', '4H', '5H', '6H', '7H', '8H', '9H', 'TH',
36
+ 'JH', 'QH', 'KH', 'AC', '2C', '3C', '4C', '5C', '6C', '7C', '8C', '9C', 'TC',
37
+ 'JC', 'QC', 'KC', 'AD', '2D', '3D', '4D', '5D', '6D', '7D', '8D', '9D', 'TD', 'JD', 'QD', 'KD',
38
+ 'AS', '2S', '3S', '4S', '5S', '6S', '7S', '8S', '9S', 'TS', 'JS', 'QS', 'KS']
39
+
40
+ name = {
41
+ "number": {
42
+ "A": "Ace",
43
+ "2": "Two",
44
+ "3": "Three",
45
+ "4": "Four",
46
+ "5": "Five",
47
+ "6": "Six",
48
+ "7": "Seven",
49
+ "8": "Eight",
50
+ "9": "Nine",
51
+ "T": "Ten",
52
+ "J": "Jack",
53
+ "Q": "Queen",
54
+ "K": "King"
55
+ },
56
+ "suit": {
57
+ "S": "Spades",
58
+ "H": "Hearts",
59
+ "C": "Clubs",
60
+ "D": "Diamonds"
61
+ }
62
+ }
63
+
64
+ hearts = list(range(0,13))
65
+ clubs = list(range(13,26))
66
+ diamonds = list(range(26,39))
67
+ spades = list(range(39,52))
68
+
69
+ # spades, hearts, clubs, diamonds
70
+ aces = [39,0,13,26]
71
+ twos = [40,1,14,27]
72
+ threes = [41,2,15,28]
73
+ fours = [42,3,16,29]
74
+ fives = [43,4,17,30]
75
+ sixes = [44,5,18,31]
76
+ sevens = [45,6,19,32]
77
+ eights = [46,7,20,33]
78
+ nines = [47,8,21,34]
79
+ tens = [48,9,22,35]
80
+ jacks = [49,10,23,36]
81
+ queens = [50,11,24,37]
82
+ kings = [51,12,25,38]
83
+
84
+ # utility function for quadration
85
+ def topthree(quad):
86
+ """Return the top three cards on the deck"""
87
+ pile = []
88
+ for i in range(3):
89
+ pile.append(quad.pop(0))
90
+ return pile
91
+
92
+ # this is the jack quadration, 1 through 52
93
+ # 1 is the Ace of Hearts, 52 is the King of Spades...we'll see how that turns out later
94
+ jackquad = list(range(0,52))
95
+ # the first bc starting 01/01/2026 at sunrise is KS
96
+ # at next sunrise switches to QS
97
+ # etc.: goes in reverse order; but each month starts with a different card
98
+ birth_card_order = list(cards.__reversed__())
99
+ # first card of the month is as follows, starting with January
100
+ # then each day goes in order according to calendar day number, based on the savana day at the equator for a given longitude
101
+ # e.g., February 29 after sunrise will be
102
+ first_card_of_the_month = [birth_card_order.index(card) for card in ["KS","JS","9S","7S","5S","3S","AS","QD","TD","8D","3D","4D"]]
103
+
104
+ def days_in_the_month(month: int):
105
+ """
106
+ month is 0-indexed to january
107
+ for cards of truth, February has 29 days...so that "card" only gets that turn to play whenever it is feb.29, right?
108
+ """
109
+ match match:
110
+ case 1 | 3 | 5 | 7 | 8 | 10:
111
+ return 31
112
+ case 4 | 6 | 9 | 11 | 12:
113
+ return 30
114
+ case 2:
115
+ return 20