kerykeion 4.26.2__py3-none-any.whl → 5.0.0a1__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 +8 -5
- kerykeion/aspects/aspects_utils.py +14 -8
- kerykeion/aspects/natal_aspects.py +26 -17
- kerykeion/aspects/synastry_aspects.py +32 -15
- kerykeion/aspects/transits_time_range.py +2 -2
- kerykeion/astrological_subject_factory.py +1132 -0
- kerykeion/charts/charts_utils.py +583 -85
- kerykeion/charts/draw_planets.py +9 -8
- kerykeion/charts/draw_planets_v2.py +639 -0
- kerykeion/charts/kerykeion_chart_svg.py +1289 -592
- kerykeion/charts/templates/chart.xml +178 -79
- kerykeion/charts/templates/wheel_only.xml +13 -12
- kerykeion/charts/themes/classic.css +91 -76
- kerykeion/charts/themes/dark-high-contrast.css +129 -107
- kerykeion/charts/themes/dark.css +130 -107
- kerykeion/charts/themes/light.css +130 -103
- kerykeion/charts/themes/strawberry.css +143 -0
- kerykeion/composite_subject_factory.py +26 -43
- kerykeion/ephemeris_data.py +6 -10
- kerykeion/house_comparison/__init__.py +3 -0
- kerykeion/house_comparison/house_comparison_factory.py +70 -0
- kerykeion/house_comparison/house_comparison_models.py +38 -0
- kerykeion/house_comparison/house_comparison_utils.py +98 -0
- kerykeion/kr_types/chart_types.py +9 -3
- kerykeion/kr_types/kr_literals.py +34 -6
- kerykeion/kr_types/kr_models.py +122 -160
- kerykeion/kr_types/settings_models.py +107 -143
- kerykeion/planetary_return_factory.py +299 -0
- kerykeion/relationship_score/relationship_score.py +3 -3
- kerykeion/relationship_score/relationship_score_factory.py +9 -12
- kerykeion/report.py +4 -4
- kerykeion/settings/config_constants.py +35 -6
- kerykeion/settings/kerykeion_settings.py +1 -0
- kerykeion/settings/kr.config.json +1301 -1255
- kerykeion/settings/legacy/__init__.py +0 -0
- kerykeion/settings/legacy/legacy_celestial_points_settings.py +299 -0
- kerykeion/settings/legacy/legacy_chart_aspects_settings.py +71 -0
- kerykeion/settings/legacy/legacy_color_settings.py +42 -0
- kerykeion/transits_time_range.py +13 -9
- kerykeion/utilities.py +228 -31
- {kerykeion-4.26.2.dist-info → kerykeion-5.0.0a1.dist-info}/METADATA +3 -3
- kerykeion-5.0.0a1.dist-info/RECORD +56 -0
- {kerykeion-4.26.2.dist-info → kerykeion-5.0.0a1.dist-info}/WHEEL +1 -1
- kerykeion/astrological_subject.py +0 -841
- kerykeion-4.26.2.dist-info/LICENSE +0 -661
- kerykeion-4.26.2.dist-info/RECORD +0 -46
- /LICENSE → /kerykeion-5.0.0a1.dist-info/LICENSE +0 -0
- {kerykeion-4.26.2.dist-info → kerykeion-5.0.0a1.dist-info}/entry_points.txt +0 -0
|
@@ -6,17 +6,34 @@
|
|
|
6
6
|
|
|
7
7
|
import logging
|
|
8
8
|
import swisseph as swe
|
|
9
|
-
from typing import get_args
|
|
9
|
+
from typing import get_args, Union, Optional
|
|
10
10
|
|
|
11
11
|
from kerykeion.settings.kerykeion_settings import get_settings
|
|
12
12
|
from kerykeion.aspects.synastry_aspects import SynastryAspects
|
|
13
13
|
from kerykeion.aspects.natal_aspects import NatalAspects
|
|
14
|
-
from kerykeion.
|
|
15
|
-
from kerykeion.kr_types import
|
|
14
|
+
from kerykeion.house_comparison.house_comparison_factory import HouseComparisonFactory
|
|
15
|
+
from kerykeion.kr_types import (
|
|
16
|
+
KerykeionException,
|
|
17
|
+
ChartType,
|
|
18
|
+
Sign,
|
|
19
|
+
ActiveAspect,
|
|
20
|
+
)
|
|
16
21
|
from kerykeion.kr_types import ChartTemplateDictionary
|
|
17
|
-
from kerykeion.kr_types.kr_models import
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
from kerykeion.kr_types.kr_models import (
|
|
23
|
+
AstrologicalSubjectModel,
|
|
24
|
+
CompositeSubjectModel,
|
|
25
|
+
PlanetReturnModel,
|
|
26
|
+
)
|
|
27
|
+
from kerykeion.kr_types.settings_models import (
|
|
28
|
+
KerykeionSettingsCelestialPointModel,
|
|
29
|
+
KerykeionSettingsModel,
|
|
30
|
+
)
|
|
31
|
+
from kerykeion.kr_types.kr_literals import (
|
|
32
|
+
KerykeionChartTheme,
|
|
33
|
+
KerykeionChartLanguage,
|
|
34
|
+
AstrologicalPoint,
|
|
35
|
+
)
|
|
36
|
+
from kerykeion.utilities import find_common_active_points
|
|
20
37
|
from kerykeion.charts.charts_utils import (
|
|
21
38
|
draw_zodiac_slice,
|
|
22
39
|
convert_latitude_coordinate_to_string,
|
|
@@ -26,25 +43,37 @@ from kerykeion.charts.charts_utils import (
|
|
|
26
43
|
draw_degree_ring,
|
|
27
44
|
draw_transit_ring,
|
|
28
45
|
draw_first_circle,
|
|
46
|
+
draw_house_comparison_grid,
|
|
29
47
|
draw_second_circle,
|
|
30
48
|
draw_third_circle,
|
|
31
49
|
draw_aspect_grid,
|
|
32
50
|
draw_houses_cusps_and_text_number,
|
|
33
51
|
draw_transit_aspect_list,
|
|
34
52
|
draw_transit_aspect_grid,
|
|
35
|
-
|
|
53
|
+
draw_single_house_comparison_grid,
|
|
54
|
+
makeLunarPhase,
|
|
36
55
|
draw_house_grid,
|
|
37
56
|
draw_planet_grid,
|
|
57
|
+
format_location_string,
|
|
58
|
+
format_datetime_with_timezone,
|
|
59
|
+
calculate_element_points,
|
|
60
|
+
calculate_synastry_element_points,
|
|
61
|
+
calculate_quality_points,
|
|
62
|
+
calculate_synastry_quality_points
|
|
38
63
|
)
|
|
39
|
-
from kerykeion.charts.
|
|
64
|
+
from kerykeion.charts.draw_planets_v2 import draw_planets_v2 as draw_planets
|
|
40
65
|
from kerykeion.utilities import get_houses_list, inline_css_variables_in_svg
|
|
41
|
-
from kerykeion.settings.config_constants import
|
|
66
|
+
from kerykeion.settings.config_constants import DEFAULT_ACTIVE_ASPECTS
|
|
67
|
+
from kerykeion.settings.legacy.legacy_color_settings import DEFAULT_CHART_COLORS
|
|
68
|
+
from kerykeion.settings.legacy.legacy_celestial_points_settings import DEFAULT_CELESTIAL_POINTS_SETTINGS
|
|
69
|
+
from kerykeion.settings.legacy.legacy_chart_aspects_settings import DEFAULT_CHART_ASPECTS_SETTINGS
|
|
42
70
|
from pathlib import Path
|
|
43
71
|
from scour.scour import scourString
|
|
44
72
|
from string import Template
|
|
45
73
|
from typing import Union, List, Literal
|
|
46
74
|
from datetime import datetime
|
|
47
75
|
|
|
76
|
+
|
|
48
77
|
class KerykeionChartSVG:
|
|
49
78
|
"""
|
|
50
79
|
KerykeionChartSVG generates astrological chart visualizations as SVG files.
|
|
@@ -77,7 +106,7 @@ class KerykeionChartSVG:
|
|
|
77
106
|
Specifies rendering style for double-chart aspect grids. Defaults to 'list'.
|
|
78
107
|
chart_language (KerykeionChartLanguage, optional):
|
|
79
108
|
Language code for chart labels. Defaults to 'EN'.
|
|
80
|
-
active_points (list[
|
|
109
|
+
active_points (list[AstrologicalPoint], optional):
|
|
81
110
|
List of celestial points and angles to include. Defaults to DEFAULT_ACTIVE_POINTS.
|
|
82
111
|
Example:
|
|
83
112
|
["Sun", "Moon", "Mercury", "Venus"]
|
|
@@ -120,19 +149,21 @@ class KerykeionChartSVG:
|
|
|
120
149
|
"""
|
|
121
150
|
|
|
122
151
|
# 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
152
|
|
|
127
153
|
_DEFAULT_HEIGHT = 550
|
|
128
154
|
_DEFAULT_FULL_WIDTH = 1200
|
|
129
|
-
_DEFAULT_NATAL_WIDTH =
|
|
130
|
-
_DEFAULT_FULL_WIDTH_WITH_TABLE =
|
|
131
|
-
|
|
155
|
+
_DEFAULT_NATAL_WIDTH = 870
|
|
156
|
+
_DEFAULT_FULL_WIDTH_WITH_TABLE = 1200
|
|
157
|
+
_DEFAULT_ULTRA_WIDE_WIDTH = 1270
|
|
158
|
+
|
|
159
|
+
_BASIC_CHART_VIEWBOX = f"0 0 {_DEFAULT_NATAL_WIDTH} {_DEFAULT_HEIGHT}"
|
|
160
|
+
_WIDE_CHART_VIEWBOX = f"0 0 {_DEFAULT_FULL_WIDTH} 546.0"
|
|
161
|
+
_ULTRA_WIDE_CHART_VIEWBOX = f"0 0 {_DEFAULT_ULTRA_WIDE_WIDTH} 546.0"
|
|
162
|
+
_TRANSIT_CHART_WITH_TABLE_VIWBOX = f"0 0 {_DEFAULT_FULL_WIDTH_WITH_TABLE} 546.0"
|
|
132
163
|
|
|
133
164
|
# Set at init
|
|
134
|
-
first_obj: Union[
|
|
135
|
-
second_obj: Union[
|
|
165
|
+
first_obj: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel]
|
|
166
|
+
second_obj: Union[AstrologicalSubjectModel, PlanetReturnModel, None]
|
|
136
167
|
chart_type: ChartType
|
|
137
168
|
new_output_directory: Union[Path, None]
|
|
138
169
|
new_settings_file: Union[Path, None, KerykeionSettingsModel, dict]
|
|
@@ -141,7 +172,7 @@ class KerykeionChartSVG:
|
|
|
141
172
|
theme: Union[KerykeionChartTheme, None]
|
|
142
173
|
double_chart_aspect_grid_type: Literal["list", "table"]
|
|
143
174
|
chart_language: KerykeionChartLanguage
|
|
144
|
-
active_points: List[
|
|
175
|
+
active_points: List[AstrologicalPoint]
|
|
145
176
|
active_aspects: List[ActiveAspect]
|
|
146
177
|
|
|
147
178
|
# Internal properties
|
|
@@ -157,7 +188,6 @@ class KerykeionChartSVG:
|
|
|
157
188
|
chart_colors_settings: dict
|
|
158
189
|
planets_settings: dict
|
|
159
190
|
aspects_settings: dict
|
|
160
|
-
user: Union[AstrologicalSubject, AstrologicalSubjectModel, CompositeSubjectModel]
|
|
161
191
|
available_planets_setting: List[KerykeionSettingsCelestialPointModel]
|
|
162
192
|
height: float
|
|
163
193
|
location: str
|
|
@@ -167,26 +197,30 @@ class KerykeionChartSVG:
|
|
|
167
197
|
|
|
168
198
|
def __init__(
|
|
169
199
|
self,
|
|
170
|
-
first_obj: Union[
|
|
200
|
+
first_obj: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
|
|
171
201
|
chart_type: ChartType = "Natal",
|
|
172
|
-
second_obj: Union[
|
|
202
|
+
second_obj: Union[AstrologicalSubjectModel, PlanetReturnModel, None] = None,
|
|
173
203
|
new_output_directory: Union[str, None] = None,
|
|
174
204
|
new_settings_file: Union[Path, None, KerykeionSettingsModel, dict] = None,
|
|
175
205
|
theme: Union[KerykeionChartTheme, None] = "classic",
|
|
176
206
|
double_chart_aspect_grid_type: Literal["list", "table"] = "list",
|
|
177
207
|
chart_language: KerykeionChartLanguage = "EN",
|
|
178
|
-
active_points:
|
|
179
|
-
|
|
208
|
+
active_points: Optional[list[AstrologicalPoint]] = None,
|
|
209
|
+
active_aspects: list[ActiveAspect]= DEFAULT_ACTIVE_ASPECTS,
|
|
210
|
+
*,
|
|
211
|
+
colors_settings: dict = DEFAULT_CHART_COLORS,
|
|
212
|
+
celestial_points_settings: list[dict] = DEFAULT_CELESTIAL_POINTS_SETTINGS,
|
|
213
|
+
aspects_settings: list[dict] = DEFAULT_CHART_ASPECTS_SETTINGS,
|
|
180
214
|
):
|
|
181
215
|
"""
|
|
182
216
|
Initialize the chart generator with subject data and configuration options.
|
|
183
217
|
|
|
184
218
|
Args:
|
|
185
|
-
first_obj (
|
|
219
|
+
first_obj (AstrologicalSubjectModel, or CompositeSubjectModel):
|
|
186
220
|
Primary astrological subject instance.
|
|
187
221
|
chart_type (ChartType, optional):
|
|
188
222
|
Type of chart to generate (e.g., 'Natal', 'Transit').
|
|
189
|
-
second_obj (AstrologicalSubject
|
|
223
|
+
second_obj (AstrologicalSubject, optional):
|
|
190
224
|
Secondary subject for Transit or Synastry charts.
|
|
191
225
|
new_output_directory (str or Path, optional):
|
|
192
226
|
Base directory to save generated SVG files.
|
|
@@ -198,138 +232,341 @@ class KerykeionChartSVG:
|
|
|
198
232
|
Layout style for double-chart aspect grids ('list' or 'table').
|
|
199
233
|
chart_language (KerykeionChartLanguage, optional):
|
|
200
234
|
Language code for chart labels (e.g., 'EN', 'IT').
|
|
201
|
-
active_points (List[
|
|
235
|
+
active_points (List[AstrologicalPoint], optional):
|
|
202
236
|
Celestial points to include in the chart visualization.
|
|
203
237
|
active_aspects (List[ActiveAspect], optional):
|
|
204
238
|
Aspects to calculate, each defined by name and orb.
|
|
205
239
|
"""
|
|
240
|
+
# --------------------
|
|
241
|
+
# COMMON INITIALIZATION
|
|
242
|
+
# --------------------
|
|
206
243
|
home_directory = Path.home()
|
|
207
244
|
self.new_settings_file = new_settings_file
|
|
208
245
|
self.chart_language = chart_language
|
|
209
246
|
self.active_points = active_points
|
|
210
247
|
self.active_aspects = active_aspects
|
|
248
|
+
self.chart_type = chart_type
|
|
249
|
+
self.double_chart_aspect_grid_type = double_chart_aspect_grid_type
|
|
250
|
+
self.chart_colors_settings = colors_settings
|
|
251
|
+
self.planets_settings = celestial_points_settings
|
|
252
|
+
self.aspects_settings = aspects_settings
|
|
211
253
|
|
|
254
|
+
if not active_points:
|
|
255
|
+
active_points = first_obj.active_points
|
|
256
|
+
else:
|
|
257
|
+
active_points = find_common_active_points(
|
|
258
|
+
active_points,
|
|
259
|
+
first_obj.active_points
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
if second_obj:
|
|
263
|
+
active_points = find_common_active_points(
|
|
264
|
+
active_points,
|
|
265
|
+
second_obj.active_points
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# Set output directory
|
|
212
269
|
if new_output_directory:
|
|
213
270
|
self.output_directory = Path(new_output_directory)
|
|
214
271
|
else:
|
|
215
272
|
self.output_directory = home_directory
|
|
216
273
|
|
|
274
|
+
# Load settings
|
|
217
275
|
self.parse_json_settings(new_settings_file)
|
|
218
|
-
self.chart_type = chart_type
|
|
219
276
|
|
|
220
|
-
#
|
|
221
|
-
self.
|
|
277
|
+
# Primary subject
|
|
278
|
+
self.first_obj = first_obj
|
|
222
279
|
|
|
280
|
+
# Default radius for all charts
|
|
281
|
+
self.main_radius = 240
|
|
282
|
+
|
|
283
|
+
# Configure available planets
|
|
223
284
|
self.available_planets_setting = []
|
|
224
285
|
for body in self.planets_settings:
|
|
225
|
-
if body["name"]
|
|
226
|
-
continue
|
|
227
|
-
else:
|
|
286
|
+
if body["name"] in active_points:
|
|
228
287
|
body["is_active"] = True
|
|
288
|
+
self.available_planets_setting.append(body)
|
|
229
289
|
|
|
230
|
-
|
|
290
|
+
# Set available celestial points
|
|
291
|
+
available_celestial_points_names = [body["name"].lower() for body in self.available_planets_setting]
|
|
292
|
+
self.available_kerykeion_celestial_points = []
|
|
293
|
+
for body in available_celestial_points_names:
|
|
294
|
+
self.available_kerykeion_celestial_points.append(self.first_obj.get(body))
|
|
231
295
|
|
|
232
|
-
#
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
available_celestial_points_names.append(body["name"].lower())
|
|
296
|
+
# ------------------------
|
|
297
|
+
# CHART TYPE SPECIFIC SETUP
|
|
298
|
+
# ------------------------
|
|
236
299
|
|
|
237
|
-
self.
|
|
238
|
-
|
|
239
|
-
self.available_kerykeion_celestial_points.append(self.user.get(body))
|
|
300
|
+
if self.chart_type in ["Natal", "ExternalNatal"]:
|
|
301
|
+
# --- NATAL / EXTERNAL NATAL CHART SETUP ---
|
|
240
302
|
|
|
241
|
-
|
|
242
|
-
|
|
303
|
+
# Validate Subject
|
|
304
|
+
if not isinstance(self.first_obj, AstrologicalSubjectModel):
|
|
305
|
+
raise KerykeionException("First object must be an AstrologicalSubjectModel or AstrologicalSubject instance.")
|
|
306
|
+
|
|
307
|
+
# Calculate aspects
|
|
243
308
|
natal_aspects_instance = NatalAspects(
|
|
244
|
-
self.
|
|
309
|
+
self.first_obj,
|
|
310
|
+
new_settings_file=self.new_settings_file,
|
|
245
311
|
active_points=active_points,
|
|
246
312
|
active_aspects=active_aspects,
|
|
247
313
|
)
|
|
248
314
|
self.aspects_list = natal_aspects_instance.relevant_aspects
|
|
249
315
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
# Kerykeion instance
|
|
255
|
-
self.t_user = second_obj
|
|
316
|
+
# Screen size
|
|
317
|
+
self.height = self._DEFAULT_HEIGHT
|
|
318
|
+
self.width = self._DEFAULT_NATAL_WIDTH
|
|
256
319
|
|
|
257
|
-
#
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
self.user,
|
|
262
|
-
new_settings_file=self.new_settings_file,
|
|
263
|
-
active_points=active_points,
|
|
264
|
-
active_aspects=active_aspects,
|
|
265
|
-
)
|
|
320
|
+
# Location and coordinates
|
|
321
|
+
self.location = self.first_obj.city
|
|
322
|
+
self.geolat = self.first_obj.lat
|
|
323
|
+
self.geolon = self.first_obj.lng
|
|
266
324
|
|
|
325
|
+
# Circle radii
|
|
326
|
+
if self.chart_type == "ExternalNatal":
|
|
327
|
+
self.first_circle_radius = 56
|
|
328
|
+
self.second_circle_radius = 92
|
|
329
|
+
self.third_circle_radius = 112
|
|
267
330
|
else:
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
331
|
+
self.first_circle_radius = 0
|
|
332
|
+
self.second_circle_radius = 36
|
|
333
|
+
self.third_circle_radius = 120
|
|
334
|
+
|
|
335
|
+
elif self.chart_type == "Composite":
|
|
336
|
+
# --- COMPOSITE CHART SETUP ---
|
|
337
|
+
|
|
338
|
+
# Validate Subject
|
|
339
|
+
if not isinstance(self.first_obj, CompositeSubjectModel):
|
|
340
|
+
raise KerykeionException("First object must be a CompositeSubjectModel instance.")
|
|
341
|
+
|
|
342
|
+
# Calculate aspects
|
|
343
|
+
self.aspects_list = NatalAspects(self.first_obj, new_settings_file=self.new_settings_file, active_points=active_points).relevant_aspects
|
|
344
|
+
|
|
345
|
+
# Screen size
|
|
346
|
+
self.height = self._DEFAULT_HEIGHT
|
|
347
|
+
self.width = self._DEFAULT_NATAL_WIDTH
|
|
275
348
|
|
|
349
|
+
# Location and coordinates (average of both subjects)
|
|
350
|
+
self.location = ""
|
|
351
|
+
self.geolat = (self.first_obj.first_subject.lat + self.first_obj.second_subject.lat) / 2
|
|
352
|
+
self.geolon = (self.first_obj.first_subject.lng + self.first_obj.second_subject.lng) / 2
|
|
353
|
+
|
|
354
|
+
# Circle radii
|
|
355
|
+
self.first_circle_radius = 0
|
|
356
|
+
self.second_circle_radius = 36
|
|
357
|
+
self.third_circle_radius = 120
|
|
358
|
+
|
|
359
|
+
elif self.chart_type == "Transit":
|
|
360
|
+
# --- TRANSIT CHART SETUP ---
|
|
361
|
+
|
|
362
|
+
# Validate Subjects
|
|
363
|
+
if not second_obj:
|
|
364
|
+
raise KerykeionException("Second object is required for Transit charts.")
|
|
365
|
+
if not isinstance(self.first_obj, AstrologicalSubjectModel):
|
|
366
|
+
raise KerykeionException("First object must be an AstrologicalSubjectModel or AstrologicalSubject instance.")
|
|
367
|
+
if not isinstance(second_obj, AstrologicalSubjectModel):
|
|
368
|
+
raise KerykeionException("Second object must be an AstrologicalSubjectModel or AstrologicalSubject instance.")
|
|
369
|
+
|
|
370
|
+
# Secondary subject setup
|
|
371
|
+
self.second_obj = second_obj
|
|
372
|
+
|
|
373
|
+
# Calculate aspects (transit to natal)
|
|
374
|
+
synastry_aspects_instance = SynastryAspects(
|
|
375
|
+
self.first_obj,
|
|
376
|
+
self.second_obj,
|
|
377
|
+
new_settings_file=self.new_settings_file,
|
|
378
|
+
active_points=active_points,
|
|
379
|
+
active_aspects=active_aspects,
|
|
380
|
+
)
|
|
276
381
|
self.aspects_list = synastry_aspects_instance.relevant_aspects
|
|
277
382
|
|
|
383
|
+
# Secondary subject available points
|
|
278
384
|
self.t_available_kerykeion_celestial_points = []
|
|
279
385
|
for body in available_celestial_points_names:
|
|
280
|
-
self.t_available_kerykeion_celestial_points.append(self.
|
|
386
|
+
self.t_available_kerykeion_celestial_points.append(self.second_obj.get(body))
|
|
281
387
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
388
|
+
# Screen size
|
|
389
|
+
self.height = self._DEFAULT_HEIGHT
|
|
390
|
+
if self.double_chart_aspect_grid_type == "table":
|
|
391
|
+
self.width = self._DEFAULT_FULL_WIDTH_WITH_TABLE
|
|
392
|
+
else:
|
|
393
|
+
self.width = self._DEFAULT_FULL_WIDTH
|
|
394
|
+
|
|
395
|
+
# Location and coordinates (from transit subject)
|
|
396
|
+
self.location = self.second_obj.city
|
|
397
|
+
self.geolat = self.second_obj.lat
|
|
398
|
+
self.geolon = self.second_obj.lng
|
|
399
|
+
self.t_name = self.language_settings["transit_name"]
|
|
285
400
|
|
|
286
|
-
|
|
401
|
+
# Circle radii
|
|
402
|
+
self.first_circle_radius = 0
|
|
403
|
+
self.second_circle_radius = 36
|
|
404
|
+
self.third_circle_radius = 120
|
|
287
405
|
|
|
288
|
-
|
|
289
|
-
|
|
406
|
+
elif self.chart_type == "Synastry":
|
|
407
|
+
# --- SYNASTRY CHART SETUP ---
|
|
408
|
+
|
|
409
|
+
# Validate Subjects
|
|
410
|
+
if not second_obj:
|
|
411
|
+
raise KerykeionException("Second object is required for Synastry charts.")
|
|
412
|
+
if not isinstance(self.first_obj, AstrologicalSubjectModel):
|
|
413
|
+
raise KerykeionException("First object must be an AstrologicalSubjectModel or AstrologicalSubject instance.")
|
|
414
|
+
if not isinstance(second_obj, AstrologicalSubjectModel):
|
|
415
|
+
raise KerykeionException("Second object must be an AstrologicalSubjectModel or AstrologicalSubject instance.")
|
|
416
|
+
|
|
417
|
+
# Secondary subject setup
|
|
418
|
+
self.second_obj = second_obj
|
|
419
|
+
|
|
420
|
+
# Calculate aspects (natal to partner)
|
|
421
|
+
synastry_aspects_instance = SynastryAspects(
|
|
422
|
+
self.first_obj,
|
|
423
|
+
self.second_obj,
|
|
424
|
+
new_settings_file=self.new_settings_file,
|
|
425
|
+
active_points=active_points,
|
|
426
|
+
active_aspects=active_aspects,
|
|
427
|
+
)
|
|
428
|
+
self.aspects_list = synastry_aspects_instance.relevant_aspects
|
|
290
429
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
430
|
+
# Secondary subject available points
|
|
431
|
+
self.t_available_kerykeion_celestial_points = []
|
|
432
|
+
for body in available_celestial_points_names:
|
|
433
|
+
self.t_available_kerykeion_celestial_points.append(self.second_obj.get(body))
|
|
434
|
+
|
|
435
|
+
# Screen size
|
|
436
|
+
self.height = self._DEFAULT_HEIGHT
|
|
294
437
|
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
438
|
|
|
300
|
-
|
|
301
|
-
self.location = self.
|
|
302
|
-
self.geolat = self.
|
|
303
|
-
self.geolon =
|
|
439
|
+
# Location and coordinates (from primary subject)
|
|
440
|
+
self.location = self.first_obj.city
|
|
441
|
+
self.geolat = self.first_obj.lat
|
|
442
|
+
self.geolon = self.first_obj.lng
|
|
304
443
|
|
|
305
|
-
|
|
306
|
-
self.
|
|
307
|
-
self.
|
|
308
|
-
self.
|
|
444
|
+
# Circle radii
|
|
445
|
+
self.first_circle_radius = 0
|
|
446
|
+
self.second_circle_radius = 36
|
|
447
|
+
self.third_circle_radius = 120
|
|
309
448
|
|
|
310
|
-
elif self.chart_type
|
|
311
|
-
|
|
312
|
-
self.geolat = self.t_user.lat
|
|
313
|
-
self.geolon = self.t_user.lng
|
|
314
|
-
self.t_name = self.language_settings["transit_name"]
|
|
449
|
+
elif self.chart_type == "Return":
|
|
450
|
+
# --- RETURN CHART SETUP ---
|
|
315
451
|
|
|
316
|
-
|
|
317
|
-
|
|
452
|
+
# Validate Subjects
|
|
453
|
+
if not second_obj:
|
|
454
|
+
raise KerykeionException("Second object is required for Return charts.")
|
|
455
|
+
if not isinstance(self.first_obj, AstrologicalSubjectModel):
|
|
456
|
+
raise KerykeionException("First object must be an AstrologicalSubjectModel or AstrologicalSubject instance.")
|
|
457
|
+
if not isinstance(second_obj, PlanetReturnModel):
|
|
458
|
+
raise KerykeionException("Second object must be a PlanetReturnModel instance.")
|
|
459
|
+
|
|
460
|
+
# Secondary subject setup
|
|
461
|
+
self.second_obj = second_obj
|
|
462
|
+
|
|
463
|
+
# Calculate aspects (natal to return)
|
|
464
|
+
synastry_aspects_instance = SynastryAspects(
|
|
465
|
+
self.first_obj,
|
|
466
|
+
self.second_obj,
|
|
467
|
+
new_settings_file=self.new_settings_file,
|
|
468
|
+
active_points=active_points,
|
|
469
|
+
active_aspects=active_aspects,
|
|
470
|
+
)
|
|
471
|
+
self.aspects_list = synastry_aspects_instance.relevant_aspects
|
|
472
|
+
|
|
473
|
+
# Secondary subject available points
|
|
474
|
+
self.t_available_kerykeion_celestial_points = []
|
|
475
|
+
for body in available_celestial_points_names:
|
|
476
|
+
self.t_available_kerykeion_celestial_points.append(self.second_obj.get(body))
|
|
477
|
+
|
|
478
|
+
# Screen size
|
|
479
|
+
self.height = self._DEFAULT_HEIGHT
|
|
480
|
+
self.width = self._DEFAULT_ULTRA_WIDE_WIDTH
|
|
481
|
+
|
|
482
|
+
# Location and coordinates (from natal subject)
|
|
483
|
+
self.location = self.first_obj.city
|
|
484
|
+
self.geolat = self.first_obj.lat
|
|
485
|
+
self.geolon = self.first_obj.lng
|
|
486
|
+
|
|
487
|
+
# Circle radii
|
|
488
|
+
self.first_circle_radius = 0
|
|
489
|
+
self.second_circle_radius = 36
|
|
490
|
+
self.third_circle_radius = 120
|
|
491
|
+
|
|
492
|
+
elif self.chart_type == "SingleWheelReturn":
|
|
493
|
+
# --- NATAL / EXTERNAL NATAL CHART SETUP ---
|
|
494
|
+
|
|
495
|
+
# Validate Subject
|
|
496
|
+
if not isinstance(self.first_obj, PlanetReturnModel):
|
|
497
|
+
raise KerykeionException("First object must be an AstrologicalSubjectModel or AstrologicalSubject instance.")
|
|
498
|
+
|
|
499
|
+
# Calculate aspects
|
|
500
|
+
natal_aspects_instance = NatalAspects(
|
|
501
|
+
self.first_obj,
|
|
502
|
+
new_settings_file=self.new_settings_file,
|
|
503
|
+
active_points=active_points,
|
|
504
|
+
active_aspects=active_aspects,
|
|
505
|
+
)
|
|
506
|
+
self.aspects_list = natal_aspects_instance.relevant_aspects
|
|
507
|
+
|
|
508
|
+
# Screen size
|
|
509
|
+
self.height = self._DEFAULT_HEIGHT
|
|
510
|
+
self.width = self._DEFAULT_NATAL_WIDTH
|
|
511
|
+
|
|
512
|
+
# Location and coordinates
|
|
513
|
+
self.location = self.first_obj.city
|
|
514
|
+
self.geolat = self.first_obj.lat
|
|
515
|
+
self.geolon = self.first_obj.lng
|
|
516
|
+
|
|
517
|
+
# Circle radii
|
|
518
|
+
if self.chart_type == "ExternalNatal":
|
|
519
|
+
self.first_circle_radius = 56
|
|
520
|
+
self.second_circle_radius = 92
|
|
521
|
+
self.third_circle_radius = 112
|
|
522
|
+
else:
|
|
523
|
+
self.first_circle_radius = 0
|
|
524
|
+
self.second_circle_radius = 36
|
|
525
|
+
self.third_circle_radius = 120
|
|
318
526
|
|
|
319
|
-
#
|
|
320
|
-
|
|
321
|
-
|
|
527
|
+
# --------------------
|
|
528
|
+
# FINAL COMMON SETUP
|
|
529
|
+
# --------------------
|
|
530
|
+
|
|
531
|
+
# Calculate element points
|
|
532
|
+
celestial_points_names = [body["name"].lower() for body in self.available_planets_setting]
|
|
533
|
+
if self.chart_type == "Synastry":
|
|
534
|
+
element_totals = calculate_synastry_element_points(
|
|
535
|
+
self.available_planets_setting,
|
|
536
|
+
celestial_points_names,
|
|
537
|
+
self.first_obj,
|
|
538
|
+
self.second_obj,
|
|
539
|
+
)
|
|
322
540
|
else:
|
|
323
|
-
|
|
541
|
+
element_totals = calculate_element_points(
|
|
542
|
+
self.available_planets_setting,
|
|
543
|
+
celestial_points_names,
|
|
544
|
+
self.first_obj,
|
|
545
|
+
)
|
|
324
546
|
|
|
325
|
-
|
|
326
|
-
self.
|
|
327
|
-
self.
|
|
328
|
-
self.
|
|
329
|
-
|
|
547
|
+
self.fire = element_totals["fire"]
|
|
548
|
+
self.earth = element_totals["earth"]
|
|
549
|
+
self.air = element_totals["air"]
|
|
550
|
+
self.water = element_totals["water"]
|
|
551
|
+
|
|
552
|
+
# Calculate qualities points
|
|
553
|
+
if self.chart_type == "Synastry":
|
|
554
|
+
qualities_totals = calculate_synastry_quality_points(
|
|
555
|
+
self.available_planets_setting,
|
|
556
|
+
celestial_points_names,
|
|
557
|
+
self.first_obj,
|
|
558
|
+
self.second_obj,
|
|
559
|
+
)
|
|
560
|
+
else:
|
|
561
|
+
qualities_totals = calculate_quality_points(
|
|
562
|
+
self.available_planets_setting,
|
|
563
|
+
celestial_points_names,
|
|
564
|
+
self.first_obj,
|
|
565
|
+
)
|
|
330
566
|
|
|
331
|
-
|
|
332
|
-
self.
|
|
567
|
+
self.cardinal = qualities_totals["cardinal"]
|
|
568
|
+
self.fixed = qualities_totals["fixed"]
|
|
569
|
+
self.mutable = qualities_totals["mutable"]
|
|
333
570
|
|
|
334
571
|
# Set up theme
|
|
335
572
|
if theme not in get_args(KerykeionChartTheme) and theme is not None:
|
|
@@ -361,7 +598,7 @@ class KerykeionChartSVG:
|
|
|
361
598
|
dir_path (Path): Target directory for SVG output.
|
|
362
599
|
"""
|
|
363
600
|
self.output_directory = dir_path
|
|
364
|
-
logging.info(f"Output
|
|
601
|
+
logging.info(f"Output directory set to: {self.output_directory}")
|
|
365
602
|
|
|
366
603
|
def parse_json_settings(self, settings_file_or_dict: Union[Path, dict, KerykeionSettingsModel, None]) -> None:
|
|
367
604
|
"""
|
|
@@ -374,9 +611,6 @@ class KerykeionChartSVG:
|
|
|
374
611
|
settings = get_settings(settings_file_or_dict)
|
|
375
612
|
|
|
376
613
|
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
614
|
|
|
381
615
|
def _draw_zodiac_circle_slices(self, r):
|
|
382
616
|
"""
|
|
@@ -394,7 +628,7 @@ class KerykeionChartSVG:
|
|
|
394
628
|
output += draw_zodiac_slice(
|
|
395
629
|
c1=self.first_circle_radius,
|
|
396
630
|
chart_type=self.chart_type,
|
|
397
|
-
seventh_house_degree_ut=self.
|
|
631
|
+
seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
398
632
|
num=i,
|
|
399
633
|
r=r,
|
|
400
634
|
style=f'fill:{self.chart_colors_settings[f"zodiac_bg_{i}"]}; fill-opacity: 0.5;',
|
|
@@ -403,65 +637,6 @@ class KerykeionChartSVG:
|
|
|
403
637
|
|
|
404
638
|
return output
|
|
405
639
|
|
|
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
640
|
def _draw_all_aspects_lines(self, r, ar):
|
|
466
641
|
"""
|
|
467
642
|
Render SVG lines for all aspects in the chart.
|
|
@@ -483,7 +658,7 @@ class KerykeionChartSVG:
|
|
|
483
658
|
ar=ar,
|
|
484
659
|
aspect=aspect,
|
|
485
660
|
color=aspect_color,
|
|
486
|
-
seventh_house_degree_ut=self.
|
|
661
|
+
seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
487
662
|
)
|
|
488
663
|
return out
|
|
489
664
|
|
|
@@ -508,7 +683,7 @@ class KerykeionChartSVG:
|
|
|
508
683
|
ar=ar,
|
|
509
684
|
aspect=aspect,
|
|
510
685
|
color=aspect_color,
|
|
511
|
-
seventh_house_degree_ut=self.
|
|
686
|
+
seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
512
687
|
)
|
|
513
688
|
return out
|
|
514
689
|
|
|
@@ -525,168 +700,424 @@ class KerykeionChartSVG:
|
|
|
525
700
|
# Initialize template dictionary
|
|
526
701
|
template_dict: dict = {}
|
|
527
702
|
|
|
528
|
-
#
|
|
529
|
-
|
|
703
|
+
# -------------------------------------#
|
|
704
|
+
# COMMON SETTINGS FOR ALL CHART TYPES #
|
|
705
|
+
# -------------------------------------#
|
|
530
706
|
|
|
531
|
-
# Set
|
|
707
|
+
# Set the color style tag and basic dimensions
|
|
708
|
+
template_dict["color_style_tag"] = self.color_style_tag
|
|
532
709
|
template_dict["chart_height"] = self.height
|
|
533
710
|
template_dict["chart_width"] = self.width
|
|
534
711
|
|
|
535
|
-
# Set
|
|
536
|
-
|
|
537
|
-
|
|
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
|
|
712
|
+
# Set paper colors
|
|
713
|
+
template_dict["paper_color_0"] = self.chart_colors_settings["paper_0"]
|
|
714
|
+
template_dict["paper_color_1"] = self.chart_colors_settings["paper_1"]
|
|
542
715
|
|
|
543
|
-
#
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
template_dict["
|
|
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)
|
|
716
|
+
# Set planet colors
|
|
717
|
+
for planet in self.planets_settings:
|
|
718
|
+
planet_id = planet["id"]
|
|
719
|
+
template_dict[f"planets_color_{planet_id}"] = planet["color"]
|
|
550
720
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
title = self.language_settings.get("couple_aspects", "Couple Aspects")
|
|
555
|
-
else:
|
|
556
|
-
title = self.language_settings.get("transit_aspects", "Transit Aspects")
|
|
721
|
+
# Set zodiac colors
|
|
722
|
+
for i in range(12):
|
|
723
|
+
template_dict[f"zodiac_color_{i}"] = self.chart_colors_settings[f"zodiac_icon_{i}"]
|
|
557
724
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
725
|
+
# Set orb colors
|
|
726
|
+
for aspect in self.aspects_settings:
|
|
727
|
+
template_dict[f"orb_color_{aspect['degree']}"] = aspect["color"]
|
|
561
728
|
|
|
562
|
-
|
|
563
|
-
|
|
729
|
+
# Draw zodiac circle slices
|
|
730
|
+
template_dict["makeZodiac"] = self._draw_zodiac_circle_slices(self.main_radius)
|
|
731
|
+
|
|
732
|
+
# Calculate element percentages
|
|
733
|
+
total_elements = self.fire + self.water + self.earth + self.air
|
|
734
|
+
fire_percentage = int(round(100 * self.fire / total_elements))
|
|
735
|
+
earth_percentage = int(round(100 * self.earth / total_elements))
|
|
736
|
+
air_percentage = int(round(100 * self.air / total_elements))
|
|
737
|
+
water_percentage = int(round(100 * self.water / total_elements))
|
|
738
|
+
|
|
739
|
+
# Element Percentages
|
|
740
|
+
template_dict["elements_string"] = f"{self.language_settings.get('elements', 'Elements')}:"
|
|
741
|
+
template_dict["fire_string"] = f"{self.language_settings['fire']} {fire_percentage}%"
|
|
742
|
+
template_dict["earth_string"] = f"{self.language_settings['earth']} {earth_percentage}%"
|
|
743
|
+
template_dict["air_string"] = f"{self.language_settings['air']} {air_percentage}%"
|
|
744
|
+
template_dict["water_string"] = f"{self.language_settings['water']} {water_percentage}%"
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
# Qualities Percentages
|
|
748
|
+
total_qualities = self.cardinal + self.fixed + self.mutable
|
|
749
|
+
cardinal_percentage = int(round(100 * self.cardinal / total_qualities))
|
|
750
|
+
fixed_percentage = int(round(100 * self.fixed / total_qualities))
|
|
751
|
+
mutable_percentage = int(round(100 * self.mutable / total_qualities))
|
|
752
|
+
|
|
753
|
+
template_dict["qualities_string"] = f"{self.language_settings.get('qualities', 'Qualities')}:"
|
|
754
|
+
template_dict["cardinal_string"] = f"{self.language_settings.get('cardinal', 'Cardinal')} {cardinal_percentage}%"
|
|
755
|
+
template_dict["fixed_string"] = f"{self.language_settings.get('fixed', 'Fixed')} {fixed_percentage}%"
|
|
756
|
+
template_dict["mutable_string"] = f"{self.language_settings.get('mutable', 'Mutable')} {mutable_percentage}%"
|
|
757
|
+
|
|
758
|
+
# Get houses list for main subject
|
|
759
|
+
first_subject_houses_list = get_houses_list(self.first_obj)
|
|
760
|
+
|
|
761
|
+
# ------------------------------- #
|
|
762
|
+
# CHART TYPE SPECIFIC SETTINGS #
|
|
763
|
+
# ------------------------------- #
|
|
764
|
+
|
|
765
|
+
if self.chart_type in ["Natal", "ExternalNatal"]:
|
|
766
|
+
# Set viewbox
|
|
767
|
+
template_dict["viewbox"] = self._BASIC_CHART_VIEWBOX
|
|
768
|
+
|
|
769
|
+
# Rings and circles
|
|
564
770
|
template_dict["transitRing"] = ""
|
|
565
|
-
template_dict["degreeRing"] = draw_degree_ring(
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
771
|
+
template_dict["degreeRing"] = draw_degree_ring(
|
|
772
|
+
self.main_radius,
|
|
773
|
+
self.first_circle_radius,
|
|
774
|
+
self.first_obj.seventh_house.abs_pos,
|
|
775
|
+
self.chart_colors_settings["paper_0"],
|
|
776
|
+
)
|
|
777
|
+
template_dict["first_circle"] = draw_first_circle(
|
|
778
|
+
self.main_radius,
|
|
779
|
+
self.chart_colors_settings["zodiac_radix_ring_2"],
|
|
780
|
+
self.chart_type,
|
|
781
|
+
self.first_circle_radius,
|
|
782
|
+
)
|
|
783
|
+
template_dict["second_circle"] = draw_second_circle(
|
|
784
|
+
self.main_radius,
|
|
785
|
+
self.chart_colors_settings["zodiac_radix_ring_1"],
|
|
786
|
+
self.chart_colors_settings["paper_1"],
|
|
787
|
+
self.chart_type,
|
|
788
|
+
self.second_circle_radius,
|
|
789
|
+
)
|
|
790
|
+
template_dict["third_circle"] = draw_third_circle(
|
|
791
|
+
self.main_radius,
|
|
792
|
+
self.chart_colors_settings["zodiac_radix_ring_0"],
|
|
793
|
+
self.chart_colors_settings["paper_1"],
|
|
794
|
+
self.chart_type,
|
|
795
|
+
self.third_circle_radius,
|
|
796
|
+
)
|
|
570
797
|
|
|
798
|
+
# Aspects
|
|
799
|
+
template_dict["makeDoubleChartAspectList"] = ""
|
|
800
|
+
template_dict["makeAspectGrid"] = draw_aspect_grid(
|
|
801
|
+
self.chart_colors_settings["paper_0"],
|
|
802
|
+
self.available_planets_setting,
|
|
803
|
+
self.aspects_list,
|
|
804
|
+
)
|
|
571
805
|
template_dict["makeAspects"] = self._draw_all_aspects_lines(self.main_radius, self.main_radius - self.third_circle_radius)
|
|
572
806
|
|
|
573
|
-
|
|
574
|
-
|
|
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}"
|
|
807
|
+
# Chart title
|
|
808
|
+
template_dict["stringTitle"] = f"{self.first_obj.name} - {self.language_settings.get("Birth Chart", "Birth Chart")}"
|
|
582
809
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
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}"
|
|
810
|
+
# Top left section
|
|
811
|
+
latitude_string = convert_latitude_coordinate_to_string(self.geolat, self.language_settings["north"], self.language_settings["south"])
|
|
812
|
+
longitude_string = convert_longitude_coordinate_to_string(self.geolon, self.language_settings["east"], self.language_settings["west"])
|
|
590
813
|
|
|
591
|
-
|
|
592
|
-
|
|
814
|
+
template_dict["top_left_0"] = f'{self.language_settings.get("location", "Location")}:'
|
|
815
|
+
template_dict["top_left_1"] = f"{self.first_obj.city}, {self.first_obj.nation}"
|
|
816
|
+
template_dict["top_left_2"] = f"{self.language_settings['latitude']}: {latitude_string}"
|
|
817
|
+
template_dict["top_left_3"] = f"{self.language_settings['longitude']}: {longitude_string}"
|
|
818
|
+
template_dict["top_left_4"] = format_datetime_with_timezone(self.first_obj.iso_formatted_local_datetime) # type: ignore
|
|
819
|
+
template_dict["top_left_5"] = f"{self.language_settings.get('day_of_week', 'Day of Week')}: {self.first_obj.day_of_week}" # type: ignore
|
|
820
|
+
|
|
821
|
+
# Bottom left section
|
|
822
|
+
if self.first_obj.zodiac_type == "Tropic":
|
|
823
|
+
zodiac_info = f"{self.language_settings.get('zodiac', 'Zodiac')}: {self.language_settings.get('tropical', 'Tropical')}"
|
|
824
|
+
else:
|
|
825
|
+
mode_const = "SIDM_" + self.first_obj.sidereal_mode # type: ignore
|
|
826
|
+
mode_name = swe.get_ayanamsa_name(getattr(swe, mode_const))
|
|
827
|
+
zodiac_info = f"{self.language_settings.get('ayanamsa', 'Ayanamsa')}: {mode_name}"
|
|
828
|
+
|
|
829
|
+
template_dict["bottom_left_0"] = zodiac_info
|
|
830
|
+
template_dict["bottom_left_1"] = f"{self.language_settings.get('domification', 'Domification')}: {self.language_settings.get('houses_system_' + self.first_obj.houses_system_identifier, self.first_obj.houses_system_name)}"
|
|
831
|
+
template_dict["bottom_left_2"] = f'{self.language_settings.get("lunation_day", "Lunation Day")}: {self.first_obj.lunar_phase.get("moon_phase", "")}'
|
|
832
|
+
template_dict["bottom_left_3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get(self.first_obj.lunar_phase.moon_phase_name.lower().replace(" ", "_"), self.first_obj.lunar_phase.moon_phase_name)}'
|
|
833
|
+
template_dict["bottom_left_4"] = f'{self.language_settings.get("perspective_type", "Perspective")}: {self.language_settings.get(self.first_obj.perspective_type.lower().replace(" ", "_"), self.first_obj.perspective_type)}'
|
|
834
|
+
|
|
835
|
+
# Moon phase section calculations
|
|
836
|
+
template_dict["makeLunarPhase"] = makeLunarPhase(self.first_obj.lunar_phase["degrees_between_s_m"], self.geolat)
|
|
837
|
+
|
|
838
|
+
# Houses and planet drawing
|
|
839
|
+
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
840
|
+
main_subject_houses_list=first_subject_houses_list,
|
|
841
|
+
chart_type=self.chart_type,
|
|
842
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
843
|
+
house_cusp_generale_name_label=self.language_settings["cusp"],
|
|
844
|
+
)
|
|
845
|
+
|
|
846
|
+
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
847
|
+
r=self.main_radius,
|
|
848
|
+
first_subject_houses_list=first_subject_houses_list,
|
|
849
|
+
standard_house_cusp_color=self.chart_colors_settings["houses_radix_line"],
|
|
850
|
+
first_house_color=self.planets_settings[12]["color"],
|
|
851
|
+
tenth_house_color=self.planets_settings[13]["color"],
|
|
852
|
+
seventh_house_color=self.planets_settings[14]["color"],
|
|
853
|
+
fourth_house_color=self.planets_settings[15]["color"],
|
|
854
|
+
c1=self.first_circle_radius,
|
|
855
|
+
c3=self.third_circle_radius,
|
|
856
|
+
chart_type=self.chart_type,
|
|
857
|
+
)
|
|
858
|
+
|
|
859
|
+
template_dict["makePlanets"] = draw_planets(
|
|
860
|
+
available_planets_setting=self.available_planets_setting,
|
|
861
|
+
chart_type=self.chart_type,
|
|
862
|
+
radius=self.main_radius,
|
|
863
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
864
|
+
third_circle_radius=self.third_circle_radius,
|
|
865
|
+
main_subject_first_house_degree_ut=self.first_obj.first_house.abs_pos,
|
|
866
|
+
main_subject_seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
867
|
+
)
|
|
868
|
+
|
|
869
|
+
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
870
|
+
planets_and_houses_grid_title=self.language_settings["planets_and_house"],
|
|
871
|
+
subject_name=self.first_obj.name,
|
|
872
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
873
|
+
chart_type=self.chart_type,
|
|
874
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
875
|
+
celestial_point_language=self.language_settings["celestial_points"],
|
|
876
|
+
)
|
|
877
|
+
template_dict["makeHouseComparisonGrid"] = ""
|
|
593
878
|
|
|
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
879
|
elif self.chart_type == "Composite":
|
|
603
|
-
|
|
880
|
+
# Set viewbox
|
|
881
|
+
template_dict["viewbox"] = self._BASIC_CHART_VIEWBOX
|
|
882
|
+
|
|
883
|
+
# Rings and circles
|
|
884
|
+
template_dict["transitRing"] = ""
|
|
885
|
+
template_dict["degreeRing"] = draw_degree_ring(
|
|
886
|
+
self.main_radius,
|
|
887
|
+
self.first_circle_radius,
|
|
888
|
+
self.first_obj.seventh_house.abs_pos,
|
|
889
|
+
self.chart_colors_settings["paper_0"],
|
|
890
|
+
)
|
|
891
|
+
template_dict["first_circle"] = draw_first_circle(
|
|
892
|
+
self.main_radius,
|
|
893
|
+
self.chart_colors_settings["zodiac_radix_ring_2"],
|
|
894
|
+
self.chart_type,
|
|
895
|
+
self.first_circle_radius,
|
|
896
|
+
)
|
|
897
|
+
template_dict["second_circle"] = draw_second_circle(
|
|
898
|
+
self.main_radius,
|
|
899
|
+
self.chart_colors_settings["zodiac_radix_ring_1"],
|
|
900
|
+
self.chart_colors_settings["paper_1"],
|
|
901
|
+
self.chart_type,
|
|
902
|
+
self.second_circle_radius,
|
|
903
|
+
)
|
|
904
|
+
template_dict["third_circle"] = draw_third_circle(
|
|
905
|
+
self.main_radius,
|
|
906
|
+
self.chart_colors_settings["zodiac_radix_ring_0"],
|
|
907
|
+
self.chart_colors_settings["paper_1"],
|
|
908
|
+
self.chart_type,
|
|
909
|
+
self.third_circle_radius,
|
|
910
|
+
)
|
|
911
|
+
|
|
912
|
+
# Aspects
|
|
913
|
+
template_dict["makeDoubleChartAspectList"] = ""
|
|
914
|
+
template_dict["makeAspectGrid"] = draw_aspect_grid(
|
|
915
|
+
self.chart_colors_settings["paper_0"],
|
|
916
|
+
self.available_planets_setting,
|
|
917
|
+
self.aspects_list,
|
|
918
|
+
)
|
|
919
|
+
template_dict["makeAspects"] = self._draw_all_aspects_lines(self.main_radius, self.main_radius - self.third_circle_radius)
|
|
920
|
+
|
|
921
|
+
# Chart title
|
|
922
|
+
template_dict["stringTitle"] = f"{self.first_obj.first_subject.name} {self.language_settings['and_word']} {self.first_obj.second_subject.name}" # type: ignore
|
|
923
|
+
|
|
924
|
+
# Top left section
|
|
925
|
+
# First subject
|
|
926
|
+
latitude = convert_latitude_coordinate_to_string(
|
|
927
|
+
self.first_obj.first_subject.lat, # type: ignore
|
|
928
|
+
self.language_settings["north_letter"],
|
|
929
|
+
self.language_settings["south_letter"],
|
|
930
|
+
)
|
|
931
|
+
longitude = convert_longitude_coordinate_to_string(
|
|
932
|
+
self.first_obj.first_subject.lng, # type: ignore
|
|
933
|
+
self.language_settings["east_letter"],
|
|
934
|
+
self.language_settings["west_letter"],
|
|
935
|
+
)
|
|
936
|
+
|
|
937
|
+
# Second subject
|
|
938
|
+
latitude_string = convert_latitude_coordinate_to_string(
|
|
939
|
+
self.first_obj.second_subject.lat, # type: ignore
|
|
940
|
+
self.language_settings["north_letter"],
|
|
941
|
+
self.language_settings["south_letter"],
|
|
942
|
+
)
|
|
943
|
+
longitude_string = convert_longitude_coordinate_to_string(
|
|
944
|
+
self.first_obj.second_subject.lng, # type: ignore
|
|
945
|
+
self.language_settings["east_letter"],
|
|
946
|
+
self.language_settings["west_letter"],
|
|
947
|
+
)
|
|
948
|
+
|
|
949
|
+
template_dict["top_left_0"] = f"{self.first_obj.first_subject.name}" # type: ignore
|
|
950
|
+
template_dict["top_left_1"] = f"{datetime.fromisoformat(self.first_obj.first_subject.iso_formatted_local_datetime).strftime('%Y-%m-%d %H:%M')}" # type: ignore
|
|
951
|
+
template_dict["top_left_2"] = f"{latitude} {longitude}"
|
|
952
|
+
template_dict["top_left_3"] = self.first_obj.second_subject.name # type: ignore
|
|
953
|
+
template_dict["top_left_4"] = f"{datetime.fromisoformat(self.first_obj.second_subject.iso_formatted_local_datetime).strftime('%Y-%m-%d %H:%M')}" # type: ignore
|
|
954
|
+
template_dict["top_left_5"] = f"{latitude_string} / {longitude_string}"
|
|
955
|
+
|
|
956
|
+
# Bottom left section
|
|
957
|
+
if self.first_obj.zodiac_type == "Tropic":
|
|
958
|
+
zodiac_info = f"{self.language_settings.get('zodiac', 'Zodiac')}: {self.language_settings.get('tropical', 'Tropical')}"
|
|
959
|
+
else:
|
|
960
|
+
mode_const = "SIDM_" + self.first_obj.sidereal_mode # type: ignore
|
|
961
|
+
mode_name = swe.get_ayanamsa_name(getattr(swe, mode_const))
|
|
962
|
+
zodiac_info = f"{self.language_settings.get('ayanamsa', 'Ayanamsa')}: {mode_name}"
|
|
963
|
+
|
|
964
|
+
template_dict["bottom_left_0"] = zodiac_info
|
|
965
|
+
template_dict["bottom_left_1"] = f"{self.language_settings.get('houses_system_' + self.first_obj.houses_system_identifier, self.first_obj.houses_system_name)} {self.language_settings.get('houses', 'Houses')}"
|
|
966
|
+
template_dict["bottom_left_2"] = f"{self.language_settings.get("perspective_type", "Perspective")}: {self.first_obj.first_subject.perspective_type}" # type: ignore
|
|
604
967
|
template_dict["bottom_left_3"] = f'{self.language_settings.get("composite_chart", "Composite Chart")} - {self.language_settings.get("midpoints", "Midpoints")}'
|
|
605
968
|
template_dict["bottom_left_4"] = ""
|
|
606
969
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
template_dict["
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
970
|
+
# Moon phase section calculations
|
|
971
|
+
template_dict["makeLunarPhase"] = makeLunarPhase(self.first_obj.lunar_phase["degrees_between_s_m"], self.geolat)
|
|
972
|
+
|
|
973
|
+
# Houses and planet drawing
|
|
974
|
+
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
975
|
+
main_subject_houses_list=first_subject_houses_list,
|
|
976
|
+
chart_type=self.chart_type,
|
|
977
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
978
|
+
house_cusp_generale_name_label=self.language_settings["cusp"],
|
|
979
|
+
)
|
|
980
|
+
|
|
981
|
+
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
982
|
+
r=self.main_radius,
|
|
983
|
+
first_subject_houses_list=first_subject_houses_list,
|
|
984
|
+
standard_house_cusp_color=self.chart_colors_settings["houses_radix_line"],
|
|
985
|
+
first_house_color=self.planets_settings[12]["color"],
|
|
986
|
+
tenth_house_color=self.planets_settings[13]["color"],
|
|
987
|
+
seventh_house_color=self.planets_settings[14]["color"],
|
|
988
|
+
fourth_house_color=self.planets_settings[15]["color"],
|
|
989
|
+
c1=self.first_circle_radius,
|
|
990
|
+
c3=self.third_circle_radius,
|
|
991
|
+
chart_type=self.chart_type,
|
|
992
|
+
)
|
|
993
|
+
|
|
994
|
+
template_dict["makePlanets"] = draw_planets(
|
|
995
|
+
available_planets_setting=self.available_planets_setting,
|
|
996
|
+
chart_type=self.chart_type,
|
|
997
|
+
radius=self.main_radius,
|
|
998
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
999
|
+
third_circle_radius=self.third_circle_radius,
|
|
1000
|
+
main_subject_first_house_degree_ut=self.first_obj.first_house.abs_pos,
|
|
1001
|
+
main_subject_seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
1002
|
+
)
|
|
1003
|
+
|
|
1004
|
+
subject_name = f"{self.first_obj.first_subject.name} {self.language_settings['and_word']} {self.first_obj.second_subject.name}" # type: ignore
|
|
1005
|
+
|
|
1006
|
+
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
1007
|
+
planets_and_houses_grid_title=self.language_settings["planets_and_house"],
|
|
1008
|
+
subject_name=subject_name,
|
|
1009
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
1010
|
+
chart_type=self.chart_type,
|
|
1011
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
1012
|
+
celestial_point_language=self.language_settings["celestial_points"],
|
|
1013
|
+
)
|
|
1014
|
+
template_dict["makeHouseComparisonGrid"] = ""
|
|
1015
|
+
|
|
1016
|
+
elif self.chart_type == "Transit":
|
|
1017
|
+
|
|
1018
|
+
# Transit has no Element Percentages
|
|
1019
|
+
template_dict["elements_string"] = ""
|
|
1020
|
+
template_dict["fire_string"] = ""
|
|
1021
|
+
template_dict["earth_string"] = ""
|
|
1022
|
+
template_dict["air_string"] = ""
|
|
1023
|
+
template_dict["water_string"] = ""
|
|
1024
|
+
|
|
1025
|
+
# Transit has no Qualities Percentages
|
|
1026
|
+
template_dict["qualities_string"] = ""
|
|
1027
|
+
template_dict["cardinal_string"] = ""
|
|
1028
|
+
template_dict["fixed_string"] = ""
|
|
1029
|
+
template_dict["mutable_string"] = ""
|
|
1030
|
+
|
|
1031
|
+
# Set viewbox
|
|
1032
|
+
if self.double_chart_aspect_grid_type == "table":
|
|
1033
|
+
template_dict["viewbox"] = self._TRANSIT_CHART_WITH_TABLE_VIWBOX
|
|
626
1034
|
else:
|
|
627
|
-
template_dict["
|
|
628
|
-
else:
|
|
629
|
-
template_dict["top_left_1"] = self.location
|
|
1035
|
+
template_dict["viewbox"] = self._WIDE_CHART_VIEWBOX
|
|
630
1036
|
|
|
631
|
-
|
|
632
|
-
|
|
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}'
|
|
1037
|
+
# Get houses list for secondary subject
|
|
1038
|
+
second_subject_houses_list = get_houses_list(self.second_obj) # type: ignore
|
|
638
1039
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
template_dict["
|
|
646
|
-
template_dict["
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
1040
|
+
# Rings and circles
|
|
1041
|
+
template_dict["transitRing"] = draw_transit_ring(
|
|
1042
|
+
self.main_radius,
|
|
1043
|
+
self.chart_colors_settings["paper_1"],
|
|
1044
|
+
self.chart_colors_settings["zodiac_transit_ring_3"],
|
|
1045
|
+
)
|
|
1046
|
+
template_dict["degreeRing"] = draw_transit_ring_degree_steps(self.main_radius, self.first_obj.seventh_house.abs_pos)
|
|
1047
|
+
template_dict["first_circle"] = draw_first_circle(
|
|
1048
|
+
self.main_radius,
|
|
1049
|
+
self.chart_colors_settings["zodiac_transit_ring_2"],
|
|
1050
|
+
self.chart_type,
|
|
1051
|
+
)
|
|
1052
|
+
template_dict["second_circle"] = draw_second_circle(
|
|
1053
|
+
self.main_radius,
|
|
1054
|
+
self.chart_colors_settings["zodiac_transit_ring_1"],
|
|
1055
|
+
self.chart_colors_settings["paper_1"],
|
|
1056
|
+
self.chart_type,
|
|
1057
|
+
)
|
|
1058
|
+
template_dict["third_circle"] = draw_third_circle(
|
|
1059
|
+
self.main_radius,
|
|
1060
|
+
self.chart_colors_settings["zodiac_transit_ring_0"],
|
|
1061
|
+
self.chart_colors_settings["paper_1"],
|
|
1062
|
+
self.chart_type,
|
|
1063
|
+
self.third_circle_radius,
|
|
1064
|
+
)
|
|
656
1065
|
|
|
1066
|
+
# Aspects
|
|
1067
|
+
if self.double_chart_aspect_grid_type == "list":
|
|
1068
|
+
title = f"{self.first_obj.name} - {self.language_settings.get("transit_aspects", "Transit Aspects")}"
|
|
1069
|
+
template_dict["makeAspectGrid"] = ""
|
|
1070
|
+
template_dict["makeDoubleChartAspectList"] = draw_transit_aspect_list(title, self.aspects_list, self.planets_settings, self.aspects_settings)
|
|
1071
|
+
else:
|
|
1072
|
+
template_dict["makeAspectGrid"] = ""
|
|
1073
|
+
template_dict["makeDoubleChartAspectList"] = draw_transit_aspect_grid(
|
|
1074
|
+
self.chart_colors_settings["paper_0"],
|
|
1075
|
+
self.available_planets_setting,
|
|
1076
|
+
self.aspects_list,
|
|
1077
|
+
550,
|
|
1078
|
+
450,
|
|
1079
|
+
)
|
|
657
1080
|
|
|
658
|
-
|
|
659
|
-
template_dict["paper_color_0"] = self.chart_colors_settings["paper_0"]
|
|
660
|
-
template_dict["paper_color_1"] = self.chart_colors_settings["paper_1"]
|
|
1081
|
+
template_dict["makeAspects"] = self._draw_all_transit_aspects_lines(self.main_radius, self.main_radius - 160)
|
|
661
1082
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
planet_id = planet["id"]
|
|
665
|
-
template_dict[f"planets_color_{planet_id}"] = planet["color"] # type: ignore
|
|
1083
|
+
# Chart title
|
|
1084
|
+
template_dict["stringTitle"] = f"{self.language_settings['transits']} {format_datetime_with_timezone(self.second_obj.iso_formatted_local_datetime)}" # type: ignore
|
|
666
1085
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
1086
|
+
# Top left section
|
|
1087
|
+
latitude_string = convert_latitude_coordinate_to_string(self.geolat, self.language_settings["north"], self.language_settings["south"])
|
|
1088
|
+
longitude_string = convert_longitude_coordinate_to_string(self.geolon, self.language_settings["east"], self.language_settings["west"])
|
|
670
1089
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
template_dict[
|
|
1090
|
+
template_dict["top_left_0"] = template_dict["top_left_0"] = f'{self.first_obj.name}'
|
|
1091
|
+
template_dict["top_left_1"] = f"{format_location_string(self.first_obj.city)}, {self.first_obj.nation}" # type: ignore
|
|
1092
|
+
template_dict["top_left_2"] = format_datetime_with_timezone(self.first_obj.iso_formatted_local_datetime) # type: ignore
|
|
1093
|
+
template_dict["top_left_3"] = f"{self.language_settings['latitude']}: {latitude_string}"
|
|
1094
|
+
template_dict["top_left_4"] = f"{self.language_settings['longitude']}: {longitude_string}"
|
|
1095
|
+
template_dict["top_left_5"] = ""#f"{self.language_settings['type']}: {self.language_settings.get(self.chart_type, self.chart_type)}"
|
|
674
1096
|
|
|
675
|
-
|
|
676
|
-
|
|
1097
|
+
# Bottom left section
|
|
1098
|
+
if self.first_obj.zodiac_type == "Tropic":
|
|
1099
|
+
zodiac_info = f"{self.language_settings.get('zodiac', 'Zodiac')}: {self.language_settings.get('tropical', 'Tropical')}"
|
|
1100
|
+
else:
|
|
1101
|
+
mode_const = "SIDM_" + self.first_obj.sidereal_mode # type: ignore
|
|
1102
|
+
mode_name = swe.get_ayanamsa_name(getattr(swe, mode_const))
|
|
1103
|
+
zodiac_info = f"{self.language_settings.get('ayanamsa', 'Ayanamsa')}: {mode_name}"
|
|
677
1104
|
|
|
678
|
-
|
|
1105
|
+
template_dict["bottom_left_0"] = zodiac_info
|
|
1106
|
+
template_dict["bottom_left_1"] = f"{self.language_settings.get('domification', 'Domification')}: {self.language_settings.get('houses_system_' + self.first_obj.houses_system_identifier, self.first_obj.houses_system_name)}"
|
|
1107
|
+
template_dict["bottom_left_2"] = f'{self.language_settings.get("lunation_day", "Lunation Day")}: {self.second_obj.lunar_phase.get("moon_phase", "")}' # type: ignore
|
|
1108
|
+
template_dict["bottom_left_3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get(self.second_obj.lunar_phase.moon_phase_name.lower().replace(" ", "_"), self.first_obj.lunar_phase.moon_phase_name)}'
|
|
1109
|
+
template_dict["bottom_left_4"] = f'{self.language_settings.get("perspective_type", "Perspective")}: {self.language_settings.get(self.second_obj.perspective_type.lower().replace(" ", "_"), self.second_obj.perspective_type)}' # type: ignore
|
|
679
1110
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
second_subject_houses_list = get_houses_list(self.t_user)
|
|
1111
|
+
# Moon phase section calculations
|
|
1112
|
+
template_dict["makeLunarPhase"] = makeLunarPhase(self.first_obj.lunar_phase["degrees_between_s_m"], self.geolat)
|
|
683
1113
|
|
|
1114
|
+
# Houses and planet drawing
|
|
684
1115
|
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
685
1116
|
main_subject_houses_list=first_subject_houses_list,
|
|
686
1117
|
secondary_subject_houses_list=second_subject_houses_list,
|
|
687
1118
|
chart_type=self.chart_type,
|
|
688
1119
|
text_color=self.chart_colors_settings["paper_0"],
|
|
689
|
-
house_cusp_generale_name_label=self.language_settings["cusp"]
|
|
1120
|
+
house_cusp_generale_name_label=self.language_settings["cusp"],
|
|
690
1121
|
)
|
|
691
1122
|
|
|
692
1123
|
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
@@ -704,12 +1135,140 @@ class KerykeionChartSVG:
|
|
|
704
1135
|
transit_house_cusp_color=self.chart_colors_settings["houses_transit_line"],
|
|
705
1136
|
)
|
|
706
1137
|
|
|
707
|
-
|
|
1138
|
+
template_dict["makePlanets"] = draw_planets(
|
|
1139
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
1140
|
+
available_planets_setting=self.available_planets_setting,
|
|
1141
|
+
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
1142
|
+
radius=self.main_radius,
|
|
1143
|
+
main_subject_first_house_degree_ut=self.first_obj.first_house.abs_pos,
|
|
1144
|
+
main_subject_seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
1145
|
+
chart_type=self.chart_type,
|
|
1146
|
+
third_circle_radius=self.third_circle_radius,
|
|
1147
|
+
)
|
|
1148
|
+
|
|
1149
|
+
# Planet grid
|
|
1150
|
+
|
|
1151
|
+
first_return_grid_title = f"{self.first_obj.name} ({self.language_settings.get('inner_wheel', 'Inner Wheel')})"
|
|
1152
|
+
second_return_grid_title = f"{self.language_settings.get('Transit', 'Transit')} ({self.language_settings.get('outer_wheel', 'Outer Wheel')})"
|
|
1153
|
+
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
1154
|
+
planets_and_houses_grid_title="",
|
|
1155
|
+
subject_name=first_return_grid_title,
|
|
1156
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
1157
|
+
chart_type=self.chart_type,
|
|
1158
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
1159
|
+
celestial_point_language=self.language_settings["celestial_points"],
|
|
1160
|
+
second_subject_name=second_return_grid_title,
|
|
1161
|
+
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
1162
|
+
)
|
|
1163
|
+
|
|
1164
|
+
# House comparison grid
|
|
1165
|
+
house_comparison_factory = HouseComparisonFactory(
|
|
1166
|
+
first_subject=self.first_obj,
|
|
1167
|
+
second_subject=self.second_obj,
|
|
1168
|
+
active_points=self.active_points,
|
|
1169
|
+
)
|
|
1170
|
+
house_comparison = house_comparison_factory.get_house_comparison()
|
|
1171
|
+
|
|
1172
|
+
template_dict["makeHouseComparisonGrid"] = draw_single_house_comparison_grid(
|
|
1173
|
+
house_comparison,
|
|
1174
|
+
celestial_point_language=self.language_settings.get("celestial_points", "Celestial Points"),
|
|
1175
|
+
active_points=self.active_points,
|
|
1176
|
+
points_owner_subject_number=2, # The second subject is the Transit
|
|
1177
|
+
house_position_comparison_label=self.language_settings.get("house_position_comparison", "House Position Comparison"),
|
|
1178
|
+
return_point_label=self.language_settings.get("transit_point", "Transit Point"),
|
|
1179
|
+
natal_house_label=self.language_settings.get("house_position", "Natal House"),
|
|
1180
|
+
x_position=930,
|
|
1181
|
+
)
|
|
1182
|
+
|
|
1183
|
+
elif self.chart_type == "Synastry":
|
|
1184
|
+
# Set viewbox
|
|
1185
|
+
template_dict["viewbox"] = self._WIDE_CHART_VIEWBOX
|
|
1186
|
+
|
|
1187
|
+
# Get houses list for secondary subject
|
|
1188
|
+
second_subject_houses_list = get_houses_list(self.second_obj) # type: ignore
|
|
1189
|
+
|
|
1190
|
+
# Rings and circles
|
|
1191
|
+
template_dict["transitRing"] = draw_transit_ring(
|
|
1192
|
+
self.main_radius,
|
|
1193
|
+
self.chart_colors_settings["paper_1"],
|
|
1194
|
+
self.chart_colors_settings["zodiac_transit_ring_3"],
|
|
1195
|
+
)
|
|
1196
|
+
template_dict["degreeRing"] = draw_transit_ring_degree_steps(self.main_radius, self.first_obj.seventh_house.abs_pos)
|
|
1197
|
+
template_dict["first_circle"] = draw_first_circle(
|
|
1198
|
+
self.main_radius,
|
|
1199
|
+
self.chart_colors_settings["zodiac_transit_ring_2"],
|
|
1200
|
+
self.chart_type,
|
|
1201
|
+
)
|
|
1202
|
+
template_dict["second_circle"] = draw_second_circle(
|
|
1203
|
+
self.main_radius,
|
|
1204
|
+
self.chart_colors_settings["zodiac_transit_ring_1"],
|
|
1205
|
+
self.chart_colors_settings["paper_1"],
|
|
1206
|
+
self.chart_type,
|
|
1207
|
+
)
|
|
1208
|
+
template_dict["third_circle"] = draw_third_circle(
|
|
1209
|
+
self.main_radius,
|
|
1210
|
+
self.chart_colors_settings["zodiac_transit_ring_0"],
|
|
1211
|
+
self.chart_colors_settings["paper_1"],
|
|
1212
|
+
self.chart_type,
|
|
1213
|
+
self.third_circle_radius,
|
|
1214
|
+
)
|
|
1215
|
+
|
|
1216
|
+
# Aspects
|
|
1217
|
+
if self.double_chart_aspect_grid_type == "list":
|
|
1218
|
+
template_dict["makeAspectGrid"] = ""
|
|
1219
|
+
template_dict["makeDoubleChartAspectList"] = draw_transit_aspect_list(
|
|
1220
|
+
f"{self.first_obj.name} - {self.second_obj.name} {self.language_settings.get('synastry_aspects', 'Synastry Aspects')}", # type: ignore
|
|
1221
|
+
self.aspects_list,
|
|
1222
|
+
self.planets_settings,
|
|
1223
|
+
self.aspects_settings
|
|
1224
|
+
)
|
|
1225
|
+
else:
|
|
1226
|
+
template_dict["makeAspectGrid"] = ""
|
|
1227
|
+
template_dict["makeDoubleChartAspectList"] = draw_transit_aspect_grid(
|
|
1228
|
+
self.chart_colors_settings["paper_0"],
|
|
1229
|
+
self.available_planets_setting,
|
|
1230
|
+
self.aspects_list,
|
|
1231
|
+
550,
|
|
1232
|
+
450,
|
|
1233
|
+
)
|
|
1234
|
+
|
|
1235
|
+
template_dict["makeAspects"] = self._draw_all_transit_aspects_lines(self.main_radius, self.main_radius - 160)
|
|
1236
|
+
|
|
1237
|
+
# Chart title
|
|
1238
|
+
template_dict["stringTitle"] = f"{self.first_obj.name} {self.language_settings['and_word']} {self.second_obj.name}" # type: ignore
|
|
1239
|
+
|
|
1240
|
+
# Top left section
|
|
1241
|
+
template_dict["top_left_0"] = f"{self.first_obj.name}:"
|
|
1242
|
+
template_dict["top_left_1"] = f"{self.first_obj.city}, {self.first_obj.nation}" # type: ignore
|
|
1243
|
+
template_dict["top_left_2"] = format_datetime_with_timezone(self.first_obj.iso_formatted_local_datetime) # type: ignore
|
|
1244
|
+
template_dict["top_left_3"] = f"{self.second_obj.name}: " # type: ignore
|
|
1245
|
+
template_dict["top_left_4"] = f"{self.second_obj.city}, {self.second_obj.nation}" # type: ignore
|
|
1246
|
+
template_dict["top_left_5"] = format_datetime_with_timezone(self.second_obj.iso_formatted_local_datetime) # type: ignore
|
|
1247
|
+
|
|
1248
|
+
# Bottom left section
|
|
1249
|
+
if self.first_obj.zodiac_type == "Tropic":
|
|
1250
|
+
zodiac_info = f"{self.language_settings.get('zodiac', 'Zodiac')}: {self.language_settings.get('tropical', 'Tropical')}"
|
|
1251
|
+
else:
|
|
1252
|
+
mode_const = "SIDM_" + self.first_obj.sidereal_mode # type: ignore
|
|
1253
|
+
mode_name = swe.get_ayanamsa_name(getattr(swe, mode_const))
|
|
1254
|
+
zodiac_info = f"{self.language_settings.get('ayanamsa', 'Ayanamsa')}: {mode_name}"
|
|
1255
|
+
|
|
1256
|
+
template_dict["bottom_left_0"] = ""
|
|
1257
|
+
template_dict["bottom_left_1"] = ""
|
|
1258
|
+
template_dict["bottom_left_2"] = zodiac_info
|
|
1259
|
+
template_dict["bottom_left_3"] = f"{self.language_settings.get('houses_system_' + self.first_obj.houses_system_identifier, self.first_obj.houses_system_name)} {self.language_settings.get('houses', 'Houses')}"
|
|
1260
|
+
template_dict["bottom_left_4"] = f'{self.language_settings.get("perspective_type", "Perspective")}: {self.language_settings.get(self.first_obj.perspective_type.lower().replace(" ", "_"), self.first_obj.perspective_type)}'
|
|
1261
|
+
|
|
1262
|
+
# Moon phase section calculations
|
|
1263
|
+
template_dict["makeLunarPhase"] = ""
|
|
1264
|
+
|
|
1265
|
+
# Houses and planet drawing
|
|
708
1266
|
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
709
1267
|
main_subject_houses_list=first_subject_houses_list,
|
|
1268
|
+
secondary_subject_houses_list=second_subject_houses_list,
|
|
710
1269
|
chart_type=self.chart_type,
|
|
711
1270
|
text_color=self.chart_colors_settings["paper_0"],
|
|
712
|
-
house_cusp_generale_name_label=self.language_settings["cusp"]
|
|
1271
|
+
house_cusp_generale_name_label=self.language_settings["cusp"],
|
|
713
1272
|
)
|
|
714
1273
|
|
|
715
1274
|
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
@@ -723,91 +1282,319 @@ class KerykeionChartSVG:
|
|
|
723
1282
|
c1=self.first_circle_radius,
|
|
724
1283
|
c3=self.third_circle_radius,
|
|
725
1284
|
chart_type=self.chart_type,
|
|
1285
|
+
second_subject_houses_list=second_subject_houses_list,
|
|
1286
|
+
transit_house_cusp_color=self.chart_colors_settings["houses_transit_line"],
|
|
726
1287
|
)
|
|
727
1288
|
|
|
728
|
-
# Draw planets
|
|
729
|
-
if self.chart_type in ["Transit", "Synastry"]:
|
|
730
1289
|
template_dict["makePlanets"] = draw_planets(
|
|
731
1290
|
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
732
1291
|
available_planets_setting=self.available_planets_setting,
|
|
733
1292
|
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
734
1293
|
radius=self.main_radius,
|
|
735
|
-
main_subject_first_house_degree_ut=self.
|
|
736
|
-
main_subject_seventh_house_degree_ut=self.
|
|
1294
|
+
main_subject_first_house_degree_ut=self.first_obj.first_house.abs_pos,
|
|
1295
|
+
main_subject_seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
737
1296
|
chart_type=self.chart_type,
|
|
738
1297
|
third_circle_radius=self.third_circle_radius,
|
|
739
1298
|
)
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1299
|
+
|
|
1300
|
+
# Planet grid
|
|
1301
|
+
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
1302
|
+
planets_and_houses_grid_title="",
|
|
1303
|
+
subject_name=f"{self.first_obj.name} ({self.language_settings.get('inner_wheel', 'Inner Wheel')})",
|
|
745
1304
|
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
1305
|
+
chart_type=self.chart_type,
|
|
1306
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
1307
|
+
celestial_point_language=self.language_settings["celestial_points"],
|
|
1308
|
+
second_subject_name= f"{self.second_obj.name} ({self.language_settings.get('outer_wheel', 'Outer Wheel')})", # type: ignore
|
|
1309
|
+
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
749
1310
|
)
|
|
1311
|
+
template_dict["makeHouseComparisonGrid"] = ""
|
|
750
1312
|
|
|
751
|
-
|
|
752
|
-
|
|
1313
|
+
elif self.chart_type == "Return":
|
|
1314
|
+
# Set viewbox
|
|
1315
|
+
template_dict["viewbox"] = self._ULTRA_WIDE_CHART_VIEWBOX
|
|
753
1316
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
air_percentage = int(round(100 * self.air / total))
|
|
757
|
-
water_percentage = int(round(100 * self.water / total))
|
|
1317
|
+
# Get houses list for secondary subject
|
|
1318
|
+
second_subject_houses_list = get_houses_list(self.second_obj) # type: ignore
|
|
758
1319
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1320
|
+
# Rings and circles
|
|
1321
|
+
template_dict["transitRing"] = draw_transit_ring(
|
|
1322
|
+
self.main_radius,
|
|
1323
|
+
self.chart_colors_settings["paper_1"],
|
|
1324
|
+
self.chart_colors_settings["zodiac_transit_ring_3"],
|
|
1325
|
+
)
|
|
1326
|
+
template_dict["degreeRing"] = draw_transit_ring_degree_steps(self.main_radius, self.first_obj.seventh_house.abs_pos)
|
|
1327
|
+
template_dict["first_circle"] = draw_first_circle(
|
|
1328
|
+
self.main_radius,
|
|
1329
|
+
self.chart_colors_settings["zodiac_transit_ring_2"],
|
|
1330
|
+
self.chart_type,
|
|
1331
|
+
)
|
|
1332
|
+
template_dict["second_circle"] = draw_second_circle(
|
|
1333
|
+
self.main_radius,
|
|
1334
|
+
self.chart_colors_settings["zodiac_transit_ring_1"],
|
|
1335
|
+
self.chart_colors_settings["paper_1"],
|
|
1336
|
+
self.chart_type,
|
|
1337
|
+
)
|
|
1338
|
+
template_dict["third_circle"] = draw_third_circle(
|
|
1339
|
+
self.main_radius,
|
|
1340
|
+
self.chart_colors_settings["zodiac_transit_ring_0"],
|
|
1341
|
+
self.chart_colors_settings["paper_1"],
|
|
1342
|
+
self.chart_type,
|
|
1343
|
+
self.third_circle_radius,
|
|
1344
|
+
)
|
|
1345
|
+
|
|
1346
|
+
# Aspects
|
|
1347
|
+
if self.double_chart_aspect_grid_type == "list":
|
|
1348
|
+
title = self.language_settings.get("return_aspects", "Natal to Return Aspects")
|
|
1349
|
+
template_dict["makeAspectGrid"] = ""
|
|
1350
|
+
template_dict["makeDoubleChartAspectList"] = draw_transit_aspect_list(title, self.aspects_list, self.planets_settings, self.aspects_settings, max_columns=7)
|
|
1351
|
+
else:
|
|
1352
|
+
template_dict["makeAspectGrid"] = ""
|
|
1353
|
+
template_dict["makeDoubleChartAspectList"] = draw_transit_aspect_grid(
|
|
1354
|
+
self.chart_colors_settings["paper_0"],
|
|
1355
|
+
self.available_planets_setting,
|
|
1356
|
+
self.aspects_list,
|
|
1357
|
+
550,
|
|
1358
|
+
450,
|
|
1359
|
+
)
|
|
1360
|
+
|
|
1361
|
+
template_dict["makeAspects"] = self._draw_all_transit_aspects_lines(self.main_radius, self.main_radius - 160)
|
|
763
1362
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
second_subject_table_name = self.language_settings["transit_name"]
|
|
1363
|
+
# Chart title
|
|
1364
|
+
if self.second_obj.return_type == "Solar":
|
|
1365
|
+
template_dict["stringTitle"] = f"{self.first_obj.name} - {self.language_settings.get('solar_return', 'Solar Return')}"
|
|
768
1366
|
else:
|
|
769
|
-
|
|
1367
|
+
template_dict["stringTitle"] = f"{self.first_obj.name} - {self.language_settings.get('lunar_return', 'Lunar Return')}"
|
|
770
1368
|
|
|
1369
|
+
|
|
1370
|
+
# Top left section
|
|
1371
|
+
# Subject
|
|
1372
|
+
latitude_string = convert_latitude_coordinate_to_string(self.first_obj.lat, self.language_settings["north"], self.language_settings["south"]) # type: ignore
|
|
1373
|
+
longitude_string = convert_longitude_coordinate_to_string(self.first_obj.lng, self.language_settings["east"], self.language_settings["west"]) # type: ignore
|
|
1374
|
+
|
|
1375
|
+
# Return
|
|
1376
|
+
return_latitude_string = convert_latitude_coordinate_to_string(self.second_obj.lat, self.language_settings["north"], self.language_settings["south"]) # type: ignore
|
|
1377
|
+
return_longitude_string = convert_longitude_coordinate_to_string(self.second_obj.lng, self.language_settings["east"], self.language_settings["west"]) # type: ignore
|
|
1378
|
+
|
|
1379
|
+
if self.second_obj.return_type == "Solar":
|
|
1380
|
+
template_dict["top_left_0"] = f"{self.language_settings.get('solar_return', 'Solar Return')}:"
|
|
1381
|
+
else:
|
|
1382
|
+
template_dict["top_left_0"] = f"{self.language_settings.get('lunar_return', 'Lunar Return')}:"
|
|
1383
|
+
template_dict["top_left_1"] = format_datetime_with_timezone(self.second_obj.iso_formatted_local_datetime) # type: ignore
|
|
1384
|
+
template_dict["top_left_2"] = f"{return_latitude_string} / {return_longitude_string}"
|
|
1385
|
+
template_dict["top_left_3"] = f"{self.first_obj.name}"
|
|
1386
|
+
template_dict["top_left_4"] = format_datetime_with_timezone(self.first_obj.iso_formatted_local_datetime) # type: ignore
|
|
1387
|
+
template_dict["top_left_5"] = f"{latitude_string} / {longitude_string}"
|
|
1388
|
+
|
|
1389
|
+
# Bottom left section
|
|
1390
|
+
if self.first_obj.zodiac_type == "Tropic":
|
|
1391
|
+
zodiac_info = f"{self.language_settings.get('zodiac', 'Zodiac')}: {self.language_settings.get('tropical', 'Tropical')}"
|
|
1392
|
+
else:
|
|
1393
|
+
mode_const = "SIDM_" + self.first_obj.sidereal_mode # type: ignore
|
|
1394
|
+
mode_name = swe.get_ayanamsa_name(getattr(swe, mode_const))
|
|
1395
|
+
zodiac_info = f"{self.language_settings.get('ayanamsa', 'Ayanamsa')}: {mode_name}"
|
|
1396
|
+
|
|
1397
|
+
template_dict["bottom_left_0"] = zodiac_info
|
|
1398
|
+
template_dict["bottom_left_1"] = f"{self.language_settings.get('domification', 'Domification')}: {self.language_settings.get('houses_system_' + self.first_obj.houses_system_identifier, self.first_obj.houses_system_name)}"
|
|
1399
|
+
template_dict["bottom_left_2"] = f'{self.language_settings.get("lunation_day", "Lunation Day")}: {self.first_obj.lunar_phase.get("moon_phase", "")}'
|
|
1400
|
+
template_dict["bottom_left_3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get(self.first_obj.lunar_phase.moon_phase_name.lower().replace(" ", "_"), self.first_obj.lunar_phase.moon_phase_name)}'
|
|
1401
|
+
template_dict["bottom_left_4"] = f'{self.language_settings.get("perspective_type", "Perspective")}: {self.language_settings.get(self.first_obj.perspective_type.lower().replace(" ", "_"), self.first_obj.perspective_type)}'
|
|
1402
|
+
|
|
1403
|
+
# Moon phase section calculations
|
|
1404
|
+
template_dict["makeLunarPhase"] = makeLunarPhase(self.first_obj.lunar_phase["degrees_between_s_m"], self.geolat)
|
|
1405
|
+
|
|
1406
|
+
# Houses and planet drawing
|
|
1407
|
+
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
1408
|
+
main_subject_houses_list=first_subject_houses_list,
|
|
1409
|
+
secondary_subject_houses_list=second_subject_houses_list,
|
|
1410
|
+
chart_type=self.chart_type,
|
|
1411
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
1412
|
+
house_cusp_generale_name_label=self.language_settings["cusp"],
|
|
1413
|
+
)
|
|
1414
|
+
|
|
1415
|
+
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
1416
|
+
r=self.main_radius,
|
|
1417
|
+
first_subject_houses_list=first_subject_houses_list,
|
|
1418
|
+
standard_house_cusp_color=self.chart_colors_settings["houses_radix_line"],
|
|
1419
|
+
first_house_color=self.planets_settings[12]["color"],
|
|
1420
|
+
tenth_house_color=self.planets_settings[13]["color"],
|
|
1421
|
+
seventh_house_color=self.planets_settings[14]["color"],
|
|
1422
|
+
fourth_house_color=self.planets_settings[15]["color"],
|
|
1423
|
+
c1=self.first_circle_radius,
|
|
1424
|
+
c3=self.third_circle_radius,
|
|
1425
|
+
chart_type=self.chart_type,
|
|
1426
|
+
second_subject_houses_list=second_subject_houses_list,
|
|
1427
|
+
transit_house_cusp_color=self.chart_colors_settings["houses_transit_line"],
|
|
1428
|
+
)
|
|
1429
|
+
|
|
1430
|
+
template_dict["makePlanets"] = draw_planets(
|
|
1431
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
1432
|
+
available_planets_setting=self.available_planets_setting,
|
|
1433
|
+
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
1434
|
+
radius=self.main_radius,
|
|
1435
|
+
main_subject_first_house_degree_ut=self.first_obj.first_house.abs_pos,
|
|
1436
|
+
main_subject_seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
1437
|
+
chart_type=self.chart_type,
|
|
1438
|
+
third_circle_radius=self.third_circle_radius,
|
|
1439
|
+
)
|
|
1440
|
+
|
|
1441
|
+
# Planet grid
|
|
1442
|
+
if self.second_obj.return_type == "Solar":
|
|
1443
|
+
first_return_grid_title = f"{self.first_obj.name} ({self.language_settings.get('inner_wheel', 'Inner Wheel')})"
|
|
1444
|
+
second_return_grid_title = f"{self.language_settings.get('solar_return', 'Solar Return')} ({self.language_settings.get('outer_wheel', 'Outer Wheel')})"
|
|
1445
|
+
else:
|
|
1446
|
+
first_return_grid_title = f"{self.first_obj.name} ({self.language_settings.get('inner_wheel', 'Inner Wheel')})"
|
|
1447
|
+
second_return_grid_title = f"{self.language_settings.get("lunar_return", "Lunar Return")} ({self.language_settings.get("outer_wheel", "Outer Wheel")})"
|
|
771
1448
|
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
772
|
-
planets_and_houses_grid_title=
|
|
773
|
-
subject_name=
|
|
1449
|
+
planets_and_houses_grid_title="",
|
|
1450
|
+
subject_name=first_return_grid_title,
|
|
774
1451
|
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
775
1452
|
chart_type=self.chart_type,
|
|
776
1453
|
text_color=self.chart_colors_settings["paper_0"],
|
|
777
1454
|
celestial_point_language=self.language_settings["celestial_points"],
|
|
778
|
-
second_subject_name=
|
|
1455
|
+
second_subject_name=second_return_grid_title,
|
|
779
1456
|
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
780
1457
|
)
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
1458
|
+
|
|
1459
|
+
house_comparison_factory = HouseComparisonFactory(
|
|
1460
|
+
first_subject=self.first_obj,
|
|
1461
|
+
second_subject=self.second_obj,
|
|
1462
|
+
active_points=self.active_points,
|
|
1463
|
+
)
|
|
1464
|
+
house_comparison = house_comparison_factory.get_house_comparison()
|
|
1465
|
+
|
|
1466
|
+
template_dict["makeHouseComparisonGrid"] = draw_house_comparison_grid(
|
|
1467
|
+
house_comparison,
|
|
1468
|
+
celestial_point_language=self.language_settings["celestial_points"],
|
|
1469
|
+
active_points=self.active_points,
|
|
1470
|
+
points_owner_subject_number=2, # The second subject is the Solar Return
|
|
1471
|
+
house_position_comparison_label=self.language_settings.get("house_position_comparison", "House Position Comparison"),
|
|
1472
|
+
return_point_label=self.language_settings.get("return_point", "Return Point"),
|
|
1473
|
+
return_label=self.language_settings.get("Return", "Return"),
|
|
1474
|
+
radix_label=self.language_settings.get("Natal", "Natal"),
|
|
1475
|
+
)
|
|
1476
|
+
|
|
1477
|
+
elif self.chart_type == "SingleWheelReturn":
|
|
1478
|
+
# Set viewbox
|
|
1479
|
+
template_dict["viewbox"] = self._BASIC_CHART_VIEWBOX
|
|
1480
|
+
|
|
1481
|
+
# Rings and circles
|
|
1482
|
+
template_dict["transitRing"] = ""
|
|
1483
|
+
template_dict["degreeRing"] = draw_degree_ring(
|
|
1484
|
+
self.main_radius,
|
|
1485
|
+
self.first_circle_radius,
|
|
1486
|
+
self.first_obj.seventh_house.abs_pos,
|
|
1487
|
+
self.chart_colors_settings["paper_0"],
|
|
1488
|
+
)
|
|
1489
|
+
template_dict["first_circle"] = draw_first_circle(
|
|
1490
|
+
self.main_radius,
|
|
1491
|
+
self.chart_colors_settings["zodiac_radix_ring_2"],
|
|
1492
|
+
self.chart_type,
|
|
1493
|
+
self.first_circle_radius,
|
|
1494
|
+
)
|
|
1495
|
+
template_dict["second_circle"] = draw_second_circle(
|
|
1496
|
+
self.main_radius,
|
|
1497
|
+
self.chart_colors_settings["zodiac_radix_ring_1"],
|
|
1498
|
+
self.chart_colors_settings["paper_1"],
|
|
1499
|
+
self.chart_type,
|
|
1500
|
+
self.second_circle_radius,
|
|
1501
|
+
)
|
|
1502
|
+
template_dict["third_circle"] = draw_third_circle(
|
|
1503
|
+
self.main_radius,
|
|
1504
|
+
self.chart_colors_settings["zodiac_radix_ring_0"],
|
|
1505
|
+
self.chart_colors_settings["paper_1"],
|
|
1506
|
+
self.chart_type,
|
|
1507
|
+
self.third_circle_radius,
|
|
1508
|
+
)
|
|
1509
|
+
|
|
1510
|
+
# Aspects
|
|
1511
|
+
template_dict["makeDoubleChartAspectList"] = ""
|
|
1512
|
+
template_dict["makeAspectGrid"] = draw_aspect_grid(
|
|
1513
|
+
self.chart_colors_settings["paper_0"],
|
|
1514
|
+
self.available_planets_setting,
|
|
1515
|
+
self.aspects_list,
|
|
1516
|
+
)
|
|
1517
|
+
template_dict["makeAspects"] = self._draw_all_aspects_lines(self.main_radius, self.main_radius - self.third_circle_radius)
|
|
1518
|
+
|
|
1519
|
+
# Chart title
|
|
1520
|
+
template_dict["stringTitle"] = self.first_obj.name
|
|
1521
|
+
|
|
1522
|
+
# Top left section
|
|
1523
|
+
latitude_string = convert_latitude_coordinate_to_string(self.geolat, self.language_settings["north"], self.language_settings["south"])
|
|
1524
|
+
longitude_string = convert_longitude_coordinate_to_string(self.geolon, self.language_settings["east"], self.language_settings["west"])
|
|
1525
|
+
|
|
1526
|
+
template_dict["top_left_0"] = f'{self.language_settings["info"]}:'
|
|
1527
|
+
template_dict["top_left_1"] = format_datetime_with_timezone(self.first_obj.iso_formatted_local_datetime) # type: ignore
|
|
1528
|
+
template_dict["top_left_2"] = format_location_string(self.location)
|
|
1529
|
+
template_dict["top_left_3"] = f"{self.language_settings['latitude']}: {latitude_string}"
|
|
1530
|
+
template_dict["top_left_4"] = f"{self.language_settings['longitude']}: {longitude_string}"
|
|
1531
|
+
|
|
1532
|
+
if self.first_obj.return_type == "Solar":
|
|
1533
|
+
template_dict["top_left_5"] = f"{self.language_settings['type']}: {self.language_settings.get('solar_return', 'Solar Return')}"
|
|
784
1534
|
else:
|
|
785
|
-
|
|
1535
|
+
template_dict["top_left_5"] = f"{self.language_settings['type']}: {self.language_settings.get('lunar_return', 'Lunar Return')}"
|
|
1536
|
+
|
|
1537
|
+
# Bottom left section
|
|
1538
|
+
if self.first_obj.zodiac_type == "Tropic":
|
|
1539
|
+
zodiac_info = f"{self.language_settings.get('zodiac', 'Zodiac')}: {self.language_settings.get('tropical', 'Tropical')}"
|
|
1540
|
+
else:
|
|
1541
|
+
mode_const = "SIDM_" + self.first_obj.sidereal_mode # type: ignore
|
|
1542
|
+
mode_name = swe.get_ayanamsa_name(getattr(swe, mode_const))
|
|
1543
|
+
zodiac_info = f"{self.language_settings.get('ayanamsa', 'Ayanamsa')}: {mode_name}"
|
|
1544
|
+
|
|
1545
|
+
template_dict["bottom_left_0"] = zodiac_info
|
|
1546
|
+
template_dict["bottom_left_1"] = f"{self.language_settings.get('houses_system_' + self.first_obj.houses_system_identifier, self.first_obj.houses_system_name)} {self.language_settings.get('houses', 'Houses')}"
|
|
1547
|
+
template_dict["bottom_left_2"] = f'{self.language_settings.get("lunation_day", "Lunation Day")}: {self.first_obj.lunar_phase.get("moon_phase", "")}'
|
|
1548
|
+
template_dict["bottom_left_3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get(self.first_obj.lunar_phase.moon_phase_name.lower().replace(" ", "_"), self.first_obj.lunar_phase.moon_phase_name)}'
|
|
1549
|
+
template_dict["bottom_left_4"] = f'{self.language_settings.get("perspective_type", "Perspective")}: {self.language_settings.get(self.first_obj.perspective_type.lower().replace(" ", "_"), self.first_obj.perspective_type)}'
|
|
1550
|
+
|
|
1551
|
+
# Moon phase section calculations
|
|
1552
|
+
template_dict["makeLunarPhase"] = makeLunarPhase(self.first_obj.lunar_phase["degrees_between_s_m"], self.geolat)
|
|
1553
|
+
|
|
1554
|
+
# Houses and planet drawing
|
|
1555
|
+
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
1556
|
+
main_subject_houses_list=first_subject_houses_list,
|
|
1557
|
+
chart_type=self.chart_type,
|
|
1558
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
1559
|
+
house_cusp_generale_name_label=self.language_settings["cusp"],
|
|
1560
|
+
)
|
|
1561
|
+
|
|
1562
|
+
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
1563
|
+
r=self.main_radius,
|
|
1564
|
+
first_subject_houses_list=first_subject_houses_list,
|
|
1565
|
+
standard_house_cusp_color=self.chart_colors_settings["houses_radix_line"],
|
|
1566
|
+
first_house_color=self.planets_settings[12]["color"],
|
|
1567
|
+
tenth_house_color=self.planets_settings[13]["color"],
|
|
1568
|
+
seventh_house_color=self.planets_settings[14]["color"],
|
|
1569
|
+
fourth_house_color=self.planets_settings[15]["color"],
|
|
1570
|
+
c1=self.first_circle_radius,
|
|
1571
|
+
c3=self.third_circle_radius,
|
|
1572
|
+
chart_type=self.chart_type,
|
|
1573
|
+
)
|
|
1574
|
+
|
|
1575
|
+
template_dict["makePlanets"] = draw_planets(
|
|
1576
|
+
available_planets_setting=self.available_planets_setting,
|
|
1577
|
+
chart_type=self.chart_type,
|
|
1578
|
+
radius=self.main_radius,
|
|
1579
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
1580
|
+
third_circle_radius=self.third_circle_radius,
|
|
1581
|
+
main_subject_first_house_degree_ut=self.first_obj.first_house.abs_pos,
|
|
1582
|
+
main_subject_seventh_house_degree_ut=self.first_obj.seventh_house.abs_pos,
|
|
1583
|
+
)
|
|
786
1584
|
|
|
787
1585
|
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
788
1586
|
planets_and_houses_grid_title=self.language_settings["planets_and_house"],
|
|
789
|
-
subject_name=
|
|
1587
|
+
subject_name=self.first_obj.name,
|
|
790
1588
|
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
791
1589
|
chart_type=self.chart_type,
|
|
792
1590
|
text_color=self.chart_colors_settings["paper_0"],
|
|
793
1591
|
celestial_point_language=self.language_settings["celestial_points"],
|
|
794
1592
|
)
|
|
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}"
|
|
1593
|
+
template_dict["makeHouseComparisonGrid"] = ""
|
|
807
1594
|
|
|
808
1595
|
return ChartTemplateDictionary(**template_dict)
|
|
809
1596
|
|
|
810
|
-
def makeTemplate(self, minify: bool = False, remove_css_variables
|
|
1597
|
+
def makeTemplate(self, minify: bool = False, remove_css_variables=False) -> str:
|
|
811
1598
|
"""
|
|
812
1599
|
Render the full chart SVG as a string.
|
|
813
1600
|
|
|
@@ -840,14 +1627,14 @@ class KerykeionChartSVG:
|
|
|
840
1627
|
template = inline_css_variables_in_svg(template)
|
|
841
1628
|
|
|
842
1629
|
if minify:
|
|
843
|
-
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
1630
|
+
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t", "").replace(" ", "").replace(" ", "")
|
|
844
1631
|
|
|
845
1632
|
else:
|
|
846
1633
|
template = template.replace('"', "'")
|
|
847
1634
|
|
|
848
1635
|
return template
|
|
849
1636
|
|
|
850
|
-
def makeSVG(self, minify: bool = False, remove_css_variables
|
|
1637
|
+
def makeSVG(self, minify: bool = False, remove_css_variables=False):
|
|
851
1638
|
"""
|
|
852
1639
|
Generate and save the full chart SVG to disk.
|
|
853
1640
|
|
|
@@ -864,14 +1651,19 @@ class KerykeionChartSVG:
|
|
|
864
1651
|
|
|
865
1652
|
self.template = self.makeTemplate(minify, remove_css_variables)
|
|
866
1653
|
|
|
867
|
-
|
|
1654
|
+
if self.chart_type == "Return" and self.second_obj.return_type == "Lunar":
|
|
1655
|
+
chartname = self.output_directory / f"{self.first_obj.name} - {self.chart_type} Chart - Lunar Return.svg"
|
|
1656
|
+
elif self.chart_type == "Return" and self.second_obj.return_type == "Solar":
|
|
1657
|
+
chartname = self.output_directory / f"{self.first_obj.name} - {self.chart_type} Chart - Solar Return.svg"
|
|
1658
|
+
else:
|
|
1659
|
+
chartname = self.output_directory / f"{self.first_obj.name} - {self.chart_type} Chart.svg"
|
|
868
1660
|
|
|
869
1661
|
with open(chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
870
1662
|
output_file.write(self.template)
|
|
871
1663
|
|
|
872
1664
|
print(f"SVG Generated Correctly in: {chartname}")
|
|
873
1665
|
|
|
874
|
-
def makeWheelOnlyTemplate(self, minify: bool = False, remove_css_variables
|
|
1666
|
+
def makeWheelOnlyTemplate(self, minify: bool = False, remove_css_variables=False):
|
|
875
1667
|
"""
|
|
876
1668
|
Render the wheel-only chart SVG as a string.
|
|
877
1669
|
|
|
@@ -886,7 +1678,12 @@ class KerykeionChartSVG:
|
|
|
886
1678
|
str: SVG markup for the chart wheel only.
|
|
887
1679
|
"""
|
|
888
1680
|
|
|
889
|
-
with open(
|
|
1681
|
+
with open(
|
|
1682
|
+
Path(__file__).parent / "templates" / "wheel_only.xml",
|
|
1683
|
+
"r",
|
|
1684
|
+
encoding="utf-8",
|
|
1685
|
+
errors="ignore",
|
|
1686
|
+
) as f:
|
|
890
1687
|
template = f.read()
|
|
891
1688
|
|
|
892
1689
|
template_dict = self._create_template_dictionary()
|
|
@@ -896,14 +1693,14 @@ class KerykeionChartSVG:
|
|
|
896
1693
|
template = inline_css_variables_in_svg(template)
|
|
897
1694
|
|
|
898
1695
|
if minify:
|
|
899
|
-
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
1696
|
+
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t", "").replace(" ", "").replace(" ", "")
|
|
900
1697
|
|
|
901
1698
|
else:
|
|
902
1699
|
template = template.replace('"', "'")
|
|
903
1700
|
|
|
904
1701
|
return template
|
|
905
1702
|
|
|
906
|
-
def makeWheelOnlySVG(self, minify: bool = False, remove_css_variables
|
|
1703
|
+
def makeWheelOnlySVG(self, minify: bool = False, remove_css_variables=False):
|
|
907
1704
|
"""
|
|
908
1705
|
Generate and save wheel-only chart SVG to disk.
|
|
909
1706
|
|
|
@@ -919,14 +1716,14 @@ class KerykeionChartSVG:
|
|
|
919
1716
|
"""
|
|
920
1717
|
|
|
921
1718
|
template = self.makeWheelOnlyTemplate(minify, remove_css_variables)
|
|
922
|
-
chartname = self.output_directory / f"{self.
|
|
1719
|
+
chartname = self.output_directory / f"{self.first_obj.name} - {self.chart_type} Chart - Wheel Only.svg"
|
|
923
1720
|
|
|
924
1721
|
with open(chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
925
1722
|
output_file.write(template)
|
|
926
1723
|
|
|
927
1724
|
print(f"SVG Generated Correctly in: {chartname}")
|
|
928
1725
|
|
|
929
|
-
def makeAspectGridOnlyTemplate(self, minify: bool = False, remove_css_variables
|
|
1726
|
+
def makeAspectGridOnlyTemplate(self, minify: bool = False, remove_css_variables=False):
|
|
930
1727
|
"""
|
|
931
1728
|
Render the aspect-grid-only chart SVG as a string.
|
|
932
1729
|
|
|
@@ -941,15 +1738,30 @@ class KerykeionChartSVG:
|
|
|
941
1738
|
str: SVG markup for the aspect grid only.
|
|
942
1739
|
"""
|
|
943
1740
|
|
|
944
|
-
with open(
|
|
1741
|
+
with open(
|
|
1742
|
+
Path(__file__).parent / "templates" / "aspect_grid_only.xml",
|
|
1743
|
+
"r",
|
|
1744
|
+
encoding="utf-8",
|
|
1745
|
+
errors="ignore",
|
|
1746
|
+
) as f:
|
|
945
1747
|
template = f.read()
|
|
946
1748
|
|
|
947
1749
|
template_dict = self._create_template_dictionary()
|
|
948
1750
|
|
|
949
|
-
if self.chart_type in ["Transit", "Synastry"]:
|
|
950
|
-
aspects_grid = draw_transit_aspect_grid(
|
|
1751
|
+
if self.chart_type in ["Transit", "Synastry", "Return"]:
|
|
1752
|
+
aspects_grid = draw_transit_aspect_grid(
|
|
1753
|
+
self.chart_colors_settings["paper_0"],
|
|
1754
|
+
self.available_planets_setting,
|
|
1755
|
+
self.aspects_list,
|
|
1756
|
+
)
|
|
951
1757
|
else:
|
|
952
|
-
aspects_grid = draw_aspect_grid(
|
|
1758
|
+
aspects_grid = draw_aspect_grid(
|
|
1759
|
+
self.chart_colors_settings["paper_0"],
|
|
1760
|
+
self.available_planets_setting,
|
|
1761
|
+
self.aspects_list,
|
|
1762
|
+
x_start=50,
|
|
1763
|
+
y_start=250,
|
|
1764
|
+
)
|
|
953
1765
|
|
|
954
1766
|
template = Template(template).substitute({**template_dict, "makeAspectGrid": aspects_grid})
|
|
955
1767
|
|
|
@@ -957,14 +1769,14 @@ class KerykeionChartSVG:
|
|
|
957
1769
|
template = inline_css_variables_in_svg(template)
|
|
958
1770
|
|
|
959
1771
|
if minify:
|
|
960
|
-
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
1772
|
+
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t", "").replace(" ", "").replace(" ", "")
|
|
961
1773
|
|
|
962
1774
|
else:
|
|
963
1775
|
template = template.replace('"', "'")
|
|
964
1776
|
|
|
965
1777
|
return template
|
|
966
1778
|
|
|
967
|
-
def makeAspectGridOnlySVG(self, minify: bool = False, remove_css_variables
|
|
1779
|
+
def makeAspectGridOnlySVG(self, minify: bool = False, remove_css_variables=False):
|
|
968
1780
|
"""
|
|
969
1781
|
Generate and save aspect-grid-only chart SVG to disk.
|
|
970
1782
|
|
|
@@ -980,240 +1792,125 @@ class KerykeionChartSVG:
|
|
|
980
1792
|
"""
|
|
981
1793
|
|
|
982
1794
|
template = self.makeAspectGridOnlyTemplate(minify, remove_css_variables)
|
|
983
|
-
chartname = self.output_directory / f"{self.
|
|
1795
|
+
chartname = self.output_directory / f"{self.first_obj.name} - {self.chart_type} Chart - Aspect Grid Only.svg"
|
|
984
1796
|
|
|
985
1797
|
with open(chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
986
1798
|
output_file.write(template)
|
|
987
1799
|
|
|
988
1800
|
print(f"SVG Generated Correctly in: {chartname}")
|
|
989
1801
|
|
|
1802
|
+
|
|
990
1803
|
if __name__ == "__main__":
|
|
991
1804
|
from kerykeion.utilities import setup_logging
|
|
992
|
-
from kerykeion.
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
#
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
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()
|
|
1805
|
+
from kerykeion.planetary_return_factory import PlanetaryReturnFactory
|
|
1806
|
+
from kerykeion.astrological_subject_factory import AstrologicalSubjectFactory
|
|
1807
|
+
|
|
1808
|
+
setup_logging(level="info")
|
|
1809
|
+
|
|
1810
|
+
subject = AstrologicalSubjectFactory.from_birth_data("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1811
|
+
|
|
1812
|
+
return_factory = PlanetaryReturnFactory(
|
|
1813
|
+
subject,
|
|
1814
|
+
city="Los Angeles",
|
|
1815
|
+
nation="US",
|
|
1816
|
+
lng=-118.2437,
|
|
1817
|
+
lat=34.0522,
|
|
1818
|
+
tz_str="America/Los_Angeles",
|
|
1819
|
+
altitude=0,
|
|
1820
|
+
)
|
|
1821
|
+
|
|
1822
|
+
###
|
|
1823
|
+
## Birth Chart
|
|
1824
|
+
birth_chart = KerykeionChartSVG(
|
|
1825
|
+
first_obj=subject,
|
|
1826
|
+
chart_language="IT",
|
|
1827
|
+
theme="strawberry",
|
|
1828
|
+
)
|
|
1829
|
+
birth_chart.makeSVG() # minify=True, remove_css_variables=True)
|
|
1830
|
+
|
|
1831
|
+
###
|
|
1832
|
+
## Solar Return Chart
|
|
1833
|
+
solar_return = return_factory.next_return_from_iso_formatted_time(
|
|
1834
|
+
"2025-01-09T18:30:00+01:00", # UTC+1
|
|
1835
|
+
return_type="Solar",
|
|
1836
|
+
)
|
|
1837
|
+
solar_return_chart = KerykeionChartSVG(
|
|
1838
|
+
first_obj=subject, chart_type="Return",
|
|
1839
|
+
second_obj=solar_return,
|
|
1840
|
+
chart_language="IT",
|
|
1841
|
+
theme="classic",
|
|
1842
|
+
active_points=["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Ascendant"],
|
|
1843
|
+
)
|
|
1844
|
+
|
|
1845
|
+
solar_return_chart.makeSVG() # minify=True, remove_css_variables=True)
|
|
1846
|
+
|
|
1847
|
+
###
|
|
1848
|
+
## Single wheel return
|
|
1849
|
+
single_wheel_return_chart = KerykeionChartSVG(
|
|
1850
|
+
first_obj=solar_return,
|
|
1851
|
+
chart_type="SingleWheelReturn",
|
|
1852
|
+
second_obj=solar_return,
|
|
1853
|
+
chart_language="IT",
|
|
1854
|
+
theme="dark",
|
|
1855
|
+
active_points=["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn"],
|
|
1856
|
+
)
|
|
1857
|
+
|
|
1858
|
+
single_wheel_return_chart.makeSVG() # minify=True, remove_css_variables=True)
|
|
1859
|
+
|
|
1860
|
+
###
|
|
1861
|
+
## Lunar return
|
|
1862
|
+
lunar_return = return_factory.next_return_from_iso_formatted_time(
|
|
1863
|
+
"2025-01-09T18:30:00+01:00", # UTC+1
|
|
1864
|
+
return_type="Lunar",
|
|
1865
|
+
)
|
|
1866
|
+
lunar_return_chart = KerykeionChartSVG(
|
|
1867
|
+
first_obj=subject,
|
|
1868
|
+
chart_type="Return",
|
|
1869
|
+
second_obj=lunar_return,
|
|
1870
|
+
chart_language="IT",
|
|
1871
|
+
theme="dark",
|
|
1872
|
+
active_points=["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn"],
|
|
1873
|
+
)
|
|
1874
|
+
lunar_return_chart.makeSVG() # minify=True, remove_css_variables=True)
|
|
1875
|
+
|
|
1876
|
+
###
|
|
1877
|
+
## Transit Chart
|
|
1878
|
+
transit = AstrologicalSubjectFactory.from_current_time()
|
|
1879
|
+
transit_chart = KerykeionChartSVG(
|
|
1880
|
+
first_obj=subject,
|
|
1881
|
+
chart_type="Transit",
|
|
1882
|
+
second_obj=transit,
|
|
1883
|
+
chart_language="IT",
|
|
1884
|
+
theme="dark",
|
|
1885
|
+
active_points=["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Ascendant"]
|
|
1886
|
+
)
|
|
1887
|
+
transit_chart.makeSVG() # minify=True, remove_css_variables=True)
|
|
1888
|
+
|
|
1889
|
+
###
|
|
1890
|
+
## Synastry Chart
|
|
1891
|
+
second_subject = AstrologicalSubjectFactory.from_birth_data("Yoko Ono", 1933, 2, 18, 18, 30, "Tokyo", "JP")
|
|
1892
|
+
synastry_chart = KerykeionChartSVG(
|
|
1893
|
+
first_obj=subject,
|
|
1894
|
+
chart_type="Synastry",
|
|
1895
|
+
second_obj=second_subject,
|
|
1896
|
+
chart_language="IT",
|
|
1897
|
+
theme="dark",
|
|
1898
|
+
active_points=["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn"],
|
|
1899
|
+
)
|
|
1900
|
+
synastry_chart.makeSVG() # minify=True, remove_css_variables=True)
|
|
1901
|
+
|
|
1902
|
+
##
|
|
1903
|
+
# Transit Chart with Grid
|
|
1904
|
+
subject.name = "Grid"
|
|
1905
|
+
transit_chart_with_grid = KerykeionChartSVG(
|
|
1906
|
+
first_obj=subject,
|
|
1907
|
+
chart_type="Transit",
|
|
1908
|
+
second_obj=transit,
|
|
1909
|
+
chart_language="IT",
|
|
1910
|
+
theme="dark",
|
|
1911
|
+
active_points=["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Ascendant"],
|
|
1912
|
+
double_chart_aspect_grid_type="table"
|
|
1913
|
+
)
|
|
1914
|
+
transit_chart_with_grid.makeSVG() # minify=True, remove_css_variables=True)
|
|
1915
|
+
transit_chart_with_grid.makeAspectGridOnlySVG()
|
|
1916
|
+
transit_chart_with_grid.makeWheelOnlySVG()
|