kerykeion 5.0.0a11__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 +2 -3
- kerykeion/aspects/__init__.py +2 -4
- kerykeion/aspects/aspects_factory.py +514 -0
- kerykeion/astrological_subject_factory.py +3 -3
- kerykeion/charts/kerykeion_chart_svg.py +9 -10
- 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/kr_models.py +27 -10
- kerykeion/relationship_score_factory.py +2 -2
- kerykeion/sweph/sefstars.txt +1602 -0
- kerykeion/transits_time_range_factory.py +4 -4
- {kerykeion-5.0.0a11.dist-info → kerykeion-5.0.0a12.dist-info}/METADATA +49 -22
- {kerykeion-5.0.0a11.dist-info → kerykeion-5.0.0a12.dist-info}/RECORD +16 -16
- kerykeion/aspects/natal_aspects_factory.py +0 -235
- kerykeion/aspects/synastry_aspects_factory.py +0 -275
- {kerykeion-5.0.0a11.dist-info → kerykeion-5.0.0a12.dist-info}/WHEEL +0 -0
- {kerykeion-5.0.0a11.dist-info → kerykeion-5.0.0a12.dist-info}/licenses/LICENSE +0 -0
|
@@ -22,7 +22,7 @@ Classes:
|
|
|
22
22
|
|
|
23
23
|
Dependencies:
|
|
24
24
|
- kerykeion.AstrologicalSubjectFactory: For creating astrological subjects
|
|
25
|
-
- kerykeion.aspects.
|
|
25
|
+
- kerykeion.aspects.AspectsFactory: For calculating angular relationships
|
|
26
26
|
- kerykeion.ephemeris_data_factory: For generating time-series planetary positions
|
|
27
27
|
- kerykeion.kr_types: For type definitions and model structures
|
|
28
28
|
- datetime: For date/time handling
|
|
@@ -59,7 +59,7 @@ from typing import Union, List
|
|
|
59
59
|
from datetime import datetime, timedelta
|
|
60
60
|
from kerykeion.kr_types.kr_models import AstrologicalSubjectModel
|
|
61
61
|
from kerykeion.astrological_subject_factory import AstrologicalSubjectFactory
|
|
62
|
-
from kerykeion.aspects import
|
|
62
|
+
from kerykeion.aspects import AspectsFactory
|
|
63
63
|
from kerykeion.ephemeris_data_factory import EphemerisDataFactory
|
|
64
64
|
from kerykeion.kr_types.kr_literals import AstrologicalPoint
|
|
65
65
|
from kerykeion.kr_types.kr_models import ActiveAspect, TransitMomentModel, TransitsTimeRangeModel
|
|
@@ -227,13 +227,13 @@ class TransitsTimeRangeFactory:
|
|
|
227
227
|
See Also:
|
|
228
228
|
TransitMomentModel: Individual transit moment structure
|
|
229
229
|
TransitsTimeRangeModel: Complete transit dataset structure
|
|
230
|
-
|
|
230
|
+
AspectsFactory: Underlying aspect calculation engine
|
|
231
231
|
"""
|
|
232
232
|
transit_moments = []
|
|
233
233
|
|
|
234
234
|
for ephemeris_point in self.ephemeris_data_points:
|
|
235
235
|
# Calculate aspects between transit positions and natal chart
|
|
236
|
-
aspects =
|
|
236
|
+
aspects = AspectsFactory.dual_chart_aspects(
|
|
237
237
|
ephemeris_point,
|
|
238
238
|
self.natal_chart,
|
|
239
239
|
active_points=self.active_points,
|
|
@@ -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
|
|
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
kerykeion/__init__.py,sha256=
|
|
2
|
-
kerykeion/astrological_subject_factory.py,sha256=
|
|
1
|
+
kerykeion/__init__.py,sha256=WTTZBOe40IuvcINRRrsqinEkTFzaJNbPcZ8iO6F3fvw,1274
|
|
2
|
+
kerykeion/astrological_subject_factory.py,sha256=TrnZ_jIphKzu7NqxlL5vp5JELzuPgxIz1KtrW7W2-5M,83655
|
|
3
3
|
kerykeion/composite_subject_factory.py,sha256=sqs7CiP_3lGI9-FeRFMFL7PIXTlSUaXA9pUDI_5zPZw,17124
|
|
4
4
|
kerykeion/ephemeris_data_factory.py,sha256=Iwd8KkBB-WmI8AEwrhe9ze8dicA5kvpflT_yQD9XkAY,20111
|
|
5
5
|
kerykeion/fetch_geonames.py,sha256=SPI4fSvD59C-IVpaoeOHuD7_kjGbTLo2fypO2x57-p4,5432
|
|
6
6
|
kerykeion/planetary_return_factory.py,sha256=7fwfjhJATFmUNJkIqgaz07sWtpwHPjHvF2oFyPGfga4,37246
|
|
7
|
-
kerykeion/relationship_score_factory.py,sha256=
|
|
7
|
+
kerykeion/relationship_score_factory.py,sha256=kcr0qEA4_2oQ_2g8IcrHgpVEyb9uAm4EmVWJAGsoCtg,11099
|
|
8
8
|
kerykeion/report.py,sha256=dUtI70wUjOouqNE1pf0ZYFY4qme9pR7WQRbs_ExEkjM,3029
|
|
9
|
-
kerykeion/transits_time_range_factory.py,sha256=
|
|
9
|
+
kerykeion/transits_time_range_factory.py,sha256=xFEdOqYINTBluwp-CKeYTJgANlPEeVw4TYMLigiC30M,13392
|
|
10
10
|
kerykeion/utilities.py,sha256=MtVyZ2dbHrJPuDoPKPrkx0MrB83fxcbGtPx87piHCtQ,23471
|
|
11
|
-
kerykeion/aspects/__init__.py,sha256=
|
|
11
|
+
kerykeion/aspects/__init__.py,sha256=csJmxvLdBu-bHuW676f3dpY__Qyc6LwRyrpWVTh3n1A,287
|
|
12
|
+
kerykeion/aspects/aspects_factory.py,sha256=09Hm50c5J-OiMwgsoxZXWidCBgZc2gzhwz95MdHJUy4,22664
|
|
12
13
|
kerykeion/aspects/aspects_utils.py,sha256=mOj2AqVGnY2vsGsezPfxI_crPJsN54p8qjpmCk5iupM,3093
|
|
13
|
-
kerykeion/aspects/natal_aspects_factory.py,sha256=If-XV1_QLpQPKjka_dJjMOqhAyAIi7icwxhhOEhwzm4,9318
|
|
14
|
-
kerykeion/aspects/synastry_aspects_factory.py,sha256=NpOn-h6nqKbkVpDucn8i-3lW_tqNZyUOQGNXCJ36ULU,12690
|
|
15
14
|
kerykeion/charts/__init__.py,sha256=i9NMZ7LdkllPlqQSi1or9gTobHbROGDKmJhBDO4R0mA,128
|
|
16
15
|
kerykeion/charts/charts_utils.py,sha256=_z-lA7ibIQ5vhr1NxpzJFyPmMp-Sh1iyYxuO56DDO4w,62922
|
|
17
16
|
kerykeion/charts/draw_planets.py,sha256=6S0sCAktZJa7eckb-h1voYbe0H27vL9otcJzA0dqFH0,28167
|
|
18
|
-
kerykeion/charts/kerykeion_chart_svg.py,sha256=
|
|
17
|
+
kerykeion/charts/kerykeion_chart_svg.py,sha256=pNSmGZYtFGSx17EKcdSSYunP_oKy3xLSiq_CmbGz8Fs,97285
|
|
19
18
|
kerykeion/charts/templates/aspect_grid_only.xml,sha256=lBHBj5bS5klGnv7QMuFxQjhlE6VZRaOgW93akLgRjX4,70055
|
|
20
19
|
kerykeion/charts/templates/chart.xml,sha256=r3a_csMqcoqeOnDA3YCD-iUxdqgRw5GV1GOf1Cp0e_E,79940
|
|
21
20
|
kerykeion/charts/templates/wheel_only.xml,sha256=X2-bwmEvQnZcM5Om7JXIWZSoSmFLAm4sY31heSq5u1k,71388
|
|
@@ -25,14 +24,14 @@ kerykeion/charts/themes/dark.css,sha256=XVspznDRNMXsFzk7hY7IB7AI58alPAV_-CgV3gCK
|
|
|
25
24
|
kerykeion/charts/themes/light.css,sha256=5eyUzhVlRjG6lPHKnprLum0HuRtPIJhMBzpGfzoTjnQ,7590
|
|
26
25
|
kerykeion/charts/themes/strawberry.css,sha256=UtcfRsCT-M9OZs_SoclWGZ0jDJiWvQjHTeI4M1jf7pQ,8314
|
|
27
26
|
kerykeion/house_comparison/__init__.py,sha256=6FYHyQY3nUJifZ2kEVCHB8cN3TjFA1q2yhmeRwJlias,238
|
|
28
|
-
kerykeion/house_comparison/house_comparison_factory.py,sha256=
|
|
29
|
-
kerykeion/house_comparison/house_comparison_models.py,sha256=
|
|
30
|
-
kerykeion/house_comparison/house_comparison_utils.py,sha256=
|
|
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
|
|
31
30
|
kerykeion/kr_types/__init__.py,sha256=dePcQY5rrgtUENhqnjcVx6j7iQJPo_1rmD0bLeIO3HA,1384
|
|
32
31
|
kerykeion/kr_types/chart_types.py,sha256=ofMYk7NRalSsdQcLVkpCbOb-dhdjYHEqIb_WPLtD0rM,2429
|
|
33
32
|
kerykeion/kr_types/kerykeion_exception.py,sha256=vTYdwj_mL-Q-MqHJvEzzBXxQ5YI2kAwUC6ImoWxMKXc,454
|
|
34
33
|
kerykeion/kr_types/kr_literals.py,sha256=4kJhzm_0LERiJEJks0KgDyThueMZj_F1OK2Far5SMZc,4870
|
|
35
|
-
kerykeion/kr_types/kr_models.py,sha256=
|
|
34
|
+
kerykeion/kr_types/kr_models.py,sha256=5wG3bh7EvCD0FTYe-W2e8jNLK408f3JQQhda6DVrOnw,14180
|
|
36
35
|
kerykeion/kr_types/settings_models.py,sha256=Llosnvw-6NHJMbdKltPHQDLR-Ltn7ZpWkjEbLJ2C6AY,17488
|
|
37
36
|
kerykeion/settings/__init__.py,sha256=NYCwcvEfn9qJ498fv1H_Gix8e-crJ3CruV13A-e2CnI,134
|
|
38
37
|
kerykeion/settings/config_constants.py,sha256=hxDZnFKWFhGrYMejDISbYT-phUk1Qqfvt-4wBG79rGA,2233
|
|
@@ -44,7 +43,8 @@ kerykeion/settings/legacy/legacy_chart_aspects_settings.py,sha256=tO4tgPgPP07_wu
|
|
|
44
43
|
kerykeion/settings/legacy/legacy_color_settings.py,sha256=gBUmGSNvvLzRYbdVtzwTDnMwWoh4tOCyT_9Q6aQRv_s,2620
|
|
45
44
|
kerykeion/sweph/README.md,sha256=L7FtNAJTWtrZNGKa8MX87SjduFYPYxwWhaI5fmtzNZo,73
|
|
46
45
|
kerykeion/sweph/seas_18.se1,sha256=X9nCqhZU43wJpq61WAdueVQJt9xL2UjrwPqn1Kdoa1s,223002
|
|
47
|
-
kerykeion
|
|
48
|
-
kerykeion-5.0.
|
|
49
|
-
kerykeion-5.0.
|
|
50
|
-
kerykeion-5.0.
|
|
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,,
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
This is part of Kerykeion (C) 2025 Giacomo Battaglia
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import logging
|
|
7
|
-
from typing import Union, List, Optional
|
|
8
|
-
|
|
9
|
-
from kerykeion.astrological_subject_factory import AstrologicalSubjectFactory
|
|
10
|
-
from kerykeion.aspects.aspects_utils import get_aspect_from_two_points, get_active_points_list
|
|
11
|
-
from kerykeion.kr_types.kr_models import AstrologicalSubjectModel, AspectModel, ActiveAspect, CompositeSubjectModel, PlanetReturnModel, NatalAspectsModel
|
|
12
|
-
from kerykeion.kr_types.kr_literals import AstrologicalPoint
|
|
13
|
-
from kerykeion.settings.config_constants import DEFAULT_ACTIVE_ASPECTS, DEFAULT_AXIS_ORBIT
|
|
14
|
-
from kerykeion.settings.legacy.legacy_celestial_points_settings import DEFAULT_CELESTIAL_POINTS_SETTINGS
|
|
15
|
-
from kerykeion.settings.legacy.legacy_chart_aspects_settings import DEFAULT_CHART_ASPECTS_SETTINGS
|
|
16
|
-
from kerykeion.utilities import find_common_active_points
|
|
17
|
-
|
|
18
|
-
# Axes constants for orb filtering
|
|
19
|
-
AXES_LIST = [
|
|
20
|
-
"Ascendant",
|
|
21
|
-
"Medium_Coeli",
|
|
22
|
-
"Descendant",
|
|
23
|
-
"Imum_Coeli",
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class NatalAspectsFactory:
|
|
28
|
-
"""
|
|
29
|
-
Factory class for creating natal aspects analysis.
|
|
30
|
-
|
|
31
|
-
This factory calculates all aspects in a birth chart and provides both
|
|
32
|
-
comprehensive and filtered aspect lists based on orb settings and relevance.
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
@staticmethod
|
|
36
|
-
def from_subject(
|
|
37
|
-
user: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
|
|
38
|
-
*,
|
|
39
|
-
active_points: Optional[List[AstrologicalPoint]] = None,
|
|
40
|
-
active_aspects: Optional[List[ActiveAspect]] = None,
|
|
41
|
-
) -> NatalAspectsModel:
|
|
42
|
-
"""
|
|
43
|
-
Create natal aspects analysis from an existing astrological subject.
|
|
44
|
-
|
|
45
|
-
Args:
|
|
46
|
-
user: The astrological subject for aspect calculation
|
|
47
|
-
|
|
48
|
-
Kwargs:
|
|
49
|
-
active_points: List of points to include in calculations
|
|
50
|
-
active_aspects: List of aspects with their orb settings
|
|
51
|
-
|
|
52
|
-
Returns:
|
|
53
|
-
NatalAspectsModel containing all calculated aspects data
|
|
54
|
-
"""
|
|
55
|
-
# Initialize settings and configurations
|
|
56
|
-
celestial_points = DEFAULT_CELESTIAL_POINTS_SETTINGS
|
|
57
|
-
aspects_settings = DEFAULT_CHART_ASPECTS_SETTINGS
|
|
58
|
-
axes_orbit_settings = DEFAULT_AXIS_ORBIT
|
|
59
|
-
|
|
60
|
-
# Set active aspects with default fallback
|
|
61
|
-
active_aspects_resolved = active_aspects if active_aspects is not None else DEFAULT_ACTIVE_ASPECTS
|
|
62
|
-
|
|
63
|
-
# Determine active points to use
|
|
64
|
-
if active_points is None:
|
|
65
|
-
active_points_resolved = user.active_points
|
|
66
|
-
else:
|
|
67
|
-
active_points_resolved = find_common_active_points(
|
|
68
|
-
user.active_points,
|
|
69
|
-
active_points,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
return NatalAspectsFactory._create_natal_aspects_model(
|
|
73
|
-
user, active_points_resolved, active_aspects_resolved,
|
|
74
|
-
aspects_settings, axes_orbit_settings, celestial_points
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
@staticmethod
|
|
78
|
-
def _create_natal_aspects_model(
|
|
79
|
-
user: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
|
|
80
|
-
active_points_resolved: List[AstrologicalPoint],
|
|
81
|
-
active_aspects_resolved: List[ActiveAspect],
|
|
82
|
-
aspects_settings: List[dict],
|
|
83
|
-
axes_orbit_settings: float,
|
|
84
|
-
celestial_points: List[dict]
|
|
85
|
-
) -> NatalAspectsModel:
|
|
86
|
-
"""
|
|
87
|
-
Create the complete natal aspects model with all calculations.
|
|
88
|
-
|
|
89
|
-
Returns:
|
|
90
|
-
NatalAspectsModel containing all aspects data
|
|
91
|
-
"""
|
|
92
|
-
all_aspects = NatalAspectsFactory._calculate_all_aspects(
|
|
93
|
-
user, active_points_resolved, active_aspects_resolved, aspects_settings, celestial_points
|
|
94
|
-
)
|
|
95
|
-
relevant_aspects = NatalAspectsFactory._filter_relevant_aspects(all_aspects, axes_orbit_settings)
|
|
96
|
-
|
|
97
|
-
return NatalAspectsModel(
|
|
98
|
-
subject=user,
|
|
99
|
-
all_aspects=all_aspects,
|
|
100
|
-
relevant_aspects=relevant_aspects,
|
|
101
|
-
active_points=active_points_resolved,
|
|
102
|
-
active_aspects=active_aspects_resolved,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
@staticmethod
|
|
106
|
-
def _calculate_all_aspects(
|
|
107
|
-
user: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
|
|
108
|
-
active_points: List[AstrologicalPoint],
|
|
109
|
-
active_aspects: List[ActiveAspect],
|
|
110
|
-
aspects_settings: List[dict],
|
|
111
|
-
celestial_points: List[dict]
|
|
112
|
-
) -> List[AspectModel]:
|
|
113
|
-
"""
|
|
114
|
-
Calculate all aspects between active points in the natal chart.
|
|
115
|
-
|
|
116
|
-
This method handles all aspect calculations including settings updates,
|
|
117
|
-
opposite pair filtering, and planet ID resolution in a single comprehensive method.
|
|
118
|
-
|
|
119
|
-
Returns:
|
|
120
|
-
List of all calculated AspectModel instances
|
|
121
|
-
"""
|
|
122
|
-
active_points_list = get_active_points_list(user, active_points)
|
|
123
|
-
|
|
124
|
-
# Update aspects settings with active aspects orbs
|
|
125
|
-
filtered_settings = []
|
|
126
|
-
for aspect_setting in aspects_settings:
|
|
127
|
-
for active_aspect in active_aspects:
|
|
128
|
-
if aspect_setting["name"] == active_aspect["name"]:
|
|
129
|
-
aspect_setting = aspect_setting.copy() # Don't modify original
|
|
130
|
-
aspect_setting["orb"] = active_aspect["orb"]
|
|
131
|
-
filtered_settings.append(aspect_setting)
|
|
132
|
-
break
|
|
133
|
-
|
|
134
|
-
# Define opposite pairs that should be skipped
|
|
135
|
-
opposite_pairs = {
|
|
136
|
-
("Ascendant", "Descendant"),
|
|
137
|
-
("Descendant", "Ascendant"),
|
|
138
|
-
("Medium_Coeli", "Imum_Coeli"),
|
|
139
|
-
("Imum_Coeli", "Medium_Coeli"),
|
|
140
|
-
("True_Node", "True_South_Node"),
|
|
141
|
-
("Mean_Node", "Mean_South_Node"),
|
|
142
|
-
("True_South_Node", "True_Node"),
|
|
143
|
-
("Mean_South_Node", "Mean_Node"),
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
all_aspects_list = []
|
|
147
|
-
|
|
148
|
-
for first in range(len(active_points_list)):
|
|
149
|
-
# Generate aspects list without repetitions
|
|
150
|
-
for second in range(first + 1, len(active_points_list)):
|
|
151
|
-
# Skip predefined opposite pairs (AC/DC, MC/IC, North/South nodes)
|
|
152
|
-
first_name = active_points_list[first]["name"]
|
|
153
|
-
second_name = active_points_list[second]["name"]
|
|
154
|
-
|
|
155
|
-
if (first_name, second_name) in opposite_pairs:
|
|
156
|
-
continue
|
|
157
|
-
|
|
158
|
-
aspect = get_aspect_from_two_points(
|
|
159
|
-
filtered_settings,
|
|
160
|
-
active_points_list[first]["abs_pos"],
|
|
161
|
-
active_points_list[second]["abs_pos"]
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
if aspect["verdict"]:
|
|
165
|
-
# Get planet IDs directly from celestial points settings
|
|
166
|
-
first_planet_id = 0
|
|
167
|
-
second_planet_id = 0
|
|
168
|
-
|
|
169
|
-
for planet in celestial_points:
|
|
170
|
-
if planet["name"] == first_name:
|
|
171
|
-
first_planet_id = planet["id"]
|
|
172
|
-
if planet["name"] == second_name:
|
|
173
|
-
second_planet_id = planet["id"]
|
|
174
|
-
|
|
175
|
-
aspect_model = AspectModel(
|
|
176
|
-
p1_name=first_name,
|
|
177
|
-
p1_owner=user.name,
|
|
178
|
-
p1_abs_pos=active_points_list[first]["abs_pos"],
|
|
179
|
-
p2_name=second_name,
|
|
180
|
-
p2_owner=user.name,
|
|
181
|
-
p2_abs_pos=active_points_list[second]["abs_pos"],
|
|
182
|
-
aspect=aspect["name"],
|
|
183
|
-
orbit=aspect["orbit"],
|
|
184
|
-
aspect_degrees=aspect["aspect_degrees"],
|
|
185
|
-
diff=aspect["diff"],
|
|
186
|
-
p1=first_planet_id,
|
|
187
|
-
p2=second_planet_id,
|
|
188
|
-
)
|
|
189
|
-
all_aspects_list.append(aspect_model)
|
|
190
|
-
|
|
191
|
-
return all_aspects_list
|
|
192
|
-
|
|
193
|
-
@staticmethod
|
|
194
|
-
def _filter_relevant_aspects(all_aspects: List[AspectModel], axes_orbit_settings: float) -> List[AspectModel]:
|
|
195
|
-
"""
|
|
196
|
-
Filter aspects based on orb thresholds for axes and other comprehensive criteria.
|
|
197
|
-
|
|
198
|
-
This method consolidates all filtering logic including axes checks and orb thresholds
|
|
199
|
-
into a single comprehensive filtering method.
|
|
200
|
-
|
|
201
|
-
Args:
|
|
202
|
-
all_aspects: Complete list of calculated aspects
|
|
203
|
-
axes_orbit_settings: Orb threshold for axes aspects
|
|
204
|
-
|
|
205
|
-
Returns:
|
|
206
|
-
Filtered list of relevant aspects
|
|
207
|
-
"""
|
|
208
|
-
logging.debug("Calculating relevant aspects by filtering orbs...")
|
|
209
|
-
|
|
210
|
-
relevant_aspects = []
|
|
211
|
-
|
|
212
|
-
for aspect in all_aspects:
|
|
213
|
-
# Check if aspect involves any of the chart axes and apply stricter orb limits
|
|
214
|
-
aspect_involves_axes = (aspect.p1_name in AXES_LIST or aspect.p2_name in AXES_LIST)
|
|
215
|
-
|
|
216
|
-
if aspect_involves_axes and abs(aspect.orbit) >= axes_orbit_settings:
|
|
217
|
-
continue
|
|
218
|
-
|
|
219
|
-
relevant_aspects.append(aspect)
|
|
220
|
-
|
|
221
|
-
return relevant_aspects
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if __name__ == "__main__":
|
|
225
|
-
from kerykeion.utilities import setup_logging
|
|
226
|
-
|
|
227
|
-
setup_logging(level="debug")
|
|
228
|
-
|
|
229
|
-
# Create subject using AstrologicalSubjectFactory
|
|
230
|
-
johnny = AstrologicalSubjectFactory.from_birth_data("Johnny Depp", 1963, 6, 9, 0, 0, city="Owensboro", nation="US")
|
|
231
|
-
|
|
232
|
-
# Create aspects analysis from subject
|
|
233
|
-
natal_aspects = NatalAspectsFactory.from_subject(johnny)
|
|
234
|
-
print(f"All aspects count: {len(natal_aspects.all_aspects)}")
|
|
235
|
-
print(f"Relevant aspects count: {len(natal_aspects.relevant_aspects)}")
|