kerykeion 5.0.0a10__py3-none-any.whl → 5.0.0a12__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 +4 -9
- kerykeion/aspects/__init__.py +2 -4
- kerykeion/aspects/aspects_factory.py +514 -0
- kerykeion/astrological_subject_factory.py +685 -79
- kerykeion/charts/draw_planets.py +584 -343
- kerykeion/charts/kerykeion_chart_svg.py +10 -16
- kerykeion/charts/templates/wheel_only.xml +1 -1
- kerykeion/composite_subject_factory.py +228 -9
- kerykeion/ephemeris_data_factory.py +431 -0
- kerykeion/fetch_geonames.py +27 -8
- kerykeion/house_comparison/house_comparison_factory.py +48 -15
- kerykeion/house_comparison/house_comparison_models.py +51 -13
- kerykeion/house_comparison/house_comparison_utils.py +35 -5
- kerykeion/kr_types/kerykeion_exception.py +6 -0
- kerykeion/kr_types/kr_models.py +82 -12
- kerykeion/planetary_return_factory.py +532 -32
- kerykeion/relationship_score_factory.py +98 -44
- kerykeion/report.py +7 -0
- kerykeion/sweph/sefstars.txt +1602 -0
- kerykeion/transits_time_range_factory.py +293 -0
- kerykeion/utilities.py +129 -67
- {kerykeion-5.0.0a10.dist-info → kerykeion-5.0.0a12.dist-info}/METADATA +49 -22
- kerykeion-5.0.0a12.dist-info/RECORD +50 -0
- kerykeion/aspects/natal_aspects_factory.py +0 -236
- kerykeion/aspects/synastry_aspects_factory.py +0 -234
- kerykeion/charts/draw_planets_v2.py +0 -648
- kerykeion/charts/draw_planets_v3.py +0 -679
- kerykeion/enums.py +0 -57
- kerykeion/ephemeris_data.py +0 -238
- kerykeion/transits_time_range.py +0 -128
- kerykeion-5.0.0a10.dist-info/RECORD +0 -53
- {kerykeion-5.0.0a10.dist-info → kerykeion-5.0.0a12.dist-info}/WHEEL +0 -0
- {kerykeion-5.0.0a10.dist-info → kerykeion-5.0.0a12.dist-info}/licenses/LICENSE +0 -0
kerykeion/utilities.py
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Giacomo Battaglia
|
|
3
|
+
Copyright: (C) 2025 Kerykeion Project
|
|
4
|
+
License: AGPL-3.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
1
7
|
from kerykeion.kr_types import (
|
|
2
8
|
KerykeionPointModel,
|
|
3
9
|
KerykeionException,
|
|
@@ -19,7 +25,18 @@ if TYPE_CHECKING:
|
|
|
19
25
|
|
|
20
26
|
|
|
21
27
|
def get_number_from_name(name: AstrologicalPoint) -> int:
|
|
22
|
-
"""
|
|
28
|
+
"""
|
|
29
|
+
Convert an astrological point name to its corresponding numerical identifier.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
name: The name of the astrological point
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
The numerical identifier used in Swiss Ephemeris calculations
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
KerykeionException: If the name is not recognized
|
|
39
|
+
"""
|
|
23
40
|
|
|
24
41
|
if name == "Sun":
|
|
25
42
|
return 0
|
|
@@ -70,18 +87,18 @@ def get_kerykeion_point_from_degree(
|
|
|
70
87
|
degree: Union[int, float], name: Union[AstrologicalPoint, Houses], point_type: PointType
|
|
71
88
|
) -> KerykeionPointModel:
|
|
72
89
|
"""
|
|
73
|
-
|
|
90
|
+
Create a KerykeionPointModel from a degree position.
|
|
74
91
|
|
|
75
92
|
Args:
|
|
76
|
-
degree (
|
|
77
|
-
name
|
|
78
|
-
point_type
|
|
79
|
-
|
|
80
|
-
Raises:
|
|
81
|
-
KerykeionException: If the degree is not within the valid range (0-360).
|
|
93
|
+
degree: The degree position (0-360, negative values are converted to positive)
|
|
94
|
+
name: The name of the celestial point or house
|
|
95
|
+
point_type: The type classification of the point
|
|
82
96
|
|
|
83
97
|
Returns:
|
|
84
|
-
KerykeionPointModel
|
|
98
|
+
A KerykeionPointModel with calculated zodiac sign, position, and properties
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
KerykeionException: If the degree is >= 360 after normalization
|
|
85
102
|
"""
|
|
86
103
|
# If - single degree is given, convert it to a positive degree
|
|
87
104
|
if degree < 0:
|
|
@@ -124,10 +141,10 @@ def get_kerykeion_point_from_degree(
|
|
|
124
141
|
|
|
125
142
|
def setup_logging(level: str) -> None:
|
|
126
143
|
"""
|
|
127
|
-
|
|
144
|
+
Configure logging for the application.
|
|
128
145
|
|
|
129
146
|
Args:
|
|
130
|
-
level: Log level as
|
|
147
|
+
level: Log level as string (debug, info, warning, error, critical)
|
|
131
148
|
"""
|
|
132
149
|
logging_options: dict[str, int] = {
|
|
133
150
|
"debug": logging.DEBUG,
|
|
@@ -145,18 +162,23 @@ def is_point_between(
|
|
|
145
162
|
start_point: Union[int, float], end_point: Union[int, float], evaluated_point: Union[int, float]
|
|
146
163
|
) -> bool:
|
|
147
164
|
"""
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
-
|
|
165
|
+
Determine if a point lies between two other points on a circle.
|
|
166
|
+
|
|
167
|
+
Special rules:
|
|
168
|
+
- If evaluated_point equals start_point, returns True
|
|
169
|
+
- If evaluated_point equals end_point, returns False
|
|
170
|
+
- The arc between start_point and end_point must not exceed 180°
|
|
152
171
|
|
|
153
172
|
Args:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
173
|
+
start_point: The starting point on the circle
|
|
174
|
+
end_point: The ending point on the circle
|
|
175
|
+
evaluated_point: The point to evaluate
|
|
157
176
|
|
|
158
177
|
Returns:
|
|
159
|
-
|
|
178
|
+
True if evaluated_point is between start_point and end_point, False otherwise
|
|
179
|
+
|
|
180
|
+
Raises:
|
|
181
|
+
KerykeionException: If the angular difference exceeds 180°
|
|
160
182
|
"""
|
|
161
183
|
|
|
162
184
|
# Normalize angles to [0, 360)
|
|
@@ -193,17 +215,17 @@ def is_point_between(
|
|
|
193
215
|
|
|
194
216
|
def get_planet_house(planet_position_degree: Union[int, float], houses_degree_ut_list: list) -> Houses:
|
|
195
217
|
"""
|
|
196
|
-
|
|
218
|
+
Determine which house contains a planet based on its degree position.
|
|
197
219
|
|
|
198
220
|
Args:
|
|
199
|
-
planet_position_degree
|
|
200
|
-
houses_degree_ut_list
|
|
221
|
+
planet_position_degree: The planet's position in degrees (0-360)
|
|
222
|
+
houses_degree_ut_list: List of house cusp degrees
|
|
201
223
|
|
|
202
224
|
Returns:
|
|
203
|
-
|
|
225
|
+
The house name containing the planet
|
|
204
226
|
|
|
205
227
|
Raises:
|
|
206
|
-
ValueError: If the planet's position
|
|
228
|
+
ValueError: If the planet's position doesn't fall within any house range
|
|
207
229
|
"""
|
|
208
230
|
|
|
209
231
|
house_names = get_args(Houses)
|
|
@@ -222,13 +244,16 @@ def get_planet_house(planet_position_degree: Union[int, float], houses_degree_ut
|
|
|
222
244
|
|
|
223
245
|
def get_moon_emoji_from_phase_int(phase: int) -> LunarPhaseEmoji:
|
|
224
246
|
"""
|
|
225
|
-
|
|
247
|
+
Get the emoji representation of a lunar phase.
|
|
226
248
|
|
|
227
249
|
Args:
|
|
228
|
-
|
|
250
|
+
phase: The lunar phase number (0-28)
|
|
229
251
|
|
|
230
252
|
Returns:
|
|
231
|
-
|
|
253
|
+
The corresponding emoji for the lunar phase
|
|
254
|
+
|
|
255
|
+
Raises:
|
|
256
|
+
KerykeionException: If phase is outside valid range
|
|
232
257
|
"""
|
|
233
258
|
|
|
234
259
|
lunar_phase_emojis = get_args(LunarPhaseEmoji)
|
|
@@ -258,13 +283,16 @@ def get_moon_emoji_from_phase_int(phase: int) -> LunarPhaseEmoji:
|
|
|
258
283
|
|
|
259
284
|
def get_moon_phase_name_from_phase_int(phase: int) -> LunarPhaseName:
|
|
260
285
|
"""
|
|
261
|
-
|
|
286
|
+
Get the name of a lunar phase from its numerical value.
|
|
262
287
|
|
|
263
288
|
Args:
|
|
264
|
-
|
|
289
|
+
phase: The lunar phase number (0-28)
|
|
265
290
|
|
|
266
291
|
Returns:
|
|
267
|
-
|
|
292
|
+
The corresponding name for the lunar phase
|
|
293
|
+
|
|
294
|
+
Raises:
|
|
295
|
+
KerykeionException: If phase is outside valid range
|
|
268
296
|
"""
|
|
269
297
|
lunar_phase_names = get_args(LunarPhaseName)
|
|
270
298
|
|
|
@@ -293,8 +321,15 @@ def get_moon_phase_name_from_phase_int(phase: int) -> LunarPhaseName:
|
|
|
293
321
|
|
|
294
322
|
def check_and_adjust_polar_latitude(latitude: float) -> float:
|
|
295
323
|
"""
|
|
296
|
-
|
|
297
|
-
|
|
324
|
+
Adjust latitude values for polar regions to prevent calculation errors.
|
|
325
|
+
|
|
326
|
+
Latitudes beyond ±66° are clamped to ±66° for house calculations.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
latitude: The original latitude value
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
The adjusted latitude value, clamped between -66° and 66°
|
|
298
333
|
"""
|
|
299
334
|
if latitude > 66.0:
|
|
300
335
|
latitude = 66.0
|
|
@@ -311,7 +346,13 @@ def get_houses_list(
|
|
|
311
346
|
subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel]
|
|
312
347
|
) -> list[KerykeionPointModel]:
|
|
313
348
|
"""
|
|
314
|
-
|
|
349
|
+
Get a list of house objects in order from the subject.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
subject: The astrological subject containing house data
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
List of KerykeionPointModel objects representing the houses
|
|
315
356
|
"""
|
|
316
357
|
houses_absolute_position_list = []
|
|
317
358
|
for house in subject.houses_names_list:
|
|
@@ -324,8 +365,13 @@ def get_available_astrological_points_list(
|
|
|
324
365
|
subject: AstrologicalSubjectModel
|
|
325
366
|
) -> list[KerykeionPointModel]:
|
|
326
367
|
"""
|
|
327
|
-
|
|
328
|
-
|
|
368
|
+
Get a list of active astrological point objects from the subject.
|
|
369
|
+
|
|
370
|
+
Args:
|
|
371
|
+
subject: The astrological subject containing point data
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
List of KerykeionPointModel objects for all active points
|
|
329
375
|
"""
|
|
330
376
|
planets_absolute_position_list = []
|
|
331
377
|
for planet in subject.active_points:
|
|
@@ -336,17 +382,17 @@ def get_available_astrological_points_list(
|
|
|
336
382
|
|
|
337
383
|
def circular_mean(first_position: Union[int, float], second_position: Union[int, float]) -> float:
|
|
338
384
|
"""
|
|
339
|
-
|
|
385
|
+
Calculate the circular mean of two angular positions.
|
|
340
386
|
|
|
341
|
-
This
|
|
342
|
-
avoiding errors that occur with simple
|
|
387
|
+
This method correctly handles positions that cross the 0°/360° boundary,
|
|
388
|
+
avoiding errors that occur with simple arithmetic means.
|
|
343
389
|
|
|
344
390
|
Args:
|
|
345
|
-
|
|
346
|
-
|
|
391
|
+
first_position: First angular position in degrees (0-360)
|
|
392
|
+
second_position: Second angular position in degrees (0-360)
|
|
347
393
|
|
|
348
394
|
Returns:
|
|
349
|
-
|
|
395
|
+
The circular mean position in degrees (0-360)
|
|
350
396
|
"""
|
|
351
397
|
x = (math.cos(math.radians(first_position)) + math.cos(math.radians(second_position))) / 2
|
|
352
398
|
y = (math.sin(math.radians(first_position)) + math.sin(math.radians(second_position))) / 2
|
|
@@ -361,14 +407,14 @@ def circular_mean(first_position: Union[int, float], second_position: Union[int,
|
|
|
361
407
|
|
|
362
408
|
def calculate_moon_phase(moon_abs_pos: float, sun_abs_pos: float) -> LunarPhaseModel:
|
|
363
409
|
"""
|
|
364
|
-
Calculate
|
|
410
|
+
Calculate lunar phase information from Sun and Moon positions.
|
|
365
411
|
|
|
366
412
|
Args:
|
|
367
|
-
|
|
368
|
-
|
|
413
|
+
moon_abs_pos: Absolute position of the Moon in degrees
|
|
414
|
+
sun_abs_pos: Absolute position of the Sun in degrees
|
|
369
415
|
|
|
370
416
|
Returns:
|
|
371
|
-
|
|
417
|
+
LunarPhaseModel containing phase data, emoji, and name
|
|
372
418
|
"""
|
|
373
419
|
# Initialize moon_phase and sun_phase to None in case of an error
|
|
374
420
|
moon_phase, sun_phase = None, None
|
|
@@ -408,14 +454,13 @@ def calculate_moon_phase(moon_abs_pos: float, sun_abs_pos: float) -> LunarPhaseM
|
|
|
408
454
|
|
|
409
455
|
def circular_sort(degrees: list[Union[int, float]]) -> list[Union[int, float]]:
|
|
410
456
|
"""
|
|
411
|
-
Sort
|
|
412
|
-
and progressing clockwise around the circle.
|
|
457
|
+
Sort degrees in circular clockwise progression starting from the first element.
|
|
413
458
|
|
|
414
459
|
Args:
|
|
415
|
-
degrees:
|
|
460
|
+
degrees: List of numeric degree values
|
|
416
461
|
|
|
417
462
|
Returns:
|
|
418
|
-
|
|
463
|
+
List sorted by clockwise distance from the first element
|
|
419
464
|
|
|
420
465
|
Raises:
|
|
421
466
|
ValueError: If the list is empty or contains non-numeric values
|
|
@@ -458,14 +503,16 @@ def circular_sort(degrees: list[Union[int, float]]) -> list[Union[int, float]]:
|
|
|
458
503
|
|
|
459
504
|
def inline_css_variables_in_svg(svg_content: str) -> str:
|
|
460
505
|
"""
|
|
461
|
-
|
|
506
|
+
Replace CSS custom properties (variables) with their values in SVG content.
|
|
507
|
+
|
|
508
|
+
Extracts CSS variables from style blocks, replaces var() references with actual values,
|
|
509
|
+
and removes all style blocks from the SVG.
|
|
462
510
|
|
|
463
511
|
Args:
|
|
464
|
-
svg_content
|
|
512
|
+
svg_content: The original SVG string with CSS variables
|
|
465
513
|
|
|
466
514
|
Returns:
|
|
467
|
-
|
|
468
|
-
and all style blocks removed
|
|
515
|
+
Modified SVG with CSS variables inlined and style blocks removed
|
|
469
516
|
"""
|
|
470
517
|
# Find and extract CSS custom properties from style tags
|
|
471
518
|
css_variable_map = {}
|
|
@@ -486,6 +533,15 @@ def inline_css_variables_in_svg(svg_content: str) -> str:
|
|
|
486
533
|
|
|
487
534
|
# Function to replace var() references with their actual values
|
|
488
535
|
def replace_css_variable_reference(match):
|
|
536
|
+
"""
|
|
537
|
+
Replace CSS variable references with their actual values.
|
|
538
|
+
|
|
539
|
+
Args:
|
|
540
|
+
match: Regular expression match object containing variable name and optional fallback.
|
|
541
|
+
|
|
542
|
+
Returns:
|
|
543
|
+
str: The resolved CSS variable value or fallback value.
|
|
544
|
+
"""
|
|
489
545
|
variable_name = match.group(1).strip()
|
|
490
546
|
fallback_value = match.group(2) if match.group(2) else None
|
|
491
547
|
|
|
@@ -510,13 +566,13 @@ def inline_css_variables_in_svg(svg_content: str) -> str:
|
|
|
510
566
|
|
|
511
567
|
def datetime_to_julian(dt: datetime) -> float:
|
|
512
568
|
"""
|
|
513
|
-
|
|
569
|
+
Convert a Python datetime object to Julian Day Number.
|
|
514
570
|
|
|
515
571
|
Args:
|
|
516
|
-
dt:
|
|
572
|
+
dt: The datetime object to convert
|
|
517
573
|
|
|
518
574
|
Returns:
|
|
519
|
-
|
|
575
|
+
The corresponding Julian Day Number (JD) as a float
|
|
520
576
|
"""
|
|
521
577
|
# Extract year, month and day
|
|
522
578
|
year = dt.year
|
|
@@ -548,13 +604,13 @@ def datetime_to_julian(dt: datetime) -> float:
|
|
|
548
604
|
|
|
549
605
|
def julian_to_datetime(jd):
|
|
550
606
|
"""
|
|
551
|
-
|
|
607
|
+
Convert a Julian Day Number to a Python datetime object.
|
|
552
608
|
|
|
553
609
|
Args:
|
|
554
|
-
jd: Julian
|
|
610
|
+
jd: Julian Day Number as a float
|
|
555
611
|
|
|
556
612
|
Returns:
|
|
557
|
-
|
|
613
|
+
The corresponding datetime object
|
|
558
614
|
"""
|
|
559
615
|
# Add 0.5 to the Julian day to adjust for noon-based Julian day
|
|
560
616
|
jd_plus = jd + 0.5
|
|
@@ -613,13 +669,16 @@ def julian_to_datetime(jd):
|
|
|
613
669
|
|
|
614
670
|
def get_house_name(house_number: int) -> Houses:
|
|
615
671
|
"""
|
|
616
|
-
|
|
672
|
+
Convert a house number to its corresponding house name.
|
|
617
673
|
|
|
618
674
|
Args:
|
|
619
675
|
house_number: House number (1-12)
|
|
620
676
|
|
|
621
677
|
Returns:
|
|
622
|
-
|
|
678
|
+
The house name
|
|
679
|
+
|
|
680
|
+
Raises:
|
|
681
|
+
ValueError: If house_number is not in range 1-12
|
|
623
682
|
"""
|
|
624
683
|
house_names: dict[int, Houses] = {
|
|
625
684
|
1: "First_House",
|
|
@@ -645,13 +704,16 @@ def get_house_name(house_number: int) -> Houses:
|
|
|
645
704
|
|
|
646
705
|
def get_house_number(house_name: Houses) -> int:
|
|
647
706
|
"""
|
|
648
|
-
|
|
707
|
+
Convert a house name to its corresponding house number.
|
|
649
708
|
|
|
650
709
|
Args:
|
|
651
|
-
house_name:
|
|
710
|
+
house_name: The house name
|
|
652
711
|
|
|
653
712
|
Returns:
|
|
654
713
|
House number (1-12)
|
|
714
|
+
|
|
715
|
+
Raises:
|
|
716
|
+
ValueError: If house_name is not recognized
|
|
655
717
|
"""
|
|
656
718
|
house_numbers: dict[Houses, int] = {
|
|
657
719
|
"First_House": 1,
|
|
@@ -677,14 +739,14 @@ def get_house_number(house_name: Houses) -> int:
|
|
|
677
739
|
|
|
678
740
|
def find_common_active_points(first_points: list[AstrologicalPoint], second_points: list[AstrologicalPoint]) -> list[AstrologicalPoint]:
|
|
679
741
|
"""
|
|
680
|
-
Find
|
|
742
|
+
Find astrological points that appear in both input lists.
|
|
681
743
|
|
|
682
744
|
Args:
|
|
683
|
-
first_points:
|
|
684
|
-
second_points:
|
|
745
|
+
first_points: First list of astrological points
|
|
746
|
+
second_points: Second list of astrological points
|
|
685
747
|
|
|
686
748
|
Returns:
|
|
687
|
-
List of
|
|
749
|
+
List of points common to both input lists (without duplicates)
|
|
688
750
|
"""
|
|
689
751
|
common_points = list(set(first_points) & set(second_points))
|
|
690
752
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kerykeion
|
|
3
|
-
Version: 5.0.
|
|
3
|
+
Version: 5.0.0a12
|
|
4
4
|
Summary: A Python library for astrological calculations, including natal charts, houses, planetary aspects, and SVG chart generation.
|
|
5
5
|
Project-URL: Homepage, https://www.kerykeion.net/
|
|
6
6
|
Project-URL: Repository, https://github.com/g-battaglia/kerykeion
|
|
@@ -186,10 +186,6 @@ birth_chart_svg = KerykeionChartSVG(john)
|
|
|
186
186
|
birth_chart_svg.makeSVG()
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
-
```python
|
|
190
|
-
birth_chart_svg.makeSVG()
|
|
191
|
-
```
|
|
192
|
-
|
|
193
189
|
The SVG file will be saved in the home directory.
|
|
194
190
|

|
|
195
191
|
|
|
@@ -221,7 +217,7 @@ synastry_chart.makeSVG()
|
|
|
221
217
|
### Transit Chart
|
|
222
218
|
|
|
223
219
|
```python
|
|
224
|
-
from kerykeion import AstrologicalSubjectFactory
|
|
220
|
+
from kerykeion import AstrologicalSubjectFactory, KerykeionChartSVG
|
|
225
221
|
|
|
226
222
|
transit = AstrologicalSubjectFactory.from_birth_data("Transit", 2025, 6, 8, 8, 45, "Atlanta", "US")
|
|
227
223
|
subject = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
@@ -315,7 +311,7 @@ You can switch chart language by passing `chart_language` to the `KerykeionChar
|
|
|
315
311
|
```python
|
|
316
312
|
from kerykeion import AstrologicalSubjectFactory, KerykeionChartSVG
|
|
317
313
|
|
|
318
|
-
|
|
314
|
+
birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
319
315
|
birth_chart_svg = KerykeionChartSVG(
|
|
320
316
|
birth_chart,
|
|
321
317
|
chart_language="IT" # Change to Italian
|
|
@@ -342,7 +338,7 @@ To generate a minified SVG, set `minify_svg=True` in the `makeSVG()` method:
|
|
|
342
338
|
|
|
343
339
|
```python
|
|
344
340
|
from kerykeion import AstrologicalSubjectFactory, KerykeionChartSVG
|
|
345
|
-
|
|
341
|
+
birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
346
342
|
birth_chart_svg = KerykeionChartSVG(birth_chart)
|
|
347
343
|
birth_chart_svg.makeSVG(
|
|
348
344
|
minify=True
|
|
@@ -355,7 +351,7 @@ To generate an SVG without CSS variables, set `remove_css_variables=True` in the
|
|
|
355
351
|
```python
|
|
356
352
|
from kerykeion import AstrologicalSubjectFactory, KerykeionChartSVG
|
|
357
353
|
|
|
358
|
-
|
|
354
|
+
birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
359
355
|
birth_chart_svg = KerykeionChartSVG(birth_chart)
|
|
360
356
|
birth_chart_svg.makeSVG(
|
|
361
357
|
remove_css_variables=True
|
|
@@ -366,13 +362,14 @@ This will inline all styles and eliminate CSS variables, resulting in an SVG tha
|
|
|
366
362
|
|
|
367
363
|
### Grid Only SVG
|
|
368
364
|
|
|
369
|
-
It's possible to generate a grid-only SVG, useful for creating a custom layout. To do this, use the `
|
|
365
|
+
It's possible to generate a grid-only SVG, useful for creating a custom layout. To do this, use the `makeAspectGridOnlySVG()` method:
|
|
370
366
|
|
|
371
367
|
```python
|
|
372
368
|
from kerykeion import AstrologicalSubjectFactory, KerykeionChartSVG
|
|
373
|
-
birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon
|
|
374
|
-
|
|
375
|
-
|
|
369
|
+
birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
370
|
+
second = AstrologicalSubjectFactory.from_birth_data("Paul McCartney", 1942, 6, 18, 15, 30, "Liverpool", "GB")
|
|
371
|
+
aspect_grid_chart = KerykeionChartSVG(birth_chart, "Synastry", second, theme="dark")
|
|
372
|
+
aspect_grid_chart.makeAspectGridOnlySVG()
|
|
376
373
|
```
|
|
377
374
|

|
|
378
375
|
|
|
@@ -444,17 +441,47 @@ python3 your_script_name.py > file.txt
|
|
|
444
441
|
|
|
445
442
|
## Example: Retrieving Aspects
|
|
446
443
|
|
|
444
|
+
Kerykeion provides a unified `AspectsFactory` class for calculating astrological aspects within single charts or between two charts:
|
|
445
|
+
|
|
447
446
|
```python
|
|
448
|
-
from kerykeion import
|
|
447
|
+
from kerykeion import AspectsFactory, AstrologicalSubjectFactory
|
|
448
|
+
|
|
449
|
+
# Create astrological subjects
|
|
450
|
+
jack = AstrologicalSubjectFactory.from_birth_data("Jack", 1990, 6, 15, 15, 15, "Roma", "IT")
|
|
451
|
+
jane = AstrologicalSubjectFactory.from_birth_data("Jane", 1991, 10, 25, 21, 0, "Roma", "IT")
|
|
452
|
+
|
|
453
|
+
# For single chart aspects (natal, return, composite, etc.)
|
|
454
|
+
single_chart_aspects = AspectsFactory.single_chart_aspects(jack)
|
|
455
|
+
print(f"Found {len(single_chart_aspects)} aspects in Jack's chart")
|
|
456
|
+
print(single_chart_aspects[0])
|
|
457
|
+
# Output: AspectModel with details like aspect type, orb, planets involved, etc.
|
|
458
|
+
|
|
459
|
+
# For dual chart aspects (synastry, transits, comparisons, etc.)
|
|
460
|
+
dual_chart_aspects = AspectsFactory.dual_chart_aspects(jack, jane)
|
|
461
|
+
print(f"Found {len(dual_chart_aspects)} aspects between Jack and Jane's charts")
|
|
462
|
+
print(dual_chart_aspects[0])
|
|
463
|
+
# Output: AspectModel with cross-chart aspect details
|
|
464
|
+
|
|
465
|
+
# The factory returns structured AspectModel objects with properties like:
|
|
466
|
+
# - p1_name, p2_name: Planet/point names
|
|
467
|
+
# - aspect: Aspect type (conjunction, trine, square, etc.)
|
|
468
|
+
# - orbit: Orb tolerance in degrees
|
|
469
|
+
# - aspect_degrees: Exact degrees for the aspect (0, 60, 90, 120, 180, etc.)
|
|
470
|
+
# - color: Hex color code for visualization
|
|
471
|
+
```
|
|
449
472
|
|
|
450
|
-
|
|
451
|
-
|
|
473
|
+
**Advanced Usage with Custom Settings:**
|
|
474
|
+
|
|
475
|
+
```python
|
|
476
|
+
# You can also customize aspect calculations with custom orb settings
|
|
477
|
+
from kerykeion.settings.config_constants import DEFAULT_ACTIVE_ASPECTS
|
|
452
478
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
#> {'p1_name': 'Sun', 'p1_abs_pos': 84.17867971515636, 'p2_name': 'Sun', 'p2_abs_pos': 211.90472999502984, 'aspect': 'trine', 'orbit': 7.726050279873476, 'aspect_degrees': 120, 'color': '#36d100', 'aid': 6, 'diff': 127.72605027987348, 'p1': 0, 'p2': 0}
|
|
479
|
+
# Modify aspect settings if needed
|
|
480
|
+
custom_aspects = DEFAULT_ACTIVE_ASPECTS.copy()
|
|
481
|
+
# ... modify as needed
|
|
457
482
|
|
|
483
|
+
# The factory automatically uses the configured settings for orb calculations
|
|
484
|
+
# and filters aspects based on relevance and orb thresholds
|
|
458
485
|
```
|
|
459
486
|
|
|
460
487
|
## Ayanamsa (Sidereal Modes)
|
|
@@ -525,7 +552,7 @@ Here's an example of how to set the theme:
|
|
|
525
552
|
from kerykeion import AstrologicalSubjectFactory, KerykeionChartSVG
|
|
526
553
|
|
|
527
554
|
dark_theme_subject = AstrologicalSubjectFactory.from_birth_data("John Lennon - Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
528
|
-
dark_theme_natal_chart = KerykeionChartSVG(
|
|
555
|
+
dark_theme_natal_chart = KerykeionChartSVG(dark_theme_subject, theme="dark_high_contrast")
|
|
529
556
|
dark_theme_natal_chart.makeSVG()
|
|
530
557
|
```
|
|
531
558
|
|
|
@@ -617,7 +644,7 @@ Clone the repository or download the ZIP via the GitHub interface.
|
|
|
617
644
|
|
|
618
645
|
## Integrating Kerykeion into Your Project
|
|
619
646
|
|
|
620
|
-
If you would like to incorporate Kerykeion
|
|
647
|
+
If you would like to incorporate Kerykeion's astrological features into your application, please reach out via [email](mailto:kerykeion.astrology@gmail.com?subject=Integration%20Request). Whether you need custom features, support, or specialized consulting, I am happy to discuss potential collaborations.
|
|
621
648
|
|
|
622
649
|
## License
|
|
623
650
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
kerykeion/__init__.py,sha256=WTTZBOe40IuvcINRRrsqinEkTFzaJNbPcZ8iO6F3fvw,1274
|
|
2
|
+
kerykeion/astrological_subject_factory.py,sha256=TrnZ_jIphKzu7NqxlL5vp5JELzuPgxIz1KtrW7W2-5M,83655
|
|
3
|
+
kerykeion/composite_subject_factory.py,sha256=sqs7CiP_3lGI9-FeRFMFL7PIXTlSUaXA9pUDI_5zPZw,17124
|
|
4
|
+
kerykeion/ephemeris_data_factory.py,sha256=Iwd8KkBB-WmI8AEwrhe9ze8dicA5kvpflT_yQD9XkAY,20111
|
|
5
|
+
kerykeion/fetch_geonames.py,sha256=SPI4fSvD59C-IVpaoeOHuD7_kjGbTLo2fypO2x57-p4,5432
|
|
6
|
+
kerykeion/planetary_return_factory.py,sha256=7fwfjhJATFmUNJkIqgaz07sWtpwHPjHvF2oFyPGfga4,37246
|
|
7
|
+
kerykeion/relationship_score_factory.py,sha256=kcr0qEA4_2oQ_2g8IcrHgpVEyb9uAm4EmVWJAGsoCtg,11099
|
|
8
|
+
kerykeion/report.py,sha256=dUtI70wUjOouqNE1pf0ZYFY4qme9pR7WQRbs_ExEkjM,3029
|
|
9
|
+
kerykeion/transits_time_range_factory.py,sha256=xFEdOqYINTBluwp-CKeYTJgANlPEeVw4TYMLigiC30M,13392
|
|
10
|
+
kerykeion/utilities.py,sha256=MtVyZ2dbHrJPuDoPKPrkx0MrB83fxcbGtPx87piHCtQ,23471
|
|
11
|
+
kerykeion/aspects/__init__.py,sha256=csJmxvLdBu-bHuW676f3dpY__Qyc6LwRyrpWVTh3n1A,287
|
|
12
|
+
kerykeion/aspects/aspects_factory.py,sha256=09Hm50c5J-OiMwgsoxZXWidCBgZc2gzhwz95MdHJUy4,22664
|
|
13
|
+
kerykeion/aspects/aspects_utils.py,sha256=mOj2AqVGnY2vsGsezPfxI_crPJsN54p8qjpmCk5iupM,3093
|
|
14
|
+
kerykeion/charts/__init__.py,sha256=i9NMZ7LdkllPlqQSi1or9gTobHbROGDKmJhBDO4R0mA,128
|
|
15
|
+
kerykeion/charts/charts_utils.py,sha256=_z-lA7ibIQ5vhr1NxpzJFyPmMp-Sh1iyYxuO56DDO4w,62922
|
|
16
|
+
kerykeion/charts/draw_planets.py,sha256=6S0sCAktZJa7eckb-h1voYbe0H27vL9otcJzA0dqFH0,28167
|
|
17
|
+
kerykeion/charts/kerykeion_chart_svg.py,sha256=pNSmGZYtFGSx17EKcdSSYunP_oKy3xLSiq_CmbGz8Fs,97285
|
|
18
|
+
kerykeion/charts/templates/aspect_grid_only.xml,sha256=lBHBj5bS5klGnv7QMuFxQjhlE6VZRaOgW93akLgRjX4,70055
|
|
19
|
+
kerykeion/charts/templates/chart.xml,sha256=r3a_csMqcoqeOnDA3YCD-iUxdqgRw5GV1GOf1Cp0e_E,79940
|
|
20
|
+
kerykeion/charts/templates/wheel_only.xml,sha256=X2-bwmEvQnZcM5Om7JXIWZSoSmFLAm4sY31heSq5u1k,71388
|
|
21
|
+
kerykeion/charts/themes/classic.css,sha256=LYYYWQHNG7-vuPCq8F2EPl3LauWXVrY3Q_tpwM0klgo,4660
|
|
22
|
+
kerykeion/charts/themes/dark-high-contrast.css,sha256=YW5X5-M0dz5Vy2oz-JyDNXJYHSmV83lYCodydC-KS1A,7506
|
|
23
|
+
kerykeion/charts/themes/dark.css,sha256=XVspznDRNMXsFzk7hY7IB7AI58alPAV_-CgV3gCKyzg,7581
|
|
24
|
+
kerykeion/charts/themes/light.css,sha256=5eyUzhVlRjG6lPHKnprLum0HuRtPIJhMBzpGfzoTjnQ,7590
|
|
25
|
+
kerykeion/charts/themes/strawberry.css,sha256=UtcfRsCT-M9OZs_SoclWGZ0jDJiWvQjHTeI4M1jf7pQ,8314
|
|
26
|
+
kerykeion/house_comparison/__init__.py,sha256=6FYHyQY3nUJifZ2kEVCHB8cN3TjFA1q2yhmeRwJlias,238
|
|
27
|
+
kerykeion/house_comparison/house_comparison_factory.py,sha256=0C48isz_yb6Pz9EQoQjEzmmhqY-3fh4MGW7sTnW-IUA,4613
|
|
28
|
+
kerykeion/house_comparison/house_comparison_models.py,sha256=RPzJeCFiq0GioWI6IONJEUqsK9I_Dksp5mOHNY-j1PI,2865
|
|
29
|
+
kerykeion/house_comparison/house_comparison_utils.py,sha256=JzWAAtBbKO1bDBRMh-D8hWROyvFo4z2pfmc6NMIN2RU,5167
|
|
30
|
+
kerykeion/kr_types/__init__.py,sha256=dePcQY5rrgtUENhqnjcVx6j7iQJPo_1rmD0bLeIO3HA,1384
|
|
31
|
+
kerykeion/kr_types/chart_types.py,sha256=ofMYk7NRalSsdQcLVkpCbOb-dhdjYHEqIb_WPLtD0rM,2429
|
|
32
|
+
kerykeion/kr_types/kerykeion_exception.py,sha256=vTYdwj_mL-Q-MqHJvEzzBXxQ5YI2kAwUC6ImoWxMKXc,454
|
|
33
|
+
kerykeion/kr_types/kr_literals.py,sha256=4kJhzm_0LERiJEJks0KgDyThueMZj_F1OK2Far5SMZc,4870
|
|
34
|
+
kerykeion/kr_types/kr_models.py,sha256=5wG3bh7EvCD0FTYe-W2e8jNLK408f3JQQhda6DVrOnw,14180
|
|
35
|
+
kerykeion/kr_types/settings_models.py,sha256=Llosnvw-6NHJMbdKltPHQDLR-Ltn7ZpWkjEbLJ2C6AY,17488
|
|
36
|
+
kerykeion/settings/__init__.py,sha256=NYCwcvEfn9qJ498fv1H_Gix8e-crJ3CruV13A-e2CnI,134
|
|
37
|
+
kerykeion/settings/config_constants.py,sha256=hxDZnFKWFhGrYMejDISbYT-phUk1Qqfvt-4wBG79rGA,2233
|
|
38
|
+
kerykeion/settings/kerykeion_settings.py,sha256=umd8TZy-8ywowsd4TTkhwxSLLyX3xYj3A1zvNsTV_Y8,2955
|
|
39
|
+
kerykeion/settings/kr.config.json,sha256=bvvhi8W-u9YHTbg9O8UyfOwclhLd8Mh8oobI1qHIgp4,58497
|
|
40
|
+
kerykeion/settings/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
+
kerykeion/settings/legacy/legacy_celestial_points_settings.py,sha256=YMvHhY8IQ_nNHf1-9JCSgRzTMQJaxXZfROztEhlP4Ac,6870
|
|
42
|
+
kerykeion/settings/legacy/legacy_chart_aspects_settings.py,sha256=tO4tgPgPP07_wu9f8SXyJQ9WrTh3iWz4YvBS2axCGU8,1650
|
|
43
|
+
kerykeion/settings/legacy/legacy_color_settings.py,sha256=gBUmGSNvvLzRYbdVtzwTDnMwWoh4tOCyT_9Q6aQRv_s,2620
|
|
44
|
+
kerykeion/sweph/README.md,sha256=L7FtNAJTWtrZNGKa8MX87SjduFYPYxwWhaI5fmtzNZo,73
|
|
45
|
+
kerykeion/sweph/seas_18.se1,sha256=X9nCqhZU43wJpq61WAdueVQJt9xL2UjrwPqn1Kdoa1s,223002
|
|
46
|
+
kerykeion/sweph/sefstars.txt,sha256=GLDcr75bckB3PauiwDijJfWz_EFj9h4Kf06Sq9T1F8Y,136618
|
|
47
|
+
kerykeion-5.0.0a12.dist-info/METADATA,sha256=uglXk2FOHWcHfjDYwJBPu-32jDEVQiC_OxRb4TP7tQE,26756
|
|
48
|
+
kerykeion-5.0.0a12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
49
|
+
kerykeion-5.0.0a12.dist-info/licenses/LICENSE,sha256=UTLH8EdbAsgQei4PA2PnBCPGLSZkq5J-dhkyJuXgWQU,34273
|
|
50
|
+
kerykeion-5.0.0a12.dist-info/RECORD,,
|