kerykeion 4.6.2__py3-none-any.whl → 4.7.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.

@@ -3,6 +3,7 @@ import datetime
3
3
  from kerykeion.kr_types import KerykeionException, ChartType
4
4
  from typing import Union
5
5
 
6
+
6
7
  def decHourJoin(inH: int, inM: int, inS: int) -> float:
7
8
  """Join hour, minutes, seconds, timezone integer to hour float.
8
9
 
@@ -20,6 +21,7 @@ def decHourJoin(inH: int, inM: int, inS: int) -> float:
20
21
  output = dh + dm + ds
21
22
  return output
22
23
 
24
+
23
25
  def degreeDiff(a: Union[int, float], b: Union[int, float]) -> float:
24
26
  """Calculate the difference between two degrees.
25
27
 
@@ -40,6 +42,7 @@ def degreeDiff(a: Union[int, float], b: Union[int, float]) -> float:
40
42
  out = 360.0 - out
41
43
  return out
42
44
 
45
+
43
46
  def offsetToTz(datetime_offset: Union[datetime.timedelta, None]) -> float:
44
47
  """Convert datetime offset to float in hours.
45
48
 
@@ -61,9 +64,9 @@ def offsetToTz(datetime_offset: Union[datetime.timedelta, None]) -> float:
61
64
  output = dh + sh
62
65
  return output
63
66
 
67
+
64
68
  def sliceToX(slice: Union[int, float], radius: Union[int, float], offset: Union[int, float]) -> float:
65
- """
66
- Calculates the x-coordinate of a point on a circle based on the slice, radius, and offset.
69
+ """Calculates the x-coordinate of a point on a circle based on the slice, radius, and offset.
67
70
 
68
71
  Args:
69
72
  - slice (int | float): Represents the
@@ -86,9 +89,9 @@ def sliceToX(slice: Union[int, float], radius: Union[int, float], offset: Union[
86
89
  radial = ((math.pi / 6) * slice) + plus
87
90
  return radius * (math.cos(radial) + 1)
88
91
 
92
+
89
93
  def sliceToY(slice: Union[int, float], r: Union[int, float], offset: Union[int, float]) -> float:
90
- """
91
- Calculates the y-coordinate of a point on a circle based on the slice, radius, and offset.
94
+ """Calculates the y-coordinate of a point on a circle based on the slice, radius, and offset.
92
95
 
93
96
  Args:
94
97
  - slice (int | float): Represents the slice of the circle to calculate
@@ -111,22 +114,21 @@ def sliceToY(slice: Union[int, float], r: Union[int, float], offset: Union[int,
111
114
 
112
115
 
113
116
  def draw_zodiac_slice(
114
- c1: Union[int, float],
115
- chart_type: ChartType,
116
- sixth_house_degree_ut: Union[int, float],
117
- num: int,
118
- r: Union[int, float],
119
- style: str,
120
- type: str,
121
- ):
122
- """
123
- Draws a zodiac slice based on the given parameters.
117
+ c1: Union[int, float],
118
+ chart_type: ChartType,
119
+ seventh_house_degree_ut: Union[int, float],
120
+ num: int,
121
+ r: Union[int, float],
122
+ style: str,
123
+ type: str,
124
+ ) -> str:
125
+ """Draws a zodiac slice based on the given parameters.
124
126
 
125
127
  Args:
126
128
  - c1 (Union[int, float]): The value of c1.
127
129
  - chart_type (Literal["Natal", "ExternalNatal", "Synastry", "Transit"]): The type of chart.
128
- - sixth_house_degree_ut (Union[int, float]): The degree of the sixth house.
129
- - num (int): The number of the sign. Note: In OpenAstro it did refer to self.zodiac,
130
+ - seventh_house_degree_ut (Union[int, float]): The degree of the seventh house.
131
+ - num (int): The number of the sign. Note: In OpenAstro it did refer to self.zodiac,
130
132
  which is a list of the signs in order, starting with Aries. Eg:
131
133
  {"name": "aries", "element": "fire"}
132
134
  - r (Union[int, float]): The value of r.
@@ -139,7 +141,7 @@ def draw_zodiac_slice(
139
141
  """
140
142
 
141
143
  # pie slices
142
- offset = 360 - sixth_house_degree_ut
144
+ offset = 360 - seventh_house_degree_ut
143
145
  # check transit
144
146
  if chart_type == "Transit" or chart_type == "Synastry":
145
147
  dropin = 0
