kerykeion 4.0.6__py3-none-any.whl → 4.12.3__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 +4 -96
- kerykeion/aspects/__init__.py +2 -2
- kerykeion/aspects/aspects_utils.py +174 -0
- kerykeion/aspects/natal_aspects.py +51 -222
- kerykeion/aspects/synastry_aspects.py +45 -23
- kerykeion/astrological_subject.py +453 -199
- kerykeion/charts/__init__.py +1 -1
- kerykeion/charts/charts_utils.py +339 -5
- kerykeion/charts/kerykeion_chart_svg.py +441 -500
- kerykeion/charts/templates/chart.xml +362 -330
- kerykeion/enums.py +50 -0
- kerykeion/fetch_geonames.py +16 -25
- kerykeion/kr_types/__init__.py +7 -0
- kerykeion/kr_types/chart_types.py +33 -32
- kerykeion/kr_types/kerykeion_exception.py +1 -1
- kerykeion/kr_types/kr_literals.py +87 -44
- kerykeion/kr_types/kr_models.py +42 -78
- kerykeion/kr_types/settings_models.py +163 -0
- kerykeion/relationship_score.py +7 -13
- kerykeion/report.py +3 -0
- kerykeion/settings/__init__.py +1 -1
- kerykeion/settings/kerykeion_settings.py +13 -183
- kerykeion/settings/kr.config.json +9 -9
- kerykeion/utilities.py +184 -22
- {kerykeion-4.0.6.dist-info → kerykeion-4.12.3.dist-info}/METADATA +142 -32
- kerykeion-4.12.3.dist-info/RECORD +32 -0
- {kerykeion-4.0.6.dist-info → kerykeion-4.12.3.dist-info}/WHEEL +1 -1
- kerykeion-4.0.6.dist-info/RECORD +0 -29
- {kerykeion-4.0.6.dist-info → kerykeion-4.12.3.dist-info}/LICENSE +0 -0
- {kerykeion-4.0.6.dist-info → kerykeion-4.12.3.dist-info}/entry_points.txt +0 -0
|
@@ -1,30 +1,40 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""
|
|
3
|
-
This is part of Kerykeion (C)
|
|
3
|
+
This is part of Kerykeion (C) 2024 Giacomo Battaglia
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import logging
|
|
8
8
|
|
|
9
|
-
from
|
|
10
|
-
from kerykeion.settings.kerykeion_settings import get_settings_dict
|
|
9
|
+
from kerykeion.settings.kerykeion_settings import get_settings
|
|
11
10
|
from kerykeion.aspects.synastry_aspects import SynastryAspects
|
|
12
11
|
from kerykeion.aspects.natal_aspects import NatalAspects
|
|
13
12
|
from kerykeion.astrological_subject import AstrologicalSubject
|
|
14
13
|
from kerykeion.kr_types import KerykeionException, ChartType
|
|
15
|
-
from kerykeion.kr_types
|
|
16
|
-
from kerykeion.
|
|
17
|
-
from
|
|
14
|
+
from kerykeion.kr_types import ChartTemplateDictionary
|
|
15
|
+
from kerykeion.kr_types.settings_models import KerykeionSettingsCelestialPointModel
|
|
16
|
+
from kerykeion.charts.charts_utils import (
|
|
17
|
+
degreeDiff,
|
|
18
|
+
sliceToX,
|
|
19
|
+
sliceToY,
|
|
20
|
+
draw_zodiac_slice,
|
|
21
|
+
convert_latitude_coordinate_to_string,
|
|
22
|
+
convert_longitude_coordinate_to_string,
|
|
23
|
+
draw_aspect_line,
|
|
24
|
+
draw_elements_percentages,
|
|
25
|
+
convert_decimal_to_degree_string,
|
|
26
|
+
draw_transit_ring_degree_steps,
|
|
27
|
+
draw_degree_ring,
|
|
28
|
+
draw_transit_ring,
|
|
29
|
+
draw_first_circle,
|
|
30
|
+
draw_second_circle
|
|
31
|
+
)
|
|
18
32
|
from pathlib import Path
|
|
33
|
+
from scour.scour import scourString
|
|
19
34
|
from string import Template
|
|
20
|
-
from typing import Union
|
|
21
|
-
|
|
35
|
+
from typing import Union, List
|
|
36
|
+
from datetime import datetime
|
|
22
37
|
|
|
23
|
-
logger = getLogger(__name__)
|
|
24
|
-
basicConfig(
|
|
25
|
-
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
26
|
-
level="INFO"
|
|
27
|
-
)
|
|
28
38
|
|
|
29
39
|
|
|
30
40
|
class KerykeionChartSVG:
|
|
@@ -36,11 +46,17 @@ class KerykeionChartSVG:
|
|
|
36
46
|
- first_obj: First kerykeion object
|
|
37
47
|
- chart_type: Natal, ExternalNatal, Transit, Synastry (Default: Type="Natal").
|
|
38
48
|
- second_obj: Second kerykeion object (Not required if type is Natal)
|
|
39
|
-
- new_output_directory: Set the output directory (default:
|
|
40
|
-
-
|
|
41
|
-
|
|
49
|
+
- new_output_directory: Set the output directory (default: home directory).
|
|
50
|
+
- new_settings_file: Set the settings file (default: kr.config.json).
|
|
51
|
+
In the settings file you can set the language, colors, planets, aspects, etc.
|
|
42
52
|
"""
|
|
53
|
+
|
|
54
|
+
# Constants
|
|
55
|
+
_DEFAULT_HEIGHT = 546.0
|
|
56
|
+
_DEFAULT_FULL_WIDTH = 1200
|
|
57
|
+
_DEFAULT_NATAL_WIDTH = 772.2
|
|
43
58
|
|
|
59
|
+
# Set at init
|
|
44
60
|
first_obj: AstrologicalSubject
|
|
45
61
|
second_obj: Union[AstrologicalSubject, None]
|
|
46
62
|
chart_type: ChartType
|
|
@@ -48,6 +64,44 @@ class KerykeionChartSVG:
|
|
|
48
64
|
new_settings_file: Union[Path, None]
|
|
49
65
|
output_directory: Path
|
|
50
66
|
|
|
67
|
+
# Internal properties
|
|
68
|
+
fire: float
|
|
69
|
+
earth: float
|
|
70
|
+
air: float
|
|
71
|
+
water: float
|
|
72
|
+
c1: float
|
|
73
|
+
c2: float
|
|
74
|
+
c3: float
|
|
75
|
+
homedir: Path
|
|
76
|
+
xml_svg: Path
|
|
77
|
+
width: Union[float, int]
|
|
78
|
+
language_settings: dict
|
|
79
|
+
chart_colors_settings: dict
|
|
80
|
+
planets_settings: dict
|
|
81
|
+
aspects_settings: dict
|
|
82
|
+
planet_in_zodiac_extra_points: int
|
|
83
|
+
chart_settings: dict
|
|
84
|
+
user: AstrologicalSubject
|
|
85
|
+
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
|
+
height: float
|
|
98
|
+
location: str
|
|
99
|
+
geolat: float
|
|
100
|
+
geolon: float
|
|
101
|
+
zoom: int
|
|
102
|
+
zodiac: tuple
|
|
103
|
+
template: str
|
|
104
|
+
|
|
51
105
|
def __init__(
|
|
52
106
|
self,
|
|
53
107
|
first_obj: AstrologicalSubject,
|
|
@@ -68,56 +122,59 @@ class KerykeionChartSVG:
|
|
|
68
122
|
|
|
69
123
|
self.xml_svg = DATA_DIR / "templates/chart.xml"
|
|
70
124
|
|
|
71
|
-
# SVG Width
|
|
72
|
-
self.natal_width = 772.2
|
|
73
|
-
self.full_width = 1200
|
|
74
|
-
|
|
75
125
|
self.parse_json_settings(new_settings_file)
|
|
76
126
|
self.chart_type = chart_type
|
|
77
127
|
|
|
78
128
|
# Kerykeion instance
|
|
79
129
|
self.user = first_obj
|
|
80
130
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
self.
|
|
131
|
+
self.available_planets_setting = []
|
|
132
|
+
for body in self.planets_settings:
|
|
133
|
+
if body['is_active'] == False:
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
self.available_planets_setting.append(body)
|
|
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"
|
|
87
152
|
]
|
|
88
153
|
|
|
154
|
+
# Available bodies
|
|
155
|
+
available_celestial_points = []
|
|
156
|
+
for body in self.available_planets_setting:
|
|
157
|
+
available_celestial_points.append(body["name"].lower())
|
|
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
|
+
|
|
89
164
|
# Make a list of the relative degrees of the points in the graphic.
|
|
90
165
|
self.points_deg = []
|
|
91
|
-
for planet in
|
|
92
|
-
self.points_deg.append(planet
|
|
93
|
-
|
|
94
|
-
self.points_deg = self.points_deg + [
|
|
95
|
-
self.user.houses_list[0]["position"],
|
|
96
|
-
self.user.houses_list[9]["position"],
|
|
97
|
-
self.user.houses_list[6]["position"],
|
|
98
|
-
self.user.houses_list[3]["position"],
|
|
99
|
-
]
|
|
166
|
+
for planet in available_celestial_points:
|
|
167
|
+
self.points_deg.append(self.user.get(planet).position)
|
|
100
168
|
|
|
101
169
|
# Make list of the points sign
|
|
102
170
|
self.points_sign = []
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
self.points_sign.append(planet["sign_num"])
|
|
106
|
-
|
|
107
|
-
self.points_sign = self.points_sign + [
|
|
108
|
-
self.user.houses_list[0]["sign_num"],
|
|
109
|
-
self.user.houses_list[9]["sign_num"],
|
|
110
|
-
self.user.houses_list[6]["sign_num"],
|
|
111
|
-
self.user.houses_list[3]["sign_num"],
|
|
112
|
-
]
|
|
171
|
+
for planet in available_celestial_points:
|
|
172
|
+
self.points_sign.append(self.user.get(planet).sign_num)
|
|
113
173
|
|
|
114
174
|
# Make a list of points if they are retrograde or not.
|
|
115
175
|
self.points_retrograde = []
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
self.points_retrograde.append(planet["retrograde"])
|
|
119
|
-
|
|
120
|
-
self.points_retrograde = self.points_retrograde + [False, False, False, False]
|
|
176
|
+
for planet in available_celestial_points:
|
|
177
|
+
self.points_retrograde.append(self.user.get(planet).retrograde)
|
|
121
178
|
|
|
122
179
|
# Makes the sign number list.
|
|
123
180
|
|
|
@@ -127,7 +184,7 @@ class KerykeionChartSVG:
|
|
|
127
184
|
|
|
128
185
|
if self.chart_type == "Natal" or self.chart_type == "ExternalNatal":
|
|
129
186
|
natal_aspects_instance = NatalAspects(self.user, new_settings_file=self.new_settings_file)
|
|
130
|
-
self.aspects_list = natal_aspects_instance.
|
|
187
|
+
self.aspects_list = natal_aspects_instance.relevant_aspects
|
|
131
188
|
|
|
132
189
|
# TODO: If not second should exit
|
|
133
190
|
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
@@ -138,112 +195,45 @@ class KerykeionChartSVG:
|
|
|
138
195
|
self.t_user = second_obj
|
|
139
196
|
|
|
140
197
|
# Make a list for the absolute degrees of the points of the graphic.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
self.t_user.
|
|
144
|
-
self.t_user.houses_degree_ut[9],
|
|
145
|
-
self.t_user.houses_degree_ut[6],
|
|
146
|
-
self.t_user.houses_degree_ut[3],
|
|
147
|
-
]
|
|
198
|
+
self.t_points_deg_ut = []
|
|
199
|
+
for planet in available_celestial_points:
|
|
200
|
+
self.t_points_deg_ut.append(self.t_user.get(planet).abs_pos)
|
|
148
201
|
|
|
149
202
|
# Make a list of the relative degrees of the points in the graphic.
|
|
150
|
-
|
|
151
203
|
self.t_points_deg = []
|
|
152
|
-
for planet in
|
|
153
|
-
self.t_points_deg.append(planet
|
|
154
|
-
|
|
155
|
-
self.t_points_deg = self.t_points_deg + [
|
|
156
|
-
self.t_user.houses_list[0]["position"],
|
|
157
|
-
self.t_user.houses_list[9]["position"],
|
|
158
|
-
self.t_user.houses_list[6]["position"],
|
|
159
|
-
self.t_user.houses_list[3]["position"],
|
|
160
|
-
]
|
|
204
|
+
for planet in available_celestial_points:
|
|
205
|
+
self.t_points_deg.append(self.t_user.get(planet).position)
|
|
161
206
|
|
|
162
207
|
# Make list of the poits sign.
|
|
163
|
-
|
|
164
208
|
self.t_points_sign = []
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
self.t_points_sign.append(planet["sign_num"])
|
|
168
|
-
|
|
169
|
-
self.t_points_sign = self.t_points_sign + [
|
|
170
|
-
self.t_user.houses_list[0]["sign_num"],
|
|
171
|
-
self.t_user.houses_list[9]["sign_num"],
|
|
172
|
-
self.t_user.houses_list[6]["sign_num"],
|
|
173
|
-
self.t_user.houses_list[3]["sign_num"],
|
|
174
|
-
]
|
|
209
|
+
for planet in available_celestial_points:
|
|
210
|
+
self.t_points_sign.append(self.t_user.get(planet).sign_num)
|
|
175
211
|
|
|
176
212
|
# Make a list of poits if they are retrograde or not.
|
|
177
|
-
|
|
178
213
|
self.t_points_retrograde = []
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
self.t_points_retrograde.append(planet["retrograde"])
|
|
182
|
-
|
|
183
|
-
self.t_points_retrograde = self.t_points_retrograde + [False, False, False, False]
|
|
214
|
+
for planet in available_celestial_points:
|
|
215
|
+
self.t_points_retrograde.append(self.t_user.get(planet).retrograde)
|
|
184
216
|
|
|
185
217
|
self.t_houses_sign_graph = []
|
|
186
218
|
for h in self.t_user.houses_list:
|
|
187
219
|
self.t_houses_sign_graph.append(h["sign_num"])
|
|
188
220
|
|
|
189
221
|
# screen size
|
|
190
|
-
|
|
191
|
-
|
|
222
|
+
self.height = self._DEFAULT_HEIGHT
|
|
223
|
+
if self.chart_type == "Synastry" or self.chart_type == "Transit":
|
|
224
|
+
self.width = self._DEFAULT_FULL_WIDTH
|
|
192
225
|
else:
|
|
193
|
-
self.
|
|
194
|
-
self.screen_height = 772.2
|
|
195
|
-
|
|
196
|
-
# check for home
|
|
197
|
-
self.home_location = self.user.city
|
|
198
|
-
self.home_geolat = self.user.lat
|
|
199
|
-
self.home_geolon = self.user.lng
|
|
200
|
-
self.home_countrycode = self.user.nation
|
|
201
|
-
self.home_timezonestr = self.user.tz_str
|
|
202
|
-
|
|
203
|
-
print(f"{self.user.name} birth location: {self.home_location}, {self.home_geolat}, {self.home_geolon}")
|
|
226
|
+
self.width = self._DEFAULT_NATAL_WIDTH
|
|
204
227
|
|
|
205
228
|
# default location
|
|
206
|
-
self.location = self.
|
|
207
|
-
self.geolat =
|
|
208
|
-
self.geolon =
|
|
209
|
-
|
|
210
|
-
self.
|
|
211
|
-
|
|
212
|
-
# current datetime
|
|
213
|
-
now = datetime.now()
|
|
214
|
-
|
|
215
|
-
# aware datetime object
|
|
216
|
-
dt_input = datetime(now.year, now.month, now.day, now.hour, now.minute, now.second)
|
|
217
|
-
dt = pytz.timezone(self.timezonestr).localize(dt_input)
|
|
218
|
-
|
|
219
|
-
# naive utc datetime object
|
|
220
|
-
dt_utc = dt.replace(tzinfo=None) - dt.utcoffset() # type: ignore
|
|
221
|
-
|
|
222
|
-
# Default
|
|
223
|
-
self.name = self.user.name
|
|
224
|
-
self.charttype = self.chart_type
|
|
225
|
-
self.year = self.user.utc.year
|
|
226
|
-
self.month = self.user.utc.month
|
|
227
|
-
self.day = self.user.utc.day
|
|
228
|
-
self.hour = self.user.utc.hour + self.user.utc.minute / 100
|
|
229
|
-
self.timezone = offsetToTz(dt.utcoffset())
|
|
230
|
-
self.altitude = 25
|
|
231
|
-
self.geonameid = None
|
|
232
|
-
|
|
233
|
-
# Transit
|
|
229
|
+
self.location = self.user.city
|
|
230
|
+
self.geolat = self.user.lat
|
|
231
|
+
self.geolon = self.user.lng
|
|
232
|
+
|
|
233
|
+
logging.info(f"{self.user.name} birth location: {self.location}, {self.geolat}, {self.geolon}")
|
|
234
234
|
|
|
235
235
|
if self.chart_type == "Transit":
|
|
236
|
-
self.t_geolon = self.geolon
|
|
237
|
-
self.t_geolat = self.geolat
|
|
238
|
-
self.t_altitude = self.altitude
|
|
239
236
|
self.t_name = self.language_settings["transit_name"]
|
|
240
|
-
self.t_year = dt_utc.year
|
|
241
|
-
self.t_month = dt_utc.month
|
|
242
|
-
self.t_day = dt_utc.day
|
|
243
|
-
self.t_hour = decHourJoin(dt_utc.hour, dt_utc.minute, dt_utc.second)
|
|
244
|
-
self.t_timezone = offsetToTz(dt.utcoffset())
|
|
245
|
-
self.t_altitude = 25
|
|
246
|
-
self.t_geonameid = None
|
|
247
237
|
|
|
248
238
|
# configuration
|
|
249
239
|
# ZOOM 1 = 100%
|
|
@@ -264,22 +254,20 @@ class KerykeionChartSVG:
|
|
|
264
254
|
{"name": "pisces", "element": "water"},
|
|
265
255
|
)
|
|
266
256
|
|
|
267
|
-
|
|
268
|
-
self.template = self.makeTemplate()
|
|
257
|
+
self.template = None
|
|
269
258
|
|
|
270
259
|
def set_output_directory(self, dir_path: Path) -> None:
|
|
271
260
|
"""
|
|
272
261
|
Sets the output direcotry and returns it's path.
|
|
273
262
|
"""
|
|
274
263
|
self.output_directory = dir_path
|
|
275
|
-
|
|
276
|
-
return print(dir_string)
|
|
264
|
+
logging.info(f"Output direcotry set to: {self.output_directory}")
|
|
277
265
|
|
|
278
266
|
def parse_json_settings(self, settings_file):
|
|
279
267
|
"""
|
|
280
268
|
Parse the settings file.
|
|
281
269
|
"""
|
|
282
|
-
settings =
|
|
270
|
+
settings = get_settings(settings_file)
|
|
283
271
|
|
|
284
272
|
language = settings["general_settings"]["language"]
|
|
285
273
|
self.language_settings = settings["language_settings"].get(language, "EN")
|
|
@@ -289,163 +277,30 @@ class KerykeionChartSVG:
|
|
|
289
277
|
self.planet_in_zodiac_extra_points = settings["general_settings"]["planet_in_zodiac_extra_points"]
|
|
290
278
|
self.chart_settings = settings["chart_settings"]
|
|
291
279
|
|
|
292
|
-
def
|
|
293
|
-
"""
|
|
294
|
-
Draws the transit ring.
|
|
295
|
-
"""
|
|
296
|
-
radius_offset = 18
|
|
297
|
-
|
|
298
|
-
out = f'<circle cx="{r}" cy="{r}" r="{r - radius_offset}" style="fill: none; stroke: {self.chart_colors_settings["paper_1"]}; stroke-width: 36px; stroke-opacity: .4;"/>'
|
|
299
|
-
out += f'<circle cx="{r}" cy="{r}" r="{r}" style="fill: none; stroke: {self.chart_colors_settings["zodiac_transit_ring_3"]}; stroke-width: 1px; stroke-opacity: .6;"/>'
|
|
300
|
-
|
|
301
|
-
return out
|
|
302
|
-
|
|
303
|
-
def _degreeRing(self, r) -> str:
|
|
280
|
+
def _draw_zodiac_circle_slices(self, r):
|
|
304
281
|
"""
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
out = ""
|
|
308
|
-
for i in range(72):
|
|
309
|
-
offset = float(i * 5) - self.user.houses_degree_ut[6]
|
|
310
|
-
if offset < 0:
|
|
311
|
-
offset = offset + 360.0
|
|
312
|
-
elif offset > 360:
|
|
313
|
-
offset = offset - 360.0
|
|
314
|
-
x1 = sliceToX(0, r - self.c1, offset) + self.c1
|
|
315
|
-
y1 = sliceToY(0, r - self.c1, offset) + self.c1
|
|
316
|
-
x2 = sliceToX(0, r + 2 - self.c1, offset) - 2 + self.c1
|
|
317
|
-
y2 = sliceToY(0, r + 2 - self.c1, offset) - 2 + self.c1
|
|
318
|
-
|
|
319
|
-
out += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {self.chart_colors_settings["paper_0"]}; stroke-width: 1px; stroke-opacity:.9;"/>'
|
|
320
|
-
|
|
321
|
-
return out
|
|
322
|
-
|
|
323
|
-
def _degreeTransitRing(self, r):
|
|
324
|
-
out = ""
|
|
325
|
-
for i in range(72):
|
|
326
|
-
offset = float(i * 5) - self.user.houses_degree_ut[6]
|
|
327
|
-
if offset < 0:
|
|
328
|
-
offset = offset + 360.0
|
|
329
|
-
elif offset > 360:
|
|
330
|
-
offset = offset - 360.0
|
|
331
|
-
x1 = sliceToX(0, r, offset)
|
|
332
|
-
y1 = sliceToY(0, r, offset)
|
|
333
|
-
x2 = sliceToX(0, r + 2, offset) - 2
|
|
334
|
-
y2 = sliceToY(0, r + 2, offset) - 2
|
|
335
|
-
out += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: #F00; stroke-width: 1px; stroke-opacity:.9;"/>'
|
|
336
|
-
|
|
337
|
-
return out
|
|
338
|
-
|
|
339
|
-
def _lat2str(self, coord):
|
|
340
|
-
"""Converts a floating point latitude to string with
|
|
341
|
-
degree, minutes and seconds and the appropriate sign
|
|
342
|
-
(north or south). Eg. 52.1234567 -> 52°7'25" N
|
|
282
|
+
Generate the SVG string representing the zodiac circle
|
|
283
|
+
with the 12 slices for each zodiac sign.
|
|
343
284
|
|
|
344
285
|
Args:
|
|
345
|
-
|
|
346
|
-
Returns:
|
|
347
|
-
str: latitude in string format with degree, minutes,
|
|
348
|
-
seconds and sign (N/S)
|
|
349
|
-
"""
|
|
350
|
-
|
|
351
|
-
sign = self.language_settings["north"]
|
|
352
|
-
if coord < 0.0:
|
|
353
|
-
sign = self.language_settings["south"]
|
|
354
|
-
coord = abs(coord)
|
|
355
|
-
deg = int(coord)
|
|
356
|
-
min = int((float(coord) - deg) * 60)
|
|
357
|
-
sec = int(round(float(((float(coord) - deg) * 60) - min) * 60.0))
|
|
358
|
-
return f"{deg}°{min}'{sec}\" {sign}"
|
|
286
|
+
r (float): The radius of the zodiac slices.
|
|
359
287
|
|
|
360
|
-
def _lon2str(self, coord):
|
|
361
|
-
"""Converts a floating point longitude to string with
|
|
362
|
-
degree, minutes and seconds and the appropriate sign
|
|
363
|
-
(east or west). Eg. 52.1234567 -> 52°7'25" E
|
|
364
|
-
|
|
365
|
-
Args:
|
|
366
|
-
coord (float): longitude in floating point format
|
|
367
288
|
Returns:
|
|
368
|
-
str:
|
|
369
|
-
seconds and sign (E/W)
|
|
289
|
+
str: The SVG string representing the zodiac circle.
|
|
370
290
|
"""
|
|
371
291
|
|
|
372
|
-
sign = self.language_settings["east"]
|
|
373
|
-
if coord < 0.0:
|
|
374
|
-
sign = self.language_settings["west"]
|
|
375
|
-
coord = abs(coord)
|
|
376
|
-
deg = int(coord)
|
|
377
|
-
min = int((float(coord) - deg) * 60)
|
|
378
|
-
sec = int(round(float(((float(coord) - deg) * 60) - min) * 60.0))
|
|
379
|
-
return f"{deg}°{min}'{sec}\" {sign}"
|
|
380
|
-
|
|
381
|
-
def _dec2deg(self, dec, type="3"):
|
|
382
|
-
"""Coverts decimal float to degrees in format
|
|
383
|
-
a°b'c".
|
|
384
|
-
"""
|
|
385
|
-
|
|
386
|
-
dec = float(dec)
|
|
387
|
-
a = int(dec)
|
|
388
|
-
a_new = (dec - float(a)) * 60.0
|
|
389
|
-
b_rounded = int(round(a_new))
|
|
390
|
-
b = int(a_new)
|
|
391
|
-
c = int(round((a_new - float(b)) * 60.0))
|
|
392
|
-
if type == "3":
|
|
393
|
-
out = f"{a:02d}°{b:02d}'{c:02d}""
|
|
394
|
-
elif type == "2":
|
|
395
|
-
out = f"{a:02d}°{b_rounded:02d}'"
|
|
396
|
-
elif type == "1":
|
|
397
|
-
out = f"{a:02d}°"
|
|
398
|
-
else:
|
|
399
|
-
raise KerykeionException(f"Wrong type: {type}, it must be 1, 2 or 3.")
|
|
400
|
-
return str(out)
|
|
401
|
-
|
|
402
|
-
def _drawAspect(self, r, ar, degA, degB, color):
|
|
403
|
-
"""
|
|
404
|
-
Draws svg aspects: ring, aspect ring, degreeA degreeB
|
|
405
|
-
"""
|
|
406
|
-
offset = (int(self.user.houses_degree_ut[6]) / -1) + int(degA)
|
|
407
|
-
x1 = sliceToX(0, ar, offset) + (r - ar)
|
|
408
|
-
y1 = sliceToY(0, ar, offset) + (r - ar)
|
|
409
|
-
offset = (int(self.user.houses_degree_ut[6]) / -1) + int(degB)
|
|
410
|
-
x2 = sliceToX(0, ar, offset) + (r - ar)
|
|
411
|
-
y2 = sliceToY(0, ar, offset) + (r - ar)
|
|
412
|
-
out = f' <line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {color}; stroke-width: 1; stroke-opacity: .9;"/>'
|
|
413
|
-
|
|
414
|
-
return out
|
|
415
|
-
|
|
416
|
-
def _zodiacSlice(self, num, r, style, type):
|
|
417
|
-
# pie slices
|
|
418
|
-
offset = 360 - self.user.houses_degree_ut[6]
|
|
419
|
-
# check transit
|
|
420
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
421
|
-
dropin = 0
|
|
422
|
-
else:
|
|
423
|
-
dropin = self.c1
|
|
424
|
-
slice = f'<path d="M{str(r)},{str(r)} L{str(dropin + sliceToX(num, r - dropin, offset))},{str(dropin + sliceToY(num, r - dropin, offset))} A{str(r - dropin)},{str(r - dropin)} 0 0,0 {str(dropin + sliceToX(num + 1, r - dropin, offset))},{str(dropin + sliceToY(num + 1, r - dropin, offset))} z" style="{style}"/>'
|
|
425
|
-
|
|
426
|
-
# symbols
|
|
427
|
-
offset = offset + 15
|
|
428
|
-
# check transit
|
|
429
|
-
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
430
|
-
dropin = 54
|
|
431
|
-
else:
|
|
432
|
-
dropin = 18 + self.c1
|
|
433
|
-
sign = f'<g transform="translate(-16,-16)"><use x="{str(dropin + sliceToX(num, r - dropin, offset))}" y="{str(dropin + sliceToY(num, r - dropin, offset))}" xlink:href="#{type}" /></g>'
|
|
434
|
-
|
|
435
|
-
return slice + "" + sign
|
|
436
|
-
|
|
437
|
-
def _makeZodiac(self, r):
|
|
438
292
|
output = ""
|
|
439
|
-
for i in
|
|
440
|
-
output
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
293
|
+
for i, zodiac_element in enumerate(self.zodiac):
|
|
294
|
+
output += draw_zodiac_slice(
|
|
295
|
+
c1=self.c1,
|
|
296
|
+
chart_type=self.chart_type,
|
|
297
|
+
seventh_house_degree_ut=self.user.houses_degree_ut[6],
|
|
298
|
+
num=i,
|
|
299
|
+
r=r,
|
|
300
|
+
style=f'fill:{self.chart_colors_settings[f"zodiac_bg_{i}"]}; fill-opacity: 0.5;',
|
|
301
|
+
type=zodiac_element["name"],
|
|
448
302
|
)
|
|
303
|
+
|
|
449
304
|
return output
|
|
450
305
|
|
|
451
306
|
def _makeHouses(self, r):
|
|
@@ -535,44 +390,50 @@ class KerykeionChartSVG:
|
|
|
535
390
|
|
|
536
391
|
return path
|
|
537
392
|
|
|
538
|
-
def
|
|
393
|
+
def _calculate_elements_points_from_planets(self):
|
|
539
394
|
"""
|
|
540
395
|
Calculate chart element points from a planet.
|
|
541
396
|
"""
|
|
397
|
+
|
|
398
|
+
for i in range(len(self.available_planets_setting)):
|
|
399
|
+
# element: get extra points if planet is in own zodiac sign.
|
|
400
|
+
related_zodiac_signs = self.available_planets_setting[i]["related_zodiac_signs"]
|
|
401
|
+
cz = self.points_sign[i]
|
|
402
|
+
extra_points = 0
|
|
403
|
+
if related_zodiac_signs != []:
|
|
404
|
+
for e in range(len(related_zodiac_signs)):
|
|
405
|
+
if int(related_zodiac_signs[e]) == int(cz):
|
|
406
|
+
extra_points = self.planet_in_zodiac_extra_points
|
|
542
407
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
extra_points = 0
|
|
547
|
-
if related_zodiac_signs != []:
|
|
548
|
-
for e in range(len(related_zodiac_signs)):
|
|
549
|
-
if int(related_zodiac_signs[e]) == int(cz):
|
|
550
|
-
extra_points = self.planet_in_zodiac_extra_points
|
|
551
|
-
|
|
552
|
-
ele = self.zodiac[self.points_sign[i]]["element"]
|
|
553
|
-
if ele == "fire":
|
|
554
|
-
self.fire = self.fire + self.planets_settings[i]["element_points"] + extra_points
|
|
408
|
+
ele = self.zodiac[self.points_sign[i]]["element"]
|
|
409
|
+
if ele == "fire":
|
|
410
|
+
self.fire = self.fire + self.available_planets_setting[i]["element_points"] + extra_points
|
|
555
411
|
|
|
556
|
-
|
|
557
|
-
|
|
412
|
+
elif ele == "earth":
|
|
413
|
+
self.earth = self.earth + self.available_planets_setting[i]["element_points"] + extra_points
|
|
558
414
|
|
|
559
|
-
|
|
560
|
-
|
|
415
|
+
elif ele == "air":
|
|
416
|
+
self.air = self.air + self.available_planets_setting[i]["element_points"] + extra_points
|
|
561
417
|
|
|
562
|
-
|
|
563
|
-
|
|
418
|
+
elif ele == "water":
|
|
419
|
+
self.water = self.water + self.available_planets_setting[i]["element_points"] + extra_points
|
|
564
420
|
|
|
565
421
|
def _make_planets(self, r):
|
|
566
422
|
planets_degut = {}
|
|
567
|
-
diff = range(len(self.
|
|
423
|
+
diff = range(len(self.available_planets_setting))
|
|
568
424
|
|
|
569
|
-
for i in range(len(self.
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
planets_degut[self.points_deg_ut[i]] = i
|
|
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
|
|
574
429
|
|
|
575
|
-
|
|
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
|
+
"""
|
|
576
437
|
|
|
577
438
|
output = ""
|
|
578
439
|
keys = list(planets_degut.keys())
|
|
@@ -601,24 +462,24 @@ class KerykeionChartSVG:
|
|
|
601
462
|
diffb = degreeDiff(next, self.points_deg_ut[i])
|
|
602
463
|
planets_by_pos[e] = [i, diffa, diffb]
|
|
603
464
|
|
|
604
|
-
|
|
465
|
+
logging.debug(f'{self.available_planets_setting[i]["label"]}, {diffa}, {diffb}')
|
|
605
466
|
|
|
606
467
|
if diffb < planet_drange:
|
|
607
468
|
if group_open:
|
|
608
|
-
groups[-1].append([e, diffa, diffb, self.
|
|
469
|
+
groups[-1].append([e, diffa, diffb, self.available_planets_setting[planets_degut[keys[e]]]["label"]])
|
|
609
470
|
else:
|
|
610
471
|
group_open = True
|
|
611
472
|
groups.append([])
|
|
612
|
-
groups[-1].append([e, diffa, diffb, self.
|
|
473
|
+
groups[-1].append([e, diffa, diffb, self.available_planets_setting[planets_degut[keys[e]]]["label"]])
|
|
613
474
|
else:
|
|
614
475
|
if group_open:
|
|
615
|
-
groups[-1].append([e, diffa, diffb, self.
|
|
476
|
+
groups[-1].append([e, diffa, diffb, self.available_planets_setting[planets_degut[keys[e]]]["label"]])
|
|
616
477
|
group_open = False
|
|
617
478
|
|
|
618
479
|
def zero(x):
|
|
619
480
|
return 0
|
|
620
481
|
|
|
621
|
-
planets_delta = list(map(zero, range(len(self.
|
|
482
|
+
planets_delta = list(map(zero, range(len(self.available_planets_setting))))
|
|
622
483
|
|
|
623
484
|
# print groups
|
|
624
485
|
# print planets_by_pos
|
|
@@ -730,7 +591,7 @@ class KerykeionChartSVG:
|
|
|
730
591
|
y1 = sliceToY(0, (r - self.c3), trueoffset) + self.c3
|
|
731
592
|
x2 = sliceToX(0, (r - rplanet - 30), trueoffset) + rplanet + 30
|
|
732
593
|
y2 = sliceToY(0, (r - rplanet - 30), trueoffset) + rplanet + 30
|
|
733
|
-
color = self.
|
|
594
|
+
color = self.available_planets_setting[i]["color"]
|
|
734
595
|
output += (
|
|
735
596
|
'<line x1="%s" y1="%s" x2="%s" y2="%s" style="stroke-width:1px;stroke:%s;stroke-opacity:.3;"/>\n'
|
|
736
597
|
% (x1, y1, x2, y2, color)
|
|
@@ -748,20 +609,21 @@ class KerykeionChartSVG:
|
|
|
748
609
|
else:
|
|
749
610
|
scale = 1
|
|
750
611
|
# output planet
|
|
751
|
-
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.
|
|
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>'
|
|
752
613
|
|
|
753
614
|
# make transit degut and display planets
|
|
754
615
|
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
755
616
|
group_offset = {}
|
|
756
617
|
t_planets_degut = {}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
else:
|
|
760
|
-
list_range = len(self.planets_settings)
|
|
618
|
+
list_range = len(self.available_planets_setting)
|
|
619
|
+
|
|
761
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
|
+
|
|
762
624
|
group_offset[i] = 0
|
|
763
|
-
|
|
764
|
-
|
|
625
|
+
t_planets_degut[self.t_points_deg_ut[i]] = i
|
|
626
|
+
|
|
765
627
|
t_keys = list(t_planets_degut.keys())
|
|
766
628
|
t_keys.sort()
|
|
767
629
|
|
|
@@ -803,7 +665,12 @@ class KerykeionChartSVG:
|
|
|
803
665
|
group_offset[groups[i][3]] = 2.0
|
|
804
666
|
|
|
805
667
|
switch = 0
|
|
668
|
+
|
|
669
|
+
# Transit planets loop
|
|
806
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
|
+
|
|
807
674
|
i = t_planets_degut[t_keys[e]]
|
|
808
675
|
|
|
809
676
|
if 22 < i < 27:
|
|
@@ -815,20 +682,21 @@ class KerykeionChartSVG:
|
|
|
815
682
|
rplanet = 26
|
|
816
683
|
switch = 1
|
|
817
684
|
|
|
685
|
+
# Transit planet name
|
|
818
686
|
zeropoint = 360 - self.user.houses_degree_ut[6]
|
|
819
687
|
t_offset = zeropoint + self.t_points_deg_ut[i]
|
|
820
688
|
if t_offset > 360:
|
|
821
689
|
t_offset = t_offset - 360
|
|
822
690
|
planet_x = sliceToX(0, (r - rplanet), t_offset) + rplanet
|
|
823
691
|
planet_y = sliceToY(0, (r - rplanet), t_offset) + rplanet
|
|
824
|
-
output += f'<g transform="translate(-6,-6)"><g transform="scale(0.5)"><use x="{planet_x*2}" y="{planet_y*2}" xlink:href="#{self.
|
|
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>'
|
|
825
693
|
|
|
826
|
-
#
|
|
694
|
+
# Transit planet line
|
|
827
695
|
x1 = sliceToX(0, r + 3, t_offset) - 3
|
|
828
696
|
y1 = sliceToY(0, r + 3, t_offset) - 3
|
|
829
697
|
x2 = sliceToX(0, r - 3, t_offset) + 3
|
|
830
698
|
y2 = sliceToY(0, r - 3, t_offset) + 3
|
|
831
|
-
output += f'<line x1="{str(x1)}" y1="{str(y1)}" x2="{str(x2)}" y2="{str(y2)}" style="stroke: {self.
|
|
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;"/>'
|
|
832
700
|
|
|
833
701
|
# transit planet degree text
|
|
834
702
|
rotate = self.user.houses_degree_ut[0] - self.t_points_deg_ut[i]
|
|
@@ -852,7 +720,7 @@ class KerykeionChartSVG:
|
|
|
852
720
|
degree = int(t_offset)
|
|
853
721
|
output += f'<g transform="translate({deg_x},{deg_y})">'
|
|
854
722
|
output += f'<text transform="rotate({rotate})" text-anchor="{textanchor}'
|
|
855
|
-
output += f'" style="fill: {self.
|
|
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")}'
|
|
856
724
|
output += "</text></g>"
|
|
857
725
|
|
|
858
726
|
# check transit
|
|
@@ -867,7 +735,7 @@ class KerykeionChartSVG:
|
|
|
867
735
|
x2 = sliceToX(0, (r - (dropin - 3)), offset) + (dropin - 3)
|
|
868
736
|
y2 = sliceToY(0, (r - (dropin - 3)), offset) + (dropin - 3)
|
|
869
737
|
|
|
870
|
-
output += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {self.
|
|
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;"/>'
|
|
871
739
|
|
|
872
740
|
# check transit
|
|
873
741
|
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
@@ -879,7 +747,7 @@ class KerykeionChartSVG:
|
|
|
879
747
|
y1 = sliceToY(0, r - dropin, offset) + dropin
|
|
880
748
|
x2 = sliceToX(0, (r - (dropin - 3)), offset) + (dropin - 3)
|
|
881
749
|
y2 = sliceToY(0, (r - (dropin - 3)), offset) + (dropin - 3)
|
|
882
|
-
output += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {self.
|
|
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;"/>'
|
|
883
751
|
|
|
884
752
|
return output
|
|
885
753
|
|
|
@@ -897,7 +765,7 @@ class KerykeionChartSVG:
|
|
|
897
765
|
tr = {} # 6
|
|
898
766
|
qc = {} # 9
|
|
899
767
|
sext = {} # 3
|
|
900
|
-
for i in range(len(self.
|
|
768
|
+
for i in range(len(self.available_planets_setting)):
|
|
901
769
|
a = self.points_deg_ut[i]
|
|
902
770
|
qc[i] = {}
|
|
903
771
|
sext[i] = {}
|
|
@@ -906,14 +774,14 @@ class KerykeionChartSVG:
|
|
|
906
774
|
tr[i] = {}
|
|
907
775
|
conj[i] = {}
|
|
908
776
|
# skip some points
|
|
909
|
-
n = self.
|
|
777
|
+
n = self.available_planets_setting[i]["name"]
|
|
910
778
|
if n == "earth" or n == "True_Node" or n == "osc. apogee" or n == "intp. apogee" or n == "intp. perigee":
|
|
911
779
|
continue
|
|
912
780
|
if n == "Dsc" or n == "Ic":
|
|
913
781
|
continue
|
|
914
|
-
for j in range(len(self.
|
|
782
|
+
for j in range(len(self.available_planets_setting)):
|
|
915
783
|
# skip some points
|
|
916
|
-
n = self.
|
|
784
|
+
n = self.available_planets_setting[j]["name"]
|
|
917
785
|
if n == "earth" or n == "True_Node" or n == "osc. apogee" or n == "intp. apogee" or n == "intp. perigee":
|
|
918
786
|
continue
|
|
919
787
|
if n == "Dsc" or n == "Ic":
|
|
@@ -966,12 +834,12 @@ class KerykeionChartSVG:
|
|
|
966
834
|
for l, w in opp[k].items():
|
|
967
835
|
for a, b in sq.items():
|
|
968
836
|
if k in sq[a] and l in sq[a]:
|
|
969
|
-
|
|
837
|
+
logging.debug(f"Got tsquare {a} {k} {l}")
|
|
970
838
|
if k > l:
|
|
971
|
-
tsquare[f"{a},{l},{k}"] = f"{self.
|
|
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']}"
|
|
972
840
|
|
|
973
841
|
else:
|
|
974
|
-
tsquare[f"{a},{k},{l}"] = f"{self.
|
|
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']}"
|
|
975
843
|
|
|
976
844
|
stellium = {}
|
|
977
845
|
# check for 4 continuous conjunctions
|
|
@@ -1000,10 +868,10 @@ class KerykeionChartSVG:
|
|
|
1000
868
|
l = [k, n, p, r]
|
|
1001
869
|
l.sort()
|
|
1002
870
|
stellium["%s %s %s %s" % (l[0], l[1], l[2], l[3])] = "%s %s %s %s" % (
|
|
1003
|
-
self.
|
|
1004
|
-
self.
|
|
1005
|
-
self.
|
|
1006
|
-
self.
|
|
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"],
|
|
1007
875
|
)
|
|
1008
876
|
# print yots
|
|
1009
877
|
out = '<g transform="translate(-30,380)">'
|
|
@@ -1014,15 +882,15 @@ class KerykeionChartSVG:
|
|
|
1014
882
|
|
|
1015
883
|
# first planet symbol
|
|
1016
884
|
out += f'<g transform="translate(20,{y})">'
|
|
1017
|
-
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.
|
|
885
|
+
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.available_planets_setting[yot[k][0]]["name"]}" /></g>'
|
|
1018
886
|
|
|
1019
887
|
# second planet symbol
|
|
1020
888
|
out += f'<g transform="translate(30,{y})">'
|
|
1021
|
-
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.
|
|
889
|
+
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.available_planets_setting[yot[k][1]]["name"]}" /></g>'
|
|
1022
890
|
|
|
1023
891
|
# third planet symbol
|
|
1024
892
|
out += f'<g transform="translate(40,{y})">'
|
|
1025
|
-
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.
|
|
893
|
+
out += f'<use transform="scale(0.4)" x="0" y="-20" xlink:href="#{self.available_planets_setting[yot[k][2]]["name"]}" /></g>'
|
|
1026
894
|
|
|
1027
895
|
y = y + 14
|
|
1028
896
|
# finalize
|
|
@@ -1034,12 +902,13 @@ class KerykeionChartSVG:
|
|
|
1034
902
|
def _makeAspects(self, r, ar):
|
|
1035
903
|
out = ""
|
|
1036
904
|
for element in self.aspects_list:
|
|
1037
|
-
out +=
|
|
1038
|
-
r,
|
|
1039
|
-
ar,
|
|
1040
|
-
element["p1_abs_pos"],
|
|
1041
|
-
element["p2_abs_pos"],
|
|
1042
|
-
self.aspects_settings[element["aid"]]["color"],
|
|
905
|
+
out += draw_aspect_line(
|
|
906
|
+
r=r,
|
|
907
|
+
ar=ar,
|
|
908
|
+
degA=element["p1_abs_pos"],
|
|
909
|
+
degB=element["p2_abs_pos"],
|
|
910
|
+
color=self.aspects_settings[element["aid"]]["color"],
|
|
911
|
+
seventh_house_degree_ut=self.user.seventh_house.abs_pos
|
|
1043
912
|
)
|
|
1044
913
|
|
|
1045
914
|
return out
|
|
@@ -1050,29 +919,27 @@ class KerykeionChartSVG:
|
|
|
1050
919
|
xindent = 380
|
|
1051
920
|
yindent = 468
|
|
1052
921
|
box = 14
|
|
1053
|
-
revr = list(range(len(self.
|
|
922
|
+
revr = list(range(len(self.available_planets_setting)))
|
|
1054
923
|
revr.reverse()
|
|
1055
924
|
counter = 0
|
|
1056
925
|
for a in revr:
|
|
1057
926
|
counter += 1
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
if (element["p1"] == a and element["p2"] == b) or (element["p1"] == b and element["p2"] == a):
|
|
1075
|
-
out += f'<use x="{xorb-box+1}" y="{yorb+1}" xlink:href="#orb{element["aspect_degrees"]}" />'
|
|
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"]}" />'
|
|
1076
943
|
|
|
1077
944
|
return out
|
|
1078
945
|
|
|
@@ -1080,15 +947,16 @@ class KerykeionChartSVG:
|
|
|
1080
947
|
def _makeAspectsTransit(self, r, ar):
|
|
1081
948
|
out = ""
|
|
1082
949
|
|
|
1083
|
-
self.aspects_list = SynastryAspects(self.user, self.t_user, new_settings_file=self.new_settings_file).
|
|
950
|
+
self.aspects_list = SynastryAspects(self.user, self.t_user, new_settings_file=self.new_settings_file).relevant_aspects
|
|
1084
951
|
|
|
1085
952
|
for element in self.aspects_list:
|
|
1086
|
-
out +=
|
|
1087
|
-
r,
|
|
1088
|
-
ar,
|
|
1089
|
-
element["p1_abs_pos"],
|
|
1090
|
-
element["p2_abs_pos"],
|
|
1091
|
-
self.aspects_settings[element["aid"]]["color"],
|
|
953
|
+
out += draw_aspect_line(
|
|
954
|
+
r=r,
|
|
955
|
+
ar=ar,
|
|
956
|
+
degA=element["p1_abs_pos"],
|
|
957
|
+
degB=element["p2_abs_pos"],
|
|
958
|
+
color=self.aspects_settings[element["aid"]]["color"],
|
|
959
|
+
seventh_house_degree_ut=self.user.seventh_house.abs_pos
|
|
1092
960
|
)
|
|
1093
961
|
|
|
1094
962
|
return out
|
|
@@ -1126,55 +994,37 @@ class KerykeionChartSVG:
|
|
|
1126
994
|
line = 0
|
|
1127
995
|
|
|
1128
996
|
out += f'<g transform="translate({nl},{line})">'
|
|
997
|
+
|
|
1129
998
|
# first planet symbol
|
|
1130
|
-
|
|
1131
|
-
# TODO: (next((item for item in self.planets_settings if item["id"] == self.aspects_list[i]["p1"]))) It preventes the use ot numeric ID, but it is not working.
|
|
1132
999
|
out += f'<use transform="scale(0.4)" x="0" y="3" xlink:href="#{self.planets_settings[self.aspects_list[i]["p1"]]["name"]}" />'
|
|
1133
1000
|
|
|
1134
1001
|
# aspect symbol
|
|
1135
1002
|
out += f'<use x="15" y="0" xlink:href="#orb{self.aspects_settings[self.aspects_list[i]["aid"]]["degree"]}" />'
|
|
1003
|
+
|
|
1136
1004
|
# second planet symbol
|
|
1137
1005
|
out += '<g transform="translate(30,0)">'
|
|
1138
|
-
|
|
1139
|
-
# TODO: (next((item for item in self.planets_settings if item["id"] == self.aspects_list[i]["p3"])))
|
|
1140
1006
|
out += '<use transform="scale(0.4)" x="0" y="3" xlink:href="#%s" />' % (self.planets_settings[self.aspects_list[i]["p2"]]["name"])
|
|
1141
1007
|
|
|
1142
1008
|
out += "</g>"
|
|
1143
1009
|
# difference in degrees
|
|
1144
|
-
out += f'<text y="8" x="45" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{
|
|
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>'
|
|
1145
1011
|
# line
|
|
1146
1012
|
out += "</g>"
|
|
1147
1013
|
line = line + 14
|
|
1148
1014
|
out += "</g>"
|
|
1149
1015
|
return out
|
|
1150
1016
|
|
|
1151
|
-
def _makeElements(self, r):
|
|
1152
|
-
total = self.fire + self.earth + self.air + self.water
|
|
1153
|
-
pf = int(round(100 * self.fire / total))
|
|
1154
|
-
pe = int(round(100 * self.earth / total))
|
|
1155
|
-
pa = int(round(100 * self.air / total))
|
|
1156
|
-
pw = int(round(100 * self.water / total))
|
|
1157
|
-
|
|
1158
|
-
out = '<g transform="translate(-30,79)">'
|
|
1159
|
-
out += f'<text y="0" style="fill:#ff6600; font-size: 10px;">{self.language_settings["fire"]} {str(pf)}%</text>'
|
|
1160
|
-
out += f'<text y="12" style="fill:#6a2d04; font-size: 10px;">{self.language_settings["earth"]} {str(pe)}%</text>'
|
|
1161
|
-
out += f'<text y="24" style="fill:#6f76d1; font-size: 10px;">{self.language_settings["air"]} {str(pa)}%</text>'
|
|
1162
|
-
out += f'<text y="36" style="fill:#630e73; font-size: 10px;">{self.language_settings["water"]} {str(pw)}%</text>'
|
|
1163
|
-
out += "</g>"
|
|
1164
|
-
|
|
1165
|
-
return out
|
|
1166
|
-
|
|
1167
1017
|
def _makePlanetGrid(self):
|
|
1168
1018
|
li = 10
|
|
1169
1019
|
offset = 0
|
|
1170
1020
|
|
|
1171
|
-
out = '<g transform="translate(
|
|
1021
|
+
out = '<g transform="translate(510,-20)">'
|
|
1172
1022
|
out += '<g transform="translate(140, -15)">'
|
|
1173
|
-
out += f'<text text-anchor="end" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 14px;">{self.language_settings["planets_and_house"]} {self.name}:</text>'
|
|
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>'
|
|
1174
1024
|
out += "</g>"
|
|
1175
1025
|
|
|
1176
1026
|
end_of_line = None
|
|
1177
|
-
for i in range(len(self.
|
|
1027
|
+
for i in range(len(self.available_planets_setting)):
|
|
1178
1028
|
offset_between_lines = 14
|
|
1179
1029
|
end_of_line = "</g>"
|
|
1180
1030
|
|
|
@@ -1183,30 +1033,29 @@ class KerykeionChartSVG:
|
|
|
1183
1033
|
li = 10
|
|
1184
1034
|
offset = -120
|
|
1185
1035
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
out += f'<g transform="translate({offset},{li})">'
|
|
1036
|
+
# start of line
|
|
1037
|
+
out += f'<g transform="translate({offset},{li})">'
|
|
1189
1038
|
|
|
1190
|
-
|
|
1191
|
-
|
|
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>'
|
|
1192
1041
|
|
|
1193
|
-
|
|
1194
|
-
|
|
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>'
|
|
1195
1044
|
|
|
1196
|
-
|
|
1197
|
-
|
|
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>'
|
|
1198
1047
|
|
|
1199
|
-
|
|
1200
|
-
|
|
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>'
|
|
1201
1050
|
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1051
|
+
# planet retrograde
|
|
1052
|
+
if self.points_retrograde[i]:
|
|
1053
|
+
out += '<g transform="translate(74,-6)"><use transform="scale(.5)" xlink:href="#retrograde" /></g>'
|
|
1205
1054
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1055
|
+
# end of line
|
|
1056
|
+
out += end_of_line
|
|
1208
1057
|
|
|
1209
|
-
|
|
1058
|
+
li = li + offset_between_lines
|
|
1210
1059
|
|
|
1211
1060
|
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
1212
1061
|
if self.chart_type == "Transit":
|
|
@@ -1221,32 +1070,31 @@ class KerykeionChartSVG:
|
|
|
1221
1070
|
t_li = 10
|
|
1222
1071
|
t_offset = 250
|
|
1223
1072
|
|
|
1224
|
-
for i in range(len(self.
|
|
1073
|
+
for i in range(len(self.available_planets_setting)):
|
|
1225
1074
|
if i == 27:
|
|
1226
1075
|
t_li = 10
|
|
1227
1076
|
t_offset = -120
|
|
1228
1077
|
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
out += f'<g transform="translate({t_offset},{t_li})">'
|
|
1078
|
+
# start of line
|
|
1079
|
+
out += f'<g transform="translate({t_offset},{t_li})">'
|
|
1232
1080
|
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
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>'
|
|
1241
1089
|
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
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>'
|
|
1245
1093
|
|
|
1246
|
-
|
|
1247
|
-
|
|
1094
|
+
# end of line
|
|
1095
|
+
out += end_of_line
|
|
1248
1096
|
|
|
1249
|
-
|
|
1097
|
+
t_li = t_li + offset_between_lines
|
|
1250
1098
|
|
|
1251
1099
|
if end_of_line is None:
|
|
1252
1100
|
raise KerykeionException("End of line not found")
|
|
@@ -1254,8 +1102,14 @@ class KerykeionChartSVG:
|
|
|
1254
1102
|
out += end_of_line
|
|
1255
1103
|
return out
|
|
1256
1104
|
|
|
1257
|
-
def
|
|
1258
|
-
|
|
1105
|
+
def _draw_house_grid(self):
|
|
1106
|
+
"""
|
|
1107
|
+
Generate SVG code for a grid of astrological houses.
|
|
1108
|
+
|
|
1109
|
+
Returns:
|
|
1110
|
+
str: The SVG code for the grid of houses.
|
|
1111
|
+
"""
|
|
1112
|
+
out = '<g transform="translate(610,-20)">'
|
|
1259
1113
|
|
|
1260
1114
|
li = 10
|
|
1261
1115
|
for i in range(12):
|
|
@@ -1266,15 +1120,17 @@ class KerykeionChartSVG:
|
|
|
1266
1120
|
out += f'<g transform="translate(0,{li})">'
|
|
1267
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>'
|
|
1268
1122
|
out += f'<g transform="translate(40,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.houses_sign_graph[i]]["name"]}" /></g>'
|
|
1269
|
-
out += f'<text x="53" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;"> {
|
|
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>'
|
|
1270
1124
|
out += "</g>"
|
|
1271
1125
|
li = li + 14
|
|
1272
1126
|
|
|
1273
1127
|
out += "</g>"
|
|
1274
1128
|
|
|
1275
1129
|
if self.chart_type == "Synastry":
|
|
1276
|
-
out += '
|
|
1130
|
+
out += '<!-- Synastry Houses -->'
|
|
1131
|
+
out += '<g transform="translate(850, -20)">'
|
|
1277
1132
|
li = 10
|
|
1133
|
+
|
|
1278
1134
|
for i in range(12):
|
|
1279
1135
|
if i < 9:
|
|
1280
1136
|
cusp = "  " + str(i + 1)
|
|
@@ -1283,14 +1139,14 @@ class KerykeionChartSVG:
|
|
|
1283
1139
|
out += '<g transform="translate(0,' + str(li) + ')">'
|
|
1284
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>'
|
|
1285
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>'
|
|
1286
|
-
out += f'<text x="53" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;"> {
|
|
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>'
|
|
1287
1143
|
out += "</g>"
|
|
1288
1144
|
li = li + 14
|
|
1289
1145
|
out += "</g>"
|
|
1290
1146
|
|
|
1291
1147
|
return out
|
|
1292
1148
|
|
|
1293
|
-
def _createTemplateDictionary(self):
|
|
1149
|
+
def _createTemplateDictionary(self) -> ChartTemplateDictionary:
|
|
1294
1150
|
# self.chart_type = "Transit"
|
|
1295
1151
|
# empty element points
|
|
1296
1152
|
self.fire = 0.0
|
|
@@ -1298,18 +1154,13 @@ class KerykeionChartSVG:
|
|
|
1298
1154
|
self.air = 0.0
|
|
1299
1155
|
self.water = 0.0
|
|
1300
1156
|
|
|
1301
|
-
#
|
|
1302
|
-
|
|
1303
|
-
if ratio < 1.3: # 1280x1024
|
|
1304
|
-
wm_off = 130
|
|
1305
|
-
else: # 1024x768, 800x600, 1280x800, 1680x1050
|
|
1306
|
-
wm_off = 100
|
|
1157
|
+
# Calculate the elements points
|
|
1158
|
+
self._calculate_elements_points_from_planets()
|
|
1307
1159
|
|
|
1308
1160
|
# Viewbox and sizing
|
|
1309
1161
|
svgHeight = "100%"
|
|
1310
1162
|
svgWidth = "100%"
|
|
1311
1163
|
rotate = "0"
|
|
1312
|
-
translate = "0"
|
|
1313
1164
|
|
|
1314
1165
|
# To increase the size of the chart, change the viewbox
|
|
1315
1166
|
if self.chart_type == "Natal" or self.chart_type == "ExternalNatal":
|
|
@@ -1318,7 +1169,7 @@ class KerykeionChartSVG:
|
|
|
1318
1169
|
viewbox = self.chart_settings["wide_chart_viewBox"]
|
|
1319
1170
|
|
|
1320
1171
|
# template dictionary
|
|
1321
|
-
td:
|
|
1172
|
+
td: ChartTemplateDictionary = dict() # type: ignore
|
|
1322
1173
|
r = 240
|
|
1323
1174
|
|
|
1324
1175
|
if self.chart_type == "ExternalNatal":
|
|
@@ -1332,14 +1183,12 @@ class KerykeionChartSVG:
|
|
|
1332
1183
|
|
|
1333
1184
|
# transit
|
|
1334
1185
|
if self.chart_type == "Transit" or self.chart_type == "Synastry":
|
|
1335
|
-
td["transitRing"] = self.
|
|
1336
|
-
td["degreeRing"] = self.
|
|
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)
|
|
1337
1188
|
|
|
1338
1189
|
# circles
|
|
1339
|
-
td["
|
|
1340
|
-
td["
|
|
1341
|
-
td["c2"] = 'cx="' + str(r) + '" cy="' + str(r) + '" r="' + str(r - 72) + '"'
|
|
1342
|
-
td["c2style"] = f"fill: {self.chart_colors_settings['paper_1']}; fill-opacity:.4; stroke: {self.chart_colors_settings['zodiac_transit_ring_1']}; stroke-opacity:.4; stroke-width: 1px"
|
|
1190
|
+
td["first_circle"] = draw_first_circle(r, self.chart_colors_settings["zodiac_transit_ring_2"], self.chart_type)
|
|
1191
|
+
td["second_circle"] = draw_second_circle(r, self.chart_colors_settings['zodiac_transit_ring_1'], self.chart_colors_settings['paper_1'], self.chart_type)
|
|
1343
1192
|
|
|
1344
1193
|
td["c3"] = 'cx="' + str(r) + '" cy="' + str(r) + '" r="' + str(r - 160) + '"'
|
|
1345
1194
|
td["c3style"] = f"fill: {self.chart_colors_settings['paper_1']}; fill-opacity:.8; stroke: {self.chart_colors_settings['zodiac_transit_ring_0']}; stroke-width: 1px"
|
|
@@ -1347,49 +1196,59 @@ class KerykeionChartSVG:
|
|
|
1347
1196
|
td["makeAspects"] = self._makeAspectsTransit(r, (r - 160))
|
|
1348
1197
|
td["makeAspectGrid"] = self._makeAspectTransitGrid(r)
|
|
1349
1198
|
td["makePatterns"] = ""
|
|
1350
|
-
td["chart_width"] = self.full_width
|
|
1351
1199
|
else:
|
|
1352
1200
|
td["transitRing"] = ""
|
|
1353
|
-
td["degreeRing"] = self.
|
|
1201
|
+
td["degreeRing"] = draw_degree_ring(r, self.c1, self.user.seventh_house.abs_pos, self.chart_colors_settings["paper_0"])
|
|
1354
1202
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
td["
|
|
1358
|
-
|
|
1359
|
-
td["c2style"] = f'fill: {self.chart_colors_settings["paper_1"]}; fill-opacity:.2; stroke: {self.chart_colors_settings["zodiac_radix_ring_1"]}; stroke-opacity:.4; stroke-width: 1px'
|
|
1203
|
+
td['first_circle'] = draw_first_circle(r, self.chart_colors_settings["zodiac_radix_ring_2"], self.chart_type, self.c1)
|
|
1204
|
+
|
|
1205
|
+
td["second_circle"] = draw_second_circle(r, self.chart_colors_settings["zodiac_radix_ring_1"], self.chart_colors_settings["paper_1"], self.chart_type, self.c2)
|
|
1206
|
+
|
|
1360
1207
|
td["c3"] = f'cx="{r}" cy="{r}" r="{r - self.c3}"'
|
|
1361
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
|
+
|
|
1362
1210
|
td["makeAspects"] = self._makeAspects(r, (r - self.c3))
|
|
1363
1211
|
td["makeAspectGrid"] = self._makeAspectGrid(r)
|
|
1364
1212
|
td["makePatterns"] = self._makePatterns()
|
|
1365
|
-
|
|
1366
|
-
|
|
1213
|
+
|
|
1214
|
+
td["chart_height"] = self.height
|
|
1215
|
+
td["chart_width"] = self.width
|
|
1367
1216
|
td["circleX"] = str(0)
|
|
1368
1217
|
td["circleY"] = str(0)
|
|
1369
1218
|
td["svgWidth"] = str(svgWidth)
|
|
1370
1219
|
td["svgHeight"] = str(svgHeight)
|
|
1371
1220
|
td["viewbox"] = viewbox
|
|
1372
1221
|
|
|
1222
|
+
# Chart Title
|
|
1373
1223
|
if self.chart_type == "Synastry":
|
|
1374
|
-
td["stringTitle"] = f"{self.name} {self.language_settings['and_word']} {self.t_user.name}"
|
|
1224
|
+
td["stringTitle"] = f"{self.user.name} {self.language_settings['and_word']} {self.t_user.name}"
|
|
1375
1225
|
|
|
1376
1226
|
elif self.chart_type == "Transit":
|
|
1377
1227
|
td["stringTitle"] = f"{self.language_settings['transits']} {self.t_user.day}/{self.t_user.month}/{self.t_user.year}"
|
|
1378
1228
|
|
|
1379
1229
|
else:
|
|
1380
|
-
td["stringTitle"] = self.name
|
|
1230
|
+
td["stringTitle"] = self.user.name
|
|
1381
1231
|
|
|
1382
|
-
#
|
|
1383
|
-
if self.chart_type == "Synastry" or self.
|
|
1384
|
-
td["stringName"] = f"{self.name}:"
|
|
1232
|
+
# Chart Name
|
|
1233
|
+
if self.chart_type == "Synastry" or self.chart_type == "Transit":
|
|
1234
|
+
td["stringName"] = f"{self.user.name}:"
|
|
1385
1235
|
else:
|
|
1386
1236
|
td["stringName"] = f'{self.language_settings["info"]}:'
|
|
1387
1237
|
|
|
1388
|
-
#
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1238
|
+
# Bottom Left Corner
|
|
1239
|
+
if self.chart_type == "Natal" or self.chart_type == "ExternalNatal" or self.chart_type == "Synastry":
|
|
1240
|
+
td["bottomLeft0"] = f"{self.user.zodiac_type if self.user.zodiac_type == 'Tropic' else self.user.zodiac_type + ' ' + self.user.sidereal_mode}"
|
|
1241
|
+
td["bottomLeft1"] = f"{self.user.houses_system_name}"
|
|
1242
|
+
td["bottomLeft2"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.language_settings.get("day", "Day")} {self.user.lunar_phase.get("moon_phase", "")}'
|
|
1243
|
+
td["bottomLeft3"] = f'{self.language_settings.get("lunar_phase", "Lunar Phase")}: {self.user.lunar_phase.moon_phase_name}'
|
|
1244
|
+
td["bottomLeft4"] = f'{self.user.perspective_type}'
|
|
1245
|
+
|
|
1246
|
+
else:
|
|
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}'
|
|
1393
1252
|
|
|
1394
1253
|
# lunar phase
|
|
1395
1254
|
deg = self.user.lunar_phase["degrees_between_s_m"]
|
|
@@ -1457,17 +1316,26 @@ class KerykeionChartSVG:
|
|
|
1457
1316
|
else:
|
|
1458
1317
|
td["stringLocation"] = self.location
|
|
1459
1318
|
|
|
1460
|
-
td["stringDateTime"] = f"{self.user.year}-{self.user.month}-{self.user.day} {self.user.hour:02d}:{self.user.minute:02d}"
|
|
1461
|
-
|
|
1462
1319
|
if self.chart_type == "Synastry":
|
|
1463
1320
|
td["stringLat"] = f"{self.t_user.name}: "
|
|
1464
1321
|
td["stringLon"] = self.t_user.city
|
|
1465
1322
|
td["stringPosition"] = f"{self.t_user.year}-{self.t_user.month}-{self.t_user.day} {self.t_user.hour:02d}:{self.t_user.minute:02d}"
|
|
1466
1323
|
|
|
1467
1324
|
else:
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1325
|
+
latitude_string = convert_latitude_coordinate_to_string(
|
|
1326
|
+
self.geolat,
|
|
1327
|
+
self.language_settings['north'],
|
|
1328
|
+
self.language_settings['south']
|
|
1329
|
+
)
|
|
1330
|
+
longitude_string = convert_longitude_coordinate_to_string(
|
|
1331
|
+
self.geolon,
|
|
1332
|
+
self.language_settings['east'],
|
|
1333
|
+
self.language_settings['west']
|
|
1334
|
+
)
|
|
1335
|
+
|
|
1336
|
+
td["stringLat"] = f"{self.language_settings['latitude']}: {latitude_string}"
|
|
1337
|
+
td["stringLon"] = f"{self.language_settings['longitude']}: {longitude_string}"
|
|
1338
|
+
td["stringPosition"] = f"{self.language_settings['type']}: {self.chart_type}"
|
|
1471
1339
|
|
|
1472
1340
|
# paper_color_X
|
|
1473
1341
|
td["paper_color_0"] = self.chart_colors_settings["paper_0"]
|
|
@@ -1489,52 +1357,77 @@ class KerykeionChartSVG:
|
|
|
1489
1357
|
# config
|
|
1490
1358
|
td["cfgZoom"] = str(self.zoom)
|
|
1491
1359
|
td["cfgRotate"] = rotate
|
|
1492
|
-
td["cfgTranslate"] = translate
|
|
1493
1360
|
|
|
1494
|
-
#
|
|
1495
|
-
|
|
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
|
|
1496
1368
|
td["makeHouses"] = self._makeHouses(r)
|
|
1497
1369
|
td["makePlanets"] = self._make_planets(r)
|
|
1498
|
-
td["
|
|
1370
|
+
td["elements_percentages"] = draw_elements_percentages(
|
|
1371
|
+
self.language_settings['fire'],
|
|
1372
|
+
self.fire,
|
|
1373
|
+
self.language_settings['earth'],
|
|
1374
|
+
self.earth,
|
|
1375
|
+
self.language_settings['air'],
|
|
1376
|
+
self.air,
|
|
1377
|
+
self.language_settings['water'],
|
|
1378
|
+
self.water,
|
|
1379
|
+
)
|
|
1499
1380
|
td["makePlanetGrid"] = self._makePlanetGrid()
|
|
1500
|
-
|
|
1381
|
+
|
|
1382
|
+
# Date time String
|
|
1383
|
+
dt = datetime.fromisoformat(self.user.iso_formatted_local_datetime)
|
|
1384
|
+
custom_format = dt.strftime('%Y-%-m-%-d %H:%M [%z]') # Note the use of '-' to remove leading zeros
|
|
1385
|
+
custom_format = custom_format[:-3] + ':' + custom_format[-3:]
|
|
1386
|
+
td["stringDateTime"] = f"{custom_format}"
|
|
1501
1387
|
|
|
1502
1388
|
return td
|
|
1503
1389
|
|
|
1504
|
-
def makeTemplate(self):
|
|
1390
|
+
def makeTemplate(self, minify: bool = False) -> str:
|
|
1505
1391
|
"""Creates the template for the SVG file"""
|
|
1506
1392
|
td = self._createTemplateDictionary()
|
|
1507
1393
|
|
|
1508
1394
|
# read template
|
|
1509
|
-
with open(self.xml_svg, "r", encoding="utf-8", errors="ignore") as
|
|
1510
|
-
f = open(self.xml_svg)
|
|
1395
|
+
with open(self.xml_svg, "r", encoding="utf-8", errors="ignore") as f:
|
|
1511
1396
|
template = Template(f.read()).substitute(td)
|
|
1512
1397
|
|
|
1513
1398
|
# return filename
|
|
1514
1399
|
|
|
1515
|
-
|
|
1400
|
+
logging.debug(f"Template dictionary keys: {td.keys()}")
|
|
1516
1401
|
|
|
1517
1402
|
self._createTemplateDictionary()
|
|
1518
|
-
return template.replace('"', "'")
|
|
1519
1403
|
|
|
1520
|
-
|
|
1404
|
+
if minify:
|
|
1405
|
+
template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
|
|
1406
|
+
|
|
1407
|
+
else:
|
|
1408
|
+
template = template.replace('"', "'")
|
|
1409
|
+
|
|
1410
|
+
return template
|
|
1411
|
+
|
|
1412
|
+
def makeSVG(self, minify: bool = False):
|
|
1521
1413
|
"""Prints out the SVG file in the specifide folder"""
|
|
1522
1414
|
|
|
1523
1415
|
if not (self.template):
|
|
1524
|
-
self.template = self.makeTemplate()
|
|
1416
|
+
self.template = self.makeTemplate(minify)
|
|
1525
1417
|
|
|
1526
|
-
self.chartname = self.output_directory / f"{self.name}{self.chart_type}Chart.svg"
|
|
1418
|
+
self.chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart.svg"
|
|
1527
1419
|
|
|
1528
1420
|
with open(self.chartname, "w", encoding="utf-8", errors="ignore") as output_file:
|
|
1529
1421
|
output_file.write(self.template)
|
|
1530
1422
|
|
|
1531
|
-
|
|
1423
|
+
logging.info(f"SVG Generated Correctly in: {self.chartname}")
|
|
1532
1424
|
|
|
1533
1425
|
|
|
1534
1426
|
if __name__ == "__main__":
|
|
1535
|
-
|
|
1427
|
+
from kerykeion.utilities import setup_logging
|
|
1428
|
+
setup_logging(level="debug")
|
|
1536
1429
|
|
|
1537
|
-
first = AstrologicalSubject("John Lennon", 1940, 10, 9,
|
|
1430
|
+
first = AstrologicalSubject("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
|
|
1538
1431
|
second = AstrologicalSubject("Paul McCartney", 1942, 6, 18, 15, 30, "Liverpool", "GB")
|
|
1539
1432
|
|
|
1540
1433
|
# Internal Natal Chart
|
|
@@ -1552,3 +1445,51 @@ if __name__ == "__main__":
|
|
|
1552
1445
|
# Transits Chart
|
|
1553
1446
|
transits_chart = KerykeionChartSVG(first, "Transit", second)
|
|
1554
1447
|
transits_chart.makeSVG()
|
|
1448
|
+
|
|
1449
|
+
# Sidereal Birth Chart (Lahiri)
|
|
1450
|
+
sidereal_subject = AstrologicalSubject("John Lennon Lahiri", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="LAHIRI")
|
|
1451
|
+
sidereal_chart = KerykeionChartSVG(sidereal_subject)
|
|
1452
|
+
sidereal_chart.makeSVG()
|
|
1453
|
+
|
|
1454
|
+
# Sidereal Birth Chart (Fagan-Bradley)
|
|
1455
|
+
sidereal_subject = AstrologicalSubject("John Lennon Fagan-Bradley", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="FAGAN_BRADLEY")
|
|
1456
|
+
sidereal_chart = KerykeionChartSVG(sidereal_subject)
|
|
1457
|
+
sidereal_chart.makeSVG()
|
|
1458
|
+
|
|
1459
|
+
# Sidereal Birth Chart (DeLuce)
|
|
1460
|
+
sidereal_subject = AstrologicalSubject("John Lennon DeLuce", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="DELUCE")
|
|
1461
|
+
sidereal_chart = KerykeionChartSVG(sidereal_subject)
|
|
1462
|
+
sidereal_chart.makeSVG()
|
|
1463
|
+
|
|
1464
|
+
# Sidereal Birth Chart (J2000)
|
|
1465
|
+
sidereal_subject = AstrologicalSubject("John Lennon J2000", 1940, 10, 9, 18, 30, "Liverpool", "GB", zodiac_type="Sidereal", sidereal_mode="J2000")
|
|
1466
|
+
sidereal_chart = KerykeionChartSVG(sidereal_subject)
|
|
1467
|
+
sidereal_chart.makeSVG()
|
|
1468
|
+
|
|
1469
|
+
# House System Morinus
|
|
1470
|
+
morinus_house_subject = AstrologicalSubject("John Lennon - House System Morinus", 1940, 10, 9, 18, 30, "Liverpool", "GB", houses_system_identifier="M")
|
|
1471
|
+
morinus_house_chart = KerykeionChartSVG(morinus_house_subject)
|
|
1472
|
+
morinus_house_chart.makeSVG()
|
|
1473
|
+
|
|
1474
|
+
## To check all the available house systems uncomment the following code:
|
|
1475
|
+
# from kerykeion.kr_types import HousesSystemIdentifier
|
|
1476
|
+
# from typing import get_args
|
|
1477
|
+
# for i in get_args(HousesSystemIdentifier):
|
|
1478
|
+
# alternatives_house_subject = AstrologicalSubject(f"John Lennon - House System {i}", 1940, 10, 9, 18, 30, "Liverpool", "GB", houses_system=i)
|
|
1479
|
+
# alternatives_house_chart = KerykeionChartSVG(alternatives_house_subject)
|
|
1480
|
+
# alternatives_house_chart.makeSVG()
|
|
1481
|
+
|
|
1482
|
+
# With True Geocentric Perspective
|
|
1483
|
+
true_geocentric_subject = AstrologicalSubject("John Lennon - True Geocentric", 1940, 10, 9, 18, 30, "Liverpool", "GB", perspective_type="True Geocentric")
|
|
1484
|
+
true_geocentric_chart = KerykeionChartSVG(true_geocentric_subject)
|
|
1485
|
+
true_geocentric_chart.makeSVG()
|
|
1486
|
+
|
|
1487
|
+
# With Heliocentric Perspective
|
|
1488
|
+
heliocentric_subject = AstrologicalSubject("John Lennon - Heliocentric", 1940, 10, 9, 18, 30, "Liverpool", "GB", perspective_type="Heliocentric")
|
|
1489
|
+
heliocentric_chart = KerykeionChartSVG(heliocentric_subject)
|
|
1490
|
+
heliocentric_chart.makeSVG()
|
|
1491
|
+
|
|
1492
|
+
# With Topocentric Perspective
|
|
1493
|
+
topocentric_subject = AstrologicalSubject("John Lennon - Topocentric", 1940, 10, 9, 18, 30, "Liverpool", "GB", perspective_type="Topocentric")
|
|
1494
|
+
topocentric_chart = KerykeionChartSVG(topocentric_subject)
|
|
1495
|
+
topocentric_chart.makeSVG()
|