kerykeion 4.1.0__tar.gz → 4.1.1__tar.gz

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.

Files changed (30) hide show
  1. {kerykeion-4.1.0 → kerykeion-4.1.1}/PKG-INFO +1 -1
  2. kerykeion-4.1.1/kerykeion/aspects/aspects_utils.py +185 -0
  3. kerykeion-4.1.1/kerykeion/aspects/natal_aspects.py +143 -0
  4. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/aspects/synastry_aspects.py +20 -13
  5. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/astrological_subject.py +47 -3
  6. {kerykeion-4.1.0 → kerykeion-4.1.1}/pyproject.toml +2 -2
  7. kerykeion-4.1.0/LICENSE +0 -661
  8. kerykeion-4.1.0/kerykeion/aspects/natal_aspects.py +0 -327
  9. {kerykeion-4.1.0 → kerykeion-4.1.1}/README.md +0 -0
  10. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/__init__.py +0 -0
  11. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/aspects/__init__.py +0 -0
  12. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/charts/__init__.py +0 -0
  13. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/charts/charts_utils.py +0 -0
  14. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/charts/kerykeion_chart_svg.py +0 -0
  15. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/charts/templates/chart.xml +0 -0
  16. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/fetch_geonames.py +0 -0
  17. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/kr_types/__init__.py +0 -0
  18. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/kr_types/chart_types.py +0 -0
  19. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/kr_types/kerykeion_exception.py +0 -0
  20. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/kr_types/kr_literals.py +0 -0
  21. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/kr_types/kr_models.py +0 -0
  22. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/kr_types/settings_models.py +0 -0
  23. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/relationship_score.py +0 -0
  24. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/report.py +0 -0
  25. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/settings/__init__.py +0 -0
  26. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/settings/kerykeion_settings.py +0 -0
  27. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/settings/kr.config.json +0 -0
  28. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/sweph/README.md +0 -0
  29. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/sweph/seas_18.se1 +0 -0
  30. {kerykeion-4.1.0 → kerykeion-4.1.1}/kerykeion/utilities.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kerykeion
3
- Version: 4.1.0
3
+ Version: 4.1.1
4
4
  Summary: A python library for astrology.
5
5
  Home-page: https://github.com/g-battaglia/kerykeion
6
6
  License: AGPL-3.0
