kerykeion 5.0.0a9__tar.gz → 5.0.0a11__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 (204) hide show
  1. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/.gitignore +1 -1
  2. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/PKG-INFO +9 -4
  3. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/__init__.py +21 -4
  4. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/aspects/__init__.py +7 -2
  5. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/aspects/aspects_utils.py +1 -3
  6. kerykeion-5.0.0a11/kerykeion/aspects/natal_aspects_factory.py +235 -0
  7. kerykeion-5.0.0a11/kerykeion/aspects/synastry_aspects_factory.py +275 -0
  8. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/astrological_subject_factory.py +688 -86
  9. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/charts_utils.py +12 -12
  10. kerykeion-5.0.0a9/kerykeion/charts/draw_planets_v2.py → kerykeion-5.0.0a11/kerykeion/charts/draw_planets.py +21 -22
  11. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/kerykeion_chart_svg.py +11 -16
  12. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/templates/wheel_only.xml +1 -1
  13. kerykeion-5.0.0a11/kerykeion/composite_subject_factory.py +408 -0
  14. kerykeion-5.0.0a11/kerykeion/ephemeris_data_factory.py +431 -0
  15. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/fetch_geonames.py +27 -8
  16. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/house_comparison/__init__.py +6 -0
  17. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/house_comparison/house_comparison_factory.py +1 -1
  18. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/house_comparison/house_comparison_utils.py +0 -1
  19. kerykeion-5.0.0a11/kerykeion/kr_types/__init__.py +59 -0
  20. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/kr_types/kerykeion_exception.py +6 -0
  21. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/kr_types/kr_models.py +84 -2
  22. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/kr_types/settings_models.py +9 -1
  23. kerykeion-5.0.0a11/kerykeion/planetary_return_factory.py +801 -0
  24. kerykeion-5.0.0a11/kerykeion/relationship_score_factory.py +291 -0
  25. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/report.py +7 -1
  26. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/settings/__init__.py +5 -0
  27. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/settings/config_constants.py +20 -6
  28. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/settings/kr.config.json +80 -0
  29. kerykeion-5.0.0a11/kerykeion/transits_time_range_factory.py +293 -0
  30. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/utilities.py +130 -68
  31. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/pyproject.toml +26 -19
  32. kerykeion-5.0.0a11/test_utils/README.md +3 -0
  33. kerykeion-5.0.0a11/test_utils/regenerate_expected_aspects.py +94 -0
  34. kerykeion-5.0.0a11/test_utils/regenerate_synastry_aspects.py +43 -0
  35. kerykeion-5.0.0a11/test_utils/regenerate_synastry_from_test.py +40 -0
  36. kerykeion-5.0.0a9/tests/charts/generate_test_charts.py → kerykeion-5.0.0a11/test_utils/regenerate_test_charts.py +112 -90
  37. kerykeion-5.0.0a11/tests/aspects/expected_natal_aspects.py +985 -0
  38. kerykeion-5.0.0a11/tests/aspects/expected_synastry_aspects.py +1853 -0
  39. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/aspects/test_natal_aspects.py +3 -3
  40. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/aspects/test_synastry_aspects.py +3 -3
  41. kerykeion-5.0.0a11/tests/charts/svg/Albert Einstein - Natal Chart.svg +802 -0
  42. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Amitabh Bachchan - Natal Chart.svg +294 -161
  43. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Angelina Jolie and Brad Pitt Composite Chart - Composite Chart.svg +287 -154
  44. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Antonio Banderas - Natal Chart.svg +294 -161
  45. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Cristiano Ronaldo - Natal Chart.svg +294 -161
  46. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Aspect Grid Transit - Transit Chart - Aspect Grid Only.svg → kerykeion-5.0.0a11/tests/charts/svg/Grid - Transit Chart - Aspect Grid Only.svg +145 -80
  47. kerykeion-5.0.0a11/tests/charts/svg/Grid - Transit Chart - Wheel Only.svg +672 -0
  48. kerykeion-5.0.0a11/tests/charts/svg/Grid - Transit Chart.svg +849 -0
  49. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Hua Chenyu - Natal Chart.svg +295 -162
  50. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Jeanne Moreau - Natal Chart.svg +294 -161
  51. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Aspect Grid Dark Synastry - Synastry Chart - Aspect Grid Only.svg +137 -111
  52. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Aspect Grid Only - Natal Chart - Aspect Grid Only.svg → kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Aspect Grid Dark Theme - Natal Chart - Aspect Grid Only.svg +145 -80
  53. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Aspect Grid Light Theme - Natal Chart - Aspect Grid Only.svg +137 -107
  54. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Aspect Grid Dark Theme - Natal Chart - Aspect Grid Only.svg → kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Aspect Grid Only - Natal Chart - Aspect Grid Only.svg +96 -117
  55. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Aspect Grid Synastry - Synastry Chart - Aspect Grid Only.svg +98 -80
  56. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Aspect Grid Transit - Transit Chart - Aspect Grid Only.svg +570 -0
  57. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - DTS - Synastry Chart.svg +840 -0
  58. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Heliocentric - Natal Chart.svg → kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Dark High Contrast Theme - Natal Chart.svg +344 -165
  59. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Dark Theme - Natal Chart.svg +849 -0
  60. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Dark Theme External - ExternalNatal Chart.svg +347 -210
  61. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - ExternalNatal Chart.svg +300 -171
  62. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Heliocentric - Natal Chart.svg +802 -0
  63. kerykeion-5.0.0a9/tests/charts/svg/John Lennon Lahiri - Natal Chart.svg → kerykeion-5.0.0a11/tests/charts/svg/John Lennon - House System Morinus - Natal Chart.svg +297 -164
  64. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Light Theme - Natal Chart.svg +849 -0
  65. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Minified - Natal Chart.svg +1 -0
  66. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Natal Chart.svg +293 -160
  67. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Return Chart - Lunar Return.svg +849 -0
  68. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Return Chart - Solar Return.svg +802 -0
  69. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - SCTWL - Synastry Chart.svg +840 -0
  70. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Synastry Chart.svg +793 -0
  71. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - TCWTG - Transit Chart.svg +849 -0
  72. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Topocentric - Natal Chart.svg +293 -160
  73. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Transit Chart.svg +802 -0
  74. kerykeion-5.0.0a11/tests/charts/svg/John Lennon - Transparent Background - Natal Chart.svg +802 -0
  75. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - True Geocentric - Natal Chart.svg +293 -160
  76. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Wheel External Only - ExternalNatal Chart - Wheel Only.svg +125 -103
  77. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Wheel Only - Natal Chart - Wheel Only.svg +118 -92
  78. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Wheel Synastry Only - Synastry Chart - Wheel Only.svg +118 -92
  79. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon - Wheel Transit Only - Transit Chart - Wheel Only.svg +118 -92
  80. kerykeion-5.0.0a9/tests/charts/svg/John Lennon Fagan-Bradley - Natal Chart.svg → kerykeion-5.0.0a11/tests/charts/svg/John Lennon DeLuce - Natal Chart.svg +296 -163
  81. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon Fagan-Bradley - Light Theme - Natal Chart - Wheel Only.svg +157 -119
  82. kerykeion-5.0.0a11/tests/charts/svg/John Lennon Fagan-Bradley - Natal Chart.svg +802 -0
  83. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon J2000 - Natal Chart.svg +293 -160
  84. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/John Lennon Lahiri - Dark Theme - Natal Chart - Wheel Only.svg +157 -123
  85. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - House System Morinus - Natal Chart.svg → kerykeion-5.0.0a11/tests/charts/svg/John Lennon Lahiri - Natal Chart.svg +297 -164
  86. kerykeion-5.0.0a11/tests/charts/svg/John Lennon Solar Return - SingleWheelReturn Chart.svg +849 -0
  87. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Kanye - Natal Chart.svg +293 -160
  88. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Light Theme - Natal Chart.svg → kerykeion-5.0.0a11/tests/charts/svg/Mehmet Oz - Natal Chart.svg +301 -203
  89. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Mikhail Bulgakov - Natal Chart.svg +294 -161
  90. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/svg/Sophia Loren - Natal Chart.svg +294 -161
  91. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/settings/test-settings.json +311 -11
  92. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_astrological_subject.py +0 -52
  93. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_astrological_subject_jyotish.py +0 -26
  94. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_json_dump.py +1 -1
  95. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_relationship_score.py +8 -8
  96. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_utc.py +0 -1
  97. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_utilities.py +1 -1
  98. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/uv.lock +29 -72
  99. kerykeion-5.0.0a9/kerykeion/aspects/natal_aspects.py +0 -181
  100. kerykeion-5.0.0a9/kerykeion/aspects/synastry_aspects.py +0 -141
  101. kerykeion-5.0.0a9/kerykeion/aspects/transits_time_range.py +0 -41
  102. kerykeion-5.0.0a9/kerykeion/charts/draw_planets.py +0 -408
  103. kerykeion-5.0.0a9/kerykeion/charts/draw_planets_v3.py +0 -679
  104. kerykeion-5.0.0a9/kerykeion/composite_subject_factory.py +0 -189
  105. kerykeion-5.0.0a9/kerykeion/enums.py +0 -57
  106. kerykeion-5.0.0a9/kerykeion/ephemeris_data.py +0 -238
  107. kerykeion-5.0.0a9/kerykeion/kr_types/__init__.py +0 -10
  108. kerykeion-5.0.0a9/kerykeion/planetary_return_factory.py +0 -300
  109. kerykeion-5.0.0a9/kerykeion/relationship_score_factory.py +0 -227
  110. kerykeion-5.0.0a9/kerykeion/transits_time_range.py +0 -128
  111. kerykeion-5.0.0a9/tests/aspects/expected_natal_aspects.py +0 -1237
  112. kerykeion-5.0.0a9/tests/aspects/expected_synastry_aspects.py +0 -2861
  113. kerykeion-5.0.0a9/tests/charts/svg/Albert Einstein - Natal Chart.svg +0 -669
  114. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - DTS - Synastry Chart.svg +0 -699
  115. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Dark High Contrast Theme - Natal Chart.svg +0 -708
  116. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Dark Theme - Natal Chart.svg +0 -708
  117. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Minified - Natal Chart.svg +0 -1
  118. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - SCTWL - Synastry Chart.svg +0 -699
  119. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Synastry Chart.svg +0 -660
  120. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - TCWTG - Transit Chart.svg +0 -708
  121. kerykeion-5.0.0a9/tests/charts/svg/John Lennon - Transit Chart.svg +0 -669
  122. kerykeion-5.0.0a9/tests/charts/svg/John Lennon DeLuce - Natal Chart.svg +0 -669
  123. kerykeion-5.0.0a9/tests/charts/svg/Mehmet Oz - Natal Chart.svg +0 -669
  124. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/.github/FUNDING.yml +0 -0
  125. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/CHANGELOG.md +0 -0
  126. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/DEVELOPMENT.md +0 -0
  127. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/LICENSE +0 -0
  128. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/MANIFEST.in +0 -0
  129. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/README.md +0 -0
  130. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/TODO.md +0 -0
  131. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/index.html +0 -0
  132. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/aspects/aspects_utils.html +0 -0
  133. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/aspects/natal_aspects.html +0 -0
  134. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/aspects/synastry_aspects.html +0 -0
  135. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/aspects/transits_time_range.html +0 -0
  136. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/aspects.html +0 -0
  137. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/astrological_subject.html +0 -0
  138. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/charts/charts_utils.html +0 -0
  139. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/charts/draw_planets.html +0 -0
  140. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/charts/kerykeion_chart_svg.html +0 -0
  141. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/charts.html +0 -0
  142. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/composite_subject_factory.html +0 -0
  143. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/enums.html +0 -0
  144. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/ephemeris_data.html +0 -0
  145. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/fetch_geonames.html +0 -0
  146. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/kr_types/chart_types.html +0 -0
  147. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/kr_types/kerykeion_exception.html +0 -0
  148. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/kr_types/kr_literals.html +0 -0
  149. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/kr_types/kr_models.html +0 -0
  150. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/kr_types/settings_models.html +0 -0
  151. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/kr_types.html +0 -0
  152. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/relationship_score/relationship_score.html +0 -0
  153. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/relationship_score/relationship_score_factory.html +0 -0
  154. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/relationship_score.html +0 -0
  155. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/report.html +0 -0
  156. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/settings/config_constants.html +0 -0
  157. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/settings/kerykeion_settings.html +0 -0
  158. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/settings.html +0 -0
  159. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/transits_time_range.html +0 -0
  160. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion/utilities.html +0 -0
  161. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/kerykeion.html +0 -0
  162. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/docs/search.js +0 -0
  163. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/examples/README.md +0 -0
  164. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/examples/astrologiacal_subject.py +0 -0
  165. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/examples/charts/composite_chart.py +0 -0
  166. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/examples/charts/kerykeion_chart_svg.py +0 -0
  167. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/__init__.py +0 -0
  168. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/templates/aspect_grid_only.xml +0 -0
  169. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/templates/chart.xml +0 -0
  170. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/themes/classic.css +0 -0
  171. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/themes/dark-high-contrast.css +0 -0
  172. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/themes/dark.css +0 -0
  173. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/themes/light.css +0 -0
  174. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/charts/themes/strawberry.css +0 -0
  175. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/house_comparison/house_comparison_models.py +0 -0
  176. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/kr_types/chart_types.py +0 -0
  177. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/kr_types/kr_literals.py +0 -0
  178. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/settings/kerykeion_settings.py +0 -0
  179. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/settings/legacy/__init__.py +0 -0
  180. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/settings/legacy/legacy_celestial_points_settings.py +0 -0
  181. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/settings/legacy/legacy_chart_aspects_settings.py +0 -0
  182. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/settings/legacy/legacy_color_settings.py +0 -0
  183. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/sweph/README.md +0 -0
  184. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/kerykeion/sweph/seas_18.se1 +0 -0
  185. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.14.0.md +0 -0
  186. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.16.0.md +0 -0
  187. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.17.0.md +0 -0
  188. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.19.0.md +0 -0
  189. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.21.0.md +0 -0
  190. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.22.0.md +0 -0
  191. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.23.0.md +0 -0
  192. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.24.0.md +0 -0
  193. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.25.0.md +0 -0
  194. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/V4.26.0.md +0 -0
  195. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/release_notes/v5.0.0a1.md +0 -0
  196. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/__init__.py +0 -0
  197. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/aspects/__init__.py +0 -0
  198. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/__init__.py +0 -0
  199. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/compare_svg_lines.py +0 -0
  200. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/charts/test_charts.py +0 -0
  201. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/settings/test_settings.py +0 -0
  202. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_ephemeris_data.py +0 -0
  203. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_fetch_geonames.py +0 -0
  204. {kerykeion-5.0.0a9 → kerykeion-5.0.0a11}/tests/test_report.py +0 -0
