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,118 @@
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
+ from dataclasses import replace
19
+
20
+ from libaditya import utils
21
+
22
+ from libaditya.objects import JulianDay, EphContext
23
+
24
+ class SWERashi:
25
+ """
26
+ swe functions that seem best placed in the Rashi
27
+ e.g., swe.sol_eclipse_when_loc(), the next solar eclipse for a location
28
+ can easily adjust Rashi to do horary, prashna, or whatever. most of the calculations are there
29
+ the rest is mostly api
30
+ """
31
+
32
+ def next_solar_eclipse_here(self):
33
+ """
34
+ return the next solar eclipse
35
+ return the Chart of that eclipse, or the context?
36
+ """
37
+ return swe.sol_eclipse_when_loc(self.context.timeJD.jd_number(),self.context.location.swe_location())
38
+
39
+ def next_solar_eclipse_here_maximum(self):
40
+ return replace(self.context,timeJD=JulianDay(self.next_solar_eclipse_here()[1][0],self.context.timeJD.utcoffset))
41
+
42
+ def previous_solar_eclipse_here(self):
43
+ """
44
+ return the previous solar eclipse
45
+ return the Chart of that eclipse, or the context?
46
+ """
47
+ return swe.sol_eclipse_when_loc(self.context.timeJD.jd_number(),self.context.location.swe_location(),backwards=True)
48
+
49
+ def previous_solar_eclipse_here_maximum(self):
50
+ return repalce(self.context,timeJD=JulianDay(self.previous_solar_eclipse_here()[1][0],self.context.timeJD.utcoffset))
51
+
52
+ def next_solar_eclipse(self, etype=0) -> EphContext:
53
+ """
54
+ find the next solar eclipse from this.context.timeJD
55
+ type is the swe flags for kinds of eclipses to return
56
+ 0 is any, so this just returns the next eclipse of any variety
57
+ happening anywhere in the world
58
+
59
+ by calculation, it can be in Sun, but it makes more sense overall, since astrologically
60
+ it is often about everything, not just the sun. so return an EphContext
61
+
62
+ return the EphContext of the next solar eclipse
63
+ """
64
+ return swe.sol_eclipse_when_glob(self.context.timeJD.jd_number(),etype)
65
+
66
+ def next_solar_eclipse_maximum(self, etype=0) -> EphContext:
67
+ return replace(self.context,timeJD=JulianDay(self.next_solar_eclipse()[1][0],self.context.timeJD.utcoffset))
68
+
69
+ def previous_solar_eclipse(self, etype=0) -> EphContext:
70
+ """
71
+ find the previous solar eclipse from this.context.timeJD
72
+ type is the swe flags for kinds of eclipses to return
73
+ 0 is any, so this just returns the next eclipse of any variety
74
+ happening anywhere in the world
75
+
76
+ that is why it is here is Sun; obviously it has to do with the Moon to, but the swe function
77
+ does not explicitly require the Moon
78
+
79
+ return the EphContext of the next solar eclipse
80
+ """
81
+ return swe.sol_eclipse_when_glob(self.context.timeJD.jd_number(),etype,backwards=True)
82
+
83
+ def previous_solar_eclipse_maximum(self, etype=0) -> EphContext:
84
+ return replace(self.context,timeJD=JulianDay(self.previous_solar_eclipse()[1][0],self.context.timeJD.utcoffset))
85
+
86
+ def next_lunar_eclipse(self, etype=0) -> EphContext:
87
+ """
88
+ find the next lunar eclipse from this.context.timeJD
89
+ type is the swe flags for kinds of eclipses to return
90
+ 0 is any, so this just returns the next eclipse of any variety
91
+ happening anywhere in the world
92
+
93
+ by calculation, it can be in Sun, but it makes more sense overall, since astrologically
94
+ it is often about everything, not just the sun. so return an EphContext
95
+
96
+ return the EphContext of the next lunar eclipse
97
+ """
98
+ return swe.lun_eclipse_when(self.context.timeJD.jd_number(),etype)
99
+
100
+ def next_lunar_eclipse_maximum(self, etype=0) -> EphContext:
101
+ return replace(self.context,timeJD=JulianDay(self.next_lunar_eclipse()[1][0],self.context.timeJD.utcoffset))
102
+
103
+ def previous_lunar_eclipse(self, etype=0) -> EphContext:
104
+ """
105
+ find the previous lunar eclipse from this.context.timeJD
106
+ type is the swe flags for kinds of eclipses to return
107
+ 0 is any, so this just returns the next eclipse of any variety
108
+ happening anywhere in the world
109
+
110
+ that is why it is here is Sun; obviously it has to do with the Moon to, but the swe function
111
+ does not explicitly require the Moon
112
+
113
+ return the EphContext of the next lunar eclipse
114
+ """
115
+ return swe.lun_eclipse_when(self.context.timeJD.jd_number(),etype,backwards=True)
116
+
117
+ def previous_lunar_eclipse_maximum(self, etype=0) -> EphContext:
118
+ return replace(self.context,timeJD=JulianDay(self.previous_lunar_eclipse()[1][0],self.context.timeJD.utcoffset))
@@ -0,0 +1,287 @@
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
+ from prettytable import PrettyTable
20
+ from dataclasses import replace
21
+
22
+ from rich.table import Table
23
+ from rich.console import Console
24
+
25
+ from libaditya import constants as const
26
+ from libaditya import utils
27
+ from libaditya import print_functions as printf
28
+
29
+ from libaditya.objects import Sign, Signs, Longitude, Planet, Planets, Cusp, Cusps, RashiBala
30
+ from libaditya.objects import planets as planet_constructors
31
+
32
+ from .jaimini import Jaimini
33
+
34
+ from .api import API
35
+
36
+ class Varga(Jaimini,API):
37
+ """
38
+ Varga is the main calculation interface
39
+
40
+ important and special functions can be found or added to the API baseclass (Mixin) to Chart
41
+ i.e., if you want to know the ayanmsa => Chart.ayanamsa()
42
+
43
+ Chart itself does not have an ayanamsa, actually
44
+ it returns Rashi.ayanamsa()
45
+
46
+ this keeps the astrology interface distinct from the humandesign interace (through libaditya.hd)
47
+ for now i have put i have put an HDContext into EphContext
48
+ this actually makes it so that with object, an EphContext, i can calculate and text-display anything i want
49
+ """
50
+
51
+ def __init__(self,context,amsha=1):
52
+ if amsha != 1:
53
+ self.context = replace(context,amsha=amsha,print_nakshatras=False)
54
+ else:
55
+ self.context = replace(context,amsha=amsha)
56
+ self._amsha = self.context.amsha
57
+ self._planets = Planets(self.context)
58
+ # this finds the physical cusps
59
+ self._cusps = Cusps(self.context)
60
+ if self._amsha != 1:
61
+ # if we are in a varga, self.init_Cusps will change them to that varga
62
+ self._cusps = self.init_Cusps(self._cusps)
63
+ self._signs = Signs(self._planets, self._cusps, self.context)
64
+ self._rashi_planets = Planets(replace(self._planets.context,amsha=1))
65
+ self._signs = Signs(self._planets,self._cusps,self.context)
66
+ self.sysflgstr = const.sysflgstr(self.context.sysflg)
67
+ # we need to initalize dignities so that we can do saptavargaja bala on demand
68
+ self._dignities = self._get_dignities()
69
+
70
+ def varga_name(self):
71
+ match self._amsha:
72
+ case 1:
73
+ return "Rashi"
74
+ case 2:
75
+ return "Hora Parivritti"
76
+ case 3:
77
+ return "Drekkana Parivritti"
78
+ case 4:
79
+ return "Chaturthamsha Parivritti"
80
+ case 5:
81
+ return "Panchamsha"
82
+ case 7:
83
+ return "Saptamsha"
84
+ case 9:
85
+ return "Navamsha"
86
+ case 30:
87
+ return "Trimshamsha (Parivritti)"
88
+ case -2:
89
+ return "Hora"
90
+ case -3:
91
+ return "Drekkana"
92
+ case -4:
93
+ return "Chaturthamsha"
94
+ case -10:
95
+ return "Dashamsha"
96
+ case -100:
97
+ return "Dashamsha - Even Signs Reverse"
98
+ case -12:
99
+ return "Dvadashamsha"
100
+ case -16:
101
+ return "Shodashamsha"
102
+ case -20:
103
+ return "Vimshamsha"
104
+ case -24:
105
+ return "Parashara Chaturvimshamsha"
106
+ case -240:
107
+ return "Siddhamsha (d24s)"
108
+ case -27:
109
+ return "Bhamsha"
110
+ case -40:
111
+ return "Khavedamsha"
112
+ case -45:
113
+ return "Akshavedamsha"
114
+ case -60:
115
+ return "Shashtyamsha"
116
+ case _ if self.amsha() > 5:
117
+ return "parivritti"
118
+
119
+ def amsha(self):
120
+ return self._amsha
121
+
122
+ def init_Planets(self, planets):
123
+ retplanets = {}
124
+ for name,planet in planets.items():
125
+ retplanets[name] = planet_constructors[name](self.context,longitude=Longitude(planet.ecliptic_longitude(),amsha=self.amsha()))
126
+ return Planets(self.context,retplanets)
127
+
128
+ def init_Cusps(self, cusps):
129
+ """
130
+ cusps is a list of Cusp classes, which is what is stored in Cusps.self.cusps
131
+ so iterate through, copying everything over, while changing the longitude
132
+ """
133
+ varga_cusps = []
134
+ for cusp in cusps:
135
+ varga_cusps.append(Cusp(longitude=cusp.ecliptic_longitude(),amsha=self.amsha(),speed=cusp.speed(),number=cusp.number(),context=cusp.context))
136
+ return Cusps(self.context,cusps=varga_cusps)
137
+
138
+ def planets(self):
139
+ return self._planets
140
+
141
+ def cusps(self):
142
+ return self._cusps
143
+
144
+ def signs(self):
145
+ return self._signs
146
+
147
+ def where_is(self, object: int | str) -> Sign:
148
+ return self.signs().where_is(object)
149
+
150
+ def lagna(self):
151
+ if self.context.sysflg == const.HELIO or self.context.sysflg == const.BARY:
152
+ return self.signs()[7]
153
+ # this is for using Varga().rich("circular")
154
+ # the lagna will be printed on the left side in the center
155
+ # then the houses and signs go counter clockwise in the order of usual western astrology chart
156
+ # so with the 7th on the left, we will have north at the top and east on the right
157
+ # with heliocentric, the sun in the middle
158
+ # with barycentric, the barycenter in the middle
159
+ # though, with barycentric, it makes it seem like the sun is the same distance as the other planets from the barycenter
160
+ # but obviously it is not. it seems on average the barycenter is not in the sun, but rather close to it
161
+ # so it seems like maybe sometimes the barycenter is inside the sun? so then it is sort of like the sun is "off-center"
162
+ # the solar system, and jupiter in particular, pull the sun "off-center"
163
+ return self.signs().lagna()
164
+
165
+ def deities(self):
166
+ """
167
+ return varga deities for the nine grahas and the lagna in that order
168
+ """
169
+ to_get = self.planets().grahas()
170
+ to_get[1] = self.cusps()[1]
171
+ ret = []
172
+ for obj in to_get.values():
173
+ ret.append(obj.deity())
174
+ return ret
175
+
176
+ def dignities(self):
177
+ return self._dignities
178
+
179
+ def _get_dignities(self) -> [str]:
180
+ """
181
+ return a list of dignities in the natural order
182
+ Sun, Moon, Mars, Mercury, Jupiter, Venus, Saturn
183
+
184
+ dignity is a combination of natural and temporary relationship
185
+ we can use the temporary relationship from the varga itself, or from the rashi chart
186
+
187
+ if Planets is in a varga and temp_planets=None, then it will use temporary relationships based on that varga
188
+ so if, for instance, you want to determine dignity in the Navamsha based on temporary friends in the Rashi
189
+ you must past d9Planets.dignites(temp_planets=d1Planets)
190
+ """
191
+ if self.context.rashi_temporary_friendships:
192
+ return self.planets()._dignities(self._rashi_planets)
193
+ else:
194
+ return self.planets()._dignities(self.planets()) # could pass self.planets(), but that is what Planets.dignities() will do without an argument
195
+
196
+ def __str__(self):
197
+ output = PrettyTable()
198
+ output.field_names = [" ", " ", " ", " "]
199
+
200
+ # we pass _rashi_planets to dignities so that it uses the rashi to calculate temporary relationships
201
+ dignities = printf.dignity_table(self.dignities())
202
+
203
+ jaimini_karakas = printf.jaimini_karakas_str(self.planets().jaimini_karakas())
204
+
205
+ output.add_row([f"{self.signs()[12]}", f"{self.signs()[1]}", f"{self.signs()[2]}", f"{self.signs()[3]}"])
206
+ output.add_divider()
207
+ output.add_row([f"{self.signs()[11]}", f"{dignities} ", f"{jaimini_karakas}", f"{self.signs()[4]}"])
208
+ output.add_divider()
209
+ output.add_row([f"{self.signs()[10]}", " ", " ", f"{self.signs()[5]}"])
210
+ output.add_divider()
211
+ output.add_row([f"{self.signs()[9]}", f"{self.signs()[8]}", f"{self.signs()[7]}", f"{self.signs()[6]}"])
212
+
213
+ ret = output.get_string(fields=[" ", " ", " ", " "])
214
+
215
+ return self.mkheader() + ret
216
+
217
+
218
+ def __repr__(self):
219
+ """
220
+ represents as a header with the chart information
221
+ """
222
+ return self.mkheader()
223
+
224
+ def mkheader(self):
225
+ return utils.mkheader(self)
226
+
227
+
228
+ def richDrawing_south_indian(self):
229
+ spread = Table(box=None)
230
+
231
+ spread.add_column(" ",justify="center")
232
+ spread.add_column(" ",justify="center")
233
+ spread.add_column(" ",justify="center")
234
+ spread.add_column(" ",justify="center")
235
+ spread.add_column(" ",justify="center")
236
+
237
+ spread.add_row(self.signs()[12].richDrawing(),self.signs()[1].richDrawing(),self.signs()[2].richDrawing(),self.signs()[3].richDrawing())
238
+ spread.add_row(self.signs()[11].richDrawing(),"dignities?","jaimini karakas?",self.signs()[4].richDrawing())
239
+ spread.add_row(self.signs()[10].richDrawing(),"empty","empty",self.signs()[5].richDrawing())
240
+ spread.add_row(self.signs()[9].richDrawing(),self.signs()[8].richDrawing(),self.signs()[7].richDrawing(),self.signs()[6].richDrawing())
241
+
242
+ return spread
243
+
244
+ def richDrawing_circular(self):
245
+ spread = Table(box=None)
246
+
247
+ spread.add_column(" ",justify="center",style="#00ff00")
248
+ spread.add_column(" ",justify="center")
249
+ spread.add_column(" ",justify="center")
250
+ spread.add_column(" ",justify="center")
251
+ spread.add_column(" ",justify="center")
252
+
253
+ lagna = self.lagna()
254
+
255
+ # list of sign classes
256
+ # with the empty list at the beginning
257
+ # we can use 1-12 as the index, just as with Varga().signs()
258
+ signs = [[]]
259
+
260
+ # initialize list of Sign classes
261
+ for sign in range(1,13):
262
+ signs.append(self.signs()[lagna.astrological_signs_forward(sign)])
263
+
264
+ # call signs.richDrawing() at the appropriate place
265
+ # lagna is on the leftmost, which is east, facing south, which is the center of the 5x5 table
266
+
267
+ # usually Chart().rashi().signs()[n] means the nth sign
268
+ # here, signs[n] means signs from the lagna
269
+ spread.add_row("",signs[11].richDrawing(),signs[10].richDrawing(),signs[9].richDrawing(),"")
270
+ spread.add_row(signs[12].richDrawing(),"","","",signs[8].richDrawing())
271
+ spread.add_row(signs[1].richDrawing(),"","","",signs[7].richDrawing())
272
+ spread.add_row(signs[2].richDrawing(),"","","",signs[6].richDrawing())
273
+ spread.add_row("",signs[3].richDrawing(),signs[4].richDrawing(),signs[5].richDrawing(),"")
274
+
275
+ return spread
276
+
277
+ def rich(self, which="circular"):
278
+ console = Console()
279
+ match which:
280
+ case "south_indian":
281
+ console.print(self.richDrawing_south_indian())
282
+ case "circular":
283
+ console.print(self.richDrawing_circular())
284
+ case _:
285
+ return
286
+
287
+