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,75 @@
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
+ import swisseph as swe
18
+
19
+ from libaditya import utils
20
+
21
+ from libaditya.objects import JulianDay
22
+
23
+ class SWEFirstLast:
24
+ """
25
+ this class inherits unto Moon, Mercury, Venus
26
+ contains all the relevant swe functions
27
+
28
+ will document here as implemented
29
+
30
+ next_heliacal_rising()
31
+ next_heliacal_setting() -> if either is Moon, returns None
32
+ next_evening_first()
33
+ next_morning_last() -> both for Moon, Mercury, Venus only
34
+ """
35
+
36
+ def next_evening_first(self):
37
+ if self.identity() not in ["Moon", "Mercury", "Venus"]:
38
+ return
39
+ return utils.toJD(swe.heliacal_ut(
40
+ self.timeJD.jd_number(),
41
+ self.context.location.swe_location(),
42
+ # need to figure out how to get current information for the place
43
+ # relative humdity can do with metpy, but it is a lot of dependcies for just one thing that
44
+ # may not really be that important
45
+ # the 4-tuple of 0 sets atmospheric information to general values
46
+ (0,0,0,0),
47
+ # a 6-tuple of values relative to an observer and various observing situations
48
+ (0,0,0,0,0,0),
49
+ self.identity(),
50
+ swe.EVENING_FIRST,
51
+ # this is the ephemeris flag, i think
52
+ self.sysflg
53
+ ), self.context)
54
+
55
+ def next_morning_last(self) -> [JulianDay]:
56
+ if self.identity() not in ["Moon", "Mercury", "Venus"]:
57
+ return
58
+ return utils.toJD(swe.heliacal_ut(
59
+ self.timeJD.jd_number(),
60
+ self.context.location.swe_location(),
61
+ # need to figure out how to get current information for the place
62
+ # relative humdity can do with metpy, but it is a lot of dependcies for just one thing that
63
+ # may not really be that important
64
+ # the 4-tuple of 0 sets atmospheric information to general values
65
+ (0,0,0,0),
66
+ # a 6-tuple of values relative to an observer and various observing situations
67
+ (0,0,0,0,0,0),
68
+ self.identity(),
69
+ swe.MORNING_LAST,
70
+ # this is the ephemeris flag, i think
71
+ self.sysflg
72
+ ), self.context)
73
+
74
+
75
+ # add meridian transits
@@ -0,0 +1,548 @@
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
+ a variety of functions to return string forms of various information
20
+ that can be computed with libaditya
21
+ """
22
+
23
+ from prettytable import PrettyTable
24
+
25
+ from libaditya import constants as const
26
+ from libaditya.objects import Planet, Sign
27
+
28
+
29
+ def dignity_table(dignities):
30
+ """
31
+ takes a list of dignites from Planets.dignities and output a string form
32
+ """
33
+ ret = ""
34
+ for n in range(0,len(dignities)):
35
+ ret += f"{const.karaka_glyphs[n]} : {dignities[n]}\n"
36
+ # slice removes last \n
37
+ return ret[:-1]
38
+
39
+ def print_dignity_table(dignites):
40
+ print(dignity_table(dignites))
41
+
42
+ def varga_deities(deities):
43
+ """
44
+ takes a list of dignites from Planets.deities and output a string form
45
+ """
46
+ ret = ""
47
+ for n in range(0,9):
48
+ ret += f"{const.graha_glyphs[n]} : {deities[n]}\n"
49
+ ret += f"Lg : {deities[9]}\n"
50
+ return ret
51
+
52
+ def print_varga_deities(deities):
53
+ print(varga_deities(deities))
54
+
55
+ def parashara_aspect_table_planets(aspects):
56
+ """
57
+ aspects is a list of lists, i.e., a list of rows returned by Planets.parashara_aspects
58
+ make a prettytable list of these values
59
+ """
60
+ output = PrettyTable()
61
+ output.field_names = [" "] + [glyph for glyph in const.graha_glyphs]
62
+ output.align[" "] = "l"
63
+
64
+ for n,row in enumerate(aspects):
65
+ output.add_row(*[[const.karaka_glyphs[n]] + row])
66
+ output.add_divider()
67
+
68
+ ret = output.get_string(fields=[" "] + [glyph for glyph in const.graha_glyphs])
69
+
70
+ return ret
71
+
72
+ def parashara_aspect_table_cusps(aspects):
73
+ """
74
+ aspects is a list of lists, i.e., a list of rows returned by Planets.parashara_aspects
75
+ make a prettytable list of these values
76
+ """
77
+ output = PrettyTable()
78
+ output.field_names = [" "] + [str(n) for n in range(1,13)]
79
+ output.align[" "] = "l"
80
+
81
+ for n,row in enumerate(aspects):
82
+ output.add_row(*[[const.karaka_glyphs[n]] + row])
83
+ output.add_divider()
84
+
85
+ return output.get_string(fields=[" "] + [str(n) for n in range(1,13)])
86
+
87
+ def jaimini_karakas_str(karakas) -> str:
88
+ """
89
+ return a PrettyTable string displaying the Jaimini karakas in karakas
90
+ karakas is a list of Planet classes, with ak being element 0, amk element 1, etc.
91
+ """
92
+ output = PrettyTable()
93
+ output.field_names = ["AK", "AmK", "BK", "MK/PuK", "PiK", "GK", "DK"]
94
+
95
+ # this table only has a header and one row
96
+ output.add_row([planet.glyph() for planet in karakas])
97
+
98
+ return output.get_string(fields=["AK", "AmK", "BK", "MK/PuK", "PiK", "GK", "DK"])
99
+
100
+ def print_jaimini_karakas(karakas):
101
+ print(jaimini_karakas_str(karakas))
102
+
103
+ def print_padas(padas):
104
+ """
105
+ receive a dictionary of all the padas
106
+ key is the sign number, value is the Sign of the pada
107
+ """
108
+ for sign,pada in padas.items():
109
+ print(f"{sign.sign_name()} pada: {pada.sign_name()}")
110
+
111
+ def print_jaimini_first_strength(fs: [int]) -> None:
112
+ """
113
+ print jaiminis first strength
114
+ """
115
+ for n,s in enumerate(fs):
116
+ print(f"{n+1}\t{s.glyph()} {s.sign()}")
117
+
118
+ def print_jaimini_second_strength(ssd: {Sign: [Planet]}) -> None:
119
+ """
120
+ print jaiminis second strength
121
+ """
122
+ for sign, strengths in ssd.items():
123
+ fstr = ""
124
+ fstr += f"({sign.sign()}) {sign.glyph()}\t"
125
+ for strength in strengths:
126
+ # strengh is a Planet class
127
+ fstr+=f" {strength.abbreviation()} "
128
+ print(fstr)
129
+
130
+ def print_jaimini_argala(result: [Planet]):
131
+ """
132
+ result is a list of Planet-s returned by Varga().argala()
133
+ the result of argala to one specific house
134
+ Rashi().argala() returns the results of argala to the signs of the lagna and 7th cusp; not currently printed by this function
135
+
136
+ result[0] = planets forming argala
137
+ result[1] = malefics forming malefic argala to the 3rd
138
+ result[2] = planets having their argala obstructed
139
+ """
140
+ print(f"argala to the rashi:")
141
+ for planet in result[0]:
142
+ print(planet.identity())
143
+ print(f"\nmalefics causing argala from/to the third:")
144
+ for planet in result[1]:
145
+ print(planet.identity())
146
+ print(f"\nobstructed planets from the rashi:")
147
+ for planet in result[2]:
148
+ print(planet.identity())
149
+
150
+ def print_jaimini_aspects(chart):
151
+ """
152
+ print all effective rashi aspects for this chart
153
+ """
154
+ print(f"Rashi aspects ({chart.context.rashi_aspects})")
155
+
156
+ s = chart.rashi().signs()
157
+ for sign in s:
158
+ print(f"\n{sign.name()}")
159
+ aspected = s.rashi_aspects_given_by(sign)
160
+ aspecting = s.rashi_aspects_given_to(sign)
161
+ for ap in aspected:
162
+ print(f"{sign.name()} -> {ap.name()}")
163
+ for ap in aspecting:
164
+ print(f"{sign.name()} <- {ap.name()}")
165
+
166
+ def print_jaimini_spiritual_planets(splanets):
167
+ """
168
+ prints infomration returned by Rashi.get_spiritual_planets
169
+ """
170
+ vargas = ["1","9","24","-24","-240"]
171
+ print("Spiritual planets:")
172
+
173
+ for varga in splanets.keys():
174
+ if not varga in vargas:
175
+ continue
176
+ print(f"d{varga}:")
177
+ print("Conjunctions")
178
+ for planet in splanets[varga]["conjunction"][0]:
179
+ # planets that are conjunct
180
+ print(f"\t{planet}")
181
+ print("Aspecting")
182
+ for sign in splanets[varga]["aspecting"]:
183
+ for planet in sign:
184
+ print(f"\t{planet}")
185
+
186
+ def print_visible_times(times):
187
+ """
188
+ takes a list of three JulianDay classes
189
+ 0 - start of visibility
190
+ 1 - optimum visibility
191
+ 2 - end of visibility
192
+ """
193
+ print("Start of visibility:")
194
+ print(times[0])
195
+ print("Optimum visibility:")
196
+ print(times[1])
197
+ print("End of visibility:")
198
+ print(times[2])
199
+
200
+ def lajjitaadi_avasthas_table(avasthas) -> str:
201
+ """
202
+ Takes the dict returned by Rashi.lajjitaadi_avasthas() and returns
203
+ a PrettyTable string.
204
+ """
205
+ output = PrettyTable()
206
+ output.field_names = ["Planet", "Avastha", "Source", "Details", "Strength"]
207
+ output.align["Planet"] = "l"
208
+ output.align["Avastha"] = "l"
209
+ output.align["Source"] = "l"
210
+ output.align["Details"] = "l"
211
+ output.align["Strength"] = "r"
212
+
213
+ for planet_name, planet_avasthas in avasthas.items():
214
+ for avastha_name, factors in planet_avasthas.items():
215
+ for factor in factors:
216
+ source = factor.get("source", "")
217
+ strength = factor.get("strength", "")
218
+ details = ""
219
+ if "planet" in factor:
220
+ details = factor["planet"]
221
+ elif "lord" in factor:
222
+ details = f"lord: {factor['lord']}"
223
+ elif "dignity" in factor:
224
+ details = factor["dignity"]
225
+ elif "detail" in factor:
226
+ details = factor["detail"]
227
+ output.add_row([planet_name, avastha_name.capitalize(), source, details, strength])
228
+
229
+ return output.get_string()
230
+
231
+ def print_lajjitaadi_avasthas(avasthas):
232
+ print(lajjitaadi_avasthas_table(avasthas))
233
+
234
+
235
+ AVASTHA_PLANET_ORDER = ["Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn"]
236
+
237
+ def avasthas_table(lajjitaadi, baladi, jagradadi, deeptadi, shayanadi) -> str:
238
+ # simple avasthas table
239
+ simple = PrettyTable()
240
+ simple.field_names = ["Planet", "Baladi", "Jagradadi", "Deeptadi", "Shayanadi"]
241
+ simple.align = "l"
242
+ for name in AVASTHA_PLANET_ORDER:
243
+ simple.add_row([name,
244
+ baladi.get(name, ""),
245
+ jagradadi.get(name, ""),
246
+ deeptadi.get(name, ""),
247
+ shayanadi.get(name, "")])
248
+
249
+ # lajjitaadi table
250
+ lajj = lajjitaadi_avasthas_table(lajjitaadi)
251
+
252
+ # lajjitaadi interaction sentences
253
+ verbs = {"delighted": "delighting", "starved": "starving", "agitated": "agitating",
254
+ "thirsty": "thirsting", "shamed": "shaming"}
255
+ adjectives = {"healthy": "secure", "proud": "proud"}
256
+ interactions = PrettyTable()
257
+ interactions.field_names = ["Interaction"]
258
+ interactions.align = "l"
259
+ for planet_name, planet_avasthas in lajjitaadi.items():
260
+ for avastha_name, factors in planet_avasthas.items():
261
+ if avastha_name in adjectives:
262
+ interactions.add_row([f"{planet_name} is {adjectives[avastha_name]}"])
263
+ continue
264
+ verb = verbs.get(avastha_name)
265
+ if not verb:
266
+ continue
267
+ for factor in factors:
268
+ if "planet" in factor:
269
+ interactions.add_row([f"{factor['planet']} is {verb} {planet_name}"])
270
+
271
+ return simple.get_string() + "\n\nLajjitaadi Avasthas\n" + lajj + "\n\n" + interactions.get_string()
272
+
273
+ def print_avasthas(lajjitaadi, baladi, jagradadi, deeptadi, shayanadi):
274
+ print(avasthas_table(lajjitaadi, baladi, jagradadi, deeptadi, shayanadi))
275
+
276
+
277
+ def akriti_yogas_table(akritis) -> str:
278
+ """
279
+ Takes the list of AkritiYoga dataclasses returned by Rashi.akriti_yogas()
280
+ and returns a PrettyTable string, sorted by to_move ascending.
281
+ """
282
+ output = PrettyTable()
283
+ output.field_names = ["Yoga", "Translation", "To Move", "Houses"]
284
+ output.align["Yoga"] = "l"
285
+ output.align["Translation"] = "l"
286
+ output.align["To Move"] = "r"
287
+ output.align["Houses"] = "l"
288
+ for y in akritis:
289
+ houses_str = ", ".join(str(h) for h in y.houses)
290
+ output.add_row([y.name, y.translation, y.to_move, houses_str])
291
+ return output.get_string()
292
+
293
+ def print_akriti_yogas(akritis):
294
+ print(akriti_yogas_table(akritis))
295
+
296
+ def rich_akriti_yogas_table(akritis):
297
+ """
298
+ Takes the list of AkritiYoga dataclasses returned by Rashi.akriti_yogas()
299
+ and returns a Rich Table renderable, sorted by to_move ascending.
300
+ """
301
+ from rich.table import Table
302
+ from rich.text import Text
303
+
304
+ output = Table(title="Akriti Yogas", box=None)
305
+ output.add_column("Yoga", style="bold", justify="left")
306
+ output.add_column("Translation", justify="left")
307
+ output.add_column("To Move", justify="right")
308
+ output.add_column("Houses", justify="left")
309
+
310
+ for y in akritis:
311
+ houses_str = ", ".join(str(h) for h in y.houses)
312
+ tm = y.to_move
313
+ if tm <= 2:
314
+ style = "bold green"
315
+ elif tm <= 4:
316
+ style = "green"
317
+ elif tm <= 5:
318
+ style = ""
319
+ else:
320
+ style = "dim"
321
+ output.add_row(
322
+ Text(y.name, style=style),
323
+ Text(y.translation, style=style),
324
+ Text(str(tm), style=style),
325
+ Text(houses_str, style=style),
326
+ )
327
+ return output
328
+
329
+ def rich_akriti_yogas(akritis):
330
+ from rich.console import Console
331
+ Console().print(rich_akriti_yogas_table(akritis))
332
+
333
+
334
+ def nabhasa_yogas_table(yogas) -> str:
335
+ """
336
+ Takes the list returned by Rashi.nabhasa_yogas() (or ashraya/dala/sankhya)
337
+ and returns a PrettyTable string, sorted by to_move ascending.
338
+ """
339
+ output = PrettyTable()
340
+ output.field_names = ["Yoga", "Translation", "Category", "To Move", "Condition"]
341
+ output.align["Yoga"] = "l"
342
+ output.align["Translation"] = "l"
343
+ output.align["Category"] = "l"
344
+ output.align["To Move"] = "r"
345
+ output.align["Condition"] = "l"
346
+ for y in yogas:
347
+ cat = getattr(y, 'category', 'Akriti')
348
+ cond = getattr(y, 'condition', None) or ", ".join(str(h) for h in y.houses)
349
+ output.add_row([y.name, y.translation, cat, y.to_move, cond])
350
+ return output.get_string()
351
+
352
+ def print_nabhasa_yogas(yogas):
353
+ print(nabhasa_yogas_table(yogas))
354
+
355
+ def rich_nabhasa_yogas_table(yogas):
356
+ """
357
+ Takes the list returned by Rashi.nabhasa_yogas() (or ashraya/dala/sankhya)
358
+ and returns a Rich Table renderable, sorted by to_move ascending.
359
+ """
360
+ from rich.table import Table
361
+ from rich.text import Text
362
+
363
+ output = Table(title="Nabhasa Yogas", box=None)
364
+ output.add_column("Yoga", style="bold", justify="left")
365
+ output.add_column("Translation", justify="left")
366
+ output.add_column("Category", justify="left")
367
+ output.add_column("To Move", justify="right")
368
+ output.add_column("Condition", justify="left")
369
+
370
+ for y in yogas:
371
+ cat = getattr(y, 'category', 'Akriti')
372
+ cond = getattr(y, 'condition', None) or ", ".join(str(h) for h in y.houses)
373
+ tm = y.to_move
374
+ if tm <= 2:
375
+ style = "bold green"
376
+ elif tm <= 4:
377
+ style = "green"
378
+ elif tm <= 5:
379
+ style = ""
380
+ else:
381
+ style = "dim"
382
+ output.add_row(
383
+ Text(y.name, style=style),
384
+ Text(y.translation, style=style),
385
+ Text(cat, style=style),
386
+ Text(str(tm), style=style),
387
+ Text(cond, style=style),
388
+ )
389
+ return output
390
+
391
+ def rich_nabhasa_yogas(yogas):
392
+ from rich.console import Console
393
+ Console().print(rich_nabhasa_yogas_table(yogas))
394
+
395
+
396
+ def mahapurusha_yogas_table(yogas) -> str:
397
+ output = PrettyTable()
398
+ output.field_names = ["Yoga", "Translation", "Planet", "Present", "House", "Dignity"]
399
+ output.align["Yoga"] = "l"
400
+ output.align["Translation"] = "l"
401
+ output.align["Planet"] = "l"
402
+ output.align["Present"] = "c"
403
+ output.align["House"] = "r"
404
+ output.align["Dignity"] = "l"
405
+ for y in yogas:
406
+ output.add_row([y.name, y.translation, y.planet,
407
+ "Yes" if y.present else "No", y.house, y.dignity])
408
+ return output.get_string()
409
+
410
+ def print_mahapurusha_yogas(yogas):
411
+ print(mahapurusha_yogas_table(yogas))
412
+
413
+ def rich_mahapurusha_yogas_table(yogas):
414
+ from rich.table import Table
415
+ from rich.text import Text
416
+
417
+ output = Table(title="Panchamahapurusha Yogas", box=None)
418
+ output.add_column("Yoga", style="bold", justify="left")
419
+ output.add_column("Translation", justify="left")
420
+ output.add_column("Planet", justify="left")
421
+ output.add_column("Present", justify="center")
422
+ output.add_column("House", justify="right")
423
+ output.add_column("Dignity", justify="left")
424
+
425
+ for y in yogas:
426
+ style = "bold green" if y.present else "dim"
427
+ output.add_row(
428
+ Text(y.name, style=style),
429
+ Text(y.translation, style=style),
430
+ Text(y.planet, style=style),
431
+ Text("Yes" if y.present else "No", style=style),
432
+ Text(str(y.house), style=style),
433
+ Text(y.dignity, style=style),
434
+ )
435
+ return output
436
+
437
+ def rich_mahapurusha_yogas(yogas):
438
+ from rich.console import Console
439
+ Console().print(rich_mahapurusha_yogas_table(yogas))
440
+
441
+
442
+ def solar_yogas_table(yogas) -> str:
443
+ output = PrettyTable()
444
+ output.field_names = ["Yoga", "Present", "Planets"]
445
+ output.align["Yoga"] = "l"
446
+ output.align["Present"] = "c"
447
+ output.align["Planets"] = "l"
448
+ for y in yogas:
449
+ output.add_row([y.name, "Yes" if y.present else "No",
450
+ ", ".join(y.planets) if y.planets else "—"])
451
+ return output.get_string()
452
+
453
+ def print_solar_yogas(yogas):
454
+ print(solar_yogas_table(yogas))
455
+
456
+ def rich_solar_yogas_table(yogas):
457
+ from rich.table import Table
458
+ from rich.text import Text
459
+
460
+ output = Table(title="Solar Yogas", box=None)
461
+ output.add_column("Yoga", style="bold", justify="left")
462
+ output.add_column("Present", justify="center")
463
+ output.add_column("Planets", justify="left")
464
+
465
+ for y in yogas:
466
+ style = "bold green" if y.present else "dim"
467
+ planets_str = ", ".join(y.planets) if y.planets else "—"
468
+ output.add_row(
469
+ Text(y.name, style=style),
470
+ Text("Yes" if y.present else "No", style=style),
471
+ Text(planets_str, style=style),
472
+ )
473
+ return output
474
+
475
+ def rich_solar_yogas(yogas):
476
+ from rich.console import Console
477
+ Console().print(rich_solar_yogas_table(yogas))
478
+
479
+
480
+ def lunar_yogas_table(yogas) -> str:
481
+ output = PrettyTable()
482
+ output.field_names = ["Yoga", "Present", "Planets"]
483
+ output.align["Yoga"] = "l"
484
+ output.align["Present"] = "c"
485
+ output.align["Planets"] = "l"
486
+ for y in yogas:
487
+ output.add_row([y.name, "Yes" if y.present else "No",
488
+ ", ".join(y.planets) if y.planets else "—"])
489
+ return output.get_string()
490
+
491
+ def print_lunar_yogas(yogas):
492
+ print(lunar_yogas_table(yogas))
493
+
494
+ def rich_lunar_yogas_table(yogas):
495
+ from rich.table import Table
496
+ from rich.text import Text
497
+
498
+ output = Table(title="Lunar Yogas", box=None)
499
+ output.add_column("Yoga", style="bold", justify="left")
500
+ output.add_column("Present", justify="center")
501
+ output.add_column("Planets", justify="left")
502
+
503
+ for y in yogas:
504
+ style = "bold green" if y.present else "dim"
505
+ planets_str = ", ".join(y.planets) if y.planets else "—"
506
+ output.add_row(
507
+ Text(y.name, style=style),
508
+ Text("Yes" if y.present else "No", style=style),
509
+ Text(planets_str, style=style),
510
+ )
511
+ return output
512
+
513
+ def rich_lunar_yogas(yogas):
514
+ from rich.console import Console
515
+ Console().print(rich_lunar_yogas_table(yogas))
516
+
517
+
518
+ from libaditya.cards import cards_constants as cardsc
519
+ cards=cardsc.cards
520
+
521
+ def print_cot_quadration(pquad):
522
+ """Print a quadration"""
523
+ # remember that lists are indexed starting with 0
524
+ print(' {} {} {} '.format(cards[pquad[51]], cards[pquad[50]], cards[pquad[49]]))
525
+ print('{} {} {} {} {} {} {}'.format(cards[pquad[6]], cards[pquad[5]], cards[pquad[4]],
526
+ cards[pquad[3]], cards[pquad[2]], cards[pquad[1]], cards[pquad[0]]))
527
+ print('{} {} {} {} {} {} {}'.format(cards[pquad[13]], cards[pquad[12]], cards[pquad[11]], cards[pquad[10]],
528
+ cards[pquad[9]], cards[pquad[8]], cards[pquad[7]]))
529
+ print('{} {} {} {} {} {} {}'.format(cards[pquad[20]], cards[pquad[19]], cards[pquad[18]], cards[pquad[17]],
530
+ cards[pquad[16]], cards[pquad[15]], cards[pquad[14]]))
531
+ print('{} {} {} {} {} {} {}'.format(cards[pquad[27]], cards[pquad[26]], cards[pquad[25]], cards[pquad[24]],
532
+ cards[pquad[23]], cards[pquad[22]], cards[pquad[21]]))
533
+ print('{} {} {} {} {} {} {}'.format(cards[pquad[34]], cards[pquad[33]], cards[pquad[32]],
534
+ cards[pquad[31]], cards[pquad[30]], cards[pquad[29]], cards[pquad[28]]))
535
+ print('{} {} {} {} {} {} {}'.format(cards[pquad[41]], cards[pquad[40]], cards[pquad[39]], cards[pquad[38]],
536
+ cards[pquad[37]], cards[pquad[36]], cards[pquad[35]]))
537
+ print('{} {} {} {} {} {} {}'.format(cards[pquad[48]], cards[pquad[47]], cards[pquad[46]], cards[pquad[45]],
538
+ cards[pquad[44]], cards[pquad[43]], cards[pquad[42]]))
539
+
540
+ def print_cot_basic_spread(bspread):
541
+ """print a birth spread"""
542
+ print(' {} '.format(cards[bspread[0]]))
543
+ print('{} {} {} {} {} {} {}'.format(cards[bspread[7]],cards[bspread[6]],
544
+ cards[bspread[5]],cards[bspread[4]],cards[bspread[3]],
545
+ cards[bspread[2]],cards[bspread[1]]))
546
+ print(' {} {} '.format(cards[bspread[9]],cards[bspread[8]]))
547
+ print(' {} '.format(cards[bspread[10]]))
548
+ print(' {} {} {} '.format(cards[bspread[13]],cards[bspread[12]],cards[bspread[11]]))