@@ -51,4 +51,4 @@ dist/
51
51
  kr_venv
52
52
  request_cache
53
53
  Pipfile
54
- .mypy_cache
54
+ .mypy_cache
@@ -1,23 +1,28 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kerykeion
3
- Version: 5.0.0a9
4
- Summary: A python library for astrology.
3
+ Version: 5.0.0a11
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
7
7
  Author-email: Giacomo Battaglia <kerykeion.astrology@gmail.com>
8
8
  License: AGPL-3.0
9
9
  License-File: LICENSE
10
- Keywords: astrology,astrology library,astrology-calculator,astronomical-algorithms,birtchart,ephemeris,svg,synastry,zodiac,zodiac-sing
10
+ Keywords: astrology,astrology calculations,astrology calculator,astrology library,astrology transits,astronomical algorithms,birth chart,ephemeris,houses of astrology,natal chart,planetary aspects,svg charts,synastry,zodiac,zodiac signs
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: Intended Audience :: Information Technology
14
- Classifier: License :: OSI Approved :: GNU General Public License (GPL)
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
15
16
  Classifier: Operating System :: OS Independent
16
17
  Classifier: Programming Language :: Python :: 3 :: Only
17
18
  Classifier: Programming Language :: Python :: 3.9
18
19
  Classifier: Programming Language :: Python :: 3.10