@@ -156,4 +158,240 @@ def draw_zodiac_slice(
156
158
  dropin = 18 + c1
157
159
  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>'
158
160
 
159
- return slice + "" + sign
161
+ return slice + "" + sign
162
+
163
+
164
+ def convert_latitude_coordinate_to_string(coord: Union[int, float], north_label: str, south_label: str) -> str:
165
+ """Converts a floating point latitude to string with
166
+ degree, minutes and seconds and the appropriate sign
167
+ (north or south). Eg. 52.1234567 -> 52°7'25" N
168
+
169
+ Args:
170
+ - coord (float | int): latitude in floating or integer format
171
+ - north_label (str): String label for north
172
+ - south_label (str): String label for south
173
+ Returns:
174
+ - str: latitude in string format with degree, minutes,
175
+ seconds and sign (N/S)
176
+ """
177
+
178
+ sign = north_label
179
+ if coord < 0.0:
180
+ sign = south_label
181
+ coord = abs(coord)
182
+ deg = int(coord)
183
+ min = int((float(coord) - deg) * 60)
184
+ sec = int(round(float(((float(coord) - deg) * 60) - min) * 60.0))
185
+ return f"{deg}°{min}'{sec}\" {sign}"
186
+
187
+
188
+ def convert_longitude_coordinate_to_string(coord: Union[int, float], east_label: str, west_label: str) -> str:
189
+ """Converts a floating point longitude to string with
190
+ degree, minutes and seconds and the appropriate sign
191
+ (east or west). Eg. 52.1234567 -> 52°7'25" E
192
+
193
+ Args:
194
+ - coord (float|int): longitude in floating point format
195
+ - east_label (str): String label for east
196
+ - west_label (str): String label for west
197
+ Returns:
198
+ str: longitude in string format with degree, minutes,
199
+ seconds and sign (E/W)
200
+ """
201
+
202
+ sign = east_label
203
+ if coord < 0.0:
204
+ sign = west_label
205
+ coord = abs(coord)
206
+ deg = int(coord)
207
+ min = int((float(coord) - deg) * 60)
208
+ sec = int(round(float(((float(coord) - deg) * 60) - min) * 60.0))
209
+ return f"{deg}°{min}'{sec}\" {sign}"
210
+
211
+
212
+ def draw_aspect_line(
213
+ r: Union[int, float],
214
+ ar: Union[int, float],
215
+ degA: Union[int, float],
216
+ degB: Union[int, float],
217
+ color: str,
218
+ seventh_house_degree_ut: Union[int, float],
219
+ ) -> str:
220
+ """Draws svg aspects: ring, aspect ring, degreeA degreeB
221
+
222
+ Args:
223
+ - r (Union[int, float]): The value of r.
224
+ - ar (Union[int, float]): The value of ar.
225
+ - degA (Union[int, float]): The degree of A.
226
+ - degB (Union[int, float]): The degree of B.
227
+ - color (str): The color of the aspect.
228
+ - seventh_house_degree_ut (Union[int, float]): The degree of the seventh house.
229
+
230
+ Returns:
231
+ str: The SVG line element as a string.
232
+ """
233
+
234
+ first_offset = (int(seventh_house_degree_ut) / -1) + int(degA)
235
+ x1 = sliceToX(0, ar, first_offset) + (r - ar)
236
+ y1 = sliceToY(0, ar, first_offset) + (r - ar)
237
+
238
+ second_offset = (int(seventh_house_degree_ut) / -1) + int(degB)
239
+ x2 = sliceToX(0, ar, second_offset) + (r - ar)
240
+ y2 = sliceToY(0, ar, second_offset) + (r - ar)
241
+
242
+ out = f'<line class="aspect" x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {color}; stroke-width: 1; stroke-opacity: .9;"/>'
243
+
244
+ return out
245
+
246
+
247
+ def draw_elements_percentages(
248
+ fire_label: str,
249
+ fire_points: float,
250
+ earth_label: str,
251
+ earth_points: float,
252
+ air_label: str,
253
+ air_points: float,
254
+ water_label: str,
255
+ water_points: float,
256
+ ) -> str:
257
+ """Draw the elements grid.
258
+
259
+ Args:
260
+ - fire_label (str): Label for fire
261
+ - fire_points (float): Points for fire
262
+ - earth_label (str): Label for earth
263
+ - earth_points (float): Points for earth
264
+ - air_label (str): Label for air
265
+ - air_points (float): Points for air
266
+ - water_label (str): Label for water
267
+ - water_points (float): Points for water
268
+
269
+ Returns:
270
+ str: The SVG elements grid as a string.
271
+ """
272
+ total = fire_points + earth_points + air_points + water_points
273
+
274
+ fire_percentage = int(round(100 * fire_points / total))
275
+ earth_percentage = int(round(100 * earth_points / total))
276
+ air_percentage = int(round(100 * air_points / total))
277
+ water_percentage = int(round(100 * water_points / total))
278
+
279
+ out = '<g transform="translate(-30,79)">'
280
+ out += f'<text y="0" style="fill:#ff6600; font-size: 10px;">{fire_label} {str(fire_percentage)}%</text>'
281
+ out += f'<text y="12" style="fill:#6a2d04; font-size: 10px;">{earth_label} {str(earth_percentage)}%</text>'
282
+ out += f'<text y="24" style="fill:#6f76d1; font-size: 10px;">{air_label} {str(air_percentage)}%</text>'
283
+ out += f'<text y="36" style="fill:#630e73; font-size: 10px;">{water_label} {str(water_percentage)}%</text>'
284
+ out += "</g>"
285
+
286
+ return out
287
+
288
+
289
+ def convert_decimal_to_degree_string(dec: float, type="3") -> str:
290
+ """
291
+ Coverts decimal float to degrees in format a°b'c".
292
+
293
+ Args:
294
+ - dec (float): decimal float
295
+ - type (str): type of format:
296
+ - 1: a°
297
+ - 2: a°b'
298
+ - 3: a°b'c"
299
+
300
+ Returns:
301
+ str: degrees in format a°b'c"
302
+ """
303
+
304
+ dec = float(dec)
305
+ a = int(dec)
306
+ a_new = (dec - float(a)) * 60.0
307
+ b_rounded = int(round(a_new))
308
+ b = int(a_new)
309
+ c = int(round((a_new - float(b)) * 60.0))
310
+
311
+ if type == "3":
312
+ out = f"{a:02d}&#176;{b:02d}&#39;{c:02d}&#34;"
313
+ elif type == "2":
314
+ out = f"{a:02d}&#176;{b_rounded:02d}&#39;"
315
+ elif type == "1":
316
+ out = f"{a:02d}&#176;"
317
+ else:
318
+ raise KerykeionException(f"Wrong type: {type}, it must be 1, 2 or 3.")
319
+
320
+ return str(out)
321
+
322
+
323
+ def draw_transit_ring_degree_steps(r: Union[int, float], seventh_house_degree_ut: Union[int, float]) -> str:
324
+ """Draws the transit ring degree steps.
325
+
326
+ Args:
327
+ - r (Union[int, float]): The value of r.
328
+ - seventh_house_degree_ut (Union[int, float]): The degree of the seventh house.
329
+
330
+ Returns:
331
+ str: The SVG path of the transit ring degree steps.
332
+ """
333
+
334
+ out = '<g id="transitRingDegreeSteps">'
335
+ for i in range(72):
336
+ offset = float(i * 5) - seventh_house_degree_ut
337
+ if offset < 0:
338
+ offset = offset + 360.0
339
+ elif offset > 360:
340
+ offset = offset - 360.0
341
+ x1 = sliceToX(0, r, offset)
342
+ y1 = sliceToY(0, r, offset)
343
+ x2 = sliceToX(0, r + 2, offset) - 2
344
+ y2 = sliceToY(0, r + 2, offset) - 2
345
+ out += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: #F00; stroke-width: 1px; stroke-opacity:.9;"/>'
346
+ out += "</g>"
347
+
348
+ return out
349
+
350
+
351
+ def draw_degree_ring(r: Union[int, float], c1: Union[int, float], seventh_house_degree_ut: Union[int, float], stroke_color: str) -> str:
352
+ """Draws the degree ring.
353
+
354
+ Args:
355
+ - r (Union[int, float]): The value of r.
356
+ - c1 (Union[int, float]): The value of c1.
357
+ - seventh_house_degree_ut (Union[int, float]): The degree of the seventh house.
358
+ - stroke_color (str): The color of the stroke.
359
+
360
+ Returns:
361
+ str: The SVG path of the degree ring.
362
+ """
363
+ out = '<g id="degreeRing">'
364
+ for i in range(72):
365
+ offset = float(i * 5) - seventh_house_degree_ut
366
+ if offset < 0:
367
+ offset = offset + 360.0
368
+ elif offset > 360:
369
+ offset = offset - 360.0
370
+ x1 = sliceToX(0, r - c1, offset) + c1
371
+ y1 = sliceToY(0, r - c1, offset) + c1
372
+ x2 = sliceToX(0, r + 2 - c1, offset) - 2 + c1
373
+ y2 = sliceToY(0, r + 2 - c1, offset) - 2 + c1
374
+
375
+ out += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {stroke_color}; stroke-width: 1px; stroke-opacity:.9;"/>'
376
+ out += "</g>"
377
+
378
+ return out
379
+
380
+ def draw_transit_ring(r: Union[int, float], paper_1_color: str, zodiac_transit_ring_3_color: str) -> str:
381
+ """
382
+ Draws the transit ring.
383
+
384
+ Args:
385
+ - r (Union[int, float]): The value of r.
386
+ - paper_1_color (str): The color of paper 1.
387
+ - zodiac_transit_ring_3_color (str): The color of the zodiac transit ring
388
+
389
+ Returns:
390
+ str: The SVG path of the transit ring.
391
+ """
392
+ radius_offset = 18
393
+
394
+ out = f'<circle cx="{r}" cy="{r}" r="{r - radius_offset}" style="fill: none; stroke: {paper_1_color}; stroke-width: 36px; stroke-opacity: .4;"/>'
395
+ out += f'<circle cx="{r}" cy="{r}" r="{r}" style="fill: none; stroke: {zodiac_transit_ring_3_color}; stroke-width: 1px; stroke-opacity: .6;"/>'
396
+
397
+ return out
@@ -4,20 +4,32 @@
4
4
  """
5
5
 
6
6
 
7
- import pytz
8
7
  import logging
9
8
 
10
- from datetime import datetime
11
9
  from kerykeion.settings.kerykeion_settings import get_settings
12
10
  from kerykeion.aspects.synastry_aspects import SynastryAspects
13
11
  from kerykeion.aspects.natal_aspects import NatalAspects
14
12
  from kerykeion.astrological_subject import AstrologicalSubject
15
13
  from kerykeion.kr_types import KerykeionException, ChartType
16
14
  from kerykeion.kr_types import ChartTemplateDictionary
17
- from kerykeion.charts.charts_utils import decHourJoin, degreeDiff, offsetToTz, sliceToX, sliceToY, draw_zodiac_slice
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
+ )
18
30
  from pathlib import Path
19
31
  from string import Template
20
- from typing import Union
32
+ from typing import Union, List
21
33
 
22
34
 
23
35
  class KerykeionChartSVG:
@@ -34,6 +46,7 @@ class KerykeionChartSVG:
34
46
  - new_settings_file: Set the settings file (default: kr.config.json)
35
47
  """
36
48
 
49
+ # Set at init
37
50
  first_obj: AstrologicalSubject
38
51
  second_obj: Union[AstrologicalSubject, None]
39
52
  chart_type: ChartType
@@ -41,6 +54,46 @@ class KerykeionChartSVG:
41
54
  new_settings_file: Union[Path, None]
42
55
  output_directory: Path
43
56
 
57
+ # Internal properties
58
+ fire: float
59
+ earth: float
60
+ air: float
61
+ water: float
62
+ c1: float
63
+ c2: float
64
+ c3: float
65
+ homedir: Path
66
+ xml_svg: Path
67
+ natal_width: float
68
+ full_width: float
69
+ language_settings: dict
70
+ chart_colors_settings: dict
71
+ planets_settings: dict
72
+ aspects_settings: dict
73
+ planet_in_zodiac_extra_points: int
74
+ chart_settings: dict
75
+ user: AstrologicalSubject
76
+ available_planets_setting: List[KerykeionSettingsCelestialPointModel]
77
+ transit_ring_exclude_points_names: List[str]
78
+ points_deg_ut: list
79
+ points_deg: list
80
+ points_sign: list
81
+ points_retrograde: list
82
+ houses_sign_graph: list
83
+ t_points_deg_ut: list
84
+ t_points_deg: list
85
+ t_points_sign: list
86
+ t_points_retrograde: list
87
+ t_houses_sign_graph: list
88
+ screen_width: float
89
+ screen_height: float
90
+ location: str
91
+ geolat: float
92
+ geolon: float
93
+ zoom: int
94
+ zodiac: tuple
95
+ template: str
96
+
44
97
  def __init__(
45
98
  self,
46
99
  first_obj: AstrologicalSubject,
@@ -77,7 +130,23 @@ class KerykeionChartSVG:
77
130
  continue
78
131
 
79
132
  self.available_planets_setting.append(body)
80
-
133
+
134
+ # House cusp points are excluded from the transit ring.
135
+ self.transit_ring_exclude_points_names = [
136
+ "First_House",
137
+ "Second_House",
138
+ "Third_House",
139
+ "Fourth_House",
140
+ "Fifth_House",
141
+ "Sixth_House",
142
+ "Seventh_House",
143
+ "Eighth_House",
144
+ "Ninth_House",
145
+ "Tenth_House",
146
+ "Eleventh_House",
147
+ "Twelfth_House"
148
+ ]
149
+
81
150
  # Available bodies
82
151
  available_celestial_points = []
83
152
  for body in self.available_planets_setting:
@@ -152,57 +221,15 @@ class KerykeionChartSVG:
152
221
  self.screen_width = 1200
153
222
  self.screen_height = 772.2
154
223
 
155
- # check for home
156
- self.home_location = self.user.city
157
- self.home_geolat = self.user.lat
158
- self.home_geolon = self.user.lng
159
- self.home_countrycode = self.user.nation
160
- self.home_timezonestr = self.user.tz_str
161
-
162
- logging.info(f"{self.user.name} birth location: {self.home_location}, {self.home_geolat}, {self.home_geolon}")
163
-
164
224
  # default location
165
- self.location = self.home_location
166
- self.geolat = float(self.home_geolat)
167
- self.geolon = float(self.home_geolon)
168
- self.countrycode = self.home_countrycode
169
- self.timezonestr = self.home_timezonestr
170
-
171
- # current datetime
172
- now = datetime.now()
173
-
174
- # aware datetime object
175
- dt_input = datetime(now.year, now.month, now.day, now.hour, now.minute, now.second)
176
- dt = pytz.timezone(self.timezonestr).localize(dt_input)
177
-
178
- # naive utc datetime object
179
- dt_utc = dt.replace(tzinfo=None) - dt.utcoffset() # type: ignore
180
-
181
- # Default
182
- self.name = self.user.name
183
- self.charttype = self.chart_type
184
- self.year = self.user.utc.year
185
- self.month = self.user.utc.month
186
- self.day = self.user.utc.day
187
- self.hour = self.user.utc.hour + self.user.utc.minute / 100
188
- self.timezone = offsetToTz(dt.utcoffset())
189
- self.altitude = 25
190
- self.geonameid = None
191
-
192
- # Transit
225
+ self.location = self.user.city
226
+ self.geolat = self.user.lat
227
+ self.geolon = self.user.lng
228
+
229
+ logging.info(f"{self.user.name} birth location: {self.location}, {self.geolat}, {self.geolon}")
193
230
 
194
231
  if self.chart_type == "Transit":
195
- self.t_geolon = self.geolon
196
- self.t_geolat = self.geolat
197
- self.t_altitude = self.altitude
198
232
  self.t_name = self.language_settings["transit_name"]
199
- self.t_year = dt_utc.year
200
- self.t_month = dt_utc.month
201
- self.t_day = dt_utc.day
202
- self.t_hour = decHourJoin(dt_utc.hour, dt_utc.minute, dt_utc.second)
203
- self.t_timezone = offsetToTz(dt.utcoffset())
204
- self.t_altitude = 25
205
- self.t_geonameid = None
206
233
 
207
234
  # configuration
208
235
  # ZOOM 1 = 100%
@@ -247,130 +274,6 @@ class KerykeionChartSVG:
247
274
  self.planet_in_zodiac_extra_points = settings["general_settings"]["planet_in_zodiac_extra_points"]
248
275
  self.chart_settings = settings["chart_settings"]
249
276
 
250
- def _transitRing(self, r) -> str:
251
- """
252
- Draws the transit ring.
253
- """
254
- radius_offset = 18
255
-
256
- 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;"/>'
257
- 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;"/>'
258
-
259
- return out
260
-
261
- def _degreeRing(self, r) -> str:
262
- """
263
- Draws the degree ring.
264
- """
265
- out = ""
266
- for i in range(72):
267
- offset = float(i * 5) - self.user.houses_degree_ut[6]
268
- if offset < 0:
269
- offset = offset + 360.0
270
- elif offset > 360:
271
- offset = offset - 360.0
272
- x1 = sliceToX(0, r - self.c1, offset) + self.c1
273
- y1 = sliceToY(0, r - self.c1, offset) + self.c1
274
- x2 = sliceToX(0, r + 2 - self.c1, offset) - 2 + self.c1
275
- y2 = sliceToY(0, r + 2 - self.c1, offset) - 2 + self.c1
276
-
277
- 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;"/>'
278
-
279
- return out
280
-
281
- def _degreeTransitRing(self, r):
282
- out = ""
283
- for i in range(72):
284
- offset = float(i * 5) - self.user.houses_degree_ut[6]
285
- if offset < 0:
286
- offset = offset + 360.0
287
- elif offset > 360:
288
- offset = offset - 360.0
289
- x1 = sliceToX(0, r, offset)
290
- y1 = sliceToY(0, r, offset)
291
- x2 = sliceToX(0, r + 2, offset) - 2
292
- y2 = sliceToY(0, r + 2, offset) - 2
293
- out += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: #F00; stroke-width: 1px; stroke-opacity:.9;"/>'
294
-
295
- return out
296
-
297
- def _lat2str(self, coord):
298
- """Converts a floating point latitude to string with
299
- degree, minutes and seconds and the appropriate sign
300
- (north or south). Eg. 52.1234567 -> 52°7'25" N
301
-
302
- Args:
303
- coord (float): latitude in floating point format
304
- Returns:
305
- str: latitude in string format with degree, minutes,
306
- seconds and sign (N/S)
307
- """
308
-
309
- sign = self.language_settings["north"]
310
- if coord < 0.0:
311
- sign = self.language_settings["south"]
312
- coord = abs(coord)
313
- deg = int(coord)
314
- min = int((float(coord) - deg) * 60)
315
- sec = int(round(float(((float(coord) - deg) * 60) - min) * 60.0))
316
- return f"{deg}°{min}'{sec}\" {sign}"
317
-
318
- def _lon2str(self, coord):
319
- """Converts a floating point longitude to string with
320
- degree, minutes and seconds and the appropriate sign
321
- (east or west). Eg. 52.1234567 -> 52°7'25" E
322
-
323
- Args:
324
- coord (float): longitude in floating point format
325
- Returns:
326
- str: longitude in string format with degree, minutes,
327
- seconds and sign (E/W)
328
- """
329
-
330
- sign = self.language_settings["east"]
331
- if coord < 0.0:
332
- sign = self.language_settings["west"]
333
- coord = abs(coord)
334
- deg = int(coord)
335
- min = int((float(coord) - deg) * 60)
336
- sec = int(round(float(((float(coord) - deg) * 60) - min) * 60.0))
337
- return f"{deg}°{min}'{sec}\" {sign}"
338
-
339
- def _dec2deg(self, dec, type="3"):
340
- """Coverts decimal float to degrees in format
341
- a°b'c".
342
- """
343
-
344
- dec = float(dec)
345
- a = int(dec)
346
- a_new = (dec - float(a)) * 60.0
347
- b_rounded = int(round(a_new))
348
- b = int(a_new)
349
- c = int(round((a_new - float(b)) * 60.0))
350
- if type == "3":
351
- out = f"{a:02d}&#176;{b:02d}&#39;{c:02d}&#34;"
352
- elif type == "2":
353
- out = f"{a:02d}&#176;{b_rounded:02d}&#39;"
354
- elif type == "1":
355
- out = f"{a:02d}&#176;"
356
- else:
357
- raise KerykeionException(f"Wrong type: {type}, it must be 1, 2 or 3.")
358
- return str(out)
359
-
360
- def _drawAspect(self, r, ar, degA, degB, color):
361
- """
362
- Draws svg aspects: ring, aspect ring, degreeA degreeB
363
- """
364
- offset = (int(self.user.houses_degree_ut[6]) / -1) + int(degA)
365
- x1 = sliceToX(0, ar, offset) + (r - ar)
366
- y1 = sliceToY(0, ar, offset) + (r - ar)
367
- offset = (int(self.user.houses_degree_ut[6]) / -1) + int(degB)
368
- x2 = sliceToX(0, ar, offset) + (r - ar)
369
- y2 = sliceToY(0, ar, offset) + (r - ar)
370
- out = f' <line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {color}; stroke-width: 1; stroke-opacity: .9;"/>'
371
-
372
- return out
373
-
374
277
  def _draw_zodiac_circle_slices(self, r):
375
278
  """
376
279
  Generate the SVG string representing the zodiac circle
@@ -388,7 +291,7 @@ class KerykeionChartSVG:
388
291
  output += draw_zodiac_slice(
389
292
  c1=self.c1,
390
293
  chart_type=self.chart_type,
391
- sixth_house_degree_ut=self.user.houses_degree_ut[6],
294
+ seventh_house_degree_ut=self.user.houses_degree_ut[6],
392
295
  num=i,
393
296
  r=r,
394
297
  style=f'fill:{self.chart_colors_settings[f"zodiac_bg_{i}"]}; fill-opacity: 0.5;',
@@ -484,44 +387,50 @@ class KerykeionChartSVG:
484
387
 
485
388
  return path
486
389
 
487
- def _value_element_from_planet(self, i):
390
+ def _calculate_elements_points_from_planets(self):
488
391
  """
489
392
  Calculate chart element points from a planet.
490
393
  """
394
+
395
+ for i in range(len(self.available_planets_setting)):
396
+ # element: get extra points if planet is in own zodiac sign.
397
+ related_zodiac_signs = self.available_planets_setting[i]["related_zodiac_signs"]
398
+ cz = self.points_sign[i]
399
+ extra_points = 0
400
+ if related_zodiac_signs != []:
401
+ for e in range(len(related_zodiac_signs)):
402
+ if int(related_zodiac_signs[e]) == int(cz):
403
+ extra_points = self.planet_in_zodiac_extra_points
491
404
 
492
- # element: get extra points if planet is in own zodiac sign.
493
- related_zodiac_signs = self.available_planets_setting[i]["related_zodiac_signs"]
494
- cz = self.points_sign[i]
495
- extra_points = 0
496
- if related_zodiac_signs != []:
497
- for e in range(len(related_zodiac_signs)):
498
- if int(related_zodiac_signs[e]) == int(cz):
499
- extra_points = self.planet_in_zodiac_extra_points
500
-
501
- ele = self.zodiac[self.points_sign[i]]["element"]
502
- if ele == "fire":
503
- self.fire = self.fire + self.available_planets_setting[i]["element_points"] + extra_points
405
+ ele = self.zodiac[self.points_sign[i]]["element"]
406
+ if ele == "fire":
407
+ self.fire = self.fire + self.available_planets_setting[i]["element_points"] + extra_points
504
408
 
505
- elif ele == "earth":
506
- self.earth = self.earth + self.available_planets_setting[i]["element_points"] + extra_points
409
+ elif ele == "earth":
410
+ self.earth = self.earth + self.available_planets_setting[i]["element_points"] + extra_points
507
411
 
508
- elif ele == "air":
509
- self.air = self.air + self.available_planets_setting[i]["element_points"] + extra_points
412
+ elif ele == "air":
413
+ self.air = self.air + self.available_planets_setting[i]["element_points"] + extra_points
510
414
 
511
- elif ele == "water":
512
- self.water = self.water + self.available_planets_setting[i]["element_points"] + extra_points
415
+ elif ele == "water":
416
+ self.water = self.water + self.available_planets_setting[i]["element_points"] + extra_points
513
417
 
514
418
  def _make_planets(self, r):
515
419
  planets_degut = {}
516
420
  diff = range(len(self.available_planets_setting))
517
421
 
518
422
  for i in range(len(self.available_planets_setting)):
519
- if self.available_planets_setting[i]["is_active"] == 1:
520
- # list of planets sorted by degree
521
- logging.debug(f"planet: {i}, degree: {self.points_deg_ut[i]}")
522
- planets_degut[self.points_deg_ut[i]] = i
423
+ # list of planets sorted by degree
424
+ logging.debug(f"planet: {i}, degree: {self.points_deg_ut[i]}")
425
+ planets_degut[self.points_deg_ut[i]] = i
523
426
 
524
- self._value_element_from_planet(i)
427
+ """
428
+ FIXME: The planets_degut is a dictionary like:
429
+ {planet_degree: planet_index}
430
+ It should be replaced bu points_deg_ut
431
+ print(self.points_deg_ut)
432
+ print(planets_degut)
433
+ """
525
434
 
526
435
  output = ""
527
436
  keys = list(planets_degut.keys())
@@ -703,14 +612,15 @@ class KerykeionChartSVG:
703
612
  if self.chart_type == "Transit" or self.chart_type == "Synastry":
704
613
  group_offset = {}
705
614
  t_planets_degut = {}
706
- if self.chart_type == "Transit":
707
- list_range = len(self.available_planets_setting) - 4
708
- else:
709
- list_range = len(self.available_planets_setting)
615
+ list_range = len(self.available_planets_setting)
616
+
710
617
  for i in range(list_range):
618
+ if self.chart_type == "Transit" and self.available_planets_setting[i]['name'] in self.transit_ring_exclude_points_names:
619
+ continue
620
+
711
621
  group_offset[i] = 0
712
- if self.available_planets_setting[i]["is_active"] == 1:
713
- t_planets_degut[self.t_points_deg_ut[i]] = i
622
+ t_planets_degut[self.t_points_deg_ut[i]] = i
623
+
714
624
  t_keys = list(t_planets_degut.keys())
715
625
  t_keys.sort()
716
626
 
@@ -752,7 +662,12 @@ class KerykeionChartSVG:
752
662
  group_offset[groups[i][3]] = 2.0
753
663
 
754
664
  switch = 0
665
+
666
+ # Transit planets loop
755
667
  for e in range(len(t_keys)):
668
+ if self.chart_type == "Transit" and self.available_planets_setting[e]["name"] in self.transit_ring_exclude_points_names:
669
+ continue
670
+
756
671
  i = t_planets_degut[t_keys[e]]
757
672
 
758
673
  if 22 < i < 27:
@@ -764,20 +679,21 @@ class KerykeionChartSVG:
764
679
  rplanet = 26
765
680
  switch = 1
766
681
 
682
+ # Transit planet name
767
683
  zeropoint = 360 - self.user.houses_degree_ut[6]
768
684
  t_offset = zeropoint + self.t_points_deg_ut[i]
769
685
  if t_offset > 360:
770
686
  t_offset = t_offset - 360
771
687
  planet_x = sliceToX(0, (r - rplanet), t_offset) + rplanet
772
688
  planet_y = sliceToY(0, (r - rplanet), t_offset) + rplanet
773
- output += f'<g 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>'
689
+ 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>'
774
690
 
775
- # transit planet line
691
+ # Transit planet line
776
692
  x1 = sliceToX(0, r + 3, t_offset) - 3
777
693
  y1 = sliceToY(0, r + 3, t_offset) - 3
778
694
  x2 = sliceToX(0, r - 3, t_offset) + 3
779
695
  y2 = sliceToY(0, r - 3, t_offset) + 3
780
- output += f'<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;"/>'
696
+ 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;"/>'
781
697
 
782
698
  # transit planet degree text
783
699
  rotate = self.user.houses_degree_ut[0] - self.t_points_deg_ut[i]
@@ -801,7 +717,7 @@ class KerykeionChartSVG:
801
717
  degree = int(t_offset)
802
718
  output += f'<g transform="translate({deg_x},{deg_y})">'
803
719
  output += f'<text transform="rotate({rotate})" text-anchor="{textanchor}'
804
- output += f'" style="fill: {self.available_planets_setting[i]["color"]}; font-size: 10px;">{self._dec2deg(self.t_points_deg[i], type="1")}'
720
+ 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")}'
805
721
  output += "</text></g>"
806
722
 
807
723
  # check transit
@@ -983,12 +899,13 @@ class KerykeionChartSVG:
983
899
  def _makeAspects(self, r, ar):
984
900
  out = ""
985
901
  for element in self.aspects_list:
986
- out += self._drawAspect(
987
- r,
988
- ar,
989
- element["p1_abs_pos"],
990
- element["p2_abs_pos"],
991
- self.aspects_settings[element["aid"]]["color"],
902
+ out += draw_aspect_line(
903
+ r=r,
904
+ ar=ar,
905
+ degA=element["p1_abs_pos"],
906
+ degB=element["p2_abs_pos"],
907
+ color=self.aspects_settings[element["aid"]]["color"],
908
+ seventh_house_degree_ut=self.user.seventh_house.abs_pos
992
909
  )
993
910
 
994
911
  return out
@@ -1004,24 +921,22 @@ class KerykeionChartSVG:
1004
921
  counter = 0
1005
922
  for a in revr:
1006
923
  counter += 1
1007
- if self.available_planets_setting[a]["is_active"] == 1:
1008
- out += f'<rect x="{xindent}" y="{yindent}" width="{box}" height="{box}" style="{style}"/>'
1009
- 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"]}" />'
1010
-
1011
- xindent = xindent + box
1012
- yindent = yindent - box
1013
- revr2 = list(range(a))
1014
- revr2.reverse()
1015
- xorb = xindent
1016
- yorb = yindent + box
1017
- for b in revr2:
1018
- if self.available_planets_setting[b]["is_active"] == 1:
1019
- out += f'<rect x="{xorb}" y="{yorb}" width="{box}" height="{box}" style="{style}"/>'
1020
-
1021
- xorb = xorb + box
1022
- for element in self.aspects_list:
1023
- if (element["p1"] == a and element["p2"] == b) or (element["p1"] == b and element["p2"] == a):
1024
- out += f'<use x="{xorb-box+1}" y="{yorb+1}" xlink:href="#orb{element["aspect_degrees"]}" />'
924
+ out += f'<rect x="{xindent}" y="{yindent}" width="{box}" height="{box}" style="{style}"/>'
925
+ 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"]}" />'
926
+
927
+ xindent = xindent + box
928
+ yindent = yindent - box
929
+ revr2 = list(range(a))
930
+ revr2.reverse()
931
+ xorb = xindent
932
+ yorb = yindent + box
933
+ for b in revr2:
934
+ out += f'<rect x="{xorb}" y="{yorb}" width="{box}" height="{box}" style="{style}"/>'
935
+
936
+ xorb = xorb + box
937
+ for element in self.aspects_list:
938
+ if (element["p1"] == a and element["p2"] == b) or (element["p1"] == b and element["p2"] == a):
939
+ out += f'<use x="{xorb-box+1}" y="{yorb+1}" xlink:href="#orb{element["aspect_degrees"]}" />'
1025
940
 
1026
941
  return out
1027
942
 
@@ -1032,12 +947,13 @@ class KerykeionChartSVG:
1032
947
  self.aspects_list = SynastryAspects(self.user, self.t_user, new_settings_file=self.new_settings_file).relevant_aspects
1033
948
 
1034
949
  for element in self.aspects_list:
1035
- out += self._drawAspect(
1036
- r,
1037
- ar,
1038
- element["p1_abs_pos"],
1039
- element["p2_abs_pos"],
1040
- self.aspects_settings[element["aid"]]["color"],
950
+ out += draw_aspect_line(
951
+ r=r,
952
+ ar=ar,
953
+ degA=element["p1_abs_pos"],
954
+ degB=element["p2_abs_pos"],
955
+ color=self.aspects_settings[element["aid"]]["color"],
956
+ seventh_house_degree_ut=self.user.seventh_house.abs_pos
1041
957
  )
1042
958
 
1043
959
  return out
@@ -1088,36 +1004,20 @@ class KerykeionChartSVG:
1088
1004
 
1089
1005
  out += "</g>"
1090
1006
  # difference in degrees
1091
- out += f'<text y="8" x="45" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{self._dec2deg(self.aspects_list[i]["orbit"])}</text>'
1007
+ 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>'
1092
1008
  # line
1093
1009
  out += "</g>"
1094
1010
  line = line + 14
1095
1011
  out += "</g>"
1096
1012
  return out
1097
1013
 
1098
- def _makeElements(self, r):
1099
- total = self.fire + self.earth + self.air + self.water
1100
- pf = int(round(100 * self.fire / total))
1101
- pe = int(round(100 * self.earth / total))
1102
- pa = int(round(100 * self.air / total))
1103
- pw = int(round(100 * self.water / total))
1104
-
1105
- out = '<g transform="translate(-30,79)">'
1106
- out += f'<text y="0" style="fill:#ff6600; font-size: 10px;">{self.language_settings["fire"]} {str(pf)}%</text>'
1107
- out += f'<text y="12" style="fill:#6a2d04; font-size: 10px;">{self.language_settings["earth"]} {str(pe)}%</text>'
1108
- out += f'<text y="24" style="fill:#6f76d1; font-size: 10px;">{self.language_settings["air"]} {str(pa)}%</text>'
1109
- out += f'<text y="36" style="fill:#630e73; font-size: 10px;">{self.language_settings["water"]} {str(pw)}%</text>'
1110
- out += "</g>"
1111
-
1112
- return out
1113
-
1114
1014
  def _makePlanetGrid(self):
1115
1015
  li = 10
1116
1016
  offset = 0
1117
1017
 
1118
1018
  out = '<g transform="translate(500,-20)">'
1119
1019
  out += '<g transform="translate(140, -15)">'
1120
- 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>'
1020
+ 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>'
1121
1021
  out += "</g>"
1122
1022
 
1123
1023
  end_of_line = None
@@ -1140,7 +1040,7 @@ class KerykeionChartSVG:
1140
1040
  out += f'<g transform="translate(5,-8)"><use transform="scale(0.4)" xlink:href="#{self.available_planets_setting[i]["name"]}" /></g>'
1141
1041
 
1142
1042
  # planet degree
1143
- out += f'<text text-anchor="start" x="19" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{self._dec2deg(self.points_deg[i])}</text>'
1043
+ 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>'
1144
1044
 
1145
1045
  # zodiac
1146
1046
  out += f'<g transform="translate(60,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.points_sign[i]]["name"]}" /></g>'
@@ -1172,27 +1072,26 @@ class KerykeionChartSVG:
1172
1072
  t_li = 10
1173
1073
  t_offset = -120
1174
1074
 
1175
- if self.available_planets_setting[i]["is_active"] == 1:
1176
- # start of line
1177
- out += f'<g transform="translate({t_offset},{t_li})">'
1075
+ # start of line
1076
+ out += f'<g transform="translate({t_offset},{t_li})">'
1178
1077
 
1179
- # planet text
1180
- 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>'
1181
- # planet symbol
1182
- out += f'<g transform="translate(5,-8)"><use transform="scale(0.4)" xlink:href="#{self.available_planets_setting[i]["name"]}" /></g>'
1183
- # planet degree
1184
- out += f'<text text-anchor="start" x="19" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;">{self._dec2deg(self.t_points_deg[i])}</text>'
1185
- # zodiac
1186
- out += f'<g transform="translate(60,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.t_points_sign[i]]["name"]}" /></g>'
1078
+ # planet text
1079
+ 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>'
1080
+ # planet symbol
1081
+ out += f'<g transform="translate(5,-8)"><use transform="scale(0.4)" xlink:href="#{self.available_planets_setting[i]["name"]}" /></g>'
1082
+ # planet degree
1083
+ 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>'
1084
+ # zodiac
1085
+ out += f'<g transform="translate(60,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.t_points_sign[i]]["name"]}" /></g>'
1187
1086
 
1188
- # planet retrograde
1189
- if self.t_points_retrograde[i]:
1190
- out += '<g transform="translate(74,-6)"><use transform="scale(.5)" xlink:href="#retrograde" /></g>'
1087
+ # planet retrograde
1088
+ if self.t_points_retrograde[i]:
1089
+ out += '<g transform="translate(74,-6)"><use transform="scale(.5)" xlink:href="#retrograde" /></g>'
1191
1090
 
1192
- # end of line
1193
- out += end_of_line
1091
+ # end of line
1092
+ out += end_of_line
1194
1093
 
1195
- t_li = t_li + offset_between_lines
1094
+ t_li = t_li + offset_between_lines
1196
1095
 
1197
1096
  if end_of_line is None:
1198
1097
  raise KerykeionException("End of line not found")
@@ -1201,6 +1100,12 @@ class KerykeionChartSVG:
1201
1100
  return out
1202
1101
 
1203
1102
  def _draw_house_grid(self):
1103
+ """
1104
+ Generate SVG code for a grid of astrological houses.
1105
+
1106
+ Returns:
1107
+ str: The SVG code for the grid of houses.
1108
+ """
1204
1109
  out = '<g transform="translate(600,-20)">'
1205
1110
 
1206
1111
  li = 10
@@ -1212,7 +1117,7 @@ class KerykeionChartSVG:
1212
1117
  out += f'<g transform="translate(0,{li})">'
1213
1118
  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>'
1214
1119
  out += f'<g transform="translate(40,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.houses_sign_graph[i]]["name"]}" /></g>'
1215
- out += f'<text x="53" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;"> {self._dec2deg(self.user.houses_list[i]["position"])}</text>'
1120
+ 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>'
1216
1121
  out += "</g>"
1217
1122
  li = li + 14
1218
1123
 
@@ -1229,7 +1134,7 @@ class KerykeionChartSVG:
1229
1134
  out += '<g transform="translate(0,' + str(li) + ')">'
1230
1135
  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>'
1231
1136
  out += f'<g transform="translate(40,-8)"><use transform="scale(0.3)" xlink:href="#{self.zodiac[self.t_houses_sign_graph[i]]["name"]}" /></g>'
1232
- out += f'<text x="53" style="fill:{self.chart_colors_settings["paper_0"]}; font-size: 10px;"> {self._dec2deg(self.t_user.houses_list[i]["position"])}</text>'
1137
+ 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>'
1233
1138
  out += "</g>"
1234
1139
  li = li + 14
1235
1140
  out += "</g>"
@@ -1244,6 +1149,9 @@ class KerykeionChartSVG:
1244
1149
  self.air = 0.0
1245
1150
  self.water = 0.0
1246
1151
 
1152
+ # Calculate the elements points
1153
+ self._calculate_elements_points_from_planets()
1154
+
1247
1155
  # width and height from screen
1248
1156
  ratio = float(self.screen_width) / float(self.screen_height)
1249
1157
  if ratio < 1.3: # 1280x1024
@@ -1278,8 +1186,8 @@ class KerykeionChartSVG:
1278
1186
 
1279
1187
  # transit
1280
1188
  if self.chart_type == "Transit" or self.chart_type == "Synastry":
1281
- td["transitRing"] = self._transitRing(r)
1282
- td["degreeRing"] = self._degreeTransitRing(r)
1189
+ td["transitRing"] = draw_transit_ring(r, self.chart_colors_settings["paper_1"], self.chart_colors_settings["zodiac_transit_ring_3"])
1190
+ td["degreeRing"] = draw_transit_ring_degree_steps(r, self.user.seventh_house.abs_pos)
1283
1191
 
1284
1192
  # circles
1285
1193
  td["c1"] = f'cx="{r}" cy="{r}" r="{r - 36}"'
@@ -1296,7 +1204,7 @@ class KerykeionChartSVG:
1296
1204
  td["chart_width"] = self.full_width
1297
1205
  else:
1298
1206
  td["transitRing"] = ""
1299
- td["degreeRing"] = self._degreeRing(r)
1207
+ td["degreeRing"] = draw_degree_ring(r, self.c1, self.user.seventh_house.abs_pos, self.chart_colors_settings["paper_0"])
1300
1208
 
1301
1209
  # circles
1302
1210
  td["c1"] = f'cx="{r}" cy="{r}" r="{r - self.c1}"'
@@ -1317,17 +1225,17 @@ class KerykeionChartSVG:
1317
1225
  td["viewbox"] = viewbox
1318
1226
 
1319
1227
  if self.chart_type == "Synastry":
1320
- td["stringTitle"] = f"{self.name} {self.language_settings['and_word']} {self.t_user.name}"
1228
+ td["stringTitle"] = f"{self.user.name} {self.language_settings['and_word']} {self.t_user.name}"
1321
1229
 
1322
1230
  elif self.chart_type == "Transit":
1323
1231
  td["stringTitle"] = f"{self.language_settings['transits']} {self.t_user.day}/{self.t_user.month}/{self.t_user.year}"
1324
1232
 
1325
1233
  else:
1326
- td["stringTitle"] = self.name
1234
+ td["stringTitle"] = self.user.name
1327
1235
 
1328
1236
  # Tipo di carta
1329
- if self.chart_type == "Synastry" or self.name == "Transit":
1330
- td["stringName"] = f"{self.name}:"
1237
+ if self.chart_type == "Synastry" or self.chart_type == "Transit":
1238
+ td["stringName"] = f"{self.user.name}:"
1331
1239
  else:
1332
1240
  td["stringName"] = f'{self.language_settings["info"]}:'
1333
1241
 
@@ -1411,9 +1319,20 @@ class KerykeionChartSVG:
1411
1319
  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}"
1412
1320
 
1413
1321
  else:
1414
- td["stringLat"] = f"{self.language_settings['latitude']}: {self._lat2str(self.geolat)}"
1415
- td["stringLon"] = f"{self.language_settings['longitude']}: {self._lon2str(self.geolon)}"
1416
- td["stringPosition"] = f"{self.language_settings['type']}: {self.charttype}"
1322
+ latitude_string = convert_latitude_coordinate_to_string(
1323
+ self.geolat,
1324
+ self.language_settings['north'],
1325
+ self.language_settings['south']
1326
+ )
1327
+ longitude_string = convert_longitude_coordinate_to_string(
1328
+ self.geolon,
1329
+ self.language_settings['east'],
1330
+ self.language_settings['west']
1331
+ )
1332
+
1333
+ td["stringLat"] = f"{self.language_settings['latitude']}: {latitude_string}"
1334
+ td["stringLon"] = f"{self.language_settings['longitude']}: {longitude_string}"
1335
+ td["stringPosition"] = f"{self.language_settings['type']}: {self.chart_type}"
1417
1336
 
1418
1337
  # paper_color_X
1419
1338
  td["paper_color_0"] = self.chart_colors_settings["paper_0"]
@@ -1446,7 +1365,16 @@ class KerykeionChartSVG:
1446
1365
  # TODO: Add the rest of the functions
1447
1366
  td["makeHouses"] = self._makeHouses(r)
1448
1367
  td["makePlanets"] = self._make_planets(r)
1449
- td["makeElements"] = self._makeElements(r)
1368
+ td["elements_percentages"] = draw_elements_percentages(
1369
+ self.language_settings['fire'],
1370
+ self.fire,
1371
+ self.language_settings['earth'],
1372
+ self.earth,
1373
+ self.language_settings['air'],
1374
+ self.air,
1375
+ self.language_settings['water'],
1376
+ self.water,
1377
+ )
1450
1378
  td["makePlanetGrid"] = self._makePlanetGrid()
1451
1379
 
1452
1380
  return td
@@ -1472,7 +1400,7 @@ class KerykeionChartSVG:
1472
1400
  if not (self.template):
1473
1401
  self.template = self.makeTemplate()
1474
1402
 
1475
- self.chartname = self.output_directory / f"{self.name}{self.chart_type}Chart.svg"
1403
+ self.chartname = self.output_directory / f"{self.user.name}{self.chart_type}Chart.svg"
1476
1404
 
1477
1405
  with open(self.chartname, "w", encoding="utf-8", errors="ignore") as output_file:
1478
1406
  output_file.write(self.template)
@@ -1,7 +1,5 @@
1
1
  <?xml version='1.0' encoding='UTF-8'?>
2
- <!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
3
- <!---
4
- This file is part of Kerykeion and is based on OpenAstro.org -->
2
+ <!--- This file is part of Kerykeion and is based on OpenAstro.org -->
5
3
  <svg
6
4
  xmlns="http://www.w3.org/2000/svg"
7
5
  xmlns:xlink="http://www.w3.org/1999/xlink"
@@ -10,7 +8,7 @@ This file is part of Kerykeion and is based on OpenAstro.org -->
10
8
  viewBox="$viewbox"
11
9
  preserveAspectRatio="xMidYMid"
12
10
  >
13
- <title>Kerykeion</title>
11
+ <title>$stringTitle | Kerykeion</title>
14
12
  <g transform="translate($cfgTranslate)">
15
13
  <g transform="rotate($cfgRotate)">
16
14
  <g transform="scale($cfgZoom)">
@@ -469,20 +467,49 @@ This file is part of Kerykeion and is based on OpenAstro.org -->
469
467
  </symbol>
470
468
  <g transform="translate(50,50)">
471
469
  <g transform="translate($circleX,$circleY)">
472
- <!-- Zodiac -->$makeZodiac <!-- First Circle -->
470
+ <!-- Zodiac -->
471
+ $makeZodiac
472
+
473
+ <!-- First Circle -->
473
474
  <circle $c1 style="$c1style" />
475
+
474
476
  <!-- Second Circle -->
475
- <circle
476
- $c2 style="$c2style" />
477
+ <circle $c2 style="$c2style" />
478
+
477
479
  <!-- Third Circle -->
478
480
  <circle $c3 style="$c3style" />
479
- <!-- TransitRing -->$transitRing <!-- Degree Ring -->$degreeRing <!-- Houses -->
480
- $makeHouses
481
- <!-- Planets -->$makePlanets <!-- Aspects -->$makeAspects </g>
482
- <!-- makePatterns -->$makePatterns <!-- AspectGrid -->
481
+
482
+ <!-- TransitRing -->
483
+ $transitRing
484
+
485
+ <!-- Degree Ring -->
486
+ $degreeRing
487
+
488
+ <!-- Houses -->
489
+ $makeHouses
490
+
491
+ <!-- Planets -->
492
+ $makePlanets
493
+
494
+ <!-- Aspects -->
495
+ $makeAspects
496
+ </g>
497
+
498
+ <!-- makePatterns -->
499
+ $makePatterns
500
+
501
+ <!-- AspectGrid -->
483
502
  $makeAspectGrid
484
- <!-- Elements -->$makeElements <!-- Planet Grid -->$makePlanetGrid <!-- Houses Grid -->
503
+
504
+ <!-- Elements -->
505
+ $elements_percentages
506
+
507
+ <!-- Planet Grid -->
508
+ $makePlanetGrid
509
+
510
+ <!-- Houses Grid -->
485
511
  $makeHousesGrid
512
+
486
513
  </g>
487
514
  </g>
488
515
  </g>
@@ -36,8 +36,13 @@ class ChartTemplateDictionary(TypedDict):
36
36
  stringLat: str
37
37
  stringLon: str
38
38
  stringPosition: str
39
+
40
+ # Font color
39
41
  paper_color_0: str
42
+ # Background color of the chart
40
43
  paper_color_1: str
44
+
45
+ # Planets colors, from 1 to 15 (0 is the Sun)
41
46
  planets_color_0: str
42
47
  planets_color_1: str
43
48
  planets_color_2: str
@@ -54,6 +59,8 @@ class ChartTemplateDictionary(TypedDict):
54
59
  planets_color_13: str
55
60
  planets_color_14: str
56
61
  planets_color_15: str
62
+
63
+ # Zodiac colors, from 0 to 11 (0 is Aries)
57
64
  zodiac_color_0: str
58
65
  zodiac_color_1: str
59
66
  zodiac_color_2: str
@@ -66,6 +73,8 @@ class ChartTemplateDictionary(TypedDict):
66
73
  zodiac_color_9: str
67
74
  zodiac_color_10: str
68
75
  zodiac_color_11: str
76
+
77
+ # Aspects colors, from 0 to 9 (0 is conjunction)
69
78
  orb_color_0: str
70
79
  orb_color_30: str
71
80
  orb_color_45: str
@@ -77,12 +86,13 @@ class ChartTemplateDictionary(TypedDict):
77
86
  orb_color_144: str
78
87
  orb_color_150: str
79
88
  orb_color_180: str
89
+
80
90
  cfgZoom: str
81
91
  cfgRotate: str
82
92
  cfgTranslate: str
83
93
  makeZodiac: str
84
94
  makeHouses: str
85
95
  makePlanets: str
86
- makeElements: str
96
+ elements_percentages: str
87
97
  makePlanetGrid: str
88
98
  makeHousesGrid: str
@@ -4,10 +4,8 @@
4
4
  """
5
5
 
6
6
 
7
- from json import load
8
7
  from pydantic import BaseModel, Field
9
- from pathlib import Path
10
- from typing import Dict, List, Union
8
+ from typing import List
11
9
 
12
10
 
13
11
  class CustomBaseModel(BaseModel):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kerykeion
3
- Version: 4.6.2
3
+ Version: 4.7.0
4
4
  Summary: A python library for astrology.
5
5
  Home-page: https://github.com/g-battaglia/kerykeion
6
6
  License: AGPL-3.0
@@ -6,17 +6,17 @@ kerykeion/aspects/natal_aspects.py,sha256=m3_v1dM6YXvENZ6iN_EJkikKxySZBeR5QKhGsa
6
6
  kerykeion/aspects/synastry_aspects.py,sha256=uwg7Lc7wKnpxW9ydOdBHqx9cvO_t0ydGfIGluBIDD7c,3993
7
7
  kerykeion/astrological_subject.py,sha256=9vLsYZYfAfkR5EJO_EkbkhXa4i788Yv1lCESaQrt5kU,22965
8
8
  kerykeion/charts/__init__.py,sha256=Juxkduy2TaagWblh_7CE8Acrg3dHL27-WEddJhau_eQ,127
9
- kerykeion/charts/charts_utils.py,sha256=jJLgoBcs9e6-ArNFsj_N7Wel0zCzMKEsGrlz_A7MECE,5167
10
- kerykeion/charts/kerykeion_chart_svg.py,sha256=6y0VHsfBEjefSrJErcKB3UH1xFOuWoEps4Y_1-IynVo,64764
11
- kerykeion/charts/templates/chart.xml,sha256=ZrkqJV3Du8vG1w8kVkM1wI-IiZNVDLDuS6dRtPz7wVo,69874
9
+ kerykeion/charts/charts_utils.py,sha256=E5qrvA7uaSxKL0PrcRtWhDP581itIm3kAebsxYVa4hE,13214
10
+ kerykeion/charts/kerykeion_chart_svg.py,sha256=IjR5E2LsKjWjfLeMcjR3UIutixASPcZbs0Ljl3HDSZg,60991
11
+ kerykeion/charts/templates/chart.xml,sha256=7gkzNRQmkOn9hCAOiPbQwd9e8x9shFtF3uEZo5tp8P0,70156
12
12
  kerykeion/enums.py,sha256=Ben9GLYkPucpYY2ZDpURzUbNCc9jzK2MuaffkgiXFdQ,965
13
13
  kerykeion/fetch_geonames.py,sha256=fWuhgP_hZTPzDuodu7hvSznzGCWj3IC3vHAX32zPRw8,4444
14
14
  kerykeion/kr_types/__init__.py,sha256=-qhGQikurdoHnGtuT1bsaEeZ-IwmZtIHMjGOPC9_oqQ,295
15
- kerykeion/kr_types/chart_types.py,sha256=PvdOEqzZZBrJxFKQqAC0KcnfIY4T4I2i6CeLQhvVbe8,1945
15
+ kerykeion/kr_types/chart_types.py,sha256=ZXBfMhidgwSGNEIO6kRELQedc8L7TF4z-pYgW28PA4s,2169
16
16
  kerykeion/kr_types/kerykeion_exception.py,sha256=G-7VFta78qBt10l54JZWvwH-3lUNKmDwuILXaVGVu9A,314
17
17
  kerykeion/kr_types/kr_literals.py,sha256=Kc7LfdeTqHi5uDGoQHWsB81GTBc5E-fGxTJqWKK1FFU,1267
18
18
  kerykeion/kr_types/kr_models.py,sha256=3gyT4z-J9EM6p5175HKJX9q9WVWQTDt5Y_m3m8lZu9s,4260
19
- kerykeion/kr_types/settings_models.py,sha256=fueHaDLW2GPQl4HWImUNsWxeM7xcF0JU-fFc3rQqPgE,12743
19
+ kerykeion/kr_types/settings_models.py,sha256=V4iEj7egXZHrWiV1cGQIezbtVmOKbOB-BRzPwa8WVtc,12683
20
20
  kerykeion/relationship_score.py,sha256=R9JugfK5_gJgr5ND-EghkqpqZcutzzKlJ-2JnYUMVv4,6794
21
21
  kerykeion/report.py,sha256=kS5avIN119pJVapYjZOvabg77nEcA8sSrOuXbRifABk,2565
22
22
  kerykeion/settings/__init__.py,sha256=QQNFCl7sgN27MKaVscqtpPk10HGz4wZS3I_7KEGMaVA,69
@@ -25,8 +25,8 @@ kerykeion/settings/kr.config.json,sha256=1Yhv9RGHom5U9e-JZZRWVfT2Ubllz2WrckdwadD
25
25
  kerykeion/sweph/README.md,sha256=L7FtNAJTWtrZNGKa8MX87SjduFYPYxwWhaI5fmtzNZo,73
26
26
  kerykeion/sweph/seas_18.se1,sha256=X9nCqhZU43wJpq61WAdueVQJt9xL2UjrwPqn1Kdoa1s,223002
27
27
  kerykeion/utilities.py,sha256=ncoXHvzXhNjhdm-uU6hMirVo287laq2GAJElNE6cBZM,10822
28
- kerykeion-4.6.2.dist-info/LICENSE,sha256=UTLH8EdbAsgQei4PA2PnBCPGLSZkq5J-dhkyJuXgWQU,34273
29
- kerykeion-4.6.2.dist-info/METADATA,sha256=hnPIiPxPtZE9OlhC3Us33D38-4g7-RA71eFeZpEATCU,10311
30
- kerykeion-4.6.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
31
- kerykeion-4.6.2.dist-info/entry_points.txt,sha256=5SmANYscFDDTdeovHvGQ-cnj0hdFvGoxPaWLCpyDFnQ,49
32
- kerykeion-4.6.2.dist-info/RECORD,,
28
+ kerykeion-4.7.0.dist-info/LICENSE,sha256=UTLH8EdbAsgQei4PA2PnBCPGLSZkq5J-dhkyJuXgWQU,34273
29
+ kerykeion-4.7.0.dist-info/METADATA,sha256=zb-U4K0Na0Gu84TVzUa2mcgksnvSCXFQjLBQ1gbKPRc,10311
30
+ kerykeion-4.7.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
31
+ kerykeion-4.7.0.dist-info/entry_points.txt,sha256=5SmANYscFDDTdeovHvGQ-cnj0hdFvGoxPaWLCpyDFnQ,49
32
+ kerykeion-4.7.0.dist-info/RECORD,,