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,323 @@
|
|
|
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 utils
|
|
22
|
+
from libaditya.objects import EphContext, Sun, JulianDay
|
|
23
|
+
|
|
24
|
+
from libaditya.cards import cards_constants as cardsc
|
|
25
|
+
from libaditya.cards.deck import Deck
|
|
26
|
+
from .cot import CoT
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class CardsOfTruth(CoT):
|
|
30
|
+
"""
|
|
31
|
+
underneath this class, CoT represents the cards as a list of two-letter strings,
|
|
32
|
+
AH through KS.
|
|
33
|
+
|
|
34
|
+
the index in this list represents its associated card always in the underlying representation
|
|
35
|
+
|
|
36
|
+
we dont really have to know how that works to use this, which is the point of libaditya
|
|
37
|
+
|
|
38
|
+
CardsOfTruth().birth_spread() returns a Spread() instance that represents the birth spread. see that class
|
|
39
|
+
for information on its use
|
|
40
|
+
|
|
41
|
+
its docstring explains about the planet order
|
|
42
|
+
|
|
43
|
+
it will also explain how to go into the Spread and get information you might need
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
# master is a calc.Rashi() object
|
|
47
|
+
def __init__(self, context=EphContext(), master=None):
|
|
48
|
+
self.context = context
|
|
49
|
+
self.master = master
|
|
50
|
+
self._birth_card: str = self._get_birth_card()
|
|
51
|
+
self._birth_spread = self.BirthSpread(self._get_birth_spread(), self)
|
|
52
|
+
|
|
53
|
+
def birth_card(self):
|
|
54
|
+
return self._birth_card
|
|
55
|
+
|
|
56
|
+
def birth_spread(self):
|
|
57
|
+
"""
|
|
58
|
+
self._birth_spread is the list of card integers of that spread
|
|
59
|
+
"""
|
|
60
|
+
return self._birth_spread
|
|
61
|
+
|
|
62
|
+
def _get_birth_card(self):
|
|
63
|
+
"""
|
|
64
|
+
find the birth card
|
|
65
|
+
first, find the time the sunrises at longitude of the persons place of birth, but on the equator
|
|
66
|
+
"""
|
|
67
|
+
sunrise_location = self.context.location.nearest_equatorial_crossing()
|
|
68
|
+
sunrise_time = Sun(EphContext(timeJD=self.context.timeJD.midnightJD(),location=sunrise_location)).rise()
|
|
69
|
+
if self.context.timeJD.jd_number() >= sunrise_time.jd_number():
|
|
70
|
+
# after sunrise on this day
|
|
71
|
+
# so use card associated with this calendar day
|
|
72
|
+
card_day = [self.context.timeJD.usrmonth(),self.context.timeJD.usrday()]
|
|
73
|
+
else:
|
|
74
|
+
# before sunrise on this day
|
|
75
|
+
# so use card associated with previous calendar day
|
|
76
|
+
# so we go back, but need to make everything switches back properly, i.e., the month or year
|
|
77
|
+
month = self.context.timeJD.usrmonth()
|
|
78
|
+
day = self.context.timeJD.usrday()-1
|
|
79
|
+
if day != 0:
|
|
80
|
+
card_day = [month,day]
|
|
81
|
+
else:
|
|
82
|
+
# we need to go back to the last day of the previous month
|
|
83
|
+
# i.e., the last card, but not necessarily in the normal sequence
|
|
84
|
+
# in python, list()[-1] is the last element of the list
|
|
85
|
+
# so if month is jaunary=element0, then month-1=december,element11
|
|
86
|
+
# then we need to know how many days are in that month
|
|
87
|
+
card_day = [month-1,cardsc.days_in_the_month(month-1)]
|
|
88
|
+
# minus 1 since months are 1-12 but python is 0-indexed
|
|
89
|
+
start_card = cardsc.first_card_of_the_month[(card_day[0]-1)]
|
|
90
|
+
# go forward the number of days from that card to find the birth card
|
|
91
|
+
birth_card = cardsc.birth_card_order[start_card+(card_day[1]-1)]
|
|
92
|
+
return birth_card
|
|
93
|
+
|
|
94
|
+
def _get_birth_spread(self):
|
|
95
|
+
birth_card = self.birth_card()
|
|
96
|
+
return self.get_birthspread_from_quadration(birth_card)
|
|
97
|
+
|
|
98
|
+
def deck(self):
|
|
99
|
+
return self._deck
|
|
100
|
+
|
|
101
|
+
def year_spread(self, year=None):
|
|
102
|
+
"""
|
|
103
|
+
get a year spread for age year
|
|
104
|
+
|
|
105
|
+
add way of doing default argument where it uses current age
|
|
106
|
+
|
|
107
|
+
if None, use current age, or try
|
|
108
|
+
not sure how well it actually works
|
|
109
|
+
"""
|
|
110
|
+
if year == None:
|
|
111
|
+
# find the persons current age
|
|
112
|
+
year = int(self.context.timeJD.current_age())
|
|
113
|
+
year_spread_list = self.get_birthspread_from_quadration(self.birth_card(),self.quadraten(cardsc.jackquad,year+1))
|
|
114
|
+
# change planets to self.master.solar_return(year)...i.e., write solar_return
|
|
115
|
+
return self.YearSpread(year_spread_list, self, which=year)
|
|
116
|
+
|
|
117
|
+
def day_quadration(self, day=None):
|
|
118
|
+
"""
|
|
119
|
+
get a day quadration spread for day "day"
|
|
120
|
+
if day=None, will get for the current day
|
|
121
|
+
|
|
122
|
+
if day is an integer, it will get the spread the "day"th day after birth
|
|
123
|
+
0 is the first day one is born, 1 is the next day, 2 the day after that, etc.
|
|
124
|
+
"""
|
|
125
|
+
if day == None:
|
|
126
|
+
# find current age in days
|
|
127
|
+
day = int(self.context.timeJD.current_age_days())
|
|
128
|
+
day_spread_list = self.get_birthspread_from_quadration(self.birth_card(),self.quadraten(CoT.queen_quadration(),day))
|
|
129
|
+
return self.DayQuadration(day_spread_list, self, which=day)
|
|
130
|
+
|
|
131
|
+
class Spread:
|
|
132
|
+
"""
|
|
133
|
+
initialize a Spread object
|
|
134
|
+
the most important argument is spread_list, which is the list of numbers presenting the cards of the spread
|
|
135
|
+
|
|
136
|
+
this object will be responsible for intializing the planets
|
|
137
|
+
im not entirely sure what the calculations for the different spreads are called
|
|
138
|
+
i think they are some sort of progression
|
|
139
|
+
probably, those calculations will end up going somewhere else depending on what exactly they are
|
|
140
|
+
|
|
141
|
+
spread_list needs to have 14 numbers in it between 0 and 51.
|
|
142
|
+
|
|
143
|
+
these integers represent the cards. the integer representing a certain card is the index of that card
|
|
144
|
+
in the list cards_constants.cards
|
|
145
|
+
|
|
146
|
+
but Spread does not check to make sure that the spread is a valid one
|
|
147
|
+
it simply puts the cards in the spread in order: base, sun, moon, etc.
|
|
148
|
+
the precise order is given by CardsOfTruth.context.cot_planet_order
|
|
149
|
+
the default is "vedic"; the other option is "solar_system"
|
|
150
|
+
|
|
151
|
+
it finds the proper planets given the spread type
|
|
152
|
+
i.e., for a birth spread, the birth planets, for a year spread, the planets at that solar return, etc.
|
|
153
|
+
and puts them into the "Sun" card, the "Moon" card, etc.
|
|
154
|
+
|
|
155
|
+
To test this out by itself, you can do this:
|
|
156
|
+
>>> CardsOfTruth().Spread(spread_list=[0,4,3,45,...])
|
|
157
|
+
where "spread_list" is a list of 14 integers between 0 and 51
|
|
158
|
+
you can also test out the planet order:
|
|
159
|
+
>>> CardsOfTruth().Spread(spread_list=[0,4,3,45,...],order="solar_system")
|
|
160
|
+
|
|
161
|
+
TODO: currently, Planet-s being put into cards is not implemented
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
def __init__(self, spread_list, master, which=0):
|
|
165
|
+
self._list = spread_list
|
|
166
|
+
self.master = master
|
|
167
|
+
self.context = self.master.context
|
|
168
|
+
# for all spreads besides natal, there is an option of which one you want
|
|
169
|
+
# e.g., for the year spread, "which" is which year
|
|
170
|
+
self.which = which
|
|
171
|
+
self._deck = Deck()
|
|
172
|
+
self._order = self.master.context.cot_planet_order
|
|
173
|
+
self._spread = self._init_Spread()
|
|
174
|
+
|
|
175
|
+
def __iter__(self):
|
|
176
|
+
return iter(self._spread)
|
|
177
|
+
|
|
178
|
+
def __getitem__(self, key):
|
|
179
|
+
if isinstance(key,str):
|
|
180
|
+
return self._spread[key]
|
|
181
|
+
else:
|
|
182
|
+
# get the planet key as a string from the correct planet order
|
|
183
|
+
# key here is an int, corresponding to the desired card
|
|
184
|
+
# 0 for the base card, 1 for sun, 2 for moon, etc.
|
|
185
|
+
return self._spread[cardsc.planet_order[self._order][key]]
|
|
186
|
+
|
|
187
|
+
def deck(self):
|
|
188
|
+
return self._deck
|
|
189
|
+
|
|
190
|
+
def spread(self):
|
|
191
|
+
return self._spread
|
|
192
|
+
|
|
193
|
+
def _init_Spread(self):
|
|
194
|
+
"""
|
|
195
|
+
initialize the Spread, self._spread
|
|
196
|
+
a dictionary, "Planet": Card
|
|
197
|
+
also through __getitem__, Spread()[int] where int is the planet number appropriate to the system
|
|
198
|
+
"""
|
|
199
|
+
spread = {}
|
|
200
|
+
for spread_position,planet_key in enumerate(cardsc.planet_order[self._order]):
|
|
201
|
+
# self._list = spread_list is a list of 14 cards in the proper positions starting from 0, the base card
|
|
202
|
+
# base card is list[0], sun is list[1], moon is list[2]
|
|
203
|
+
# for vedic mars is list[3], for solar_system mercury is list[3], etc.
|
|
204
|
+
# self._list[spread_position] as the int representation of the card at that position
|
|
205
|
+
# put this int into cardsc.cards to get the string version, e.g., "KD"
|
|
206
|
+
spread[planet_key] = self.deck()[cardsc.cards[self._list[spread_position]]]
|
|
207
|
+
# tell the Card which planet it is
|
|
208
|
+
# it uses this, for instance, to print the glyph of the planet in the header
|
|
209
|
+
spread[planet_key]._planet = planet_key
|
|
210
|
+
# with this above, we should be able to iterate over Spread regardless of the system
|
|
211
|
+
return spread
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _place_Objects(self):
|
|
215
|
+
"""
|
|
216
|
+
it initializes those Planet-s into Spread
|
|
217
|
+
it adds these Planet-s to their proper Card in the Spread
|
|
218
|
+
so then we will have Spread().planets() and Spread()["Sun"] to see which Planet-s are in the Sun card
|
|
219
|
+
"""
|
|
220
|
+
# here is where we will need to know the type of spread
|
|
221
|
+
# for instance, the year spread is based on the solar return
|
|
222
|
+
# so we will need to get the plaents for the proper solar return
|
|
223
|
+
for planet in self._planets:
|
|
224
|
+
# put this planet in the card of its lord
|
|
225
|
+
self.spread()[planet.lord()].set_attribute(("planets",planet))
|
|
226
|
+
for cusp in self._cusps:
|
|
227
|
+
# put this cusp in the card of its lord
|
|
228
|
+
self.spread()[cusp.lord()].set_attribute(("cusps",cusp))
|
|
229
|
+
|
|
230
|
+
def richDrawing(self):
|
|
231
|
+
spread = Table(box=box.SIMPLE)
|
|
232
|
+
|
|
233
|
+
spread.add_column(" ",justify="center",style="white")
|
|
234
|
+
spread.add_column(" ",justify="center",style="white")
|
|
235
|
+
spread.add_column(" ",justify="center",style="white")
|
|
236
|
+
spread.add_column(" ",justify="center",style="white")
|
|
237
|
+
spread.add_column(" ",justify="center",style="white")
|
|
238
|
+
spread.add_column(" ",justify="center",style="white")
|
|
239
|
+
spread.add_column(" ",justify="center",style="white")
|
|
240
|
+
|
|
241
|
+
spread.add_row(" "," "," ",self[0].richDrawing()," "," "," ")
|
|
242
|
+
spread.add_row(self[7].richDrawing(),self[6].richDrawing(),self[5].richDrawing(),self[4].richDrawing(),self[3].richDrawing(),self[2].richDrawing(),self[1].richDrawing())
|
|
243
|
+
spread.add_row(" "," ",self[9].richDrawing()," ",self[8].richDrawing()," "," ")
|
|
244
|
+
spread.add_row(" "," "," ",self[10].richDrawing()," "," "," ")
|
|
245
|
+
spread.add_row(" "," ",self[13].richDrawing(),self[12].richDrawing(),self[11].richDrawing()," "," ")
|
|
246
|
+
|
|
247
|
+
return spread
|
|
248
|
+
|
|
249
|
+
def rich(self):
|
|
250
|
+
from rich.console import Console
|
|
251
|
+
Console().print(self.richDrawing())
|
|
252
|
+
|
|
253
|
+
# the following are classes for specific kinds of spread
|
|
254
|
+
# the only difference is really how self._get_Planets() and self._get_Cusps() work
|
|
255
|
+
# this is where they get the appropriate planets and cusps and put them into the spread
|
|
256
|
+
|
|
257
|
+
class BirthSpread(Spread):
|
|
258
|
+
|
|
259
|
+
def __init__(self, spread_list, master, which=0):
|
|
260
|
+
super().__init__(spread_list, master)
|
|
261
|
+
self._planets = self._get_Planets()
|
|
262
|
+
self._cusps = self._get_Cusps()
|
|
263
|
+
self._place_Objects()
|
|
264
|
+
|
|
265
|
+
def _get_Planets(self):
|
|
266
|
+
"""
|
|
267
|
+
get the correct Planets for this spread
|
|
268
|
+
right now, natal or solar return
|
|
269
|
+
"""
|
|
270
|
+
return self.master.master.planets()
|
|
271
|
+
|
|
272
|
+
def _get_Cusps(self):
|
|
273
|
+
"""
|
|
274
|
+
get the correct Cusps for this spread
|
|
275
|
+
right now, natal or solar return
|
|
276
|
+
"""
|
|
277
|
+
return self.master.master.cusps()
|
|
278
|
+
|
|
279
|
+
class YearSpread(Spread):
|
|
280
|
+
|
|
281
|
+
def __init__(self, spread_list, master, which):
|
|
282
|
+
super().__init__(spread_list, master, which)
|
|
283
|
+
self._planets = self._get_Planets()
|
|
284
|
+
self._cusps = self._get_Cusps()
|
|
285
|
+
self._place_Objects()
|
|
286
|
+
|
|
287
|
+
def _get_Planets(self):
|
|
288
|
+
"""
|
|
289
|
+
get the correct Planets for this spread
|
|
290
|
+
right now, natal or solar return
|
|
291
|
+
"""
|
|
292
|
+
return self.master.master.solar_return(self.which).rashi().planets()
|
|
293
|
+
|
|
294
|
+
def _get_Cusps(self):
|
|
295
|
+
"""
|
|
296
|
+
get the correct Cusps for this spread
|
|
297
|
+
right now, natal or solar return
|
|
298
|
+
"""
|
|
299
|
+
return self.master.master.solar_return(self.which).rashi().cusps()
|
|
300
|
+
|
|
301
|
+
class DayQuadration(Spread):
|
|
302
|
+
|
|
303
|
+
def __init__(self, spread_list, master, which=0):
|
|
304
|
+
super().__init__(spread_list, master)
|
|
305
|
+
self._planets = self._get_Planets()
|
|
306
|
+
self._cusps = self._get_Cusps()
|
|
307
|
+
self._place_Objects()
|
|
308
|
+
|
|
309
|
+
def _get_Planets(self):
|
|
310
|
+
"""
|
|
311
|
+
get the correct Planets for this spread
|
|
312
|
+
right now, natal or solar return
|
|
313
|
+
"""
|
|
314
|
+
chart = self.master.master.master.timejd(self.context.timeJD.jd_number()+self.which)
|
|
315
|
+
return chart.rashi().planets()
|
|
316
|
+
|
|
317
|
+
def _get_Cusps(self):
|
|
318
|
+
"""
|
|
319
|
+
get the correct Cusps for this spread
|
|
320
|
+
right now, natal or solar return
|
|
321
|
+
"""
|
|
322
|
+
chart = self.master.master.master.timejd(self.context.timeJD.jd_number()+self.which)
|
|
323
|
+
return chart.rashi().cusps()
|
libaditya/cards/cot.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
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 libaditya.cards import cards_constants as cardsc
|
|
18
|
+
|
|
19
|
+
def getindex(card):
|
|
20
|
+
"""Get the index number of the birth card from the Jack Quadration"""
|
|
21
|
+
return cardsc.cards.index(card)
|
|
22
|
+
|
|
23
|
+
class CoT:
|
|
24
|
+
"""
|
|
25
|
+
CoT is a class of static methods that provide most of the basic cot calculation functionality
|
|
26
|
+
|
|
27
|
+
this is a Mixin, having no __init__() method
|
|
28
|
+
|
|
29
|
+
you can use these methods through CardsOfTruth, the class this inherits unto, e.g.,:
|
|
30
|
+
>>> CardsOfTruth().queen_quadration()
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def jack_quadration():
|
|
35
|
+
return cardsc.jackquad
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def queen_quadration():
|
|
39
|
+
return CoT.quadrate(cardsc.jackquad)
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
def king_quadration():
|
|
43
|
+
return CoT.quadrate(CoT.queen_quadration())
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def quadrate(tquad):
|
|
47
|
+
"""
|
|
48
|
+
tquad is the deck that you want to quadrate
|
|
49
|
+
"""
|
|
50
|
+
# say we are starting with the jack quadration
|
|
51
|
+
# we pick up the AH, put 2H on top of that, 3H on top, etc. until KS is on the top
|
|
52
|
+
# then we turn the deck over and start from the top, which is now AH
|
|
53
|
+
# this is why I have made AH=1(0) and KS=52(51)
|
|
54
|
+
quad=tquad.copy() # so that i dont have to pass a copy of the quadration to this function
|
|
55
|
+
# first we need to take the top four cards together and put them in one pile
|
|
56
|
+
pile1 = []
|
|
57
|
+
pile2 = []
|
|
58
|
+
pile3 = []
|
|
59
|
+
pile4 = []
|
|
60
|
+
# the new pile needs to go on, i.e., the last element of the new next to the first element of the bottom one
|
|
61
|
+
while len(quad) > 4:
|
|
62
|
+
pile1 = cardsc.topthree(quad)+pile1
|
|
63
|
+
pile2 = cardsc.topthree(quad)+pile2
|
|
64
|
+
pile3 = cardsc.topthree(quad)+pile3
|
|
65
|
+
pile4 = cardsc.topthree(quad)+pile4
|
|
66
|
+
|
|
67
|
+
pile1=[quad.pop(0)]+pile1
|
|
68
|
+
pile2=[quad.pop(0)]+pile2
|
|
69
|
+
pile3=[quad.pop(0)]+pile3
|
|
70
|
+
pile4=[quad.pop(0)]+pile4
|
|
71
|
+
|
|
72
|
+
# now we have four piles. now we need to put the second on top of the first
|
|
73
|
+
# we can use quad since we popped all of its item off
|
|
74
|
+
quad = (pile4+(pile3+(pile2+pile1)))
|
|
75
|
+
|
|
76
|
+
# now we put the first card into the first pile, the second into the second, etc.
|
|
77
|
+
# until there are no more cards
|
|
78
|
+
|
|
79
|
+
# make sure our piles are empty
|
|
80
|
+
pile1 = []
|
|
81
|
+
pile2 = []
|
|
82
|
+
pile3 = []
|
|
83
|
+
pile4 = []
|
|
84
|
+
|
|
85
|
+
while len(quad):
|
|
86
|
+
pile1=[quad.pop(0)]+pile1
|
|
87
|
+
pile2=[quad.pop(0)]+pile2
|
|
88
|
+
pile3=[quad.pop(0)]+pile3
|
|
89
|
+
pile4=[quad.pop(0)]+pile4
|
|
90
|
+
|
|
91
|
+
quad = (pile4+(pile3+(pile2+pile1)))
|
|
92
|
+
|
|
93
|
+
# this should be the next quadration. we dont have to deal with turning the deck over here
|
|
94
|
+
# as long as everything was done correctly
|
|
95
|
+
|
|
96
|
+
return quad
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def quadraten(nquad,n):
|
|
100
|
+
while n:
|
|
101
|
+
nquad=CoT.quadrate(nquad.copy())
|
|
102
|
+
n=n-1
|
|
103
|
+
return nquad
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def getbspreadwxcfromquad(card,pos,quad):
|
|
108
|
+
"""get the birth spread from quad where card is in pos"""
|
|
109
|
+
"""0 is the birth card position, 1 is the sun card, 9 is rahu card, 13 is pluto card, etc."""
|
|
110
|
+
cindex=quad.index(getindex(card)) # this is where the card is in the quadration
|
|
111
|
+
# we want to get the birth spread for which card is in pos
|
|
112
|
+
# so if pos is 0, we can simply call getbirthspreadfromquad(card,quad)
|
|
113
|
+
# if pos is not 0, we want to find the card that would be in the 0 pos in quad
|
|
114
|
+
# say pos is 4, then 4-4=0 is the birth card
|
|
115
|
+
# cindex is the index of the desired card in the quad
|
|
116
|
+
# so cindex-pos is the index of the birth card
|
|
117
|
+
# if cindex-pos>=0 this is fine, we can call getbirthspreadfromquad(cindex-pos,quad)
|
|
118
|
+
# otherwise, if cindex-pos=-1, then the index is actually 51, i.e, 52-1
|
|
119
|
+
if cindex-pos>=0:
|
|
120
|
+
return CoT.get_birthspread_from_quadration(cardsc.cards[quad[cindex-pos]],quad)
|
|
121
|
+
else:
|
|
122
|
+
return CoT.get_birthspread_from_quadration(cardsc.cards[quad[52-(cindex-pos)]],quad)
|
|
123
|
+
|
|
124
|
+
@staticmethod
|
|
125
|
+
def get_birth_spread_with_card_in_position(card,pos):
|
|
126
|
+
"""
|
|
127
|
+
get a birth spread where card is in pos#
|
|
128
|
+
0 is the birth card, 2 is the moon card, 7 is the saturn card, etc.
|
|
129
|
+
"""
|
|
130
|
+
return CoT.getbspreadwxcfromquad(card,pos,CoT.queen_quadration())
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def get_birthspread_from_quadration(birthcard,quad=None):
|
|
134
|
+
"""birthcard is two characters that indicate the birth card, eg., 'AS', ace of spades"""
|
|
135
|
+
"""so we need to get that card and the next 13 cards from the Queen Quadration"""
|
|
136
|
+
if quad is None:
|
|
137
|
+
quad = CoT.queen_quadration()
|
|
138
|
+
bc=quad.index(getindex(birthcard))
|
|
139
|
+
bspread=[]
|
|
140
|
+
for x in range(bc,bc+14):
|
|
141
|
+
bspread.append(quad[x%52])
|
|
142
|
+
return bspread
|
libaditya/cards/deck.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
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 libaditya.cards import cards_constants as cardsc
|
|
18
|
+
from libaditya.cards.card import Card
|
|
19
|
+
|
|
20
|
+
class Deck:
|
|
21
|
+
"""
|
|
22
|
+
could this also be a tarot deck, or would that be different?
|
|
23
|
+
but tarot doesnt use planets, so it doesnt really have any astrology in it
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, deck_type="52 playing cards"):
|
|
27
|
+
self._deck_type = deck_type
|
|
28
|
+
self._deck = self._init_Deck()
|
|
29
|
+
|
|
30
|
+
def __iter__(self):
|
|
31
|
+
return iter(self._deck)
|
|
32
|
+
|
|
33
|
+
def __getitem__(self, card: str):
|
|
34
|
+
return self._deck[card]
|
|
35
|
+
|
|
36
|
+
def deck(self):
|
|
37
|
+
return self._deck
|
|
38
|
+
|
|
39
|
+
def index(self, card):
|
|
40
|
+
return self._deck.index(card)
|
|
41
|
+
|
|
42
|
+
def _init_Deck(self):
|
|
43
|
+
"""
|
|
44
|
+
a dictionary of 52 k-v pairs: "Card": Card
|
|
45
|
+
i.e., key-constructor
|
|
46
|
+
"""
|
|
47
|
+
deck = {}
|
|
48
|
+
|
|
49
|
+
for index,card in enumerate(cardsc.cards):
|
|
50
|
+
deck[card] = Card(card,index)
|
|
51
|
+
|
|
52
|
+
return deck
|
libaditya/charts/api.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
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 dataclasses import replace
|
|
19
|
+
from typing import Self
|
|
20
|
+
|
|
21
|
+
class API:
|
|
22
|
+
"""
|
|
23
|
+
Mixin class for Chart api
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def ayanamsa(self):
|
|
27
|
+
return self.context.ayanamsa
|
|
28
|
+
|
|
29
|
+
def ascendant(self):
|
|
30
|
+
return self.rashi().lagna()
|
|
31
|
+
|
|
32
|
+
def nakshatra(self):
|
|
33
|
+
"""
|
|
34
|
+
this returns a Nakshatra object
|
|
35
|
+
"""
|
|
36
|
+
return self.rashi().planets().moon().nakshatra()
|
|
@@ -0,0 +1,80 @@
|
|
|
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 dataclasses import replace
|
|
19
|
+
from typing import Self
|
|
20
|
+
|
|
21
|
+
from libaditya.objects import Planets
|
|
22
|
+
import libaditya.constants as const
|
|
23
|
+
from libaditya.hd import calc as hdcalc
|
|
24
|
+
from libaditya.hd import constants as hdc
|
|
25
|
+
|
|
26
|
+
from libaditya.draw.draw_bodygraph import DrawBodyGraph
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Bodygraph(DrawBodyGraph):
|
|
30
|
+
"""
|
|
31
|
+
by calculation, a bodygraph is simply a set of planets
|
|
32
|
+
the conscious planets are the birth planets, in this order:
|
|
33
|
+
Sun, Earth, Moon, Rahu, Ketu, Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Chiron (doesn't activate gate)
|
|
34
|
+
the unconscious planets are the planets at the time when the Sun was 88 degrees before the birth placement
|
|
35
|
+
the dream planets are the planets at the time the Moon was 88 degrees before the birth placement
|
|
36
|
+
|
|
37
|
+
this can draw a bodygraph
|
|
38
|
+
|
|
39
|
+
use Bodygraph().draw_svg(outfile="(optional; default is {Bodygraph().context.name}.svg)")
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, context):
|
|
43
|
+
self.context = context
|
|
44
|
+
self._conscious_planets = Planets(self.context)
|
|
45
|
+
self._unconscious_context = hdcalc.unconscious_context(self.context)
|
|
46
|
+
self._unconscious_planets = Planets(self._unconscious_context)
|
|
47
|
+
self._dream_context = hdcalc.dream_context(self.context)
|
|
48
|
+
self._dream_planets = Planets(self._dream_context)
|
|
49
|
+
|
|
50
|
+
def conscious_planets(self):
|
|
51
|
+
return self._conscious_planets
|
|
52
|
+
|
|
53
|
+
def unconscious_planets(self):
|
|
54
|
+
return self._unconscious_planets
|
|
55
|
+
|
|
56
|
+
def planets(self):
|
|
57
|
+
return self.conscious_planets().hd_planets() + self.unconscious_planets().hd_planets()
|
|
58
|
+
|
|
59
|
+
def conscious_gates(self,chiron=True):
|
|
60
|
+
return self.conscious_planets().gates(chiron)
|
|
61
|
+
|
|
62
|
+
def unconscious_gates(self,chiron=True):
|
|
63
|
+
return self.unconscious_planets().gates()
|
|
64
|
+
|
|
65
|
+
def all_gates(self,chiron=False):
|
|
66
|
+
"""
|
|
67
|
+
get all_gates that should be activated in the bodygraph
|
|
68
|
+
"""
|
|
69
|
+
return self.conscious_gates(chiron) + self.unconscious_gates(chiron)
|
|
70
|
+
|
|
71
|
+
def dream_planets(self):
|
|
72
|
+
"""
|
|
73
|
+
these are the unconscious dream planets, since the conscious ones for the dreamgraph
|
|
74
|
+
are the same as the conscious ones for the bodygraph
|
|
75
|
+
"""
|
|
76
|
+
return self._dream_planets
|
|
77
|
+
|
|
78
|
+
def _new_bodygraph(self, **kwargs):
|
|
79
|
+
return Bodygraph(context=replace(self.context,**kwargs))
|
|
80
|
+
|