19
20
  Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Religion
20
24
  Classifier: Topic :: Scientific/Engineering :: Astronomy
25
+ Classifier: Topic :: Scientific/Engineering :: Visualization
21
26
  Classifier: Topic :: Software Development
22
27
  Classifier: Topic :: Software Development :: Libraries
23
28
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -6,12 +6,11 @@ This is part of Kerykeion (C) 2025 Giacomo Battaglia
6
6
  """
7
7
 
8
8
  # Local
9
- from .aspects import SynastryAspects, NatalAspects
9
+ from .aspects import SynastryAspectsFactory, NatalAspectsFactory
10
10
  from .astrological_subject_factory import AstrologicalSubjectFactory
11
11
  from .charts.kerykeion_chart_svg import KerykeionChartSVG
12
12
  from .composite_subject_factory import CompositeSubjectFactory
13
- from .enums import Planets, Aspects, Signs
14
- from .ephemeris_data import EphemerisDataFactory
13
+ from .ephemeris_data_factory import EphemerisDataFactory
15
14
  from .house_comparison.house_comparison_factory import HouseComparisonFactory
16
15
  from .house_comparison.house_comparison_models import HouseComparisonModel
17
16
  from .kr_types import *
@@ -19,4 +18,22 @@ from .planetary_return_factory import PlanetaryReturnFactory, PlanetReturnModel
19
18
  from .relationship_score_factory import RelationshipScoreFactory
20
19
  from .report import Report
21
20
  from .settings import KerykeionSettingsModel, get_settings
22
- from .transits_time_range import TransitsTimeRangeFactory
21
+ from .transits_time_range_factory import TransitsTimeRangeFactory
22
+
23
+ __all__ = [
24
+ "SynastryAspectsFactory",
25
+ "NatalAspectsFactory",
26
+ "AstrologicalSubjectFactory",
27
+ "KerykeionChartSVG",
28
+ "CompositeSubjectFactory",
29
+ "EphemerisDataFactory",
30
+ "HouseComparisonFactory",
31
+ "HouseComparisonModel",
32
+ "PlanetaryReturnFactory",
33
+ "PlanetReturnModel",
34
+ "RelationshipScoreFactory",
35
+ "Report",
36
+ "KerykeionSettingsModel",
37
+ "get_settings",
38
+ "TransitsTimeRangeFactory",
39
+ ]
@@ -7,5 +7,10 @@ The aspects module contains the classes and functions for calculating
7
7
  """
