kerykeion 4.26.2__py3-none-any.whl → 5.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kerykeion might be problematic. Click here for more details.
- kerykeion/__init__.py +54 -11
- kerykeion/aspects/__init__.py +5 -2
- kerykeion/aspects/aspects_factory.py +569 -0
- kerykeion/aspects/aspects_utils.py +81 -8
- kerykeion/astrological_subject_factory.py +1897 -0
- kerykeion/backword.py +773 -0
- kerykeion/chart_data_factory.py +549 -0
- kerykeion/charts/chart_drawer.py +2601 -0
- kerykeion/charts/charts_utils.py +948 -177
- kerykeion/charts/draw_planets.py +602 -351
- kerykeion/charts/templates/aspect_grid_only.xml +328 -202
- kerykeion/charts/templates/chart.xml +432 -272
- kerykeion/charts/templates/wheel_only.xml +350 -214
- kerykeion/charts/themes/black-and-white.css +148 -0
- kerykeion/charts/themes/classic.css +107 -76
- kerykeion/charts/themes/dark-high-contrast.css +145 -107
- kerykeion/charts/themes/dark.css +146 -107
- kerykeion/charts/themes/light.css +146 -103
- kerykeion/charts/themes/strawberry.css +158 -0
- kerykeion/composite_subject_factory.py +253 -51
- kerykeion/ephemeris_data_factory.py +434 -0
- kerykeion/fetch_geonames.py +27 -8
- kerykeion/house_comparison/__init__.py +6 -0
- kerykeion/house_comparison/house_comparison_factory.py +103 -0
- kerykeion/house_comparison/house_comparison_utils.py +126 -0
- kerykeion/kr_types/__init__.py +66 -6
- kerykeion/kr_types/chart_template_model.py +20 -0
- kerykeion/kr_types/kerykeion_exception.py +15 -9
- kerykeion/kr_types/kr_literals.py +14 -132
- kerykeion/kr_types/kr_models.py +14 -318
- kerykeion/kr_types/settings_models.py +15 -203
- kerykeion/planetary_return_factory.py +805 -0
- kerykeion/relationship_score_factory.py +301 -0
- kerykeion/report.py +751 -64
- kerykeion/schemas/__init__.py +106 -0
- kerykeion/schemas/chart_template_model.py +367 -0
- kerykeion/schemas/kerykeion_exception.py +20 -0
- kerykeion/schemas/kr_literals.py +181 -0
- kerykeion/schemas/kr_models.py +605 -0
- kerykeion/schemas/settings_models.py +180 -0
- kerykeion/settings/__init__.py +20 -1
- kerykeion/settings/chart_defaults.py +444 -0
- kerykeion/settings/config_constants.py +117 -12
- kerykeion/settings/kerykeion_settings.py +31 -73
- kerykeion/settings/translation_strings.py +1479 -0
- kerykeion/settings/translations.py +74 -0
- kerykeion/sweph/ast136/s136108s.se1 +0 -0
- kerykeion/sweph/ast136/s136199s.se1 +0 -0
- kerykeion/sweph/ast136/s136472s.se1 +0 -0
- kerykeion/sweph/ast28/se28978s.se1 +0 -0
- kerykeion/sweph/ast50/se50000s.se1 +0 -0
- kerykeion/sweph/ast90/se90377s.se1 +0 -0
- kerykeion/sweph/ast90/se90482s.se1 +0 -0
- kerykeion/sweph/sefstars.txt +1602 -0
- kerykeion/transits_time_range_factory.py +302 -0
- kerykeion/utilities.py +393 -114
- kerykeion-5.0.0.dist-info/METADATA +1176 -0
- kerykeion-5.0.0.dist-info/RECORD +63 -0
- {kerykeion-4.26.2.dist-info → kerykeion-5.0.0.dist-info}/WHEEL +1 -1
- kerykeion/aspects/natal_aspects.py +0 -172
- kerykeion/aspects/synastry_aspects.py +0 -124
- kerykeion/aspects/transits_time_range.py +0 -41
- kerykeion/astrological_subject.py +0 -841
- kerykeion/charts/kerykeion_chart_svg.py +0 -1219
- kerykeion/enums.py +0 -57
- kerykeion/ephemeris_data.py +0 -242
- kerykeion/kr_types/chart_types.py +0 -95
- kerykeion/relationship_score/__init__.py +0 -2
- kerykeion/relationship_score/relationship_score.py +0 -175
- kerykeion/relationship_score/relationship_score_factory.py +0 -230
- kerykeion/settings/kr.config.json +0 -1258
- kerykeion/transits_time_range.py +0 -124
- kerykeion-4.26.2.dist-info/LICENSE +0 -661
- kerykeion-4.26.2.dist-info/METADATA +0 -629
- kerykeion-4.26.2.dist-info/RECORD +0 -46
- kerykeion-4.26.2.dist-info/entry_points.txt +0 -3
- /LICENSE → /kerykeion-5.0.0.dist-info/licenses/LICENSE +0 -0
|
@@ -1,1219 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
This is part of Kerykeion (C) 2025 Giacomo Battaglia
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import logging
|
|
8
|
-
import swisseph as swe
|
|
9
|
-
from typing import get_args
|
|
10
|
-
|
|
11
|
-
from kerykeion.settings.kerykeion_settings import get_settings
|
|
12
|
-
from kerykeion.aspects.synastry_aspects import SynastryAspects
|
|
13
|
-
from kerykeion.aspects.natal_aspects import NatalAspects
|
|
14
|
-
from kerykeion.astrological_subject import AstrologicalSubject
|
|
15
|
-
from kerykeion.kr_types import KerykeionException, ChartType, KerykeionPointModel, Sign, ActiveAspect
|
|
16
|
-
from kerykeion.kr_types import ChartTemplateDictionary
|
|
17
|
-
from kerykeion.kr_types.kr_models import AstrologicalSubjectModel, CompositeSubjectModel
|
|
18
|
-
from kerykeion.kr_types.settings_models import KerykeionSettingsCelestialPointModel, KerykeionSettingsModel
|
|
19
|
-
from kerykeion.kr_types.kr_literals import KerykeionChartTheme, KerykeionChartLanguage, AxialCusps, Planet
|
|
20
|
-
from kerykeion.charts.charts_utils import (
|
|
21
|
-
draw_zodiac_slice,
|
|
22
|
-
convert_latitude_coordinate_to_string,
|
|
23
|
-
convert_longitude_coordinate_to_string,
|
|
24
|
-
draw_aspect_line,
|
|
25
|
-
draw_transit_ring_degree_steps,
|
|
26
|
-
draw_degree_ring,
|
|
27
|
-
draw_transit_ring,
|
|
28
|
-
draw_first_circle,
|
|
29
|
-
draw_second_circle,
|
|
30
|
-
draw_third_circle,
|
|
31
|
-
draw_aspect_grid,
|
|
32
|
-
draw_houses_cusps_and_text_number,
|
|
33
|
-
draw_transit_aspect_list,
|
|
34
|
-
draw_transit_aspect_grid,
|
|
35
|
-
calculate_moon_phase_chart_params,
|
|
36
|
-
draw_house_grid,
|
|
37
|
-
draw_planet_grid,
|
|
38
|
-
)
|
|
39
|
-
from kerykeion.charts.draw_planets import draw_planets # type: ignore
|
|
40
|
-
from kerykeion.utilities import get_houses_list, inline_css_variables_in_svg
|
|
41
|
-
from kerykeion.settings.config_constants import DEFAULT_ACTIVE_POINTS, DEFAULT_ACTIVE_ASPECTS
|
|
42
|
-
from pathlib import Path
|
|
43
|
-
from scour.scour import scourString
|
|
44
|
-
from string import Template
|
|
45
|
-
from typing import Union, List, Literal
|
|
46
|
-
from datetime import datetime
|
|
47
|
-
|
|
48
|
-
class KerykeionChartSVG:
|
|
49
|
-
"""
|
|
50
|
-
KerykeionChartSVG generates astrological chart visualizations as SVG files.
|
|
51
|
-
|
|
52
|
-
This class supports creating full chart SVGs, wheel-only SVGs, and aspect-grid-only SVGs
|
|
53
|
-
for various chart types including Natal, ExternalNatal, Transit, Synastry, and Composite.
|
|
54
|
-
Charts are rendered using XML templates and drawing utilities, with customizable themes,
|
|
55
|
-
language, active points, and aspects.
|
|
56
|
-
The rendered SVGs can be saved to a specified output directory or, by default, to the user's home directory.
|
|
57
|
-
|
|
58
|
-
NOTE:
|
|
59
|
-
The generated SVG files are optimized for web use, opening in browsers. If you want to
|
|
60
|
-
use them in other applications, you might need to adjust the SVG settings or styles.
|
|
61
|
-
|
|
62
|
-
Args:
|
|
63
|
-
first_obj (AstrologicalSubject | AstrologicalSubjectModel | CompositeSubjectModel):
|
|
64
|
-
The primary astrological subject for the chart.
|
|
65
|
-
chart_type (ChartType, optional):
|
|
66
|
-
The type of chart to generate ('Natal', 'ExternalNatal', 'Transit', 'Synastry', 'Composite').
|
|
67
|
-
Defaults to 'Natal'.
|
|
68
|
-
second_obj (AstrologicalSubject | AstrologicalSubjectModel, optional):
|
|
69
|
-
The secondary subject for Transit or Synastry charts. Not required for Natal or Composite.
|
|
70
|
-
new_output_directory (str | Path, optional):
|
|
71
|
-
Directory to write generated SVG files. Defaults to the user's home directory.
|
|
72
|
-
new_settings_file (Path | dict | KerykeionSettingsModel, optional):
|
|
73
|
-
Path or settings object to override default chart configuration (colors, fonts, aspects).
|
|
74
|
-
theme (KerykeionChartTheme, optional):
|
|
75
|
-
CSS theme for the chart. If None, no default styles are applied. Defaults to 'classic'.
|
|
76
|
-
double_chart_aspect_grid_type (Literal['list', 'table'], optional):
|
|
77
|
-
Specifies rendering style for double-chart aspect grids. Defaults to 'list'.
|
|
78
|
-
chart_language (KerykeionChartLanguage, optional):
|
|
79
|
-
Language code for chart labels. Defaults to 'EN'.
|
|
80
|
-
active_points (list[Planet | AxialCusps], optional):
|
|
81
|
-
List of celestial points and angles to include. Defaults to DEFAULT_ACTIVE_POINTS.
|
|
82
|
-
Example:
|
|
83
|
-
["Sun", "Moon", "Mercury", "Venus"]
|
|
84
|
-
|
|
85
|
-
active_aspects (list[ActiveAspect], optional):
|
|
86
|
-
List of aspects (name and orb) to calculate. Defaults to DEFAULT_ACTIVE_ASPECTS.
|
|
87
|
-
Example:
|
|
88
|
-
[
|
|
89
|
-
{"name": "conjunction", "orb": 10},
|
|
90
|
-
{"name": "opposition", "orb": 10},
|
|
91
|
-
{"name": "trine", "orb": 8},
|
|
92
|
-
{"name": "sextile", "orb": 6},
|
|
93
|
-
{"name": "square", "orb": 5},
|
|
94
|
-
{"name": "quintile", "orb": 1},
|
|
95
|
-
]
|
|
96
|
-
|
|
97
|
-
Public Methods:
|
|
98
|
-
makeTemplate(minify=False, remove_css_variables=False) -> str:
|
|
99
|
-
Render the full chart SVG as a string without writing to disk. Use `minify=True`
|
|
100
|
-
to remove whitespace and quotes, and `remove_css_variables=True` to embed CSS vars.
|
|
101
|
-
|
|
102
|
-
makeSVG(minify=False, remove_css_variables=False) -> None:
|
|
103
|
-
Generate and write the full chart SVG file to the output directory.
|
|
104
|
-
Filenames follow the pattern:
|
|
105
|
-
'{subject.name} - {chart_type} Chart.svg'.
|
|
106
|
-
|
|
107
|
-
makeWheelOnlyTemplate(minify=False, remove_css_variables=False) -> str:
|
|
108
|
-
Render only the chart wheel (no aspect grid) as an SVG string.
|
|
109
|
-
|
|
110
|
-
makeWheelOnlySVG(minify=False, remove_css_variables=False) -> None:
|
|
111
|
-
Generate and write the wheel-only SVG file:
|
|
112
|
-
'{subject.name} - {chart_type} Chart - Wheel Only.svg'.
|
|
113
|
-
|
|
114
|
-
makeAspectGridOnlyTemplate(minify=False, remove_css_variables=False) -> str:
|
|
115
|
-
Render only the aspect grid as an SVG string.
|
|
116
|
-
|
|
117
|
-
makeAspectGridOnlySVG(minify=False, remove_css_variables=False) -> None:
|
|
118
|
-
Generate and write the aspect-grid-only SVG file:
|
|
119
|
-
'{subject.name} - {chart_type} Chart - Aspect Grid Only.svg'.
|
|
120
|
-
"""
|
|
121
|
-
|
|
122
|
-
# Constants
|
|
123
|
-
_BASIC_CHART_VIEWBOX = "0 0 820 550.0"
|
|
124
|
-
_WIDE_CHART_VIEWBOX = "0 0 1200 546.0"
|
|
125
|
-
_TRANSIT_CHART_WITH_TABLE_VIWBOX = "0 0 960 546.0"
|
|
126
|
-
|
|
127
|
-
_DEFAULT_HEIGHT = 550
|
|
128
|
-
_DEFAULT_FULL_WIDTH = 1200
|
|
129
|
-
_DEFAULT_NATAL_WIDTH = 820
|
|
130
|
-
_DEFAULT_FULL_WIDTH_WITH_TABLE = 960
|
|
131
|
-
_PLANET_IN_ZODIAC_EXTRA_POINTS = 10
|
|
132
|
-
|
|
133
|
-
# Set at init
|
|
134
|
-
first_obj: Union[AstrologicalSubject, AstrologicalSubjectModel]
|
|
135
|
-
second_obj: Union[AstrologicalSubject, AstrologicalSubjectModel, None]
|
|
136
|
-
chart_type: ChartType
|
|
137
|
-
new_output_directory: Union[Path, None]
|
|
138
|
-
new_settings_file: Union[Path, None, KerykeionSettingsModel, dict]
|
|
139
|
-
output_directory: Path
|
|
140
|
-
new_settings_file: Union[Path, None, KerykeionSettingsModel, dict]
|
|
141
|
-
theme: Union[KerykeionChartTheme, None]
|
|
142
|
-
double_chart_aspect_grid_type: Literal["list", "table"]
|
|
143
|
-
chart_language: KerykeionChartLanguage
|
|
144
|
-
active_points: List[Union[Planet, AxialCusps]]
|
|
145
|
-
active_aspects: List[ActiveAspect]
|
|
146
|
-
|
|
147
|
-
# Internal properties
|
|
148
|
-
fire: float
|
|
149
|
-
earth: float
|
|
150
|
-
air: float
|
|
151
|
-
water: float
|
|
152
|
-
first_circle_radius: float
|
|
153
|
-
second_circle_radius: float
|
|
154
|
-
third_circle_radius: float
|
|
155
|
-
width: Union[float, int]
|
|
156
|
-
language_settings: dict
|
|
157
|
-
chart_colors_settings: dict
|
|
158
|
-
planets_settings: dict
|
|
159
|
-
aspects_settings: dict
|
|
160
|
-
user: Union[AstrologicalSubject, AstrologicalSubjectModel, CompositeSubjectModel]
|
|
161
|
-
available_planets_setting: List[KerykeionSettingsCelestialPointModel]
|
|
162
|
-
height: float
|
|
163
|
-
location: str
|
|
164
|
-
geolat: float
|
|
165
|
-
geolon: float
|
|
166
|
-
template: str
|
|
167
|
-
|
|
168
|
-
def __init__(
|
|
169
|
-
self,
|
|
170
|
-
first_obj: Union[AstrologicalSubject, AstrologicalSubjectModel, CompositeSubjectModel],
|
|
171
|
-
chart_type: ChartType = "Natal",
|
|
172
|
-
second_obj: Union[AstrologicalSubject, AstrologicalSubjectModel, None] = None,
|
|
173
|
-
new_output_directory: Union[str, None] = None,
|
|
174
|
-
new_settings_file: Union[Path, None, KerykeionSettingsModel, dict] = None,
|
|
175
|
-
theme: Union[KerykeionChartTheme, None] = "classic",
|
|
176
|
-
double_chart_aspect_grid_type: Literal["list", "table"] = "list",
|
|
177
|
-
chart_language: KerykeionChartLanguage = "EN",
|
|
178
|
-
active_points: List[Union[Planet, AxialCusps]] = DEFAULT_ACTIVE_POINTS,
|
|
179
|
-
active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
|
|
180
|
-
):
|
|
181
|
-
"""
|
|
182
|
-
Initialize the chart generator with subject data and configuration options.
|
|
183
|
-
|
|
184
|
-
Args:
|
|
185
|
-
first_obj (AstrologicalSubject, AstrologicalSubjectModel, or CompositeSubjectModel):
|
|
186
|
-
Primary astrological subject instance.
|
|
187
|
-
chart_type (ChartType, optional):
|
|
188
|
-
Type of chart to generate (e.g., 'Natal', 'Transit').
|
|
189
|
-
second_obj (AstrologicalSubject or AstrologicalSubjectModel, optional):
|
|
190
|
-
Secondary subject for Transit or Synastry charts.
|
|
191
|
-
new_output_directory (str or Path, optional):
|
|
192
|
-
Base directory to save generated SVG files.
|
|
193
|
-
new_settings_file (Path, dict, or KerykeionSettingsModel, optional):
|
|
194
|
-
Custom settings source for chart colors, fonts, and aspects.
|
|
195
|
-
theme (KerykeionChartTheme or None, optional):
|
|
196
|
-
CSS theme to apply; None for default styling.
|
|
197
|
-
double_chart_aspect_grid_type (Literal['list','table'], optional):
|
|
198
|
-
Layout style for double-chart aspect grids ('list' or 'table').
|
|
199
|
-
chart_language (KerykeionChartLanguage, optional):
|
|
200
|
-
Language code for chart labels (e.g., 'EN', 'IT').
|
|
201
|
-
active_points (List[Planet or AxialCusps], optional):
|
|
202
|
-
Celestial points to include in the chart visualization.
|
|
203
|
-
active_aspects (List[ActiveAspect], optional):
|
|
204
|
-
Aspects to calculate, each defined by name and orb.
|
|
205
|
-
"""
|
|
206
|
-
home_directory = Path.home()
|
|
207
|
-
self.new_settings_file = new_settings_file
|
|
208
|
-
self.chart_language = chart_language
|
|
209
|
-
self.active_points = active_points
|
|
210
|
-
self.active_aspects = active_aspects
|
|
211
|
-
|
|
212
|
-
if new_output_directory:
|
|
213
|
-
self.output_directory = Path(new_output_directory)
|
|
214
|
-
else:
|
|
215
|
-
self.output_directory = home_directory
|
|
216
|
-
|
|
217
|
-
self.parse_json_settings(new_settings_file)
|
|
218
|
-
self.chart_type = chart_type
|
|
219
|
-
|
|
220
|
-
# Kerykeion instance
|
|
221
|
-
self.user = first_obj
|
|
222
|
-
|
|
223
|
-
self.available_planets_setting = []
|
|
224
|
-
for body in self.planets_settings:
|
|
225
|
-
if body["name"] not in active_points:
|
|
226
|
-
continue
|
|
227
|
-
else:
|
|
228
|
-
body["is_active"] = True
|
|
229
|
-
|
|
230
|
-
self.available_planets_setting.append(body)
|
|
231
|
-
|
|
232
|
-
# Available bodies
|
|
233
|
-
available_celestial_points_names = []
|
|
234
|
-
for body in self.available_planets_setting:
|
|
235
|
-
available_celestial_points_names.append(body["name"].lower())
|
|
236
|
-
|
|
237
|
-
self.available_kerykeion_celestial_points: list[KerykeionPointModel] = []
|
|
238
|
-
for body in available_celestial_points_names:
|
|
239
|
-
self.available_kerykeion_celestial_points.append(self.user.get(body))
|
|
240
|
-
|
|
241
|
-
# Makes the sign number list.
|
|
242
|
-
if self.chart_type == "Natal" or self.chart_type == "ExternalNatal":
|
|
243
|
-
natal_aspects_instance = NatalAspects(
|
|
244
|
-
self.user, new_settings_file=self.new_settings_file,
|
|
245
|
-
active_points=active_points,
|
|
246
|
-
active_aspects=active_aspects,
|
|
247
|
-
)
|
|
248
|
-
self.aspects_list = natal_aspects_instance.relevant_aspects
|
|
249
|
-
|
|
250
|
-
elif self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
251
|
-
if not second_obj:
|
|
252
|
-
raise KerykeionException("Second object is required for Transit or Synastry charts.")
|
|
253
|
-
|
|
254
|
-
# Kerykeion instance
|
|
255
|
-
self.t_user = second_obj
|
|
256
|
-
|
|
257
|
-
# Aspects
|
|
258
|
-
if self.chart_type == "Transit":
|
|
259
|
-
synastry_aspects_instance = SynastryAspects(
|
|
260
|
-
self.t_user,
|
|
261
|
-
self.user,
|
|
262
|
-
new_settings_file=self.new_settings_file,
|
|
263
|
-
active_points=active_points,
|
|
264
|
-
active_aspects=active_aspects,
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
else:
|
|
268
|
-
synastry_aspects_instance = SynastryAspects(
|
|
269
|
-
self.user,
|
|
270
|
-
self.t_user,
|
|
271
|
-
new_settings_file=self.new_settings_file,
|
|
272
|
-
active_points=active_points,
|
|
273
|
-
active_aspects=active_aspects,
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
self.aspects_list = synastry_aspects_instance.relevant_aspects
|
|
277
|
-
|
|
278
|
-
self.t_available_kerykeion_celestial_points = []
|
|
279
|
-
for body in available_celestial_points_names:
|
|
280
|
-
self.t_available_kerykeion_celestial_points.append(self.t_user.get(body))
|
|
281
|
-
|
|
282
|
-
elif self.chart_type == "Composite":
|
|
283
|
-
if not isinstance(first_obj, CompositeSubjectModel):
|
|
284
|
-
raise KerykeionException("First object must be a CompositeSubjectModel instance.")
|
|
285
|
-
|
|
286
|
-
self.aspects_list = NatalAspects(self.user, new_settings_file=self.new_settings_file, active_points=active_points).relevant_aspects
|
|
287
|
-
|
|
288
|
-
# Double chart aspect grid type
|
|
289
|
-
self.double_chart_aspect_grid_type = double_chart_aspect_grid_type
|
|
290
|
-
|
|
291
|
-
# screen size
|
|
292
|
-
self.height = self._DEFAULT_HEIGHT
|
|
293
|
-
if self.chart_type == "Synastry" or self.chart_type == "Transit":
|
|
294
|
-
self.width = self._DEFAULT_FULL_WIDTH
|
|
295
|
-
elif self.double_chart_aspect_grid_type == "table" and self.chart_type == "Transit":
|
|
296
|
-
self.width = self._DEFAULT_FULL_WIDTH_WITH_TABLE
|
|
297
|
-
else:
|
|
298
|
-
self.width = self._DEFAULT_NATAL_WIDTH
|
|
299
|
-
|
|
300
|
-
if self.chart_type in ["Natal", "ExternalNatal", "Synastry"]:
|
|
301
|
-
self.location = self.user.city
|
|
302
|
-
self.geolat = self.user.lat
|
|
303
|
-
self.geolon = self.user.lng
|
|
304
|
-
|
|
305
|
-
elif self.chart_type == "Composite":
|
|
306
|
-
self.location = ""
|
|
307
|
-
self.geolat = (self.user.first_subject.lat + self.user.second_subject.lat) / 2
|
|
308
|
-
self.geolon = (self.user.first_subject.lng + self.user.second_subject.lng) / 2
|
|
309
|
-
|
|
310
|
-
elif self.chart_type in ["Transit"]:
|
|
311
|
-
self.location = self.t_user.city
|
|
312
|
-
self.geolat = self.t_user.lat
|
|
313
|
-
self.geolon = self.t_user.lng
|
|
314
|
-
self.t_name = self.language_settings["transit_name"]
|
|
315
|
-
|
|
316
|
-
# Default radius for the chart
|
|
317
|
-
self.main_radius = 240
|
|
318
|
-
|
|
319
|
-
# Set circle radii based on chart type
|
|
320
|
-
if self.chart_type == "ExternalNatal":
|
|
321
|
-
self.first_circle_radius, self.second_circle_radius, self.third_circle_radius = 56, 92, 112
|
|
322
|
-
else:
|
|
323
|
-
self.first_circle_radius, self.second_circle_radius, self.third_circle_radius = 0, 36, 120
|
|
324
|
-
|
|
325
|
-
# Initialize element points
|
|
326
|
-
self.fire = 0.0
|
|
327
|
-
self.earth = 0.0
|
|
328
|
-
self.air = 0.0
|
|
329
|
-
self.water = 0.0
|
|
330
|
-
|
|
331
|
-
# Calculate element points from planets
|
|
332
|
-
self._calculate_elements_points_from_planets()
|
|
333
|
-
|
|
334
|
-
# Set up theme
|
|
335
|
-
if theme not in get_args(KerykeionChartTheme) and theme is not None:
|
|
336
|
-
raise KerykeionException(f"Theme {theme} is not available. Set None for default theme.")
|
|
337
|
-
|
|
338
|
-
self.set_up_theme(theme)
|
|
339
|
-
|
|
340
|
-
def set_up_theme(self, theme: Union[KerykeionChartTheme, None] = None) -> None:
|
|
341
|
-
"""
|
|
342
|
-
Load and apply a CSS theme for the chart visualization.
|
|
343
|
-
|
|
344
|
-
Args:
|
|
345
|
-
theme (KerykeionChartTheme or None): Name of the theme to apply. If None, no CSS is applied.
|
|
346
|
-
"""
|
|
347
|
-
if theme is None:
|
|
348
|
-
self.color_style_tag = ""
|
|
349
|
-
return
|
|
350
|
-
|
|
351
|
-
theme_dir = Path(__file__).parent / "themes"
|
|
352
|
-
|
|
353
|
-
with open(theme_dir / f"{theme}.css", "r") as f:
|
|
354
|
-
self.color_style_tag = f.read()
|
|
355
|
-
|
|
356
|
-
def set_output_directory(self, dir_path: Path) -> None:
|
|
357
|
-
"""
|
|
358
|
-
Set the directory where generated SVG files will be saved.
|
|
359
|
-
|
|
360
|
-
Args:
|
|
361
|
-
dir_path (Path): Target directory for SVG output.
|
|
362
|
-
"""
|
|
363
|
-
self.output_directory = dir_path
|
|
364
|
-
logging.info(f"Output direcotry set to: {self.output_directory}")
|
|
365
|
-
|
|
366
|
-
def parse_json_settings(self, settings_file_or_dict: Union[Path, dict, KerykeionSettingsModel, None]) -> None:
|
|
367
|
-
"""
|
|
368
|
-
Load and parse chart configuration settings.
|
|
369
|
-
|
|
370
|
-
Args:
|
|
371
|
-
settings_file_or_dict (Path, dict, or KerykeionSettingsModel):
|
|
372
|
-
Source for custom chart settings.
|
|
373
|
-
"""
|
|
374
|
-
settings = get_settings(settings_file_or_dict)
|
|
375
|
-
|
|
376
|
-
self.language_settings = settings["language_settings"][self.chart_language]
|
|
377
|
-
self.chart_colors_settings = settings["chart_colors"]
|
|
378
|
-
self.planets_settings = settings["celestial_points"]
|
|
379
|
-
self.aspects_settings = settings["aspects"]
|
|
380
|
-
|
|
381
|
-
def _draw_zodiac_circle_slices(self, r):
|
|
382
|
-
"""
|
|
383
|
-
Draw zodiac circle slices for each sign.
|
|
384
|
-
|
|
385
|
-
Args:
|
|
386
|
-
r (float): Outer radius of the zodiac ring.
|
|
387
|
-
|
|
388
|
-
Returns:
|
|
389
|
-
str: Concatenated SVG elements for zodiac slices.
|
|
390
|
-
"""
|
|
391
|
-
sings = get_args(Sign)
|
|
392
|
-
output = ""
|
|
393
|
-
for i, sing in enumerate(sings):
|
|
394
|
-
output += draw_zodiac_slice(
|
|
395
|
-
c1=self.first_circle_radius,
|
|
396
|
-
chart_type=self.chart_type,
|
|
397
|
-
seventh_house_degree_ut=self.user.seventh_house.abs_pos,
|
|
398
|
-
num=i,
|
|
399
|
-
r=r,
|
|
400
|
-
style=f'fill:{self.chart_colors_settings[f"zodiac_bg_{i}"]}; fill-opacity: 0.5;',
|
|
401
|
-
type=sing,
|
|
402
|
-
)
|
|
403
|
-
|
|
404
|
-
return output
|
|
405
|
-
|
|
406
|
-
def _calculate_elements_points_from_planets(self):
|
|
407
|
-
"""
|
|
408
|
-
Compute elemental point totals based on active planetary positions.
|
|
409
|
-
|
|
410
|
-
Iterates over each active planet to determine its zodiac element and adds extra points
|
|
411
|
-
if the planet is in a related sign. Updates self.fire, self.earth, self.air, and self.water.
|
|
412
|
-
|
|
413
|
-
Returns:
|
|
414
|
-
None
|
|
415
|
-
"""
|
|
416
|
-
|
|
417
|
-
ZODIAC = (
|
|
418
|
-
{"name": "Ari", "element": "fire"},
|
|
419
|
-
{"name": "Tau", "element": "earth"},
|
|
420
|
-
{"name": "Gem", "element": "air"},
|
|
421
|
-
{"name": "Can", "element": "water"},
|
|
422
|
-
{"name": "Leo", "element": "fire"},
|
|
423
|
-
{"name": "Vir", "element": "earth"},
|
|
424
|
-
{"name": "Lib", "element": "air"},
|
|
425
|
-
{"name": "Sco", "element": "water"},
|
|
426
|
-
{"name": "Sag", "element": "fire"},
|
|
427
|
-
{"name": "Cap", "element": "earth"},
|
|
428
|
-
{"name": "Aqu", "element": "air"},
|
|
429
|
-
{"name": "Pis", "element": "water"},
|
|
430
|
-
)
|
|
431
|
-
|
|
432
|
-
# Available bodies
|
|
433
|
-
available_celestial_points_names = []
|
|
434
|
-
for body in self.available_planets_setting:
|
|
435
|
-
available_celestial_points_names.append(body["name"].lower())
|
|
436
|
-
|
|
437
|
-
# Make list of the points sign
|
|
438
|
-
points_sign = []
|
|
439
|
-
for planet in available_celestial_points_names:
|
|
440
|
-
points_sign.append(self.user.get(planet).sign_num)
|
|
441
|
-
|
|
442
|
-
for i in range(len(self.available_planets_setting)):
|
|
443
|
-
# element: get extra points if planet is in own zodiac sign.
|
|
444
|
-
related_zodiac_signs = self.available_planets_setting[i]["related_zodiac_signs"]
|
|
445
|
-
cz = points_sign[i]
|
|
446
|
-
extra_points = 0
|
|
447
|
-
if related_zodiac_signs != []:
|
|
448
|
-
for e in range(len(related_zodiac_signs)):
|
|
449
|
-
if int(related_zodiac_signs[e]) == int(cz):
|
|
450
|
-
extra_points = self._PLANET_IN_ZODIAC_EXTRA_POINTS
|
|
451
|
-
|
|
452
|
-
ele = ZODIAC[points_sign[i]]["element"]
|
|
453
|
-
if ele == "fire":
|
|
454
|
-
self.fire = self.fire + self.available_planets_setting[i]["element_points"] + extra_points
|
|
455
|
-
|
|
456
|
-
elif ele == "earth":
|
|
457
|
-
self.earth = self.earth + self.available_planets_setting[i]["element_points"] + extra_points
|
|
458
|
-
|
|
459
|
-
elif ele == "air":
|
|
460
|
-
self.air = self.air + self.available_planets_setting[i]["element_points"] + extra_points
|
|
461
|
-
|
|
462
|
-
elif ele == "water":
|
|
463
|
-
self.water = self.water + self.available_planets_setting[i]["element_points"] + extra_points
|
|
464
|
-
|
|
465
|
-
def _draw_all_aspects_lines(self, r, ar):
|
|
466
|
-
"""
|
|
467
|
-
Render SVG lines for all aspects in the chart.
|
|
468
|
-
|
|
469
|
-
Args:
|
|
470
|
-
r (float): Radius at which aspect lines originate.
|
|
471
|
-
ar (float): Radius at which aspect lines terminate.
|
|
472
|
-
|
|
473
|
-
Returns:
|
|
474
|
-
str: SVG markup for all aspect lines.
|
|
475
|
-
"""
|
|
476
|
-
out = ""
|
|
477
|
-
for aspect in self.aspects_list:
|
|
478
|
-
aspect_name = aspect["aspect"]
|
|
479
|
-
aspect_color = next((a["color"] for a in self.aspects_settings if a["name"] == aspect_name), None)
|
|
480
|
-
if aspect_color:
|
|
481
|
-
out += draw_aspect_line(
|
|
482
|
-
r=r,
|
|
483
|
-
ar=ar,
|
|
484
|
-
aspect=aspect,
|
|
485
|
-
color=aspect_color,
|
|
486
|
-
seventh_house_degree_ut=self.user.seventh_house.abs_pos
|
|
487
|
-
)
|
|
488
|
-
return out
|
|
489
|
-
|
|
490
|
-
def _draw_all_transit_aspects_lines(self, r, ar):
|
|
491
|
-
"""
|
|
492
|
-
Render SVG lines for all transit aspects in the chart.
|
|
493
|
-
|
|
494
|
-
Args:
|
|
495
|
-
r (float): Radius at which transit aspect lines originate.
|
|
496
|
-
ar (float): Radius at which transit aspect lines terminate.
|
|
497
|
-
|
|
498
|
-
Returns:
|
|
499
|
-
str: SVG markup for all transit aspect lines.
|
|
500
|
-
"""
|
|
501
|
-
out = ""
|
|
502
|
-
for aspect in self.aspects_list:
|
|
503
|
-
aspect_name = aspect["aspect"]
|
|
504
|
-
aspect_color = next((a["color"] for a in self.aspects_settings if a["name"] == aspect_name), None)
|
|
505
|
-
if aspect_color:
|
|
506
|
-
out += draw_aspect_line(
|
|
507
|
-
r=r,
|
|
508
|
-
ar=ar,
|
|
509
|
-
aspect=aspect,
|
|
510
|
-
color=aspect_color,
|
|
511
|
-
seventh_house_degree_ut=self.user.seventh_house.abs_pos
|
|
512
|
-
)
|
|
513
|
-
return out
|
|
514
|
-
|
|
515
|
-
def _create_template_dictionary(self) -> ChartTemplateDictionary:
|
|
516
|
-
"""
|
|
517
|
-
Assemble chart data and rendering instructions into a template dictionary.
|
|
518
|
-
|
|
519
|
-
Gathers styling, dimensions, and SVG fragments for chart components based on
|
|
520
|
-
chart type and subjects.
|
|
521
|
-
|
|
522
|
-
Returns:
|
|
523
|
-
ChartTemplateDictionary: Populated structure of template variables.
|
|
524
|
-
"""
|
|
525
|
-
# Initialize template dictionary
|
|
526
|
-
template_dict: dict = {}
|
|
527
|
-
|
|
528
|
-
# Set the color style tag
|
|
529
|
-
template_dict["color_style_tag"] = self.color_style_tag
|
|
530
|
-
|
|
531
|
-
# Set chart dimensions
|
|
532
|
-
template_dict["chart_height"] = self.height
|
|
533
|
-
template_dict["chart_width"] = self.width
|
|
534
|
-
|
|
535
|
-
# Set viewbox based on chart type
|
|
536
|
-
if self.chart_type in ["Natal", "ExternalNatal", "Composite"]:
|
|
537
|
-
template_dict['viewbox'] = self._BASIC_CHART_VIEWBOX
|
|
538
|
-
elif self.double_chart_aspect_grid_type == "table" and self.chart_type == "Transit":
|
|
539
|
-
template_dict['viewbox'] = self._TRANSIT_CHART_WITH_TABLE_VIWBOX
|
|
540
|
-
else:
|
|
541
|
-
template_dict['viewbox'] = self._WIDE_CHART_VIEWBOX
|
|
542
|
-
|
|
543
|
-
# Generate rings and circles based on chart type
|
|
544
|
-
if self.chart_type in ["Transit", "Synastry"]:
|
|
545
|
-
template_dict["transitRing"] = draw_transit_ring(self.main_radius, self.chart_colors_settings["paper_1"], self.chart_colors_settings["zodiac_transit_ring_3"])
|
|
546
|
-
template_dict["degreeRing"] = draw_transit_ring_degree_steps(self.main_radius, self.user.seventh_house.abs_pos)
|
|
547
|
-
template_dict["first_circle"] = draw_first_circle(self.main_radius, self.chart_colors_settings["zodiac_transit_ring_2"], self.chart_type)
|
|
548
|
-
template_dict["second_circle"] = draw_second_circle(self.main_radius, self.chart_colors_settings['zodiac_transit_ring_1'], self.chart_colors_settings['paper_1'], self.chart_type)
|
|
549
|
-
template_dict['third_circle'] = draw_third_circle(self.main_radius, self.chart_colors_settings['zodiac_transit_ring_0'], self.chart_colors_settings['paper_1'], self.chart_type, self.third_circle_radius)
|
|
550
|
-
|
|
551
|
-
if self.double_chart_aspect_grid_type == "list":
|
|
552
|
-
title = ""
|
|
553
|
-
if self.chart_type == "Synastry":
|
|
554
|
-
title = self.language_settings.get("couple_aspects", "Couple Aspects")
|
|
555
|
-
else:
|
|
556
|
-
title = self.language_settings.get("transit_aspects", "Transit Aspects")
|
|
557
|
-
|
|
558
|
-
template_dict["makeAspectGrid"] = draw_transit_aspect_list(title, self.aspects_list, self.planets_settings, self.aspects_settings)
|
|
559
|
-
else:
|
|
560
|
-
template_dict["makeAspectGrid"] = draw_transit_aspect_grid(self.chart_colors_settings['paper_0'], self.available_planets_setting, self.aspects_list, 550, 450)
|
|
561
|
-
|
|
562
|
-
template_dict["makeAspects"] = self._draw_all_transit_aspects_lines(self.main_radius, self.main_radius - 160)
|
|
563
|
-
else:
|
|
564
|
-
template_dict["transitRing"] = ""
|
|
565
|
-
template_dict["degreeRing"] = draw_degree_ring(self.main_radius, self.first_circle_radius, self.user.seventh_house.abs_pos, self.chart_colors_settings["paper_0"])
|
|
566
|
-
template_dict['first_circle'] = draw_first_circle(self.main_radius, self.chart_colors_settings["zodiac_radix_ring_2"], self.chart_type, self.first_circle_radius)
|
|
567
|
-
template_dict["second_circle"] = draw_second_circle(self.main_radius, self.chart_colors_settings["zodiac_radix_ring_1"], self.chart_colors_settings["paper_1"], self.chart_type, self.second_circle_radius)
|
|
568
|
-
template_dict['third_circle'] = draw_third_circle(self.main_radius, self.chart_colors_settings["zodiac_radix_ring_0"], self.chart_colors_settings["paper_1"], self.chart_type, self.third_circle_radius)
|
|
569
|
-
template_dict["makeAspectGrid"] = draw_aspect_grid(self.chart_colors_settings['paper_0'], self.available_planets_setting, self.aspects_list)
|
|
570
|
-
|
|
571
|
-
template_dict["makeAspects"] = self._draw_all_aspects_lines(self.main_radius, self.main_radius - self.third_circle_radius)
|
|
572
|
-
|
|
573
|
-
# Set chart title
|
|
574
|
-
if self.chart_type == "Synastry":
|
|
575
|
-
template_dict["stringTitle"] = f"{self.user.name} {self.language_settings['and_word']} {self.t_user.name}"
|
|
576
|
-
elif self.chart_type == "Transit":
|
|
577
|
-
template_dict["stringTitle"] = f"{self.language_settings['transits']} {self.t_user.day}/{self.t_user.month}/{self.t_user.year}"
|
|
578
|
-
elif self.chart_type in ["Natal", "ExternalNatal"]:
|
|
579
|
-
template_dict["stringTitle"] = self.user.name
|
|
580
|
-
elif self.chart_type == "Composite":
|
|
581
|
-
template_dict["stringTitle"] = f"{self.user.first_subject.name} {self.language_settings['and_word']} {self.user.second_subject.name}"
|
|
582
|
-
|
|
583
|
-
# Zodiac Type Info
|
|
584
|
-
if self.user.zodiac_type == 'Tropic':
|
|
585
|
-
zodiac_info = f"{self.language_settings.get('zodiac', 'Zodiac')}: {self.language_settings.get('tropical', 'Tropical')}"
|
|
586
|
-
else:
|
|
587
|
-
mode_const = "SIDM_" + self.user.sidereal_mode # type: ignore
|
|
588
|
-
mode_name = swe.get_ayanamsa_name(getattr(swe, mode_const))
|
|
589
|
-
zodiac_info = f"{self.language_settings.get('ayanamsa', 'Ayanamsa')}: {mode_name}"
|
|
590
|
-
|
|
591
|
-
template_dict["bottom_left_0"] = f"{self.language_settings.get('houses_system_' + self.user.houses_system_identifier, self.user.houses_system_name)} {self.language_settings.get('houses', 'Houses')}"
|
|
592
|
-
template_dict["bottom_left_1"] = zodiac_info
|
|
593
|
-
|
|
594
|
-
if self.chart_type in ["Natal", "ExternalNatal", "Synastry"]:
|
|
595
|
-
template_dict["bottom_left_2"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")} {self.language_settings.get("day", "Day").lower()}: {self.user.lunar_phase.get("moon_phase", "")}'
|
|
596
|
-
template_dict["bottom_left_3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get(self.user.lunar_phase.moon_phase_name.lower().replace(" ", "_"), self.user.lunar_phase.moon_phase_name)}'
|
|
597
|
-
template_dict["bottom_left_4"] = f'{self.language_settings.get(self.user.perspective_type.lower().replace(" ", "_"), self.user.perspective_type)}'
|
|
598
|
-
elif self.chart_type == "Transit":
|
|
599
|
-
template_dict["bottom_left_2"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get("day", "Day")} {self.t_user.lunar_phase.get("moon_phase", "")}'
|
|
600
|
-
template_dict["bottom_left_3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.t_user.lunar_phase.moon_phase_name}'
|
|
601
|
-
template_dict["bottom_left_4"] = f'{self.language_settings.get(self.t_user.perspective_type.lower().replace(" ", "_"), self.t_user.perspective_type)}'
|
|
602
|
-
elif self.chart_type == "Composite":
|
|
603
|
-
template_dict["bottom_left_2"] = f'{self.user.first_subject.perspective_type}'
|
|
604
|
-
template_dict["bottom_left_3"] = f'{self.language_settings.get("composite_chart", "Composite Chart")} - {self.language_settings.get("midpoints", "Midpoints")}'
|
|
605
|
-
template_dict["bottom_left_4"] = ""
|
|
606
|
-
|
|
607
|
-
# Draw moon phase
|
|
608
|
-
moon_phase_dict = calculate_moon_phase_chart_params(
|
|
609
|
-
self.user.lunar_phase["degrees_between_s_m"],
|
|
610
|
-
self.geolat
|
|
611
|
-
)
|
|
612
|
-
|
|
613
|
-
template_dict["lunar_phase_rotate"] = moon_phase_dict["lunar_phase_rotate"]
|
|
614
|
-
template_dict["lunar_phase_circle_center_x"] = moon_phase_dict["circle_center_x"]
|
|
615
|
-
template_dict["lunar_phase_circle_radius"] = moon_phase_dict["circle_radius"]
|
|
616
|
-
|
|
617
|
-
if self.chart_type == "Composite":
|
|
618
|
-
template_dict["top_left_1"] = f"{datetime.fromisoformat(self.user.first_subject.iso_formatted_local_datetime).strftime('%Y-%m-%d %H:%M')}"
|
|
619
|
-
# Set location string
|
|
620
|
-
elif len(self.location) > 35:
|
|
621
|
-
split_location = self.location.split(",")
|
|
622
|
-
if len(split_location) > 1:
|
|
623
|
-
template_dict["top_left_1"] = split_location[0] + ", " + split_location[-1]
|
|
624
|
-
if len(template_dict["top_left_1"]) > 35:
|
|
625
|
-
template_dict["top_left_1"] = template_dict["top_left_1"][:35] + "..."
|
|
626
|
-
else:
|
|
627
|
-
template_dict["top_left_1"] = self.location[:35] + "..."
|
|
628
|
-
else:
|
|
629
|
-
template_dict["top_left_1"] = self.location
|
|
630
|
-
|
|
631
|
-
# Set chart name
|
|
632
|
-
if self.chart_type in ["Synastry", "Transit"]:
|
|
633
|
-
template_dict["top_left_0"] = f"{self.user.name}:"
|
|
634
|
-
elif self.chart_type in ["Natal", "ExternalNatal"]:
|
|
635
|
-
template_dict["top_left_0"] = f'{self.language_settings["info"]}:'
|
|
636
|
-
elif self.chart_type == "Composite":
|
|
637
|
-
template_dict["top_left_0"] = f'{self.user.first_subject.name}'
|
|
638
|
-
|
|
639
|
-
# Set additional information for Synastry chart type
|
|
640
|
-
if self.chart_type == "Synastry":
|
|
641
|
-
template_dict["top_left_3"] = f"{self.t_user.name}: "
|
|
642
|
-
template_dict["top_left_4"] = self.t_user.city
|
|
643
|
-
template_dict["top_left_5"] = f"{self.t_user.year}-{self.t_user.month}-{self.t_user.day} {self.t_user.hour:02d}:{self.t_user.minute:02d}"
|
|
644
|
-
elif self.chart_type == "Composite":
|
|
645
|
-
template_dict["top_left_3"] = self.user.second_subject.name
|
|
646
|
-
template_dict["top_left_4"] = f"{datetime.fromisoformat(self.user.second_subject.iso_formatted_local_datetime).strftime('%Y-%m-%d %H:%M')}"
|
|
647
|
-
latitude_string = convert_latitude_coordinate_to_string(self.user.second_subject.lat, self.language_settings['north_letter'], self.language_settings['south_letter'])
|
|
648
|
-
longitude_string = convert_longitude_coordinate_to_string(self.user.second_subject.lng, self.language_settings['east_letter'], self.language_settings['west_letter'])
|
|
649
|
-
template_dict["top_left_5"] = f"{latitude_string} / {longitude_string}"
|
|
650
|
-
else:
|
|
651
|
-
latitude_string = convert_latitude_coordinate_to_string(self.geolat, self.language_settings['north'], self.language_settings['south'])
|
|
652
|
-
longitude_string = convert_longitude_coordinate_to_string(self.geolon, self.language_settings['east'], self.language_settings['west'])
|
|
653
|
-
template_dict["top_left_3"] = f"{self.language_settings['latitude']}: {latitude_string}"
|
|
654
|
-
template_dict["top_left_4"] = f"{self.language_settings['longitude']}: {longitude_string}"
|
|
655
|
-
template_dict["top_left_5"] = f"{self.language_settings['type']}: {self.language_settings.get(self.chart_type, self.chart_type)}"
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
# Set paper colors
|
|
659
|
-
template_dict["paper_color_0"] = self.chart_colors_settings["paper_0"]
|
|
660
|
-
template_dict["paper_color_1"] = self.chart_colors_settings["paper_1"]
|
|
661
|
-
|
|
662
|
-
# Set planet colors
|
|
663
|
-
for planet in self.planets_settings:
|
|
664
|
-
planet_id = planet["id"]
|
|
665
|
-
template_dict[f"planets_color_{planet_id}"] = planet["color"] # type: ignore
|
|
666
|
-
|
|
667
|
-
# Set zodiac colors
|
|
668
|
-
for i in range(12):
|
|
669
|
-
template_dict[f"zodiac_color_{i}"] = self.chart_colors_settings[f"zodiac_icon_{i}"] # type: ignore
|
|
670
|
-
|
|
671
|
-
# Set orb colors
|
|
672
|
-
for aspect in self.aspects_settings:
|
|
673
|
-
template_dict[f"orb_color_{aspect['degree']}"] = aspect['color'] # type: ignore
|
|
674
|
-
|
|
675
|
-
# Drawing functions
|
|
676
|
-
template_dict["makeZodiac"] = self._draw_zodiac_circle_slices(self.main_radius)
|
|
677
|
-
|
|
678
|
-
first_subject_houses_list = get_houses_list(self.user)
|
|
679
|
-
|
|
680
|
-
# Draw houses grid and cusps
|
|
681
|
-
if self.chart_type in ["Transit", "Synastry"]:
|
|
682
|
-
second_subject_houses_list = get_houses_list(self.t_user)
|
|
683
|
-
|
|
684
|
-
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
685
|
-
main_subject_houses_list=first_subject_houses_list,
|
|
686
|
-
secondary_subject_houses_list=second_subject_houses_list,
|
|
687
|
-
chart_type=self.chart_type,
|
|
688
|
-
text_color=self.chart_colors_settings["paper_0"],
|
|
689
|
-
house_cusp_generale_name_label=self.language_settings["cusp"]
|
|
690
|
-
)
|
|
691
|
-
|
|
692
|
-
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
693
|
-
r=self.main_radius,
|
|
694
|
-
first_subject_houses_list=first_subject_houses_list,
|
|
695
|
-
standard_house_cusp_color=self.chart_colors_settings["houses_radix_line"],
|
|
696
|
-
first_house_color=self.planets_settings[12]["color"],
|
|
697
|
-
tenth_house_color=self.planets_settings[13]["color"],
|
|
698
|
-
seventh_house_color=self.planets_settings[14]["color"],
|
|
699
|
-
fourth_house_color=self.planets_settings[15]["color"],
|
|
700
|
-
c1=self.first_circle_radius,
|
|
701
|
-
c3=self.third_circle_radius,
|
|
702
|
-
chart_type=self.chart_type,
|
|
703
|
-
second_subject_houses_list=second_subject_houses_list,
|
|
704
|
-
transit_house_cusp_color=self.chart_colors_settings["houses_transit_line"],
|
|
705
|
-
)
|
|
706
|
-
|
|
707
|
-
else:
|
|
708
|
-
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
709
|
-
main_subject_houses_list=first_subject_houses_list,
|
|
710
|
-
chart_type=self.chart_type,
|
|
711
|
-
text_color=self.chart_colors_settings["paper_0"],
|
|
712
|
-
house_cusp_generale_name_label=self.language_settings["cusp"]
|
|
713
|
-
)
|
|
714
|
-
|
|
715
|
-
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
716
|
-
r=self.main_radius,
|
|
717
|
-
first_subject_houses_list=first_subject_houses_list,
|
|
718
|
-
standard_house_cusp_color=self.chart_colors_settings["houses_radix_line"],
|
|
719
|
-
first_house_color=self.planets_settings[12]["color"],
|
|
720
|
-
tenth_house_color=self.planets_settings[13]["color"],
|
|
721
|
-
seventh_house_color=self.planets_settings[14]["color"],
|
|
722
|
-
fourth_house_color=self.planets_settings[15]["color"],
|
|
723
|
-
c1=self.first_circle_radius,
|
|
724
|
-
c3=self.third_circle_radius,
|
|
725
|
-
chart_type=self.chart_type,
|
|
726
|
-
)
|
|
727
|
-
|
|
728
|
-
# Draw planets
|
|
729
|
-
if self.chart_type in ["Transit", "Synastry"]:
|
|
730
|
-
template_dict["makePlanets"] = draw_planets(
|
|
731
|
-
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
732
|
-
available_planets_setting=self.available_planets_setting,
|
|
733
|
-
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
734
|
-
radius=self.main_radius,
|
|
735
|
-
main_subject_first_house_degree_ut=self.user.first_house.abs_pos,
|
|
736
|
-
main_subject_seventh_house_degree_ut=self.user.seventh_house.abs_pos,
|
|
737
|
-
chart_type=self.chart_type,
|
|
738
|
-
third_circle_radius=self.third_circle_radius,
|
|
739
|
-
)
|
|
740
|
-
else:
|
|
741
|
-
template_dict["makePlanets"] = draw_planets(
|
|
742
|
-
available_planets_setting=self.available_planets_setting,
|
|
743
|
-
chart_type=self.chart_type,
|
|
744
|
-
radius=self.main_radius,
|
|
745
|
-
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
746
|
-
third_circle_radius=self.third_circle_radius,
|
|
747
|
-
main_subject_first_house_degree_ut=self.user.first_house.abs_pos,
|
|
748
|
-
main_subject_seventh_house_degree_ut=self.user.seventh_house.abs_pos
|
|
749
|
-
)
|
|
750
|
-
|
|
751
|
-
# Draw elements percentages
|
|
752
|
-
total = self.fire + self.water + self.earth + self.air
|
|
753
|
-
|
|
754
|
-
fire_percentage = int(round(100 * self.fire / total))
|
|
755
|
-
earth_percentage = int(round(100 * self.earth / total))
|
|
756
|
-
air_percentage = int(round(100 * self.air / total))
|
|
757
|
-
water_percentage = int(round(100 * self.water / total))
|
|
758
|
-
|
|
759
|
-
template_dict["fire_string"] = f"{self.language_settings['fire']} {fire_percentage}%"
|
|
760
|
-
template_dict["earth_string"] = f"{self.language_settings['earth']} {earth_percentage}%"
|
|
761
|
-
template_dict["air_string"] = f"{self.language_settings['air']} {air_percentage}%"
|
|
762
|
-
template_dict["water_string"] = f"{self.language_settings['water']} {water_percentage}%"
|
|
763
|
-
|
|
764
|
-
# Draw planet grid
|
|
765
|
-
if self.chart_type in ["Transit", "Synastry"]:
|
|
766
|
-
if self.chart_type == "Transit":
|
|
767
|
-
second_subject_table_name = self.language_settings["transit_name"]
|
|
768
|
-
else:
|
|
769
|
-
second_subject_table_name = self.t_user.name
|
|
770
|
-
|
|
771
|
-
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
772
|
-
planets_and_houses_grid_title=self.language_settings["planets_and_house"],
|
|
773
|
-
subject_name=self.user.name,
|
|
774
|
-
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
775
|
-
chart_type=self.chart_type,
|
|
776
|
-
text_color=self.chart_colors_settings["paper_0"],
|
|
777
|
-
celestial_point_language=self.language_settings["celestial_points"],
|
|
778
|
-
second_subject_name=second_subject_table_name,
|
|
779
|
-
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
780
|
-
)
|
|
781
|
-
else:
|
|
782
|
-
if self.chart_type == "Composite":
|
|
783
|
-
subject_name = f"{self.user.first_subject.name} {self.language_settings['and_word']} {self.user.second_subject.name}"
|
|
784
|
-
else:
|
|
785
|
-
subject_name = self.user.name
|
|
786
|
-
|
|
787
|
-
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
788
|
-
planets_and_houses_grid_title=self.language_settings["planets_and_house"],
|
|
789
|
-
subject_name=subject_name,
|
|
790
|
-
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
791
|
-
chart_type=self.chart_type,
|
|
792
|
-
text_color=self.chart_colors_settings["paper_0"],
|
|
793
|
-
celestial_point_language=self.language_settings["celestial_points"],
|
|
794
|
-
)
|
|
795
|
-
|
|
796
|
-
# Set date time string
|
|
797
|
-
if self.chart_type in ["Composite"]:
|
|
798
|
-
# First Subject Latitude and Longitude
|
|
799
|
-
latitude = convert_latitude_coordinate_to_string(self.user.first_subject.lat, self.language_settings["north_letter"], self.language_settings["south_letter"])
|
|
800
|
-
longitude = convert_longitude_coordinate_to_string(self.user.first_subject.lng, self.language_settings["east_letter"], self.language_settings["west_letter"])
|
|
801
|
-
template_dict["top_left_2"] = f"{latitude} {longitude}"
|
|
802
|
-
else:
|
|
803
|
-
dt = datetime.fromisoformat(self.user.iso_formatted_local_datetime)
|
|
804
|
-
custom_format = dt.strftime('%Y-%m-%d %H:%M [%z]')
|
|
805
|
-
custom_format = custom_format[:-3] + ':' + custom_format[-3:]
|
|
806
|
-
template_dict["top_left_2"] = f"{custom_format}"
|
|
807
|
-
|
|
808
|
-
return ChartTemplateDictionary(**template_dict)
|
|
809
|
-
|
|
810
|
-
def makeTemplate(self, minify: bool = False, remove_css_variables = False) -> str:
|
|
811
|
-
"""
|
|
812
|
-
Render the full chart SVG as a string.
|
|
813
|
-
|
|
814
|
-
Reads the XML template, substitutes variables, and optionally inlines CSS
|
|
815
|
-
variables and minifies the output.
|
|
816
|
-
|
|
817
|
-
Args:
|
|
818
|
-
minify (bool): Remove whitespace and quotes for compactness.
|
|
819
|
-
remove_css_variables (bool): Embed CSS variable definitions.
|
|
820
|
-
|
|
821
|
-
Returns:
|
|
822
|
-
str: SVG markup as a string.
|
|
823
|
-
"""
|
|
824
|
-
td = self._create_template_dictionary()
|
|
825
|
-
|
|
826
|
-
DATA_DIR = Path(__file__).parent
|
|
827
|
-
xml_svg = DATA_DIR / "templates" / "chart.xml"
|
|
828
|
-
|
|
829
|
-
# read template
|
|
830
|
-
with open(xml_svg, "r", encoding="utf-8", errors="ignore") as f:
|
|
831
|
-
template = Template(f.read()).substitute(td)
|
|
832
|
-
|
|
833
|
-
# return filename
|
|
834
|
-
|
|
835
|
-
logging.debug(f"Template dictionary keys: {td.keys()}")
|
|
836
|
-
|
|
837
|
-
self._create_template_dictionary()
|
|
838
|
-
|
|
839
|
-
if remove_css_variables:
|
|
840
|
-
template = inline_css_variables_in_svg(template)
|
|
841
|
-
|
|
842
|
-
if minify:
|
|
843
|
-
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
844
|
-
|
|
845
|
-
else:
|
|
846
|
-
template = template.replace('"', "'")
|
|
847
|
-
|
|
848
|
-
return template
|
|
849
|
-
|
|
850
|
-
def makeSVG(self, minify: bool = False, remove_css_variables = False):
|
|
851
|
-
"""
|
|
852
|
-
Generate and save the full chart SVG to disk.
|
|
853
|
-
|
|
854
|
-
Calls makeTemplate to render the SVG, then writes a file named
|
|
855
|
-
"{subject.name} - {chart_type} Chart.svg" in the output directory.
|
|
856
|
-
|
|
857
|
-
Args:
|
|
858
|
-
minify (bool): Pass-through to makeTemplate for compact output.
|
|
859
|
-
remove_css_variables (bool): Pass-through to makeTemplate to embed CSS variables.
|
|
860
|
-
|
|
861
|
-
Returns:
|
|
862
|
-
None
|
|
863
|
-
"""
|
|
864
|
-
|
|
865
|
-
self.template = self.makeTemplate(minify, remove_css_variables)
|
|
866
|
-
|
|
867
|
-
chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart.svg"
|
|
868
|
-
|
|
869
|
-
with open(chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
870
|
-
output_file.write(self.template)
|
|
871
|
-
|
|
872
|
-
print(f"SVG Generated Correctly in: {chartname}")
|
|
873
|
-
|
|
874
|
-
def makeWheelOnlyTemplate(self, minify: bool = False, remove_css_variables = False):
|
|
875
|
-
"""
|
|
876
|
-
Render the wheel-only chart SVG as a string.
|
|
877
|
-
|
|
878
|
-
Reads the wheel-only XML template, substitutes chart data, and applies optional
|
|
879
|
-
CSS inlining and minification.
|
|
880
|
-
|
|
881
|
-
Args:
|
|
882
|
-
minify (bool): Remove whitespace and quotes for compactness.
|
|
883
|
-
remove_css_variables (bool): Embed CSS variable definitions.
|
|
884
|
-
|
|
885
|
-
Returns:
|
|
886
|
-
str: SVG markup for the chart wheel only.
|
|
887
|
-
"""
|
|
888
|
-
|
|
889
|
-
with open(Path(__file__).parent / "templates" / "wheel_only.xml", "r", encoding="utf-8", errors="ignore") as f:
|
|
890
|
-
template = f.read()
|
|
891
|
-
|
|
892
|
-
template_dict = self._create_template_dictionary()
|
|
893
|
-
template = Template(template).substitute(template_dict)
|
|
894
|
-
|
|
895
|
-
if remove_css_variables:
|
|
896
|
-
template = inline_css_variables_in_svg(template)
|
|
897
|
-
|
|
898
|
-
if minify:
|
|
899
|
-
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
900
|
-
|
|
901
|
-
else:
|
|
902
|
-
template = template.replace('"', "'")
|
|
903
|
-
|
|
904
|
-
return template
|
|
905
|
-
|
|
906
|
-
def makeWheelOnlySVG(self, minify: bool = False, remove_css_variables = False):
|
|
907
|
-
"""
|
|
908
|
-
Generate and save wheel-only chart SVG to disk.
|
|
909
|
-
|
|
910
|
-
Calls makeWheelOnlyTemplate and writes a file named
|
|
911
|
-
"{subject.name} - {chart_type} Chart - Wheel Only.svg" in the output directory.
|
|
912
|
-
|
|
913
|
-
Args:
|
|
914
|
-
minify (bool): Pass-through to makeWheelOnlyTemplate for compact output.
|
|
915
|
-
remove_css_variables (bool): Pass-through to makeWheelOnlyTemplate to embed CSS variables.
|
|
916
|
-
|
|
917
|
-
Returns:
|
|
918
|
-
None
|
|
919
|
-
"""
|
|
920
|
-
|
|
921
|
-
template = self.makeWheelOnlyTemplate(minify, remove_css_variables)
|
|
922
|
-
chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart - Wheel Only.svg"
|
|
923
|
-
|
|
924
|
-
with open(chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
925
|
-
output_file.write(template)
|
|
926
|
-
|
|
927
|
-
print(f"SVG Generated Correctly in: {chartname}")
|
|
928
|
-
|
|
929
|
-
def makeAspectGridOnlyTemplate(self, minify: bool = False, remove_css_variables = False):
|
|
930
|
-
"""
|
|
931
|
-
Render the aspect-grid-only chart SVG as a string.
|
|
932
|
-
|
|
933
|
-
Reads the aspect-grid XML template, generates the aspect grid based on chart type,
|
|
934
|
-
and applies optional CSS inlining and minification.
|
|
935
|
-
|
|
936
|
-
Args:
|
|
937
|
-
minify (bool): Remove whitespace and quotes for compactness.
|
|
938
|
-
remove_css_variables (bool): Embed CSS variable definitions.
|
|
939
|
-
|
|
940
|
-
Returns:
|
|
941
|
-
str: SVG markup for the aspect grid only.
|
|
942
|
-
"""
|
|
943
|
-
|
|
944
|
-
with open(Path(__file__).parent / "templates" / "aspect_grid_only.xml", "r", encoding="utf-8", errors="ignore") as f:
|
|
945
|
-
template = f.read()
|
|
946
|
-
|
|
947
|
-
template_dict = self._create_template_dictionary()
|
|
948
|
-
|
|
949
|
-
if self.chart_type in ["Transit", "Synastry"]:
|
|
950
|
-
aspects_grid = draw_transit_aspect_grid(self.chart_colors_settings['paper_0'], self.available_planets_setting, self.aspects_list)
|
|
951
|
-
else:
|
|
952
|
-
aspects_grid = draw_aspect_grid(self.chart_colors_settings['paper_0'], self.available_planets_setting, self.aspects_list, x_start=50, y_start=250)
|
|
953
|
-
|
|
954
|
-
template = Template(template).substitute({**template_dict, "makeAspectGrid": aspects_grid})
|
|
955
|
-
|
|
956
|
-
if remove_css_variables:
|
|
957
|
-
template = inline_css_variables_in_svg(template)
|
|
958
|
-
|
|
959
|
-
if minify:
|
|
960
|
-
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
961
|
-
|
|
962
|
-
else:
|
|
963
|
-
template = template.replace('"', "'")
|
|
964
|
-
|
|
965
|
-
return template
|
|
966
|
-
|
|
967
|
-
def makeAspectGridOnlySVG(self, minify: bool = False, remove_css_variables = False):
|
|
968
|
-
"""
|
|
969
|
-
Generate and save aspect-grid-only chart SVG to disk.
|
|
970
|
-
|
|
971
|
-
Calls makeAspectGridOnlyTemplate and writes a file named
|
|
972
|
-
"{subject.name} - {chart_type} Chart - Aspect Grid Only.svg" in the output directory.
|
|
973
|
-
|
|
974
|
-
Args:
|
|
975
|
-
minify (bool): Pass-through to makeAspectGridOnlyTemplate for compact output.
|
|
976
|
-
remove_css_variables (bool): Pass-through to makeAspectGridOnlyTemplate to embed CSS variables.
|
|
977
|
-
|
|
978
|
-
Returns:
|
|
979
|
-
None
|
|
980
|
-
"""
|
|
981
|
-
|
|
982
|
-
template = self.makeAspectGridOnlyTemplate(minify, remove_css_variables)
|
|
983
|
-
chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart - Aspect Grid Only.svg"
|
|
984
|
-
|
|
985
|
-
with open(chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
986
|
-
output_file.write(template)
|
|
987
|
-
|
|
988
|
-
print(f"SVG Generated Correctly in: {chartname}")
|
|
989
|
-
|
|
990
|
-
if __name__ == "__main__":
|
|
991
|
-
from kerykeion.utilities import setup_logging
|
|
992
|
-
from kerykeion.composite_subject_factory import CompositeSubjectFactory
|
|
993
|
-
setup_logging(level="debug")
|
|
994
|
-
|
|
995
|
-
first = AstrologicalSubject("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
996
|
-
second = AstrologicalSubject("Paul McCartney", 1942, 6, 18, 15, 30, "Liverpool", "GB")
|
|
997
|
-
|
|
998
|
-
# Internal Natal Chart
|
|
999
|
-
internal_natal_chart = KerykeionChartSVG(first)
|
|
1000
|
-
internal_natal_chart.makeSVG()
|
|
1001
|
-
|
|
1002
|
-
# External Natal Chart
|
|
1003
|
-
external_natal_chart = KerykeionChartSVG(first, "ExternalNatal", second)
|
|
1004
|
-
external_natal_chart.makeSVG()
|
|
1005
|
-
|
|
1006
|
-
# Synastry Chart
|
|
1007
|
-
synastry_chart = KerykeionChartSVG(first, "Synastry", second)
|
|
1008
|
-
synastry_chart.makeSVG()
|
|
1009
|
-
|
|
1010
|
-
# Transits Chart
|
|
1011
|
-
transits_chart = KerykeionChartSVG(first, "Transit", second)
|
|
1012
|
-
transits_chart.makeSVG()
|
|
1013
|
-
|
|
1014
|
-
# Sidereal Birth Chart (Lahiri)
|
|
1015
|
-
sidereal_subject = AstrologicalSubject("John Lennon Lahiri", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="LAHIRI")
|
|
1016
|
-
sidereal_chart = KerykeionChartSVG(sidereal_subject)
|
|
1017
|
-
sidereal_chart.makeSVG()
|
|
1018
|
-
|
|
1019
|
-
# Sidereal Birth Chart (Fagan-Bradley)
|
|
1020
|
-
sidereal_subject = AstrologicalSubject("John Lennon Fagan-Bradley", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="FAGAN_BRADLEY")
|
|
1021
|
-
sidereal_chart = KerykeionChartSVG(sidereal_subject)
|
|
1022
|
-
sidereal_chart.makeSVG()
|
|
1023
|
-
|
|
1024
|
-
# Sidereal Birth Chart (DeLuce)
|
|
1025
|
-
sidereal_subject = AstrologicalSubject("John Lennon DeLuce", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="DELUCE")
|
|
1026
|
-
sidereal_chart = KerykeionChartSVG(sidereal_subject)
|
|
1027
|
-
sidereal_chart.makeSVG()
|
|
1028
|
-
|
|
1029
|
-
# Sidereal Birth Chart (J2000)
|
|
1030
|
-
sidereal_subject = AstrologicalSubject("John Lennon J2000", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="J2000")
|
|
1031
|
-
sidereal_chart = KerykeionChartSVG(sidereal_subject)
|
|
1032
|
-
sidereal_chart.makeSVG()
|
|
1033
|
-
|
|
1034
|
-
# House System Morinus
|
|
1035
|
-
morinus_house_subject = AstrologicalSubject("John Lennon - House System Morinus", 1940, 10, 9, 18, 30, "Liverpool", "GB", houses_system_identifier="M")
|
|
1036
|
-
morinus_house_chart = KerykeionChartSVG(morinus_house_subject)
|
|
1037
|
-
morinus_house_chart.makeSVG()
|
|
1038
|
-
|
|
1039
|
-
## To check all the available house systems uncomment the following code:
|
|
1040
|
-
# from kerykeion.kr_types import HousesSystemIdentifier
|
|
1041
|
-
# from typing import get_args
|
|
1042
|
-
# for i in get_args(HousesSystemIdentifier):
|
|
1043
|
-
# alternatives_house_subject = AstrologicalSubject(f"John Lennon - House System {i}", 1940, 10, 9, 18, 30, "Liverpool", "GB", houses_system=i)
|
|
1044
|
-
# alternatives_house_chart = KerykeionChartSVG(alternatives_house_subject)
|
|
1045
|
-
# alternatives_house_chart.makeSVG()
|
|
1046
|
-
|
|
1047
|
-
# With True Geocentric Perspective
|
|
1048
|
-
true_geocentric_subject = AstrologicalSubject("John Lennon - True Geocentric", 1940, 10, 9, 18, 30, "Liverpool", "GB", perspective_type="True Geocentric")
|
|
1049
|
-
true_geocentric_chart = KerykeionChartSVG(true_geocentric_subject)
|
|
1050
|
-
true_geocentric_chart.makeSVG()
|
|
1051
|
-
|
|
1052
|
-
# With Heliocentric Perspective
|
|
1053
|
-
heliocentric_subject = AstrologicalSubject("John Lennon - Heliocentric", 1940, 10, 9, 18, 30, "Liverpool", "GB", perspective_type="Heliocentric")
|
|
1054
|
-
heliocentric_chart = KerykeionChartSVG(heliocentric_subject)
|
|
1055
|
-
heliocentric_chart.makeSVG()
|
|
1056
|
-
|
|
1057
|
-
# With Topocentric Perspective
|
|
1058
|
-
topocentric_subject = AstrologicalSubject("John Lennon - Topocentric", 1940, 10, 9, 18, 30, "Liverpool", "GB", perspective_type="Topocentric")
|
|
1059
|
-
topocentric_chart = KerykeionChartSVG(topocentric_subject)
|
|
1060
|
-
topocentric_chart.makeSVG()
|
|
1061
|
-
|
|
1062
|
-
# Minified SVG
|
|
1063
|
-
minified_subject = AstrologicalSubject("John Lennon - Minified", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1064
|
-
minified_chart = KerykeionChartSVG(minified_subject)
|
|
1065
|
-
minified_chart.makeSVG(minify=True)
|
|
1066
|
-
|
|
1067
|
-
# Dark Theme Natal Chart
|
|
1068
|
-
dark_theme_subject = AstrologicalSubject("John Lennon - Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1069
|
-
dark_theme_natal_chart = KerykeionChartSVG(dark_theme_subject, theme="dark")
|
|
1070
|
-
dark_theme_natal_chart.makeSVG()
|
|
1071
|
-
|
|
1072
|
-
# Dark High Contrast Theme Natal Chart
|
|
1073
|
-
dark_high_contrast_theme_subject = AstrologicalSubject("John Lennon - Dark High Contrast Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1074
|
-
dark_high_contrast_theme_natal_chart = KerykeionChartSVG(dark_high_contrast_theme_subject, theme="dark-high-contrast")
|
|
1075
|
-
dark_high_contrast_theme_natal_chart.makeSVG()
|
|
1076
|
-
|
|
1077
|
-
# Light Theme Natal Chart
|
|
1078
|
-
light_theme_subject = AstrologicalSubject("John Lennon - Light Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1079
|
-
light_theme_natal_chart = KerykeionChartSVG(light_theme_subject, theme="light")
|
|
1080
|
-
light_theme_natal_chart.makeSVG()
|
|
1081
|
-
|
|
1082
|
-
# Dark Theme External Natal Chart
|
|
1083
|
-
dark_theme_external_subject = AstrologicalSubject("John Lennon - Dark Theme External", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1084
|
-
dark_theme_external_chart = KerykeionChartSVG(dark_theme_external_subject, "ExternalNatal", second, theme="dark")
|
|
1085
|
-
dark_theme_external_chart.makeSVG()
|
|
1086
|
-
|
|
1087
|
-
# Dark Theme Synastry Chart
|
|
1088
|
-
dark_theme_synastry_subject = AstrologicalSubject("John Lennon - DTS", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1089
|
-
dark_theme_synastry_chart = KerykeionChartSVG(dark_theme_synastry_subject, "Synastry", second, theme="dark")
|
|
1090
|
-
dark_theme_synastry_chart.makeSVG()
|
|
1091
|
-
|
|
1092
|
-
# Wheel Natal Only Chart
|
|
1093
|
-
wheel_only_subject = AstrologicalSubject("John Lennon - Wheel Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1094
|
-
wheel_only_chart = KerykeionChartSVG(wheel_only_subject)
|
|
1095
|
-
wheel_only_chart.makeWheelOnlySVG()
|
|
1096
|
-
|
|
1097
|
-
# Wheel External Natal Only Chart
|
|
1098
|
-
wheel_external_subject = AstrologicalSubject("John Lennon - Wheel External Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1099
|
-
wheel_external_chart = KerykeionChartSVG(wheel_external_subject, "ExternalNatal", second)
|
|
1100
|
-
wheel_external_chart.makeWheelOnlySVG()
|
|
1101
|
-
|
|
1102
|
-
# Wheel Synastry Only Chart
|
|
1103
|
-
wheel_synastry_subject = AstrologicalSubject("John Lennon - Wheel Synastry Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1104
|
-
wheel_synastry_chart = KerykeionChartSVG(wheel_synastry_subject, "Synastry", second)
|
|
1105
|
-
wheel_synastry_chart.makeWheelOnlySVG()
|
|
1106
|
-
|
|
1107
|
-
# Wheel Transit Only Chart
|
|
1108
|
-
wheel_transit_subject = AstrologicalSubject("John Lennon - Wheel Transit Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1109
|
-
wheel_transit_chart = KerykeionChartSVG(wheel_transit_subject, "Transit", second)
|
|
1110
|
-
wheel_transit_chart.makeWheelOnlySVG()
|
|
1111
|
-
|
|
1112
|
-
# Wheel Sidereal Birth Chart (Lahiri) Dark Theme
|
|
1113
|
-
sidereal_dark_subject = AstrologicalSubject("John Lennon Lahiri - Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="LAHIRI")
|
|
1114
|
-
sidereal_dark_chart = KerykeionChartSVG(sidereal_dark_subject, theme="dark")
|
|
1115
|
-
sidereal_dark_chart.makeWheelOnlySVG()
|
|
1116
|
-
|
|
1117
|
-
# Wheel Sidereal Birth Chart (Fagan-Bradley) Light Theme
|
|
1118
|
-
sidereal_light_subject = AstrologicalSubject("John Lennon Fagan-Bradley - Light Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="FAGAN_BRADLEY")
|
|
1119
|
-
sidereal_light_chart = KerykeionChartSVG(sidereal_light_subject, theme="light")
|
|
1120
|
-
sidereal_light_chart.makeWheelOnlySVG()
|
|
1121
|
-
|
|
1122
|
-
# Aspect Grid Only Natal Chart
|
|
1123
|
-
aspect_grid_only_subject = AstrologicalSubject("John Lennon - Aspect Grid Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1124
|
-
aspect_grid_only_chart = KerykeionChartSVG(aspect_grid_only_subject)
|
|
1125
|
-
aspect_grid_only_chart.makeAspectGridOnlySVG()
|
|
1126
|
-
|
|
1127
|
-
# Aspect Grid Only Dark Theme Natal Chart
|
|
1128
|
-
aspect_grid_dark_subject = AstrologicalSubject("John Lennon - Aspect Grid Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1129
|
-
aspect_grid_dark_chart = KerykeionChartSVG(aspect_grid_dark_subject, theme="dark")
|
|
1130
|
-
aspect_grid_dark_chart.makeAspectGridOnlySVG()
|
|
1131
|
-
|
|
1132
|
-
# Aspect Grid Only Light Theme Natal Chart
|
|
1133
|
-
aspect_grid_light_subject = AstrologicalSubject("John Lennon - Aspect Grid Light Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1134
|
-
aspect_grid_light_chart = KerykeionChartSVG(aspect_grid_light_subject, theme="light")
|
|
1135
|
-
aspect_grid_light_chart.makeAspectGridOnlySVG()
|
|
1136
|
-
|
|
1137
|
-
# Synastry Chart Aspect Grid Only
|
|
1138
|
-
aspect_grid_synastry_subject = AstrologicalSubject("John Lennon - Aspect Grid Synastry", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1139
|
-
aspect_grid_synastry_chart = KerykeionChartSVG(aspect_grid_synastry_subject, "Synastry", second)
|
|
1140
|
-
aspect_grid_synastry_chart.makeAspectGridOnlySVG()
|
|
1141
|
-
|
|
1142
|
-
# Transit Chart Aspect Grid Only
|
|
1143
|
-
aspect_grid_transit_subject = AstrologicalSubject("John Lennon - Aspect Grid Transit", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1144
|
-
aspect_grid_transit_chart = KerykeionChartSVG(aspect_grid_transit_subject, "Transit", second)
|
|
1145
|
-
aspect_grid_transit_chart.makeAspectGridOnlySVG()
|
|
1146
|
-
|
|
1147
|
-
# Synastry Chart Aspect Grid Only Dark Theme
|
|
1148
|
-
aspect_grid_dark_synastry_subject = AstrologicalSubject("John Lennon - Aspect Grid Dark Synastry", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1149
|
-
aspect_grid_dark_synastry_chart = KerykeionChartSVG(aspect_grid_dark_synastry_subject, "Synastry", second, theme="dark")
|
|
1150
|
-
aspect_grid_dark_synastry_chart.makeAspectGridOnlySVG()
|
|
1151
|
-
|
|
1152
|
-
# Synastry Chart With draw_transit_aspect_list table
|
|
1153
|
-
synastry_chart_with_table_list_subject = AstrologicalSubject("John Lennon - SCTWL", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1154
|
-
synastry_chart_with_table_list = KerykeionChartSVG(synastry_chart_with_table_list_subject, "Synastry", second, double_chart_aspect_grid_type="list", theme="dark")
|
|
1155
|
-
synastry_chart_with_table_list.makeSVG()
|
|
1156
|
-
|
|
1157
|
-
# Transit Chart With draw_transit_aspect_grid table
|
|
1158
|
-
transit_chart_with_table_grid_subject = AstrologicalSubject("John Lennon - TCWTG", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1159
|
-
transit_chart_with_table_grid = KerykeionChartSVG(transit_chart_with_table_grid_subject, "Transit", second, double_chart_aspect_grid_type="table", theme="dark")
|
|
1160
|
-
transit_chart_with_table_grid.makeSVG()
|
|
1161
|
-
|
|
1162
|
-
# Chines Language Chart
|
|
1163
|
-
chinese_subject = AstrologicalSubject("Hua Chenyu", 1990, 2, 7, 12, 0, "Hunan", "CN")
|
|
1164
|
-
chinese_chart = KerykeionChartSVG(chinese_subject, chart_language="CN")
|
|
1165
|
-
chinese_chart.makeSVG()
|
|
1166
|
-
|
|
1167
|
-
# French Language Chart
|
|
1168
|
-
french_subject = AstrologicalSubject("Jeanne Moreau", 1928, 1, 23, 10, 0, "Paris", "FR")
|
|
1169
|
-
french_chart = KerykeionChartSVG(french_subject, chart_language="FR")
|
|
1170
|
-
french_chart.makeSVG()
|
|
1171
|
-
|
|
1172
|
-
# Spanish Language Chart
|
|
1173
|
-
spanish_subject = AstrologicalSubject("Antonio Banderas", 1960, 8, 10, 12, 0, "Malaga", "ES")
|
|
1174
|
-
spanish_chart = KerykeionChartSVG(spanish_subject, chart_language="ES")
|
|
1175
|
-
spanish_chart.makeSVG()
|
|
1176
|
-
|
|
1177
|
-
# Portuguese Language Chart
|
|
1178
|
-
portuguese_subject = AstrologicalSubject("Cristiano Ronaldo", 1985, 2, 5, 5, 25, "Funchal", "PT")
|
|
1179
|
-
portuguese_chart = KerykeionChartSVG(portuguese_subject, chart_language="PT")
|
|
1180
|
-
portuguese_chart.makeSVG()
|
|
1181
|
-
|
|
1182
|
-
# Italian Language Chart
|
|
1183
|
-
italian_subject = AstrologicalSubject("Sophia Loren", 1934, 9, 20, 2, 0, "Rome", "IT")
|
|
1184
|
-
italian_chart = KerykeionChartSVG(italian_subject, chart_language="IT")
|
|
1185
|
-
italian_chart.makeSVG()
|
|
1186
|
-
|
|
1187
|
-
# Russian Language Chart
|
|
1188
|
-
russian_subject = AstrologicalSubject("Mikhail Bulgakov", 1891, 5, 15, 12, 0, "Kiev", "UA")
|
|
1189
|
-
russian_chart = KerykeionChartSVG(russian_subject, chart_language="RU")
|
|
1190
|
-
russian_chart.makeSVG()
|
|
1191
|
-
|
|
1192
|
-
# Turkish Language Chart
|
|
1193
|
-
turkish_subject = AstrologicalSubject("Mehmet Oz", 1960, 6, 11, 12, 0, "Istanbul", "TR")
|
|
1194
|
-
turkish_chart = KerykeionChartSVG(turkish_subject, chart_language="TR")
|
|
1195
|
-
turkish_chart.makeSVG()
|
|
1196
|
-
|
|
1197
|
-
# German Language Chart
|
|
1198
|
-
german_subject = AstrologicalSubject("Albert Einstein", 1879, 3, 14, 11, 30, "Ulm", "DE")
|
|
1199
|
-
german_chart = KerykeionChartSVG(german_subject, chart_language="DE")
|
|
1200
|
-
german_chart.makeSVG()
|
|
1201
|
-
|
|
1202
|
-
# Hindi Language Chart
|
|
1203
|
-
hindi_subject = AstrologicalSubject("Amitabh Bachchan", 1942, 10, 11, 4, 0, "Allahabad", "IN")
|
|
1204
|
-
hindi_chart = KerykeionChartSVG(hindi_subject, chart_language="HI")
|
|
1205
|
-
hindi_chart.makeSVG()
|
|
1206
|
-
|
|
1207
|
-
# Kanye West Natal Chart
|
|
1208
|
-
kanye_west_subject = AstrologicalSubject("Kanye", 1977, 6, 8, 8, 45, "Atlanta", "US")
|
|
1209
|
-
kanye_west_chart = KerykeionChartSVG(kanye_west_subject)
|
|
1210
|
-
kanye_west_chart.makeSVG()
|
|
1211
|
-
|
|
1212
|
-
# Composite Chart
|
|
1213
|
-
angelina = AstrologicalSubject("Angelina Jolie", 1975, 6, 4, 9, 9, "Los Angeles", "US", lng=-118.15, lat=34.03, tz_str="America/Los_Angeles")
|
|
1214
|
-
brad = AstrologicalSubject("Brad Pitt", 1963, 12, 18, 6, 31, "Shawnee", "US", lng=-96.56, lat=35.20, tz_str="America/Chicago")
|
|
1215
|
-
|
|
1216
|
-
composite_subject_factory = CompositeSubjectFactory(angelina, brad)
|
|
1217
|
-
composite_subject_model = composite_subject_factory.get_midpoint_composite_subject_model()
|
|
1218
|
-
composite_chart = KerykeionChartSVG(composite_subject_model, "Composite")
|
|
1219
|
-
composite_chart.makeSVG()
|