@@ -0,0 +1,185 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ This is part of Kerykeion (C) 2023 Giacomo Battaglia
4
+ """
5
+ # TODO: Better documentation and unit tests
6
+
7
+ from swisseph import difdeg2n
8
+ from typing import Union
9
+
10
+
11
+ def get_aspect_from_two_points(aspects_settings: dict, point_one: Union[float, int], point_two: Union[float, int]):
12
+ """
13
+ Utility function.
14
+ It calculates the aspects between the 2 points.
15
+ Args: first point, second point.
16
+ """
17
+
18
+ distance = abs(difdeg2n(point_one, point_two))
19
+ diff = abs(point_one - point_two)
20
+
21
+ if int(distance) <= aspects_settings[0]["orb"]:
22
+ name = aspects_settings[0]["name"]
23
+ aspect_degrees = aspects_settings[0]["degree"]
24
+ color = aspects_settings[0]["color"]
25
+ verdict = True
26
+ aid = 0
27
+
28
+ elif (
29
+ (aspects_settings[1]["degree"] - aspects_settings[1]["orb"])
30
+ <= int(distance)
31
+ <= (aspects_settings[1]["degree"] + aspects_settings[1]["orb"])
32
+ ):
33
+ name = aspects_settings[1]["name"]
34
+ aspect_degrees = aspects_settings[1]["degree"]
35
+ color = aspects_settings[1]["color"]
36
+ verdict = True
37
+ aid = 1
38
+
39
+ elif (
40
+ (aspects_settings[2]["degree"] - aspects_settings[2]["orb"])
41
+ <= int(distance)
42
+ <= (aspects_settings[2]["degree"] + aspects_settings[2]["orb"])
43
+ ):
44
+ name = aspects_settings[2]["name"]
45
+ aspect_degrees = aspects_settings[2]["degree"]
46
+ color = aspects_settings[2]["color"]
47
+ verdict = True
48
+ aid = 2
49
+
50
+ elif (
51
+ (aspects_settings[3]["degree"] - aspects_settings[3]["orb"])
52
+ <= int(distance)
53
+ <= (aspects_settings[3]["degree"] + aspects_settings[3]["orb"])
54
+ ):
55
+ name = aspects_settings[3]["name"]
56
+ aspect_degrees = aspects_settings[3]["degree"]
57
+ color = aspects_settings[3]["color"]
58
+ verdict = True
59
+ aid = 3
60
+
61
+ elif (
62
+ (aspects_settings[4]["degree"] - aspects_settings[4]["orb"])
63
+ <= int(distance)
64
+ <= (aspects_settings[4]["degree"] + aspects_settings[4]["orb"])
65
+ ):
66
+ name = aspects_settings[4]["name"]
67
+ aspect_degrees = aspects_settings[4]["degree"]
68
+ color = aspects_settings[4]["color"]
69
+ verdict = True
70
+ aid = 4
71
+
72
+ elif (
73
+ (aspects_settings[5]["degree"] - aspects_settings[5]["orb"])
74
+ <= int(distance)
75
+ <= (aspects_settings[5]["degree"] + aspects_settings[5]["orb"])
76
+ ):
77
+ name = aspects_settings[5]["name"]
78
+ aspect_degrees = aspects_settings[5]["degree"]
79
+ color = aspects_settings[5]["color"]
80
+ verdict = True
81
+ aid = 5
82
+
83
+ elif (
84
+ (aspects_settings[6]["degree"] - aspects_settings[6]["orb"])
85
+ <= int(distance)
86
+ <= (aspects_settings[6]["degree"] + aspects_settings[6]["orb"])
87
+ ):
88
+ name = aspects_settings[6]["name"]
89
+ aspect_degrees = aspects_settings[6]["degree"]
90
+ color = aspects_settings[6]["color"]
91
+ verdict = True
92
+ aid = 6
93
+
94
+ elif (
95
+ (aspects_settings[7]["degree"] - aspects_settings[7]["orb"])
96
+ <= int(distance)
97
+ <= (aspects_settings[7]["degree"] + aspects_settings[7]["orb"])
98
+ ):
99
+ name = aspects_settings[7]["name"]
100
+ aspect_degrees = aspects_settings[7]["degree"]
101
+ color = aspects_settings[7]["color"]
102
+ verdict = True
103
+ aid = 7
104
+
105
+ elif (
106
+ (aspects_settings[8]["degree"] - aspects_settings[8]["orb"])
107
+ <= int(distance)
108
+ <= (aspects_settings[8]["degree"] + aspects_settings[8]["orb"])
109
+ ):
110
+ name = aspects_settings[8]["name"]
111
+ aspect_degrees = aspects_settings[8]["degree"]
112
+ color = aspects_settings[8]["color"]
113
+ verdict = True
114
+ aid = 8
115
+
116
+ elif (
117
+ (aspects_settings[9]["degree"] - aspects_settings[9]["orb"])
118
+ <= int(distance)
119
+ <= (aspects_settings[9]["degree"] + aspects_settings[9]["orb"])
120
+ ):
121
+ name = aspects_settings[9]["name"]
122
+ aspect_degrees = aspects_settings[9]["degree"]
123
+ color = aspects_settings[9]["color"]
124
+ verdict = True
125
+ aid = 9
126
+
127
+ elif (
128
+ (aspects_settings[10]["degree"] - aspects_settings[10]["orb"])
129
+ <= int(distance)
130
+ <= (aspects_settings[10]["degree"] + aspects_settings[10]["orb"])
131
+ ):
132
+ name = aspects_settings[10]["name"]
133
+ aspect_degrees = aspects_settings[10]["degree"]
134
+ color = aspects_settings[10]["color"]
135
+ verdict = True
136
+ aid = 10
137
+
138
+ else:
139
+ verdict = False
140
+ name = None
141
+ distance = 0
142
+ aspect_degrees = 0
143
+ color = None
144
+ aid = None
145
+
146
+ return (
147
+ verdict,
148
+ name,
149
+ distance - aspect_degrees,
150
+ aspect_degrees,
151
+ color,
152
+ aid,
153
+ diff,
154
+ )
155
+
156
+
157
+ def planet_id_decoder(planets_settings: dict, name: str):
158
+ """
159
+ Check if the name of the planet is the same in the settings and return
160
+ the correct id for the planet.
161
+ """
162
+ str_name = str(name)
163
+ for planet in planets_settings:
164
+ if planet["name"] == str_name:
165
+ result = planet["id"]
166
+ return result
167
+
168
+
169
+ def filter_by_settings(planets_settings: dict, init_point_list: list):
170
+ """
171
+ Creates a list of all the desired
172
+ points filtering by the settings.
173
+ """
174
+
175
+ set_points_name = []
176
+ for p in planets_settings:
177
+ if p["is_active"]:
178
+ set_points_name.append(p["name"])
179
+
180
+ point_list = []
181
+ for l in init_point_list:
182
+ if l["name"] in set_points_name:
183
+ point_list.append(l)
184
+
185
+ return point_list
@@ -0,0 +1,143 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ This is part of Kerykeion (C) 2023 Giacomo Battaglia
4
+ """
5
+
6
+ from pathlib import Path
7
+ from kerykeion import AstrologicalSubject
8
+ from logging import getLogger, basicConfig
9
+ from typing import Union
10
+ from kerykeion.settings.kerykeion_settings import get_settings
11
+ from dataclasses import dataclass
12
+ from kerykeion.aspects.aspects_utils import filter_by_settings, planet_id_decoder, get_aspect_from_two_points
13
+
14
+ logger = getLogger(__name__)
15
+ basicConfig(format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level="INFO")
16
+
17
+
18
+ @dataclass
19
+ class NatalAspects:
20
+ """
21
+ Generates an object with all the aspects of a birthcart.
22
+ """
23
+
24
+ user: AstrologicalSubject
25
+ new_settings_file: Union[Path, None] = None
26
+ _all_aspects: Union[list, None] = None
27
+ _relevant_aspects: Union[list, None] = None
28
+
29
+ def __post_init__(self):
30
+ settings = get_settings(self.new_settings_file)
31
+
32
+ self.init_point_list = self.user.planets_list + self.user.houses_list
33
+
34
+ self.planets_settings = settings["celestial_points"]
35
+ self.aspects_settings = settings["aspects"]
36
+ self.axes_orbit_settings = settings["general_settings"]["axes_orbit"]
37
+
38
+ @property
39
+ def all_aspects(self):
40
+ """
41
+ Return all the aspects of the points in the natal chart in a dictionary,
42
+ first all the individual aspects of each planet, second the aspects
43
+ without repetitions.
44
+ """
45
+
46
+ if self._all_aspects is not None:
47
+ return self._all_aspects
48
+
49
+ point_list = filter_by_settings(self.planets_settings, self.init_point_list)
50
+
51
+ self.all_aspects_list = []
52
+
53
+ for first in range(len(point_list)):
54
+ # Generates the aspects list without repetitions
55
+ for second in range(first + 1, len(point_list)):
56
+ verdict, name, orbit, aspect_degrees, color, aid, diff = get_aspect_from_two_points(
57
+ self.aspects_settings, point_list[first]["abs_pos"], point_list[second]["abs_pos"]
58
+ )
59
+
60
+ if verdict == True:
61
+ d_asp = {
62
+ "p1_name": point_list[first]["name"],
63
+ "p1_abs_pos": point_list[first]["abs_pos"],
64
+ "p2_name": point_list[second]["name"],
65
+ "p2_abs_pos": point_list[second]["abs_pos"],
66
+ "aspect": name,
67
+ "orbit": orbit,
68
+ "aspect_degrees": aspect_degrees,
69
+ "color": color,
70
+ "aid": aid,
71
+ "diff": diff,
72
+ "p1": planet_id_decoder(self.planets_settings, point_list[first]["name"]),
73
+ "p2": planet_id_decoder(
74
+ self.planets_settings,
75
+ point_list[second]["name"],
76
+ ),
77
+ }
78
+
79
+ self.all_aspects_list.append(d_asp)
80
+
81
+ return self.all_aspects_list
82
+
83
+ @property
84
+ def relevant_aspects(self):
85
+ """
86
+ Filters the aspects list with the desired points, in this case
87
+ the most important are hardcoded.
88
+ Set the list with set_points and creating a list with the names
89
+ or the numbers of the houses.
90
+ """
91
+
92
+ if self._relevant_aspects is not None:
93
+ logger.debug("Relevant aspects already calculated, returning cached value")
94
+ return self._relevant_aspects
95
+
96
+ logger.debug("Relevant aspects not already calculated, calculating now...")
97
+ self.all_aspects
98
+
99
+ aspects_filtered = []
100
+ for a in self.all_aspects_list:
101
+ if self.aspects_settings[a["aid"]]["is_active"] == True:
102
+ aspects_filtered.append(a)
103
+
104
+ axes_list = [
105
+ "First_House",
106
+ "Tenth_House",
107
+ "Seventh_House",
108
+ "Fourth_House",
109
+ ]
110
+ counter = 0
111
+
112
+ aspects_list_subtract = []
113
+ for a in aspects_filtered:
114
+ counter += 1
115
+ name_p1 = str(a["p1_name"])
116
+ name_p2 = str(a["p2_name"])
117
+
118
+ if name_p1 in axes_list:
119
+ if abs(a["orbit"]) >= self.axes_orbit_settings:
120
+ aspects_list_subtract.append(a)
121
+
122
+ elif name_p2 in axes_list:
123
+ if abs(a["orbit"]) >= self.axes_orbit_settings:
124
+ aspects_list_subtract.append(a)
125
+
126
+ self.aspects = [item for item in aspects_filtered if item not in aspects_list_subtract]
127
+
128
+ return self.aspects
129
+
130
+
131
+ if __name__ == "__main__":
132
+ basicConfig(level="DEBUG", force=True)
133
+ johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US")
134
+
135
+ # All aspects
136
+ aspects = NatalAspects(johnny)
137
+ print(aspects.all_aspects)
138
+
139
+ print("\n")
140
+
141
+ # Relevant aspects
142
+ aspects = NatalAspects(johnny)
143
+ print(aspects.relevant_aspects)
@@ -8,6 +8,8 @@ from pathlib import Path
8
8
  from typing import Union
