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
libaditya/utils.py
ADDED
|
@@ -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
|
+
import time as tmod
|
|
20
|
+
import os
|
|
21
|
+
|
|
22
|
+
from libaditya import constants as const
|
|
23
|
+
|
|
24
|
+
def dms2dec(dms):
|
|
25
|
+
"""
|
|
26
|
+
dms is a tuple (hour,minutes,seconds) that wants to be turned into a float
|
|
27
|
+
"""
|
|
28
|
+
return dms[0] + (dms[1] / 60) + (dms[2] / 3600)
|
|
29
|
+
|
|
30
|
+
def sign_degree_to_longitude(sd: float, context):
|
|
31
|
+
"""
|
|
32
|
+
sd is a float of the 10.28, i.e., 10th sign, 28th degree
|
|
33
|
+
now change to an ecliptic longitude based on which Circle we are using
|
|
34
|
+
"""
|
|
35
|
+
from libaditya.objects import Circle
|
|
36
|
+
sign=int(sd[0])
|
|
37
|
+
degrees=float(sd[1])
|
|
38
|
+
if context.circle == Circle.ZODIAC:
|
|
39
|
+
return ((sign-1)*30) + degrees
|
|
40
|
+
else:
|
|
41
|
+
return (((sign-2)%12)*30) + degrees
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def signize(long, toround, names):
|
|
45
|
+
"""
|
|
46
|
+
return a string with 360degree longitude long given with
|
|
47
|
+
long (sign), with long being in the sign
|
|
48
|
+
signs contains the signs to be used, which might be adityas
|
|
49
|
+
"""
|
|
50
|
+
index = int(
|
|
51
|
+
(long % 360) / 30
|
|
52
|
+
) # mod 360 in case long=360...but it probably wouldnt with swe, right?
|
|
53
|
+
if toround[0]:
|
|
54
|
+
inlong = round(long % 30, toround[1])
|
|
55
|
+
else:
|
|
56
|
+
inlong = long % 30
|
|
57
|
+
return f"{dec2dmsstr(inlong)} {names[index]}"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def intize_date(date):
|
|
61
|
+
"""
|
|
62
|
+
take a string 'MM/DD/YYYY'
|
|
63
|
+
and return a tuple of int (mm,dd,yyyy)
|
|
64
|
+
"""
|
|
65
|
+
date = date.split("/")
|
|
66
|
+
year = int(date[2])
|
|
67
|
+
month = int(date[0])
|
|
68
|
+
day = int(date[1])
|
|
69
|
+
|
|
70
|
+
return (month, day, year)
|
|
71
|
+
|
|
72
|
+
def even(n):
|
|
73
|
+
return n%2 == 0
|
|
74
|
+
|
|
75
|
+
def odd(n):
|
|
76
|
+
return n%2 == 1
|
|
77
|
+
|
|
78
|
+
def intize_time(time):
|
|
79
|
+
"""
|
|
80
|
+
take a string 'HH:MM:SS'
|
|
81
|
+
and return a float of that time
|
|
82
|
+
"""
|
|
83
|
+
time = time.split(":")
|
|
84
|
+
# if len == 2, HH:MM, otherwise, HH:MM:SS
|
|
85
|
+
if len(time) == 2:
|
|
86
|
+
return int(time[0]) + int(time[1]) / 60
|
|
87
|
+
else:
|
|
88
|
+
return int(time[0]) + int(time[1]) / 60 + int(time[2]) / 3600
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def tmod_to_jd(now):
|
|
92
|
+
"""
|
|
93
|
+
time a struct from the time module
|
|
94
|
+
and convert it to julian day float
|
|
95
|
+
"""
|
|
96
|
+
return swe.julday(
|
|
97
|
+
now.tm_year,
|
|
98
|
+
now.tm_mon,
|
|
99
|
+
now.tm_mday,
|
|
100
|
+
now.tm_hour + now.tm_min / 60 + now.tm_sec / 3600,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def date2str(date):
|
|
105
|
+
"""date is a revjul-tuple (year,month,day,hour); return a string 'month/day/year'"""
|
|
106
|
+
return f"{date[1]:02d}/{date[2]:02d}/{date[0]:02d}"
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def time2str(time):
|
|
110
|
+
"""time is a dec2dms tupel (deg,min,sec); returns a string 'HH:MM:SS'"""
|
|
111
|
+
return f"{str(int(time[0])).zfill(2)}:{str(int(time[1])).zfill(2)}:{str(int(time[2])).zfill(2)}"
|
|
112
|
+
|
|
113
|
+
def mktimezone(offset,timezone="UTC"):
|
|
114
|
+
sign = ""
|
|
115
|
+
appendix = ""
|
|
116
|
+
if offset > 0:
|
|
117
|
+
sign = "+"
|
|
118
|
+
if offset == 0 or timezone != "UTC":
|
|
119
|
+
appendix = ""
|
|
120
|
+
else:
|
|
121
|
+
appendix = sign + f"{round(offset, 2)}"
|
|
122
|
+
return timezone + appendix
|
|
123
|
+
|
|
124
|
+
def mktab(n):
|
|
125
|
+
tab = ""
|
|
126
|
+
for i in range(0, n):
|
|
127
|
+
tab += "\t"
|
|
128
|
+
return tab
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def dec2dms(dd):
|
|
132
|
+
"""dd is a float that wants to be turned into degs,mins,secs; returns (deg,min,sec)"""
|
|
133
|
+
dd = abs(dd)
|
|
134
|
+
minutes, seconds = divmod(dd * 3600, 60)
|
|
135
|
+
degrees, minutes = divmod(minutes, 60)
|
|
136
|
+
return (degrees, minutes, seconds)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def dec2dmsstr(dd):
|
|
140
|
+
"""dd is a float that wants to be turned into degs,mins,secs; returns (deg,min,sec)"""
|
|
141
|
+
dd = abs(dd)
|
|
142
|
+
minutes, seconds = divmod(dd * 3600, 60)
|
|
143
|
+
degrees, minutes = divmod(minutes, 60)
|
|
144
|
+
return f"{int(degrees):02d}:{int(minutes):02d}:{int(seconds):02d}"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def dec2ymd(age: float) -> str:
|
|
149
|
+
"""
|
|
150
|
+
take a floating point age (=number of years) and return a string
|
|
151
|
+
"x years, y months, z days, a hours, b minutes, c seconds"
|
|
152
|
+
the days isnt precise, since i didnt just now feel like
|
|
153
|
+
programming the details of that
|
|
154
|
+
if any of these are zero, it does not print that
|
|
155
|
+
"""
|
|
156
|
+
# import pdb; pdb.set_trace()
|
|
157
|
+
sign = ""
|
|
158
|
+
if age < 0:
|
|
159
|
+
sign = "-"
|
|
160
|
+
age=-age
|
|
161
|
+
strlist=[]
|
|
162
|
+
# how many years is the integer part
|
|
163
|
+
years = int(age)
|
|
164
|
+
if not years == 0:
|
|
165
|
+
strlist.append(f"{years} years")
|
|
166
|
+
# get the decimal part of the float
|
|
167
|
+
rem = age % 1
|
|
168
|
+
# multiple by 12 to find numbers of months as a float
|
|
169
|
+
md = rem*12
|
|
170
|
+
# months is the decimal part
|
|
171
|
+
months = int(md)
|
|
172
|
+
if not months == 0:
|
|
173
|
+
strlist.append(f"{months} months")
|
|
174
|
+
rem = md % 1
|
|
175
|
+
# days are approximatebecause to be precise we need to find
|
|
176
|
+
# the precise monthetc. and i dont feel like it
|
|
177
|
+
dpart = rem*31
|
|
178
|
+
days = int(rem*31)
|
|
179
|
+
if not days == 0:
|
|
180
|
+
strlist.append(f"{days} days")
|
|
181
|
+
if years == 0 and months == 0:
|
|
182
|
+
# only compute hours and seconds if years and months are 0
|
|
183
|
+
rem = dpart%1
|
|
184
|
+
dpart = rem*24
|
|
185
|
+
hours = int(dpart)
|
|
186
|
+
if not hours == 0:
|
|
187
|
+
strlist.append(f"{hours} hours")
|
|
188
|
+
mpart = rem*60
|
|
189
|
+
minutes = int(mpart)
|
|
190
|
+
if not minutes == 0:
|
|
191
|
+
strlist.append(f"{minutes} minutes")
|
|
192
|
+
rem = mpart%1
|
|
193
|
+
seconds = int(rem*60)
|
|
194
|
+
if not seconds == 0:
|
|
195
|
+
strlist.append(f"{seconds} seconds")
|
|
196
|
+
if not strlist:
|
|
197
|
+
return "Less than one second"
|
|
198
|
+
strlist[0] = sign+strlist[0]
|
|
199
|
+
return ", ".join(strlist)
|
|
200
|
+
|
|
201
|
+
def mktab(n):
|
|
202
|
+
tab = ""
|
|
203
|
+
for i in range(0,n):
|
|
204
|
+
tab += "\t"
|
|
205
|
+
return tab
|
|
206
|
+
|
|
207
|
+
def mksub(n):
|
|
208
|
+
sub = ""
|
|
209
|
+
for i in range(0,n):
|
|
210
|
+
sub += "sub"
|
|
211
|
+
return sub
|
|
212
|
+
|
|
213
|
+
def construct_varga_row(cusp):
|
|
214
|
+
"""
|
|
215
|
+
construct a row where every column
|
|
216
|
+
is "" except the one the corresponds to the sign
|
|
217
|
+
the planet/cusp is in, then print its in_sign_longitude there
|
|
218
|
+
e.g., if Sun is in Cancer, print nothing in the
|
|
219
|
+
first, second column, third column, print longitude in fourth column, nothing in fifth,etc.
|
|
220
|
+
"""
|
|
221
|
+
ret = []
|
|
222
|
+
|
|
223
|
+
for n in range(0,12):
|
|
224
|
+
if n == cusp.sign_index():
|
|
225
|
+
ret.append(cusp.in_sign_longitude())
|
|
226
|
+
else:
|
|
227
|
+
ret.append("")
|
|
228
|
+
return ret
|
|
229
|
+
|
|
230
|
+
# make a string for dasha lords including subdashas
|
|
231
|
+
def mk_dasha_lord(dlist):
|
|
232
|
+
"""
|
|
233
|
+
make a string of dashas lords
|
|
234
|
+
"""
|
|
235
|
+
lordstr = ""
|
|
236
|
+
for lord in range(0,len(dlist)):
|
|
237
|
+
if lord == len(dlist)-1:
|
|
238
|
+
lordstr += const.vimshottari_dashas[dlist[lord]][0]
|
|
239
|
+
else:
|
|
240
|
+
lordstr += const.vimshottari_dashas[dlist[lord]][0] + "/"
|
|
241
|
+
return lordstr
|
|
242
|
+
|
|
243
|
+
DIGNITY_RANK = {"EX": 9, "MT": 8, "OH": 7, "GF": 6, "F": 5, "N": 4, "E": 3, "GE": 2, "DB": 1}
|
|
244
|
+
|
|
245
|
+
def compare_signs_dignities(sign1,sign2,dignities: [str]) -> int:
|
|
246
|
+
"""
|
|
247
|
+
compare which sign has stronger dignities among its occupying planets
|
|
248
|
+
dignities is the list of planetary dignities returned by Planets.dignities()
|
|
249
|
+
|
|
250
|
+
if different planet counts, more planets wins
|
|
251
|
+
if same count, sort each sign's planets by dignity descending,
|
|
252
|
+
compare element by element; first difference determines the winner
|
|
253
|
+
|
|
254
|
+
0 means equal
|
|
255
|
+
1 means sign1 has stronger dignities
|
|
256
|
+
2 means sign2 has stronger dignities
|
|
257
|
+
"""
|
|
258
|
+
s1digs = sorted([DIGNITY_RANK.get(dignities[p.list_index()], 0) for p in sign1.karakas()], reverse=True)
|
|
259
|
+
s2digs = sorted([DIGNITY_RANK.get(dignities[p.list_index()], 0) for p in sign2.karakas()], reverse=True)
|
|
260
|
+
if not s1digs and not s2digs:
|
|
261
|
+
return 0
|
|
262
|
+
if len(s1digs) != len(s2digs):
|
|
263
|
+
return 1 if len(s1digs) > len(s2digs) else 2
|
|
264
|
+
for d1, d2 in zip(s1digs, s2digs):
|
|
265
|
+
if d1 > d2: return 1
|
|
266
|
+
if d1 < d2: return 2
|
|
267
|
+
return 0
|
|
268
|
+
|
|
269
|
+
def compare_planets_dignities(planet1,planet2) -> int:
|
|
270
|
+
"""
|
|
271
|
+
compare the dignities of these two planets
|
|
272
|
+
0 for equal
|
|
273
|
+
1 for planet1 has higher dignity
|
|
274
|
+
2 for planet2 has higher dignity
|
|
275
|
+
"""
|
|
276
|
+
match planet1,planet2:
|
|
277
|
+
case "EX", "EX":
|
|
278
|
+
return 0
|
|
279
|
+
case "EX", _:
|
|
280
|
+
return 1
|
|
281
|
+
case _, "EX":
|
|
282
|
+
return 2
|
|
283
|
+
case "MT", "MT":
|
|
284
|
+
return 0
|
|
285
|
+
case "MT", _:
|
|
286
|
+
return 1
|
|
287
|
+
case _, "MT":
|
|
288
|
+
return 2
|
|
289
|
+
case "GF", "GF":
|
|
290
|
+
return 0
|
|
291
|
+
case "GF", _:
|
|
292
|
+
return 1
|
|
293
|
+
case _, "GF":
|
|
294
|
+
return 2
|
|
295
|
+
case "F", "F":
|
|
296
|
+
return 0
|
|
297
|
+
case "F", _:
|
|
298
|
+
return 1
|
|
299
|
+
case _, "F":
|
|
300
|
+
return 2
|
|
301
|
+
case "E", "E":
|
|
302
|
+
return 0
|
|
303
|
+
case "E", _:
|
|
304
|
+
return 1
|
|
305
|
+
case _, "E":
|
|
306
|
+
return 2
|
|
307
|
+
case "N", "N":
|
|
308
|
+
return 0
|
|
309
|
+
case "N", _:
|
|
310
|
+
return 1
|
|
311
|
+
case _, "N":
|
|
312
|
+
return 2
|
|
313
|
+
case "GE", "GE":
|
|
314
|
+
return 0
|
|
315
|
+
case "GE", _:
|
|
316
|
+
return 1
|
|
317
|
+
case _, "GE":
|
|
318
|
+
return 2
|
|
319
|
+
case "DB", "DB":
|
|
320
|
+
return 0
|
|
321
|
+
case "DB", _:
|
|
322
|
+
return 1
|
|
323
|
+
case _, "DB":
|
|
324
|
+
return 2
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def compare_signs_modalities(sign1,sign2) -> int:
|
|
329
|
+
"""
|
|
330
|
+
compare the modalities of sign1 and sign2, both Sign classes
|
|
331
|
+
return which is stronger
|
|
332
|
+
0 means equal strength
|
|
333
|
+
1 means sign1 is stronger
|
|
334
|
+
2 means sign2 is stronger
|
|
335
|
+
"""
|
|
336
|
+
if sign1.modality() == sign2.modality():
|
|
337
|
+
return 0
|
|
338
|
+
match (sign1.modality(),sign2.modality()):
|
|
339
|
+
case ("Dual", "Fixed"):
|
|
340
|
+
return 1
|
|
341
|
+
case ("Dual", "Moveable"):
|
|
342
|
+
return 1
|
|
343
|
+
case ("Fixed", "Dual"):
|
|
344
|
+
return 2
|
|
345
|
+
case ("Fixed", "Moveable"):
|
|
346
|
+
return 1
|
|
347
|
+
case ("Moveable", "Dual"):
|
|
348
|
+
return 2
|
|
349
|
+
case ("Moveable", "Fixed"):
|
|
350
|
+
return 2
|
|
351
|
+
|
|
352
|
+
def copy_collect_charts(root,outdir="all-charts"):
|
|
353
|
+
"""
|
|
354
|
+
will copy all .chtk files in root and down to outdir/*.chtk
|
|
355
|
+
will give errors if run again because the file is already there, but it works
|
|
356
|
+
"""
|
|
357
|
+
import subprocess
|
|
358
|
+
ret = []
|
|
359
|
+
for root, sub, files in os.walk(root):
|
|
360
|
+
for file in files:
|
|
361
|
+
this_path = os.path.join(root, file)
|
|
362
|
+
res = subprocess.call(["cp", f"{this_path}", f"{outdir}/{file}"])
|
|
363
|
+
if res != 0:
|
|
364
|
+
print("cp command failed")
|
|
365
|
+
|
|
366
|
+
return ret
|
|
367
|
+
|
|
368
|
+
def toJD(ls,context):
|
|
369
|
+
"""
|
|
370
|
+
take a list ls of julianday floats
|
|
371
|
+
return a list of JulianDay classes
|
|
372
|
+
"""
|
|
373
|
+
from libaditya.objects import JulianDay
|
|
374
|
+
return [JulianDay(jd_number,context.timeJD.utcoffset) for jd_number in ls]
|
|
375
|
+
|
|
376
|
+
def is_stellarium_id(swe_id):
|
|
377
|
+
"""
|
|
378
|
+
find if swe_id is actually a stellarium id
|
|
379
|
+
"""
|
|
380
|
+
if isinstance(swe_id, int):
|
|
381
|
+
return False
|
|
382
|
+
return "HIP" in swe_id or " " in swe_id
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def set_swe_true_sidereal_ayanamsa():
|
|
386
|
+
"""
|
|
387
|
+
this is used by calling TheStars.set_true_sidereal_hd_ayanamsa()
|
|
388
|
+
this sets the swe ayanamsa to the true sidereal ayanamsa, so that when we intialize
|
|
389
|
+
our stars they have the appropriate coordinates for what we are doing
|
|
390
|
+
|
|
391
|
+
define a custom ayanamsha
|
|
392
|
+
this is from the faq at masteringthezodiac.com
|
|
393
|
+
• Ayanamsa: User Defined SVP
|
|
394
|
+
• Fixed Sidereal Vernal Point: 31.2836
|
|
395
|
+
• Yearly Incremental SVP: 0.00
|
|
396
|
+
• Reference Year: 2000
|
|
397
|
+
reference year means January 1, 2000
|
|
398
|
+
Then choose the true sidereal-M (Midpoint) setting
|
|
399
|
+
"""
|
|
400
|
+
swe.set_sid_mode(swe.SIDM_USER + swe.SIDBIT_USER_UT, 2451545.0, 31.2836)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def mkheader(obj):
|
|
404
|
+
header = ""
|
|
405
|
+
header += f"{obj.context.name}\n"
|
|
406
|
+
header += f"Varga {obj.context.amsha} {obj.varga_name()}\n"
|
|
407
|
+
header += f"{obj.sysflgstr} coordinates\n"
|
|
408
|
+
header += f"{const.circle_name(obj.context.circle)}\n"
|
|
409
|
+
header += f"House system {swe.house_name(obj.context.hsys.encode())}\n"
|
|
410
|
+
digplace = "rashi" if obj.context.rashi_temporary_friendships else "varga"
|
|
411
|
+
header += f"Dignities based on {digplace}\n"
|
|
412
|
+
header += f"{obj.context.rashi_aspects} rashi aspects\n"
|
|
413
|
+
if obj.context.sysflg == swe.FLG_SIDEREAL:
|
|
414
|
+
# for sidereal signs we actually use swisseph 36
|
|
415
|
+
# dhruva equatorial is only for nakshatras
|
|
416
|
+
if obj.context.ayanamsa == 98:
|
|
417
|
+
header += f"{const.ayanamsa_name(36)} ayanamsa for signs\n"
|
|
418
|
+
header += f"{const.ayanamsa_name(98)} ayanamsa for nakshatras\n"
|
|
419
|
+
else:
|
|
420
|
+
header += f"{const.ayanamsa_name(obj.context.ayanamsa)} ayanamsa\n"
|
|
421
|
+
elif obj.context.sysflg == (swe.FLG_SIDEREAL | swe.FLG_TOPOCTR):
|
|
422
|
+
if obj.context.ayanamsa == 98:
|
|
423
|
+
header += f"{const.ayanamsa_name(36)} ayanamsa for signs\n"
|
|
424
|
+
header += f"{const.ayanamsa_name(98)} ayanamsa for nakshatras\n"
|
|
425
|
+
header += f"{obj.context.location.placename()} ({obj.context.location.latitude()} lat, {obj.context.location.longitude()} long)\n"
|
|
426
|
+
header += f"{const.ayanamsa_name(obj.context.ayanamsa)} ayanamsa\n"
|
|
427
|
+
else:
|
|
428
|
+
header += f"{const.ayanamsa_name(obj.context.ayanamsa)} ayanamsa\n"
|
|
429
|
+
header += f"{obj.context.location.placename()} ({obj.context.location.latitude()} lat, {obj.context.location.longitude()} long)\n"
|
|
430
|
+
header += f"{obj.context.timeJD}\n"
|
|
431
|
+
return header
|
libaditya/write.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
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 toml
|
|
19
|
+
|
|
20
|
+
from libaditya.objects import JulianDay, Location
|
|
21
|
+
from libaditya import read
|
|
22
|
+
|
|
23
|
+
def new_chart_interactive(outfile=None):
|
|
24
|
+
"""
|
|
25
|
+
take user input and write out a new chart
|
|
26
|
+
|
|
27
|
+
name: str (optional)
|
|
28
|
+
date: MM/DD/YYYY
|
|
29
|
+
hour: (HH:MM(:SS)) (UTC)
|
|
30
|
+
utcoffset: float
|
|
31
|
+
lat: N is positive
|
|
32
|
+
long: E is positive
|
|
33
|
+
three formats: 1) decimal
|
|
34
|
+
2) DD:MM(:SS)
|
|
35
|
+
3) 0DD(E/W)MM'SS(.SS)
|
|
36
|
+
3) DD(N/S)MM'SS(.SS)
|
|
37
|
+
alt: float - meters
|
|
38
|
+
placename: str (optional)
|
|
39
|
+
"""
|
|
40
|
+
name = input("Name: ")
|
|
41
|
+
date = input("Date (MM/DD/YYYY): ")
|
|
42
|
+
hour = input("Hour (HH:MM(:SS)) (UTC): ")
|
|
43
|
+
utcoffset = float(input("UTC offset: "))
|
|
44
|
+
# lat and long are floats
|
|
45
|
+
lat = read.parse_position_argument(input("Latitude (N is positive): "))
|
|
46
|
+
long = read.parse_position_argument(input("Longitude (E is positive): "))
|
|
47
|
+
alt = float(input("Altitude (meters): "))
|
|
48
|
+
placename = input("Placename (optional): ")
|
|
49
|
+
|
|
50
|
+
# name, placename, month, day, year, timedec, lat, long, utcoffset
|
|
51
|
+
month, day, year = read.intize_date(date)
|
|
52
|
+
timedec = read.intize_time(hour)
|
|
53
|
+
timeJD = JulianDay((year,month,day,timedec),utcoffset)
|
|
54
|
+
location = Location(lat, long, alt, placename, timeJD.mktimezone())
|
|
55
|
+
d=dict()
|
|
56
|
+
d["name"] = name.split(".")
|
|
57
|
+
d["timeJD"] = dict()
|
|
58
|
+
d["timeJD"]["jd"]=timeJD.jd_number()
|
|
59
|
+
d["timeJD"]["utcoffset"]=timeJD.utcoffset
|
|
60
|
+
d["location"]=location.__dict__
|
|
61
|
+
|
|
62
|
+
if outfile is not None:
|
|
63
|
+
# split in case they put extension on there
|
|
64
|
+
name=outfile.split(".")
|
|
65
|
+
with open(f"{name.lower().replace(' ','-')}.toml", "w") as fd:
|
|
66
|
+
toml.dump(d,fd)
|
|
67
|
+
return
|