kerykeion 4.12.3__py3-none-any.whl → 4.18.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kerykeion might be problematic. Click here for more details.
- kerykeion/__init__.py +3 -1
- kerykeion/aspects/aspects_utils.py +40 -123
- kerykeion/aspects/natal_aspects.py +34 -25
- kerykeion/aspects/synastry_aspects.py +34 -28
- kerykeion/astrological_subject.py +199 -196
- kerykeion/charts/charts_utils.py +701 -62
- kerykeion/charts/draw_planets.py +407 -0
- kerykeion/charts/kerykeion_chart_svg.py +534 -1140
- kerykeion/charts/templates/aspect_grid_only.xml +452 -0
- kerykeion/charts/templates/chart.xml +88 -70
- kerykeion/charts/templates/wheel_only.xml +499 -0
- kerykeion/charts/themes/classic.css +82 -0
- kerykeion/charts/themes/dark-high-contrast.css +121 -0
- kerykeion/charts/themes/dark.css +121 -0
- kerykeion/charts/themes/light.css +117 -0
- kerykeion/enums.py +1 -0
- kerykeion/ephemeris_data.py +178 -0
- kerykeion/fetch_geonames.py +2 -3
- kerykeion/kr_types/chart_types.py +6 -16
- kerykeion/kr_types/kr_literals.py +12 -3
- kerykeion/kr_types/kr_models.py +77 -32
- kerykeion/kr_types/settings_models.py +4 -10
- kerykeion/relationship_score/__init__.py +2 -0
- kerykeion/relationship_score/relationship_score.py +175 -0
- kerykeion/relationship_score/relationship_score_factory.py +275 -0
- kerykeion/report.py +6 -3
- kerykeion/settings/kerykeion_settings.py +6 -1
- kerykeion/settings/kr.config.json +256 -102
- kerykeion/utilities.py +122 -217
- {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/METADATA +40 -10
- kerykeion-4.18.0.dist-info/RECORD +42 -0
- kerykeion/relationship_score.py +0 -205
- kerykeion-4.12.3.dist-info/RECORD +0 -32
- {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/LICENSE +0 -0
- {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/WHEEL +0 -0
- {kerykeion-4.12.3.dist-info → kerykeion-4.18.0.dist-info}/entry_points.txt +0 -0
kerykeion/__init__.py
CHANGED
|
@@ -9,8 +9,10 @@ This is part of Kerykeion (C) 2024 Giacomo Battaglia
|
|
|
9
9
|
from .astrological_subject import AstrologicalSubject
|
|
10
10
|
from .charts.kerykeion_chart_svg import KerykeionChartSVG
|
|
11
11
|
from .kr_types import *
|
|
12
|
-
from .relationship_score import RelationshipScore
|
|
12
|
+
from .relationship_score.relationship_score import RelationshipScore
|
|
13
|
+
from .relationship_score.relationship_score_factory import RelationshipScoreFactory
|
|
13
14
|
from .aspects import SynastryAspects, NatalAspects
|
|
14
15
|
from .report import Report
|
|
15
16
|
from .settings import KerykeionSettingsModel, get_settings
|
|
16
17
|
from .enums import Planets, Aspects, Signs
|
|
18
|
+
from .ephemeris_data import EphemerisDataFactory
|
|
@@ -8,143 +8,56 @@ from kerykeion import AstrologicalSubject
|
|
|
8
8
|
from kerykeion.settings import KerykeionSettingsModel
|
|
9
9
|
from swisseph import difdeg2n
|
|
10
10
|
from typing import Union
|
|
11
|
+
from kerykeion.kr_types.kr_models import AstrologicalSubjectModel
|
|
12
|
+
from kerykeion.kr_types.settings_models import KerykeionSettingsCelestialPointModel, KerykeionSettingsAspectModel
|
|
11
13
|
|
|
12
14
|
|
|
13
|
-
def get_aspect_from_two_points(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
def get_aspect_from_two_points(
|
|
16
|
+
aspects_settings: Union[list[KerykeionSettingsAspectModel], list[dict]],
|
|
17
|
+
point_one: Union[float, int],
|
|
18
|
+
point_two: Union[float, int],
|
|
19
|
+
):
|
|
18
20
|
"""
|
|
21
|
+
Utility function to calculate the aspects between two points.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
aspects_settings (dict): Dictionary containing aspect settings.
|
|
25
|
+
point_one (Union[float, int]): First point.
|
|
26
|
+
point_two (Union[float, int]): Second point.
|
|
19
27
|
|
|
28
|
+
Returns:
|
|
29
|
+
dict: Dictionary containing the aspect details.
|
|
30
|
+
"""
|
|
20
31
|
distance = abs(difdeg2n(point_one, point_two))
|
|
21
32
|
diff = abs(point_one - point_two)
|
|
22
33
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
verdict = True
|
|
27
|
-
aid = 0
|
|
28
|
-
|
|
29
|
-
elif (
|
|
30
|
-
(aspects_settings[1]["degree"] - aspects_settings[1]["orb"])
|
|
31
|
-
<= int(distance)
|
|
32
|
-
<= (aspects_settings[1]["degree"] + aspects_settings[1]["orb"])
|
|
33
|
-
):
|
|
34
|
-
name = aspects_settings[1]["name"]
|
|
35
|
-
aspect_degrees = aspects_settings[1]["degree"]
|
|
36
|
-
verdict = True
|
|
37
|
-
aid = 1
|
|
38
|
-
|
|
39
|
-
elif (
|
|
40
|
-
(aspects_settings[2]["degree"] - aspects_settings[2]["orb"])
|
|
41
|
-
<= int(distance)
|
|
42
|
-
<= (aspects_settings[2]["degree"] + aspects_settings[2]["orb"])
|
|
43
|
-
):
|
|
44
|
-
name = aspects_settings[2]["name"]
|
|
45
|
-
aspect_degrees = aspects_settings[2]["degree"]
|
|
46
|
-
verdict = True
|
|
47
|
-
aid = 2
|
|
48
|
-
|
|
49
|
-
elif (
|
|
50
|
-
(aspects_settings[3]["degree"] - aspects_settings[3]["orb"])
|
|
51
|
-
<= int(distance)
|
|
52
|
-
<= (aspects_settings[3]["degree"] + aspects_settings[3]["orb"])
|
|
53
|
-
):
|
|
54
|
-
name = aspects_settings[3]["name"]
|
|
55
|
-
aspect_degrees = aspects_settings[3]["degree"]
|
|
56
|
-
verdict = True
|
|
57
|
-
aid = 3
|
|
58
|
-
|
|
59
|
-
elif (
|
|
60
|
-
(aspects_settings[4]["degree"] - aspects_settings[4]["orb"])
|
|
61
|
-
<= int(distance)
|
|
62
|
-
<= (aspects_settings[4]["degree"] + aspects_settings[4]["orb"])
|
|
63
|
-
):
|
|
64
|
-
name = aspects_settings[4]["name"]
|
|
65
|
-
aspect_degrees = aspects_settings[4]["degree"]
|
|
66
|
-
verdict = True
|
|
67
|
-
aid = 4
|
|
68
|
-
|
|
69
|
-
elif (
|
|
70
|
-
(aspects_settings[5]["degree"] - aspects_settings[5]["orb"])
|
|
71
|
-
<= int(distance)
|
|
72
|
-
<= (aspects_settings[5]["degree"] + aspects_settings[5]["orb"])
|
|
73
|
-
):
|
|
74
|
-
name = aspects_settings[5]["name"]
|
|
75
|
-
aspect_degrees = aspects_settings[5]["degree"]
|
|
76
|
-
verdict = True
|
|
77
|
-
aid = 5
|
|
78
|
-
|
|
79
|
-
elif (
|
|
80
|
-
(aspects_settings[6]["degree"] - aspects_settings[6]["orb"])
|
|
81
|
-
<= int(distance)
|
|
82
|
-
<= (aspects_settings[6]["degree"] + aspects_settings[6]["orb"])
|
|
83
|
-
):
|
|
84
|
-
name = aspects_settings[6]["name"]
|
|
85
|
-
aspect_degrees = aspects_settings[6]["degree"]
|
|
86
|
-
verdict = True
|
|
87
|
-
aid = 6
|
|
88
|
-
|
|
89
|
-
elif (
|
|
90
|
-
(aspects_settings[7]["degree"] - aspects_settings[7]["orb"])
|
|
91
|
-
<= int(distance)
|
|
92
|
-
<= (aspects_settings[7]["degree"] + aspects_settings[7]["orb"])
|
|
93
|
-
):
|
|
94
|
-
name = aspects_settings[7]["name"]
|
|
95
|
-
aspect_degrees = aspects_settings[7]["degree"]
|
|
96
|
-
verdict = True
|
|
97
|
-
aid = 7
|
|
98
|
-
|
|
99
|
-
elif (
|
|
100
|
-
(aspects_settings[8]["degree"] - aspects_settings[8]["orb"])
|
|
101
|
-
<= int(distance)
|
|
102
|
-
<= (aspects_settings[8]["degree"] + aspects_settings[8]["orb"])
|
|
103
|
-
):
|
|
104
|
-
name = aspects_settings[8]["name"]
|
|
105
|
-
aspect_degrees = aspects_settings[8]["degree"]
|
|
106
|
-
verdict = True
|
|
107
|
-
aid = 8
|
|
108
|
-
|
|
109
|
-
elif (
|
|
110
|
-
(aspects_settings[9]["degree"] - aspects_settings[9]["orb"])
|
|
111
|
-
<= int(distance)
|
|
112
|
-
<= (aspects_settings[9]["degree"] + aspects_settings[9]["orb"])
|
|
113
|
-
):
|
|
114
|
-
name = aspects_settings[9]["name"]
|
|
115
|
-
aspect_degrees = aspects_settings[9]["degree"]
|
|
116
|
-
verdict = True
|
|
117
|
-
aid = 9
|
|
118
|
-
|
|
119
|
-
elif (
|
|
120
|
-
(aspects_settings[10]["degree"] - aspects_settings[10]["orb"])
|
|
121
|
-
<= int(distance)
|
|
122
|
-
<= (aspects_settings[10]["degree"] + aspects_settings[10]["orb"])
|
|
123
|
-
):
|
|
124
|
-
name = aspects_settings[10]["name"]
|
|
125
|
-
aspect_degrees = aspects_settings[10]["degree"]
|
|
126
|
-
verdict = True
|
|
127
|
-
aid = 10
|
|
34
|
+
for aid, aspect in enumerate(aspects_settings):
|
|
35
|
+
aspect_degree = aspect["degree"] # type: ignore
|
|
36
|
+
aspect_orb = aspect["orb"] # type: ignore
|
|
128
37
|
|
|
38
|
+
if (aspect_degree - aspect_orb) <= int(distance) <= (aspect_degree + aspect_orb):
|
|
39
|
+
name = aspect["name"] # type: ignore
|
|
40
|
+
aspect_degrees = aspect_degree
|
|
41
|
+
verdict = True
|
|
42
|
+
break
|
|
129
43
|
else:
|
|
130
44
|
verdict = False
|
|
131
45
|
name = None
|
|
132
|
-
distance = 0
|
|
133
46
|
aspect_degrees = 0
|
|
134
|
-
|
|
135
|
-
aid = None
|
|
47
|
+
aid = None # type: ignore
|
|
136
48
|
|
|
137
|
-
return
|
|
138
|
-
verdict,
|
|
139
|
-
name,
|
|
140
|
-
distance - aspect_degrees,
|
|
141
|
-
aspect_degrees,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
49
|
+
return {
|
|
50
|
+
"verdict": verdict,
|
|
51
|
+
"name": name,
|
|
52
|
+
"orbit": distance - aspect_degrees,
|
|
53
|
+
"distance": distance - aspect_degrees,
|
|
54
|
+
"aspect_degrees": aspect_degrees,
|
|
55
|
+
"aid": aid,
|
|
56
|
+
"diff": diff,
|
|
57
|
+
}
|
|
145
58
|
|
|
146
59
|
|
|
147
|
-
def planet_id_decoder(planets_settings:
|
|
60
|
+
def planet_id_decoder(planets_settings: list[KerykeionSettingsCelestialPointModel], name: str) -> int:
|
|
148
61
|
"""
|
|
149
62
|
Check if the name of the planet is the same in the settings and return
|
|
150
63
|
the correct id for the planet.
|
|
@@ -155,8 +68,12 @@ def planet_id_decoder(planets_settings: dict, name: str):
|
|
|
155
68
|
result = planet["id"]
|
|
156
69
|
return result
|
|
157
70
|
|
|
71
|
+
raise ValueError(f"Planet {name} not found in the settings")
|
|
72
|
+
|
|
158
73
|
|
|
159
|
-
def get_active_points_list(
|
|
74
|
+
def get_active_points_list(
|
|
75
|
+
subject: Union[AstrologicalSubject, AstrologicalSubjectModel], settings: Union[KerykeionSettingsModel, dict]
|
|
76
|
+
) -> list:
|
|
160
77
|
"""
|
|
161
78
|
Given an astrological subject and the settings, return a list of the active points.
|
|
162
79
|
Args:
|
|
@@ -11,6 +11,8 @@ from kerykeion.settings.kerykeion_settings import get_settings
|
|
|
11
11
|
from dataclasses import dataclass
|
|
12
12
|
from functools import cached_property
|
|
13
13
|
from kerykeion.aspects.aspects_utils import planet_id_decoder, get_aspect_from_two_points, get_active_points_list
|
|
14
|
+
from kerykeion.kr_types.kr_models import AstrologicalSubjectModel, AspectModel
|
|
15
|
+
from kerykeion.kr_types.settings_models import KerykeionSettingsModel
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
AXES_LIST = [
|
|
@@ -27,15 +29,15 @@ class NatalAspects:
|
|
|
27
29
|
Generates an object with all the aspects of a birthcart.
|
|
28
30
|
"""
|
|
29
31
|
|
|
30
|
-
user: AstrologicalSubject
|
|
31
|
-
new_settings_file: Union[Path, None] = None
|
|
32
|
+
user: Union[AstrologicalSubject, AstrologicalSubjectModel]
|
|
33
|
+
new_settings_file: Union[Path, KerykeionSettingsModel, dict, None] = None
|
|
32
34
|
|
|
33
35
|
def __post_init__(self):
|
|
34
36
|
self.settings = get_settings(self.new_settings_file)
|
|
35
37
|
|
|
36
|
-
self.celestial_points = self.settings
|
|
37
|
-
self.aspects_settings = self.settings
|
|
38
|
-
self.axes_orbit_settings = self.settings
|
|
38
|
+
self.celestial_points = self.settings.celestial_points
|
|
39
|
+
self.aspects_settings = self.settings.aspects
|
|
40
|
+
self.axes_orbit_settings = self.settings.general_settings.axes_orbit
|
|
39
41
|
|
|
40
42
|
@cached_property
|
|
41
43
|
def all_aspects(self):
|
|
@@ -52,29 +54,34 @@ class NatalAspects:
|
|
|
52
54
|
for first in range(len(active_points_list)):
|
|
53
55
|
# Generates the aspects list without repetitions
|
|
54
56
|
for second in range(first + 1, len(active_points_list)):
|
|
55
|
-
|
|
56
|
-
self.aspects_settings, active_points_list[first]["abs_pos"],
|
|
57
|
+
aspect = get_aspect_from_two_points(
|
|
58
|
+
self.aspects_settings, active_points_list[first]["abs_pos"],
|
|
59
|
+
active_points_list[second]["abs_pos"]
|
|
57
60
|
)
|
|
58
61
|
|
|
62
|
+
verdict = aspect["verdict"]
|
|
63
|
+
name = aspect["name"]
|
|
64
|
+
orbit = aspect["orbit"]
|
|
65
|
+
aspect_degrees = aspect["aspect_degrees"]
|
|
66
|
+
aid = aspect["aid"]
|
|
67
|
+
diff = aspect["diff"]
|
|
68
|
+
|
|
59
69
|
if verdict == True:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
self.all_aspects_list.append(d_asp)
|
|
70
|
+
aspect_model = AspectModel(
|
|
71
|
+
p1_name=active_points_list[first]["name"],
|
|
72
|
+
p1_abs_pos=active_points_list[first]["abs_pos"],
|
|
73
|
+
p2_name=active_points_list[second]["name"],
|
|
74
|
+
p2_abs_pos=active_points_list[second]["abs_pos"],
|
|
75
|
+
aspect=name,
|
|
76
|
+
orbit=orbit,
|
|
77
|
+
aspect_degrees=aspect_degrees,
|
|
78
|
+
aid=aid,
|
|
79
|
+
diff=diff,
|
|
80
|
+
p1=planet_id_decoder(self.celestial_points, active_points_list[first]["name"]),
|
|
81
|
+
p2=planet_id_decoder(self.celestial_points, active_points_list[second]["name"]),
|
|
82
|
+
is_major=self.aspects_settings[aid]["is_major"],
|
|
83
|
+
)
|
|
84
|
+
self.all_aspects_list.append(aspect_model)
|
|
78
85
|
|
|
79
86
|
return self.all_aspects_list
|
|
80
87
|
|
|
@@ -85,6 +92,7 @@ class NatalAspects:
|
|
|
85
92
|
the most important are hardcoded.
|
|
86
93
|
Set the list with set_points and creating a list with the names
|
|
87
94
|
or the numbers of the houses.
|
|
95
|
+
The relevant aspects are the ones that are set as active ("is_active") in the settings.
|
|
88
96
|
"""
|
|
89
97
|
|
|
90
98
|
logging.debug("Relevant aspects not already calculated, calculating now...")
|
|
@@ -119,6 +127,7 @@ class NatalAspects:
|
|
|
119
127
|
|
|
120
128
|
if __name__ == "__main__":
|
|
121
129
|
from kerykeion.utilities import setup_logging
|
|
130
|
+
|
|
122
131
|
setup_logging(level="debug")
|
|
123
132
|
|
|
124
133
|
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US")
|
|
@@ -11,6 +11,9 @@ from functools import cached_property
|
|
|
11
11
|
from kerykeion.aspects.natal_aspects import NatalAspects
|
|
12
12
|
from kerykeion.settings.kerykeion_settings import get_settings
|
|
13
13
|
from kerykeion.aspects.aspects_utils import planet_id_decoder, get_aspect_from_two_points, get_active_points_list
|
|
14
|
+
from kerykeion.kr_types.kr_models import AstrologicalSubjectModel, AspectModel
|
|
15
|
+
from kerykeion.kr_types.settings_models import KerykeionSettingsModel
|
|
16
|
+
from typing import Union
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
class SynastryAspects(NatalAspects):
|
|
@@ -20,9 +23,9 @@ class SynastryAspects(NatalAspects):
|
|
|
20
23
|
|
|
21
24
|
def __init__(
|
|
22
25
|
self,
|
|
23
|
-
kr_object_one: AstrologicalSubject,
|
|
24
|
-
kr_object_two: AstrologicalSubject,
|
|
25
|
-
new_settings_file: Union[Path, None] = None,
|
|
26
|
+
kr_object_one: Union[AstrologicalSubject, AstrologicalSubjectModel],
|
|
27
|
+
kr_object_two: Union[AstrologicalSubject, AstrologicalSubjectModel],
|
|
28
|
+
new_settings_file: Union[Path, KerykeionSettingsModel, dict, None] = None,
|
|
26
29
|
):
|
|
27
30
|
# Subjects
|
|
28
31
|
self.first_user = kr_object_one
|
|
@@ -32,9 +35,9 @@ class SynastryAspects(NatalAspects):
|
|
|
32
35
|
self.new_settings_file = new_settings_file
|
|
33
36
|
self.settings = get_settings(self.new_settings_file)
|
|
34
37
|
|
|
35
|
-
self.celestial_points = self.settings
|
|
36
|
-
self.aspects_settings = self.settings
|
|
37
|
-
self.axes_orbit_settings = self.settings
|
|
38
|
+
self.celestial_points = self.settings.celestial_points
|
|
39
|
+
self.aspects_settings = self.settings.aspects
|
|
40
|
+
self.axes_orbit_settings = self.settings.general_settings.axes_orbit
|
|
38
41
|
|
|
39
42
|
# Private variables of the aspects
|
|
40
43
|
self._all_aspects: Union[list, None] = None
|
|
@@ -60,43 +63,46 @@ class SynastryAspects(NatalAspects):
|
|
|
60
63
|
for first in range(len(first_active_points_list)):
|
|
61
64
|
# Generates the aspects list whitout repetitions
|
|
62
65
|
for second in range(len(second_active_points_list)):
|
|
63
|
-
|
|
66
|
+
aspect = get_aspect_from_two_points(
|
|
64
67
|
self.aspects_settings,
|
|
65
68
|
first_active_points_list[first]["abs_pos"],
|
|
66
69
|
second_active_points_list[second]["abs_pos"],
|
|
67
70
|
)
|
|
68
71
|
|
|
72
|
+
verdict = aspect["verdict"]
|
|
73
|
+
name = aspect["name"]
|
|
74
|
+
orbit = aspect["orbit"]
|
|
75
|
+
aspect_degrees = aspect["aspect_degrees"]
|
|
76
|
+
aid = aspect["aid"]
|
|
77
|
+
diff = aspect["diff"]
|
|
78
|
+
|
|
69
79
|
if verdict == True:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
second_active_points_list[second]["name"],
|
|
86
|
-
),
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
self.all_aspects_list.append(d_asp)
|
|
80
|
+
aspect_model = AspectModel(
|
|
81
|
+
p1_name=first_active_points_list[first]["name"],
|
|
82
|
+
p1_abs_pos=first_active_points_list[first]["abs_pos"],
|
|
83
|
+
p2_name=second_active_points_list[second]["name"],
|
|
84
|
+
p2_abs_pos=second_active_points_list[second]["abs_pos"],
|
|
85
|
+
aspect=name,
|
|
86
|
+
orbit=orbit,
|
|
87
|
+
aspect_degrees=aspect_degrees,
|
|
88
|
+
aid=aid,
|
|
89
|
+
diff=diff,
|
|
90
|
+
p1=planet_id_decoder(self.celestial_points, first_active_points_list[first]["name"]),
|
|
91
|
+
p2=planet_id_decoder(self.celestial_points, second_active_points_list[second]["name"]),
|
|
92
|
+
is_major=self.aspects_settings[aid]["is_major"],
|
|
93
|
+
)
|
|
94
|
+
self.all_aspects_list.append(aspect_model)
|
|
90
95
|
|
|
91
96
|
return self.all_aspects_list
|
|
92
97
|
|
|
93
98
|
|
|
94
99
|
if __name__ == "__main__":
|
|
95
100
|
from kerykeion.utilities import setup_logging
|
|
101
|
+
|
|
96
102
|
setup_logging(level="debug")
|
|
97
103
|
|
|
98
104
|
john = AstrologicalSubject("John", 1940, 10, 9, 18, 30, "Liverpool")
|
|
99
|
-
yoko = AstrologicalSubject("Yoko", 1933, 2, 18, 18, 30, "Tokyo")
|
|
105
|
+
yoko = AstrologicalSubject("Yoko", 1933, 2, 18, 18, 30, "Tokyo", "JP")
|
|
100
106
|
|
|
101
107
|
synastry_aspects = SynastryAspects(john, yoko)
|
|
102
108
|
|