kerykeion 4.9.1__py3-none-any.whl → 4.10.1__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.

Potentially problematic release.


This version of kerykeion might be problematic. Click here for more details.

kerykeion/__init__.py CHANGED
@@ -13,7 +13,7 @@
13
13
  </a>
14
14
  <a href="https://pypi.org/project/kerykeion" target="_blank">
15
15
  <img src="https://visitor-badge.laobi.icu/badge?page_id=g-battaglia.kerykeion" alt="visitors"/>
16
- </a>
16
+ </a>
17
17
  <a href="https://pypi.org/project/kerykeion" target="_blank">
18
18
  <img src="https://img.shields.io/pypi/v/kerykeion?label=pypi%20package" alt="Package version">
19
19
  </a>
@@ -102,7 +102,7 @@ kanye = AstrologicalSubject(
102
102
  The difference is that you have to pass the longitude, latitude and the timezone string, instead of the city and nation.
103
103
  If you omit the nation, it will be set to "GB" by default, but the value is not used for calculations. It's better to set it to the correct value though.
104
104
 
105
- ## Generate a SVG Chart:
105
+ ## Generate a SVG Chart
106
106
 
107
107
  ```python
108
108
  from kerykeion import AstrologicalSubject, KerykeionChartSVG
@@ -141,7 +141,7 @@ report.print_report()
141
141
 
142
142
  Returns:
143
143
 
144
- ```
144
+ ```bash
145
145
  +- Kerykeion report for Kanye -+
146
146
  +----------+------+-------------+-----------+----------+
147
147
  | Date | Time | Location | Longitude | Latitude |
@@ -187,7 +187,7 @@ Returns:
187
187
  And if you want to export it to a file:
188
188
 
189
189
  ```bash
190
- $ python3 your_script_name.py > file.txt
190
+ python3 your_script_name.py > file.txt
191
191
  ```
192
192
 
193
193
  ## Other exeples of possibles usecase
@@ -209,6 +209,14 @@ print(aspect_list[0])
209
209
 
210
210
  ```
211
211
 
212
+ ## Ayanamsa (Sidereal Modes)
213
+
214
+ You can set the zodiac type and the sidereal mode in the AstrologicalSubject class:
215
+
216
+ ```python
217
+ johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", zodiac_type="Sidereal", sidereal_mode="LAHIRI")
218
+ ```
219
+
212
220
  ## Documentation
213
221
 
214
222
  Most of the functions and the classes are self documented by the types and have docstrings.
@@ -231,8 +239,7 @@ To understand how this impacts your use of the software, please see the [LICENSE
231
239
  If you have questions, you can reach out to me at my [email](mailto:battaglia.giacomo@yahoo.it?subject=Kerykeion) address.
232
240
  As a rule of thumb, if you are using this library in a project, you should open source the code of the project with a compatible license.
233
241
 
234
- You can implement the logic of kerkeion in your project and also keep it closed source by using a third party API, like the [AstrologerAPI](https://rapidapi.com/gbattaglia/api/astrologer/). The AstrologerAPI is AGPL-3.0 compliant. Subscribing to the API is also, currently, the best way to support the project.
235
-
242
+ You can implement the logic of kerykeion in your project and also keep it closed source by using a third party API, like the [AstrologerAPI](https://rapidapi.com/gbattaglia/api/astrologer/). The AstrologerAPI is AGPL-3.0 compliant. Subscribing to the API is also, currently, the best way to support the project.
236
243
  """
237
244
 
238
245
  # Local
@@ -15,7 +15,8 @@ from kerykeion.kr_types import (
15
15
  AstrologicalSubjectModel,
16
16
  LunarPhaseModel,
17
17
  KerykeionPointModel,
18
- PointType
18
+ PointType,
19
+ SiderealMode
19
20
  )
20
21
  from kerykeion.utilities import (
21
22
  get_number_from_name,
@@ -25,9 +26,10 @@ from kerykeion.utilities import (
25
26
  get_moon_phase_name_from_phase_int,
26
27
  )
27
28
  from pathlib import Path
28
- from typing import Union
29
+ from typing import Union, get_args
29
30
 
30
31
  DEFAULT_GEONAMES_USERNAME = "century.boy"
32
+ DEFAULT_SIDEREAL_MODE = "FAGAN_BRADLEY"
31
33
 
32
34
 
33
35
  class AstrologicalSubject:
@@ -59,6 +61,10 @@ class AstrologicalSubject:
59
61
  _ Defaults to None.
60
62
  - disable_chiron (bool, optional): Disables the calculation of Chiron. Defaults to False.
61
63
  Chiron calculation can create some issues with the Swiss Ephemeris when the date is too far in the past.
64
+ - sidereal_mode (SiderealMode, optional): Also known as Ayanamsa.
65
+ The mode to use for the sidereal zodiac, according to the Swiss Ephemeris.
66
+ Defaults to "FAGAN_BRADLEY".
67
+ Available modes are visible in the SiderealMode Literal.
62
68
  """
63
69
 
64
70
  # Defined by the user
@@ -77,6 +83,7 @@ class AstrologicalSubject:
77
83
  geonames_username: str
78
84
  online: bool
79
85
  zodiac_type: ZodiacType
86
+ sidereal_mode: SiderealMode
80
87
 
81
88
  # Generated internally
82
89
  city_data: dict[str, str]
@@ -140,16 +147,16 @@ class AstrologicalSubject:
140
147
  zodiac_type: ZodiacType = "Tropic",
141
148
  online: bool = True,
142
149
  utc_datetime: Union[datetime, None] = None,
143
- disable_chiron: bool = False
150
+ disable_chiron: bool = False,
151
+ sidereal_mode: Union[SiderealMode, None] = None
144
152
  ) -> None:
145
153
  logging.debug("Starting Kerykeion")
146
154
 
147
155
  # We set the swisseph path to the current directory
148
- swe.set_ephe_path(
149
- str(
150
- Path(__file__).parent.absolute() / "sweph"
151
- )
152
- )
156
+ swe.set_ephe_path(str(Path(__file__).parent.absolute() / "sweph"))
157
+
158
+ # Flags for the Swiss Ephemeris
159
+ self._iflag = swe.FLG_SWIEPH + swe.FLG_SPEED
153
160
 
154
161
  self.name = name
155
162
  self.year = year
@@ -168,6 +175,29 @@ class AstrologicalSubject:
168
175
  self.geonames_username = geonames_username
169
176
  self.utc_datetime = utc_datetime
170
177
  self.disable_chiron = disable_chiron
178
+ self.sidereal_mode = sidereal_mode
179
+
180
+ # Zodiac Type and Sidereal mode checks and setup --->
181
+ if zodiac_type and not zodiac_type in get_args(ZodiacType):
182
+ raise KerykeionException(f"\n* ERROR: '{zodiac_type}' is NOT a valid zodiac type! Available types are: *" + "\n" + str(get_args(ZodiacType)))
183
+
184
+ if self.sidereal_mode and self.zodiac_type == "Tropic":
185
+ raise KerykeionException("You can't set a sidereal mode with a Tropic zodiac type!")
186
+
187
+ if self.zodiac_type == "Sidereal" and not self.sidereal_mode:
188
+ self.sidereal_mode = DEFAULT_SIDEREAL_MODE
189
+ logging.info("No sidereal mode set, using default FAGAN_BRADLEY")
190
+
191
+ if self.zodiac_type == "Sidereal":
192
+ # Check if the sidereal mode is valid
193
+ if not self.sidereal_mode in get_args(SiderealMode):
194
+ raise KerykeionException(f"\n* ERROR: '{self.sidereal_mode}' is NOT a valid sidereal mode! Available modes are: *" + "\n" + str(get_args(SiderealMode)))
195
+
196
+ self._iflag += swe.FLG_SIDEREAL
197
+ mode = "SIDM_" + self.sidereal_mode
198
+ swe.set_sid_mode(getattr(swe, mode))
199
+ logging.debug(f"Using sidereal mode: {mode}")
200
+ # <--- Zodiac Type and Sidereal mode checks and setup
171
201
 
172
202
  # This message is set to encourage the user to set a custom geonames username
173
203
  if geonames_username is None and online:
@@ -207,9 +237,7 @@ class AstrologicalSubject:
207
237
  logging.info("No longitude specified, using London as default")
208
238
 
209
239
  if (not self.online) and (not tz_str):
210
- raise KerykeionException(
211
- "You need to set the coordinates and timezone if you want to use the offline mode!"
212
- )
240
+ raise KerykeionException("You need to set the coordinates and timezone if you want to use the offline mode!")
213
241
 
214
242
  self._check_if_poles()
215
243
 
@@ -328,12 +356,9 @@ class AstrologicalSubject:
328
356
  self.houses_degree_ut = swe.houses(
329
357
  tjdut=self.julian_day, lat=self.lat, lon=self.lng, hsys=str.encode('P')
330
358
  )[0]
331
- else:
332
- raise KerykeionException("Zodiac type not recognized! Please use 'Tropic' or 'Sidereal'")
333
359
 
334
360
  point_type: PointType = "House"
335
- # creates the list of the house in 360°
336
- self.houses_degree_ut = swe.houses(self.julian_day, self.lat, self.lng)[0]
361
+
337
362
  # stores the house in singular dictionaries.
338
363
  self.first_house = calculate_position(self.houses_degree_ut[0], "First_House", point_type=point_type)
339
364
  self.second_house = calculate_position(self.houses_degree_ut[1], "Second_House", point_type=point_type)
@@ -365,12 +390,6 @@ class AstrologicalSubject:
365
390
 
366
391
  def _planets_degrees_lister(self):
367
392
  """Sidereal or tropic mode."""
368
- self._iflag = swe.FLG_SWIEPH + swe.FLG_SPEED
369
-
370
- if self.zodiac_type == "Sidereal":
371
- self._iflag += swe.FLG_SIDEREAL
372
- mode = "SIDM_FAGAN_BRADLEY"
373
- swe.set_sid_mode(getattr(swe, mode))
374
393
 
375
394
  # Calculates the position of the planets and stores it in a list.
376
395
  sun_deg = swe.calc(self.julian_day, 0, self._iflag)[0][0]
@@ -569,7 +588,7 @@ class AstrologicalSubject:
569
588
  self.lat = -66.0
570
589
  logging.info("Polar circle override for houses, using -66 degrees")
571
590
 
572
- def json(self, dump=False, destination_folder: Union[str, None] = None) -> str:
591
+ def json(self, dump=False, destination_folder: Union[str, None] = None, indent: Union[int, None] = None) -> str:
573
592
  """
574
593
  Dumps the Kerykeion object to a json string foramt,
575
594
  if dump=True also dumps to file located in destination
@@ -577,7 +596,7 @@ class AstrologicalSubject:
577
596
  """
578
597
 
579
598
  KrData = AstrologicalSubjectModel(**self.__dict__)
580
- json_string = KrData.model_dump_json(exclude_none=True)
599
+ json_string = KrData.model_dump_json(exclude_none=True, indent=indent)
581
600
 
582
601
  if dump:
583
602
  if destination_folder:
@@ -620,3 +639,7 @@ if __name__ == "__main__":
620
639
 
621
640
  print('\n')
622
641
  print(johnny.chiron)
642
+
643
+ # With Sidereal Zodiac
644
+ johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", zodiac_type="Sidereal", sidereal_mode="LAHIRI")
645
+ print(johnny.json(dump=True, indent=2))
@@ -45,9 +45,9 @@ class KerykeionChartSVG:
45
45
  - first_obj: First kerykeion object
46
46
  - chart_type: Natal, ExternalNatal, Transit, Synastry (Default: Type="Natal").
47
47
  - second_obj: Second kerykeion object (Not required if type is Natal)
48
- - new_output_directory: Set the output directory (default: output_directory)
49
- - lang: language settings (default: "EN")
50
- - new_settings_file: Set the settings file (default: kr.config.json)
48
+ - new_output_directory: Set the output directory (default: home directory).
49
+ - new_settings_file: Set the settings file (default: kr.config.json).
50
+ In the settings file you can set the language, colors, planets, aspects, etc.
51
51
  """
52
52
 
53
53
  # Constants
@@ -218,7 +218,6 @@ class KerykeionChartSVG:
218
218
  self.t_houses_sign_graph.append(h["sign_num"])
219
219
 
220
220
  # screen size
221
-
222
221
  self.height = self._DEFAULT_HEIGHT
223
222
  if self.chart_type == "Synastry" or self.chart_type == "Transit":
224
223
  self.width = self._DEFAULT_FULL_WIDTH
@@ -1159,7 +1158,6 @@ class KerykeionChartSVG:
1159
1158
  svgHeight = "100%"
1160
1159
  svgWidth = "100%"
1161
1160
  rotate = "0"
1162
- translate = "0"
1163
1161
 
1164
1162
  # To increase the size of the chart, change the viewbox
1165
1163
  if self.chart_type == "Natal" or self.chart_type == "ExternalNatal":
@@ -1218,6 +1216,7 @@ class KerykeionChartSVG:
1218
1216
  td["svgHeight"] = str(svgHeight)
1219
1217
  td["viewbox"] = viewbox
1220
1218
 
1219
+ # Chart Title
1221
1220
  if self.chart_type == "Synastry":
1222
1221
  td["stringTitle"] = f"{self.user.name} {self.language_settings['and_word']} {self.t_user.name}"
1223
1222
 
@@ -1227,17 +1226,24 @@ class KerykeionChartSVG:
1227
1226
  else:
1228
1227
  td["stringTitle"] = self.user.name
1229
1228
 
1230
- # Tipo di carta
1229
+ # Chart Name
1231
1230
  if self.chart_type == "Synastry" or self.chart_type == "Transit":
1232
1231
  td["stringName"] = f"{self.user.name}:"
1233
1232
  else:
1234
1233
  td["stringName"] = f'{self.language_settings["info"]}:'
1235
1234
 
1236
- # bottom left
1237
- td["bottomLeft1"] = ""
1238
- td["bottomLeft2"] = ""
1239
- td["bottomLeft3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get("day", "Day")} {self.user.lunar_phase.get("moon_phase", "")}'
1240
- td["bottomLeft4"] = ""
1235
+ # Bottom Left Corner
1236
+ if self.chart_type == "Natal" or self.chart_type == "ExternalNatal" or self.chart_type == "Synastry":
1237
+ td["bottomLeft1"] = f"{self.user.zodiac_type if self.user.zodiac_type == 'Tropic' else self.user.zodiac_type + ' ' + self.user.sidereal_mode}"
1238
+ td["bottomLeft2"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.user.lunar_phase.moon_phase_name}'
1239
+ td["bottomLeft3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get("day", "Day")} {self.user.lunar_phase.get("moon_phase", "")}'
1240
+ td["bottomLeft4"] = ""
1241
+
1242
+ else:
1243
+ td["bottomLeft1"] = f"{self.user.zodiac_type if self.user.zodiac_type == 'Tropic' else self.user.zodiac_type + ' ' + self.user.sidereal_mode}"
1244
+ td["bottomLeft2"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.t_user.lunar_phase.moon_phase_name}'
1245
+ td["bottomLeft3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get("day", "Day")} {self.t_user.lunar_phase.get("moon_phase", "")}'
1246
+ td["bottomLeft4"] = ""
1241
1247
 
1242
1248
  # lunar phase
1243
1249
  deg = self.user.lunar_phase["degrees_between_s_m"]
@@ -1348,7 +1354,6 @@ class KerykeionChartSVG:
1348
1354
  # config
1349
1355
  td["cfgZoom"] = str(self.zoom)
1350
1356
  td["cfgRotate"] = rotate
1351
- td["cfgTranslate"] = translate
1352
1357
 
1353
1358
  # ---
1354
1359
  # Drawing Functions
@@ -1401,7 +1406,7 @@ class KerykeionChartSVG:
1401
1406
  if not (self.template):
1402
1407
  self.template = self.makeTemplate(minify)
1403
1408
 
1404
- self.chartname = self.output_directory / f"{self.user.name}{self.chart_type}Chart.svg"
1409
+ self.chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart.svg"
1405
1410
 
1406
1411
  with open(self.chartname, "w", encoding="utf-8", errors="ignore") as output_file:
1407
1412
  output_file.write(self.template)
@@ -1426,9 +1431,28 @@ if __name__ == "__main__":
1426
1431
 
1427
1432
  # Synastry Chart
1428
1433
  synastry_chart = KerykeionChartSVG(first, "Synastry", second)
1429
- synastry_chart.makeSVG(minify=True)
1434
+ synastry_chart.makeSVG()
1430
1435
 
1431
1436
  # Transits Chart
1432
1437
  transits_chart = KerykeionChartSVG(first, "Transit", second)
1433
- transits_chart.makeSVG(minify=True)
1434
-
1438
+ transits_chart.makeSVG()
1439
+
1440
+ # Sidereal Birth Chart (Lahiri)
1441
+ sidereal_subject = AstrologicalSubject("John Lennon Lahiri", 1940, 10, 9, 10, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="LAHIRI")
1442
+ sidereal_chart = KerykeionChartSVG(sidereal_subject)
1443
+ sidereal_chart.makeSVG()
1444
+
1445
+ # Sidereal Birth Chart (Fagan-Bradley)
1446
+ sidereal_subject = AstrologicalSubject("John Lennon Fagan-Bradley", 1940, 10, 9, 10, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="FAGAN_BRADLEY")
1447
+ sidereal_chart = KerykeionChartSVG(sidereal_subject)
1448
+ sidereal_chart.makeSVG()
1449
+
1450
+ # Sidereal Birth Chart (DeLuce)
1451
+ sidereal_subject = AstrologicalSubject("John Lennon DeLuce", 1940, 10, 9, 10, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="DELUCE")
1452
+ sidereal_chart = KerykeionChartSVG(sidereal_subject)
1453
+ sidereal_chart.makeSVG()
1454
+
1455
+ # Sidereal Birth Chart (J2000)
1456
+ sidereal_subject = AstrologicalSubject("John Lennon J2000", 1940, 10, 9, 10, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="J2000")
1457
+ sidereal_chart = KerykeionChartSVG(sidereal_subject)
1458
+ sidereal_chart.makeSVG()