9
9
 
10
10
  from kerykeion.aspects.natal_aspects import NatalAspects
11
+ from kerykeion.settings.kerykeion_settings import get_settings
12
+ from kerykeion.aspects.aspects_utils import filter_by_settings, planet_id_decoder, get_aspect_from_two_points
11
13
 
12
14
 
13
15
  class SynastryAspects(NatalAspects):
@@ -25,13 +27,18 @@ class SynastryAspects(NatalAspects):
25
27
  self.second_user = kr_object_two
26
28
 
27
29
  self.new_settings_file = new_settings_file
28
- self._parse_json_settings()
29
30
 
30
31
  self.first_init_point_list = self.first_user.planets_list + self.first_user.houses_list
31
32
  self.second_init_point_list = self.second_user.planets_list + self.second_user.houses_list
32
-
33
- self._all_aspects: list = None
34
- self._relevant_aspects: list = None
33
+
34
+ self._all_aspects: Union[list, None] = None
35
+ self._relevant_aspects: Union[list, None] = None
36
+
37
+ settings = get_settings(self.new_settings_file)
38
+
39
+ self.planets_settings = settings["celestial_points"]
40
+ self.aspects_settings = settings["aspects"]
41
+ self.axes_orbit_settings = settings["general_settings"]["axes_orbit"]
35
42
 
