kerykeion 4.12.3__py3-none-any.whl → 4.18.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kerykeion might be problematic. Click here for more details.
- kerykeion/__init__.py +3 -1
- kerykeion/aspects/aspects_utils.py +40 -123
- kerykeion/aspects/natal_aspects.py +34 -25
- kerykeion/aspects/synastry_aspects.py +34 -28
- kerykeion/astrological_subject.py +199 -196
- kerykeion/charts/charts_utils.py +701 -62
- kerykeion/charts/draw_planets.py +407 -0
- kerykeion/charts/kerykeion_chart_svg.py +534 -1140
- kerykeion/charts/templates/aspect_grid_only.xml +452 -0
- kerykeion/charts/templates/chart.xml +88 -70
- kerykeion/charts/templates/wheel_only.xml +499 -0
- kerykeion/charts/themes/classic.css +82 -0
- kerykeion/charts/themes/dark-high-contrast.css +121 -0
- kerykeion/charts/themes/dark.css +121 -0
- kerykeion/charts/themes/light.css +117 -0
- kerykeion/enums.py +1 -0
- kerykeion/ephemeris_data.py +178 -0
- kerykeion/fetch_geonames.py +2 -3
- kerykeion/kr_types/chart_types.py +6 -16
- kerykeion/kr_types/kr_literals.py +12 -3
- kerykeion/kr_types/kr_models.py +77 -32
- kerykeion/kr_types/settings_models.py +4 -10
- kerykeion/relationship_score/__init__.py +2 -0
- kerykeion/relationship_score/relationship_score.py +175 -0
- kerykeion/relationship_score/relationship_score_factory.py +275 -0
- kerykeion/report.py +6 -3
- kerykeion/settings/kerykeion_settings.py +6 -1
- kerykeion/settings/kr.config.json +256 -102
- kerykeion/utilities.py +122 -217
- {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/METADATA +40 -10
- kerykeion-4.18.0.dist-info/RECORD +42 -0
- kerykeion/relationship_score.py +0 -205
- kerykeion-4.12.3.dist-info/RECORD +0 -32
- {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/LICENSE +0 -0
- {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/WHEEL +0 -0
- {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/entry_points.txt +0 -0
|
@@ -5,38 +5,46 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
import logging
|
|
8
|
+
from typing import get_args
|
|
8
9
|
|
|
9
10
|
from kerykeion.settings.kerykeion_settings import get_settings
|
|
10
11
|
from kerykeion.aspects.synastry_aspects import SynastryAspects
|
|
11
12
|
from kerykeion.aspects.natal_aspects import NatalAspects
|
|
12
13
|
from kerykeion.astrological_subject import AstrologicalSubject
|
|
13
|
-
from kerykeion.kr_types import KerykeionException, ChartType
|
|
14
|
+
from kerykeion.kr_types import KerykeionException, ChartType, KerykeionPointModel, Sign
|
|
14
15
|
from kerykeion.kr_types import ChartTemplateDictionary
|
|
15
|
-
from kerykeion.kr_types.
|
|
16
|
+
from kerykeion.kr_types.kr_models import AstrologicalSubjectModel
|
|
17
|
+
from kerykeion.kr_types.settings_models import KerykeionSettingsCelestialPointModel, KerykeionSettingsModel
|
|
18
|
+
from kerykeion.kr_types.kr_literals import KerykeionChartTheme
|
|
16
19
|
from kerykeion.charts.charts_utils import (
|
|
17
|
-
degreeDiff,
|
|
18
|
-
sliceToX,
|
|
19
|
-
sliceToY,
|
|
20
20
|
draw_zodiac_slice,
|
|
21
21
|
convert_latitude_coordinate_to_string,
|
|
22
22
|
convert_longitude_coordinate_to_string,
|
|
23
23
|
draw_aspect_line,
|
|
24
24
|
draw_elements_percentages,
|
|
25
|
-
convert_decimal_to_degree_string,
|
|
26
25
|
draw_transit_ring_degree_steps,
|
|
27
26
|
draw_degree_ring,
|
|
28
27
|
draw_transit_ring,
|
|
29
28
|
draw_first_circle,
|
|
30
|
-
draw_second_circle
|
|
29
|
+
draw_second_circle,
|
|
30
|
+
draw_third_circle,
|
|
31
|
+
draw_aspect_grid,
|
|
32
|
+
draw_houses_cusps_and_text_number,
|
|
33
|
+
draw_transit_aspect_list,
|
|
34
|
+
draw_transit_aspect_grid,
|
|
35
|
+
draw_moon_phase,
|
|
36
|
+
draw_house_grid,
|
|
37
|
+
draw_planet_grid,
|
|
31
38
|
)
|
|
39
|
+
from kerykeion.charts.draw_planets import draw_planets # type: ignore
|
|
40
|
+
from kerykeion.utilities import get_houses_list
|
|
32
41
|
from pathlib import Path
|
|
33
42
|
from scour.scour import scourString
|
|
34
43
|
from string import Template
|
|
35
|
-
from typing import Union, List
|
|
44
|
+
from typing import Union, List, Literal
|
|
36
45
|
from datetime import datetime
|
|
37
46
|
|
|
38
47
|
|
|
39
|
-
|
|
40
48
|
class KerykeionChartSVG:
|
|
41
49
|
"""
|
|
42
50
|
Creates the instance that can generate the chart with the
|
|
@@ -49,19 +57,26 @@ class KerykeionChartSVG:
|
|
|
49
57
|
- new_output_directory: Set the output directory (default: home directory).
|
|
50
58
|
- new_settings_file: Set the settings file (default: kr.config.json).
|
|
51
59
|
In the settings file you can set the language, colors, planets, aspects, etc.
|
|
60
|
+
- theme: Set the theme for the chart (default: classic). If None the <style> tag will be empty.
|
|
61
|
+
That's useful if you want to use your own CSS file customizing the value of the default theme variables.
|
|
62
|
+
- double_chart_aspect_grid_type: Set the type of the aspect grid for the double chart (transit or synastry). (Default: list.)
|
|
63
|
+
- chart_language: Set the language for the chart (default: EN).
|
|
52
64
|
"""
|
|
53
65
|
|
|
54
66
|
# Constants
|
|
67
|
+
_BASIC_CHART_VIEWBOX = "0 0 772.2 546.0"
|
|
68
|
+
_WIDE_CHART_VIEWBOX = "0 0 1060 546.0"
|
|
55
69
|
_DEFAULT_HEIGHT = 546.0
|
|
56
70
|
_DEFAULT_FULL_WIDTH = 1200
|
|
57
71
|
_DEFAULT_NATAL_WIDTH = 772.2
|
|
72
|
+
_PLANET_IN_ZODIAC_EXTRA_POINTS = 10
|
|
58
73
|
|
|
59
74
|
# Set at init
|
|
60
|
-
first_obj: AstrologicalSubject
|
|
61
|
-
second_obj: Union[AstrologicalSubject, None]
|
|
75
|
+
first_obj: Union[AstrologicalSubject, AstrologicalSubjectModel]
|
|
76
|
+
second_obj: Union[AstrologicalSubject, AstrologicalSubjectModel, None]
|
|
62
77
|
chart_type: ChartType
|
|
63
78
|
new_output_directory: Union[Path, None]
|
|
64
|
-
new_settings_file: Union[Path, None]
|
|
79
|
+
new_settings_file: Union[Path, None, KerykeionSettingsModel, dict]
|
|
65
80
|
output_directory: Path
|
|
66
81
|
|
|
67
82
|
# Internal properties
|
|
@@ -69,58 +84,43 @@ class KerykeionChartSVG:
|
|
|
69
84
|
earth: float
|
|
70
85
|
air: float
|
|
71
86
|
water: float
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
xml_svg: Path
|
|
87
|
+
main_radius: float
|
|
88
|
+
first_circle_radius: float
|
|
89
|
+
second_circle_radius: float
|
|
90
|
+
third_circle_radius: float
|
|
77
91
|
width: Union[float, int]
|
|
78
92
|
language_settings: dict
|
|
79
93
|
chart_colors_settings: dict
|
|
80
94
|
planets_settings: dict
|
|
81
95
|
aspects_settings: dict
|
|
82
|
-
|
|
83
|
-
chart_settings: dict
|
|
84
|
-
user: AstrologicalSubject
|
|
96
|
+
user: Union[AstrologicalSubject, AstrologicalSubjectModel]
|
|
85
97
|
available_planets_setting: List[KerykeionSettingsCelestialPointModel]
|
|
86
|
-
transit_ring_exclude_points_names: List[str]
|
|
87
|
-
points_deg_ut: list
|
|
88
|
-
points_deg: list
|
|
89
|
-
points_sign: list
|
|
90
|
-
points_retrograde: list
|
|
91
|
-
houses_sign_graph: list
|
|
92
|
-
t_points_deg_ut: list
|
|
93
|
-
t_points_deg: list
|
|
94
|
-
t_points_sign: list
|
|
95
|
-
t_points_retrograde: list
|
|
96
|
-
t_houses_sign_graph: list
|
|
97
98
|
height: float
|
|
98
99
|
location: str
|
|
99
100
|
geolat: float
|
|
100
101
|
geolon: float
|
|
101
|
-
zoom: int
|
|
102
|
-
zodiac: tuple
|
|
103
102
|
template: str
|
|
104
103
|
|
|
105
104
|
def __init__(
|
|
106
105
|
self,
|
|
107
|
-
first_obj: AstrologicalSubject,
|
|
106
|
+
first_obj: Union[AstrologicalSubject, AstrologicalSubjectModel],
|
|
108
107
|
chart_type: ChartType = "Natal",
|
|
109
|
-
second_obj: Union[AstrologicalSubject, None] = None,
|
|
108
|
+
second_obj: Union[AstrologicalSubject, AstrologicalSubjectModel, None] = None,
|
|
110
109
|
new_output_directory: Union[str, None] = None,
|
|
111
|
-
new_settings_file: Union[Path, None] = None,
|
|
110
|
+
new_settings_file: Union[Path, None, KerykeionSettingsModel, dict] = None,
|
|
111
|
+
theme: Union[KerykeionChartTheme, None] = "classic",
|
|
112
|
+
double_chart_aspect_grid_type: Literal["list", "table"] = "list",
|
|
113
|
+
chart_language: str = "EN",
|
|
112
114
|
):
|
|
113
115
|
# Directories:
|
|
114
|
-
|
|
115
|
-
self.homedir = Path.home()
|
|
116
|
+
home_directory = Path.home()
|
|
116
117
|
self.new_settings_file = new_settings_file
|
|
118
|
+
self.chart_language = chart_language
|
|
117
119
|
|
|
118
120
|
if new_output_directory:
|
|
119
121
|
self.output_directory = Path(new_output_directory)
|
|
120
122
|
else:
|
|
121
|
-
self.output_directory =
|
|
122
|
-
|
|
123
|
-
self.xml_svg = DATA_DIR / "templates/chart.xml"
|
|
123
|
+
self.output_directory = home_directory
|
|
124
124
|
|
|
125
125
|
self.parse_json_settings(new_settings_file)
|
|
126
126
|
self.chart_type = chart_type
|
|
@@ -135,58 +135,20 @@ class KerykeionChartSVG:
|
|
|
135
135
|
|
|
136
136
|
self.available_planets_setting.append(body)
|
|
137
137
|
|
|
138
|
-
# House cusp points are excluded from the transit ring.
|
|
139
|
-
self.transit_ring_exclude_points_names = [
|
|
140
|
-
"First_House",
|
|
141
|
-
"Second_House",
|
|
142
|
-
"Third_House",
|
|
143
|
-
"Fourth_House",
|
|
144
|
-
"Fifth_House",
|
|
145
|
-
"Sixth_House",
|
|
146
|
-
"Seventh_House",
|
|
147
|
-
"Eighth_House",
|
|
148
|
-
"Ninth_House",
|
|
149
|
-
"Tenth_House",
|
|
150
|
-
"Eleventh_House",
|
|
151
|
-
"Twelfth_House"
|
|
152
|
-
]
|
|
153
|
-
|
|
154
138
|
# Available bodies
|
|
155
|
-
|
|
139
|
+
available_celestial_points_names = []
|
|
156
140
|
for body in self.available_planets_setting:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
# Make a list for the absolute degrees of the points of the graphic.
|
|
160
|
-
self.points_deg_ut = []
|
|
161
|
-
for planet in available_celestial_points:
|
|
162
|
-
self.points_deg_ut.append(self.user.get(planet).abs_pos)
|
|
163
|
-
|
|
164
|
-
# Make a list of the relative degrees of the points in the graphic.
|
|
165
|
-
self.points_deg = []
|
|
166
|
-
for planet in available_celestial_points:
|
|
167
|
-
self.points_deg.append(self.user.get(planet).position)
|
|
168
|
-
|
|
169
|
-
# Make list of the points sign
|
|
170
|
-
self.points_sign = []
|
|
171
|
-
for planet in available_celestial_points:
|
|
172
|
-
self.points_sign.append(self.user.get(planet).sign_num)
|
|
141
|
+
available_celestial_points_names.append(body["name"].lower())
|
|
173
142
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
self.points_retrograde.append(self.user.get(planet).retrograde)
|
|
143
|
+
self.available_kerykeion_celestial_points: list[KerykeionPointModel] = []
|
|
144
|
+
for body in available_celestial_points_names:
|
|
145
|
+
self.available_kerykeion_celestial_points.append(self.user.get(body))
|
|
178
146
|
|
|
179
147
|
# Makes the sign number list.
|
|
180
|
-
|
|
181
|
-
self.houses_sign_graph = []
|
|
182
|
-
for h in self.user.houses_list:
|
|
183
|
-
self.houses_sign_graph.append(h["sign_num"])
|
|
184
|
-
|
|
185
148
|
if self.chart_type == "Natal" or self.chart_type == "ExternalNatal":
|
|
186
149
|
natal_aspects_instance = NatalAspects(self.user, new_settings_file=self.new_settings_file)
|
|
187
150
|
self.aspects_list = natal_aspects_instance.relevant_aspects
|
|
188
151
|
|
|
189
|
-
# TODO: If not second should exit
|
|
190
152
|
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
191
153
|
if not second_obj:
|
|
192
154
|
raise KerykeionException("Second object is required for Transit or Synastry charts.")
|
|
@@ -194,29 +156,15 @@ class KerykeionChartSVG:
|
|
|
194
156
|
# Kerykeion instance
|
|
195
157
|
self.t_user = second_obj
|
|
196
158
|
|
|
197
|
-
#
|
|
198
|
-
self.
|
|
199
|
-
for planet in available_celestial_points:
|
|
200
|
-
self.t_points_deg_ut.append(self.t_user.get(planet).abs_pos)
|
|
201
|
-
|
|
202
|
-
# Make a list of the relative degrees of the points in the graphic.
|
|
203
|
-
self.t_points_deg = []
|
|
204
|
-
for planet in available_celestial_points:
|
|
205
|
-
self.t_points_deg.append(self.t_user.get(planet).position)
|
|
159
|
+
# Aspects
|
|
160
|
+
self.aspects_list = SynastryAspects(self.user, self.t_user, new_settings_file=self.new_settings_file).relevant_aspects
|
|
206
161
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
self.t_points_sign.append(self.t_user.get(planet).sign_num)
|
|
162
|
+
self.t_available_kerykeion_celestial_points = []
|
|
163
|
+
for body in available_celestial_points_names:
|
|
164
|
+
self.t_available_kerykeion_celestial_points.append(self.t_user.get(body))
|
|
211
165
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
for planet in available_celestial_points:
|
|
215
|
-
self.t_points_retrograde.append(self.t_user.get(planet).retrograde)
|
|
216
|
-
|
|
217
|
-
self.t_houses_sign_graph = []
|
|
218
|
-
for h in self.t_user.houses_list:
|
|
219
|
-
self.t_houses_sign_graph.append(h["sign_num"])
|
|
166
|
+
# Double chart aspect grid type
|
|
167
|
+
self.double_chart_aspect_grid_type = double_chart_aspect_grid_type
|
|
220
168
|
|
|
221
169
|
# screen size
|
|
222
170
|
self.height = self._DEFAULT_HEIGHT
|
|
@@ -230,31 +178,45 @@ class KerykeionChartSVG:
|
|
|
230
178
|
self.geolat = self.user.lat
|
|
231
179
|
self.geolon = self.user.lng
|
|
232
180
|
|
|
233
|
-
logging.info(f"{self.user.name} birth location: {self.location}, {self.geolat}, {self.geolon}")
|
|
234
|
-
|
|
235
181
|
if self.chart_type == "Transit":
|
|
236
182
|
self.t_name = self.language_settings["transit_name"]
|
|
237
183
|
|
|
238
|
-
#
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
self.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
184
|
+
# Default radius for the chart
|
|
185
|
+
self.main_radius = 240
|
|
186
|
+
|
|
187
|
+
# Set circle radii based on chart type
|
|
188
|
+
if self.chart_type == "ExternalNatal":
|
|
189
|
+
self.first_circle_radius, self.second_circle_radius, self.third_circle_radius = 56, 92, 112
|
|
190
|
+
else:
|
|
191
|
+
self.first_circle_radius, self.second_circle_radius, self.third_circle_radius = 0, 36, 120
|
|
192
|
+
|
|
193
|
+
# Initialize element points
|
|
194
|
+
self.fire = 0.0
|
|
195
|
+
self.earth = 0.0
|
|
196
|
+
self.air = 0.0
|
|
197
|
+
self.water = 0.0
|
|
198
|
+
|
|
199
|
+
# Calculate element points from planets
|
|
200
|
+
self._calculate_elements_points_from_planets()
|
|
201
|
+
|
|
202
|
+
# Set up theme
|
|
203
|
+
if theme not in get_args(KerykeionChartTheme) and theme is not None:
|
|
204
|
+
raise KerykeionException(f"Theme {theme} is not available. Set None for default theme.")
|
|
205
|
+
|
|
206
|
+
self.set_up_theme(theme)
|
|
207
|
+
|
|
208
|
+
def set_up_theme(self, theme: Union[KerykeionChartTheme, None] = None) -> None:
|
|
209
|
+
"""
|
|
210
|
+
Set the theme for the chart.
|
|
211
|
+
"""
|
|
212
|
+
if theme is None:
|
|
213
|
+
self.color_style_tag = ""
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
theme_dir = Path(__file__).parent / "themes"
|
|
256
217
|
|
|
257
|
-
|
|
218
|
+
with open(theme_dir / f"{theme}.css", "r") as f:
|
|
219
|
+
self.color_style_tag = f.read()
|
|
258
220
|
|
|
259
221
|
def set_output_directory(self, dir_path: Path) -> None:
|
|
260
222
|
"""
|
|
@@ -263,19 +225,16 @@ class KerykeionChartSVG:
|
|
|
263
225
|
self.output_directory = dir_path
|
|
264
226
|
logging.info(f"Output direcotry set to: {self.output_directory}")
|
|
265
227
|
|
|
266
|
-
def parse_json_settings(self,
|
|
228
|
+
def parse_json_settings(self, settings_file_or_dict: Union[Path, dict, KerykeionSettingsModel, None]) -> None:
|
|
267
229
|
"""
|
|
268
230
|
Parse the settings file.
|
|
269
231
|
"""
|
|
270
|
-
settings = get_settings(
|
|
232
|
+
settings = get_settings(settings_file_or_dict)
|
|
271
233
|
|
|
272
|
-
|
|
273
|
-
self.language_settings = settings["language_settings"].get(language, "EN")
|
|
234
|
+
self.language_settings = settings["language_settings"][self.chart_language]
|
|
274
235
|
self.chart_colors_settings = settings["chart_colors"]
|
|
275
236
|
self.planets_settings = settings["celestial_points"]
|
|
276
237
|
self.aspects_settings = settings["aspects"]
|
|
277
|
-
self.planet_in_zodiac_extra_points = settings["general_settings"]["planet_in_zodiac_extra_points"]
|
|
278
|
-
self.chart_settings = settings["chart_settings"]
|
|
279
238
|
|
|
280
239
|
def _draw_zodiac_circle_slices(self, r):
|
|
281
240
|
"""
|
|
@@ -288,124 +247,65 @@ class KerykeionChartSVG:
|
|
|
288
247
|
Returns:
|
|
289
248
|
str: The SVG string representing the zodiac circle.
|
|
290
249
|
"""
|
|
291
|
-
|
|
250
|
+
sings = get_args(Sign)
|
|
292
251
|
output = ""
|
|
293
|
-
for i,
|
|
252
|
+
for i, sing in enumerate(sings):
|
|
294
253
|
output += draw_zodiac_slice(
|
|
295
|
-
c1=self.
|
|
254
|
+
c1=self.first_circle_radius,
|
|
296
255
|
chart_type=self.chart_type,
|
|
297
|
-
seventh_house_degree_ut=self.user.
|
|
256
|
+
seventh_house_degree_ut=self.user.seventh_house.abs_pos,
|
|
298
257
|
num=i,
|
|
299
258
|
r=r,
|
|
300
259
|
style=f'fill:{self.chart_colors_settings[f"zodiac_bg_{i}"]}; fill-opacity: 0.5;',
|
|
301
|
-
type=
|
|
260
|
+
type=sing,
|
|
302
261
|
)
|
|
303
262
|
|
|
304
263
|
return output
|
|
305
264
|
|
|
306
|
-
def _makeHouses(self, r):
|
|
307
|
-
path = ""
|
|
308
|
-
|
|
309
|
-
xr = 12
|
|
310
|
-
for i in range(xr):
|
|
311
|
-
# check transit
|
|
312
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
313
|
-
dropin = 160
|
|
314
|
-
roff = 72
|
|
315
|
-
t_roff = 36
|
|
316
|
-
else:
|
|
317
|
-
dropin = self.c3
|
|
318
|
-
roff = self.c1
|
|
319
|
-
|
|
320
|
-
# offset is negative desc houses_degree_ut[6]
|
|
321
|
-
offset = (int(self.user.houses_degree_ut[int(xr / 2)]) / -1) + int(self.user.houses_degree_ut[i])
|
|
322
|
-
x1 = sliceToX(0, (r - dropin), offset) + dropin
|
|
323
|
-
y1 = sliceToY(0, (r - dropin), offset) + dropin
|
|
324
|
-
x2 = sliceToX(0, r - roff, offset) + roff
|
|
325
|
-
y2 = sliceToY(0, r - roff, offset) + roff
|
|
326
|
-
|
|
327
|
-
if i < (xr - 1):
|
|
328
|
-
text_offset = offset + int(degreeDiff(self.user.houses_degree_ut[(i + 1)], self.user.houses_degree_ut[i]) / 2)
|
|
329
|
-
else:
|
|
330
|
-
text_offset = offset + int(degreeDiff(self.user.houses_degree_ut[0], self.user.houses_degree_ut[(xr - 1)]) / 2)
|
|
331
|
-
|
|
332
|
-
# mc, asc, dsc, ic
|
|
333
|
-
if i == 0:
|
|
334
|
-
linecolor = self.planets_settings[12]["color"]
|
|
335
|
-
elif i == 9:
|
|
336
|
-
linecolor = self.planets_settings[13]["color"]
|
|
337
|
-
elif i == 6:
|
|
338
|
-
linecolor = self.planets_settings[14]["color"]
|
|
339
|
-
elif i == 3:
|
|
340
|
-
linecolor = self.planets_settings[15]["color"]
|
|
341
|
-
else:
|
|
342
|
-
linecolor = self.chart_colors_settings["houses_radix_line"]
|
|
343
|
-
|
|
344
|
-
# Transit houses lines.
|
|
345
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
346
|
-
# Degrees for point zero.
|
|
347
|
-
|
|
348
|
-
zeropoint = 360 - self.user.houses_degree_ut[6]
|
|
349
|
-
t_offset = zeropoint + self.t_user.houses_degree_ut[i]
|
|
350
|
-
if t_offset > 360:
|
|
351
|
-
t_offset = t_offset - 360
|
|
352
|
-
t_x1 = sliceToX(0, (r - t_roff), t_offset) + t_roff
|
|
353
|
-
t_y1 = sliceToY(0, (r - t_roff), t_offset) + t_roff
|
|
354
|
-
t_x2 = sliceToX(0, r, t_offset)
|
|
355
|
-
t_y2 = sliceToY(0, r, t_offset)
|
|
356
|
-
if i < 11:
|
|
357
|
-
t_text_offset = t_offset + int(degreeDiff(self.t_user.houses_degree_ut[(i + 1)], self.t_user.houses_degree_ut[i]) / 2)
|
|
358
|
-
else:
|
|
359
|
-
t_text_offset = t_offset + int(degreeDiff(self.t_user.houses_degree_ut[0], self.t_user.houses_degree_ut[11]) / 2)
|
|
360
|
-
# linecolor
|
|
361
|
-
if i == 0 or i == 9 or i == 6 or i == 3:
|
|
362
|
-
t_linecolor = linecolor
|
|
363
|
-
else:
|
|
364
|
-
t_linecolor = self.chart_colors_settings["houses_transit_line"]
|
|
365
|
-
xtext = sliceToX(0, (r - 8), t_text_offset) + 8
|
|
366
|
-
ytext = sliceToY(0, (r - 8), t_text_offset) + 8
|
|
367
|
-
|
|
368
|
-
if self.chart_type == "Transit":
|
|
369
|
-
path = path + '<text style="fill: #00f; fill-opacity: 0; font-size: 14px"><tspan x="' + str(xtext - 3) + '" y="' + str(ytext + 3) + '">' + str(i + 1) + "</tspan></text>"
|
|
370
|
-
path = f"{path}<line x1='{str(t_x1)}' y1='{str(t_y1)}' x2='{str(t_x2)}' y2='{str(t_y2)}' style='stroke: {t_linecolor}; stroke-width: 2px; stroke-opacity:0;'/>"
|
|
371
|
-
|
|
372
|
-
else:
|
|
373
|
-
path = path + '<text style="fill: #00f; fill-opacity: .4; font-size: 14px"><tspan x="' + str(xtext - 3) + '" y="' + str(ytext + 3) + '">' + str(i + 1) + "</tspan></text>"
|
|
374
|
-
path = f"{path}<line x1='{str(t_x1)}' y1='{str(t_y1)}' x2='{str(t_x2)}' y2='{str(t_y2)}' style='stroke: {t_linecolor}; stroke-width: 2px; stroke-opacity:.3;'/>"
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
# if transit
|
|
378
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
379
|
-
dropin = 84
|
|
380
|
-
elif self.chart_type == "ExternalNatal":
|
|
381
|
-
dropin = 100
|
|
382
|
-
# Natal
|
|
383
|
-
else:
|
|
384
|
-
dropin = 48
|
|
385
|
-
|
|
386
|
-
xtext = sliceToX(0, (r - dropin), text_offset) + dropin # was 132
|
|
387
|
-
ytext = sliceToY(0, (r - dropin), text_offset) + dropin # was 132
|
|
388
|
-
path = f'{path}<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {linecolor}; stroke-width: 2px; stroke-dasharray:3,2; stroke-opacity:.4;"/>'
|
|
389
|
-
path = path + '<text style="fill: #f00; fill-opacity: .6; font-size: 14px"><tspan x="' + str(xtext - 3) + '" y="' + str(ytext + 3) + '">' + str(i + 1) + "</tspan></text>"
|
|
390
|
-
|
|
391
|
-
return path
|
|
392
|
-
|
|
393
265
|
def _calculate_elements_points_from_planets(self):
|
|
394
266
|
"""
|
|
395
267
|
Calculate chart element points from a planet.
|
|
268
|
+
TODO: Refactor this method.
|
|
269
|
+
Should be completely rewritten. Maybe even part of the AstrologicalSubject class.
|
|
270
|
+
The points should include just the standard way of calculating the elements points.
|
|
396
271
|
"""
|
|
272
|
+
|
|
273
|
+
ZODIAC = (
|
|
274
|
+
{"name": "Ari", "element": "fire"},
|
|
275
|
+
{"name": "Tau", "element": "earth"},
|
|
276
|
+
{"name": "Gem", "element": "air"},
|
|
277
|
+
{"name": "Can", "element": "water"},
|
|
278
|
+
{"name": "Leo", "element": "fire"},
|
|
279
|
+
{"name": "Vir", "element": "earth"},
|
|
280
|
+
{"name": "Lib", "element": "air"},
|
|
281
|
+
{"name": "Sco", "element": "water"},
|
|
282
|
+
{"name": "Sag", "element": "fire"},
|
|
283
|
+
{"name": "Cap", "element": "earth"},
|
|
284
|
+
{"name": "Aqu", "element": "air"},
|
|
285
|
+
{"name": "Pis", "element": "water"},
|
|
286
|
+
)
|
|
397
287
|
|
|
288
|
+
# Available bodies
|
|
289
|
+
available_celestial_points_names = []
|
|
290
|
+
for body in self.available_planets_setting:
|
|
291
|
+
available_celestial_points_names.append(body["name"].lower())
|
|
292
|
+
|
|
293
|
+
# Make list of the points sign
|
|
294
|
+
points_sign = []
|
|
295
|
+
for planet in available_celestial_points_names:
|
|
296
|
+
points_sign.append(self.user.get(planet).sign_num)
|
|
297
|
+
|
|
398
298
|
for i in range(len(self.available_planets_setting)):
|
|
399
299
|
# element: get extra points if planet is in own zodiac sign.
|
|
400
300
|
related_zodiac_signs = self.available_planets_setting[i]["related_zodiac_signs"]
|
|
401
|
-
cz =
|
|
301
|
+
cz = points_sign[i]
|
|
402
302
|
extra_points = 0
|
|
403
303
|
if related_zodiac_signs != []:
|
|
404
304
|
for e in range(len(related_zodiac_signs)):
|
|
405
305
|
if int(related_zodiac_signs[e]) == int(cz):
|
|
406
|
-
extra_points = self.
|
|
306
|
+
extra_points = self._PLANET_IN_ZODIAC_EXTRA_POINTS
|
|
407
307
|
|
|
408
|
-
ele =
|
|
308
|
+
ele = ZODIAC[points_sign[i]]["element"]
|
|
409
309
|
if ele == "fire":
|
|
410
310
|
self.fire = self.fire + self.available_planets_setting[i]["element_points"] + extra_points
|
|
411
311
|
|
|
@@ -418,956 +318,223 @@ class KerykeionChartSVG:
|
|
|
418
318
|
elif ele == "water":
|
|
419
319
|
self.water = self.water + self.available_planets_setting[i]["element_points"] + extra_points
|
|
420
320
|
|
|
421
|
-
def
|
|
422
|
-
planets_degut = {}
|
|
423
|
-
diff = range(len(self.available_planets_setting))
|
|
424
|
-
|
|
425
|
-
for i in range(len(self.available_planets_setting)):
|
|
426
|
-
# list of planets sorted by degree
|
|
427
|
-
logging.debug(f"planet: {i}, degree: {self.points_deg_ut[i]}")
|
|
428
|
-
planets_degut[self.points_deg_ut[i]] = i
|
|
429
|
-
|
|
430
|
-
"""
|
|
431
|
-
FIXME: The planets_degut is a dictionary like:
|
|
432
|
-
{planet_degree: planet_index}
|
|
433
|
-
It should be replaced bu points_deg_ut
|
|
434
|
-
print(self.points_deg_ut)
|
|
435
|
-
print(planets_degut)
|
|
436
|
-
"""
|
|
437
|
-
|
|
438
|
-
output = ""
|
|
439
|
-
keys = list(planets_degut.keys())
|
|
440
|
-
keys.sort()
|
|
441
|
-
switch = 0
|
|
442
|
-
|
|
443
|
-
planets_degrouped = {}
|
|
444
|
-
groups = []
|
|
445
|
-
planets_by_pos = list(range(len(planets_degut)))
|
|
446
|
-
planet_drange = 3.4
|
|
447
|
-
# get groups closely together
|
|
448
|
-
group_open = False
|
|
449
|
-
for e in range(len(keys)):
|
|
450
|
-
i = planets_degut[keys[e]]
|
|
451
|
-
# get distances between planets
|
|
452
|
-
if e == 0:
|
|
453
|
-
prev = self.points_deg_ut[planets_degut[keys[-1]]]
|
|
454
|
-
next = self.points_deg_ut[planets_degut[keys[1]]]
|
|
455
|
-
elif e == (len(keys) - 1):
|
|
456
|
-
prev = self.points_deg_ut[planets_degut[keys[e - 1]]]
|
|
457
|
-
next = self.points_deg_ut[planets_degut[keys[0]]]
|
|
458
|
-
else:
|
|
459
|
-
prev = self.points_deg_ut[planets_degut[keys[e - 1]]]
|
|
460
|
-
next = self.points_deg_ut[planets_degut[keys[e + 1]]]
|
|
461
|
-
diffa = degreeDiff(prev, self.points_deg_ut[i])
|
|
462
|
-
diffb = degreeDiff(next, self.points_deg_ut[i])
|
|
463
|
-
planets_by_pos[e] = [i, diffa, diffb]
|
|
464
|
-
|
|
465
|
-
logging.debug(f'{self.available_planets_setting[i]["label"]}, {diffa}, {diffb}')
|
|
466
|
-
|
|
467
|
-
if diffb < planet_drange:
|
|
468
|
-
if group_open:
|
|
469
|
-
groups[-1].append([e, diffa, diffb, self.available_planets_setting[planets_degut[keys[e]]]["label"]])
|
|
470
|
-
else:
|
|
471
|
-
group_open = True
|
|
472
|
-
groups.append([])
|
|
473
|
-
groups[-1].append([e, diffa, diffb, self.available_planets_setting[planets_degut[keys[e]]]["label"]])
|
|
474
|
-
else:
|
|
475
|
-
if group_open:
|
|
476
|
-
groups[-1].append([e, diffa, diffb, self.available_planets_setting[planets_degut[keys[e]]]["label"]])
|
|
477
|
-
group_open = False
|
|
478
|
-
|
|
479
|
-
def zero(x):
|
|
480
|
-
return 0
|
|
481
|
-
|
|
482
|
-
planets_delta = list(map(zero, range(len(self.available_planets_setting))))
|
|
483
|
-
|
|
484
|
-
# print groups
|
|
485
|
-
# print planets_by_pos
|
|
486
|
-
for a in range(len(groups)):
|
|
487
|
-
# Two grouped planets
|
|
488
|
-
if len(groups[a]) == 2:
|
|
489
|
-
next_to_a = groups[a][0][0] - 1
|
|
490
|
-
if groups[a][1][0] == (len(planets_by_pos) - 1):
|
|
491
|
-
next_to_b = 0
|
|
492
|
-
else:
|
|
493
|
-
next_to_b = groups[a][1][0] + 1
|
|
494
|
-
# if both planets have room
|
|
495
|
-
if (groups[a][0][1] > (2 * planet_drange)) & (groups[a][1][2] > (2 * planet_drange)):
|
|
496
|
-
planets_delta[groups[a][0][0]] = -(planet_drange - groups[a][0][2]) / 2
|
|
497
|
-
planets_delta[groups[a][1][0]] = +(planet_drange - groups[a][0][2]) / 2
|
|
498
|
-
# if planet a has room
|
|
499
|
-
elif groups[a][0][1] > (2 * planet_drange):
|
|
500
|
-
planets_delta[groups[a][0][0]] = -planet_drange
|
|
501
|
-
# if planet b has room
|
|
502
|
-
elif groups[a][1][2] > (2 * planet_drange):
|
|
503
|
-
planets_delta[groups[a][1][0]] = +planet_drange
|
|
504
|
-
|
|
505
|
-
# if planets next to a and b have room move them
|
|
506
|
-
elif (planets_by_pos[next_to_a][1] > (2.4 * planet_drange)) & (planets_by_pos[next_to_b][2] > (2.4 * planet_drange)):
|
|
507
|
-
planets_delta[(next_to_a)] = groups[a][0][1] - planet_drange * 2
|
|
508
|
-
planets_delta[groups[a][0][0]] = -planet_drange * 0.5
|
|
509
|
-
planets_delta[next_to_b] = -(groups[a][1][2] - planet_drange * 2)
|
|
510
|
-
planets_delta[groups[a][1][0]] = +planet_drange * 0.5
|
|
511
|
-
|
|
512
|
-
# if planet next to a has room move them
|
|
513
|
-
elif planets_by_pos[next_to_a][1] > (2 * planet_drange):
|
|
514
|
-
planets_delta[(next_to_a)] = groups[a][0][1] - planet_drange * 2.5
|
|
515
|
-
planets_delta[groups[a][0][0]] = -planet_drange * 1.2
|
|
516
|
-
|
|
517
|
-
# if planet next to b has room move them
|
|
518
|
-
elif planets_by_pos[next_to_b][2] > (2 * planet_drange):
|
|
519
|
-
planets_delta[next_to_b] = -(groups[a][1][2] - planet_drange * 2.5)
|
|
520
|
-
planets_delta[groups[a][1][0]] = +planet_drange * 1.2
|
|
521
|
-
|
|
522
|
-
# Three grouped planets or more
|
|
523
|
-
xl = len(groups[a])
|
|
524
|
-
if xl >= 3:
|
|
525
|
-
available = groups[a][0][1]
|
|
526
|
-
for f in range(xl):
|
|
527
|
-
available += groups[a][f][2]
|
|
528
|
-
need = (3 * planet_drange) + (1.2 * (xl - 1) * planet_drange)
|
|
529
|
-
leftover = available - need
|
|
530
|
-
xa = groups[a][0][1]
|
|
531
|
-
xb = groups[a][(xl - 1)][2]
|
|
532
|
-
|
|
533
|
-
# center
|
|
534
|
-
if (xa > (need * 0.5)) & (xb > (need * 0.5)):
|
|
535
|
-
startA = xa - (need * 0.5)
|
|
536
|
-
# position relative to next planets
|
|
537
|
-
else:
|
|
538
|
-
startA = (leftover / (xa + xb)) * xa
|
|
539
|
-
startB = (leftover / (xa + xb)) * xb
|
|
540
|
-
|
|
541
|
-
if available > need:
|
|
542
|
-
planets_delta[groups[a][0][0]] = startA - groups[a][0][1] + (1.5 * planet_drange)
|
|
543
|
-
for f in range(xl - 1):
|
|
544
|
-
planets_delta[groups[a][(f + 1)][0]] = 1.2 * planet_drange + planets_delta[groups[a][f][0]] - groups[a][f][2]
|
|
545
|
-
|
|
546
|
-
for e in range(len(keys)):
|
|
547
|
-
i = planets_degut[keys[e]]
|
|
548
|
-
|
|
549
|
-
# coordinates
|
|
550
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
551
|
-
if 22 < i < 27:
|
|
552
|
-
rplanet = 76
|
|
553
|
-
elif switch == 1:
|
|
554
|
-
rplanet = 110
|
|
555
|
-
switch = 0
|
|
556
|
-
else:
|
|
557
|
-
rplanet = 130
|
|
558
|
-
switch = 1
|
|
559
|
-
else:
|
|
560
|
-
# if 22 < i < 27 it is asc,mc,dsc,ic (angles of chart)
|
|
561
|
-
# put on special line (rplanet is range from outer ring)
|
|
562
|
-
amin, bmin, cmin = 0, 0, 0
|
|
563
|
-
if self.chart_type == "ExternalNatal":
|
|
564
|
-
amin = 74 - 10
|
|
565
|
-
bmin = 94 - 10
|
|
566
|
-
cmin = 40 - 10
|
|
567
|
-
|
|
568
|
-
if 22 < i < 27:
|
|
569
|
-
rplanet = 40 - cmin
|
|
570
|
-
elif switch == 1:
|
|
571
|
-
rplanet = 74 - amin
|
|
572
|
-
switch = 0
|
|
573
|
-
else:
|
|
574
|
-
rplanet = 94 - bmin
|
|
575
|
-
switch = 1
|
|
576
|
-
|
|
577
|
-
rtext = 45
|
|
578
|
-
|
|
579
|
-
offset = (int(self.user.houses_degree_ut[6]) / -1) + int(self.points_deg_ut[i] + planets_delta[e])
|
|
580
|
-
trueoffset = (int(self.user.houses_degree_ut[6]) / -1) + int(self.points_deg_ut[i])
|
|
581
|
-
|
|
582
|
-
planet_x = sliceToX(0, (r - rplanet), offset) + rplanet
|
|
583
|
-
planet_y = sliceToY(0, (r - rplanet), offset) + rplanet
|
|
584
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
585
|
-
scale = 0.8
|
|
586
|
-
|
|
587
|
-
elif self.chart_type == "ExternalNatal":
|
|
588
|
-
scale = 0.8
|
|
589
|
-
# line1
|
|
590
|
-
x1 = sliceToX(0, (r - self.c3), trueoffset) + self.c3
|
|
591
|
-
y1 = sliceToY(0, (r - self.c3), trueoffset) + self.c3
|
|
592
|
-
x2 = sliceToX(0, (r - rplanet - 30), trueoffset) + rplanet + 30
|
|
593
|
-
y2 = sliceToY(0, (r - rplanet - 30), trueoffset) + rplanet + 30
|
|
594
|
-
color = self.available_planets_setting[i]["color"]
|
|
595
|
-
output += (
|
|
596
|
-
'<line x1="%s" y1="%s" x2="%s" y2="%s" style="stroke-width:1px;stroke:%s;stroke-opacity:.3;"/>\n'
|
|
597
|
-
% (x1, y1, x2, y2, color)
|
|
598
|
-
)
|
|
599
|
-
# line2
|
|
600
|
-
x1 = sliceToX(0, (r - rplanet - 30), trueoffset) + rplanet + 30
|
|
601
|
-
y1 = sliceToY(0, (r - rplanet - 30), trueoffset) + rplanet + 30
|
|
602
|
-
x2 = sliceToX(0, (r - rplanet - 10), offset) + rplanet + 10
|
|
603
|
-
y2 = sliceToY(0, (r - rplanet - 10), offset) + rplanet + 10
|
|
604
|
-
output += (
|
|
605
|
-
'<line x1="%s" y1="%s" x2="%s" y2="%s" style="stroke-width:1px;stroke:%s;stroke-opacity:.5;"/>\n'
|
|
606
|
-
% (x1, y1, x2, y2, color)
|
|
607
|
-
)
|
|
608
|
-
|
|
609
|
-
else:
|
|
610
|
-
scale = 1
|
|
611
|
-
# output planet
|
|
612
|
-
output += f'<g transform="translate(-{12 * scale},-{12 * scale})"><g transform="scale({scale})"><use x="{planet_x * (1/scale)}" y="{planet_y * (1/scale)}" xlink:href="#{self.available_planets_setting[i]["name"]}" /></g></g>'
|
|
613
|
-
|
|
614
|
-
# make transit degut and display planets
|
|
615
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
616
|
-
group_offset = {}
|
|
617
|
-
t_planets_degut = {}
|
|
618
|
-
list_range = len(self.available_planets_setting)
|
|
619
|
-
|
|
620
|
-
for i in range(list_range):
|
|
621
|
-
if self.chart_type == "Transit" and self.available_planets_setting[i]['name'] in self.transit_ring_exclude_points_names:
|
|
622
|
-
continue
|
|
623
|
-
|
|
624
|
-
group_offset[i] = 0
|
|
625
|
-
t_planets_degut[self.t_points_deg_ut[i]] = i
|
|
626
|
-
|
|
627
|
-
t_keys = list(t_planets_degut.keys())
|
|
628
|
-
t_keys.sort()
|
|
629
|
-
|
|
630
|
-
# grab closely grouped planets
|
|
631
|
-
groups = []
|
|
632
|
-
in_group = False
|
|
633
|
-
for e in range(len(t_keys)):
|
|
634
|
-
i_a = t_planets_degut[t_keys[e]]
|
|
635
|
-
if e == (len(t_keys) - 1):
|
|
636
|
-
i_b = t_planets_degut[t_keys[0]]
|
|
637
|
-
else:
|
|
638
|
-
i_b = t_planets_degut[t_keys[e + 1]]
|
|
639
|
-
|
|
640
|
-
a = self.t_points_deg_ut[i_a]
|
|
641
|
-
b = self.t_points_deg_ut[i_b]
|
|
642
|
-
diff = degreeDiff(a, b)
|
|
643
|
-
if diff <= 2.5:
|
|
644
|
-
if in_group:
|
|
645
|
-
groups[-1].append(i_b)
|
|
646
|
-
else:
|
|
647
|
-
groups.append([i_a])
|
|
648
|
-
groups[-1].append(i_b)
|
|
649
|
-
in_group = True
|
|
650
|
-
else:
|
|
651
|
-
in_group = False
|
|
652
|
-
# loop groups and set degrees display adjustment
|
|
653
|
-
for i in range(len(groups)):
|
|
654
|
-
if len(groups[i]) == 2:
|
|
655
|
-
group_offset[groups[i][0]] = -1.0
|
|
656
|
-
group_offset[groups[i][1]] = 1.0
|
|
657
|
-
elif len(groups[i]) == 3:
|
|
658
|
-
group_offset[groups[i][0]] = -1.5
|
|
659
|
-
group_offset[groups[i][1]] = 0
|
|
660
|
-
group_offset[groups[i][2]] = 1.5
|
|
661
|
-
elif len(groups[i]) == 4:
|
|
662
|
-
group_offset[groups[i][0]] = -2.0
|
|
663
|
-
group_offset[groups[i][1]] = -1.0
|
|
664
|
-
group_offset[groups[i][2]] = 1.0
|
|
665
|
-
group_offset[groups[i][3]] = 2.0
|
|
666
|
-
|
|
667
|
-
switch = 0
|
|
668
|
-
|
|
669
|
-
# Transit planets loop
|
|
670
|
-
for e in range(len(t_keys)):
|
|
671
|
-
if self.chart_type == "Transit" and self.available_planets_setting[e]["name"] in self.transit_ring_exclude_points_names:
|
|
672
|
-
continue
|
|
673
|
-
|
|
674
|
-
i = t_planets_degut[t_keys[e]]
|
|
675
|
-
|
|
676
|
-
if 22 < i < 27:
|
|
677
|
-
rplanet = 9
|
|
678
|
-
elif switch == 1:
|
|
679
|
-
rplanet = 18
|
|
680
|
-
switch = 0
|
|
681
|
-
else:
|
|
682
|
-
rplanet = 26
|
|
683
|
-
switch = 1
|
|
684
|
-
|
|
685
|
-
# Transit planet name
|
|
686
|
-
zeropoint = 360 - self.user.houses_degree_ut[6]
|
|
687
|
-
t_offset = zeropoint + self.t_points_deg_ut[i]
|
|
688
|
-
if t_offset > 360:
|
|
689
|
-
t_offset = t_offset - 360
|
|
690
|
-
planet_x = sliceToX(0, (r - rplanet), t_offset) + rplanet
|
|
691
|
-
planet_y = sliceToY(0, (r - rplanet), t_offset) + rplanet
|
|
692
|
-
output += f'<g class="transit-planet-name" transform="translate(-6,-6)"><g transform="scale(0.5)"><use x="{planet_x*2}" y="{planet_y*2}" xlink:href="#{self.available_planets_setting[i]["name"]}" /></g></g>'
|
|
693
|
-
|
|
694
|
-
# Transit planet line
|
|
695
|
-
x1 = sliceToX(0, r + 3, t_offset) - 3
|
|
696
|
-
y1 = sliceToY(0, r + 3, t_offset) - 3
|
|
697
|
-
x2 = sliceToX(0, r - 3, t_offset) + 3
|
|
698
|
-
y2 = sliceToY(0, r - 3, t_offset) + 3
|
|
699
|
-
output += f'<line class="transit-planet-line" x1="{str(x1)}" y1="{str(y1)}" x2="{str(x2)}" y2="{str(y2)}" style="stroke: {self.available_planets_setting[i]["color"]}; stroke-width: 1px; stroke-opacity:.8;"/>'
|
|
700
|
-
|
|
701
|
-
# transit planet degree text
|
|
702
|
-
rotate = self.user.houses_degree_ut[0] - self.t_points_deg_ut[i]
|
|
703
|
-
textanchor = "end"
|
|
704
|
-
t_offset += group_offset[i]
|
|
705
|
-
rtext = -3.0
|
|
706
|
-
|
|
707
|
-
if -90 > rotate > -270:
|
|
708
|
-
rotate = rotate + 180.0
|
|
709
|
-
textanchor = "start"
|
|
710
|
-
if 270 > rotate > 90:
|
|
711
|
-
rotate = rotate - 180.0
|
|
712
|
-
textanchor = "start"
|
|
713
|
-
|
|
714
|
-
if textanchor == "end":
|
|
715
|
-
xo = 1
|
|
716
|
-
else:
|
|
717
|
-
xo = -1
|
|
718
|
-
deg_x = sliceToX(0, (r - rtext), t_offset + xo) + rtext
|
|
719
|
-
deg_y = sliceToY(0, (r - rtext), t_offset + xo) + rtext
|
|
720
|
-
degree = int(t_offset)
|
|
721
|
-
output += f'<g transform="translate({deg_x},{deg_y})">'
|
|
722
|
-
output += f'<text transform="rotate({rotate})" text-anchor="{textanchor}'
|
|
723
|
-
output += f'" style="fill: {self.available_planets_setting[i]["color"]}; font-size: 10px;">{convert_decimal_to_degree_string(self.t_points_deg[i], type="1")}'
|
|
724
|
-
output += "</text></g>"
|
|
725
|
-
|
|
726
|
-
# check transit
|
|
727
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
728
|
-
dropin = 36
|
|
729
|
-
else:
|
|
730
|
-
dropin = 0
|
|
731
|
-
|
|
732
|
-
# planet line
|
|
733
|
-
x1 = sliceToX(0, r - (dropin + 3), offset) + (dropin + 3)
|
|
734
|
-
y1 = sliceToY(0, r - (dropin + 3), offset) + (dropin + 3)
|
|
735
|
-
x2 = sliceToX(0, (r - (dropin - 3)), offset) + (dropin - 3)
|
|
736
|
-
y2 = sliceToY(0, (r - (dropin - 3)), offset) + (dropin - 3)
|
|
737
|
-
|
|
738
|
-
output += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {self.available_planets_setting[i]["color"]}; stroke-width: 2px; stroke-opacity:.6;"/>'
|
|
739
|
-
|
|
740
|
-
# check transit
|
|
741
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
742
|
-
dropin = 160
|
|
743
|
-
else:
|
|
744
|
-
dropin = 120
|
|
745
|
-
|
|
746
|
-
x1 = sliceToX(0, r - dropin, offset) + dropin
|
|
747
|
-
y1 = sliceToY(0, r - dropin, offset) + dropin
|
|
748
|
-
x2 = sliceToX(0, (r - (dropin - 3)), offset) + (dropin - 3)
|
|
749
|
-
y2 = sliceToY(0, (r - (dropin - 3)), offset) + (dropin - 3)
|
|
750
|
-
output += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {self.available_planets_setting[i]["color"]}; stroke-width: 2px; stroke-opacity:.6;"/>'
|
|
751
|
-
|
|
752
|
-
return output
|
|
753
|
-
|
|
754
|
-
def _makePatterns(self):
|
|
755
|
-
"""
|
|
756
|
-
* Stellium: At least four planets linked together in a series of continuous conjunctions.
|
|
757
|
-
* Grand trine: Three trine aspects together.
|
|
758
|
-
* Grand cross: Two pairs of opposing planets squared to each other.
|
|
759
|
-
* T-Square: Two planets in opposition squared to a third.
|
|
760
|
-
* Yod: Two qunicunxes together joined by a sextile.
|
|
761
|
-
"""
|
|
762
|
-
conj = {} # 0
|
|
763
|
-
opp = {} # 10
|
|
764
|
-
sq = {} # 5
|
|
765
|
-
tr = {} # 6
|
|
766
|
-
qc = {} # 9
|
|
767
|
-
sext = {} # 3
|
|
768
|
-
for i in range(len(self.available_planets_setting)):
|
|
769
|
-
a = self.points_deg_ut[i]
|
|
770
|
-
qc[i] = {}
|
|
771
|
-
sext[i] = {}
|
|
772
|
-
opp[i] = {}
|
|
773
|
-
sq[i] = {}
|
|
774
|
-
tr[i] = {}
|
|
775
|
-
conj[i] = {}
|
|
776
|
-
# skip some points
|
|
777
|
-
n = self.available_planets_setting[i]["name"]
|
|
778
|
-
if n == "earth" or n == "True_Node" or n == "osc. apogee" or n == "intp. apogee" or n == "intp. perigee":
|
|
779
|
-
continue
|
|
780
|
-
if n == "Dsc" or n == "Ic":
|
|
781
|
-
continue
|
|
782
|
-
for j in range(len(self.available_planets_setting)):
|
|
783
|
-
# skip some points
|
|
784
|
-
n = self.available_planets_setting[j]["name"]
|
|
785
|
-
if n == "earth" or n == "True_Node" or n == "osc. apogee" or n == "intp. apogee" or n == "intp. perigee":
|
|
786
|
-
continue
|
|
787
|
-
if n == "Dsc" or n == "Ic":
|
|
788
|
-
continue
|
|
789
|
-
b = self.points_deg_ut[j]
|
|
790
|
-
delta = float(degreeDiff(a, b))
|
|
791
|
-
# check for opposition
|
|
792
|
-
xa = float(self.aspects_settings[10]["degree"]) - float(self.aspects_settings[10]["orb"])
|
|
793
|
-
xb = float(self.aspects_settings[10]["degree"]) + float(self.aspects_settings[10]["orb"])
|
|
794
|
-
if xa <= delta <= xb:
|
|
795
|
-
opp[i][j] = True
|
|
796
|
-
# check for conjunction
|
|
797
|
-
xa = float(self.aspects_settings[0]["degree"]) - float(self.aspects_settings[0]["orb"])
|
|
798
|
-
xb = float(self.aspects_settings[0]["degree"]) + float(self.aspects_settings[0]["orb"])
|
|
799
|
-
if xa <= delta <= xb:
|
|
800
|
-
conj[i][j] = True
|
|
801
|
-
# check for squares
|
|
802
|
-
xa = float(self.aspects_settings[5]["degree"]) - float(self.aspects_settings[5]["orb"])
|
|
803
|
-
xb = float(self.aspects_settings[5]["degree"]) + float(self.aspects_settings[5]["orb"])
|
|
804
|
-
if xa <= delta <= xb:
|
|
805
|
-
sq[i][j] = True
|
|
806
|
-
# check for qunicunxes
|
|
807
|
-
xa = float(self.aspects_settings[9]["degree"]) - float(self.aspects_settings[9]["orb"])
|
|
808
|
-
xb = float(self.aspects_settings[9]["degree"]) + float(self.aspects_settings[9]["orb"])
|
|
809
|
-
if xa <= delta <= xb:
|
|
810
|
-
qc[i][j] = True
|
|
811
|
-
# check for sextiles
|
|
812
|
-
xa = float(self.aspects_settings[3]["degree"]) - float(self.aspects_settings[3]["orb"])
|
|
813
|
-
xb = float(self.aspects_settings[3]["degree"]) + float(self.aspects_settings[3]["orb"])
|
|
814
|
-
if xa <= delta <= xb:
|
|
815
|
-
sext[i][j] = True
|
|
816
|
-
|
|
817
|
-
yot = {}
|
|
818
|
-
# check for double qunicunxes
|
|
819
|
-
for k, v in qc.items():
|
|
820
|
-
if len(qc[k]) >= 2:
|
|
821
|
-
# check for sextile
|
|
822
|
-
for l, w in qc[k].items():
|
|
823
|
-
for m, x in qc[k].items():
|
|
824
|
-
if m in sext[l]:
|
|
825
|
-
if l > m:
|
|
826
|
-
yot["%s,%s,%s" % (k, m, l)] = [k, m, l]
|
|
827
|
-
else:
|
|
828
|
-
yot["%s,%s,%s" % (k, l, m)] = [k, l, m]
|
|
829
|
-
tsquare = {}
|
|
830
|
-
# check for opposition
|
|
831
|
-
for k, v in opp.items():
|
|
832
|
-
if len(opp[k]) >= 1:
|
|
833
|
-
# check for square
|
|
834
|
-
for l, w in opp[k].items():
|
|
835
|
-
for a, b in sq.items():
|
|
836
|
-
if k in sq[a] and l in sq[a]:
|
|
837
|
-
logging.debug(f"Got tsquare {a} {k} {l}")
|
|
838
|
-
if k > l:
|
|
839
|
-
tsquare[f"{a},{l},{k}"] = f"{self.available_planets_setting[a]['label']} => {self.available_planets_setting[l]['label']}, {self.available_planets_setting[k]['label']}"
|
|
840
|
-
|
|
841
|
-
else:
|
|
842
|
-
tsquare[f"{a},{k},{l}"] = f"{self.available_planets_setting[a]['label']} => {self.available_planets_setting[k]['label']}, {self.available_planets_setting[l]['label']}"
|
|
843
|
-
|
|
844
|
-
stellium = {}
|
|
845
|
-
# check for 4 continuous conjunctions
|
|
846
|
-
for k, v in conj.items():
|
|
847
|
-
if len(conj[k]) >= 1:
|
|
848
|
-
# first conjunction
|
|
849
|
-
for l, m in conj[k].items():
|
|
850
|
-
if len(conj[l]) >= 1:
|
|
851
|
-
for n, o in conj[l].items():
|
|
852
|
-
# skip 1st conj
|
|
853
|
-
if n == k:
|
|
854
|
-
continue
|
|
855
|
-
if len(conj[n]) >= 1:
|
|
856
|
-
# third conjunction
|
|
857
|
-
for p, q in conj[n].items():
|
|
858
|
-
# skip first and second conj
|
|
859
|
-
if p == k or p == n:
|
|
860
|
-
continue
|
|
861
|
-
if len(conj[p]) >= 1:
|
|
862
|
-
# fourth conjunction
|
|
863
|
-
for r, s in conj[p].items():
|
|
864
|
-
# skip conj 1,2,3
|
|
865
|
-
if r == k or r == n or r == p:
|
|
866
|
-
continue
|
|
867
|
-
|
|
868
|
-
l = [k, n, p, r]
|
|
869
|
-
l.sort()
|
|
870
|
-
stellium["%s %s %s %s" % (l[0], l[1], l[2], l[3])] = "%s %s %s %s" % (
|
|
871
|
-
self.available_planets_setting[l[0]]["label"],
|
|
872
|
-
self.available_planets_setting[l[1]]["label"],
|
|
873
|
-
self.available_planets_setting[l[2]]["label"],
|
|
874
|
-
self.available_planets_setting[l[3]]["label"],
|
|
875
|
-
)
|
|
876
|
-
# print yots
|
|
877
|
-
out = '<g transform="translate(-30,380)">'
|
|
878
|
-
if len(yot) >= 1:
|
|
879
|
-
y = 0
|
|
880
|
-
for k, v in yot.items():
|
|
881
|
-
out += f'<text y="{y}" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 12px;">{"Yot"}</text>'
|
|
882
|
-
|
|
883
|
-
# first planet symbol
|
|
884
|
-
out += f'<g transform="translate(20,{y})">'
|
|
885
|
-
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.available_planets_setting[yot[k][0]]["name"]}" /></g>'
|
|
886
|
-
|
|
887
|
-
# second planet symbol
|
|
888
|
-
out += f'<g transform="translate(30,{y})">'
|
|
889
|
-
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.available_planets_setting[yot[k][1]]["name"]}" /></g>'
|
|
890
|
-
|
|
891
|
-
# third planet symbol
|
|
892
|
-
out += f'<g transform="translate(40,{y})">'
|
|
893
|
-
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.available_planets_setting[yot[k][2]]["name"]}" /></g>'
|
|
894
|
-
|
|
895
|
-
y = y + 14
|
|
896
|
-
# finalize
|
|
897
|
-
out += "</g>"
|
|
898
|
-
# return out
|
|
899
|
-
return ""
|
|
900
|
-
|
|
901
|
-
# Aspect and aspect grid functions for natal type charts.
|
|
902
|
-
def _makeAspects(self, r, ar):
|
|
321
|
+
def _draw_all_aspects_lines(self, r, ar):
|
|
903
322
|
out = ""
|
|
904
|
-
for
|
|
323
|
+
for aspect in self.aspects_list:
|
|
905
324
|
out += draw_aspect_line(
|
|
906
325
|
r=r,
|
|
907
326
|
ar=ar,
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
color=self.aspects_settings[element["aid"]]["color"],
|
|
327
|
+
aspect=aspect,
|
|
328
|
+
color=self.aspects_settings[aspect["aid"]]["color"],
|
|
911
329
|
seventh_house_degree_ut=self.user.seventh_house.abs_pos
|
|
912
330
|
)
|
|
913
331
|
|
|
914
332
|
return out
|
|
915
333
|
|
|
916
|
-
def
|
|
917
|
-
out = ""
|
|
918
|
-
style = "stroke:%s; stroke-width: 1px; stroke-opacity:.6; fill:none" % (self.chart_colors_settings["paper_0"])
|
|
919
|
-
xindent = 380
|
|
920
|
-
yindent = 468
|
|
921
|
-
box = 14
|
|
922
|
-
revr = list(range(len(self.available_planets_setting)))
|
|
923
|
-
revr.reverse()
|
|
924
|
-
counter = 0
|
|
925
|
-
for a in revr:
|
|
926
|
-
counter += 1
|
|
927
|
-
out += f'<rect x="{xindent}" y="{yindent}" width="{box}" height="{box}" style="{style}"/>'
|
|
928
|
-
out += f'<use transform="scale(0.4)" x="{(xindent+2)*2.5}" y="{(yindent+1)*2.5}" xlink:href="#{self.available_planets_setting[a]["name"]}" />'
|
|
929
|
-
|
|
930
|
-
xindent = xindent + box
|
|
931
|
-
yindent = yindent - box
|
|
932
|
-
revr2 = list(range(a))
|
|
933
|
-
revr2.reverse()
|
|
934
|
-
xorb = xindent
|
|
935
|
-
yorb = yindent + box
|
|
936
|
-
for b in revr2:
|
|
937
|
-
out += f'<rect x="{xorb}" y="{yorb}" width="{box}" height="{box}" style="{style}"/>'
|
|
938
|
-
|
|
939
|
-
xorb = xorb + box
|
|
940
|
-
for element in self.aspects_list:
|
|
941
|
-
if (element["p1"] == a and element["p2"] == b) or (element["p1"] == b and element["p2"] == a):
|
|
942
|
-
out += f'<use x="{xorb-box+1}" y="{yorb+1}" xlink:href="#orb{element["aspect_degrees"]}" />'
|
|
943
|
-
|
|
944
|
-
return out
|
|
945
|
-
|
|
946
|
-
# Aspect and aspect grid functions for transit type charts
|
|
947
|
-
def _makeAspectsTransit(self, r, ar):
|
|
334
|
+
def _draw_all_transit_aspects_lines(self, r, ar):
|
|
948
335
|
out = ""
|
|
949
|
-
|
|
950
|
-
self.aspects_list = SynastryAspects(self.user, self.t_user, new_settings_file=self.new_settings_file).relevant_aspects
|
|
951
|
-
|
|
952
|
-
for element in self.aspects_list:
|
|
336
|
+
for aspect in self.aspects_list:
|
|
953
337
|
out += draw_aspect_line(
|
|
954
338
|
r=r,
|
|
955
339
|
ar=ar,
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
color=self.aspects_settings[element["aid"]]["color"],
|
|
340
|
+
aspect=aspect,
|
|
341
|
+
color=self.aspects_settings[aspect["aid"]]["color"],
|
|
959
342
|
seventh_house_degree_ut=self.user.seventh_house.abs_pos
|
|
960
343
|
)
|
|
961
|
-
|
|
962
|
-
return out
|
|
963
|
-
|
|
964
|
-
def _makeAspectTransitGrid(self, r):
|
|
965
|
-
out = '<g transform="translate(500,310)">'
|
|
966
|
-
out += f'<text y="-15" x="0" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 14px;">{self.language_settings["aspects"]}:</text>'
|
|
967
|
-
|
|
968
|
-
line = 0
|
|
969
|
-
nl = 0
|
|
970
|
-
|
|
971
|
-
for i in range(len(self.aspects_list)):
|
|
972
|
-
if i == 12:
|
|
973
|
-
nl = 100
|
|
974
|
-
|
|
975
|
-
line = 0
|
|
976
|
-
|
|
977
|
-
elif i == 24:
|
|
978
|
-
nl = 200
|
|
979
|
-
|
|
980
|
-
line = 0
|
|
981
|
-
|
|
982
|
-
elif i == 36:
|
|
983
|
-
nl = 300
|
|
984
|
-
|
|
985
|
-
line = 0
|
|
986
|
-
|
|
987
|
-
elif i == 48:
|
|
988
|
-
nl = 400
|
|
989
|
-
|
|
990
|
-
# When there are more than 60 aspects, the text is moved up
|
|
991
|
-
if len(self.aspects_list) > 60:
|
|
992
|
-
line = -1 * (len(self.aspects_list) - 60) * 14
|
|
993
|
-
else:
|
|
994
|
-
line = 0
|
|
995
|
-
|
|
996
|
-
out += f'<g transform="translate({nl},{line})">'
|
|
997
|
-
|
|
998
|
-
# first planet symbol
|
|
999
|
-
out += f'<use transform="scale(0.4)" x="0" y="3" xlink:href="#{self.planets_settings[self.aspects_list[i]["p1"]]["name"]}" />'
|
|
1000
|
-
|
|
1001
|
-
# aspect symbol
|
|
1002
|
-
out += f'<use x="15" y="0" xlink:href="#orb{self.aspects_settings[self.aspects_list[i]["aid"]]["degree"]}" />'
|
|
1003
|
-
|
|
1004
|
-
# second planet symbol
|
|
1005
|
-
out += '<g transform="translate(30,0)">'
|
|
1006
|
-
out += '<use transform="scale(0.4)" x="0" y="3" xlink:href="#%s" />' % (self.planets_settings[self.aspects_list[i]["p2"]]["name"])
|
|
1007
|
-
|
|
1008
|
-
out += "</g>"
|
|
1009
|
-
# difference in degrees
|
|
1010
|
-
out += f'<text y="8" x="45" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{convert_decimal_to_degree_string(self.aspects_list[i]["orbit"])}</text>'
|
|
1011
|
-
# line
|
|
1012
|
-
out += "</g>"
|
|
1013
|
-
line = line + 14
|
|
1014
|
-
out += "</g>"
|
|
1015
|
-
return out
|
|
1016
|
-
|
|
1017
|
-
def _makePlanetGrid(self):
|
|
1018
|
-
li = 10
|
|
1019
|
-
offset = 0
|
|
1020
|
-
|
|
1021
|
-
out = '<g transform="translate(510,-20)">'
|
|
1022
|
-
out += '<g transform="translate(140, -15)">'
|
|
1023
|
-
out += f'<text text-anchor="end" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 14px;">{self.language_settings["planets_and_house"]} {self.user.name}:</text>'
|
|
1024
|
-
out += "</g>"
|
|
1025
|
-
|
|
1026
|
-
end_of_line = None
|
|
1027
|
-
for i in range(len(self.available_planets_setting)):
|
|
1028
|
-
offset_between_lines = 14
|
|
1029
|
-
end_of_line = "</g>"
|
|
1030
|
-
|
|
1031
|
-
# Guarda qui !!
|
|
1032
|
-
if i == 27:
|
|
1033
|
-
li = 10
|
|
1034
|
-
offset = -120
|
|
1035
|
-
|
|
1036
|
-
# start of line
|
|
1037
|
-
out += f'<g transform="translate({offset},{li})">'
|
|
1038
|
-
|
|
1039
|
-
# planet text
|
|
1040
|
-
out += f'<text text-anchor="end" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{self.language_settings["celestial_points"][self.available_planets_setting[i]["label"]]}</text>'
|
|
1041
|
-
|
|
1042
|
-
# planet symbol
|
|
1043
|
-
out += f'<g transform="translate(5,-8)"><use transform="scale(0.4)" xlink:href="#{self.available_planets_setting[i]["name"]}" /></g>'
|
|
1044
|
-
|
|
1045
|
-
# planet degree
|
|
1046
|
-
out += f'<text text-anchor="start" x="19" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{convert_decimal_to_degree_string(self.points_deg[i])}</text>'
|
|
1047
|
-
|
|
1048
|
-
# zodiac
|
|
1049
|
-
out += f'<g transform="translate(60,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.points_sign[i]]["name"]}" /></g>'
|
|
1050
|
-
|
|
1051
|
-
# planet retrograde
|
|
1052
|
-
if self.points_retrograde[i]:
|
|
1053
|
-
out += '<g transform="translate(74,-6)"><use transform="scale(.5)" xlink:href="#retrograde" /></g>'
|
|
1054
|
-
|
|
1055
|
-
# end of line
|
|
1056
|
-
out += end_of_line
|
|
1057
|
-
|
|
1058
|
-
li = li + offset_between_lines
|
|
1059
|
-
|
|
1060
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
1061
|
-
if self.chart_type == "Transit":
|
|
1062
|
-
out += '<g transform="translate(320, -15)">'
|
|
1063
|
-
out += f'<text text-anchor="end" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 14px;">{self.t_name}:</text>'
|
|
1064
|
-
else:
|
|
1065
|
-
out += '<g transform="translate(380, -15)">'
|
|
1066
|
-
out += f'<text text-anchor="end" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 14px;">{self.language_settings["planets_and_house"]} {self.t_user.name}:</text>'
|
|
1067
|
-
|
|
1068
|
-
out += end_of_line
|
|
1069
|
-
|
|
1070
|
-
t_li = 10
|
|
1071
|
-
t_offset = 250
|
|
1072
|
-
|
|
1073
|
-
for i in range(len(self.available_planets_setting)):
|
|
1074
|
-
if i == 27:
|
|
1075
|
-
t_li = 10
|
|
1076
|
-
t_offset = -120
|
|
1077
|
-
|
|
1078
|
-
# start of line
|
|
1079
|
-
out += f'<g transform="translate({t_offset},{t_li})">'
|
|
1080
|
-
|
|
1081
|
-
# planet text
|
|
1082
|
-
out += f'<text text-anchor="end" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{self.language_settings["celestial_points"][self.available_planets_setting[i]["label"]]}</text>'
|
|
1083
|
-
# planet symbol
|
|
1084
|
-
out += f'<g transform="translate(5,-8)"><use transform="scale(0.4)" xlink:href="#{self.available_planets_setting[i]["name"]}" /></g>'
|
|
1085
|
-
# planet degree
|
|
1086
|
-
out += f'<text text-anchor="start" x="19" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{convert_decimal_to_degree_string(self.t_points_deg[i])}</text>'
|
|
1087
|
-
# zodiac
|
|
1088
|
-
out += f'<g transform="translate(60,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.t_points_sign[i]]["name"]}" /></g>'
|
|
1089
|
-
|
|
1090
|
-
# planet retrograde
|
|
1091
|
-
if self.t_points_retrograde[i]:
|
|
1092
|
-
out += '<g transform="translate(74,-6)"><use transform="scale(.5)" xlink:href="#retrograde" /></g>'
|
|
1093
|
-
|
|
1094
|
-
# end of line
|
|
1095
|
-
out += end_of_line
|
|
1096
|
-
|
|
1097
|
-
t_li = t_li + offset_between_lines
|
|
1098
|
-
|
|
1099
|
-
if end_of_line is None:
|
|
1100
|
-
raise KerykeionException("End of line not found")
|
|
1101
|
-
|
|
1102
|
-
out += end_of_line
|
|
1103
344
|
return out
|
|
1104
345
|
|
|
1105
|
-
def
|
|
346
|
+
def _create_template_dictionary(self) -> ChartTemplateDictionary:
|
|
1106
347
|
"""
|
|
1107
|
-
|
|
348
|
+
Create a dictionary containing the template data for generating an astrological chart.
|
|
1108
349
|
|
|
1109
350
|
Returns:
|
|
1110
|
-
|
|
351
|
+
ChartTemplateDictionary: A dictionary with template data for the chart.
|
|
1111
352
|
"""
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
li = 10
|
|
1115
|
-
for i in range(12):
|
|
1116
|
-
if i < 9:
|
|
1117
|
-
cusp = "  " + str(i + 1)
|
|
1118
|
-
else:
|
|
1119
|
-
cusp = str(i + 1)
|
|
1120
|
-
out += f'<g transform="translate(0,{li})">'
|
|
1121
|
-
out += f'<text text-anchor="end" x="40" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{self.language_settings["cusp"]} {cusp}:</text>'
|
|
1122
|
-
out += f'<g transform="translate(40,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.houses_sign_graph[i]]["name"]}" /></g>'
|
|
1123
|
-
out += f'<text x="53" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;"> {convert_decimal_to_degree_string(self.user.houses_list[i]["position"])}</text>'
|
|
1124
|
-
out += "</g>"
|
|
1125
|
-
li = li + 14
|
|
353
|
+
# Initialize template dictionary
|
|
354
|
+
template_dict: ChartTemplateDictionary = dict() # type: ignore
|
|
1126
355
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
if self.chart_type == "Synastry":
|
|
1130
|
-
out += '<!-- Synastry Houses -->'
|
|
1131
|
-
out += '<g transform="translate(850, -20)">'
|
|
1132
|
-
li = 10
|
|
1133
|
-
|
|
1134
|
-
for i in range(12):
|
|
1135
|
-
if i < 9:
|
|
1136
|
-
cusp = "  " + str(i + 1)
|
|
1137
|
-
else:
|
|
1138
|
-
cusp = str(i + 1)
|
|
1139
|
-
out += '<g transform="translate(0,' + str(li) + ')">'
|
|
1140
|
-
out += f'<text text-anchor="end" x="40" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{self.language_settings["cusp"]} {cusp}:</text>'
|
|
1141
|
-
out += f'<g transform="translate(40,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.t_houses_sign_graph[i]]["name"]}" /></g>'
|
|
1142
|
-
out += f'<text x="53" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;"> {convert_decimal_to_degree_string(self.t_user.houses_list[i]["position"])}</text>'
|
|
1143
|
-
out += "</g>"
|
|
1144
|
-
li = li + 14
|
|
1145
|
-
out += "</g>"
|
|
1146
|
-
|
|
1147
|
-
return out
|
|
1148
|
-
|
|
1149
|
-
def _createTemplateDictionary(self) -> ChartTemplateDictionary:
|
|
1150
|
-
# self.chart_type = "Transit"
|
|
1151
|
-
# empty element points
|
|
1152
|
-
self.fire = 0.0
|
|
1153
|
-
self.earth = 0.0
|
|
1154
|
-
self.air = 0.0
|
|
1155
|
-
self.water = 0.0
|
|
1156
|
-
|
|
1157
|
-
# Calculate the elements points
|
|
1158
|
-
self._calculate_elements_points_from_planets()
|
|
1159
|
-
|
|
1160
|
-
# Viewbox and sizing
|
|
1161
|
-
svgHeight = "100%"
|
|
1162
|
-
svgWidth = "100%"
|
|
1163
|
-
rotate = "0"
|
|
1164
|
-
|
|
1165
|
-
# To increase the size of the chart, change the viewbox
|
|
1166
|
-
if self.chart_type == "Natal" or self.chart_type == "ExternalNatal":
|
|
1167
|
-
viewbox = self.chart_settings["basic_chart_viewBox"]
|
|
1168
|
-
else:
|
|
1169
|
-
viewbox = self.chart_settings["wide_chart_viewBox"]
|
|
356
|
+
# Set the color style tag
|
|
357
|
+
template_dict["color_style_tag"] = self.color_style_tag
|
|
1170
358
|
|
|
1171
|
-
#
|
|
1172
|
-
|
|
1173
|
-
|
|
359
|
+
# Set chart dimensions
|
|
360
|
+
template_dict["chart_height"] = self.height
|
|
361
|
+
template_dict["chart_width"] = self.width
|
|
1174
362
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
self.c2 = 92
|
|
1178
|
-
self.c3 = 112
|
|
1179
|
-
else:
|
|
1180
|
-
self.c1 = 0
|
|
1181
|
-
self.c2 = 36
|
|
1182
|
-
self.c3 = 120
|
|
363
|
+
# Set chart name
|
|
364
|
+
template_dict["stringName"] = f"{self.user.name}:" if self.chart_type in ["Synastry", "Transit"] else f'{self.language_settings["info"]}:'
|
|
1183
365
|
|
|
1184
|
-
#
|
|
1185
|
-
if self.chart_type
|
|
1186
|
-
td["transitRing"] = draw_transit_ring(r, self.chart_colors_settings["paper_1"], self.chart_colors_settings["zodiac_transit_ring_3"])
|
|
1187
|
-
td["degreeRing"] = draw_transit_ring_degree_steps(r, self.user.seventh_house.abs_pos)
|
|
366
|
+
# Set viewbox based on chart type
|
|
367
|
+
template_dict['viewbox'] = self._BASIC_CHART_VIEWBOX if self.chart_type in ["Natal", "ExternalNatal"] else self._WIDE_CHART_VIEWBOX
|
|
1188
368
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
369
|
+
# Generate rings and circles based on chart type
|
|
370
|
+
if self.chart_type in ["Transit", "Synastry"]:
|
|
371
|
+
template_dict["transitRing"] = draw_transit_ring(self.main_radius, self.chart_colors_settings["paper_1"], self.chart_colors_settings["zodiac_transit_ring_3"])
|
|
372
|
+
template_dict["degreeRing"] = draw_transit_ring_degree_steps(self.main_radius, self.user.seventh_house.abs_pos)
|
|
373
|
+
template_dict["first_circle"] = draw_first_circle(self.main_radius, self.chart_colors_settings["zodiac_transit_ring_2"], self.chart_type)
|
|
374
|
+
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)
|
|
375
|
+
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)
|
|
1192
376
|
|
|
1193
|
-
|
|
1194
|
-
|
|
377
|
+
if self.double_chart_aspect_grid_type == "list":
|
|
378
|
+
template_dict["makeAspectGrid"] = draw_transit_aspect_list(self.language_settings["aspects"], self.aspects_list, self.planets_settings, self.aspects_settings)
|
|
379
|
+
else:
|
|
380
|
+
template_dict["makeAspectGrid"] = draw_transit_aspect_grid(self.chart_colors_settings['paper_0'], self.available_planets_setting, self.aspects_list, 550, 450)
|
|
1195
381
|
|
|
1196
|
-
|
|
1197
|
-
td["makeAspectGrid"] = self._makeAspectTransitGrid(r)
|
|
1198
|
-
td["makePatterns"] = ""
|
|
382
|
+
template_dict["makeAspects"] = self._draw_all_transit_aspects_lines(self.main_radius, self.main_radius - 160)
|
|
1199
383
|
else:
|
|
1200
|
-
|
|
1201
|
-
|
|
384
|
+
template_dict["transitRing"] = ""
|
|
385
|
+
template_dict["degreeRing"] = draw_degree_ring(self.main_radius, self.first_circle_radius, self.user.seventh_house.abs_pos, self.chart_colors_settings["paper_0"])
|
|
386
|
+
template_dict['first_circle'] = draw_first_circle(self.main_radius, self.chart_colors_settings["zodiac_radix_ring_2"], self.chart_type, self.first_circle_radius)
|
|
387
|
+
template_dict["second_circle"] = draw_second_circle(self.main_radius, self.chart_colors_settings["zodiac_radix_ring_1"], self.chart_colors_settings["paper_1"], self.chart_type, self.second_circle_radius)
|
|
388
|
+
template_dict['third_circle'] = draw_third_circle(self.main_radius, self.chart_colors_settings["zodiac_radix_ring_0"], self.chart_colors_settings["paper_1"], self.chart_type, self.third_circle_radius)
|
|
389
|
+
template_dict["makeAspectGrid"] = draw_aspect_grid(self.chart_colors_settings['paper_0'], self.available_planets_setting, self.aspects_list)
|
|
1202
390
|
|
|
1203
|
-
|
|
391
|
+
template_dict["makeAspects"] = self._draw_all_aspects_lines(self.main_radius, self.main_radius - self.third_circle_radius)
|
|
1204
392
|
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
td["c3"] = f'cx="{r}" cy="{r}" r="{r - self.c3}"'
|
|
1208
|
-
td["c3style"] = f'fill: {self.chart_colors_settings["paper_1"]}; fill-opacity:.8; stroke: {self.chart_colors_settings["zodiac_radix_ring_0"]}; stroke-width: 1px'
|
|
1209
|
-
|
|
1210
|
-
td["makeAspects"] = self._makeAspects(r, (r - self.c3))
|
|
1211
|
-
td["makeAspectGrid"] = self._makeAspectGrid(r)
|
|
1212
|
-
td["makePatterns"] = self._makePatterns()
|
|
1213
|
-
|
|
1214
|
-
td["chart_height"] = self.height
|
|
1215
|
-
td["chart_width"] = self.width
|
|
1216
|
-
td["circleX"] = str(0)
|
|
1217
|
-
td["circleY"] = str(0)
|
|
1218
|
-
td["svgWidth"] = str(svgWidth)
|
|
1219
|
-
td["svgHeight"] = str(svgHeight)
|
|
1220
|
-
td["viewbox"] = viewbox
|
|
1221
|
-
|
|
1222
|
-
# Chart Title
|
|
393
|
+
# Set chart title
|
|
1223
394
|
if self.chart_type == "Synastry":
|
|
1224
|
-
|
|
1225
|
-
|
|
395
|
+
template_dict["stringTitle"] = f"{self.user.name} {self.language_settings['and_word']} {self.t_user.name}"
|
|
1226
396
|
elif self.chart_type == "Transit":
|
|
1227
|
-
|
|
1228
|
-
|
|
397
|
+
template_dict["stringTitle"] = f"{self.language_settings['transits']} {self.t_user.day}/{self.t_user.month}/{self.t_user.year}"
|
|
1229
398
|
else:
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
#
|
|
1233
|
-
if self.
|
|
1234
|
-
|
|
399
|
+
template_dict["stringTitle"] = self.user.name
|
|
400
|
+
|
|
401
|
+
# Set bottom left corner information
|
|
402
|
+
template_dict["bottomLeft0"] = f"{self.user.zodiac_type if self.user.zodiac_type == 'Tropic' else str(self.user.zodiac_type) + ' ' + str(self.user.sidereal_mode)}"
|
|
403
|
+
template_dict["bottomLeft1"] = f"{self.user.houses_system_name}"
|
|
404
|
+
if self.chart_type in ["Natal", "ExternalNatal", "Synastry"]:
|
|
405
|
+
template_dict["bottomLeft2"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get("day", "Day")} {self.user.lunar_phase.get("moon_phase", "")}'
|
|
406
|
+
template_dict["bottomLeft3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.user.lunar_phase.moon_phase_name}'
|
|
407
|
+
template_dict["bottomLeft4"] = f'{self.user.perspective_type}'
|
|
1235
408
|
else:
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
409
|
+
template_dict["bottomLeft2"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get("day", "Day")} {self.t_user.lunar_phase.get("moon_phase", "")}'
|
|
410
|
+
template_dict["bottomLeft3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.t_user.lunar_phase.moon_phase_name}'
|
|
411
|
+
template_dict["bottomLeft4"] = f'{self.t_user.perspective_type}'
|
|
412
|
+
|
|
413
|
+
# Draw moon phase
|
|
414
|
+
template_dict['moon_phase'] = draw_moon_phase(
|
|
415
|
+
self.user.lunar_phase["degrees_between_s_m"],
|
|
416
|
+
self.geolat
|
|
417
|
+
)
|
|
1245
418
|
|
|
1246
|
-
|
|
1247
|
-
td["bottomLeft0"] = f"{self.user.zodiac_type if self.user.zodiac_type == 'Tropic' else self.user.zodiac_type + ' ' + self.user.sidereal_mode}"
|
|
1248
|
-
td["bottomLeft1"] = f"{self.user.houses_system_name}"
|
|
1249
|
-
td["bottomLeft2"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get("day", "Day")} {self.t_user.lunar_phase.get("moon_phase", "")}'
|
|
1250
|
-
td["bottomLeft3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.t_user.lunar_phase.moon_phase_name}'
|
|
1251
|
-
td["bottomLeft4"] = f'{self.t_user.perspective_type}'
|
|
1252
|
-
|
|
1253
|
-
# lunar phase
|
|
1254
|
-
deg = self.user.lunar_phase["degrees_between_s_m"]
|
|
1255
|
-
|
|
1256
|
-
lffg = None
|
|
1257
|
-
lfbg = None
|
|
1258
|
-
lfcx = None
|
|
1259
|
-
lfr = None
|
|
1260
|
-
|
|
1261
|
-
if deg < 90.0:
|
|
1262
|
-
maxr = deg
|
|
1263
|
-
if deg > 80.0:
|
|
1264
|
-
maxr = maxr * maxr
|
|
1265
|
-
lfcx = 20.0 + (deg / 90.0) * (maxr + 10.0)
|
|
1266
|
-
lfr = 10.0 + (deg / 90.0) * maxr
|
|
1267
|
-
lffg = self.chart_colors_settings["lunar_phase_0"]
|
|
1268
|
-
lfbg = self.chart_colors_settings["lunar_phase_1"]
|
|
1269
|
-
|
|
1270
|
-
elif deg < 180.0:
|
|
1271
|
-
maxr = 180.0 - deg
|
|
1272
|
-
if deg < 100.0:
|
|
1273
|
-
maxr = maxr * maxr
|
|
1274
|
-
lfcx = 20.0 + ((deg - 90.0) / 90.0 * (maxr + 10.0)) - (maxr + 10.0)
|
|
1275
|
-
lfr = 10.0 + maxr - ((deg - 90.0) / 90.0 * maxr)
|
|
1276
|
-
lffg = self.chart_colors_settings["lunar_phase_1"]
|
|
1277
|
-
lfbg = self.chart_colors_settings["lunar_phase_0"]
|
|
1278
|
-
|
|
1279
|
-
elif deg < 270.0:
|
|
1280
|
-
maxr = deg - 180.0
|
|
1281
|
-
if deg > 260.0:
|
|
1282
|
-
maxr = maxr * maxr
|
|
1283
|
-
lfcx = 20.0 + ((deg - 180.0) / 90.0 * (maxr + 10.0))
|
|
1284
|
-
lfr = 10.0 + ((deg - 180.0) / 90.0 * maxr)
|
|
1285
|
-
lffg, lfbg = self.chart_colors_settings["lunar_phase_1"], self.chart_colors_settings["lunar_phase_0"]
|
|
1286
|
-
|
|
1287
|
-
elif deg < 361:
|
|
1288
|
-
maxr = 360.0 - deg
|
|
1289
|
-
if deg < 280.0:
|
|
1290
|
-
maxr = maxr * maxr
|
|
1291
|
-
lfcx = 20.0 + ((deg - 270.0) / 90.0 * (maxr + 10.0)) - (maxr + 10.0)
|
|
1292
|
-
lfr = 10.0 + maxr - ((deg - 270.0) / 90.0 * maxr)
|
|
1293
|
-
lffg, lfbg = self.chart_colors_settings["lunar_phase_0"], self.chart_colors_settings["lunar_phase_1"]
|
|
1294
|
-
|
|
1295
|
-
if lffg is None or lfbg is None or lfcx is None or lfr is None:
|
|
1296
|
-
raise KerykeionException("Lunar phase error")
|
|
1297
|
-
|
|
1298
|
-
td["lunar_phase_fg"] = lffg
|
|
1299
|
-
td["lunar_phase_bg"] = lfbg
|
|
1300
|
-
td["lunar_phase_cx"] = lfcx
|
|
1301
|
-
td["lunar_phase_r"] = lfr
|
|
1302
|
-
td["lunar_phase_outline"] = self.chart_colors_settings["lunar_phase_2"]
|
|
1303
|
-
|
|
1304
|
-
# rotation based on latitude
|
|
1305
|
-
td["lunar_phase_rotate"] = -90.0 - self.geolat
|
|
1306
|
-
|
|
1307
|
-
# stringlocation
|
|
419
|
+
# Set location string
|
|
1308
420
|
if len(self.location) > 35:
|
|
1309
|
-
|
|
1310
|
-
if len(
|
|
1311
|
-
|
|
1312
|
-
if len(
|
|
1313
|
-
|
|
421
|
+
split_location = self.location.split(",")
|
|
422
|
+
if len(split_location) > 1:
|
|
423
|
+
template_dict["stringLocation"] = split_location[0] + ", " + split_location[-1]
|
|
424
|
+
if len(template_dict["stringLocation"]) > 35:
|
|
425
|
+
template_dict["stringLocation"] = template_dict["stringLocation"][:35] + "..."
|
|
1314
426
|
else:
|
|
1315
|
-
|
|
427
|
+
template_dict["stringLocation"] = self.location[:35] + "..."
|
|
1316
428
|
else:
|
|
1317
|
-
|
|
429
|
+
template_dict["stringLocation"] = self.location
|
|
1318
430
|
|
|
431
|
+
# Set additional information for Synastry chart type
|
|
1319
432
|
if self.chart_type == "Synastry":
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
433
|
+
template_dict["stringLat"] = f"{self.t_user.name}: "
|
|
434
|
+
template_dict["stringLon"] = self.t_user.city
|
|
435
|
+
template_dict["stringPosition"] = f"{self.t_user.year}-{self.t_user.month}-{self.t_user.day} {self.t_user.hour:02d}:{self.t_user.minute:02d}"
|
|
1324
436
|
else:
|
|
1325
|
-
latitude_string = convert_latitude_coordinate_to_string(
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
437
|
+
latitude_string = convert_latitude_coordinate_to_string(self.geolat, self.language_settings['north'], self.language_settings['south'])
|
|
438
|
+
longitude_string = convert_longitude_coordinate_to_string(self.geolon, self.language_settings['east'], self.language_settings['west'])
|
|
439
|
+
template_dict["stringLat"] = f"{self.language_settings['latitude']}: {latitude_string}"
|
|
440
|
+
template_dict["stringLon"] = f"{self.language_settings['longitude']}: {longitude_string}"
|
|
441
|
+
template_dict["stringPosition"] = f"{self.language_settings['type']}: {self.chart_type}"
|
|
442
|
+
|
|
443
|
+
# Set paper colors
|
|
444
|
+
template_dict["paper_color_0"] = self.chart_colors_settings["paper_0"]
|
|
445
|
+
template_dict["paper_color_1"] = self.chart_colors_settings["paper_1"]
|
|
446
|
+
|
|
447
|
+
# Set planet colors
|
|
448
|
+
for planet in self.planets_settings:
|
|
449
|
+
planet_id = planet["id"]
|
|
450
|
+
template_dict[f"planets_color_{planet_id}"] = planet["color"] # type: ignore
|
|
451
|
+
|
|
452
|
+
# Set zodiac colors
|
|
453
|
+
for i in range(12):
|
|
454
|
+
template_dict[f"zodiac_color_{i}"] = self.chart_colors_settings[f"zodiac_icon_{i}"] # type: ignore
|
|
455
|
+
|
|
456
|
+
# Set orb colors
|
|
457
|
+
for aspect in self.aspects_settings:
|
|
458
|
+
template_dict[f"orb_color_{aspect['degree']}"] = aspect['color'] # type: ignore
|
|
459
|
+
|
|
460
|
+
# Drawing functions
|
|
461
|
+
template_dict["makeZodiac"] = self._draw_zodiac_circle_slices(self.main_radius)
|
|
462
|
+
|
|
463
|
+
first_subject_houses_list = get_houses_list(self.user)
|
|
464
|
+
|
|
465
|
+
# Draw houses grid and cusps
|
|
466
|
+
if self.chart_type in ["Transit", "Synastry"]:
|
|
467
|
+
second_subject_houses_list = get_houses_list(self.t_user)
|
|
468
|
+
|
|
469
|
+
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
470
|
+
main_subject_houses_list=first_subject_houses_list,
|
|
471
|
+
secondary_subject_houses_list=second_subject_houses_list,
|
|
472
|
+
chart_type=self.chart_type,
|
|
473
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
474
|
+
house_cusp_generale_name_label=self.language_settings["cusp"]
|
|
1329
475
|
)
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
self.
|
|
1333
|
-
|
|
476
|
+
|
|
477
|
+
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
478
|
+
r=self.main_radius,
|
|
479
|
+
first_subject_houses_list=first_subject_houses_list,
|
|
480
|
+
standard_house_cusp_color=self.chart_colors_settings["houses_radix_line"],
|
|
481
|
+
first_house_color=self.planets_settings[12]["color"],
|
|
482
|
+
tenth_house_color=self.planets_settings[13]["color"],
|
|
483
|
+
seventh_house_color=self.planets_settings[14]["color"],
|
|
484
|
+
fourth_house_color=self.planets_settings[15]["color"],
|
|
485
|
+
c1=self.first_circle_radius,
|
|
486
|
+
c3=self.third_circle_radius,
|
|
487
|
+
chart_type=self.chart_type,
|
|
488
|
+
second_subject_houses_list=second_subject_houses_list,
|
|
489
|
+
transit_house_cusp_color=self.chart_colors_settings["houses_transit_line"],
|
|
1334
490
|
)
|
|
1335
491
|
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
492
|
+
else:
|
|
493
|
+
template_dict["makeHousesGrid"] = draw_house_grid(
|
|
494
|
+
main_subject_houses_list=first_subject_houses_list,
|
|
495
|
+
chart_type=self.chart_type,
|
|
496
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
497
|
+
house_cusp_generale_name_label=self.language_settings["cusp"]
|
|
498
|
+
)
|
|
1339
499
|
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
500
|
+
template_dict["makeHouses"] = draw_houses_cusps_and_text_number(
|
|
501
|
+
r=self.main_radius,
|
|
502
|
+
first_subject_houses_list=first_subject_houses_list,
|
|
503
|
+
standard_house_cusp_color=self.chart_colors_settings["houses_radix_line"],
|
|
504
|
+
first_house_color=self.planets_settings[12]["color"],
|
|
505
|
+
tenth_house_color=self.planets_settings[13]["color"],
|
|
506
|
+
seventh_house_color=self.planets_settings[14]["color"],
|
|
507
|
+
fourth_house_color=self.planets_settings[15]["color"],
|
|
508
|
+
c1=self.first_circle_radius,
|
|
509
|
+
c3=self.third_circle_radius,
|
|
510
|
+
chart_type=self.chart_type,
|
|
511
|
+
)
|
|
1343
512
|
|
|
1344
|
-
#
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
513
|
+
# Draw planets
|
|
514
|
+
if self.chart_type in ["Transit", "Synastry"]:
|
|
515
|
+
template_dict["makePlanets"] = draw_planets(
|
|
516
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
517
|
+
available_planets_setting=self.available_planets_setting,
|
|
518
|
+
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
519
|
+
radius=self.main_radius,
|
|
520
|
+
main_subject_first_house_degree_ut=self.user.first_house.abs_pos,
|
|
521
|
+
main_subject_seventh_house_degree_ut=self.user.seventh_house.abs_pos,
|
|
522
|
+
chart_type=self.chart_type,
|
|
523
|
+
third_circle_radius=self.third_circle_radius,
|
|
524
|
+
)
|
|
525
|
+
else:
|
|
526
|
+
template_dict["makePlanets"] = draw_planets(
|
|
527
|
+
available_planets_setting=self.available_planets_setting,
|
|
528
|
+
chart_type=self.chart_type,
|
|
529
|
+
radius=self.main_radius,
|
|
530
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
531
|
+
third_circle_radius=self.third_circle_radius,
|
|
532
|
+
main_subject_first_house_degree_ut=self.user.first_house.abs_pos,
|
|
533
|
+
main_subject_seventh_house_degree_ut=self.user.seventh_house.abs_pos
|
|
534
|
+
)
|
|
1348
535
|
|
|
1349
|
-
#
|
|
1350
|
-
|
|
1351
|
-
td[f"zodiac_color_{i}"] = self.chart_colors_settings[f"zodiac_icon_{i}"]
|
|
1352
|
-
|
|
1353
|
-
# orb_color_X
|
|
1354
|
-
for i in range(len(self.aspects_settings)):
|
|
1355
|
-
td[f"orb_color_{self.aspects_settings[i]['degree']}"] = self.aspects_settings[i]['color']
|
|
1356
|
-
|
|
1357
|
-
# config
|
|
1358
|
-
td["cfgZoom"] = str(self.zoom)
|
|
1359
|
-
td["cfgRotate"] = rotate
|
|
1360
|
-
|
|
1361
|
-
# ---
|
|
1362
|
-
# Drawing Functions
|
|
1363
|
-
#---
|
|
1364
|
-
|
|
1365
|
-
td["makeZodiac"] = self._draw_zodiac_circle_slices(r)
|
|
1366
|
-
td["makeHousesGrid"] = self._draw_house_grid()
|
|
1367
|
-
# TODO: Add the rest of the functions
|
|
1368
|
-
td["makeHouses"] = self._makeHouses(r)
|
|
1369
|
-
td["makePlanets"] = self._make_planets(r)
|
|
1370
|
-
td["elements_percentages"] = draw_elements_percentages(
|
|
536
|
+
# Draw elements percentages
|
|
537
|
+
template_dict["elements_percentages"] = draw_elements_percentages(
|
|
1371
538
|
self.language_settings['fire'],
|
|
1372
539
|
self.fire,
|
|
1373
540
|
self.language_settings['earth'],
|
|
@@ -1377,29 +544,57 @@ class KerykeionChartSVG:
|
|
|
1377
544
|
self.language_settings['water'],
|
|
1378
545
|
self.water,
|
|
1379
546
|
)
|
|
1380
|
-
td["makePlanetGrid"] = self._makePlanetGrid()
|
|
1381
547
|
|
|
1382
|
-
#
|
|
548
|
+
# Draw planet grid
|
|
549
|
+
if self.chart_type in ["Transit", "Synastry"]:
|
|
550
|
+
if self.chart_type == "Transit":
|
|
551
|
+
second_subject_table_name = self.language_settings["transit_name"]
|
|
552
|
+
else:
|
|
553
|
+
second_subject_table_name = self.t_user.name
|
|
554
|
+
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
555
|
+
planets_and_houses_grid_title=self.language_settings["planets_and_house"],
|
|
556
|
+
subject_name=self.user.name,
|
|
557
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
558
|
+
chart_type=self.chart_type,
|
|
559
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
560
|
+
celestial_point_language=self.language_settings["celestial_points"],
|
|
561
|
+
second_subject_name=second_subject_table_name,
|
|
562
|
+
second_subject_available_kerykeion_celestial_points=self.t_available_kerykeion_celestial_points,
|
|
563
|
+
)
|
|
564
|
+
else:
|
|
565
|
+
template_dict["makePlanetGrid"] = draw_planet_grid(
|
|
566
|
+
planets_and_houses_grid_title=self.language_settings["planets_and_house"],
|
|
567
|
+
subject_name=self.user.name,
|
|
568
|
+
available_kerykeion_celestial_points=self.available_kerykeion_celestial_points,
|
|
569
|
+
chart_type=self.chart_type,
|
|
570
|
+
text_color=self.chart_colors_settings["paper_0"],
|
|
571
|
+
celestial_point_language=self.language_settings["celestial_points"],
|
|
572
|
+
)
|
|
573
|
+
|
|
574
|
+
# Set date time string
|
|
1383
575
|
dt = datetime.fromisoformat(self.user.iso_formatted_local_datetime)
|
|
1384
|
-
custom_format = dt.strftime('%Y
|
|
576
|
+
custom_format = dt.strftime('%Y-%m-%d %H:%M [%z]')
|
|
1385
577
|
custom_format = custom_format[:-3] + ':' + custom_format[-3:]
|
|
1386
|
-
|
|
578
|
+
template_dict["stringDateTime"] = f"{custom_format}"
|
|
1387
579
|
|
|
1388
|
-
return
|
|
580
|
+
return template_dict
|
|
1389
581
|
|
|
1390
582
|
def makeTemplate(self, minify: bool = False) -> str:
|
|
1391
583
|
"""Creates the template for the SVG file"""
|
|
1392
|
-
td = self.
|
|
584
|
+
td = self._create_template_dictionary()
|
|
1393
585
|
|
|
586
|
+
DATA_DIR = Path(__file__).parent
|
|
587
|
+
xml_svg = DATA_DIR / "templates" / "chart.xml"
|
|
588
|
+
|
|
1394
589
|
# read template
|
|
1395
|
-
with open(
|
|
590
|
+
with open(xml_svg, "r", encoding="utf-8", errors="ignore") as f:
|
|
1396
591
|
template = Template(f.read()).substitute(td)
|
|
1397
592
|
|
|
1398
593
|
# return filename
|
|
1399
594
|
|
|
1400
595
|
logging.debug(f"Template dictionary keys: {td.keys()}")
|
|
1401
596
|
|
|
1402
|
-
self.
|
|
597
|
+
self._create_template_dictionary()
|
|
1403
598
|
|
|
1404
599
|
if minify:
|
|
1405
600
|
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
@@ -1410,9 +605,9 @@ class KerykeionChartSVG:
|
|
|
1410
605
|
return template
|
|
1411
606
|
|
|
1412
607
|
def makeSVG(self, minify: bool = False):
|
|
1413
|
-
"""Prints out the SVG file in the
|
|
608
|
+
"""Prints out the SVG file in the specified folder"""
|
|
1414
609
|
|
|
1415
|
-
if not (self
|
|
610
|
+
if not hasattr(self, "template"):
|
|
1416
611
|
self.template = self.makeTemplate(minify)
|
|
1417
612
|
|
|
1418
613
|
self.chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart.svg"
|
|
@@ -1422,6 +617,70 @@ class KerykeionChartSVG:
|
|
|
1422
617
|
|
|
1423
618
|
logging.info(f"SVG Generated Correctly in: {self.chartname}")
|
|
1424
619
|
|
|
620
|
+
def makeWheelOnlyTemplate(self, minify: bool = False):
|
|
621
|
+
"""Creates the template for the SVG file with only the wheel"""
|
|
622
|
+
|
|
623
|
+
with open(Path(__file__).parent / "templates" / "wheel_only.xml", "r", encoding="utf-8", errors="ignore") as f:
|
|
624
|
+
template = f.read()
|
|
625
|
+
|
|
626
|
+
template_dict = self._create_template_dictionary()
|
|
627
|
+
template = Template(template).substitute(template_dict)
|
|
628
|
+
|
|
629
|
+
if minify:
|
|
630
|
+
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
631
|
+
|
|
632
|
+
else:
|
|
633
|
+
template = template.replace('"', "'")
|
|
634
|
+
|
|
635
|
+
return template
|
|
636
|
+
|
|
637
|
+
def makeWheelOnlySVG(self, minify: bool = False):
|
|
638
|
+
"""Prints out the SVG file in the specified folder with only the wheel"""
|
|
639
|
+
|
|
640
|
+
template = self.makeWheelOnlyTemplate(minify)
|
|
641
|
+
|
|
642
|
+
self.chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart - Wheel Only.svg"
|
|
643
|
+
|
|
644
|
+
with open(self.chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
645
|
+
output_file.write(template)
|
|
646
|
+
|
|
647
|
+
logging.info(f"SVG Generated Correctly in: {self.chartname}")
|
|
648
|
+
|
|
649
|
+
def makeAspectGridOnlyTemplate(self, minify: bool = False):
|
|
650
|
+
"""Creates the template for the SVG file with only the aspect grid"""
|
|
651
|
+
|
|
652
|
+
with open(Path(__file__).parent / "templates" / "aspect_grid_only.xml", "r", encoding="utf-8", errors="ignore") as f:
|
|
653
|
+
template = f.read()
|
|
654
|
+
|
|
655
|
+
template_dict = self._create_template_dictionary()
|
|
656
|
+
|
|
657
|
+
if self.chart_type in ["Transit", "Synastry"]:
|
|
658
|
+
aspects_grid = draw_transit_aspect_grid(self.chart_colors_settings['paper_0'], self.available_planets_setting, self.aspects_list)
|
|
659
|
+
else:
|
|
660
|
+
aspects_grid = draw_aspect_grid(self.chart_colors_settings['paper_0'], self.available_planets_setting, self.aspects_list, x_start=50, y_start=250)
|
|
661
|
+
|
|
662
|
+
template = Template(template).substitute({**template_dict, "makeAspectGrid": aspects_grid})
|
|
663
|
+
|
|
664
|
+
if minify:
|
|
665
|
+
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
666
|
+
|
|
667
|
+
else:
|
|
668
|
+
template = template.replace('"', "'")
|
|
669
|
+
|
|
670
|
+
return template
|
|
671
|
+
|
|
672
|
+
def makeAspectGridOnlySVG(self, minify: bool = False):
|
|
673
|
+
"""Prints out the SVG file in the specified folder with only the aspect grid"""
|
|
674
|
+
|
|
675
|
+
template = self.makeAspectGridOnlyTemplate(minify)
|
|
676
|
+
|
|
677
|
+
self.chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart - Aspect Grid Only.svg"
|
|
678
|
+
|
|
679
|
+
with open(self.chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
680
|
+
output_file.write(template)
|
|
681
|
+
|
|
682
|
+
logging.info(f"SVG Generated Correctly in: {self.chartname}")
|
|
683
|
+
|
|
1425
684
|
|
|
1426
685
|
if __name__ == "__main__":
|
|
1427
686
|
from kerykeion.utilities import setup_logging
|
|
@@ -1492,4 +751,139 @@ if __name__ == "__main__":
|
|
|
1492
751
|
# With Topocentric Perspective
|
|
1493
752
|
topocentric_subject = AstrologicalSubject("John Lennon - Topocentric", 1940, 10, 9, 18, 30, "Liverpool", "GB", perspective_type="Topocentric")
|
|
1494
753
|
topocentric_chart = KerykeionChartSVG(topocentric_subject)
|
|
1495
|
-
topocentric_chart.makeSVG()
|
|
754
|
+
topocentric_chart.makeSVG()
|
|
755
|
+
|
|
756
|
+
# Minified SVG
|
|
757
|
+
minified_subject = AstrologicalSubject("John Lennon - Minified", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
758
|
+
minified_chart = KerykeionChartSVG(minified_subject)
|
|
759
|
+
minified_chart.makeSVG(minify=True)
|
|
760
|
+
|
|
761
|
+
# Dark Theme Natal Chart
|
|
762
|
+
dark_theme_subject = AstrologicalSubject("John Lennon - Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
763
|
+
dark_theme_natal_chart = KerykeionChartSVG(dark_theme_subject, theme="dark")
|
|
764
|
+
dark_theme_natal_chart.makeSVG()
|
|
765
|
+
|
|
766
|
+
# Dark High Contrast Theme Natal Chart
|
|
767
|
+
dark_high_contrast_theme_subject = AstrologicalSubject("John Lennon - Dark High Contrast Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
768
|
+
dark_high_contrast_theme_natal_chart = KerykeionChartSVG(dark_high_contrast_theme_subject, theme="dark-high-contrast")
|
|
769
|
+
dark_high_contrast_theme_natal_chart.makeSVG()
|
|
770
|
+
|
|
771
|
+
# Light Theme Natal Chart
|
|
772
|
+
light_theme_subject = AstrologicalSubject("John Lennon - Light Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
773
|
+
light_theme_natal_chart = KerykeionChartSVG(light_theme_subject, theme="light")
|
|
774
|
+
light_theme_natal_chart.makeSVG()
|
|
775
|
+
|
|
776
|
+
# Dark Theme External Natal Chart
|
|
777
|
+
dark_theme_external_subject = AstrologicalSubject("John Lennon - Dark Theme External", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
778
|
+
dark_theme_external_chart = KerykeionChartSVG(dark_theme_external_subject, "ExternalNatal", second, theme="dark")
|
|
779
|
+
dark_theme_external_chart.makeSVG()
|
|
780
|
+
|
|
781
|
+
# Dark Theme Synastry Chart
|
|
782
|
+
dark_theme_synastry_subject = AstrologicalSubject("John Lennon - DTS", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
783
|
+
dark_theme_synastry_chart = KerykeionChartSVG(dark_theme_synastry_subject, "Synastry", second, theme="dark")
|
|
784
|
+
dark_theme_synastry_chart.makeSVG()
|
|
785
|
+
|
|
786
|
+
# Wheel Natal Only Chart
|
|
787
|
+
wheel_only_subject = AstrologicalSubject("John Lennon - Wheel Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
788
|
+
wheel_only_chart = KerykeionChartSVG(wheel_only_subject)
|
|
789
|
+
wheel_only_chart.makeWheelOnlySVG()
|
|
790
|
+
|
|
791
|
+
# Wheel External Natal Only Chart
|
|
792
|
+
wheel_external_subject = AstrologicalSubject("John Lennon - Wheel External Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
793
|
+
wheel_external_chart = KerykeionChartSVG(wheel_external_subject, "ExternalNatal", second)
|
|
794
|
+
wheel_external_chart.makeWheelOnlySVG()
|
|
795
|
+
|
|
796
|
+
# Wheel Synastry Only Chart
|
|
797
|
+
wheel_synastry_subject = AstrologicalSubject("John Lennon - Wheel Synastry Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
798
|
+
wheel_synastry_chart = KerykeionChartSVG(wheel_synastry_subject, "Synastry", second)
|
|
799
|
+
wheel_synastry_chart.makeWheelOnlySVG()
|
|
800
|
+
|
|
801
|
+
# Wheel Transit Only Chart
|
|
802
|
+
wheel_transit_subject = AstrologicalSubject("John Lennon - Wheel Transit Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
803
|
+
wheel_transit_chart = KerykeionChartSVG(wheel_transit_subject, "Transit", second)
|
|
804
|
+
wheel_transit_chart.makeWheelOnlySVG()
|
|
805
|
+
|
|
806
|
+
# Wheel Sidereal Birth Chart (Lahiri) Dark Theme
|
|
807
|
+
sidereal_dark_subject = AstrologicalSubject("John Lennon Lahiri - Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="LAHIRI")
|
|
808
|
+
sidereal_dark_chart = KerykeionChartSVG(sidereal_dark_subject, theme="dark")
|
|
809
|
+
sidereal_dark_chart.makeWheelOnlySVG()
|
|
810
|
+
|
|
811
|
+
# Wheel Sidereal Birth Chart (Fagan-Bradley) Light Theme
|
|
812
|
+
sidereal_light_subject = AstrologicalSubject("John Lennon Fagan-Bradley - Light Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="FAGAN_BRADLEY")
|
|
813
|
+
sidereal_light_chart = KerykeionChartSVG(sidereal_light_subject, theme="light")
|
|
814
|
+
sidereal_light_chart.makeWheelOnlySVG()
|
|
815
|
+
|
|
816
|
+
# Aspect Grid Only Natal Chart
|
|
817
|
+
aspect_grid_only_subject = AstrologicalSubject("John Lennon - Aspect Grid Only", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
818
|
+
aspect_grid_only_chart = KerykeionChartSVG(aspect_grid_only_subject)
|
|
819
|
+
aspect_grid_only_chart.makeAspectGridOnlySVG()
|
|
820
|
+
|
|
821
|
+
# Aspect Grid Only Dark Theme Natal Chart
|
|
822
|
+
aspect_grid_dark_subject = AstrologicalSubject("John Lennon - Aspect Grid Dark Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
823
|
+
aspect_grid_dark_chart = KerykeionChartSVG(aspect_grid_dark_subject, theme="dark")
|
|
824
|
+
aspect_grid_dark_chart.makeAspectGridOnlySVG()
|
|
825
|
+
|
|
826
|
+
# Aspect Grid Only Light Theme Natal Chart
|
|
827
|
+
aspect_grid_light_subject = AstrologicalSubject("John Lennon - Aspect Grid Light Theme", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
828
|
+
aspect_grid_light_chart = KerykeionChartSVG(aspect_grid_light_subject, theme="light")
|
|
829
|
+
aspect_grid_light_chart.makeAspectGridOnlySVG()
|
|
830
|
+
|
|
831
|
+
# Synastry Chart Aspect Grid Only
|
|
832
|
+
aspect_grid_synastry_subject = AstrologicalSubject("John Lennon - Aspect Grid Synastry", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
833
|
+
aspect_grid_synastry_chart = KerykeionChartSVG(aspect_grid_synastry_subject, "Synastry", second)
|
|
834
|
+
aspect_grid_synastry_chart.makeAspectGridOnlySVG()
|
|
835
|
+
|
|
836
|
+
# Transit Chart Aspect Grid Only
|
|
837
|
+
aspect_grid_transit_subject = AstrologicalSubject("John Lennon - Aspect Grid Transit", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
838
|
+
aspect_grid_transit_chart = KerykeionChartSVG(aspect_grid_transit_subject, "Transit", second)
|
|
839
|
+
aspect_grid_transit_chart.makeAspectGridOnlySVG()
|
|
840
|
+
|
|
841
|
+
# Synastry Chart Aspect Grid Only Dark Theme
|
|
842
|
+
aspect_grid_dark_synastry_subject = AstrologicalSubject("John Lennon - Aspect Grid Dark Synastry", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
843
|
+
aspect_grid_dark_synastry_chart = KerykeionChartSVG(aspect_grid_dark_synastry_subject, "Synastry", second, theme="dark")
|
|
844
|
+
aspect_grid_dark_synastry_chart.makeAspectGridOnlySVG()
|
|
845
|
+
|
|
846
|
+
# Transit Chart With draw_transit_aspect_grid table
|
|
847
|
+
transit_chart_with_table_grid_subject = AstrologicalSubject("John Lennon - TCWTG", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
848
|
+
transit_chart_with_table_grid = KerykeionChartSVG(transit_chart_with_table_grid_subject, "Transit", second, double_chart_aspect_grid_type="table", theme="dark")
|
|
849
|
+
transit_chart_with_table_grid.makeSVG()
|
|
850
|
+
|
|
851
|
+
# Chines Language Chart
|
|
852
|
+
chinese_subject = AstrologicalSubject("Hua Chenyu", 1990, 2, 7, 12, 0, "Hunan", "CN")
|
|
853
|
+
chinese_chart = KerykeionChartSVG(chinese_subject, chart_language="CN")
|
|
854
|
+
chinese_chart.makeSVG()
|
|
855
|
+
|
|
856
|
+
# French Language Chart
|
|
857
|
+
french_subject = AstrologicalSubject("Jeanne Moreau", 1928, 1, 23, 10, 0, "Paris", "FR")
|
|
858
|
+
french_chart = KerykeionChartSVG(french_subject, chart_language="FR")
|
|
859
|
+
french_chart.makeSVG()
|
|
860
|
+
|
|
861
|
+
# Spanish Language Chart
|
|
862
|
+
spanish_subject = AstrologicalSubject("Antonio Banderas", 1960, 8, 10, 12, 0, "Malaga", "ES")
|
|
863
|
+
spanish_chart = KerykeionChartSVG(spanish_subject, chart_language="ES")
|
|
864
|
+
spanish_chart.makeSVG()
|
|
865
|
+
|
|
866
|
+
# Portuguese Language Chart
|
|
867
|
+
portuguese_subject = AstrologicalSubject("Cristiano Ronaldo", 1985, 2, 5, 5, 25, "Funchal", "PT")
|
|
868
|
+
portuguese_chart = KerykeionChartSVG(portuguese_subject, chart_language="PT")
|
|
869
|
+
portuguese_chart.makeSVG()
|
|
870
|
+
|
|
871
|
+
# Italian Language Chart
|
|
872
|
+
italian_subject = AstrologicalSubject("Sophia Loren", 1934, 9, 20, 2, 0, "Rome", "IT")
|
|
873
|
+
italian_chart = KerykeionChartSVG(italian_subject, chart_language="IT")
|
|
874
|
+
italian_chart.makeSVG()
|
|
875
|
+
|
|
876
|
+
# Russian Language Chart
|
|
877
|
+
russian_subject = AstrologicalSubject("Mikhail Bulgakov", 1891, 5, 15, 12, 0, "Kiev", "UA")
|
|
878
|
+
russian_chart = KerykeionChartSVG(russian_subject, chart_language="RU")
|
|
879
|
+
russian_chart.makeSVG()
|
|
880
|
+
|
|
881
|
+
# Turkish Language Chart
|
|
882
|
+
turkish_subject = AstrologicalSubject("Mehmet Oz", 1960, 6, 11, 12, 0, "Istanbul", "TR")
|
|
883
|
+
turkish_chart = KerykeionChartSVG(turkish_subject, chart_language="TR")
|
|
884
|
+
turkish_chart.makeSVG()
|
|
885
|
+
|
|
886
|
+
# German Language Chart
|
|
887
|
+
german_subject = AstrologicalSubject("Albert Einstein", 1879, 3, 14, 11, 30, "Ulm", "DE")
|
|
888
|
+
german_chart = KerykeionChartSVG(german_subject, chart_language="DE")
|
|
889
|
+
german_chart.makeSVG()
|