kerykeion 5.1.8__py3-none-any.whl → 5.1.10__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/charts/chart_drawer.py +146 -10
- kerykeion/charts/templates/chart.xml +15 -15
- {kerykeion-5.1.8.dist-info → kerykeion-5.1.10.dist-info}/METADATA +1 -1
- {kerykeion-5.1.8.dist-info → kerykeion-5.1.10.dist-info}/RECORD +6 -6
- {kerykeion-5.1.8.dist-info → kerykeion-5.1.10.dist-info}/WHEEL +0 -0
- {kerykeion-5.1.8.dist-info → kerykeion-5.1.10.dist-info}/licenses/LICENSE +0 -0
kerykeion/charts/chart_drawer.py
CHANGED
|
@@ -10,7 +10,7 @@ from math import ceil
|
|
|
10
10
|
from datetime import datetime
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
from string import Template
|
|
13
|
-
from typing import Any, Mapping, Optional, Union, get_args
|
|
13
|
+
from typing import Any, Mapping, Optional, Sequence, Union, get_args
|
|
14
14
|
|
|
15
15
|
import swisseph as swe
|
|
16
16
|
from scour.scour import scourString
|
|
@@ -173,6 +173,10 @@ class ChartDrawer:
|
|
|
173
173
|
_DEFAULT_FULL_WIDTH_WITH_TABLE = 1250
|
|
174
174
|
_DEFAULT_ULTRA_WIDE_WIDTH = 1320
|
|
175
175
|
|
|
176
|
+
_VERTICAL_PADDING_TOP = 15
|
|
177
|
+
_VERTICAL_PADDING_BOTTOM = 15
|
|
178
|
+
_TITLE_SPACING = 8
|
|
179
|
+
|
|
176
180
|
_ASPECT_LIST_ASPECTS_PER_COLUMN = 14
|
|
177
181
|
_ASPECT_LIST_COLUMN_WIDTH = 105
|
|
178
182
|
|
|
@@ -608,6 +612,9 @@ class ChartDrawer:
|
|
|
608
612
|
|
|
609
613
|
delta_height = max(self.height - minimum_height, 0)
|
|
610
614
|
|
|
615
|
+
# Move title up for synastry charts
|
|
616
|
+
offsets["title"] = -10
|
|
617
|
+
|
|
611
618
|
offsets["wheel"] += delta_height
|
|
612
619
|
offsets["aspect_grid"] += delta_height
|
|
613
620
|
offsets["aspect_list"] += delta_height
|
|
@@ -664,8 +671,10 @@ class ChartDrawer:
|
|
|
664
671
|
return collected
|
|
665
672
|
|
|
666
673
|
def _dynamic_viewbox(self) -> str:
|
|
667
|
-
"""Return the viewBox string based on current width/height."""
|
|
668
|
-
|
|
674
|
+
"""Return the viewBox string based on current width/height with vertical padding."""
|
|
675
|
+
min_y = -self._VERTICAL_PADDING_TOP
|
|
676
|
+
viewbox_height = int(self.height) + self._VERTICAL_PADDING_TOP + self._VERTICAL_PADDING_BOTTOM
|
|
677
|
+
return f"0 {min_y} {int(self.width)} {viewbox_height}"
|
|
669
678
|
|
|
670
679
|
def _wheel_only_viewbox(self, margin: int = 20) -> str:
|
|
671
680
|
"""Return a tight viewBox for the wheel-only template.
|
|
@@ -770,18 +779,65 @@ class ChartDrawer:
|
|
|
770
779
|
# Secondary houses grid default x ~ 1015
|
|
771
780
|
secondary_houses_grid_right = 1015 + 120
|
|
772
781
|
extents.append(secondary_houses_grid_right)
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
782
|
+
if self.second_obj is not None:
|
|
783
|
+
point_column_label = self._translate("point", "Point")
|
|
784
|
+
first_subject_label = self._truncate_name(self.first_obj.name, 8, "…", True) # type: ignore[union-attr]
|
|
785
|
+
second_subject_label = self._truncate_name(self.second_obj.name, 8, "…", True) # type: ignore[union-attr]
|
|
786
|
+
|
|
787
|
+
first_columns = [
|
|
788
|
+
f"{first_subject_label} {point_column_label}",
|
|
789
|
+
first_subject_label,
|
|
790
|
+
second_subject_label,
|
|
791
|
+
]
|
|
792
|
+
second_columns = [
|
|
793
|
+
f"{second_subject_label} {point_column_label}",
|
|
794
|
+
second_subject_label,
|
|
795
|
+
first_subject_label,
|
|
796
|
+
]
|
|
797
|
+
|
|
798
|
+
first_grid_width = self._estimate_house_comparison_grid_width(
|
|
799
|
+
column_labels=first_columns,
|
|
800
|
+
include_radix_column=True,
|
|
801
|
+
include_title=True,
|
|
802
|
+
)
|
|
803
|
+
second_grid_width = self._estimate_house_comparison_grid_width(
|
|
804
|
+
column_labels=second_columns,
|
|
805
|
+
include_radix_column=True,
|
|
806
|
+
include_title=False,
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
first_house_comparison_grid_right = 1090 + first_grid_width
|
|
810
|
+
second_house_comparison_grid_right = 1290 + second_grid_width
|
|
811
|
+
extents.extend([first_house_comparison_grid_right, second_house_comparison_grid_right])
|
|
776
812
|
|
|
777
813
|
if self.chart_type == "Transit":
|
|
778
814
|
# House comparison grid at x ~ 1030
|
|
779
|
-
|
|
815
|
+
transit_columns = [
|
|
816
|
+
self._translate("transit_point", "Transit Point"),
|
|
817
|
+
self._translate("house_position", "Natal House"),
|
|
818
|
+
]
|
|
819
|
+
transit_grid_width = self._estimate_house_comparison_grid_width(
|
|
820
|
+
column_labels=transit_columns,
|
|
821
|
+
include_radix_column=False,
|
|
822
|
+
include_title=True,
|
|
823
|
+
minimum_width=170.0,
|
|
824
|
+
)
|
|
825
|
+
house_comparison_grid_right = 980 + transit_grid_width
|
|
780
826
|
extents.append(house_comparison_grid_right)
|
|
781
827
|
|
|
782
828
|
if self.chart_type == "DualReturnChart":
|
|
783
|
-
# House comparison grid
|
|
784
|
-
|
|
829
|
+
# House comparison grid translated to x ~ 1100
|
|
830
|
+
dual_return_columns = [
|
|
831
|
+
self._translate("return_point", "Return Point"),
|
|
832
|
+
self._translate("Return", "DualReturnChart"),
|
|
833
|
+
self._translate("Natal", "Natal"),
|
|
834
|
+
]
|
|
835
|
+
dual_return_grid_width = self._estimate_house_comparison_grid_width(
|
|
836
|
+
column_labels=dual_return_columns,
|
|
837
|
+
include_radix_column=True,
|
|
838
|
+
include_title=True,
|
|
839
|
+
)
|
|
840
|
+
house_comparison_grid_right = 1100 + dual_return_grid_width
|
|
785
841
|
extents.append(house_comparison_grid_right)
|
|
786
842
|
|
|
787
843
|
# Conservative safety padding
|
|
@@ -839,6 +895,86 @@ class ChartDrawer:
|
|
|
839
895
|
# imposed by the title area.
|
|
840
896
|
return max(per_column, min(allowed_capacity, max_capacity_by_top))
|
|
841
897
|
|
|
898
|
+
@staticmethod
|
|
899
|
+
def _estimate_text_width(text: str, font_size: int) -> float:
|
|
900
|
+
"""Very rough text width estimation in pixels based on font size."""
|
|
901
|
+
if not text:
|
|
902
|
+
return 0.0
|
|
903
|
+
average_char_width = float(font_size)
|
|
904
|
+
return max(float(font_size), len(text) * average_char_width)
|
|
905
|
+
|
|
906
|
+
def _get_active_point_display_names(self) -> list[str]:
|
|
907
|
+
"""Return localized labels for the currently active celestial points."""
|
|
908
|
+
language_map = {}
|
|
909
|
+
fallback_map = {}
|
|
910
|
+
|
|
911
|
+
if hasattr(self, "_language_model"):
|
|
912
|
+
language_map = self._language_model.celestial_points.model_dump()
|
|
913
|
+
if hasattr(self, "_fallback_language_model"):
|
|
914
|
+
fallback_map = self._fallback_language_model.celestial_points.model_dump()
|
|
915
|
+
|
|
916
|
+
display_names: list[str] = []
|
|
917
|
+
for point in self.active_points:
|
|
918
|
+
key = str(point)
|
|
919
|
+
label = language_map.get(key) or fallback_map.get(key) or key
|
|
920
|
+
display_names.append(str(label))
|
|
921
|
+
return display_names
|
|
922
|
+
|
|
923
|
+
def _estimate_house_comparison_grid_width(
|
|
924
|
+
self,
|
|
925
|
+
*,
|
|
926
|
+
column_labels: Sequence[str],
|
|
927
|
+
include_radix_column: bool,
|
|
928
|
+
include_title: bool,
|
|
929
|
+
minimum_width: float = 250.0,
|
|
930
|
+
) -> int:
|
|
931
|
+
"""
|
|
932
|
+
Approximate the rendered width for a house comparison grid in the current locale.
|
|
933
|
+
|
|
934
|
+
Args:
|
|
935
|
+
column_labels: Ordered labels for the header row.
|
|
936
|
+
include_radix_column: Whether a third numeric column is rendered.
|
|
937
|
+
include_title: Include the localized title in the width estimation.
|
|
938
|
+
minimum_width: Absolute lower bound to prevent extreme shrinking.
|
|
939
|
+
"""
|
|
940
|
+
font_size_body = 10
|
|
941
|
+
font_size_title = 14
|
|
942
|
+
minimum_grid_width = float(minimum_width)
|
|
943
|
+
|
|
944
|
+
active_names = self._get_active_point_display_names()
|
|
945
|
+
max_name_width = max(
|
|
946
|
+
(self._estimate_text_width(name, font_size_body) for name in active_names),
|
|
947
|
+
default=self._estimate_text_width("Sun", font_size_body),
|
|
948
|
+
)
|
|
949
|
+
width_candidates: list[float] = []
|
|
950
|
+
|
|
951
|
+
name_start = 15
|
|
952
|
+
width_candidates.append(name_start + max_name_width)
|
|
953
|
+
|
|
954
|
+
value_offsets = [90]
|
|
955
|
+
if include_radix_column:
|
|
956
|
+
value_offsets.append(140)
|
|
957
|
+
value_samples = ("12", "-", "0")
|
|
958
|
+
max_value_width = max((self._estimate_text_width(sample, font_size_body) for sample in value_samples))
|
|
959
|
+
for offset in value_offsets:
|
|
960
|
+
width_candidates.append(offset + max_value_width)
|
|
961
|
+
|
|
962
|
+
header_offsets = [0, 77]
|
|
963
|
+
if include_radix_column:
|
|
964
|
+
header_offsets.append(132)
|
|
965
|
+
for idx, offset in enumerate(header_offsets):
|
|
966
|
+
label = column_labels[idx] if idx < len(column_labels) else ""
|
|
967
|
+
if not label:
|
|
968
|
+
continue
|
|
969
|
+
width_candidates.append(offset + self._estimate_text_width(label, font_size_body))
|
|
970
|
+
|
|
971
|
+
if include_title:
|
|
972
|
+
title_label = self._translate("house_position_comparison", "House Position Comparison")
|
|
973
|
+
width_candidates.append(self._estimate_text_width(title_label, font_size_title))
|
|
974
|
+
|
|
975
|
+
grid_width = max(width_candidates, default=minimum_grid_width)
|
|
976
|
+
return int(max(grid_width, minimum_grid_width))
|
|
977
|
+
|
|
842
978
|
def _minimum_width_for_chart_type(self) -> int:
|
|
843
979
|
"""Baseline width to avoid compressing core groups too tightly."""
|
|
844
980
|
wheel_right = 100 + (2 * self.main_radius)
|
|
@@ -851,7 +987,7 @@ class ChartDrawer:
|
|
|
851
987
|
if self.chart_type == "DualReturnChart":
|
|
852
988
|
return max(int(baseline), self._DEFAULT_ULTRA_WIDE_WIDTH // 2)
|
|
853
989
|
if self.chart_type == "Transit":
|
|
854
|
-
return max(int(baseline),
|
|
990
|
+
return max(int(baseline), 450)
|
|
855
991
|
return max(int(baseline), self._DEFAULT_NATAL_WIDTH)
|
|
856
992
|
|
|
857
993
|
def _update_width_to_content(self) -> None:
|
|
@@ -21,41 +21,41 @@
|
|
|
21
21
|
<g kr:node="Main_Chart">
|
|
22
22
|
<g kr:node="Top_Left_Text" transform="translate(0,$title_translate_y)">
|
|
23
23
|
<text x="20" y="22" style="fill: $paper_color_0; font-size: 24px">$stringTitle</text>
|
|
24
|
-
<text x="20" y="
|
|
25
|
-
<text x="20" y="
|
|
26
|
-
<text x="20" y="
|
|
27
|
-
<text x="20" y="
|
|
28
|
-
<text x="20" y="
|
|
29
|
-
<text x="20" y="
|
|
24
|
+
<text x="20" y="58" style="fill: $paper_color_0; font-size: 10px">$top_left_0</text>
|
|
25
|
+
<text x="20" y="70" style="fill: $paper_color_0; font-size: 10px">$top_left_1</text>
|
|
26
|
+
<text x="20" y="82" style="fill: $paper_color_0; font-size: 10px">$top_left_2</text>
|
|
27
|
+
<text x="20" y="94" style="fill: $paper_color_0; font-size: 10px">$top_left_3</text>
|
|
28
|
+
<text x="20" y="106" style="fill: $paper_color_0; font-size: 10px">$top_left_4</text>
|
|
29
|
+
<text x="20" y="118" style="fill: $paper_color_0; font-size: 10px">$top_left_5</text>
|
|
30
30
|
</g>
|
|
31
31
|
|
|
32
32
|
<!-- Elements -->
|
|
33
33
|
<g kr:node="Elements_Percentages" transform="translate(0,$elements_translate_y)">
|
|
34
|
-
<text x="20" y="
|
|
35
|
-
<text x="20" y="
|
|
34
|
+
<text x="20" y="138" style="fill: $paper_color_0; font-size: 10px;">$elements_string</text>
|
|
35
|
+
<text x="20" y="152"
|
|
36
36
|
style="fill: var(--kerykeion-chart-color-fire-percentage); font-size: 10px;">
|
|
37
37
|
$fire_string</text>
|
|
38
|
-
<text x="20" y="
|
|
38
|
+
<text x="20" y="164"
|
|
39
39
|
style="fill: var(--kerykeion-chart-color-earth-percentage); font-size: 10px;">
|
|
40
40
|
$earth_string</text>
|
|
41
|
-
<text x="20" y="
|
|
41
|
+
<text x="20" y="176"
|
|
42
42
|
style="fill: var(--kerykeion-chart-color-air-percentage); font-size: 10px;">
|
|
43
43
|
$air_string</text>
|
|
44
|
-
<text x="20" y="
|
|
44
|
+
<text x="20" y="188"
|
|
45
45
|
style="fill: var(--kerykeion-chart-color-water-percentage); font-size: 10px;">
|
|
46
46
|
$water_string</text>
|
|
47
47
|
</g>
|
|
48
48
|
|
|
49
49
|
<!-- Qualities -->
|
|
50
50
|
<g kr:node="Qualities_Percentages" transform="translate(0,$qualities_translate_y)">
|
|
51
|
-
<text x="20" y="
|
|
52
|
-
<text x="20" y="
|
|
51
|
+
<text x="20" y="208" style="fill: $paper_color_0; font-size: 10px;">$qualities_string</text>
|
|
52
|
+
<text x="20" y="222"
|
|
53
53
|
style="fill: var(--kerykeion-chart-color-cardinal-percentage); font-size: 10px;">
|
|
54
54
|
$cardinal_string</text>
|
|
55
|
-
<text x="20" y="
|
|
55
|
+
<text x="20" y="234"
|
|
56
56
|
style="fill: var(--kerykeion-chart-color-fixed-percentage); font-size: 10px;">
|
|
57
57
|
$fixed_string</text>
|
|
58
|
-
<text x="20" y="
|
|
58
|
+
<text x="20" y="246"
|
|
59
59
|
style="fill: var(--kerykeion-chart-color-mutable-percentage); font-size: 10px;">
|
|
60
60
|
$mutable_string</text>
|
|
61
61
|
</g>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kerykeion
|
|
3
|
-
Version: 5.1.
|
|
3
|
+
Version: 5.1.10
|
|
4
4
|
Summary: A Python library for astrological calculations, including natal charts, houses, planetary aspects, and SVG chart generation.
|
|
5
5
|
Project-URL: Homepage, https://www.kerykeion.net/
|
|
6
6
|
Project-URL: Repository, https://github.com/g-battaglia/kerykeion
|
|
@@ -14,11 +14,11 @@ kerykeion/aspects/__init__.py,sha256=csJmxvLdBu-bHuW676f3dpY__Qyc6LwRyrpWVTh3n1A
|
|
|
14
14
|
kerykeion/aspects/aspects_factory.py,sha256=XCuOOpo0ZW7sihYT2f50bLVpebEk19b9EtEjXonwte0,24156
|
|
15
15
|
kerykeion/aspects/aspects_utils.py,sha256=2YloOKOmN0h2d6J8A1vCe-y4A2mWNoOUYCGDVwGl4gA,5794
|
|
16
16
|
kerykeion/charts/__init__.py,sha256=i9NMZ7LdkllPlqQSi1or9gTobHbROGDKmJhBDO4R0mA,128
|
|
17
|
-
kerykeion/charts/chart_drawer.py,sha256=
|
|
17
|
+
kerykeion/charts/chart_drawer.py,sha256=AQGtJsUWRm_D-RH1w1Q9GRD6cRtgmjDQN1e-UMOtO3Y,130645
|
|
18
18
|
kerykeion/charts/charts_utils.py,sha256=iwgDhVc_GwKuQBZ6JNmn6RWVILD5KIcjbrnDTR3wrAc,70911
|
|
19
19
|
kerykeion/charts/draw_planets.py,sha256=tIj3FeLLomVSbCaZUxfw_qBEB3pxi4EIEhqaeTgTyTY,29061
|
|
20
20
|
kerykeion/charts/templates/aspect_grid_only.xml,sha256=v3QtNMjk-kBdUTfB0r6thg--Ta_tNFdRQCzdk5PAycY,86429
|
|
21
|
-
kerykeion/charts/templates/chart.xml,sha256=
|
|
21
|
+
kerykeion/charts/templates/chart.xml,sha256=QhCSkORLw61cXycF2fMmCLsSailPyIxLbVtsR-CXsKI,92096
|
|
22
22
|
kerykeion/charts/templates/wheel_only.xml,sha256=05k2KiVMP-5NW0e8PZrTX-VPn5x-SaNzEYPgU1_OKa0,87775
|
|
23
23
|
kerykeion/charts/themes/black-and-white.css,sha256=IIoy9wyB4znrvPvmallKmgDW4HMJPywTv5IZsolaEp4,6543
|
|
24
24
|
kerykeion/charts/themes/classic.css,sha256=xvBiI4DtY5fMaA7ilxGl26VEDY1VzkOTWm1XOs9n-ec,5158
|
|
@@ -57,7 +57,7 @@ kerykeion/sweph/ast28/se28978s.se1,sha256=nU2Qp-ELc_tzFnRc1QT6uVueWXEipvhYDgfQRX
|
|
|
57
57
|
kerykeion/sweph/ast50/se50000s.se1,sha256=9jTrPlIrZMOBWC9cNgwzcfz0KBHdXFZoY9-NZ_HtECo,15748
|
|
58
58
|
kerykeion/sweph/ast90/se90377s.se1,sha256=bto2x4LtBv8b1ej1XhVFYq-kfHO9cczbKV9U1f9UVu4,10288
|
|
59
59
|
kerykeion/sweph/ast90/se90482s.se1,sha256=uHxz6bP4K8zgtQFrlWFwxrYfmqm5kXxsg6OYhAIUbAA,16173
|
|
60
|
-
kerykeion-5.1.
|
|
61
|
-
kerykeion-5.1.
|
|
62
|
-
kerykeion-5.1.
|
|
63
|
-
kerykeion-5.1.
|
|
60
|
+
kerykeion-5.1.10.dist-info/METADATA,sha256=KMaQJSdjbOrF-W6uowiZUDoN-WHDAMy3oCH7PO3kS1I,61803
|
|
61
|
+
kerykeion-5.1.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
62
|
+
kerykeion-5.1.10.dist-info/licenses/LICENSE,sha256=UTLH8EdbAsgQei4PA2PnBCPGLSZkq5J-dhkyJuXgWQU,34273
|
|
63
|
+
kerykeion-5.1.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|