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

Files changed (36) hide show
  1. kerykeion/__init__.py +3 -1
  2. kerykeion/aspects/aspects_utils.py +40 -123
  3. kerykeion/aspects/natal_aspects.py +34 -25
  4. kerykeion/aspects/synastry_aspects.py +34 -28
  5. kerykeion/astrological_subject.py +199 -196
  6. kerykeion/charts/charts_utils.py +701 -62
  7. kerykeion/charts/draw_planets.py +407 -0
  8. kerykeion/charts/kerykeion_chart_svg.py +534 -1140
  9. kerykeion/charts/templates/aspect_grid_only.xml +452 -0
  10. kerykeion/charts/templates/chart.xml +88 -70
  11. kerykeion/charts/templates/wheel_only.xml +499 -0
  12. kerykeion/charts/themes/classic.css +82 -0
  13. kerykeion/charts/themes/dark-high-contrast.css +121 -0
  14. kerykeion/charts/themes/dark.css +121 -0
  15. kerykeion/charts/themes/light.css +117 -0
  16. kerykeion/enums.py +1 -0
  17. kerykeion/ephemeris_data.py +178 -0
  18. kerykeion/fetch_geonames.py +2 -3
  19. kerykeion/kr_types/chart_types.py +6 -16
  20. kerykeion/kr_types/kr_literals.py +12 -3
  21. kerykeion/kr_types/kr_models.py +77 -32
  22. kerykeion/kr_types/settings_models.py +4 -10
  23. kerykeion/relationship_score/__init__.py +2 -0
  24. kerykeion/relationship_score/relationship_score.py +175 -0
  25. kerykeion/relationship_score/relationship_score_factory.py +275 -0
  26. kerykeion/report.py +6 -3
  27. kerykeion/settings/kerykeion_settings.py +6 -1
  28. kerykeion/settings/kr.config.json +256 -102
  29. kerykeion/utilities.py +122 -217
  30. {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/METADATA +40 -10
  31. kerykeion-4.18.0.dist-info/RECORD +42 -0
  32. kerykeion/relationship_score.py +0 -205
  33. kerykeion-4.12.3.dist-info/RECORD +0 -32
  34. {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/LICENSE +0 -0
  35. {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/WHEEL +0 -0
  36. {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/entry_points.txt +0 -0
kerykeion/utilities.py CHANGED
@@ -1,9 +1,11 @@
1
- from kerykeion.kr_types import KerykeionPointModel, KerykeionException, KerykeionSettingsModel, AstrologicalSubjectModel
2
- from kerykeion.kr_types.kr_literals import LunarPhaseEmoji, LunarPhaseName, PointType, Planet
3
- from typing import Union
1
+ from kerykeion.kr_types import KerykeionPointModel, KerykeionException, ZodiacSignModel, AstrologicalSubjectModel
2
+ from kerykeion.kr_types.kr_literals import LunarPhaseEmoji, LunarPhaseName, PointType, Planet, Houses
3
+ from typing import Union, get_args, TYPE_CHECKING
4
4
  import logging
5
5
  import math
6
6
 
7
+ if TYPE_CHECKING:
8
+ from kerykeion import AstrologicalSubject
7
9
 
8
10
 
9
11
  def get_number_from_name(name: Planet) -> int:
@@ -35,176 +37,63 @@ def get_number_from_name(name: Planet) -> int:
35
37
  return 11
36
38
  elif name == "Chiron":
37
39
  return 15
40
+ elif name == "Mean_Lilith":
41
+ return 12
38
42
  else:
39
43
  raise KerykeionException(f"Error in getting number from name! Name: {name}")
40
44
 
41
45
 
42
- def calculate_position(
43
- degree: Union[int, float], number_name: str, point_type: PointType
46
+ def get_kerykeion_point_from_degree(
47
+ degree: Union[int, float], name: Union[Planet, Houses], point_type: PointType
44
48
  ) -> KerykeionPointModel:
45
- """Utility function to create a dictionary dividing the houses or the planets list."""
46
-
47
- if degree < 30:
48
- dictionary = {
49
- "name": number_name,
50
- "quality": "Cardinal",
51
- "element": "Fire",
52
- "sign": "Ari",
53
- "sign_num": 0,
54
- "position": degree,
55
- "abs_pos": degree,
56
- "emoji": "♈️",
57
- "point_type": point_type,
58
- }
59
-
60
- elif degree < 60:
61
- result = degree - 30
62
- dictionary = {
63
- "name": number_name,
64
- "quality": "Fixed",
65
- "element": "Earth",
66
- "sign": "Tau",
67
- "sign_num": 1,
68
- "position": result,
69
- "abs_pos": degree,
70
- "emoji": "♉️",
71
- "point_type": point_type,
72
- }
73
- elif degree < 90:
74
- result = degree - 60
75
- dictionary = {
76
- "name": number_name,
77
- "quality": "Mutable",
78
- "element": "Air",
79
- "sign": "Gem",
80
- "sign_num": 2,
81
- "position": result,
82
- "abs_pos": degree,
83
- "emoji": "♊️",
84
- "point_type": point_type,
85
- }
86
- elif degree < 120:
87
- result = degree - 90
88
- dictionary = {
89
- "name": number_name,
90
- "quality": "Cardinal",
91
- "element": "Water",
92
- "sign": "Can",
93
- "sign_num": 3,
94
- "position": result,
95
- "abs_pos": degree,
96
- "emoji": "♋️",
97
- "point_type": point_type,
98
- }
99
- elif degree < 150:
100
- result = degree - 120
101
- dictionary = {
102
- "name": number_name,
103
- "quality": "Fixed",
104
- "element": "Fire",
105
- "sign": "Leo",
106
- "sign_num": 4,
107
- "position": result,
108
- "abs_pos": degree,
109
- "emoji": "♌️",
110
- "point_type": point_type,
111
- }
112
- elif degree < 180:
113
- result = degree - 150
114
- dictionary = {
115
- "name": number_name,
116
- "quality": "Mutable",
117
- "element": "Earth",
118
- "sign": "Vir",
119
- "sign_num": 5,
120
- "position": result,
121
- "abs_pos": degree,
122
- "emoji": "♍️",
123
- "point_type": point_type,
124
- }
125
- elif degree < 210:
126
- result = degree - 180
127
- dictionary = {
128
- "name": number_name,
129
- "quality": "Cardinal",
130
- "element": "Air",
131
- "sign": "Lib",
132
- "sign_num": 6,
133
- "position": result,
134
- "abs_pos": degree,
135
- "emoji": "♎️",
136
- "point_type": point_type,
137
- }
138
- elif degree < 240:
139
- result = degree - 210
140
- dictionary = {
141
- "name": number_name,
142
- "quality": "Fixed",
143
- "element": "Water",
144
- "sign": "Sco",
145
- "sign_num": 7,
146
- "position": result,
147
- "abs_pos": degree,
148
- "emoji": "♏️",
149
- "point_type": point_type,
150
- }
151
- elif degree < 270:
152
- result = degree - 240
153
- dictionary = {
154
- "name": number_name,
155
- "quality": "Mutable",
156
- "element": "Fire",
157
- "sign": "Sag",
158
- "sign_num": 8,
159
- "position": result,
160
- "abs_pos": degree,
161
- "emoji": "♐️",
162
- "point_type": point_type,
163
- }
164
- elif degree < 300:
165
- result = degree - 270
166
- dictionary = {
167
- "name": number_name,
168
- "quality": "Cardinal",
169
- "element": "Earth",
170
- "sign": "Cap",
171
- "sign_num": 9,
172
- "position": result,
173
- "abs_pos": degree,
174
- "emoji": "♑️",
175
- "point_type": point_type,
176
- }
177
- elif degree < 330:
178
- result = degree - 300
179
- dictionary = {
180
- "name": number_name,
181
- "quality": "Fixed",
182
- "element": "Air",
183
- "sign": "Aqu",
184
- "sign_num": 10,
185
- "position": result,
186
- "abs_pos": degree,
187
- "emoji": "♒️",
188
- "point_type": point_type,
189
- }
190
- elif degree < 360:
191
- result = degree - 330
192
- dictionary = {
193
- "name": number_name,
194
- "quality": "Mutable",
195
- "element": "Water",
196
- "sign": "Pis",
197
- "sign_num": 11,
198
- "position": result,
199
- "abs_pos": degree,
200
- "emoji": "♓️",
201
- "point_type": point_type,
202
- }
203
- else:
49
+ """
50
+ Returns a KerykeionPointModel object based on the given degree.
51
+
52
+ Args:
53
+ degree (Union[int, float]): The degree of the celestial point.
54
+ name (str): The name of the celestial point.
55
+ point_type (PointType): The type of the celestial point.
56
+
57
+ Raises:
58
+ KerykeionException: If the degree is not within the valid range (0-360).
59
+
60
+ Returns:
61
+ KerykeionPointModel: The model representing the celestial point.
62
+ """
63
+
64
+ if degree < 0 or degree >= 360:
204
65
  raise KerykeionException(f"Error in calculating positions! Degrees: {degree}")
205
66
 
206
- return KerykeionPointModel(**dictionary)
67
+ ZODIAC_SIGNS = {
68
+ 0: ZodiacSignModel(sign="Ari", quality="Cardinal", element="Fire", emoji="♈️", sign_num=0),
69
+ 1: ZodiacSignModel(sign="Tau", quality="Fixed", element="Earth", emoji="♉️", sign_num=1),
70
+ 2: ZodiacSignModel(sign="Gem", quality="Mutable", element="Air", emoji="♊️", sign_num=2),
71
+ 3: ZodiacSignModel(sign="Can", quality="Cardinal", element="Water", emoji="♋️", sign_num=3),
72
+ 4: ZodiacSignModel(sign="Leo", quality="Fixed", element="Fire", emoji="♌️", sign_num=4),
73
+ 5: ZodiacSignModel(sign="Vir", quality="Mutable", element="Earth", emoji="♍️", sign_num=5),
74
+ 6: ZodiacSignModel(sign="Lib", quality="Cardinal", element="Air", emoji="♎️", sign_num=6),
75
+ 7: ZodiacSignModel(sign="Sco", quality="Fixed", element="Water", emoji="♏️", sign_num=7),
76
+ 8: ZodiacSignModel(sign="Sag", quality="Mutable", element="Fire", emoji="♐️", sign_num=8),
77
+ 9: ZodiacSignModel(sign="Cap", quality="Cardinal", element="Earth", emoji="♑️", sign_num=9),
78
+ 10: ZodiacSignModel(sign="Aqu", quality="Fixed", element="Air", emoji="♒️", sign_num=10),
79
+ 11: ZodiacSignModel(sign="Pis", quality="Mutable", element="Water", emoji="♓️", sign_num=11),
80
+ }
81
+
82
+ sign_index = int(degree // 30)
83
+ sign_degree = degree % 30
84
+ zodiac_sign = ZODIAC_SIGNS[sign_index]
207
85
 
86
+ return KerykeionPointModel(
87
+ name=name,
88
+ quality=zodiac_sign.quality,
89
+ element=zodiac_sign.element,
90
+ sign=zodiac_sign.sign,
91
+ sign_num=zodiac_sign.sign_num,
92
+ position=sign_degree,
93
+ abs_pos=degree,
94
+ emoji=zodiac_sign.emoji,
95
+ point_type=point_type,
96
+ )
208
97
 
209
98
  def setup_logging(level: str) -> None:
210
99
  """
@@ -218,6 +107,7 @@ def setup_logging(level: str) -> None:
218
107
  "info": logging.INFO,
219
108
  "warning": logging.WARNING,
220
109
  "error": logging.ERROR,
110
+ "critical": logging.CRITICAL,
221
111
  }
222
112
  format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
223
113
  loglevel: int = logging_options.get(level, logging.INFO)
@@ -247,47 +137,33 @@ def check_if_point_between(
247
137
  return False
248
138
 
249
139
 
250
- def get_planet_house(planet_position_degree: Union[int, float], houses_degree_ut_list: list) -> str:
140
+ def get_planet_house(planet_position_degree: Union[int, float], houses_degree_ut_list: list) -> Houses:
251
141
  """
252
- Returns the house in which a planet is located.
142
+ Determines the house in which a planet is located based on its position in degrees.
253
143
 
254
144
  Args:
255
- - planet_position_degree: The position of the planet in degrees
256
- - houses_degree_ut_list: A list of the houses in degrees (0-360)
145
+ planet_position_degree (Union[int, float]): The position of the planet in degrees.
146
+ houses_degree_ut_list (list): A list of the houses in degrees (0-360).
257
147
 
258
148
  Returns:
259
- - The house in which the planet is located
149
+ str: The house in which the planet is located.
150
+
151
+ Raises:
152
+ ValueError: If the planet's position does not fall within any house range.
260
153
  """
261
154
 
262
- house = None
263
- if check_if_point_between(houses_degree_ut_list[0], houses_degree_ut_list[1], planet_position_degree) == True:
264
- house = "First_House"
265
- elif check_if_point_between(houses_degree_ut_list[1], houses_degree_ut_list[2], planet_position_degree) == True:
266
- house = "Second_House"
267
- elif check_if_point_between(houses_degree_ut_list[2], houses_degree_ut_list[3], planet_position_degree) == True:
268
- house = "Third_House"
269
- elif check_if_point_between(houses_degree_ut_list[3], houses_degree_ut_list[4], planet_position_degree) == True:
270
- house = "Fourth_House"
271
- elif check_if_point_between(houses_degree_ut_list[4], houses_degree_ut_list[5], planet_position_degree) == True:
272
- house = "Fifth_House"
273
- elif check_if_point_between(houses_degree_ut_list[5], houses_degree_ut_list[6], planet_position_degree) == True:
274
- house = "Sixth_House"
275
- elif check_if_point_between(houses_degree_ut_list[6], houses_degree_ut_list[7], planet_position_degree) == True:
276
- house = "Seventh_House"
277
- elif check_if_point_between(houses_degree_ut_list[7], houses_degree_ut_list[8], planet_position_degree) == True:
278
- house = "Eighth_House"
279
- elif check_if_point_between(houses_degree_ut_list[8], houses_degree_ut_list[9], planet_position_degree) == True:
280
- house = "Ninth_House"
281
- elif check_if_point_between(houses_degree_ut_list[9], houses_degree_ut_list[10], planet_position_degree) == True:
282
- house = "Tenth_House"
283
- elif check_if_point_between(houses_degree_ut_list[10], houses_degree_ut_list[11], planet_position_degree) == True:
284
- house = "Eleventh_House"
285
- elif check_if_point_between(houses_degree_ut_list[11], houses_degree_ut_list[0], planet_position_degree) == True:
286
- house = "Twelfth_House"
287
- else:
288
- raise ValueError("Error in house calculation, planet: ", planet_position_degree, "houses: ", houses_degree_ut_list)
155
+ house_names = get_args(Houses)
156
+
157
+ # Iterate through the house boundaries to find the correct house
158
+ for i in range(len(house_names)):
159
+ start_degree = houses_degree_ut_list[i]
160
+ end_degree = houses_degree_ut_list[(i + 1) % len(houses_degree_ut_list)]
161
+ if check_if_point_between(start_degree, end_degree, planet_position_degree):
162
+ return house_names[i]
163
+
164
+ # If no house is found, raise an error
165
+ raise ValueError(f"Error in house calculation, planet: {planet_position_degree}, houses: {houses_degree_ut_list}")
289
166
 
290
- return house
291
167
 
292
168
  def get_moon_emoji_from_phase_int(phase: int) -> LunarPhaseEmoji:
293
169
  """
@@ -299,23 +175,25 @@ def get_moon_emoji_from_phase_int(phase: int) -> LunarPhaseEmoji:
299
175
  Returns:
300
176
  - The emoji of the moon phase
301
177
  """
178
+
179
+ lunar_phase_emojis = get_args(LunarPhaseEmoji)
302
180
 
303
181
  if phase == 1:
304
- result = "🌑"
182
+ result = lunar_phase_emojis[0]
305
183
  elif phase < 7:
306
- result = "🌒"
184
+ result = lunar_phase_emojis[1]
307
185
  elif 7 <= phase <= 9:
308
- result = "🌓"
186
+ result = lunar_phase_emojis[2]
309
187
  elif phase < 14:
310
- result = "🌔"
188
+ result = lunar_phase_emojis[3]
311
189
  elif phase == 14:
312
- result = "🌕"
190
+ result = lunar_phase_emojis[4]
313
191
  elif phase < 20:
314
- result = "🌖"
192
+ result = lunar_phase_emojis[5]
315
193
  elif 20 <= phase <= 22:
316
- result = "🌗"
194
+ result = lunar_phase_emojis[6]
317
195
  elif phase <= 28:
318
- result = "🌘"
196
+ result = lunar_phase_emojis[7]
319
197
 
320
198
  else:
321
199
  raise KerykeionException(f"Error in moon emoji calculation! Phase: {phase}")
@@ -332,23 +210,25 @@ def get_moon_phase_name_from_phase_int(phase: int) -> LunarPhaseName:
332
210
  Returns:
333
211
  - The name of the moon phase
334
212
  """
335
-
213
+ lunar_phase_names = get_args(LunarPhaseName)
214
+
215
+
336
216
  if phase == 1:
337
- result = "New Moon"
217
+ result = lunar_phase_names[0]
338
218
  elif phase < 7:
339
- result = "Waxing Crescent"
219
+ result = lunar_phase_names[1]
340
220
  elif 7 <= phase <= 9:
341
- result = "First Quarter"
221
+ result = lunar_phase_names[2]
342
222
  elif phase < 14:
343
- result = "Waxing Gibbous"
223
+ result = lunar_phase_names[3]
344
224
  elif phase == 14:
345
- result = "Full Moon"
225
+ result = lunar_phase_names[4]
346
226
  elif phase < 20:
347
- result = "Waning Gibbous"
227
+ result = lunar_phase_names[5]
348
228
  elif 20 <= phase <= 22:
349
- result = "Last Quarter"
229
+ result = lunar_phase_names[6]
350
230
  elif phase <= 28:
351
- result = "Waning Crescent"
231
+ result = lunar_phase_names[7]
352
232
 
353
233
  else:
354
234
  raise KerykeionException(f"Error in moon name calculation! Phase: {phase}")
@@ -356,7 +236,7 @@ def get_moon_phase_name_from_phase_int(phase: int) -> LunarPhaseName:
356
236
  return result
357
237
 
358
238
 
359
- def check_and_adjust_polar_latitude(latitude: float, longitude: float) -> bool:
239
+ def check_and_adjust_polar_latitude(latitude: float) -> float:
360
240
  """
361
241
  Utility function to check if the location is in the polar circle.
362
242
  If it is, it sets the latitude to 66 or -66 degrees.
@@ -367,4 +247,29 @@ def check_and_adjust_polar_latitude(latitude: float, longitude: float) -> bool:
367
247
 
368
248
  elif latitude < -66.0:
369
249
  latitude = -66.0
370
- logging.info("Polar circle override for houses, using -66 degrees")
250
+ logging.info("Polar circle override for houses, using -66 degrees")
251
+
252
+ return latitude
253
+
254
+
255
+ def get_houses_list(subject: Union["AstrologicalSubject", AstrologicalSubjectModel]) -> list[KerykeionPointModel]:
256
+ """
257
+ Return the names of the houses in the order of the houses.
258
+ """
259
+ houses_absolute_position_list = []
260
+ for house in subject.houses_names_list:
261
+ houses_absolute_position_list.append(subject[house.lower()])
262
+
263
+ return houses_absolute_position_list
264
+
265
+
266
+ def get_available_planets_list(subject: Union["AstrologicalSubject", AstrologicalSubjectModel]) -> list[KerykeionPointModel]:
267
+ """
268
+ Return the names of the planets in the order of the planets.
269
+ The names can be used to access the planets from the AstrologicalSubject object with the __getitem__ method or the [] operator.
270
+ """
271
+ planets_absolute_position_list = []
272
+ for planet in subject.planets_names_list:
273
+ planets_absolute_position_list.append(subject[planet.lower()])
274
+
275
+ return planets_absolute_position_list
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kerykeion
3
- Version: 4.12.3
3
+ Version: 4.18.0
4
4
  Summary: A python library for astrology.
5
5
  Home-page: https://www.kerykeion.net/
6
6
  License: AGPL-3.0
7
7
  Keywords: astrology,ephemeris,astrology library,birtchart,svg,zodiac,zodiac-sing,astronomical-algorithms,synastry,astrology-calculator
8
8
  Author: Giacomo Battaglia
9
- Author-email: battaglia.giacomo@yahoo.it
9
+ Author-email: kerykeion.astrology@gmail.com
10
10
  Requires-Python: >=3.9,<4.0
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
@@ -69,7 +69,7 @@ The core goal of this project is to provide a simple and easy approach to astrol
69
69
 
70
70
  Here's an example of a birthchart:
71
71
 
72
- ![Kanye Birth Chart](https://www.kerykeion.net/assets/img/examples/birth-chart.svg)
72
+ ![Kanye Birth Chart](https://www.kerykeion.net/docs/assets/img/examples/birth-chart.svg)
73
73
 
74
74
  ## Web API
75
75
 
@@ -154,7 +154,7 @@ birth_chart_svg.makeSVG()
154
154
  ```
155
155
 
156
156
  The SVG file will be saved in the home directory.
157
- ![John Lennon Birth Chart](https://www.kerykeion.net/assets/img/examples/birth-chart.svg)
157
+ ![John Lennon Birth Chart](https://www.kerykeion.net/docs/assets/img/examples/birth-chart.svg)
158
158
 
159
159
  ### Synastry Chart
160
160
 
@@ -170,7 +170,7 @@ synastry_chart.makeSVG()
170
170
 
171
171
  ```
172
172
 
173
- ![John Lennon and Paul McCartney Synastry](https://www.kerykeion.net/assets/img/examples/synastry-chart.svg)
173
+ ![John Lennon and Paul McCartney Synastry](https://www.kerykeion.net/docs/assets/img/examples/synastry-chart.svg)
174
174
 
175
175
  ### Change the output directory
176
176
 
@@ -189,9 +189,12 @@ synastry_chart.makeSVG()
189
189
 
190
190
  ### Change Language
191
191
 
192
- To change the language of the chart you should create a new kr.config.js file and pass it to the BirthChartSVG class. So far the available languages are English, Portuguese, Italian, Spanish, French and Chinese.
192
+ You can change the language of the SVG by passing the `chart_language` parameter to the KerykeionChartSVG class:
193
193
 
194
- Some examples [here](https://www.kerykeion.net/docs/examples/change-language).
194
+ ```python
195
+ first = AstrologicalSubject("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB", chart_language="ES")
196
+ ```
197
+ More details [here](https://www.kerykeion.net/docs/examples/chart-language).
195
198
 
196
199
  ## Report
197
200
 
@@ -318,6 +321,29 @@ More examples [here](https://www.kerykeion.net/docs/examples/perspective-type/).
318
321
 
319
322
  Full list of supported perspective types [here](https://www.kerykeion.net/pydocs/kerykeion/kr_types/kr_literals.html#PerspectiveType).
320
323
 
324
+ ## Themes
325
+
326
+ You can now personalize your astrological charts with different themes! Four themes are available:
327
+
328
+ - **Classic** (default)
329
+ - **Dark**
330
+ - **Dark High Contrast**
331
+ - **Light**
332
+
333
+ Each theme offers a distinct visual style, allowing you to choose the one that best suits your preferences or presentation needs. If you prefer more control over the appearance, you can opt not to set any theme, making it easier to customize the chart by overriding the default CSS variables. For more detailed instructions on how to apply themes, check the [documentation](https://www.kerykeion.net/docs/examples/theming)
334
+
335
+ Here's an example of how to set the theme:
336
+
337
+ ```python
338
+ from kerykeion import AstrologicalSubject, KerykeionChartSVG
339
+
340
+ dark_theme_subject = AstrologicalSubject("John Lennon - Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
341
+ dark_theme_natal_chart = KerykeionChartSVG(dark_high_contrast_theme_subject, theme="dark_high_contrast")
342
+ dark_theme_natal_chart.makeSVG()
343
+ ```
344
+
345
+ ![John Lennon](https://www.kerykeion.net/assets/img/showcase/John%20Lennon%20-%20Dark%20-%20Natal%20Chart.svg)
346
+
321
347
  ## Alternative Initialization
322
348
 
323
349
  You can initialize the AstrologicalSubject from a **UTC** ISO 8601 string:
@@ -351,16 +377,20 @@ Sooner or later I'll try to write an extensive documentation.
351
377
 
352
378
  You can clone this repository or download a zip file using the right side buttons.
353
379
 
354
- ## Contributing
380
+ ## Integrate Kerykeion Functionalities in Your Project
355
381
 
356
- Feel free to contribute to the code!
382
+ If you are interested in integrating Kerykeion's astrological functionalities into your project, I would be happy to collaborate with you. Whether you need custom features, support, or consultation, feel free to reach out to me at my [email](mailto:kerykeion.astrology@gmail.com?subject=Integration%20Request) address.
357
383
 
358
384
  ## License
359
385
 
360
386
  This project is licensed under the AGPL-3.0 License.
361
387
  To understand how this impacts your use of the software, please see the [LICENSE](LICENSE) file for details.
362
- If you have questions, you can reach out to me at my [email](mailto:battaglia.giacomo@yahoo.it?subject=Kerykeion) address.
388
+ If you have questions, you can reach out to me at my [email](mailto:kerykeion.astrology@gmail.com?subject=Kerykeion) address.
363
389
  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.
364
390
 
365
391
  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.
366
392
 
393
+ ## Contributing
394
+
395
+ Feel free to contribute to the code!
396
+
@@ -0,0 +1,42 @@
1
+ LICENSE,sha256=UTLH8EdbAsgQei4PA2PnBCPGLSZkq5J-dhkyJuXgWQU,34273
2
+ kerykeion/__init__.py,sha256=2NnLOl-3f7L7x_8vXFKV7mgExlJBmsNIBenZNsR1Seo,639
3
+ kerykeion/aspects/__init__.py,sha256=9FlDVI1ndCJga0-chNIhcLitjU_x3kbtAFfFqVp2ejc,293
4
+ kerykeion/aspects/aspects_utils.py,sha256=kwH_FpReN8rMstyHthE_fWD6doltAVzXkKFcNfo-hLw,2977
5
+ kerykeion/aspects/natal_aspects.py,sha256=ESWKPiVUW6vjNgwEHjIkckwqS1y_vZ8_OAaWxUgfcdQ,4973
6
+ kerykeion/aspects/synastry_aspects.py,sha256=xe28zmrsYU5mxHf6vloEPu-FdJF9x-v7xEGVFkRUSF8,4334
7
+ kerykeion/astrological_subject.py,sha256=YkEHyge_S6FTsAsLNuSMBR-4XdNMFhRo6lHqYdp-u6Y,35045
8
+ kerykeion/charts/__init__.py,sha256=Juxkduy2TaagWblh_7CE8Acrg3dHL27-WEddJhau_eQ,127
9
+ kerykeion/charts/charts_utils.py,sha256=IMvYy6jt6HmZZqpE1FIMhpL3eIqdxq2_aaF1RrpgzpE,42148
10
+ kerykeion/charts/draw_planets.py,sha256=Uty3zpWYMQZvvK7ZHhlmynCHeL8DIN3qL2ifnBXVciM,17393
11
+ kerykeion/charts/kerykeion_chart_svg.py,sha256=1jBMLQ24Mg4EoNZGb7KauH6CpC6830V8lG2tnFZF9MY,42521
12
+ kerykeion/charts/templates/aspect_grid_only.xml,sha256=5CUctWk2wgXV-ev2JHJ5yLlow7gzzFZz1eO744PLu2A,65150
13
+ kerykeion/charts/templates/chart.xml,sha256=ryQao1xDqlSjNUY0HzZiJjdRK__mQoMFA3WV-W6t5Jo,68383
14
+ kerykeion/charts/templates/wheel_only.xml,sha256=xyFlULo1rKZDk8kT9pRWgaEoYyNcmwK40PARKqr30FY,66372
15
+ kerykeion/charts/themes/classic.css,sha256=-b6XllAZmqUDjBwDtIkfzfI3Wtc8AImuGMpfAQ_2wa0,3552
16
+ kerykeion/charts/themes/dark-high-contrast.css,sha256=6Hs_LM3m7xvEuRxWwXjLj6DBvf9W3W_A0hknUimfGCA,6099
17
+ kerykeion/charts/themes/dark.css,sha256=egJbTzqnqMaSk3AQ6KI-PMId-BbT2bqzjpuVds2ffcc,6099
18
+ kerykeion/charts/themes/light.css,sha256=urUXkEQlJ-IymdDO7Hp8hFwwjqka6GB42LkaiWZtpfs,6092
19
+ kerykeion/enums.py,sha256=Xp_0A6jBSW7SZvB5LlKfBObg0xTqB6hTq1IXjz-UWl4,997
20
+ kerykeion/ephemeris_data.py,sha256=H_vpSyRv9685qObfgjJgiqHcFaXT48gAYsqihH0Bixw,8068
21
+ kerykeion/fetch_geonames.py,sha256=NmyTErvKISjJCAxvRB1H35aVZI8_-_U-Cqb_rmqRseA,4563
22
+ kerykeion/kr_types/__init__.py,sha256=-qhGQikurdoHnGtuT1bsaEeZ-IwmZtIHMjGOPC9_oqQ,295
23
+ kerykeion/kr_types/chart_types.py,sha256=OlDvjCra7acaBT--B_gqsqOcAwbuKCXmQQyDTDNfy4o,1983
24
+ kerykeion/kr_types/kerykeion_exception.py,sha256=G-7VFta78qBt10l54JZWvwH-3lUNKmDwuILXaVGVu9A,314
25
+ kerykeion/kr_types/kr_literals.py,sha256=36oJanMtO-1s5Nk4kvlNX3H2eZgoF3ZwTph0lu8wMcE,3505
26
+ kerykeion/kr_types/kr_models.py,sha256=hibUM0HAgL5u2Nx_k6R3wO1VNoKwurzxdj7MJDsrbsg,4235
27
+ kerykeion/kr_types/settings_models.py,sha256=xAIUdJ0vDfS19FiuQdBlwfo6_vCZOZ97K4_vgOD6has,11600
28
+ kerykeion/relationship_score/__init__.py,sha256=cLaEBQXQBfyRkv0OaS3ceLROzvWcvKXWiRq0PS6LDjY,114
29
+ kerykeion/relationship_score/relationship_score.py,sha256=ZUMRjEJdtB5_nRXdx4WJdBbTHu9ACwQTeTGhyeOSsoE,6504
30
+ kerykeion/relationship_score/relationship_score_factory.py,sha256=DL-a-Sb7JLscZl0qlW69SpkETkDmB-akpf5y3Sz8sds,10865
31
+ kerykeion/report.py,sha256=QEZfadIxmqIugoLHMW0KBhOqCwTywGSDDfpX4NJD6qg,2785
32
+ kerykeion/settings/__init__.py,sha256=QQNFCl7sgN27MKaVscqtpPk10HGz4wZS3I_7KEGMaVA,69
33
+ kerykeion/settings/kerykeion_settings.py,sha256=zGLq9vNUQRXs8KY47EyKZ9bHrDl2gNYrvVhwsbh4yas,2578
34
+ kerykeion/settings/kr.config.json,sha256=svjWzo-6kG7pWRgwpL0Rz9aueENu-2k7byUeIdEstLk,18796
35
+ kerykeion/sweph/README.md,sha256=L7FtNAJTWtrZNGKa8MX87SjduFYPYxwWhaI5fmtzNZo,73
36
+ kerykeion/sweph/seas_18.se1,sha256=X9nCqhZU43wJpq61WAdueVQJt9xL2UjrwPqn1Kdoa1s,223002
37
+ kerykeion/utilities.py,sha256=VazaGS8n2p3CD8P2q31A1kSKbmXRNMG8DytLuBwEaU4,9219
38
+ kerykeion-4.18.0.dist-info/LICENSE,sha256=UTLH8EdbAsgQei4PA2PnBCPGLSZkq5J-dhkyJuXgWQU,34273
39
+ kerykeion-4.18.0.dist-info/METADATA,sha256=SK_8wXf0v2Zd6p8x8UMQ3zdMat3qXtx4pv43qv0fb2g,15912
40
+ kerykeion-4.18.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
41
+ kerykeion-4.18.0.dist-info/entry_points.txt,sha256=5SmANYscFDDTdeovHvGQ-cnj0hdFvGoxPaWLCpyDFnQ,49
42
+ kerykeion-4.18.0.dist-info/RECORD,,