8
8
 
9
9
 
10
- from .synastry_aspects import SynastryAspects
11
- from .natal_aspects import NatalAspects
10
+ from .synastry_aspects_factory import SynastryAspectsFactory
11
+ from .natal_aspects_factory import NatalAspectsFactory
12
+
13
+ __all__ = [
14
+ "SynastryAspectsFactory",
15
+ "NatalAspectsFactory",
16
+ ]
@@ -4,17 +4,15 @@
4
4
  """
5
5
  # TODO: Better documentation and unit tests
6
6
 
7
- from kerykeion.settings import KerykeionSettingsModel
8
7
  from swisseph import difdeg2n
9
8
  from typing import Union, TYPE_CHECKING
10
9
  from kerykeion.kr_types.kr_models import AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel
11
- from kerykeion.kr_types.kr_literals import AstrologicalPoint
12
10
  from kerykeion.kr_types.settings_models import KerykeionSettingsCelestialPointModel
13
11
  from kerykeion.settings.legacy.legacy_celestial_points_settings import DEFAULT_CELESTIAL_POINTS_SETTINGS
14
12
 
15
13
 
16
14
  if TYPE_CHECKING:
17
- from kerykeion import AstrologicalSubjectFactory
15
+ pass
18
16
 
19
17
  def get_aspect_from_two_points(
20
18
  aspects_settings: Union[list[dict], list[dict]],
@@ -0,0 +1,235 @@
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)}")
@@ -0,0 +1,275 @@
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, SynastryAspectsModel
12
+ from kerykeion.settings.config_constants import DEFAULT_ACTIVE_ASPECTS, DEFAULT_AXIS_ORBIT
13
+ from kerykeion.settings.legacy.legacy_celestial_points_settings import DEFAULT_CELESTIAL_POINTS_SETTINGS
14
+ from kerykeion.settings.legacy.legacy_chart_aspects_settings import DEFAULT_CHART_ASPECTS_SETTINGS
15
+ from kerykeion.kr_types.kr_literals import AstrologicalPoint
16
+ from kerykeion.utilities import find_common_active_points
17
+
18
+
19
+ # Axes constants for orb filtering
20
+ AXES_LIST = [
21
+ "Ascendant",
22
+ "Medium_Coeli",
23
+ "Descendant",
24
+ "Imum_Coeli",
25
+ ]
26
+
27
+
28
+ class SynastryAspectsFactory:
29
+ """
30
+ Factory class for creating synastry aspects analysis between two astrological subjects.
31
+
32
+ This factory calculates all astrological aspects (angular relationships) between
33
+ planets and points in two different charts. It's primarily used for relationship
34
+ compatibility analysis, transit calculations, and comparative astrology.
35
+
36
+ The factory provides both comprehensive aspect lists and filtered relevant aspects
37
+ based on orb settings and chart axes considerations.
38
+
39
+ Key Features:
40
+ - Calculates all aspects between two subjects
41
+ - Filters aspects based on orb thresholds
42
+ - Applies stricter orb limits for chart axes (ASC, MC, DSC, IC)
43
+ - Supports multiple subject types (natal, composite, planetary returns)
44
+
45
+ Example:
46
+ >>> john = AstrologicalSubjectFactory.from_birth_data("John", 1990, 1, 1, 12, 0, "London", "GB")
47
+ >>> jane = AstrologicalSubjectFactory.from_birth_data("Jane", 1992, 6, 15, 14, 30, "Paris", "FR")
48
+ >>> synastry = SynastryAspectsFactory.from_subjects(john, jane)
49
+ >>> print(f"Found {len(synastry.relevant_aspects)} relevant aspects")
50
+ """
51
+
52
+ @staticmethod
53
+ def from_subjects(
54
+ first_subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
55
+ second_subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
56
+ *,
57
+ active_points: Optional[List[AstrologicalPoint]] = None,
58
+ active_aspects: Optional[List[ActiveAspect]] = None,
59
+ ) -> SynastryAspectsModel:
60
+ """
61
+ Create synastry aspects analysis between two astrological subjects.
62
+
63
+ This method calculates all astrological aspects (angular relationships)
64
+ between planets and points in two different birth charts, commonly used
65
+ for relationship compatibility analysis.
66
+
67
+ Args:
68
+ first_subject: The first astrological subject (person, composite chart, or planetary return)
69
+ second_subject: The second astrological subject to compare with the first
70
+ active_points: Optional list of celestial points to include in calculations.
71
+ If None, uses common points between both subjects.
72
+ active_aspects: Optional list of aspect types with their orb settings.
73
+ If None, uses default aspect configuration.
74
+
75
+ Returns:
76
+ SynastryAspectsModel: Complete model containing all calculated aspects data,
77
+ including both comprehensive and filtered relevant aspects.
78
+
79
+ Example:
80
+ >>> john = AstrologicalSubjectFactory.from_birth_data("John", 1990, 1, 1, 12, 0, "London", "GB")
81
+ >>> jane = AstrologicalSubjectFactory.from_birth_data("Jane", 1992, 6, 15, 14, 30, "Paris", "FR")
82
+ >>> synastry = SynastryAspectsFactory.from_subjects(john, jane)
83
+ >>> print(f"Found {len(synastry.relevant_aspects)} relevant aspects")
84
+ """
85
+ # Initialize settings and configurations
86
+ celestial_points = DEFAULT_CELESTIAL_POINTS_SETTINGS
87
+ aspects_settings = DEFAULT_CHART_ASPECTS_SETTINGS
88
+ axes_orbit_settings = DEFAULT_AXIS_ORBIT
89
+
90
+ # Set active aspects with default fallback
91
+ active_aspects_resolved = active_aspects if active_aspects is not None else DEFAULT_ACTIVE_ASPECTS
92
+
93
+ # Determine active points to use - find common points between both subjects
94
+ if active_points is None:
95
+ active_points_resolved = first_subject.active_points
96
+ else:
97
+ active_points_resolved = find_common_active_points(
98
+ first_subject.active_points,
99
+ active_points,
100
+ )
101
+
102
+ # Further filter with second subject's active points
103
+ active_points_resolved = find_common_active_points(
104
+ second_subject.active_points,
105
+ active_points_resolved,
106
+ )
107
+
108
+ return SynastryAspectsFactory._create_synastry_aspects_model(
109
+ first_subject, second_subject, active_points_resolved, active_aspects_resolved,
110
+ aspects_settings, axes_orbit_settings, celestial_points
111
+ )
112
+
113
+ @staticmethod
114
+ def _create_synastry_aspects_model(
115
+ first_subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
116
+ second_subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
117
+ active_points_resolved: List[AstrologicalPoint],
118
+ active_aspects_resolved: List[ActiveAspect],
119
+ aspects_settings: List[dict],
120
+ axes_orbit_settings: float,
121
+ celestial_points: List[dict]
122
+ ) -> SynastryAspectsModel:
123
+ """
124
+ Create the complete synastry aspects model with all calculations.
125
+
126
+ Args:
127
+ first_subject: First astrological subject
128
+ second_subject: Second astrological subject
129
+ active_points_resolved: Resolved list of active celestial points
130
+ active_aspects_resolved: Resolved list of active aspects with orbs
131
+ aspects_settings: Chart aspect configuration settings
132
+ axes_orbit_settings: Orb threshold for chart axes
133
+ celestial_points: Celestial points configuration
134
+
135
+ Returns:
136
+ SynastryAspectsModel: Complete model containing all aspects data
137
+ """
138
+ all_aspects = SynastryAspectsFactory._calculate_all_aspects(
139
+ first_subject, second_subject, active_points_resolved, active_aspects_resolved,
140
+ aspects_settings, celestial_points
141
+ )
142
+ relevant_aspects = SynastryAspectsFactory._filter_relevant_aspects(all_aspects, axes_orbit_settings)
143
+
144
+ return SynastryAspectsModel(
145
+ first_subject=first_subject,
146
+ second_subject=second_subject,
147
+ all_aspects=all_aspects,
148
+ relevant_aspects=relevant_aspects,
149
+ active_points=active_points_resolved,
150
+ active_aspects=active_aspects_resolved,
151
+ )
152
+
153
+ @staticmethod
154
+ def _calculate_all_aspects(
155
+ first_subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
156
+ second_subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
157
+ active_points: List[AstrologicalPoint],
158
+ active_aspects: List[ActiveAspect],
159
+ aspects_settings: List[dict],
160
+ celestial_points: List[dict]
161
+ ) -> List[AspectModel]:
162
+ """
163
+ Calculate all synastry aspects between two subjects.
164
+
165
+ This method performs comprehensive aspect calculations between all active points
166
+ of both subjects, applying the specified orb settings and creating detailed
167
+ aspect models with planet IDs and positional information.
168
+
169
+ Args:
170
+ first_subject: First astrological subject
171
+ second_subject: Second astrological subject
172
+ active_points: List of celestial points to include in calculations
173
+ active_aspects: List of aspect types with their orb settings
174
+ aspects_settings: Base aspect configuration settings
175
+ celestial_points: Celestial points configuration with IDs
176
+
177
+ Returns:
178
+ List[AspectModel]: Complete list of all calculated aspect instances
179
+ """
180
+ # Get active points lists for both subjects
181
+ first_active_points_list = get_active_points_list(first_subject, active_points)
182
+ second_active_points_list = get_active_points_list(second_subject, active_points)
183
+
184
+ # Create a lookup dictionary for planet IDs to optimize performance
185
+ planet_id_lookup = {planet["name"]: planet["id"] for planet in celestial_points}
186
+
187
+ # Update aspects settings with active aspects orbs
188
+ filtered_settings = []
189
+ for aspect_setting in aspects_settings:
190
+ for active_aspect in active_aspects:
191
+ if aspect_setting["name"] == active_aspect["name"]:
192
+ aspect_setting = aspect_setting.copy() # Don't modify original
193
+ aspect_setting["orb"] = active_aspect["orb"]
194
+ filtered_settings.append(aspect_setting)
195
+ break
196
+
197
+ all_aspects_list = []
198
+ for first in range(len(first_active_points_list)):
199
+ # Generate aspects list between all points of first and second subjects
200
+ for second in range(len(second_active_points_list)):
201
+ aspect = get_aspect_from_two_points(
202
+ filtered_settings,
203
+ first_active_points_list[first]["abs_pos"],
204
+ second_active_points_list[second]["abs_pos"],
205
+ )
206
+
207
+ if aspect["verdict"]:
208
+ first_name = first_active_points_list[first]["name"]
209
+ second_name = second_active_points_list[second]["name"]
210
+
211
+ # Get planet IDs using lookup dictionary for better performance
212
+ first_planet_id = planet_id_lookup.get(first_name, 0)
213
+ second_planet_id = planet_id_lookup.get(second_name, 0)
214
+
215
+ aspect_model = AspectModel(
216
+ p1_name=first_name,
217
+ p1_owner=first_subject.name,
218
+ p1_abs_pos=first_active_points_list[first]["abs_pos"],
219
+ p2_name=second_name,
220
+ p2_owner=second_subject.name,
221
+ p2_abs_pos=second_active_points_list[second]["abs_pos"],
222
+ aspect=aspect["name"],
223
+ orbit=aspect["orbit"],
224
+ aspect_degrees=aspect["aspect_degrees"],
225
+ diff=aspect["diff"],
226
+ p1=first_planet_id,
227
+ p2=second_planet_id,
228
+ )
229
+ all_aspects_list.append(aspect_model)
230
+
231
+ return all_aspects_list
232
+
233
+ @staticmethod
234
+ def _filter_relevant_aspects(all_aspects: List[AspectModel], axes_orbit_settings: float) -> List[AspectModel]:
235
+ """
236
+ Filter aspects based on orb thresholds for axes and comprehensive criteria.
237
+
238
+ This method consolidates all filtering logic including axes checks and orb thresholds
239
+ for synastry aspects in a single comprehensive filtering method.
240
+
241
+ Args:
242
+ all_aspects: Complete list of calculated aspects
243
+ axes_orbit_settings: Orb threshold for axes aspects
244
+
245
+ Returns:
246
+ Filtered list of relevant aspects
247
+ """
248
+ logging.debug("Calculating relevant synastry aspects by filtering orbs...")
249
+
250
+ relevant_aspects = []
251
+
252
+ for aspect in all_aspects:
253
+ # Check if aspect involves any of the chart axes and apply stricter orb limits
254
+ aspect_involves_axes = (aspect.p1_name in AXES_LIST or aspect.p2_name in AXES_LIST)
255
+
256
+ if aspect_involves_axes and abs(aspect.orbit) >= axes_orbit_settings:
257
+ continue
258
+
259
+ relevant_aspects.append(aspect)
260
+
261
+ return relevant_aspects
262
+
263
+
264
+ if __name__ == "__main__":
265
+ from kerykeion.utilities import setup_logging
266
+
267
+ setup_logging(level="debug")
268
+
269
+ john = AstrologicalSubjectFactory.from_birth_data("John", 1940, 10, 9, 10, 30, "Liverpool", "GB")
270
+ yoko = AstrologicalSubjectFactory.from_birth_data("Yoko", 1933, 2, 18, 10, 30, "Tokyo", "JP")
271
+
272
+ # Create synastry aspects analysis using the factory
273
+ synastry_aspects_model = SynastryAspectsFactory.from_subjects(john, yoko)
274
+ print(f"All synastry aspects: {len(synastry_aspects_model.all_aspects)}")
275
+ print(f"Relevant synastry aspects: {len(synastry_aspects_model.relevant_aspects)}")