kerykeion 5.0.0a11__py3-none-any.whl → 5.0.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of kerykeion might be problematic. Click here for more details.

Files changed (56) hide show
  1. kerykeion/__init__.py +32 -9
  2. kerykeion/aspects/__init__.py +2 -4
  3. kerykeion/aspects/aspects_factory.py +530 -0
  4. kerykeion/aspects/aspects_utils.py +75 -6
  5. kerykeion/astrological_subject_factory.py +380 -229
  6. kerykeion/backword.py +680 -0
  7. kerykeion/chart_data_factory.py +484 -0
  8. kerykeion/charts/{kerykeion_chart_svg.py → chart_drawer.py} +612 -439
  9. kerykeion/charts/charts_utils.py +135 -94
  10. kerykeion/charts/draw_planets.py +38 -28
  11. kerykeion/charts/templates/aspect_grid_only.xml +188 -17
  12. kerykeion/charts/templates/chart.xml +104 -28
  13. kerykeion/charts/templates/wheel_only.xml +195 -24
  14. kerykeion/charts/themes/classic.css +11 -0
  15. kerykeion/charts/themes/dark-high-contrast.css +11 -0
  16. kerykeion/charts/themes/dark.css +11 -0
  17. kerykeion/charts/themes/light.css +11 -0
  18. kerykeion/charts/themes/strawberry.css +10 -0
  19. kerykeion/composite_subject_factory.py +4 -4
  20. kerykeion/ephemeris_data_factory.py +12 -9
  21. kerykeion/house_comparison/__init__.py +0 -3
  22. kerykeion/house_comparison/house_comparison_factory.py +51 -18
  23. kerykeion/house_comparison/house_comparison_utils.py +37 -8
  24. kerykeion/planetary_return_factory.py +8 -4
  25. kerykeion/relationship_score_factory.py +5 -5
  26. kerykeion/report.py +748 -67
  27. kerykeion/{kr_types → schemas}/__init__.py +44 -4
  28. kerykeion/schemas/chart_template_model.py +340 -0
  29. kerykeion/{kr_types → schemas}/kr_literals.py +7 -3
  30. kerykeion/{kr_types → schemas}/kr_models.py +247 -21
  31. kerykeion/{kr_types → schemas}/settings_models.py +7 -7
  32. kerykeion/settings/config_constants.py +75 -8
  33. kerykeion/settings/kerykeion_settings.py +1 -1
  34. kerykeion/settings/kr.config.json +130 -40
  35. kerykeion/settings/legacy/legacy_celestial_points_settings.py +8 -8
  36. kerykeion/sweph/ast136/s136108s.se1 +0 -0
  37. kerykeion/sweph/ast136/s136199s.se1 +0 -0
  38. kerykeion/sweph/ast136/s136472s.se1 +0 -0
  39. kerykeion/sweph/ast28/se28978s.se1 +0 -0
  40. kerykeion/sweph/ast50/se50000s.se1 +0 -0
  41. kerykeion/sweph/ast90/se90377s.se1 +0 -0
  42. kerykeion/sweph/ast90/se90482s.se1 +0 -0
  43. kerykeion/sweph/sefstars.txt +1602 -0
  44. kerykeion/transits_time_range_factory.py +11 -11
  45. kerykeion/utilities.py +61 -38
  46. kerykeion-5.0.0b1.dist-info/METADATA +1055 -0
  47. kerykeion-5.0.0b1.dist-info/RECORD +58 -0
  48. kerykeion/aspects/natal_aspects_factory.py +0 -235
  49. kerykeion/aspects/synastry_aspects_factory.py +0 -275
  50. kerykeion/house_comparison/house_comparison_models.py +0 -38
  51. kerykeion/kr_types/chart_types.py +0 -106
  52. kerykeion-5.0.0a11.dist-info/METADATA +0 -641
  53. kerykeion-5.0.0a11.dist-info/RECORD +0 -50
  54. /kerykeion/{kr_types → schemas}/kerykeion_exception.py +0 -0
  55. {kerykeion-5.0.0a11.dist-info → kerykeion-5.0.0b1.dist-info}/WHEEL +0 -0
  56. {kerykeion-5.0.0a11.dist-info → kerykeion-5.0.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,1055 @@
1
+ Metadata-Version: 2.4
2
+ Name: kerykeion
3
+ Version: 5.0.0b1
4
+ Summary: A Python library for astrological calculations, including natal charts, houses, planetary aspects, and SVG chart generation.
5
+ Project-URL: Homepage, https://www.kerykeion.net/
6
+ Project-URL: Repository, https://github.com/g-battaglia/kerykeion
7
+ Author-email: Giacomo Battaglia <kerykeion.astrology@gmail.com>
8
+ License: AGPL-3.0
9
+ License-File: LICENSE
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
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Information Technology
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
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
24
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
25
+ Classifier: Topic :: Scientific/Engineering :: Visualization
26
+ Classifier: Topic :: Software Development
27
+ Classifier: Topic :: Software Development :: Libraries
28
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
29
+ Classifier: Typing :: Typed
30
+ Requires-Python: >=3.9
31
+ Requires-Dist: pydantic>=2.5
32
+ Requires-Dist: pyswisseph>=2.10.3.1
33
+ Requires-Dist: pytz>=2024.2
34
+ Requires-Dist: requests-cache>=1.2.1
35
+ Requires-Dist: requests>=2.32.3
36
+ Requires-Dist: scour>=0.38.2
37
+ Requires-Dist: simple-ascii-tables>=1.0.0
38
+ Requires-Dist: typing-extensions>=4.12.2
39
+ Description-Content-Type: text/markdown
40
+
41
+ <h1 align="center">Kerykeion</h1>
42
+
43
+ <div align="center">
44
+ <img src="https://img.shields.io/github/stars/g-battaglia/kerykeion.svg?logo=github" alt="stars">
45
+ <img src="https://img.shields.io/github/forks/g-battaglia/kerykeion.svg?logo=github" alt="forks">
46
+ </div>
47
+ <div align="center">
48
+ <img src="https://static.pepy.tech/badge/kerykeion/month" alt="PyPI Downloads">
49
+ <img src="https://static.pepy.tech/badge/kerykeion/week" alt="PyPI Downloads">
50
+ <img src="https://img.shields.io/github/contributors/g-battaglia/kerykeion?color=blue&logo=github" alt="contributors">
51
+ <img src="https://img.shields.io/pypi/v/kerykeion?label=pypi%20package" alt="Package version">
52
+ <img src="https://img.shields.io/pypi/pyversions/kerykeion.svg" alt="Supported Python versions">
53
+ </div>
54
+ <p align="center">⭐ Like this project? Star it on GitHub and help it grow! ⭐</p>
55
+ &nbsp;
56
+
57
+ Kerykeion is a Python library for astrology. It computes planetary and house positions, detects aspects, and generates SVG charts—including birth, synastry, transit, and composite charts. You can also customize which planets to include in your calculations.
58
+
59
+ The main goal of this project is to offer a clean, data-driven approach to astrology, making it accessible and programmable.
60
+
61
+ Kerykeion also integrates seamlessly with LLM and AI applications.
62
+
63
+ Here is an example of a birthchart:
64
+
65
+ ![John Lenon Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Dark%20Theme%20-%20Natal%20Chart.svg)
66
+
67
+ **Web API**
68
+ ---
69
+
70
+ If you want to use Kerykeion in a web application, you can try the dedicated web API:
71
+
72
+ **[AstrologerAPI](https://rapidapi.com/gbattaglia/api/astrologer/pricing)**
73
+
74
+ It is [open source](https://github.com/g-battaglia/Astrologer-API) and directly supports this project.
75
+
76
+ **Donate**
77
+ --
78
+
79
+ Maintaining this project requires substantial time and effort. The Astrologer API alone cannot cover the costs of full-time development. If you find Kerykeion valuable and would like to support further development, please consider donating:
80
+
81
+ [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/kerykeion)
82
+
83
+ ## ⚠️ Development Branch Notice
84
+
85
+ This branch (`next`) is **not the stable version** of Kerykeion. It is the **development branch for the upcoming V5 release**.
86
+
87
+ If you're looking for the latest stable version, please check out the [`master`](https://github.com/g-battaglia/kerykeion/tree/master) branch instead.
88
+
89
+ ## Table of Contents
90
+ - [**Web API**](#web-api)
91
+ - [**Donate**](#donate)
92
+ - [⚠️ Development Branch Notice](#️-development-branch-notice)
93
+ - [Table of Contents](#table-of-contents)
94
+ - [Installation](#installation)
95
+ - [Basic Usage](#basic-usage)
96
+ - [Generate a SVG Chart](#generate-a-svg-chart)
97
+ - [Birth Chart](#birth-chart)
98
+ - [External Birth Chart](#external-birth-chart)
99
+ - [Synastry Chart](#synastry-chart)
100
+ - [Transit Chart](#transit-chart)
101
+ - [Composite Chart](#composite-chart)
102
+ - [Wheel Only Charts](#wheel-only-charts)
103
+ - [Birth Chart](#birth-chart-1)
104
+ - [Wheel Only Birth Chart (External)](#wheel-only-birth-chart-external)
105
+ - [Synastry Chart](#synastry-chart-1)
106
+ - [Change the Output Directory](#change-the-output-directory)
107
+ - [Change Language](#change-language)
108
+ - [Minified SVG](#minified-svg)
109
+ - [SVG without CSS Variables](#svg-without-css-variables)
110
+ - [Grid Only SVG](#grid-only-svg)
111
+ - [Report Generator](#report-generator)
112
+ - [Quick Examples](#quick-examples)
113
+ - [Section Access](#section-access)
114
+ - [Example: Retrieving Aspects](#example-retrieving-aspects)
115
+ - [Ayanamsa (Sidereal Modes)](#ayanamsa-sidereal-modes)
116
+ - [House Systems](#house-systems)
117
+ - [Perspective Type](#perspective-type)
118
+ - [Themes](#themes)
119
+ - [Alternative Initialization](#alternative-initialization)
120
+ - [Lunar Nodes (Rahu \& Ketu)](#lunar-nodes-rahu--ketu)
121
+ - [JSON Support](#json-support)
122
+ - [Auto Generated Documentation](#auto-generated-documentation)
123
+ - [Development](#development)
124
+ - [Kerykeion v5.0 – What's New](#kerykeion-v50--whats-new)
125
+ - [🎯 Key Highlights](#-key-highlights)
126
+ - [Factory-Centered Architecture](#factory-centered-architecture)
127
+ - [Pydantic 2 Models \& Type Safety](#pydantic-2-models--type-safety)
128
+ - [Enhanced Features](#enhanced-features)
129
+ - [🚨 Breaking Changes](#-breaking-changes)
130
+ - [1. Removed Legacy Classes](#1-removed-legacy-classes)
131
+ - [2. Import Changes](#2-import-changes)
132
+ - [3. Lunar Nodes Naming](#3-lunar-nodes-naming)
133
+ - [4. Chart Generation Changes](#4-chart-generation-changes)
134
+ - [5. Aspects API Changes](#5-aspects-api-changes)
135
+ - [🔄 Migration Guide](#-migration-guide)
136
+ - [Using the Backward Compatibility Layer](#using-the-backward-compatibility-layer)
137
+ - [Step-by-Step Migration](#step-by-step-migration)
138
+ - [Automated Migration Script](#automated-migration-script)
139
+ - [📦 Other Notable Changes](#-other-notable-changes)
140
+ - [🎨 New Themes](#-new-themes)
141
+ - [📚 Resources](#-resources)
142
+ - [Integrating Kerykeion into Your Project](#integrating-kerykeion-into-your-project)
143
+ - [License](#license)
144
+ - [Contributing](#contributing)
145
+ - [Citations](#citations)
146
+
147
+ ## Installation
148
+
149
+ Kerykeion requires **Python 3.9** or higher.
150
+
151
+ ```bash
152
+ pip3 install kerykeion
153
+ ```
154
+
155
+ ## Basic Usage
156
+
157
+ Below is a simple example illustrating the creation of an astrological subject and retrieving astrological details:
158
+
159
+ ```python
160
+ from kerykeion import AstrologicalSubjectFactory
161
+
162
+ # Create an instance of the AstrologicalSubjectFactory class.
163
+ # Arguments: Name, year, month, day, hour, minutes, city, nation
164
+ john = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
165
+
166
+ # Retrieve information about the Sun:
167
+ print(john.sun.model_dump_json())
168
+ # > {"name":"Sun","quality":"Cardinal","element":"Air","sign":"Lib","sign_num":6,"position":16.26789199474399,"abs_pos":196.267891994744,"emoji":"♎️","point_type":"AstrologicalPoint","house":"Sixth_House","retrograde":false}
169
+
170
+ # Retrieve information about the first house:
171
+ print(john.first_house.model_dump_json())
172
+ # > {"name":"First_House","quality":"Cardinal","element":"Fire","sign":"Ari","sign_num":0,"position":19.74676624176799,"abs_pos":19.74676624176799,"emoji":"♈️","point_type":"House","house":null,"retrograde":null}
173
+
174
+ # Retrieve the element of the Moon sign:
175
+ print(john.moon.element)
176
+ # > 'Air'
177
+ ```
178
+
179
+ **To avoid using GeoNames online, specify longitude, latitude, and timezone instead of city and nation:**
180
+
181
+ ```python
182
+ john = AstrologicalSubjectFactory.from_birth_data(
183
+ "John Lennon", 1940, 10, 9, 18, 30,
184
+ lng=-2.9833, # Longitude for Liverpool
185
+ lat=53.4000, # Latitude for Liverpool
186
+ tz_str="Europe/London", # Timezone for Liverpool
187
+ city="Liverpool",
188
+ )
189
+ ```
190
+
191
+ ## Generate a SVG Chart
192
+
193
+ To generate a chart, use the `ChartDataFactory` to pre-compute chart data, then `ChartDrawer` to create the visualization. This two-step process ensures clean separation between astrological calculations and chart rendering.
194
+
195
+ **Tip:**
196
+ The optimized way to open the generated SVG files is with a web browser (e.g., Chrome, Firefox).
197
+ To improve compatibility across different applications, you can use the `remove_css_variables` parameter when generating the SVG. This will inline all styles and eliminate CSS variables, resulting in an SVG that is more broadly supported.
198
+
199
+ ### Birth Chart
200
+
201
+ ```python
202
+ from kerykeion import AstrologicalSubjectFactory
203
+ from kerykeion.chart_data_factory import ChartDataFactory
204
+ from kerykeion.charts.chart_drawer import ChartDrawer
205
+
206
+ # Step 1: Create subject
207
+ john = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
208
+
209
+ # Step 2: Pre-compute chart data
210
+ chart_data = ChartDataFactory.create_natal_chart_data(john)
211
+
212
+ # Step 3: Create visualization
213
+ birth_chart_svg = ChartDrawer(chart_data=chart_data)
214
+ birth_chart_svg.save_svg()
215
+ ```
216
+
217
+ The SVG file will be saved in the home directory.
218
+ ![John Lennon Birth Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Natal%20Chart.svg)
219
+
220
+ ### External Birth Chart
221
+
222
+ ```python
223
+ from kerykeion import AstrologicalSubjectFactory
224
+ from kerykeion.chart_data_factory import ChartDataFactory
225
+ from kerykeion.charts.chart_drawer import ChartDrawer
226
+
227
+ # Step 1: Create subject
228
+ birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
229
+
230
+ # Step 2: Pre-compute chart data for external natal chart
231
+ chart_data = ChartDataFactory.create_external_natal_chart_data(birth_chart)
232
+
233
+ # Step 3: Create visualization
234
+ birth_chart_svg = ChartDrawer(chart_data=chart_data)
235
+ birth_chart_svg.save_svg()
236
+ ```
237
+ ![John Lennon External Birth Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20ExternalNatal%20Chart.svg)
238
+
239
+ ### Synastry Chart
240
+
241
+ ```python
242
+ from kerykeion import AstrologicalSubjectFactory
243
+ from kerykeion.chart_data_factory import ChartDataFactory
244
+ from kerykeion.charts.chart_drawer import ChartDrawer
245
+
246
+ # Step 1: Create subjects
247
+ first = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
248
+ second = AstrologicalSubjectFactory.from_birth_data("Paul McCartney", 1942, 6, 18, 15, 30, "Liverpool", "GB")
249
+
250
+ # Step 2: Pre-compute synastry chart data
251
+ chart_data = ChartDataFactory.create_synastry_chart_data(first, second)
252
+
253
+ # Step 3: Create visualization
254
+ synastry_chart = ChartDrawer(chart_data=chart_data)
255
+ synastry_chart.save_svg()
256
+ ```
257
+
258
+ ![John Lennon and Paul McCartney Synastry](https://www.kerykeion.net/img/examples/synastry-chart.svg)
259
+
260
+
261
+ ### Transit Chart
262
+
263
+ ```python
264
+ from kerykeion import AstrologicalSubjectFactory
265
+ from kerykeion.chart_data_factory import ChartDataFactory
266
+ from kerykeion.charts.chart_drawer import ChartDrawer
267
+
268
+ # Step 1: Create subjects
269
+ transit = AstrologicalSubjectFactory.from_birth_data("Transit", 2025, 6, 8, 8, 45, "Atlanta", "US")
270
+ subject = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
271
+
272
+ # Step 2: Pre-compute transit chart data
273
+ chart_data = ChartDataFactory.create_transit_chart_data(subject, transit)
274
+
275
+ # Step 3: Create visualization
276
+ transit_chart = ChartDrawer(chart_data=chart_data)
277
+ transit_chart.save_svg()
278
+ ```
279
+
280
+ ![John Lennon Transit Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Transit%20Chart.svg)
281
+
282
+ ### Composite Chart
283
+
284
+ ```python
285
+ from kerykeion import CompositeSubjectFactory, AstrologicalSubjectFactory
286
+ from kerykeion.chart_data_factory import ChartDataFactory
287
+ from kerykeion.charts.chart_drawer import ChartDrawer
288
+
289
+ # Step 1: Create subjects
290
+ angelina = AstrologicalSubjectFactory.from_birth_data("Angelina Jolie", 1975, 6, 4, 9, 9, "Los Angeles", "US", lng=-118.15, lat=34.03, tz_str="America/Los_Angeles")
291
+
292
+ brad = AstrologicalSubjectFactory.from_birth_data("Brad Pitt", 1963, 12, 18, 6, 31, "Shawnee", "US", lng=-96.56, lat=35.20, tz_str="America/Chicago")
293
+
294
+ # Step 2: Create composite subject
295
+ factory = CompositeSubjectFactory(angelina, brad)
296
+ composite_model = factory.get_midpoint_composite_subject_model()
297
+
298
+ # Step 3: Pre-compute composite chart data
299
+ chart_data = ChartDataFactory.create_composite_chart_data(composite_model)
300
+
301
+ # Step 4: Create visualization
302
+ composite_chart = ChartDrawer(chart_data=chart_data)
303
+ composite_chart.save_svg()
304
+ ```
305
+
306
+ ![Angelina Jolie and Brad Pitt Composite Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/Angelina%20Jolie%20and%20Brad%20Pitt%20Composite%20Chart%20-%20Composite%20Chart.svg)
307
+
308
+ ## Wheel Only Charts
309
+
310
+ For *all* the charts, you can generate a wheel-only chart by using the method `makeWheelOnlySVG()`:
311
+
312
+ ### Birth Chart
313
+ ```python
314
+ from kerykeion import AstrologicalSubjectFactory
315
+ from kerykeion.chart_data_factory import ChartDataFactory
316
+ from kerykeion.charts.chart_drawer import ChartDrawer
317
+
318
+ # Step 1: Create subject
319
+ birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
320
+
321
+ # Step 2: Pre-compute chart data
322
+ chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
323
+
324
+ # Step 3: Create visualization
325
+ birth_chart_svg = ChartDrawer(chart_data=chart_data)
326
+ birth_chart_svg.save_wheel_only_svg_file()
327
+ ```
328
+ ![John Lennon Birth Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Wheel%20Only%20-%20Natal%20Chart%20-%20Wheel%20Only.svg)
329
+
330
+ ### Wheel Only Birth Chart (External)
331
+
332
+ ```python
333
+ from kerykeion import AstrologicalSubjectFactory
334
+ from kerykeion.chart_data_factory import ChartDataFactory
335
+ from kerykeion.charts.chart_drawer import ChartDrawer
336
+
337
+ # Step 1: Create subject
338
+ birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
339
+
340
+ # Step 2: Pre-compute external natal chart data
341
+ chart_data = ChartDataFactory.create_external_natal_chart_data(birth_chart)
342
+
343
+ # Step 3: Create visualization
344
+ birth_chart_svg = ChartDrawer(chart_data=chart_data)
345
+ birth_chart_svg.save_wheel_only_svg_file(
346
+ wheel_only=True,
347
+ wheel_only_external=True
348
+ )
349
+ ```
350
+
351
+ ![John Lennon Birth Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Wheel%20External%20Only%20-%20ExternalNatal%20Chart%20-%20Wheel%20Only.svg)
352
+
353
+ ### Synastry Chart
354
+ ```python
355
+ from kerykeion import AstrologicalSubjectFactory
356
+ from kerykeion.chart_data_factory import ChartDataFactory
357
+ from kerykeion.charts.chart_drawer import ChartDrawer
358
+
359
+ # Step 1: Create subjects
360
+ first = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
361
+ second = AstrologicalSubjectFactory.from_birth_data("Paul McCartney", 1942, 6, 18, 15, 30, "Liverpool", "GB")
362
+
363
+ # Step 2: Pre-compute synastry chart data
364
+ chart_data = ChartDataFactory.create_synastry_chart_data(first, second)
365
+
366
+ # Step 3: Create visualization
367
+ synastry_chart = ChartDrawer(chart_data=chart_data)
368
+ synastry_chart.save_wheel_only_svg_file()
369
+ ```
370
+
371
+ ![John Lennon and Paul McCartney Synastry](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Wheel%20Synastry%20Only%20-%20Synastry%20Chart%20-%20Wheel%20Only.svg)
372
+
373
+ ### Change the Output Directory
374
+
375
+ To save the SVG file in a custom location, specify the `output_path` parameter in `save_svg()`:
376
+
377
+ ```python
378
+ from kerykeion import AstrologicalSubjectFactory
379
+ from kerykeion.chart_data_factory import ChartDataFactory
380
+ from kerykeion.charts.chart_drawer import ChartDrawer
381
+
382
+ # Step 1: Create subjects
383
+ first = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
384
+ second = AstrologicalSubjectFactory.from_birth_data("Paul McCartney", 1942, 6, 18, 15, 30, "Liverpool", "GB")
385
+
386
+ # Step 2: Pre-compute synastry chart data
387
+ chart_data = ChartDataFactory.create_synastry_chart_data(first, second)
388
+
389
+ # Step 3: Create visualization with custom output directory
390
+ synastry_chart = ChartDrawer(chart_data=chart_data)
391
+ synastry_chart.save_svg(output_path=".")
392
+ ```
393
+
394
+ ### Change Language
395
+
396
+ You can switch chart language by passing `chart_language` to the `ChartDrawer` class:
397
+
398
+ ```python
399
+ from kerykeion import AstrologicalSubjectFactory
400
+ from kerykeion.chart_data_factory import ChartDataFactory
401
+ from kerykeion.charts.chart_drawer import ChartDrawer
402
+
403
+ # Step 1: Create subject
404
+ birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
405
+
406
+ # Step 2: Pre-compute chart data
407
+ chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
408
+
409
+ # Step 3: Create visualization with Italian language
410
+ birth_chart_svg = ChartDrawer(
411
+ chart_data=chart_data,
412
+ chart_language="IT" # Change to Italian
413
+ )
414
+ birth_chart_svg.save_svg()
415
+ ```
416
+
417
+ More details [here](https://www.kerykeion.net/docs/chart-language).
418
+
419
+ The available languages are:
420
+ - EN (English)
421
+ - FR (French)
422
+ - PT (Portuguese)
423
+ - ES (Spanish)
424
+ - TR (Turkish)
425
+ - RU (Russian)
426
+ - IT (Italian)
427
+ - CN (Chinese)
428
+ - DE (German)
429
+
430
+
431
+ ### Minified SVG
432
+ To generate a minified SVG, set `minify_svg=True` in the `makeSVG()` method:
433
+
434
+ ```python
435
+ from kerykeion import AstrologicalSubjectFactory
436
+ from kerykeion.chart_data_factory import ChartDataFactory
437
+ from kerykeion.charts.chart_drawer import ChartDrawer
438
+
439
+ # Step 1: Create subject
440
+ birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
441
+
442
+ # Step 2: Pre-compute chart data
443
+ chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
444
+
445
+ # Step 3: Create visualization
446
+ birth_chart_svg = ChartDrawer(chart_data=chart_data)
447
+ birth_chart_svg.save_svg(
448
+ minify=True
449
+ )
450
+ ```
451
+
452
+ ### SVG without CSS Variables
453
+ To generate an SVG without CSS variables, set `remove_css_variables=True` in the `makeSVG()` method:
454
+
455
+ ```python
456
+ from kerykeion import AstrologicalSubjectFactory
457
+ from kerykeion.chart_data_factory import ChartDataFactory
458
+ from kerykeion.charts.chart_drawer import ChartDrawer
459
+
460
+ # Step 1: Create subject
461
+ birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
462
+
463
+ # Step 2: Pre-compute chart data
464
+ chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
465
+
466
+ # Step 3: Create visualization
467
+ birth_chart_svg = ChartDrawer(chart_data=chart_data)
468
+ birth_chart_svg.save_svg(
469
+ remove_css_variables=True
470
+ )
471
+ ```
472
+ This will inline all styles and eliminate CSS variables, resulting in an SVG that is more broadly supported.
473
+
474
+
475
+ ### Grid Only SVG
476
+
477
+ It's possible to generate a grid-only SVG, useful for creating a custom layout. To do this, use the `save_aspect_grid_only_svg_file()` method:
478
+
479
+ ```python
480
+ from kerykeion import AstrologicalSubjectFactory
481
+ from kerykeion.chart_data_factory import ChartDataFactory
482
+ from kerykeion.charts.chart_drawer import ChartDrawer
483
+
484
+ # Step 1: Create subjects
485
+ birth_chart = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
486
+ second = AstrologicalSubjectFactory.from_birth_data("Paul McCartney", 1942, 6, 18, 15, 30, "Liverpool", "GB")
487
+
488
+ # Step 2: Pre-compute synastry chart data
489
+ chart_data = ChartDataFactory.create_synastry_chart_data(birth_chart, second)
490
+
491
+ # Step 3: Create visualization with dark theme
492
+ aspect_grid_chart = ChartDrawer(chart_data=chart_data, theme="dark")
493
+ aspect_grid_chart.save_aspect_grid_only_svg_file()
494
+ ```
495
+ ![John Lennon Birth Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Aspect%20Grid%20Only%20-%20Natal%20Chart%20-%20Aspect%20Grid%20Only.svg)
496
+
497
+ ## Report Generator
498
+
499
+ `ReportGenerator` mirrors the chart-type dispatch of `ChartDrawer`. It accepts raw `AstrologicalSubjectModel` instances as well as any `ChartDataModel` produced by `ChartDataFactory`—including natal, composite, synastry, transit, and planetary return charts—and renders the appropriate textual report automatically.
500
+
501
+ ### Quick Examples
502
+
503
+ ```python
504
+ from kerykeion import ReportGenerator, AstrologicalSubjectFactory, ChartDataFactory
505
+
506
+ # Subject-only report
507
+ subject = AstrologicalSubjectFactory.from_birth_data(
508
+ "Sample Natal", 1990, 7, 21, 14, 45, "Rome", "IT"
509
+ )
510
+ ReportGenerator(subject).print_report(include_aspects=False)
511
+
512
+ # Single-chart data (elements, qualities, aspects enabled)
513
+ natal_data = ChartDataFactory.create_natal_chart_data(subject)
514
+ ReportGenerator(natal_data).print_report(max_aspects=10)
515
+
516
+ # Dual-chart data (synastry, transit, dual return, …)
517
+ partner = AstrologicalSubjectFactory.from_birth_data(
518
+ "Sample Partner", 1992, 11, 5, 9, 30, "Rome", "IT"
519
+ )
520
+ synastry_data = ChartDataFactory.create_synastry_chart_data(subject, partner)
521
+ ReportGenerator(synastry_data).print_report(max_aspects=12)
522
+ ```
523
+
524
+ Each report contains:
525
+ - A chart-aware title summarising the subject(s) and chart type
526
+ - Birth/event metadata and configuration settings
527
+ - Celestial points with sign, position, **daily motion**, **declination**, retrograde flag, and house
528
+ - House cusp tables for every subject involved
529
+ - Lunar phase details when available
530
+ - Element/quality distributions and active configuration summaries (for chart data)
531
+ - Aspect listings tailored for single or dual charts, with symbols for type and movement
532
+ - Dual-chart extras such as house comparisons and relationship scores (when provided by the data)
533
+
534
+ ### Section Access
535
+
536
+ All section helpers remain available for targeted output:
537
+
538
+ ```python
539
+ report = ReportGenerator(natal_data)
540
+ print(report.get_subject_data_report())
541
+ print(report.get_celestial_points_report())
542
+ print(report.get_elements_report())
543
+ print(report.get_aspects_report(max_aspects=5))
544
+ ```
545
+
546
+ Refer to the refreshed [Report Documentation](https://www.kerykeion.net/report/) for end-to-end examples covering every supported chart model.
547
+
548
+ ## Example: Retrieving Aspects
549
+
550
+ Kerykeion provides a unified `AspectsFactory` class for calculating astrological aspects within single charts or between two charts:
551
+
552
+ ```python
553
+ from kerykeion import AspectsFactory, AstrologicalSubjectFactory
554
+
555
+ # Create astrological subjects
556
+ jack = AstrologicalSubjectFactory.from_birth_data("Jack", 1990, 6, 15, 15, 15, "Roma", "IT")
557
+ jane = AstrologicalSubjectFactory.from_birth_data("Jane", 1991, 10, 25, 21, 0, "Roma", "IT")
558
+
559
+ # For single chart aspects (natal, return, composite, etc.)
560
+ single_chart_aspects = AspectsFactory.single_chart_aspects(jack)
561
+ print(f"Found {len(single_chart_aspects)} aspects in Jack's chart")
562
+ print(single_chart_aspects[0])
563
+ # Output: AspectModel with details like aspect type, orb, planets involved, etc.
564
+
565
+ # For dual chart aspects (synastry, transits, comparisons, etc.)
566
+ dual_chart_aspects = AspectsFactory.dual_chart_aspects(jack, jane)
567
+ print(f"Found {len(dual_chart_aspects)} aspects between Jack and Jane's charts")
568
+ print(dual_chart_aspects[0])
569
+ # Output: AspectModel with cross-chart aspect details
570
+
571
+ # The factory returns structured AspectModel objects with properties like:
572
+ # - p1_name, p2_name: Planet/point names
573
+ # - aspect: Aspect type (conjunction, trine, square, etc.)
574
+ # - orbit: Orb tolerance in degrees
575
+ # - aspect_degrees: Exact degrees for the aspect (0, 60, 90, 120, 180, etc.)
576
+ # - color: Hex color code for visualization
577
+ ```
578
+
579
+ **Advanced Usage with Custom Settings:**
580
+
581
+ ```python
582
+ # You can also customize aspect calculations with custom orb settings
583
+ from kerykeion.settings.config_constants import DEFAULT_ACTIVE_ASPECTS
584
+
585
+ # Modify aspect settings if needed
586
+ custom_aspects = DEFAULT_ACTIVE_ASPECTS.copy()
587
+ # ... modify as needed
588
+
589
+ # The factory automatically uses the configured settings for orb calculations
590
+ # and filters aspects based on relevance and orb thresholds
591
+ ```
592
+
593
+ ## Ayanamsa (Sidereal Modes)
594
+
595
+ By default, the zodiac type is **Tropical**. To use **Sidereal**, specify the sidereal mode:
596
+
597
+ ```python
598
+ johnny = AstrologicalSubjectFactory.from_birth_data(
599
+ "Johnny Depp", 1963, 6, 9, 0, 0,
600
+ "Owensboro", "US",
601
+ zodiac_type="Sidereal",
602
+ sidereal_mode="LAHIRI"
603
+ )
604
+ ```
605
+
606
+ More examples [here](https://www.kerykeion.net/docs//sidereal-modes/).
607
+
608
+ Full list of supported sidereal modes [here](https://www.kerykeion.net/pydocs/kerykeion/schemas/kr_literals.html#SiderealMode).
609
+
610
+ ## House Systems
611
+
612
+ By default, houses are calculated using **Placidus**. Configure a different house system as follows:
613
+
614
+ ```python
615
+ johnny = AstrologicalSubjectFactory.from_birth_data(
616
+ "Johnny Depp", 1963, 6, 9, 0, 0,
617
+ "Owensboro", "US",
618
+ houses_system="M"
619
+ )
620
+ ```
621
+
622
+ More examples [here](https://www.kerykeion.net/docs//houses-systems/).
623
+
624
+ Full list of supported house systems [here](https://www.kerykeion.net/pydocs/kerykeion/schemas/kr_literals.html#HousesSystem).
625
+
626
+ So far all the available houses system in the Swiss Ephemeris are supported but the Gauquelin Sectors.
627
+
628
+ ## Perspective Type
629
+
630
+ By default, Kerykeion uses the **Apparent Geocentric** perspective (the most standard in astrology). Other perspectives (e.g., **Heliocentric**) can be set this way:
631
+
632
+ ```python
633
+ johnny = AstrologicalSubjectFactory.from_birth_data(
634
+ "Johnny Depp", 1963, 6, 9, 0, 0,
635
+ "Owensboro", "US",
636
+ perspective_type="Heliocentric"
637
+ )
638
+ ```
639
+
640
+ More examples [here](https://www.kerykeion.net/docs//perspective-type/).
641
+
642
+ Full list of supported perspective types [here](https://www.kerykeion.net/pydocs/kerykeion/schemas/kr_literals.html#PerspectiveType).
643
+
644
+ ## Themes
645
+
646
+ Kerykeion provides several chart themes:
647
+
648
+ - **Classic** (default)
649
+ - **Dark**
650
+ - **Dark High Contrast**
651
+ - **Light**
652
+
653
+ Each theme offers a distinct visual style, allowing you to choose the one that best suits your preferences or presentation needs. If you prefer more control over the appearance, you can opt not to set any theme, making it easier to customize the chart by overriding the default CSS variables. For more detailed instructions on how to apply themes, check the [documentation](https://www.kerykeion.net/docs/theming)
654
+
655
+ Here's an example of how to set the theme:
656
+
657
+ ```python
658
+ from kerykeion import AstrologicalSubjectFactory
659
+ from kerykeion.chart_data_factory import ChartDataFactory
660
+ from kerykeion.charts.chart_drawer import ChartDrawer
661
+
662
+ # Step 1: Create subject
663
+ dark_theme_subject = AstrologicalSubjectFactory.from_birth_data("John Lennon - Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
664
+
665
+ # Step 2: Pre-compute chart data
666
+ chart_data = ChartDataFactory.create_natal_chart_data(dark_theme_subject)
667
+
668
+ # Step 3: Create visualization with dark high contrast theme
669
+ dark_theme_natal_chart = ChartDrawer(chart_data=chart_data, theme="dark_high_contrast")
670
+ dark_theme_natal_chart.save_svg()
671
+ ```
672
+
673
+ ![John Lennon](https://www.kerykeion.net/img/showcase/John%20Lennon%20-%20Dark%20-%20Natal%20Chart.svg)
674
+
675
+ ## Alternative Initialization
676
+
677
+ Create an `AstrologicalSubject` from a UTC ISO 8601 string:
678
+
679
+ ```python
680
+ subject = AstrologicalSubject.get_from_iso_utc_time(
681
+ "Johnny Depp", "1963-06-09T05:00:00Z", "Owensboro", "US"
682
+ )
683
+ ```
684
+
685
+ If you set `online=True`, provide a `geonames_username` to allow city-based geolocation:
686
+
687
+ ```python
688
+ from kerykeion.astrological_subject import AstrologicalSubjectFactory
689
+
690
+ subject = AstrologicalSubject.get_from_iso_utc_time(
691
+ "Johnny Depp", "1963-06-09T05:00:00Z", "Owensboro", "US", online=True
692
+ )
693
+ ```
694
+
695
+ ## Lunar Nodes (Rahu & Ketu)
696
+
697
+ Kerykeion supports both **True** and **Mean** Lunar Nodes:
698
+
699
+ - **True North Lunar Node**: `"true_node"` (name kept without "north" for backward compatibility).
700
+ - **True South Lunar Node**: `"true_south_node"`.
701
+ - **Mean North Lunar Node**: `"mean_node"` (name kept without "north" for backward compatibility).
702
+ - **Mean South Lunar Node**: `"mean_south_node"`.
703
+
704
+ In instances of the classes used to generate aspects and SVG charts, only the mean nodes are active. To activate the true nodes, you need to pass the `active_points` parameter to the `ChartDataFactory` methods.
705
+
706
+ Example:
707
+
708
+ ```python
709
+ from kerykeion import AstrologicalSubjectFactory
710
+ from kerykeion.chart_data_factory import ChartDataFactory
711
+ from kerykeion.charts.chart_drawer import ChartDrawer
712
+
713
+ # Step 1: Create subject
714
+ subject = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
715
+
716
+ # Step 2: Pre-compute chart data with custom active points including true nodes
717
+ chart_data = ChartDataFactory.create_natal_chart_data(
718
+ subject,
719
+ active_points=[
720
+ "Sun",
721
+ "Moon",
722
+ "Mercury",
723
+ "Venus",
724
+ "Mars",
725
+ "Jupiter",
726
+ "Saturn",
727
+ "Uranus",
728
+ "Neptune",
729
+ "Pluto",
730
+ "Mean_Node",
731
+ "Mean_South_Node",
732
+ "True_Node", # Activates True North Node
733
+ "True_South_Node", # Activates True South Node
734
+ "Ascendant",
735
+ "Medium_Coeli",
736
+ "Descendant",
737
+ "Imum_Coeli"
738
+ ]
739
+ )
740
+
741
+ # Step 3: Create visualization
742
+ chart = ChartDrawer(chart_data=chart_data)
743
+ chart.save_svg()
744
+ ```
745
+
746
+ ## JSON Support
747
+
748
+ You can serialize the astrological subject (the base data used throughout the library) to JSON:
749
+
750
+ ```python
751
+ from kerykeion import AstrologicalSubjectFactory
752
+
753
+ johnny = AstrologicalSubjectFactory.from_birth_data("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US")
754
+
755
+ print(johnny.json(dump=False, indent=2))
756
+ ```
757
+
758
+ ## Auto Generated Documentation
759
+
760
+ You can find auto-generated documentation [here](https://www.kerykeion.net/pydocs/kerykeion.html). Most classes and functions include docstrings.
761
+
762
+ ## Development
763
+
764
+ Clone the repository or download the ZIP via the GitHub interface.
765
+
766
+ ## Kerykeion v5.0 – What's New
767
+
768
+ Kerykeion v5 is a **complete redesign** that modernizes the library with a data-first approach, factory-based architecture, and Pydantic 2 models. This version brings significant improvements in API design, type safety, and extensibility.
769
+
770
+ ### 🎯 Key Highlights
771
+
772
+ #### Factory-Centered Architecture
773
+ The old class-based approach has been replaced with a modern factory pattern:
774
+
775
+ - **`AstrologicalSubjectFactory`**: Replaces the old `AstrologicalSubject` class
776
+ - **`ChartDataFactory`**: Pre-computes enriched chart data (elements, qualities, aspects)
777
+ - **`ChartDrawer`**: Pure SVG rendering separated from calculations
778
+ - **`AspectsFactory`**: Unified aspects calculation for natal and synastry charts
779
+ - **`PlanetaryReturnFactory`**: Solar and Lunar returns computation
780
+ - **`HouseComparisonFactory`**: House overlay analysis for synastry
781
+ - **`RelationshipScoreFactory`**: Compatibility scoring between charts
782
+
783
+ **Old v4 API:**
784
+ ```python
785
+ from kerykeion import AstrologicalSubject, KerykeionChartSVG
786
+
787
+ # v4 - Class-based approach
788
+ subject = AstrologicalSubject("John", 1990, 1, 1, 12, 0, "London", "GB")
789
+ chart = KerykeionChartSVG(subject)
790
+ chart.makeSVG()
791
+ ```
792
+
793
+ **New v5 API:**
794
+ ```python
795
+ from kerykeion import AstrologicalSubjectFactory, ChartDataFactory, ChartDrawer
796
+
797
+ # v5 - Factory-based approach with separation of concerns
798
+ subject = AstrologicalSubjectFactory.from_birth_data("John", 1990, 1, 1, 12, 0, "London", "GB")
799
+ chart_data = ChartDataFactory.create_natal_chart_data(subject)
800
+ drawer = ChartDrawer(chart_data=chart_data)
801
+ drawer.save_svg()
802
+ ```
803
+
804
+ #### Pydantic 2 Models & Type Safety
805
+ All data structures are now strongly typed Pydantic models:
806
+
807
+ - **`AstrologicalSubjectModel`**: Subject data with full validation
808
+ - **`ChartDataModel`**: Enriched chart data with elements, qualities, aspects
809
+ - **`SingleChartAspectsModel` / `DualChartAspectsModel`**: Typed aspect collections
810
+ - **`PlanetReturnModel`**: Planetary return data
811
+ - **`ElementDistributionModel`**: Element statistics (fire, earth, air, water)
812
+ - **`QualityDistributionModel`**: Quality statistics (cardinal, fixed, mutable)
813
+
814
+ All models support:
815
+ - JSON serialization/deserialization
816
+ - Dictionary export
817
+ - Subscript access
818
+ - Full IDE autocomplete and type checking
819
+
820
+ #### Enhanced Features
821
+ - **Speed & Declination**: All celestial points now include daily motion speed and declination
822
+ - **Element & Quality Analysis**: Automatic calculation of element/quality distributions
823
+ - **Relationship Scoring**: Built-in compatibility analysis for synastry
824
+ - **House Comparison**: Detailed house overlay analysis
825
+ - **Transit Time Ranges**: Advanced transit tracking over time periods
826
+ - **Report Module**: Comprehensive text reports with ASCII tables
827
+
828
+ ### 🚨 Breaking Changes
829
+
830
+ #### 1. Removed Legacy Classes
831
+ The following classes have been **completely removed** and must be replaced:
832
+
833
+ | Removed (v4) | Replacement (v5) |
834
+ |--------------|------------------|
835
+ | `AstrologicalSubject` | `AstrologicalSubjectFactory.from_birth_data()` |
836
+ | `KerykeionChartSVG` | `ChartDrawer` + `ChartDataFactory` |
837
+ | `NatalAspects` | `AspectsFactory.single_chart_aspects()` |
838
+ | `SynastryAspects` | `AspectsFactory.dual_chart_aspects()` |
839
+ | `relationship_score()` | `RelationshipScoreFactory` |
840
+
841
+ **Note**: The `kerykeion.backword` module provides temporary wrappers for `AstrologicalSubject` and `KerykeionChartSVG` with deprecation warnings. These will be **removed in v6.0**.
842
+
843
+ #### 2. Import Changes
844
+ Module structure has been completely reorganized:
845
+
846
+ **Old imports (v4):**
847
+ ```python
848
+ from kerykeion import AstrologicalSubject, KerykeionChartSVG
849
+ from kerykeion.kr_types import KerykeionException
850
+ ```
851
+
852
+ **New imports (v5):**
853
+ ```python
854
+ from kerykeion import AstrologicalSubjectFactory, ChartDataFactory, ChartDrawer
855
+ from kerykeion.schemas.kerykeion_exception import KerykeionException
856
+ ```
857
+
858
+ #### 3. Lunar Nodes Naming
859
+ All lunar node fields have been renamed for clarity:
860
+
861
+ | Old Name (v4) | New Name (v5) |
862
+ |---------------|---------------|
863
+ | `Mean_Node` | `Mean_North_Lunar_Node` |
864
+ | `True_Node` | `True_North_Lunar_Node` |
865
+ | `Mean_South_Node` | `Mean_South_Lunar_Node` |
866
+ | `True_South_Node` | `True_South_Lunar_Node` |
867
+
868
+ **Migration example:**
869
+ ```python
870
+ # v4
871
+ print(subject.mean_node)
872
+
873
+ # v5
874
+ print(subject.mean_north_lunar_node)
875
+ ```
876
+
877
+ #### 4. Chart Generation Changes
878
+ The two-step process (data + rendering) is now required:
879
+
880
+ **Old v4:**
881
+ ```python
882
+ chart = KerykeionChartSVG(subject)
883
+ chart.makeSVG()
884
+ ```
885
+
886
+ **New v5:**
887
+ ```python
888
+ chart_data = ChartDataFactory.create_natal_chart_data(subject)
889
+ drawer = ChartDrawer(chart_data=chart_data)
890
+ drawer.save_svg()
891
+ ```
892
+
893
+ #### 5. Aspects API Changes
894
+ Aspects are now calculated through the factory:
895
+
896
+ **Old v4:**
897
+ ```python
898
+ from kerykeion import NatalAspects, SynastryAspects
899
+
900
+ natal_aspects = NatalAspects(subject)
901
+ synastry_aspects = SynastryAspects(subject1, subject2)
902
+ ```
903
+
904
+ **New v5:**
905
+ ```python
906
+ from kerykeion import AspectsFactory
907
+
908
+ natal_aspects = AspectsFactory.single_chart_aspects(subject)
909
+ synastry_aspects = AspectsFactory.dual_chart_aspects(subject1, subject2)
910
+ ```
911
+
912
+ ### 🔄 Migration Guide
913
+
914
+ #### Using the Backward Compatibility Layer
915
+
916
+ For a gradual migration, use the `kerykeion.backword` module:
917
+
918
+ ```python
919
+ from kerykeion import AstrologicalSubject # Legacy wrapper
920
+
921
+ subject = AstrologicalSubject("John Doe", 1990, 1, 1, 12, 0, "London", "GB")
922
+
923
+ # These still work but show DeprecationWarnings
924
+ print(subject.mean_node) # Maps to mean_north_lunar_node
925
+ print(subject.true_node) # Maps to true_north_lunar_node
926
+ ```
927
+
928
+ **⚠️ Warning**: This compatibility layer will be **removed in v6.0**.
929
+
930
+ #### Step-by-Step Migration
931
+
932
+ 1. **Update imports**
933
+ ```python
934
+ # Old
935
+ from kerykeion import AstrologicalSubject, KerykeionChartSVG
936
+
937
+ # New
938
+ from kerykeion import AstrologicalSubjectFactory, ChartDataFactory, ChartDrawer
939
+ ```
940
+
941
+ 2. **Update subject creation**
942
+ ```python
943
+ # Old
944
+ subject = AstrologicalSubject("John", 1990, 1, 1, 12, 0, "London", "GB")
945
+
946
+ # New
947
+ subject = AstrologicalSubjectFactory.from_birth_data("John", 1990, 1, 1, 12, 0, "London", "GB")
948
+ ```
949
+
950
+ 3. **Update chart generation**
951
+ ```python
952
+ # Old
953
+ chart = KerykeionChartSVG(subject)
954
+ chart.makeSVG()
955
+
956
+ # New
957
+ chart_data = ChartDataFactory.create_natal_chart_data(subject)
958
+ drawer = ChartDrawer(chart_data=chart_data)
959
+ drawer.save_svg()
960
+ ```
961
+
962
+ 4. **Update field access** (lunar nodes)
963
+ ```python
964
+ # Old
965
+ print(subject.mean_node.position)
966
+
967
+ # New
968
+ print(subject.mean_north_lunar_node.position)
969
+ ```
970
+
971
+ 5. **Update aspects**
972
+ ```python
973
+ # Old
974
+ from kerykeion import NatalAspects
975
+ aspects = NatalAspects(subject)
976
+
977
+ # New
978
+ from kerykeion import AspectsFactory
979
+ aspects = AspectsFactory.single_chart_aspects(subject)
980
+ ```
981
+
982
+ #### Automated Migration Script
983
+
984
+ Use this sed script to update Python files automatically:
985
+
986
+ ```bash
987
+ # Update lunar node references
988
+ find . -name "*.py" -type f -exec sed -i.bak \
989
+ -e 's/\.mean_node/.mean_north_lunar_node/g' \
990
+ -e 's/\.true_node/.true_north_lunar_node/g' \
991
+ -e 's/\.mean_south_node/.mean_south_lunar_node/g' \
992
+ -e 's/\.true_south_node/.true_south_lunar_node/g' \
993
+ -e 's/"Mean_Node"/"Mean_North_Lunar_Node"/g' \
994
+ -e 's/"True_Node"/"True_North_Lunar_Node"/g' \
995
+ -e 's/"Mean_South_Node"/"Mean_South_Lunar_Node"/g' \
996
+ -e 's/"True_South_Node"/"True_South_Lunar_Node"/g' \
997
+ {} \;
998
+ ```
999
+
1000
+ **Note**: Always review automated changes and test thoroughly before committing.
1001
+
1002
+ ### 📦 Other Notable Changes
1003
+
1004
+ - **Packaging**: Migrated from Poetry to PEP 621 + Hatchling with `uv.lock`
1005
+ - **Settings**: Centralized in `kerykeion.schemas` and `kerykeion.settings`
1006
+ - **Configuration**: Legacy presets available in `settings/legacy/`
1007
+ - **Type System**: All literals consolidated in `kr_literals.py`
1008
+ - **Performance**: Caching improvements with `functools.lru_cache`
1009
+ - **Testing**: 376 tests with 87% coverage, regenerated fixtures for v5
1010
+
1011
+ ### 🎨 New Themes
1012
+
1013
+ Additional chart themes added:
1014
+ - `classic` (default)
1015
+ - `dark`
1016
+ - `dark_high_contrast`
1017
+ - `light`
1018
+ - `strawberry`
1019
+
1020
+ ### 📚 Resources
1021
+
1022
+ - **Full Release Notes**: [v5.0.0.md](release_notes/v5.0.0b1.md)
1023
+ - **Documentation**: [kerykeion.readthedocs.io](https://kerykeion.readthedocs.io)
1024
+ - **API Reference**: [kerykeion.net/pydocs](https://www.kerykeion.net/pydocs/kerykeion.html)
1025
+ - **Examples**: See the `examples/` folder for runnable code
1026
+ - **Support**: [GitHub Discussions](https://github.com/g-battaglia/kerykeion/discussions)
1027
+
1028
+ **Migration Timeline:**
1029
+ - **v5.0**: Current - Backward compatibility layer available
1030
+ - **v6.0**: Future - Compatibility layer will be removed
1031
+
1032
+ ## Integrating Kerykeion into Your Project
1033
+
1034
+ 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.
1035
+
1036
+ ## License
1037
+
1038
+ This project is covered under the AGPL-3.0 License. For detailed information, please see the [LICENSE](LICENSE) file. If you have questions, feel free to contact me at [kerykeion.astrology@gmail.com](mailto:kerykeion.astrology@gmail.com?subject=Kerykeion).
1039
+
1040
+ As a rule of thumb, if you use this library in a project, you should open-source that project under a compatible license. Alternatively, if you wish to keep your source closed, consider using the [AstrologerAPI](https://rapidapi.com/gbattaglia/api/astrologer/), which is AGPL-3.0 compliant and also helps support the project.
1041
+
1042
+ Since the AstrologerAPI is an external third-party service, using it does *not* require your code to be open-source.
1043
+
1044
+ ## Contributing
1045
+
1046
+ Contributions are welcome! Feel free to submit pull requests or report issues.
1047
+
1048
+ ## Citations
1049
+
1050
+ If using Kerykeion in published or academic work, please cite as follows:
1051
+
1052
+ ```
1053
+ Battaglia, G. (2025). Kerykeion: A Python Library for Astrological Calculations and Chart Generation.
1054
+ https://github.com/g-battaglia/kerykeion
1055
+ ```