36
43
  @property
37
44
  def all_aspects(self):
@@ -40,22 +47,21 @@ class SynastryAspects(NatalAspects):
40
47
  first all the individual aspects of each planet, second the aspects
41
48
  whiteout repetitions.
42
49
  """
43
-
50
+
44
51
  if self._all_aspects is not None:
45
52
  return self._all_aspects
46
53
 
47
- f_1 = self._filter_by_settings(self.first_init_point_list)
48
- f_2 = self._filter_by_settings(self.second_init_point_list)
54
+ f_1 = filter_by_settings(self.planets_settings, self.first_init_point_list)
55
+
56
+ f_2 = filter_by_settings(self.planets_settings, self.second_init_point_list)
49
57
 
50
58
  self.all_aspects_list = []
51
59
 
52
60
  for first in range(len(f_1)):
53
61
  # Generates the aspects list whitout repetitions
54
62
  for second in range(len(f_2)):
55
- verdict, name, orbit, aspect_degrees, color, aid, diff = self.get_aspect_from_two_points(
56
- self.aspects_settings,
57
- f_1[first]["abs_pos"],
58
- f_2[second]["abs_pos"]
63
+ verdict, name, orbit, aspect_degrees, color, aid, diff = get_aspect_from_two_points(
64
+ self.aspects_settings, f_1[first]["abs_pos"], f_2[second]["abs_pos"]
59
65
  )
60
66
 
61
67
  if verdict == True:
@@ -70,8 +76,9 @@ class SynastryAspects(NatalAspects):
70
76
  "color": color,
71
77
  "aid": aid,
72
78
  "diff": diff,
73
- "p1": self._p_id_decoder(f_1[first]["name"]),
74
- "p2": self._p_id_decoder(
79
+ "p1": planet_id_decoder(self.planets_settings, f_1[first]["name"]),
80
+ "p2": planet_id_decoder(
81
+ self.planets_settings,
75
82
  f_2[second]["name"],
76
83
  ),
77
84
  }
@@ -145,7 +145,6 @@ class AstrologicalSubject:
145
145
  )
146
146
  )
147
147
 
148
-
149
148
  self.name = name
150
149
  self.year = year
151
150
  self.month = month
@@ -160,7 +159,8 @@ class AstrologicalSubject:
160
159
  self.zodiac_type = zodiac_type
161
160
  self.online = online
162
161
  self.json_dir = Path.home()
163
-
162
+ self.geonames_username = geonames_username
163
+
164
164
  # This message is set to encourage the user to set a custom geonames username
165
165
  if geonames_username is None and online:
166
166
  logger.info(
@@ -179,6 +179,7 @@ class AstrologicalSubject:
179
179
  "\n" + \
180
180
  "********"
181
181
  )
182
+
182
183
  self.geonames_username = DEFAULT_GEONAMES_USERNAME
183
184
 
184
185
  if not self.city:
@@ -263,7 +264,50 @@ class AstrologicalSubject:
263
264
  self.julian_day = float(swe.julday(self.utc.year, self.utc.month, self.utc.day, self.utc_time))
264
265
 
265
266
  def _houses(self) -> None:
266
- """Calculate positions and store them in dictionaries"""
267
+ """
268
+ Calculate positions and store them in dictionaries
269
+
270
+ https://www.astro.com/faq/fq_fh_owhouse_e.htm
271
+ https://github.com/jwmatthys/pd-swisseph/blob/master/swehouse.c#L685
272
+ hsys = letter code for house system;
273
+ A equal
274
+ E equal
275
+ B Alcabitius
276
+ C Campanus
277
+ D equal (MC)
278
+ F Carter "Poli-Equatorial"
279
+ G 36 Gauquelin sectors
280
+ H horizon / azimut
281
+ I Sunshine solution Treindl
282
+ i Sunshine solution Makransky
283
+ K Koch
284
+ L Pullen SD "sinusoidal delta", ex Neo-Porphyry
285
+ M Morinus
286
+ N equal/1=Aries
287
+ O Porphyry
288
+ P Placidus
289
+ Q Pullen SR "sinusoidal ratio"
290
+ R Regiomontanus
291
+ S Sripati
292
+ T Polich/Page ("topocentric")
293
+ U Krusinski-Pisa-Goelzer
294
+ V equal Vehlow
295
+ W equal, whole sign
296
+ X axial rotation system/ Meridian houses
297
+ Y APC houses
298
+ """
299
+
300
+ if self.zodiac_type == "Sidereal":
301
+ self.houses_degree_ut = swe.houses_ex(
302
+ tjdut=self.julian_day, lat=self.lat, lon=self.lng, hsys=str.encode('P'), flags=swe.FLG_SIDEREAL
303
+ )[0]
304
+ elif self.zodiac_type == "Tropic":
305
+ self.houses_degree_ut = swe.houses(
306
+ tjdut=self.julian_day, lat=self.lat, lon=self.lng, hsys=str.encode('P')
307
+ )[0]
308
+ else:
309
+ raise KerykeionException("Zodiac type not recognized! Please use 'Tropic' or 'Sidereal'")
310
+
267
311
  point_type: Literal["Planet", "House"] = "House"
268
312
  # creates the list of the house in 360°
269
313
  self.houses_degree_ut = swe.houses(self.julian_day, self.lat, self.lng)[0]
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "kerykeion"
3
- version = "4.1.0"
3
+ version = "4.1.1"
4
4
  authors = ["Giacomo Battaglia <battaglia.giacomo@yahoo.it>"]
5
5
  description = "A python library for astrology."
6
6
  license = "AGPL-3.0"
@@ -85,7 +85,7 @@ line-length = 120
85
85
  [tool.poe.tasks]
86
86
  test = "pytest"
87
87
  test-no-capture = "poetry run pytest --show-capture no "
88
- lint = "mypy"
88
+ analize = "mypy"
89
89
  docs = "pdoc kerykeion -o ./docs"
90
90
  format = "black --line-length 120"
91
91
  "format:all" = "black kerykeion tests --line-length 120"