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,2059 @@
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 prettytable import PrettyTable
19
+ from dataclasses import replace
20
+
21
+ from libaditya import constants as const
22
+ from libaditya import utils
23
+
24
+ from .julian_day import JulianDay
25
+ from .location import Location, Yamakoti
26
+ from .celestial_object import CelestialObject
27
+ from .context import EphContext
28
+ from .longitude import Longitude
29
+ from .nakshatras import Nakshatra, Nakshatras
30
+ from .shadbala import PlanetBala
31
+ from .swe_functions import SWEFirstLast
32
+
33
+
34
+ class Planet(CelestialObject,Longitude,PlanetBala):
35
+ """
36
+ this class has information and functions related to planets
37
+ each Planet takes a planet number and an EphContext
38
+ """
39
+
40
+ def __init__(self, pnumber, context=EphContext(),master=None):
41
+ self.timeJD = context.timeJD
42
+ self.context = context
43
+ self._amsha = self.context.amsha
44
+ self.master = master
45
+ self.pnumber = pnumber
46
+ self.attributes = {"constellation": "n/a", "dignity": "n/a", "lajjitaadi_avasthas": {},
47
+ "lajjitaadi_giving": {}, "lajjitaadi_receiving": {},
48
+ "baladi_avastha": "", "jagradadi_avastha": "", "deeptadi_avastha": "", "shayanadi_avastha": ""}
49
+ # below is what i want; effectively. const.names are globals
50
+ # self.planet_name = const.planet_names[self.pnumber]
51
+ # const.names[self.context.name_types]["planets"][self.pnumber]
52
+ self.planet_name = const.names[self.context.names_type]["planets"][self.pnumber]
53
+ self.jd = self.timeJD.jd
54
+ self._ayanamsa = self.context.ayanamsa
55
+ self.system = self.context.sysflg
56
+ self.sysflg = self.system | swe.FLG_SPEED
57
+ self.sysflgstr = const.sysflgstr(context.sysflg)
58
+ # if a longitude is passed, we are in a varga not equal to 1
59
+ self.long, self.lat, self.dist, self.long_speed, self.lat_speed, self.dist_speed = self.init_coords()
60
+ # deal with Ketu; i tried to put this in Ketu's class, but it didnt work comletely
61
+ # this works because self.pnumber for Ketu is set to Rahu
62
+ # so at this point self.long with be Rahu's longitude, which we then change to Ketu's
63
+ if isinstance(self,Ketu):
64
+ self.long = (self.long-180)%360
65
+ self.pnumber = 8
66
+ # if we are not doing heliocentric or barycentric, then Earth will be opposite the Sun
67
+ # this is really for the purpose of HD, which uses Earth as opposite the Sun
68
+ if isinstance(self,Earth) and self.context.sysflg != const.HELIO and self.context.sysflg != const.BARY:
69
+ self.long = (self.long-180)%360
70
+ # so that we only need only longitude() function with all the signizing and rounding or not
71
+ # this instantiates all the functions in Longitude
72
+ # this is for all the calculations that require *only* longitude
73
+ # thus it is used for both Planet and Cusp
74
+ super().__init__(self.long,self._amsha,self.context)
75
+ if self._amsha != 1:
76
+ self.lat = self.dist = self.long_speed = self.lat_speed = self.dist_speed = 0
77
+ #self._hd = HDLongitude(self.ecliptic_longitude(),context=self.context)
78
+ # below is the default for the outer planets, since they dont have dignity
79
+ # the others are set post-instantiation, since we need all the planets to fully determine
80
+ # dignity, so then these are added later
81
+ (self._right_ascension, self._declination, self._equatorial_distance,_,_,_) = swe.calc_ut(self.context.timeJD.jd_number(),self.swe_id(),swe.FLG_EQUATORIAL)[0]
82
+ from .nakshatras import Nakshatra
83
+ self._nakshatra = Nakshatra(self)
84
+
85
+ # this < is specialized to jaimini_karakas since it uses in_sign_longitude, not ecliptic longitude
86
+ def __lt__(self,p2):
87
+ return self.amsha_raw_in_sign_longitude() < p2.amsha_raw_in_sign_longitude()
88
+
89
+ def amsha(self):
90
+ return self._amsha
91
+
92
+ def table_row(self):
93
+ return (
94
+ [self.name()]
95
+ + [self.longitude()]
96
+ + [self.nakshatra_name()]
97
+ + [self.nakshatra().elapsed()]
98
+ + [self.longitude_speed()]
99
+ + [self.latitude()]
100
+ + [self.latitude_speed()]
101
+ + [self.distance()]
102
+ + [self.distance_speed()]
103
+ + [self.constellation()]
104
+ )
105
+
106
+ def init_coords(self):
107
+ """
108
+ i dont really like the way this function works
109
+
110
+ was one of the earliest i wrote for this; could be clearer i think
111
+ """
112
+ loc = self.context.location.swe_location()
113
+ if self.system == const.SID or self.system == (const.SID | const.TOPO):
114
+ # will need to add custom ayanamsas here
115
+ if self.ayanamsa() == 98:
116
+ self._ayanamsa = 36
117
+ swe.set_sid_mode(self.ayanamsa())
118
+ if self.ayanamsa() == 97:
119
+ utils.set_swe_true_sidereal_ayanamsa()
120
+ if self.system == const.TOPO or self.system == (const.SID | const.TOPO):
121
+ swe.set_topo(loc[0], loc[1], loc[2])
122
+ # for draconic charts i choose -8 to indicate that system
123
+ # but swe doesnt accept that, so replace it if necessary
124
+ if isinstance(self,Earth) and self.context.sysflg != const.HELIO and self.context.sysflg != const.BARY:
125
+ return swe.calc_ut(self.jd, swe.SUN, self.sysflg if self.sysflg >= 0 else 0)[0]
126
+ return swe.calc_ut(self.jd, self.pnumber, self.sysflg if self.sysflg >= 0 else 0)[0]
127
+
128
+ def name(self) -> str:
129
+ return self.planet_name + self.retrostr()
130
+
131
+ def swe_id(self):
132
+ return self.pnumber
133
+
134
+ def dignity(self):
135
+ """
136
+ return the dignity that has been set by Planets.
137
+ """
138
+ match self.identity():
139
+ case "Earth" | "Uranus" | "Neptune" | "Pluto" | "Chiron":
140
+ return ""
141
+ case _:
142
+ return self.attributes["dignity"]
143
+
144
+ def lajjitaadi_avasthas(self):
145
+ return self.attributes["lajjitaadi_avasthas"]
146
+
147
+ def lajjitaadi_avasthas_giving(self):
148
+ return self.attributes["lajjitaadi_giving"]
149
+
150
+ def lajjitaadi_avasthas_receiving(self):
151
+ return self.attributes["lajjitaadi_receiving"]
152
+
153
+ def baladi_avastha(self):
154
+ return self.attributes["baladi_avastha"]
155
+
156
+ def jagradadi_avastha(self):
157
+ return self.attributes["jagradadi_avastha"]
158
+
159
+ def deeptadi_avastha(self):
160
+ return self.attributes["deeptadi_avastha"]
161
+
162
+ def shayanadi_avastha(self):
163
+ return self.attributes["shayanadi_avastha"]
164
+
165
+ def combined_relationship(self):
166
+ """
167
+ return the "combined_relationship"
168
+ this is not really a good name for this
169
+ at the moment this is only used for saptavargajabala, where, if a planet is EX or DB,
170
+ then you use the combined relationships as if they were not
171
+ but for MT and OH, you use MT and OH
172
+ which is why "combined_relationship" is not really a good name
173
+ """
174
+ return self.attributes["combined_relationship"]
175
+
176
+ def Self(self):
177
+ return self
178
+
179
+ def dig_bala(self):
180
+ """
181
+ we need a Sign to get this...really just a longitude
182
+ we can always just pass the longitude
183
+
184
+ : do not try to import Sign into this file; it will give an error;
185
+ anyway, that would only be to put a type hint. but that is really not needed
186
+ we just need the object
187
+ """
188
+ return self.attributes["dig_bala"]
189
+
190
+ def list_index(self):
191
+ match self.pnumber:
192
+ case swe.SUN:
193
+ return 0
194
+ case swe.MOON:
195
+ return 1
196
+ case swe.MARS:
197
+ return 2
198
+ case swe.MERCURY:
199
+ return 3
200
+ case swe.JUPITER:
201
+ return 4
202
+ case swe.VENUS:
203
+ return 5
204
+ case swe.SATURN:
205
+ return 6
206
+ case swe.TRUE_NODE:
207
+ return 7
208
+ case swe.TRUE_NODE:
209
+ return 8
210
+ case swe.URANUS:
211
+ return 9
212
+ case swe.NEPTUNE:
213
+ return 10
214
+ case swe.PLUTO:
215
+ return 11
216
+ case swe.CHIRON:
217
+ return 12
218
+ case swe.EARTH:
219
+ return 13
220
+
221
+ def number(self, system="vedic"):
222
+ if system == "solar_order":
223
+ match self.identity():
224
+ # only these are different
225
+ case "Mercury":
226
+ return 3
227
+ case "Venus":
228
+ return 4
229
+ case "Mars":
230
+ return 5
231
+ case "Jupiter":
232
+ return 6
233
+ case _:
234
+ return self.list_index()+1
235
+ else:
236
+ return self.list_index()+1
237
+
238
+ def system_name(self) -> str:
239
+ return self.sysflgstr
240
+
241
+ def object_type(self) -> str:
242
+ return "Planet"
243
+
244
+ def identity(self) -> str:
245
+ return self._id
246
+
247
+ def key(self) -> str:
248
+ return self.identity()
249
+
250
+ def ayanamsa(self):
251
+ return self._ayanamsa
252
+
253
+ def ayanamsa_name(self) -> str:
254
+ return const.ayanamsa_name(self.ayanamsa())
255
+
256
+ def retrograde(self) -> bool:
257
+ if self.longitude_speed() < 0:
258
+ return True
259
+ else:
260
+ return False
261
+
262
+ def retrostr(self) -> str:
263
+ if self.retrograde():
264
+ return " (R)"
265
+ else:
266
+ return ""
267
+
268
+ def gender(self):
269
+ match self.identity():
270
+ case "Sun":
271
+ return "M"
272
+ case "Moon":
273
+ return "F"
274
+ case "Mars":
275
+ return "M"
276
+ case "Mercury":
277
+ return "N"
278
+ case "Jupiter":
279
+ return "M"
280
+ case "Venus":
281
+ return "F"
282
+ case "Saturn":
283
+ return "N"
284
+ case "Rahu":
285
+ return "F"
286
+ case "Ketu":
287
+ return "N"
288
+
289
+ def daily_motion(self):
290
+ """
291
+ return daily motion in degress that the planet traverses
292
+ in the next 24 hours from self.julianday
293
+ """
294
+ return (
295
+ (swe.calc_ut(self.timeJD.jd + 1, self.pnumber, self.sysflg)[0][0])
296
+ - (swe.calc_ut(self.timeJD.jd, self.pnumber, self.sysflg)[0][0])
297
+ )
298
+
299
+ def riseset(self, rs, location=Location()):
300
+ """
301
+ :rs flag for rise, set, or one of the two meridian transits
302
+ swe.CALC_RISE, swe.CALC_SET, swe.MTRANSIT, swe.ITRANSIT
303
+ :location a Location class for where this is for
304
+ """
305
+ return JulianDay(
306
+ swe.rise_trans(
307
+ self.timeJD.jd_number(), # midnightjd() if (rs == swe.CALC_RISE) else self.jd,
308
+ self.pnumber,
309
+ rs | swe.BIT_HINDU_RISING,
310
+ location.swe_location(),
311
+ )[1][0],self.timeJD.utcoffset,self.timeJD.timezone()
312
+ )
313
+
314
+ def nakshatra(self) -> Nakshatra:
315
+ return self._nakshatra
316
+
317
+ def nakshatra_name(self) -> str:
318
+ return self._nakshatra.nakshatra()
319
+
320
+ def nature(self):
321
+ """
322
+ "" for none
323
+ """
324
+ match self.identity():
325
+ case "Uranus" | "Neptune" | "Pluto" | "Chiron":
326
+ return "none"
327
+ case _:
328
+ return ""
329
+
330
+
331
+ def _get_dignity(self, self_in_rashi, lord: Self) -> str:
332
+ """
333
+ return the dignity of a planet
334
+ i.e, the combined relationship, so we need to know where the lord is
335
+
336
+ this doesnt really work like you might expect, since we need information from Planets
337
+ since a Planet cannot always determine its dignity on its own
338
+
339
+ we need self_in_rashi to calculate temporary relationships based on the rashi chart
340
+ so now we cant calculate temporary relationships based on the specific varga with this code
341
+ """
342
+ # for saptavargaja bala, if a planet is EX or DB, we need to use their dignity as if they were not
343
+ # EX or DB, thus we find the combined dignity and store it, and then find the actual dignity
344
+ natural_relationship = self.natural_relationship_from(lord)
345
+ distance = self_in_rashi.signs_apart(lord.sign())
346
+ match distance:
347
+ case 1 | 2 | 3 | 9 | 10 | 11:
348
+ temporary_relationship = "F"
349
+ case _:
350
+ temporary_relationship = "E"
351
+ match (natural_relationship,temporary_relationship):
352
+ case ("F","F"):
353
+ self.attributes["combined_relationship"] = "GF"
354
+ self.attributes["dignity"] = "GF"
355
+ case ("N","F"):
356
+ self.attributes["combined_relationship"] = "F"
357
+ self.attributes["dignity"] = "F"
358
+ case ("E","F"):
359
+ self.attributes["combined_relationship"] = "N"
360
+ self.attributes["dignity"] = "N"
361
+ case ("F","E"):
362
+ self.attributes["combined_relationship"] = "N"
363
+ self.attributes["dignity"] = "N"
364
+ case ("N","E"):
365
+ self.attributes["combined_relationship"] = "E"
366
+ self.attributes["dignity"] = "E"
367
+ case ("E","E"):
368
+ self.attributes["combined_relationship"] = "GE"
369
+ self.attributes["dignity"] = "GE"
370
+ case ("N","N"):
371
+ self.attributes["combined_relationship"] = "N"
372
+ self.attributes["dignity"] = "N"
373
+ if self.is_ex():
374
+ self.attributes["dignity"] = "EX"
375
+ # Mercury exalts himself, so for saptavargajabala, that means EX=OH
376
+ if self.identity() == "Mercury":
377
+ self.attributes["combined_relationship"] = "OH"
378
+ return "EX"
379
+ if self.is_mt():
380
+ self.attributes["dignity"] = "MT"
381
+ return "MT"
382
+ if self.is_oh():
383
+ self.attributes["dignity"] = "OH"
384
+ return "OH"
385
+ if self.is_db():
386
+ self.attributes["dignity"] = "DB"
387
+ return "DB"
388
+ return self.attributes["dignity"]
389
+
390
+
391
+ def parashara_aspect_to(self, planet) -> float | str:
392
+ """
393
+ return the float of the precise parashara aspect between
394
+ self and planet; planet can also be a cusp; any specific longitude, really
395
+
396
+ this function does aspects for Sun, Moon, Mercury and Venus
397
+ the other karakas have their own special aspects that are defined in their own classes
398
+
399
+ this is implemented according to the sutras from bphs as found in graha sutras by ew
400
+ """
401
+ if self.identity() == planet.identity():
402
+ # a planet is not aspecting itself; so there is no value
403
+ return ""
404
+ if self.sign() == planet.sign():
405
+ # Y for yuti, conjunction
406
+ return "Y"
407
+ diff = self.degrees_apart(planet.ecliptic_longitude())
408
+ if diff <= 30 or diff >= 300:
409
+ # within this orb planets do not aspect other planets
410
+ return ""
411
+ if diff > 180 and diff < 300:
412
+ return (300 - diff)/2
413
+ if diff > 150 and diff <= 180:
414
+ return (diff - 150)*2
415
+ if diff > 120 and diff <= 150:
416
+ return (150 - diff)
417
+ if diff > 90 and diff <= 120:
418
+ return ((120-diff)/2) + 30
419
+ if diff > 60 and diff <= 90:
420
+ return (diff - 60) + 15
421
+ if diff > 30 and diff <= 60:
422
+ return (diff - 30)/2
423
+
424
+ def parashara_aspect_from(self, planet) -> float | str:
425
+ return planet.parashara_aspect_to(self)
426
+
427
+ def lowest_hourly_speed(self) -> float:
428
+ return self.lowest_daily_speed()/24
429
+
430
+ def lowest_minutely_speed(self) -> float:
431
+ return self.lowest_hourly_speed()/60
432
+
433
+ def lowest_secondly_speed(self) -> float:
434
+ return self.lowest_minutely_speed()/60
435
+
436
+ def ucca(self):
437
+ """
438
+ this is the (sign,degrees) of this Planets exaltation
439
+ storing it this ways means this information can be used just like this
440
+ for zodiac or aditya circles
441
+ """
442
+ # this is a doc string that will show in the repl's "help()" function for all objects that inherit from Planet
443
+ # so yes this method actually "does" something; well, it doesnt, but it has a value to it
444
+ pass
445
+
446
+ def jaimini_info(self):
447
+ """
448
+ return a string of planetary information that can be stored in a dictionary that can be convereted to toml
449
+ separate attributes by a comma, in the proper order
450
+
451
+ curent fields:
452
+ name,nature,lord,dignity
453
+ """
454
+ return f"{self.planet_name},{self.nature()},{self.lord()},{self.dignity()}"
455
+
456
+ def __str__(self):
457
+ ayanamsa = ""
458
+ if self.system == swe.FLG_SIDEREAL:
459
+ ayanamsa = f"\nUsing {const.ayanamsa_name(self.ayanamsa())} ayanamsa"
460
+ return (
461
+ f"amsha {self.amsha()}\n{self.planet_name}{self.retrostr()} {self.ecliptic_longitude()} degrees ({self.longitude()}) {self.system_name()} longitude{ayanamsa}\n"
462
+ + f"{self.timeJD}\n"
463
+ )
464
+
465
+
466
+ class Sun(Planet):
467
+ def __init__(self, context=EphContext(),master=None):
468
+ super().__init__(swe.SUN, context,master)
469
+ self._id = "Sun"
470
+
471
+ def glyph(self):
472
+ return "⨀"
473
+
474
+ def abbreviation(self) -> str:
475
+ """
476
+ two letter representation of Planet's name
477
+ """
478
+ return "Su"
479
+
480
+ def type(self):
481
+ return Sun
482
+
483
+ def sunrise_yamakoti(self) -> JulianDay:
484
+ return self.riseset(swe.CALC_RISE, Yamakoti)
485
+
486
+ def lowest_daily_speed(self) -> float:
487
+ """
488
+ return a speed lower than the lowest speed for this planet
489
+ used in finding the time when a planet is at a certain longitude
490
+ this is the daily motion
491
+ i.e., x/24 hours = hours motion
492
+ x/24/60 = minute motion
493
+ """
494
+ return .9
495
+
496
+ def is_outer_planet(self):
497
+ return False
498
+
499
+ def is_karaka(self):
500
+ return True
501
+
502
+ def is_graha(self):
503
+ return True
504
+
505
+ def nature(self) -> str:
506
+ """
507
+ nature means benefic or malefic
508
+ """
509
+ return "Malefic"
510
+
511
+ def ingress(self, next_long):
512
+ """
513
+ return Sun for the JulianDay where Sun arrives at longitude next_long
514
+ """
515
+ if next_long == self.ecliptic_longitude():
516
+ return self
517
+ # % 360 help in case we are looking for the equinox, next_long = 0
518
+ if round(self.ecliptic_longitude(),3)%360 == round(next_long,3):
519
+ # if we dont go forward one second the longitude we are are will be
520
+ # for example, 269.99999769, and then the ephemeris will print "30:00:00 bhaga"
521
+ # so by going forward one seconds, we get to 270.0000000343 and it will print "00:00:00 pusha"
522
+ return Sun(replace(self.context,timeJD=self.timeJD.shift("f","seconds",30)))
523
+ # difference between current longitude and desired longitude
524
+ diff = self.degrees_apart(next_long)
525
+ shift_factor = diff*self.lowest_daily_speed()
526
+ return Sun(replace(self.context,timeJD=self.timeJD.shift("f","days",shift_factor))).ingress(next_long)
527
+
528
+ def next_equinox(self):
529
+ """
530
+ get the next equinox from the current timeJD
531
+ """
532
+ # between ascending and descending, so find descending
533
+ if self.ecliptic_longitude() > 0 and self.ecliptic_longitude() < 180:
534
+ return self.ingress(180)
535
+ # otherwise, we are between descending and ascending, so find ascending
536
+ else:
537
+ return self.ingress(0)
538
+
539
+ def next_solstice(self):
540
+ """
541
+ get the next solstice from the current timeJD
542
+ """
543
+ # between norther and southern, so find southern
544
+ if self.ecliptic_longitude() > 90 and self.ecliptic_longitude() < 270:
545
+ return self.ingress(270)
546
+ # otherwise, we are between southern and northern, so find northern
547
+ else:
548
+ return self.ingress(90)
549
+
550
+ def is_ex(self):
551
+ if self.sign() == 1:
552
+ return True
553
+ else:
554
+ return False
555
+
556
+ def is_mt(self):
557
+ if self.sign() == 5 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 20):
558
+ return True
559
+ else:
560
+ return False
561
+
562
+ def is_oh(self):
563
+ if self.sign() == 5 and self.amsha_raw_in_sign_longitude() > 20:
564
+ return True
565
+ else:
566
+ return False
567
+
568
+ def is_db(self):
569
+ if self.sign() == 7:
570
+ return True
571
+ else:
572
+ return False
573
+
574
+ def natural_relationship_from(self, lord):
575
+ match lord.identity():
576
+ case "Moon":
577
+ return "F"
578
+ case "Mars":
579
+ return "F"
580
+ case "Mercury":
581
+ return "N"
582
+ case "Jupiter":
583
+ return "F"
584
+ case "Venus":
585
+ return "E"
586
+ case "Saturn":
587
+ return "E"
588
+
589
+ def ucca(self):
590
+ return (1,10)
591
+
592
+ def nica(self):
593
+ return (7,10)
594
+
595
+ def dig_bala_cusp(self):
596
+ """
597
+ this is the cusp at which this Planet has digbala
598
+ """
599
+ return 10
600
+
601
+ def cheshta_bala(self):
602
+ """
603
+ sun has 60 points of cheshta bala at the northern solstice, i.e., 90 degrees longitude
604
+ """
605
+ return self.virupas_between(90)
606
+
607
+
608
+ class Moon(Planet,SWEFirstLast):
609
+ def __init__(self, context=EphContext(),master=None, nature=None):
610
+ super().__init__(swe.MOON, context,master)
611
+ self._id = "Moon"
612
+ self.attributes["nature"] = nature
613
+
614
+ def glyph(self):
615
+ return "☾"
616
+
617
+ def abbreviation(self) -> str:
618
+ """
619
+ two letter representation of Planet's name
620
+ """
621
+ return "Mo"
622
+
623
+ def type(self):
624
+ return Moon
625
+
626
+ def nature(self):
627
+ return self.attributes["nature"]
628
+
629
+ def next_crossing_of_rahu(self) -> str:
630
+ """
631
+ JulianDay of the next time Moon is conjunct true node Rahu
632
+ """
633
+ jd_cross, moon_longitude, moon_latitude = swe.mooncross_node_ut(self.context.timeJD.jd_number())
634
+ crossJD = JulianDay(jd_cross,self.context.timeJD.utcoffset)
635
+ ret = ""
636
+ ret = f"{crossJD}\n"
637
+ ret += f"swe.{moon_longitude=} swe.{moon_latitude=}\n"
638
+ return ret
639
+
640
+ def is_benefic(self):
641
+ if self.nature() == "Benefic":
642
+ return True
643
+ else:
644
+ return False
645
+
646
+ def is_malefic(self):
647
+ return not self.is_benefic()
648
+
649
+ def lowest_daily_speed(self) -> float:
650
+ """
651
+ return a speed lower than the lowest speed for this planet
652
+ used in finding the time when a planet is at a certain longitude
653
+ this is the daily motion
654
+ i.e., x/24 hours = hours motion
655
+ x/24/60 = minute motion
656
+ """
657
+ return 11.0
658
+
659
+ def is_outer_planet(self):
660
+ return False
661
+
662
+ def is_karaka(self):
663
+ return True
664
+
665
+ def is_graha(self):
666
+ return True
667
+
668
+ def is_ex(self):
669
+ if self.sign() == 2 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 3):
670
+ return True
671
+ else:
672
+ return False
673
+
674
+ def is_mt(self):
675
+ if self.sign() == 2 and self.amsha_raw_in_sign_longitude() > 3:
676
+ return True
677
+ else:
678
+ return False
679
+
680
+ def is_oh(self):
681
+ if self.sign() == 4:
682
+ return True
683
+ else:
684
+ return False
685
+
686
+ def is_db(self):
687
+ if self.sign() == 8 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 3):
688
+ return True
689
+ else:
690
+ return False
691
+
692
+ def natural_relationship_from(self, lord):
693
+ match lord.identity():
694
+ case "Sun":
695
+ return "F"
696
+ case "Mars":
697
+ return "N"
698
+ case "Mercury":
699
+ return "F"
700
+ case "Jupiter":
701
+ return "N"
702
+ case "Venus":
703
+ return "N"
704
+ case "Saturn":
705
+ return "N"
706
+
707
+ def ucca(self):
708
+ return ((2,0),(2,3))
709
+
710
+ def nica(self):
711
+ return ((8,0),(8,3))
712
+
713
+ def dig_bala_cusp(self):
714
+ return 4
715
+
716
+ def cheshta_bala(self):
717
+ """
718
+ moon has 60 points of cheshta bala at the full moon
719
+ """
720
+ from libaditya.calc import Panchanga
721
+ panch = Panchanga(self.context)
722
+ if self.nature() == "Benefic":
723
+ # Moon is heading towards full which is where is has 60
724
+ next_full_moon = panch.next_full_moon().moon()
725
+ return self.virupas_between(next_full_moon)
726
+ else:
727
+ # Moon is malefic, heading towards new
728
+ # so the place is has 60 points is opposite where the new moon is
729
+ next_new_moon = panch.next_new_moon()
730
+ return self.virupas_between((next_new_moon.moon().ecliptic_longitude()+180)%360)
731
+
732
+ def ingress(self, next_long):
733
+ """
734
+ return Moon for the JulianDay where Moon arrives at longitude next_long
735
+ """
736
+ #import pdb; pdb.set_trace()
737
+ if next_long == self.ecliptic_longitude():
738
+ return self
739
+ # % 360 help in case we are looking for the equinox, next_long = 0
740
+ if round(self.ecliptic_longitude(),3)%360 == round(next_long,3):
741
+ # if we dont go forward one second the longitude we are are will be
742
+ # for example, 269.99999769, and then the ephemeris will print "30:00:00 bhaga"
743
+ # so by going forward one seconds, we get to 270.0000000343 and it will print "00:00:00 pusha"
744
+ return Moon(replace(self.context,timeJD=self.timeJD.shift("f","seconds",1)))
745
+ # difference between current longitude and desired longitude
746
+ diff = self.degrees_apart(next_long)
747
+ shift_factor = diff*(self.lowest_daily_speed()/24)
748
+ return Moon(replace(self.context,timeJD=self.timeJD.shift("f","hours",shift_factor))).ingress(next_long)
749
+
750
+
751
+ class Mars(Planet):
752
+
753
+ def __init__(self, context=EphContext(),master=None):
754
+ super().__init__(swe.MARS, context,master)
755
+ self._id = "Mars"
756
+
757
+ def glyph(self):
758
+ return "♂"
759
+
760
+ def abbreviation(self) -> str:
761
+ """
762
+ two letter representation of Planet's name
763
+ """
764
+ return "Ma"
765
+
766
+ def type(self):
767
+ return Mars
768
+
769
+ def nature(self) -> str:
770
+ """
771
+ nature means benefic or malefic
772
+ """
773
+ return "Malefic"
774
+
775
+ def is_outer_planet(self):
776
+ return False
777
+
778
+ def is_karaka(self):
779
+ return True
780
+
781
+ def is_graha(self):
782
+ return True
783
+
784
+ def is_ex(self):
785
+ if self.sign() == 10:
786
+ return True
787
+ else:
788
+ return False
789
+
790
+ def is_mt(self):
791
+ if self.sign() == 1 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 12):
792
+ return True
793
+ else:
794
+ return False
795
+
796
+ def is_oh(self):
797
+ if (self.sign() == 1 and self.amsha_raw_in_sign_longitude() > 12) or self.sign() == 8:
798
+ return True
799
+ else:
800
+ return False
801
+
802
+ def is_db(self):
803
+ if self.sign() == 4:
804
+ return True
805
+ else:
806
+ return False
807
+
808
+ def natural_relationship_from(self, lord):
809
+ match lord.identity():
810
+ case "Sun":
811
+ return "F"
812
+ case "Moon":
813
+ return "F"
814
+ case "Mercury":
815
+ return "E"
816
+ case "Jupiter":
817
+ return "F"
818
+ case "Venus":
819
+ return "N"
820
+ case "Saturn":
821
+ return "N"
822
+
823
+ def parashara_aspect_to(self, planet) -> float | str:
824
+ """
825
+ return the float of the precise parashara aspect between
826
+ self and planet
827
+
828
+ this function does aspects for Mars
829
+ the other karakas have their own special aspects that are defined in their own classes
830
+
831
+ this is implemented according to the sutras from bphs as found in graha sutras by ew
832
+ """
833
+ if self.identity() == planet.identity():
834
+ # a planet is not aspecting itself; so there is no value
835
+ return ""
836
+ if self.sign() == planet.sign():
837
+ # Y for yuti, conjunction
838
+ return "Y"
839
+ diff = self.degrees_apart(planet.ecliptic_longitude())
840
+ if diff <= 30 or diff >= 300:
841
+ # within this orb planets do not aspect other planets
842
+ return ""
843
+ if diff > 240 and diff < 300:
844
+ return (300 - diff)/2
845
+ if diff > 210 and diff <= 240:
846
+ return 60 - (diff - 210)
847
+ if diff > 180 and diff < 210:
848
+ return 60
849
+ if diff > 150 and diff <= 180:
850
+ return (diff - 150)*2
851
+ if diff > 120 and diff <= 150:
852
+ return (150 - diff)
853
+ if diff > 90 and diff <= 120:
854
+ return 60 - (120 - diff)
855
+ if diff > 60 and diff <= 90:
856
+ return (diff - 60) + (diff - 60)/2 + 15
857
+ if diff > 30 and diff <= 60:
858
+ return (diff - 30)/2
859
+
860
+ def ucca(self):
861
+ return (10,28)
862
+
863
+ def nica(self):
864
+ return (4,28)
865
+
866
+ def dig_bala_cusp(self):
867
+ return 10
868
+
869
+
870
+ class Mercury(Planet,SWEFirstLast):
871
+
872
+ def __init__(self, context=EphContext(),master=None):
873
+ super().__init__(swe.MERCURY, context,master)
874
+ self._id = "Mercury"
875
+
876
+ def glyph(self):
877
+ return "☿"
878
+
879
+ def abbreviation(self) -> str:
880
+ """
881
+ two letter representation of Planet's name
882
+ """
883
+ return "Me"
884
+
885
+ def type(self):
886
+ return Mercury
887
+
888
+ def nature(self) -> str:
889
+ """
890
+ nature means benefic or malefic
891
+ """
892
+ return "Benefic"
893
+
894
+ def is_outer_planet(self):
895
+ return False
896
+
897
+ def is_karaka(self):
898
+ return True
899
+
900
+ def is_graha(self):
901
+ return True
902
+
903
+ def is_ex(self):
904
+ if self.sign() == 6 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 15):
905
+ return True
906
+ else:
907
+ return False
908
+
909
+ def is_mt(self):
910
+ if self.sign() == 6 and (self.amsha_raw_in_sign_longitude() >= 15 and self.amsha_raw_in_sign_longitude() < 20):
911
+ return True
912
+ else:
913
+ return False
914
+
915
+ def is_oh(self):
916
+ if self.sign() == 3 or (self.sign() == 6 and self.amsha_raw_in_sign_longitude() >= 20):
917
+ return True
918
+ else:
919
+ return False
920
+
921
+ def is_db(self):
922
+ if self.sign() == 12 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 15):
923
+ return True
924
+ else:
925
+ return False
926
+
927
+ def natural_relationship_from(self, lord):
928
+ match lord.identity():
929
+ case "Sun":
930
+ return "F"
931
+ case "Moon":
932
+ return "E"
933
+ case "Mars":
934
+ return "N"
935
+ case "Mercury":
936
+ return "OH"
937
+ case "Jupiter":
938
+ return "N"
939
+ case "Venus":
940
+ return "F"
941
+ case "Saturn":
942
+ return "N"
943
+
944
+ def ucca(self):
945
+ return ((6,0),(6,15))
946
+
947
+ def nica(self):
948
+ return ((12,0),(12,15))
949
+
950
+ def dig_bala_cusp(self):
951
+ return 1
952
+
953
+
954
+ class Jupiter(Planet):
955
+
956
+ def __init__(self, context=EphContext(),master=None):
957
+ super().__init__(swe.JUPITER, context,master)
958
+ self._id = "Jupiter"
959
+
960
+ def glyph(self):
961
+ return "♃"
962
+
963
+ def abbreviation(self) -> str:
964
+ """
965
+ two letter representation of Planet's name
966
+ """
967
+ return "Ju"
968
+
969
+ def type(self):
970
+ return Jupiter
971
+
972
+ def nature(self) -> str:
973
+ """
974
+ nature means benefic or malefic
975
+ """
976
+ return "Benefic"
977
+
978
+ def is_outer_planet(self):
979
+ return False
980
+
981
+ def is_karaka(self):
982
+ return True
983
+
984
+ def is_graha(self):
985
+ return True
986
+
987
+ def is_ex(self):
988
+ if self.sign() == 4:
989
+ return True
990
+ else:
991
+ return False
992
+
993
+ def is_mt(self):
994
+ if self.sign() == 9 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 10):
995
+ return True
996
+ else:
997
+ return False
998
+
999
+ def is_oh(self):
1000
+ if self.sign() == 12 or (self.sign() == 9 and self.amsha_raw_in_sign_longitude() > 10):
1001
+ return True
1002
+ else:
1003
+ return False
1004
+
1005
+ def is_db(self):
1006
+ if self.sign() == 10:
1007
+ return True
1008
+ else:
1009
+ return False
1010
+
1011
+ def natural_relationship_from(self, lord):
1012
+ match lord.identity():
1013
+ case "Sun":
1014
+ return "F"
1015
+ case "Moon":
1016
+ return "F"
1017
+ case "Mars":
1018
+ return "F"
1019
+ case "Mercury":
1020
+ return "E"
1021
+ case "Venus":
1022
+ return "E"
1023
+ case "Saturn":
1024
+ return "N"
1025
+
1026
+ def parashara_aspect_to(self, planet) -> float | str:
1027
+ """
1028
+ return the float of the precise parashara aspect between
1029
+ self and planet
1030
+
1031
+ this function does aspects for Jupiter
1032
+ the other karakas have their own special aspects that are defined in their own classes
1033
+
1034
+ this is implemented according to the sutras from bphs as found in graha sutras by ew
1035
+ """
1036
+ if self.identity() == planet.identity():
1037
+ # a planet is not aspecting itself; so there is no value
1038
+ return ""
1039
+ if self.sign() == planet.sign():
1040
+ # Y for yuti, conjunction
1041
+ return "Y"
1042
+ diff = self.degrees_apart(planet.ecliptic_longitude())
1043
+ if diff <= 30 or diff >= 300:
1044
+ # within this orb planets do not aspect other planets
1045
+ return ""
1046
+ if diff > 270 and diff < 300:
1047
+ return (300 - diff)/2
1048
+ if diff > 240 and diff <= 270:
1049
+ return ((30-(diff-240))*1.5) + 15
1050
+ if diff > 210 and diff <= 240:
1051
+ return ((diff-210)/2) + 45
1052
+ if diff > 180 and diff <= 210:
1053
+ return (300 - diff)/2
1054
+ if diff > 150 and diff <= 180:
1055
+ return (diff - 150)*2
1056
+ if diff > 120 and diff <= 150:
1057
+ return 60 - ((diff-120)*2)
1058
+ if diff > 90 and diff <= 120:
1059
+ return ((120-diff)/2) + 45
1060
+ if diff > 60 and diff <= 90:
1061
+ return (diff - 60) + 15
1062
+ if diff > 30 and diff <= 60:
1063
+ return (diff - 30)/2
1064
+
1065
+ def ucca(self):
1066
+ return (4,5)
1067
+
1068
+ def nica(self):
1069
+ return (10,5)
1070
+
1071
+ def dig_bala_cusp(self):
1072
+ return 1
1073
+
1074
+ class Venus(Planet,SWEFirstLast):
1075
+
1076
+ def __init__(self, context=EphContext(),master=None):
1077
+ super().__init__(swe.VENUS, context,master)
1078
+ self._id = "Venus"
1079
+
1080
+ def glyph(self):
1081
+ return "♀"
1082
+
1083
+ def abbreviation(self) -> str:
1084
+ """
1085
+ two letter representation of Planet's name
1086
+ """
1087
+ return "Ve"
1088
+
1089
+ def type(self):
1090
+ return Venus
1091
+
1092
+ def nature(self) -> str:
1093
+ """
1094
+ nature means benefic or malefic
1095
+ """
1096
+ return "Benefic"
1097
+
1098
+ def is_outer_planet(self):
1099
+ return False
1100
+
1101
+ def is_karaka(self):
1102
+ return True
1103
+
1104
+ def is_graha(self):
1105
+ return True
1106
+
1107
+ def is_ex(self):
1108
+ if self.sign() == 12:
1109
+ return True
1110
+ else:
1111
+ return False
1112
+
1113
+ def is_mt(self):
1114
+ if self.sign() == 7 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 15):
1115
+ return True
1116
+ else:
1117
+ return False
1118
+
1119
+ def is_oh(self):
1120
+ if self.sign() == 2 or (self.sign() == 7 and self.amsha_raw_in_sign_longitude() > 15):
1121
+ return True
1122
+ else:
1123
+ return False
1124
+
1125
+ def is_db(self):
1126
+ if self.sign() == 6:
1127
+ return True
1128
+ else:
1129
+ return False
1130
+
1131
+ def natural_relationship_from(self, lord):
1132
+ match lord.identity():
1133
+ case "Sun":
1134
+ return "E"
1135
+ case "Moon":
1136
+ return "E"
1137
+ case "Mars":
1138
+ return "N"
1139
+ case "Mercury":
1140
+ return "F"
1141
+ case "Jupiter":
1142
+ return "N"
1143
+ case "Saturn":
1144
+ return "F"
1145
+
1146
+ def ucca(self):
1147
+ return (12,27)
1148
+
1149
+ def nica(self):
1150
+ return (6,27)
1151
+
1152
+ def dig_bala_cusp(self):
1153
+ return 4
1154
+
1155
+
1156
+ class Saturn(Planet):
1157
+
1158
+ def __init__(self, context=EphContext(),master=None):
1159
+ super().__init__(swe.SATURN, context,master)
1160
+ self._id = "Saturn"
1161
+
1162
+ def glyph(self):
1163
+ return "♄"
1164
+
1165
+ def abbreviation(self) -> str:
1166
+ """
1167
+ two letter representation of Planet's name
1168
+ """
1169
+ return "Sa"
1170
+
1171
+ def type(self):
1172
+ return Saturn
1173
+
1174
+ def nature(self) -> str:
1175
+ """
1176
+ nature means benefic or malefic
1177
+ """
1178
+ return "Malefic"
1179
+
1180
+ def is_outer_planet(self):
1181
+ return False
1182
+
1183
+ def is_karaka(self):
1184
+ return True
1185
+
1186
+ def is_graha(self):
1187
+ return True
1188
+
1189
+ def is_ex(self):
1190
+ if self.sign() == 7:
1191
+ return True
1192
+ else:
1193
+ return False
1194
+
1195
+ def is_mt(self):
1196
+ if self.sign() == 11 and (self.amsha_raw_in_sign_longitude() >= 0 and self.amsha_raw_in_sign_longitude() < 20):
1197
+ return True
1198
+ else:
1199
+ return False
1200
+
1201
+ def is_oh(self):
1202
+ if self.sign() == 10 or (self.sign() == 11 and self.amsha_raw_in_sign_longitude() > 20):
1203
+ return True
1204
+ else:
1205
+ return False
1206
+
1207
+ def is_db(self):
1208
+ if self.sign() == 1:
1209
+ return True
1210
+ else:
1211
+ return False
1212
+
1213
+ def natural_relationship_from(self, lord):
1214
+ match lord.identity():
1215
+ case "Sun":
1216
+ return "E"
1217
+ case "Moon":
1218
+ return "E"
1219
+ case "Mars":
1220
+ return "E"
1221
+ case "Mercury":
1222
+ return "F"
1223
+ case "Jupiter":
1224
+ return "N"
1225
+ case "Venus":
1226
+ return "F"
1227
+
1228
+ def parashara_aspect_to(self, planet) -> float | str:
1229
+ """
1230
+ return the float of the precise parashara aspect between
1231
+ self and planet
1232
+
1233
+ this function does aspects for Saturn
1234
+ the other karakas have their own special aspects that are defined in their own classes
1235
+
1236
+ this is implemented according to the sutras from bphs as found in graha sutras by ew
1237
+ """
1238
+ if self.identity() == planet.identity():
1239
+ # a planet is not aspecting itself; so there is no value
1240
+ return ""
1241
+ if self.sign() == planet.sign():
1242
+ # Y for yuti, conjunction
1243
+ return "Y"
1244
+ diff = self.degrees_apart(planet.ecliptic_longitude())
1245
+ if diff <= 30 or diff >= 300:
1246
+ # within this orb planets do not aspect other planets
1247
+ return ""
1248
+ if diff > 270 and diff < 300:
1249
+ return (300 - diff)*2
1250
+ if diff > 240 and diff <= 270:
1251
+ return (diff - 240) + 30
1252
+ if diff > 180 and diff <= 240:
1253
+ return (300 - diff)/2
1254
+ if diff > 150 and diff <= 180:
1255
+ return (diff - 150)*2
1256
+ if diff > 120 and diff <= 150:
1257
+ return (150 - diff)
1258
+ if diff > 90 and diff <= 120:
1259
+ return ((120-diff)/2) + 30
1260
+ if diff > 60 and diff <= 90:
1261
+ return 60 - ((diff - 60)/2)
1262
+ if diff > 30 and diff <= 60:
1263
+ return (diff - 30)*2
1264
+
1265
+ def ucca(self):
1266
+ return (7,20)
1267
+
1268
+ def nica(self):
1269
+ return (1,20)
1270
+
1271
+ def dig_bala_cusp(self):
1272
+ return 7
1273
+
1274
+ class Rahu(Planet):
1275
+
1276
+ def __init__(self, context=EphContext(),master=None):
1277
+ super().__init__(swe.TRUE_NODE, context,master)
1278
+ self.planet_name = const.names[context.names_type]["planets"][10]
1279
+ self._id = "Rahu"
1280
+
1281
+ def glyph(self):
1282
+ return "☊"
1283
+
1284
+ def abbreviation(self) -> str:
1285
+ """
1286
+ two letter representation of Planet's name
1287
+ """
1288
+ return "Ra"
1289
+
1290
+ def type(self):
1291
+ return Rahu
1292
+
1293
+ def nature(self) -> str:
1294
+ """
1295
+ nature means benefic or malefic
1296
+ """
1297
+ return "Malefic"
1298
+
1299
+ def is_outer_planet(self):
1300
+ return False
1301
+
1302
+ def is_karaka(self):
1303
+ return False
1304
+
1305
+ def is_graha(self):
1306
+ return True
1307
+
1308
+
1309
+ class Ketu(Planet):
1310
+
1311
+ def __init__(self, context=EphContext(),master=None):
1312
+ super().__init__(swe.TRUE_NODE, context,master)
1313
+ self.planet_name = const.names[context.names_type]["planets"][11]
1314
+ self._id = "Ketu"
1315
+
1316
+ def number(self, system="vedic"):
1317
+ return 9
1318
+
1319
+ def glyph(self):
1320
+ return "☋"
1321
+
1322
+ def abbreviation(self) -> str:
1323
+ """
1324
+ two letter representation of Planet's name
1325
+ """
1326
+ return "Ke"
1327
+
1328
+ def type(self):
1329
+ return Ketu
1330
+
1331
+ def nature(self) -> str:
1332
+ """
1333
+ nature means benefic or malefic
1334
+ """
1335
+ return "Malefic"
1336
+
1337
+ def is_outer_planet(self):
1338
+ return False
1339
+
1340
+ def is_karaka(self):
1341
+ return False
1342
+
1343
+ def is_graha(self):
1344
+ return True
1345
+
1346
+
1347
+ class Uranus(Planet):
1348
+ def __init__(self, context=EphContext(),master=None):
1349
+ super().__init__(swe.URANUS, context,master)
1350
+ self._id = "Uranus"
1351
+
1352
+ def glyph(self):
1353
+ return "⛢"
1354
+
1355
+ def abbreviation(self) -> str:
1356
+ """
1357
+ two letter representation of Planet's name
1358
+ """
1359
+ return "Ur"
1360
+
1361
+ def type(self):
1362
+ return Uranus
1363
+
1364
+ def is_outer_planet(self):
1365
+ return True
1366
+
1367
+ def is_karaka(self):
1368
+ return False
1369
+
1370
+ def is_graha(self):
1371
+ return False
1372
+
1373
+ class Neptune(Planet):
1374
+
1375
+ def __init__(self, context=EphContext(),master=None):
1376
+ super().__init__(swe.NEPTUNE, context,master)
1377
+ self._id = "Neptune"
1378
+
1379
+ def glyph(self):
1380
+ return "♆"
1381
+
1382
+ def abbreviation(self) -> str:
1383
+ """
1384
+ two letter representation of Planet's name
1385
+ """
1386
+ return "Ne"
1387
+
1388
+ def type(self):
1389
+ return Neptune
1390
+
1391
+ def is_outer_planet(self):
1392
+ return True
1393
+
1394
+ def is_karaka(self):
1395
+ return False
1396
+
1397
+ def is_graha(self):
1398
+ return False
1399
+
1400
+
1401
+ class Pluto(Planet):
1402
+
1403
+ def __init__(self, context=EphContext(),master=None):
1404
+ super().__init__(swe.PLUTO, context,master)
1405
+ self._id = "Pluto"
1406
+
1407
+ def glyph(self):
1408
+ return "♇"
1409
+
1410
+ def abbreviation(self) -> str:
1411
+ """
1412
+ two letter representation of Planet's name
1413
+ """
1414
+ return "Pu"
1415
+
1416
+ def type(self):
1417
+ return Pluto
1418
+
1419
+ def is_outer_planet(self):
1420
+ return True
1421
+
1422
+ def is_karaka(self):
1423
+ return False
1424
+
1425
+ def is_graha(self):
1426
+ return False
1427
+
1428
+ class Earth(Planet):
1429
+ def __init__(self, context=EphContext(),master=None):
1430
+ super().__init__(swe.EARTH,context,master)
1431
+ self._id = "Earth"
1432
+
1433
+ def glyph(self):
1434
+ return "⨁"
1435
+
1436
+ def abbreviation(self) -> str:
1437
+ """
1438
+ two letter representation of Planet's name
1439
+ """
1440
+ return "Ea"
1441
+
1442
+ def type(self):
1443
+ return Earth
1444
+
1445
+ def nature(self) -> str:
1446
+ """
1447
+ nature means benefic or malefic
1448
+ """
1449
+ return "Benefic"
1450
+
1451
+ def is_outer_planet(self):
1452
+ return False
1453
+
1454
+ def is_karaka(self):
1455
+ return False
1456
+
1457
+ def is_graha(self):
1458
+ return False
1459
+
1460
+ class Chiron(Planet):
1461
+
1462
+ def __init__(self, context=EphContext(),master=None):
1463
+ self.planet_name = "Chiron"
1464
+ super().__init__(swe.CHIRON, context,master)
1465
+ self._id = "Chiron"
1466
+
1467
+ def type(self):
1468
+ return Chiron
1469
+
1470
+ def abbreviation(self) -> str:
1471
+ """
1472
+ two letter representation of Planet's name
1473
+ """
1474
+ return "Ch"
1475
+
1476
+ def is_outer_planet(self):
1477
+ return True
1478
+
1479
+ def is_karaka(self):
1480
+ return False
1481
+
1482
+ def is_graha(self):
1483
+ return False
1484
+
1485
+ natural_planets = {
1486
+ "Sun": Sun,
1487
+ "Earth": Earth,
1488
+ "Moon": Moon,
1489
+ "Mars": Mars,
1490
+ "Mercury": Mercury,
1491
+ "Jupiter": Jupiter,
1492
+ "Venus": Venus,
1493
+ "Saturn": Saturn,
1494
+ "Rahu": Rahu,
1495
+ "Ketu": Ketu,
1496
+ "Uranus": Uranus,
1497
+ "Neptune": Neptune,
1498
+ "Pluto": Pluto,
1499
+ "Chiron": Chiron,
1500
+ }
1501
+
1502
+ class Planets:
1503
+ """
1504
+ a group of all the Planet-s that are available
1505
+
1506
+ here is special terminology used in Planets:
1507
+
1508
+ "karakas" - means "producer" in Sanskrit; they cause things to exist
1509
+ these are the visible, embodied planets
1510
+ sun, moon, mercury, venus, mars, jupiter, saturn
1511
+
1512
+ "grahas" - means "seizer" in Sanskrit, forces of consciousness
1513
+ these are the karakas plus rahu and ketu, the north node and the south node
1514
+
1515
+ Planets().hd13() - these are the 13 planets used in Human Design, in an order
1516
+ that is appropriate for hd
1517
+
1518
+ if you look at the way Planets().karakas/grahas/hd13() are defined, you can see how it is possible to
1519
+ determine a particular order that works for you
1520
+
1521
+ Planets().(...) returns a dictionary of "Identity": Planet (Identity is the English name)
1522
+ >>> for hdplanet in Planets().hd13().values():
1523
+ print(hdplanet.name())
1524
+ and it will iterate through the hdplanets in their proper order
1525
+
1526
+ current print(Planets()) will print all the currently included Planet-s that applicable for that system
1527
+ i.e., it won't print Earth using tropical, though i may change that
1528
+ it will not print rahuketu if the chart is barycentric or heliocentric
1529
+
1530
+ all of these Planet-s will be in the same amsha; e.g., all natal planets, or all navamsha planets; they all stay together
1531
+
1532
+ to get a particular Planet:
1533
+ >>> chart.rashi().planets().sun()
1534
+ will return the Sun object
1535
+ >>> chart.rashi().planets()["Sun"]
1536
+ the same
1537
+ >>> chart.rashi().planets()[1]
1538
+ the same
1539
+ right now, if it is an integer, it will go in the natural vedic order, sun, moon, mars, mercury, jupiter, venus, saturn, rahu, ketu, uranus, neptune, pluto, chiron
1540
+ """
1541
+
1542
+ def __init__(self, context=EphContext()):
1543
+ """
1544
+ initialize Planets
1545
+ planets default is for vargas > 1, which will pass
1546
+ a list of Planet classes and this will make a container for them
1547
+ the varga.__init__ function will make a dictionary of planets
1548
+ and pass that dictionary into this class
1549
+ """
1550
+ self.timeJD = context.timeJD # the JulianDay class of this planet
1551
+ self.context = context
1552
+ self._amsha = self.context.amsha
1553
+ self.jd = self.timeJD.jd
1554
+ self.ayanamsa = context.ayanamsa
1555
+ self.system = context.sysflg
1556
+ self.sysflgstr = const.sysflgstr(context.sysflg)
1557
+ self._planets = self.init_Planets()
1558
+ self.set_attributes()
1559
+ from .nakshatras import Nakshatras
1560
+ self._nakshatras = Nakshatras(self,self.context)
1561
+
1562
+ def __iter__(self):
1563
+ return iter(self._planets.values())
1564
+
1565
+ def __getitem__(self,n):
1566
+ """
1567
+ self._planets (i.e., "self") is a dictionary of "Sun": Sun
1568
+
1569
+ if n is int, treat this as the natural number of the planet
1570
+
1571
+ returns a Planet class
1572
+ """
1573
+ if isinstance(n, int):
1574
+ # if n is an integer, treat is like the planet's natrual vedic number
1575
+ for planet in self._planets.values():
1576
+ if planet.number() == n:
1577
+ return planet
1578
+ return self._planets[n]
1579
+
1580
+ def planets(self):
1581
+ return self._planets
1582
+
1583
+ def items(self):
1584
+ return self._planets.items()
1585
+
1586
+ def karakas(self):
1587
+ return {"Sun": self.sun(),
1588
+ "Moon": self.moon(),
1589
+ "Mars": self.mars(),
1590
+ "Mercury": self.mercury(),
1591
+ "Jupiter": self.jupiter(),
1592
+ "Venus": self.venus(),
1593
+ "Saturn": self.saturn()
1594
+ }
1595
+
1596
+ def grahas(self):
1597
+ return {"Sun": self.sun(),
1598
+ "Moon": self.moon(),
1599
+ "Mars": self.mars(),
1600
+ "Mercury": self.mercury(),
1601
+ "Jupiter": self.jupiter(),
1602
+ "Venus": self.venus(),
1603
+ "Saturn": self.saturn(),
1604
+ "Rahu": self.rahu(),
1605
+ "Ketu": self.ketu()
1606
+ }
1607
+
1608
+ def hd13(self):
1609
+ return {"Sun": self.sun(),
1610
+ "Earth": self.earth(),
1611
+ "Moon": self.moon(),
1612
+ "Rahu": self.rahu(),
1613
+ "Ketu": self.ketu(),
1614
+ "Mercury": self.mercury(),
1615
+ "Venus": self.venus(),
1616
+ "Mars": self.mars(),
1617
+ "Jupiter": self.jupiter(),
1618
+ "Saturn": self.saturn(),
1619
+ "Uranus": self.uranus(),
1620
+ "Neptune": self.neptune(),
1621
+ "Pluto": self.pluto()
1622
+ }
1623
+
1624
+
1625
+ def init_Planets(self):
1626
+ ret = {}
1627
+
1628
+ # chiron can only be computed in a certain time frame
1629
+ if self.timeJD.jd < 1967601.5 or self.timeJD.jd > 3419437.5:
1630
+ if "Chiron" in natural_planets.keys():
1631
+ natural_planets.pop("Chiron")
1632
+ # swe can only compute Chiron between these two days
1633
+ # so if it is outside this range, get rid of Chiron
1634
+
1635
+ # # add Earth if using barycentric or heliocentric
1636
+ # if self.system == const.BARY or self.system == const.HELIO:
1637
+ # # add Earth to the planet_dict["planets"], after Pluto and before Chiron
1638
+ # natural_planets["Earth"] = Earth
1639
+
1640
+ for planet,constructor in natural_planets.items():
1641
+ ret[planet] = constructor(self.context,self)
1642
+
1643
+ return ret
1644
+
1645
+ def set_attributes(self):
1646
+ """
1647
+ there is some information i want each Planet to know, but that I have to use
1648
+ the other Planet-s to calculate first. so we init_Planets() above,
1649
+ then we can set_attributes() in __init__(), e.g., dignity
1650
+ """
1651
+ # moons nature
1652
+ moon_nature = "Benefic" if self.sun().degrees_apart(self.moon().ecliptic_longitude()) <= 180 else "Malefic"
1653
+ self.moon().set_attribute(("nature",moon_nature))
1654
+
1655
+
1656
+
1657
+ def nakshatras(self) -> Nakshatras:
1658
+ return self._nakshatras
1659
+
1660
+ def _dignities(self, temp_planets=None) -> [str]:
1661
+ """
1662
+ this method is superceded by Varga.dignities()
1663
+ Varga.dignities() calls Planet._dignities() according to the options
1664
+ in Varga.context, so you use the option EphContext(rashi_temporary_friends=True/False; default is True)
1665
+
1666
+ return a list of dignities in the natural order
1667
+ Sun, Moon, Mars, Mercury, Jupiter, Venus, Saturn
1668
+
1669
+ dignity is a combination of natural and temporary relationship
1670
+ we can use the temporary relationship from the varga itself, or from the rashi chart
1671
+
1672
+ if Planets is in a varga and temp_planets=None, then it will use temporary relationships based on that varga
1673
+ so if, for instance, you want to determine dignity in the Navamsha based on temporary friends in the Rashi
1674
+ you must past d9Planets.dignites(temp_planets=d1Planets)
1675
+ """
1676
+ if temp_planets == None:
1677
+ temp_planets = self
1678
+ # else: temp_planets are the planets from the rashi chart
1679
+ dignities = []
1680
+ for planet in self.karakas().values():
1681
+ # _dignity() takes two arguments: 1) itself in the rashi chart or this varga, depending on the options
1682
+ # 2) its lord in rashi or in this varga, depending on the option
1683
+ # set with EphContext.rashi_temporary_friends True or False
1684
+ dignities.append(planet._get_dignity(temp_planets.karakas()[planet.identity()],temp_planets.karakas()[planet.lord()]))
1685
+ # Planet._get_dignity sets Planet.attributes["dignity"], but we may also want to have dignities for Rahu and Ketu
1686
+ # so we set them here
1687
+ self.rahu().set_attribute(("dignity",self.planets()[self.rahu().lord()].dignity()))
1688
+ self.ketu().set_attribute(("dignity",self.planets()[self.ketu().lord()].dignity()))
1689
+ return dignities
1690
+
1691
+
1692
+ def parashara_aspects(self):
1693
+ """
1694
+ return a list of lists, each inner list being a row
1695
+ the first list is sun aspecting sun through ketu in order, etc.
1696
+ """
1697
+ ret = []
1698
+
1699
+ for aspecting in self.karakas().values():
1700
+ this_row = []
1701
+ for aspected in self.grahas().values():
1702
+ value = aspecting.parashara_aspect_to(aspected)
1703
+ this_row.append(int(round(value,0)) if isinstance(value,float) else value)
1704
+ ret.append(this_row)
1705
+
1706
+ return ret
1707
+
1708
+ def parashara_aspects_cusps(self, cusps):
1709
+ """
1710
+ return a list of lists, each inner list being a row
1711
+ the first list is sun aspecting sun through ketu in order, etc.
1712
+ """
1713
+ ret = []
1714
+
1715
+ for aspecting in self.karakas().values():
1716
+ this_row = []
1717
+ for aspected in cusps:
1718
+ value = aspecting.parashara_aspect_to(aspected)
1719
+ this_row.append(int(round(value,0)) if isinstance(value,float) else value)
1720
+ ret.append(this_row)
1721
+
1722
+ return ret
1723
+
1724
+ def jaimini_karakas(self):
1725
+ """
1726
+ -> [Self]
1727
+ return a list of Planet classes where the first element is the ak, the second the amk, etc.
1728
+
1729
+ fixed so that it will calculate these always based on their positions in the rashi chart
1730
+ """
1731
+ # we need to sort according to real in sign longitude
1732
+ longs = {}
1733
+ for karaka in self.karakas().values():
1734
+ # the longitude is the key, the Planet the value
1735
+ # the following doesnt work if two planets have the same longitude!
1736
+ # longs[karaka.in_sign_longitude()] = karaka
1737
+ # below is better, but still, what if two planets have same longitude? doesnt work then
1738
+ longs[karaka] = karaka.real_in_sign_longitude()
1739
+ ret = []
1740
+ # for long in sorted(longs.values())
1741
+ # sorted from least in sign longitude to to most
1742
+ # sorted returns a list of Planet classes
1743
+ karakas_reverse = {k: v for k, v in sorted(longs.items(), key=lambda item: item[1])}
1744
+ #karakas_reverse = sorted(longs.items())
1745
+ # karakas_reverse is a list of tuples (Planet,in_sign_longitude)
1746
+ #ret = [karaka[0] for karaka in karakas_reverse]
1747
+ # sorted() gives from least to most, but karakas are from most to least
1748
+ return list(karakas_reverse.__reversed__())
1749
+
1750
+ def is_moon_benefic(self):
1751
+ return self.sun().degrees_apart(self.moon().ecliptic_longitude()) <= 180
1752
+
1753
+ def is_moon_malefic(self):
1754
+ return self.sun().degrees_apart(self.moon().ecliptic_longitude()) > 180
1755
+
1756
+ def sun(self):
1757
+ return self._planets["Sun"]
1758
+
1759
+ def moon(self):
1760
+ return self._planets["Moon"]
1761
+
1762
+ def mars(self):
1763
+ return self._planets["Mars"]
1764
+
1765
+ def mercury(self):
1766
+ return self._planets["Mercury"]
1767
+
1768
+ def jupiter(self):
1769
+ return self._planets["Jupiter"]
1770
+
1771
+ def venus(self):
1772
+ return self._planets["Venus"]
1773
+
1774
+ def saturn(self):
1775
+ return self._planets["Saturn"]
1776
+
1777
+ def rahu(self):
1778
+ return self._planets["Rahu"]
1779
+
1780
+ def ketu(self):
1781
+ return self._planets["Ketu"]
1782
+
1783
+ def uranus(self):
1784
+ return self._planets["Uranus"]
1785
+
1786
+ def neptune(self):
1787
+ return self._planets["Neptune"]
1788
+
1789
+ def pluto(self):
1790
+ return self._planets["Pluto"]
1791
+
1792
+ def chiron(self):
1793
+ return self._planets["Chiron"]
1794
+
1795
+ def earth(self):
1796
+ return self._planets["Earth"]
1797
+
1798
+ def grahas_within_one_degree(self):
1799
+ """
1800
+ find all the grahas in Planets that are within one degree of each other
1801
+ """
1802
+ grahas = []
1803
+ for graha_chosen in self.grahas().values():
1804
+ for graha_line in self.grahas().values():
1805
+ if graha_chosen == graha_line:
1806
+ continue
1807
+ if abs(graha_chosen.amsha_longitude()-graha_line.amsha_longitude()) < 1:
1808
+ grahas.append((graha_chosen,graha_line))
1809
+ return grahas
1810
+
1811
+
1812
+ def __str__(self):
1813
+ if self.context.print_nakshatras:
1814
+ return self.planets_with_nakshatras()
1815
+ else:
1816
+ return self.planets_complete_information()
1817
+
1818
+ def planets_with_nakshatras(self):
1819
+ """
1820
+ return a PrettyTable string with coordinates for all planets on julianday
1821
+ using sysflag coordinates
1822
+ """
1823
+ output = PrettyTable()
1824
+ output.field_names = [
1825
+ "Planet",
1826
+ "Longitude",
1827
+ "Nakshatra",
1828
+ "Elapsed",
1829
+ "Speed",
1830
+ "Latitude",
1831
+ "Latitude Speed",
1832
+ "Distance",
1833
+ "Dist. Speed",
1834
+ "Constellation"
1835
+ ]
1836
+ output.align["Planet"] = "l"
1837
+ output.align["Longitude"] = "l"
1838
+ output.align["Nakshatra"] = "r"
1839
+ output.align["Elapsed"] = "r"
1840
+ output.align["Speed"] = "r"
1841
+ output.align["Latitude"] = "r"
1842
+ output.align["Latitude Speed"] = "r"
1843
+ output.align["Distance"] = "r"
1844
+ output.align["Dist. Speed"] = "r"
1845
+ output.align["Constellation"] = "r"
1846
+
1847
+ for p in self._planets.values():
1848
+ # dont print earth unless it is heliocentric or barycentric
1849
+ if isinstance(p, Earth) and not (
1850
+ self.system == const.HELIO or self.system == const.BARY
1851
+ ):
1852
+ continue
1853
+ # dont print rahuketu if it is heliocentric or barycentric
1854
+ if (isinstance(p, Rahu) or isinstance(p, Ketu)) and (
1855
+ self.system == const.HELIO or self.system == const.BARY
1856
+ ):
1857
+ continue
1858
+ # dont print the Sun when printing heliocentric coordinates
1859
+ if isinstance(p, Sun) and self.system == const.HELIO:
1860
+ continue
1861
+ if not self.context.print_outer_planets and p.is_outer_planet():
1862
+ continue
1863
+ output.add_row(p.table_row())
1864
+
1865
+ ret = output.get_string(
1866
+ fields=[
1867
+ "Planet",
1868
+ "Longitude",
1869
+ "Speed",
1870
+ "Nakshatra",
1871
+ "Elapsed",
1872
+ "Latitude",
1873
+ "Constellation"
1874
+ ]
1875
+ )
1876
+
1877
+ return self.mkheader() + ret
1878
+
1879
+ def planets_complete_information(self):
1880
+ """
1881
+ return a PrettyTable string with coordinates for all planets on julianday
1882
+ using sysflag coordinates
1883
+ """
1884
+ output = PrettyTable()
1885
+ output.field_names = [
1886
+ "Planet",
1887
+ "Longitude",
1888
+ "Speed",
1889
+ "Latitude",
1890
+ "Latitude Speed",
1891
+ "Distance",
1892
+ "Dist. Speed",
1893
+ "Constellation"
1894
+ ]
1895
+ output.align["Planet"] = "l"
1896
+ output.align["Longitude"] = "l"
1897
+ output.align["Speed"] = "r"
1898
+ output.align["Latitude"] = "r"
1899
+ output.align["Latitude Speed"] = "r"
1900
+ output.align["Distance"] = "r"
1901
+ output.align["Dist. Speed"] = "r"
1902
+ output.align["Constellation"] = "r"
1903
+
1904
+ for p in self._planets.values():
1905
+ # dont print earth unless it is heliocentric or barycentric
1906
+ if isinstance(p, Earth) and not (
1907
+ self.system == const.HELIO or self.system == const.BARY
1908
+ ):
1909
+ continue
1910
+ # dont print rahuketu if it is heliocentric or barycentric
1911
+ if (isinstance(p, Rahu) or isinstance(p, Ketu)) and (
1912
+ self.system == const.HELIO or self.system == const.BARY
1913
+ ):
1914
+ continue
1915
+ # dont print the Sun when printing heliocentric coordinates
1916
+ if isinstance(p, Sun) and self.system == const.HELIO:
1917
+ continue
1918
+ if not self.context.print_outer_planets and p.is_outer_planet():
1919
+ continue
1920
+ output.add_row(p.table_row()[:2]+p.table_row()[4:])
1921
+
1922
+ ret = output.get_string(
1923
+ fields=[
1924
+ "Planet",
1925
+ "Longitude",
1926
+ "Speed",
1927
+ "Latitude",
1928
+ "Latitude Speed",
1929
+ "Distance",
1930
+ "Dist. Speed",
1931
+ "Constellation"
1932
+ ]
1933
+ )
1934
+
1935
+ return self.mkheader() + ret
1936
+
1937
+ def __repr__(self):
1938
+ return self.planets_complete_information()
1939
+
1940
+ def hd_planets(self):
1941
+ definition = self.hd_planets_definition()
1942
+ state = self.hd_planets_state()
1943
+ return "Human Design Planets\n" + self.mkheader() + definition + "\n" + state
1944
+
1945
+ def gates(self, chiron=True):
1946
+ """
1947
+ return a list of the float of each Planet.gate()
1948
+ if chiron is False, dont include his gate activation
1949
+ this is for determining defined gates, because chiron does not activate a gate
1950
+ """
1951
+ planets = list(self.hd13().values())
1952
+ if chiron:
1953
+ planets.append(self.chiron())
1954
+ return [planet.hd().gate() for planet in planets]
1955
+
1956
+ def mkheader(self):
1957
+ header = f"{self.sysflgstr} coordinates\n"
1958
+ header += f"{const.circle_name(self.context.circle)}\n"
1959
+ if self.system == swe.FLG_SIDEREAL:
1960
+ # for sidereal signs we actually use swisseph 36
1961
+ # dhruva equatorial is only for nakshatras
1962
+ if self.ayanamsa == 98:
1963
+ header += f"{const.ayanamsa_name(36)} ayanamsa for signs\n"
1964
+ header += f"{const.ayanamsa_name(98)} ayanamsa for nakshatras\n"
1965
+ else:
1966
+ header += f"{const.ayanamsa_name(self.ayanamsa)} ayanamsa\n"
1967
+ elif self.system == (swe.FLG_SIDEREAL | swe.FLG_TOPOCTR):
1968
+ if self.ayanamsa == 98:
1969
+ self.ayanamsa = 36
1970
+ header += f"{self.context.location}\n"
1971
+ header += f"{const.ayanamsa_name(self.ayanamsa)} ayanamsa\n"
1972
+ else:
1973
+ header += f"{const.ayanamsa_name(self.ayanamsa)} ayanamsa\n"
1974
+ if self.system == swe.FLG_TOPOCTR:
1975
+ header += f"{self.context.location}\n"
1976
+ header += f"{self.timeJD}\n"
1977
+ return header
1978
+
1979
+ def hd_planets_definition(self) -> str:
1980
+ output = PrettyTable()
1981
+ output.field_names = [
1982
+ "Planet",
1983
+ "Longitude",
1984
+ "Gate",
1985
+ "Line",
1986
+ "Color",
1987
+ "Tone",
1988
+ "Base",
1989
+ "Speed",
1990
+ "Sign"
1991
+ ]
1992
+ output.align["Planet"] = "l"
1993
+ output.align["Longitude"] = "l"
1994
+ output.align["Gate"] = "r"
1995
+ output.align["Line"] = "r"
1996
+ output.align["Color"] = "r"
1997
+ output.align["Tone"] = "r"
1998
+ output.align["Base"] = "r"
1999
+ output.align["Speed"] = "r"
2000
+ output.align["Sign"] = "r"
2001
+
2002
+ for planet in self:
2003
+ output.add_row([planet.name()] + planet.hd().row_definition() + [planet.speed()] + [planet.signize()])
2004
+
2005
+ ret = output.get_string(
2006
+ fields=[
2007
+ "Planet",
2008
+ "Longitude",
2009
+ "Gate",
2010
+ "Line",
2011
+ "Color",
2012
+ "Tone",
2013
+ "Base",
2014
+ "Speed",
2015
+ "Sign"
2016
+ ]
2017
+ )
2018
+ return ret
2019
+
2020
+ def hd_planets_state(self) -> str:
2021
+ output = PrettyTable()
2022
+ output.field_names = [
2023
+ "Planet",
2024
+ "Longitude",
2025
+ "Gate Elapsed",
2026
+ "Line Elapsed",
2027
+ "Color Elapsed",
2028
+ "Tone Elapsed",
2029
+ "Base Elapsed",
2030
+ "Speed"
2031
+ ]
2032
+ output.align["Planet"] = "l"
2033
+ output.align["Longitude"] = "l"
2034
+ output.align["Gate Elapsed"] = "r"
2035
+ output.align["Line Elapsed"] = "r"
2036
+ output.align["Color Elapsed"] = "r"
2037
+ output.align["Tone Elapsed"] = "r"
2038
+ output.align["Base Elapsed"] = "r"
2039
+ output.align["Speed"] = "r"
2040
+
2041
+ for planet in self:
2042
+ output.add_row([planet.name()] + planet.hd().row_state() + [planet.speed()])
2043
+
2044
+ ret = output.get_string(
2045
+ fields=[
2046
+ "Planet",
2047
+ "Longitude",
2048
+ "Gate Elapsed",
2049
+ "Line Elapsed",
2050
+ "Color Elapsed",
2051
+ "Tone Elapsed",
2052
+ "Base Elapsed",
2053
+ "Speed",
2054
+ ]
2055
+ )
2056
+
2057
+ return ret
2058
+
2059
+