kerykeion 4.18.3__py3-none-any.whl → 5.1.9__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 +56 -11
- kerykeion/aspects/__init__.py +7 -4
- kerykeion/aspects/aspects_factory.py +568 -0
- kerykeion/aspects/aspects_utils.py +86 -13
- kerykeion/astrological_subject_factory.py +1901 -0
- kerykeion/backword.py +820 -0
- kerykeion/chart_data_factory.py +552 -0
- kerykeion/charts/__init__.py +2 -2
- kerykeion/charts/chart_drawer.py +2794 -0
- kerykeion/charts/charts_utils.py +1066 -309
- kerykeion/charts/draw_planets.py +602 -351
- kerykeion/charts/templates/aspect_grid_only.xml +337 -193
- kerykeion/charts/templates/chart.xml +441 -240
- kerykeion/charts/templates/wheel_only.xml +365 -211
- kerykeion/charts/themes/black-and-white.css +148 -0
- kerykeion/charts/themes/classic.css +107 -76
- kerykeion/charts/themes/dark-high-contrast.css +145 -107
- kerykeion/charts/themes/dark.css +146 -107
- kerykeion/charts/themes/light.css +146 -103
- kerykeion/charts/themes/strawberry.css +158 -0
- kerykeion/composite_subject_factory.py +408 -0
- kerykeion/ephemeris_data_factory.py +443 -0
- kerykeion/fetch_geonames.py +81 -21
- kerykeion/house_comparison/__init__.py +6 -0
- kerykeion/house_comparison/house_comparison_factory.py +103 -0
- kerykeion/house_comparison/house_comparison_utils.py +126 -0
- kerykeion/kr_types/__init__.py +66 -6
- kerykeion/kr_types/chart_template_model.py +20 -0
- kerykeion/kr_types/kerykeion_exception.py +15 -9
- kerykeion/kr_types/kr_literals.py +14 -106
- kerykeion/kr_types/kr_models.py +14 -179
- kerykeion/kr_types/settings_models.py +15 -152
- kerykeion/planetary_return_factory.py +805 -0
- kerykeion/relationship_score_factory.py +301 -0
- kerykeion/report.py +750 -65
- kerykeion/schemas/__init__.py +106 -0
- kerykeion/schemas/chart_template_model.py +367 -0
- kerykeion/schemas/kerykeion_exception.py +20 -0
- kerykeion/schemas/kr_literals.py +181 -0
- kerykeion/schemas/kr_models.py +603 -0
- kerykeion/schemas/settings_models.py +188 -0
- kerykeion/settings/__init__.py +20 -1
- kerykeion/settings/chart_defaults.py +444 -0
- kerykeion/settings/config_constants.py +152 -0
- kerykeion/settings/kerykeion_settings.py +36 -61
- kerykeion/settings/translation_strings.py +1499 -0
- kerykeion/settings/translations.py +74 -0
- kerykeion/sweph/ast136/s136108s.se1 +0 -0
- kerykeion/sweph/ast136/s136199s.se1 +0 -0
- kerykeion/sweph/ast136/s136472s.se1 +0 -0
- kerykeion/sweph/ast28/se28978s.se1 +0 -0
- kerykeion/sweph/ast50/se50000s.se1 +0 -0
- kerykeion/sweph/ast90/se90377s.se1 +0 -0
- kerykeion/sweph/ast90/se90482s.se1 +0 -0
- kerykeion/sweph/sefstars.txt +1602 -0
- kerykeion/transits_time_range_factory.py +302 -0
- kerykeion/utilities.py +626 -125
- kerykeion-5.1.9.dist-info/METADATA +1793 -0
- kerykeion-5.1.9.dist-info/RECORD +63 -0
- {kerykeion-4.18.3.dist-info → kerykeion-5.1.9.dist-info}/WHEEL +1 -1
- kerykeion/aspects/natal_aspects.py +0 -143
- kerykeion/aspects/synastry_aspects.py +0 -113
- kerykeion/astrological_subject.py +0 -818
- kerykeion/charts/kerykeion_chart_svg.py +0 -894
- kerykeion/enums.py +0 -51
- kerykeion/ephemeris_data.py +0 -178
- kerykeion/kr_types/chart_types.py +0 -88
- kerykeion/relationship_score/__init__.py +0 -2
- kerykeion/relationship_score/relationship_score.py +0 -175
- kerykeion/relationship_score/relationship_score_factory.py +0 -275
- kerykeion/settings/kr.config.json +0 -721
- kerykeion-4.18.3.dist-info/LICENSE +0 -661
- kerykeion-4.18.3.dist-info/METADATA +0 -396
- kerykeion-4.18.3.dist-info/RECORD +0 -42
- kerykeion-4.18.3.dist-info/entry_points.txt +0 -3
- /LICENSE → /kerykeion-5.1.9.dist-info/licenses/LICENSE +0 -0
|
@@ -1,818 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
This is part of Kerykeion (C) 2024 Giacomo Battaglia
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import pytz
|
|
7
|
-
import swisseph as swe
|
|
8
|
-
import logging
|
|
9
|
-
import warnings
|
|
10
|
-
|
|
11
|
-
from datetime import datetime
|
|
12
|
-
from functools import cached_property
|
|
13
|
-
from kerykeion.fetch_geonames import FetchGeonames
|
|
14
|
-
from kerykeion.kr_types import (
|
|
15
|
-
KerykeionException,
|
|
16
|
-
ZodiacType,
|
|
17
|
-
AstrologicalSubjectModel,
|
|
18
|
-
LunarPhaseModel,
|
|
19
|
-
KerykeionPointModel,
|
|
20
|
-
PointType,
|
|
21
|
-
SiderealMode,
|
|
22
|
-
HousesSystemIdentifier,
|
|
23
|
-
PerspectiveType,
|
|
24
|
-
Planet,
|
|
25
|
-
Houses
|
|
26
|
-
)
|
|
27
|
-
from kerykeion.utilities import (
|
|
28
|
-
get_number_from_name,
|
|
29
|
-
get_kerykeion_point_from_degree,
|
|
30
|
-
get_planet_house,
|
|
31
|
-
get_moon_emoji_from_phase_int,
|
|
32
|
-
get_moon_phase_name_from_phase_int,
|
|
33
|
-
check_and_adjust_polar_latitude
|
|
34
|
-
)
|
|
35
|
-
from pathlib import Path
|
|
36
|
-
from typing import Union, get_args
|
|
37
|
-
|
|
38
|
-
DEFAULT_GEONAMES_USERNAME = "century.boy"
|
|
39
|
-
DEFAULT_SIDEREAL_MODE: SiderealMode = "FAGAN_BRADLEY"
|
|
40
|
-
DEFAULT_HOUSES_SYSTEM_IDENTIFIER: HousesSystemIdentifier = "P"
|
|
41
|
-
DEFAULT_ZODIAC_TYPE: ZodiacType = "Tropic"
|
|
42
|
-
DEFAULT_PERSPECTIVE_TYPE: PerspectiveType = "Apparent Geocentric"
|
|
43
|
-
GEONAMES_DEFAULT_USERNAME_WARNING = (
|
|
44
|
-
"\n********\n"
|
|
45
|
-
"NO GEONAMES USERNAME SET!\n"
|
|
46
|
-
"Using the default geonames username is not recommended, please set a custom one!\n"
|
|
47
|
-
"You can get one for free here:\n"
|
|
48
|
-
"https://www.geonames.org/login\n"
|
|
49
|
-
"Keep in mind that the default username is limited to 2000 requests per hour and is shared with everyone else using this library.\n"
|
|
50
|
-
"********"
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
NOW = datetime.now()
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class AstrologicalSubject:
|
|
57
|
-
"""
|
|
58
|
-
Calculates all the astrological information, the coordinates,
|
|
59
|
-
it's utc and julian day and returns an object with all that data.
|
|
60
|
-
|
|
61
|
-
Args:
|
|
62
|
-
- name (str, optional): The name of the subject. Defaults to "Now".
|
|
63
|
-
- year (int, optional): The year of birth. Defaults to the current year.
|
|
64
|
-
- month (int, optional): The month of birth. Defaults to the current month.
|
|
65
|
-
- day (int, optional): The day of birth. Defaults to the current day.
|
|
66
|
-
- hour (int, optional): The hour of birth. Defaults to the current hour.
|
|
67
|
-
- minute (int, optional): Defaults to the current minute.
|
|
68
|
-
- city (str, optional): City or location of birth. Defaults to "London", which is GMT time.
|
|
69
|
-
The city argument is used to get the coordinates and timezone from geonames just in case
|
|
70
|
-
you don't insert them manually (see _get_tz).
|
|
71
|
-
If you insert the coordinates and timezone manually, the city argument is not used for calculations
|
|
72
|
-
but it's still used as a value for the city attribute.
|
|
73
|
-
- nat (str, optional): _ Defaults to "".
|
|
74
|
-
- lng (Union[int, float], optional): Longitude of the birth location. Defaults to 0 (Greenwich, London).
|
|
75
|
-
- lat (Union[int, float], optional): Latitude of the birth location. Defaults to 51.5074 (Greenwich, London).
|
|
76
|
-
- tz_str (Union[str, bool], optional): Timezone of the birth location. Defaults to "GMT".
|
|
77
|
-
- geonames_username (str, optional): The username for the geonames API. Note: Change this to your own username to avoid rate limits!
|
|
78
|
-
You can get one for free here: https://www.geonames.org/login
|
|
79
|
-
- online (bool, optional): Sets if you want to use the online mode, which fetches the timezone and coordinates from geonames.
|
|
80
|
-
If you already have the coordinates and timezone, set this to False. Defaults to True.
|
|
81
|
-
- disable_chiron: Deprecated, use disable_chiron_and_lilith instead.
|
|
82
|
-
- sidereal_mode (SiderealMode, optional): Also known as Ayanamsa.
|
|
83
|
-
The mode to use for the sidereal zodiac, according to the Swiss Ephemeris.
|
|
84
|
-
Defaults to "FAGAN_BRADLEY".
|
|
85
|
-
Available modes are visible in the SiderealMode Literal.
|
|
86
|
-
- houses_system_identifier (HousesSystemIdentifier, optional): The system to use for the calculation of the houses.
|
|
87
|
-
Defaults to "P" (Placidus).
|
|
88
|
-
Available systems are visible in the HousesSystemIdentifier Literal.
|
|
89
|
-
- perspective_type (PerspectiveType, optional): The perspective to use for the calculation of the chart.
|
|
90
|
-
Defaults to "Apparent Geocentric".
|
|
91
|
-
Available perspectives are visible in the PerspectiveType Literal.
|
|
92
|
-
- is_dst (Union[None, bool], optional): Specify if the time is in DST. Defaults to None.
|
|
93
|
-
By default (None), the library will try to guess if the time is in DST or not and raise an AmbiguousTimeError
|
|
94
|
-
if it can't guess. If you know the time is in DST, set this to True, if you know it's not, set it to False.
|
|
95
|
-
- disable_chiron_and_lilith (bool, optional): boolean representing if Chiron and Lilith should be disabled. Default is False.
|
|
96
|
-
Chiron calculation can create some issues with the Swiss Ephemeris when the date is too far in the past.
|
|
97
|
-
"""
|
|
98
|
-
|
|
99
|
-
# Defined by the user
|
|
100
|
-
name: str
|
|
101
|
-
year: int
|
|
102
|
-
month: int
|
|
103
|
-
day: int
|
|
104
|
-
hour: int
|
|
105
|
-
minute: int
|
|
106
|
-
city: str
|
|
107
|
-
nation: str
|
|
108
|
-
lng: Union[int, float]
|
|
109
|
-
lat: Union[int, float]
|
|
110
|
-
tz_str: str
|
|
111
|
-
geonames_username: str
|
|
112
|
-
online: bool
|
|
113
|
-
zodiac_type: ZodiacType
|
|
114
|
-
sidereal_mode: Union[SiderealMode, None]
|
|
115
|
-
houses_system_identifier: HousesSystemIdentifier
|
|
116
|
-
houses_system_name: str
|
|
117
|
-
perspective_type: PerspectiveType
|
|
118
|
-
is_dst: Union[None, bool]
|
|
119
|
-
|
|
120
|
-
# Generated internally
|
|
121
|
-
city_data: dict[str, str]
|
|
122
|
-
julian_day: Union[int, float]
|
|
123
|
-
json_dir: Path
|
|
124
|
-
iso_formatted_local_datetime: str
|
|
125
|
-
iso_formatted_utc_datetime: str
|
|
126
|
-
|
|
127
|
-
# Planets
|
|
128
|
-
sun: KerykeionPointModel
|
|
129
|
-
moon: KerykeionPointModel
|
|
130
|
-
mercury: KerykeionPointModel
|
|
131
|
-
venus: KerykeionPointModel
|
|
132
|
-
mars: KerykeionPointModel
|
|
133
|
-
jupiter: KerykeionPointModel
|
|
134
|
-
saturn: KerykeionPointModel
|
|
135
|
-
uranus: KerykeionPointModel
|
|
136
|
-
neptune: KerykeionPointModel
|
|
137
|
-
pluto: KerykeionPointModel
|
|
138
|
-
true_node: KerykeionPointModel
|
|
139
|
-
mean_node: KerykeionPointModel
|
|
140
|
-
chiron: Union[KerykeionPointModel, None]
|
|
141
|
-
mean_lilith: Union[KerykeionPointModel, None]
|
|
142
|
-
|
|
143
|
-
# Houses
|
|
144
|
-
first_house: KerykeionPointModel
|
|
145
|
-
second_house: KerykeionPointModel
|
|
146
|
-
third_house: KerykeionPointModel
|
|
147
|
-
fourth_house: KerykeionPointModel
|
|
148
|
-
fifth_house: KerykeionPointModel
|
|
149
|
-
sixth_house: KerykeionPointModel
|
|
150
|
-
seventh_house: KerykeionPointModel
|
|
151
|
-
eighth_house: KerykeionPointModel
|
|
152
|
-
ninth_house: KerykeionPointModel
|
|
153
|
-
tenth_house: KerykeionPointModel
|
|
154
|
-
eleventh_house: KerykeionPointModel
|
|
155
|
-
twelfth_house: KerykeionPointModel
|
|
156
|
-
|
|
157
|
-
# Lists
|
|
158
|
-
_houses_list: list[KerykeionPointModel]
|
|
159
|
-
_houses_degree_ut: list[float]
|
|
160
|
-
|
|
161
|
-
# Enable or disable features
|
|
162
|
-
disable_chiron: Union[None, bool]
|
|
163
|
-
disable_chiron_and_lilith: bool
|
|
164
|
-
|
|
165
|
-
planets_names_list: list[Planet]
|
|
166
|
-
houses_names_list: list[Houses]
|
|
167
|
-
|
|
168
|
-
def __init__(
|
|
169
|
-
self,
|
|
170
|
-
name="Now",
|
|
171
|
-
year: int = NOW.year,
|
|
172
|
-
month: int = NOW.month,
|
|
173
|
-
day: int = NOW.day,
|
|
174
|
-
hour: int = NOW.hour,
|
|
175
|
-
minute: int = NOW.minute,
|
|
176
|
-
city: Union[str, None] = None,
|
|
177
|
-
nation: Union[str, None] = None,
|
|
178
|
-
lng: Union[int, float, None] = None,
|
|
179
|
-
lat: Union[int, float, None] = None,
|
|
180
|
-
tz_str: Union[str, None] = None,
|
|
181
|
-
geonames_username: Union[str, None] = None,
|
|
182
|
-
zodiac_type: ZodiacType = DEFAULT_ZODIAC_TYPE,
|
|
183
|
-
online: bool = True,
|
|
184
|
-
disable_chiron: Union[None, bool] = None, # Deprecated
|
|
185
|
-
sidereal_mode: Union[SiderealMode, None] = None,
|
|
186
|
-
houses_system_identifier: HousesSystemIdentifier = DEFAULT_HOUSES_SYSTEM_IDENTIFIER,
|
|
187
|
-
perspective_type: PerspectiveType = DEFAULT_PERSPECTIVE_TYPE,
|
|
188
|
-
is_dst: Union[None, bool] = None,
|
|
189
|
-
disable_chiron_and_lilith: bool = False
|
|
190
|
-
) -> None:
|
|
191
|
-
logging.debug("Starting Kerykeion")
|
|
192
|
-
|
|
193
|
-
# Deprecation warnings --->
|
|
194
|
-
if disable_chiron is not None:
|
|
195
|
-
warnings.warn(
|
|
196
|
-
"The 'disable_chiron' argument is deprecated and will be removed in a future version. "
|
|
197
|
-
"Please use 'disable_chiron' instead.",
|
|
198
|
-
DeprecationWarning
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
if disable_chiron_and_lilith:
|
|
202
|
-
raise ValueError("Cannot specify both 'disable_chiron' and 'disable_chiron_and_lilith'. Use 'disable_chiron_and_lilith' only.")
|
|
203
|
-
|
|
204
|
-
self.disable_chiron_and_lilith = disable_chiron
|
|
205
|
-
# <--- Deprecation warnings
|
|
206
|
-
|
|
207
|
-
self.name = name
|
|
208
|
-
self.year = year
|
|
209
|
-
self.month = month
|
|
210
|
-
self.day = day
|
|
211
|
-
self.hour = hour
|
|
212
|
-
self.minute = minute
|
|
213
|
-
self.zodiac_type = zodiac_type
|
|
214
|
-
self.online = online
|
|
215
|
-
self.json_dir = Path.home()
|
|
216
|
-
self.disable_chiron = disable_chiron
|
|
217
|
-
self.sidereal_mode = sidereal_mode
|
|
218
|
-
self.houses_system_identifier = houses_system_identifier
|
|
219
|
-
self.perspective_type = perspective_type
|
|
220
|
-
self.is_dst = is_dst
|
|
221
|
-
self.disable_chiron_and_lilith = disable_chiron_and_lilith
|
|
222
|
-
|
|
223
|
-
#---------------#
|
|
224
|
-
# General setup #
|
|
225
|
-
#---------------#
|
|
226
|
-
|
|
227
|
-
# Geonames username
|
|
228
|
-
if geonames_username is None and online:
|
|
229
|
-
logging.warning(GEONAMES_DEFAULT_USERNAME_WARNING)
|
|
230
|
-
self.geonames_username = DEFAULT_GEONAMES_USERNAME
|
|
231
|
-
else:
|
|
232
|
-
self.geonames_username = geonames_username # type: ignore
|
|
233
|
-
|
|
234
|
-
# City
|
|
235
|
-
if not city:
|
|
236
|
-
self.city = "London"
|
|
237
|
-
logging.info("No city specified, using London as default")
|
|
238
|
-
else:
|
|
239
|
-
self.city = city
|
|
240
|
-
|
|
241
|
-
# Nation
|
|
242
|
-
if not nation:
|
|
243
|
-
self.nation = "GB"
|
|
244
|
-
logging.info("No nation specified, using GB as default")
|
|
245
|
-
else:
|
|
246
|
-
self.nation = nation
|
|
247
|
-
|
|
248
|
-
# Latitude
|
|
249
|
-
if not lat and not self.online:
|
|
250
|
-
self.lat = 51.5074
|
|
251
|
-
logging.info("No latitude specified, using London as default")
|
|
252
|
-
else:
|
|
253
|
-
self.lat = lat # type: ignore
|
|
254
|
-
|
|
255
|
-
# Longitude
|
|
256
|
-
if not lng and not self.online:
|
|
257
|
-
self.lng = 0
|
|
258
|
-
logging.info("No longitude specified, using London as default")
|
|
259
|
-
else:
|
|
260
|
-
self.lng = lng # type: ignore
|
|
261
|
-
|
|
262
|
-
# Timezone
|
|
263
|
-
if (not self.online) and (not tz_str):
|
|
264
|
-
raise KerykeionException("You need to set the coordinates and timezone if you want to use the offline mode!")
|
|
265
|
-
else:
|
|
266
|
-
self.tz_str = tz_str # type: ignore
|
|
267
|
-
|
|
268
|
-
#-----------------------#
|
|
269
|
-
# Swiss Ephemeris setup #
|
|
270
|
-
#-----------------------#
|
|
271
|
-
|
|
272
|
-
# We set the swisseph path to the current directory
|
|
273
|
-
swe.set_ephe_path(str(Path(__file__).parent.absolute() / "sweph"))
|
|
274
|
-
|
|
275
|
-
# Flags for the Swiss Ephemeris
|
|
276
|
-
self._iflag = swe.FLG_SWIEPH + swe.FLG_SPEED
|
|
277
|
-
|
|
278
|
-
# Chart Perspective check and setup --->
|
|
279
|
-
if self.perspective_type not in get_args(PerspectiveType):
|
|
280
|
-
raise KerykeionException(f"\n* ERROR: '{self.perspective_type}' is NOT a valid chart perspective! Available perspectives are: *" + "\n" + str(get_args(PerspectiveType)))
|
|
281
|
-
|
|
282
|
-
if self.perspective_type == "True Geocentric":
|
|
283
|
-
self._iflag += swe.FLG_TRUEPOS
|
|
284
|
-
elif self.perspective_type == "Heliocentric":
|
|
285
|
-
self._iflag += swe.FLG_HELCTR
|
|
286
|
-
elif self.perspective_type == "Topocentric":
|
|
287
|
-
self._iflag += swe.FLG_TOPOCTR
|
|
288
|
-
# geopos_is_set, for topocentric
|
|
289
|
-
if (self.online) and (not self.tz_str) and (not self.lat) and (not self.lng):
|
|
290
|
-
self._fetch_and_set_tz_and_coordinates_from_geonames()
|
|
291
|
-
swe.set_topo(self.lng, self.lat, 0)
|
|
292
|
-
# <--- Chart Perspective check and setup
|
|
293
|
-
|
|
294
|
-
# House System check and setup --->
|
|
295
|
-
if self.houses_system_identifier not in get_args(HousesSystemIdentifier):
|
|
296
|
-
raise KerykeionException(f"\n* ERROR: '{self.houses_system_identifier}' is NOT a valid house system! Available systems are: *" + "\n" + str(get_args(HousesSystemIdentifier)))
|
|
297
|
-
|
|
298
|
-
self.houses_system_name = swe.house_name(self.houses_system_identifier.encode('ascii'))
|
|
299
|
-
# <--- House System check and setup
|
|
300
|
-
|
|
301
|
-
# Zodiac Type and Sidereal mode checks and setup --->
|
|
302
|
-
if zodiac_type and not zodiac_type in get_args(ZodiacType):
|
|
303
|
-
raise KerykeionException(f"\n* ERROR: '{zodiac_type}' is NOT a valid zodiac type! Available types are: *" + "\n" + str(get_args(ZodiacType)))
|
|
304
|
-
|
|
305
|
-
if self.sidereal_mode and self.zodiac_type == "Tropic":
|
|
306
|
-
raise KerykeionException("You can't set a sidereal mode with a Tropic zodiac type!")
|
|
307
|
-
|
|
308
|
-
if self.zodiac_type == "Sidereal" and not self.sidereal_mode:
|
|
309
|
-
self.sidereal_mode = DEFAULT_SIDEREAL_MODE
|
|
310
|
-
logging.info("No sidereal mode set, using default FAGAN_BRADLEY")
|
|
311
|
-
|
|
312
|
-
if self.zodiac_type == "Sidereal":
|
|
313
|
-
# Check if the sidereal mode is valid
|
|
314
|
-
|
|
315
|
-
if not self.sidereal_mode or not self.sidereal_mode in get_args(SiderealMode):
|
|
316
|
-
raise KerykeionException(f"\n* ERROR: '{self.sidereal_mode}' is NOT a valid sidereal mode! Available modes are: *" + "\n" + str(get_args(SiderealMode)))
|
|
317
|
-
|
|
318
|
-
self._iflag += swe.FLG_SIDEREAL
|
|
319
|
-
mode = "SIDM_" + self.sidereal_mode
|
|
320
|
-
swe.set_sid_mode(getattr(swe, mode))
|
|
321
|
-
logging.debug(f"Using sidereal mode: {mode}")
|
|
322
|
-
# <--- Zodiac Type and Sidereal mode checks and setup
|
|
323
|
-
|
|
324
|
-
#------------------------#
|
|
325
|
-
# Start the calculations #
|
|
326
|
-
#------------------------#
|
|
327
|
-
|
|
328
|
-
# UTC, julian day and local time setup --->
|
|
329
|
-
if (self.online) and (not self.tz_str) and (not self.lat) and (not self.lng):
|
|
330
|
-
self._fetch_and_set_tz_and_coordinates_from_geonames()
|
|
331
|
-
|
|
332
|
-
self.lat = check_and_adjust_polar_latitude(self.lat)
|
|
333
|
-
|
|
334
|
-
# Local time to UTC
|
|
335
|
-
local_time = pytz.timezone(self.tz_str)
|
|
336
|
-
naive_datetime = datetime(self.year, self.month, self.day, self.hour, self.minute, 0)
|
|
337
|
-
|
|
338
|
-
try:
|
|
339
|
-
local_datetime = local_time.localize(naive_datetime, is_dst=self.is_dst)
|
|
340
|
-
except pytz.exceptions.AmbiguousTimeError:
|
|
341
|
-
raise KerykeionException("Ambiguous time! Please specify if the time is in DST or not with the is_dst argument.")
|
|
342
|
-
|
|
343
|
-
utc_object = local_datetime.astimezone(pytz.utc)
|
|
344
|
-
self.iso_formatted_utc_datetime = utc_object.isoformat()
|
|
345
|
-
|
|
346
|
-
# ISO formatted local datetime
|
|
347
|
-
self.iso_formatted_local_datetime = local_datetime.isoformat()
|
|
348
|
-
|
|
349
|
-
# Julian day calculation
|
|
350
|
-
utc_float_hour_with_minutes = utc_object.hour + (utc_object.minute / 60)
|
|
351
|
-
self.julian_day = float(swe.julday(utc_object.year, utc_object.month, utc_object.day, utc_float_hour_with_minutes))
|
|
352
|
-
# <--- UTC, julian day and local time setup
|
|
353
|
-
|
|
354
|
-
self._initialize_houses()
|
|
355
|
-
self._initialize_planets()
|
|
356
|
-
self._initialize_moon_phase()
|
|
357
|
-
|
|
358
|
-
# Deprecated properties
|
|
359
|
-
self.utc_time
|
|
360
|
-
self.local_time
|
|
361
|
-
|
|
362
|
-
def __str__(self) -> str:
|
|
363
|
-
return f"Astrological data for: {self.name}, {self.iso_formatted_utc_datetime} UTC\nBirth location: {self.city}, Lat {self.lat}, Lon {self.lng}"
|
|
364
|
-
|
|
365
|
-
def __repr__(self) -> str:
|
|
366
|
-
return f"Astrological data for: {self.name}, {self.iso_formatted_utc_datetime} UTC\nBirth location: {self.city}, Lat {self.lat}, Lon {self.lng}"
|
|
367
|
-
|
|
368
|
-
def __getitem__(self, item):
|
|
369
|
-
return getattr(self, item)
|
|
370
|
-
|
|
371
|
-
def get(self, item, default=None):
|
|
372
|
-
return getattr(self, item, default)
|
|
373
|
-
|
|
374
|
-
def _fetch_and_set_tz_and_coordinates_from_geonames(self) -> None:
|
|
375
|
-
"""Gets the nearest time zone for the calculation"""
|
|
376
|
-
logging.info("Fetching timezone/coordinates from geonames")
|
|
377
|
-
|
|
378
|
-
geonames = FetchGeonames(
|
|
379
|
-
self.city,
|
|
380
|
-
self.nation,
|
|
381
|
-
username=self.geonames_username,
|
|
382
|
-
)
|
|
383
|
-
self.city_data: dict[str, str] = geonames.get_serialized_data()
|
|
384
|
-
|
|
385
|
-
if (
|
|
386
|
-
not "countryCode" in self.city_data
|
|
387
|
-
or not "timezonestr" in self.city_data
|
|
388
|
-
or not "lat" in self.city_data
|
|
389
|
-
or not "lng" in self.city_data
|
|
390
|
-
):
|
|
391
|
-
raise KerykeionException("No data found for this city, try again! Maybe check your connection?")
|
|
392
|
-
|
|
393
|
-
self.nation = self.city_data["countryCode"]
|
|
394
|
-
self.lng = float(self.city_data["lng"])
|
|
395
|
-
self.lat = float(self.city_data["lat"])
|
|
396
|
-
self.tz_str = self.city_data["timezonestr"]
|
|
397
|
-
|
|
398
|
-
def _initialize_houses(self) -> None:
|
|
399
|
-
"""
|
|
400
|
-
Calculate positions and store them in dictionaries
|
|
401
|
-
|
|
402
|
-
https://www.astro.com/faq/fq_fh_owhouse_e.htm
|
|
403
|
-
https://github.com/jwmatthys/pd-swisseph/blob/master/swehouse.c#L685
|
|
404
|
-
hsys = letter code for house system;
|
|
405
|
-
A equal
|
|
406
|
-
E equal
|
|
407
|
-
B Alcabitius
|
|
408
|
-
C Campanus
|
|
409
|
-
D equal (MC)
|
|
410
|
-
F Carter "Poli-Equatorial"
|
|
411
|
-
G 36 Gauquelin sectors
|
|
412
|
-
H horizon / azimut
|
|
413
|
-
I Sunshine solution Treindl
|
|
414
|
-
i Sunshine solution Makransky
|
|
415
|
-
K Koch
|
|
416
|
-
L Pullen SD "sinusoidal delta", ex Neo-Porphyry
|
|
417
|
-
M Morinus
|
|
418
|
-
N equal/1=Aries
|
|
419
|
-
O Porphyry
|
|
420
|
-
P Placidus
|
|
421
|
-
Q Pullen SR "sinusoidal ratio"
|
|
422
|
-
R Regiomontanus
|
|
423
|
-
S Sripati
|
|
424
|
-
T Polich/Page ("topocentric")
|
|
425
|
-
U Krusinski-Pisa-Goelzer
|
|
426
|
-
V equal Vehlow
|
|
427
|
-
W equal, whole sign
|
|
428
|
-
X axial rotation system/ Meridian houses
|
|
429
|
-
Y APC houses
|
|
430
|
-
"""
|
|
431
|
-
|
|
432
|
-
if self.zodiac_type == "Sidereal":
|
|
433
|
-
self._houses_degree_ut = swe.houses_ex(
|
|
434
|
-
tjdut=self.julian_day,
|
|
435
|
-
lat=self.lat, lon=self.lng,
|
|
436
|
-
hsys=str.encode(self.houses_system_identifier),
|
|
437
|
-
flags=swe.FLG_SIDEREAL
|
|
438
|
-
)[0]
|
|
439
|
-
|
|
440
|
-
elif self.zodiac_type == "Tropic":
|
|
441
|
-
self._houses_degree_ut = swe.houses(
|
|
442
|
-
tjdut=self.julian_day, lat=self.lat,
|
|
443
|
-
lon=self.lng,
|
|
444
|
-
hsys=str.encode(self.houses_system_identifier)
|
|
445
|
-
)[0]
|
|
446
|
-
|
|
447
|
-
point_type: PointType = "House"
|
|
448
|
-
|
|
449
|
-
# stores the house in singular dictionaries.
|
|
450
|
-
self.first_house = get_kerykeion_point_from_degree(self._houses_degree_ut[0], "First_House", point_type=point_type)
|
|
451
|
-
self.second_house = get_kerykeion_point_from_degree(self._houses_degree_ut[1], "Second_House", point_type=point_type)
|
|
452
|
-
self.third_house = get_kerykeion_point_from_degree(self._houses_degree_ut[2], "Third_House", point_type=point_type)
|
|
453
|
-
self.fourth_house = get_kerykeion_point_from_degree(self._houses_degree_ut[3], "Fourth_House", point_type=point_type)
|
|
454
|
-
self.fifth_house = get_kerykeion_point_from_degree(self._houses_degree_ut[4], "Fifth_House", point_type=point_type)
|
|
455
|
-
self.sixth_house = get_kerykeion_point_from_degree(self._houses_degree_ut[5], "Sixth_House", point_type=point_type)
|
|
456
|
-
self.seventh_house = get_kerykeion_point_from_degree(self._houses_degree_ut[6], "Seventh_House", point_type=point_type)
|
|
457
|
-
self.eighth_house = get_kerykeion_point_from_degree(self._houses_degree_ut[7], "Eighth_House", point_type=point_type)
|
|
458
|
-
self.ninth_house = get_kerykeion_point_from_degree(self._houses_degree_ut[8], "Ninth_House", point_type=point_type)
|
|
459
|
-
self.tenth_house = get_kerykeion_point_from_degree(self._houses_degree_ut[9], "Tenth_House", point_type=point_type)
|
|
460
|
-
self.eleventh_house = get_kerykeion_point_from_degree(self._houses_degree_ut[10], "Eleventh_House", point_type=point_type)
|
|
461
|
-
self.twelfth_house = get_kerykeion_point_from_degree(self._houses_degree_ut[11], "Twelfth_House", point_type=point_type)
|
|
462
|
-
|
|
463
|
-
self.houses_names_list = list(get_args(Houses))
|
|
464
|
-
|
|
465
|
-
# Deprecated
|
|
466
|
-
self._houses_list = [
|
|
467
|
-
self.first_house,
|
|
468
|
-
self.second_house,
|
|
469
|
-
self.third_house,
|
|
470
|
-
self.fourth_house,
|
|
471
|
-
self.fifth_house,
|
|
472
|
-
self.sixth_house,
|
|
473
|
-
self.seventh_house,
|
|
474
|
-
self.eighth_house,
|
|
475
|
-
self.ninth_house,
|
|
476
|
-
self.tenth_house,
|
|
477
|
-
self.eleventh_house,
|
|
478
|
-
self.twelfth_house,
|
|
479
|
-
]
|
|
480
|
-
|
|
481
|
-
def _initialize_planets(self) -> None:
|
|
482
|
-
"""Defines body positon in signs and information and
|
|
483
|
-
stores them in dictionaries"""
|
|
484
|
-
|
|
485
|
-
point_type: PointType = "Planet"
|
|
486
|
-
|
|
487
|
-
sun_deg = swe.calc(self.julian_day, 0, self._iflag)[0][0]
|
|
488
|
-
moon_deg = swe.calc(self.julian_day, 1, self._iflag)[0][0]
|
|
489
|
-
mercury_deg = swe.calc(self.julian_day, 2, self._iflag)[0][0]
|
|
490
|
-
venus_deg = swe.calc(self.julian_day, 3, self._iflag)[0][0]
|
|
491
|
-
mars_deg = swe.calc(self.julian_day, 4, self._iflag)[0][0]
|
|
492
|
-
jupiter_deg = swe.calc(self.julian_day, 5, self._iflag)[0][0]
|
|
493
|
-
saturn_deg = swe.calc(self.julian_day, 6, self._iflag)[0][0]
|
|
494
|
-
uranus_deg = swe.calc(self.julian_day, 7, self._iflag)[0][0]
|
|
495
|
-
neptune_deg = swe.calc(self.julian_day, 8, self._iflag)[0][0]
|
|
496
|
-
pluto_deg = swe.calc(self.julian_day, 9, self._iflag)[0][0]
|
|
497
|
-
mean_node_deg = swe.calc(self.julian_day, 10, self._iflag)[0][0]
|
|
498
|
-
true_node_deg = swe.calc(self.julian_day, 11, self._iflag)[0][0]
|
|
499
|
-
|
|
500
|
-
self.sun = get_kerykeion_point_from_degree(sun_deg, "Sun", point_type=point_type)
|
|
501
|
-
self.moon = get_kerykeion_point_from_degree(moon_deg, "Moon", point_type=point_type)
|
|
502
|
-
self.mercury = get_kerykeion_point_from_degree(mercury_deg, "Mercury", point_type=point_type)
|
|
503
|
-
self.venus = get_kerykeion_point_from_degree(venus_deg, "Venus", point_type=point_type)
|
|
504
|
-
self.mars = get_kerykeion_point_from_degree(mars_deg, "Mars", point_type=point_type)
|
|
505
|
-
self.jupiter = get_kerykeion_point_from_degree(jupiter_deg, "Jupiter", point_type=point_type)
|
|
506
|
-
self.saturn = get_kerykeion_point_from_degree(saturn_deg, "Saturn", point_type=point_type)
|
|
507
|
-
self.uranus = get_kerykeion_point_from_degree(uranus_deg, "Uranus", point_type=point_type)
|
|
508
|
-
self.neptune = get_kerykeion_point_from_degree(neptune_deg, "Neptune", point_type=point_type)
|
|
509
|
-
self.pluto = get_kerykeion_point_from_degree(pluto_deg, "Pluto", point_type=point_type)
|
|
510
|
-
self.mean_node = get_kerykeion_point_from_degree(mean_node_deg, "Mean_Node", point_type=point_type)
|
|
511
|
-
self.true_node = get_kerykeion_point_from_degree(true_node_deg, "True_Node", point_type=point_type)
|
|
512
|
-
|
|
513
|
-
self.sun.house = get_planet_house(sun_deg, self._houses_degree_ut)
|
|
514
|
-
self.moon.house = get_planet_house(moon_deg, self._houses_degree_ut)
|
|
515
|
-
self.mercury.house = get_planet_house(mercury_deg, self._houses_degree_ut)
|
|
516
|
-
self.venus.house = get_planet_house(venus_deg, self._houses_degree_ut)
|
|
517
|
-
self.mars.house = get_planet_house(mars_deg, self._houses_degree_ut)
|
|
518
|
-
self.jupiter.house = get_planet_house(jupiter_deg, self._houses_degree_ut)
|
|
519
|
-
self.saturn.house = get_planet_house(saturn_deg, self._houses_degree_ut)
|
|
520
|
-
self.uranus.house = get_planet_house(uranus_deg, self._houses_degree_ut)
|
|
521
|
-
self.neptune.house = get_planet_house(neptune_deg, self._houses_degree_ut)
|
|
522
|
-
self.pluto.house = get_planet_house(pluto_deg, self._houses_degree_ut)
|
|
523
|
-
self.mean_node.house = get_planet_house(mean_node_deg, self._houses_degree_ut)
|
|
524
|
-
self.true_node.house = get_planet_house(true_node_deg, self._houses_degree_ut)
|
|
525
|
-
|
|
526
|
-
# Deprecated
|
|
527
|
-
planets_list = [
|
|
528
|
-
self.sun,
|
|
529
|
-
self.moon,
|
|
530
|
-
self.mercury,
|
|
531
|
-
self.venus,
|
|
532
|
-
self.mars,
|
|
533
|
-
self.jupiter,
|
|
534
|
-
self.saturn,
|
|
535
|
-
self.uranus,
|
|
536
|
-
self.neptune,
|
|
537
|
-
self.pluto,
|
|
538
|
-
self.mean_node,
|
|
539
|
-
self.true_node,
|
|
540
|
-
]
|
|
541
|
-
|
|
542
|
-
if not self.disable_chiron_and_lilith:
|
|
543
|
-
chiron_deg = swe.calc(self.julian_day, 15, self._iflag)[0][0]
|
|
544
|
-
mean_lilith_deg = swe.calc(self.julian_day, 12, self._iflag)[0][0]
|
|
545
|
-
|
|
546
|
-
self.chiron = get_kerykeion_point_from_degree(chiron_deg, "Chiron", point_type=point_type)
|
|
547
|
-
self.mean_lilith = get_kerykeion_point_from_degree(mean_lilith_deg, "Mean_Lilith", point_type=point_type)
|
|
548
|
-
|
|
549
|
-
self.chiron.house = get_planet_house(chiron_deg, self._houses_degree_ut)
|
|
550
|
-
self.mean_lilith.house = get_planet_house(mean_lilith_deg, self._houses_degree_ut)
|
|
551
|
-
|
|
552
|
-
# Deprecated
|
|
553
|
-
planets_list.append(self.chiron)
|
|
554
|
-
planets_list.append(self.mean_lilith)
|
|
555
|
-
|
|
556
|
-
else:
|
|
557
|
-
self.chiron = None
|
|
558
|
-
self.mean_lilith = None
|
|
559
|
-
|
|
560
|
-
# FIXME: Update after removing planets_list
|
|
561
|
-
self.planets_names_list = [planet["name"] for planet in planets_list]
|
|
562
|
-
|
|
563
|
-
# Check in retrograde or not:
|
|
564
|
-
for planet in planets_list:
|
|
565
|
-
planet_number = get_number_from_name(planet["name"])
|
|
566
|
-
if swe.calc(self.julian_day, planet_number, self._iflag)[0][3] < 0:
|
|
567
|
-
planet["retrograde"] = True
|
|
568
|
-
else:
|
|
569
|
-
planet["retrograde"] = False
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
def _initialize_moon_phase(self) -> None:
|
|
573
|
-
"""
|
|
574
|
-
Calculate and initialize the lunar phase based on the positions of the moon and sun.
|
|
575
|
-
|
|
576
|
-
This function calculates the degrees between the moon and the sun, determines the moon phase
|
|
577
|
-
and sun phase, and initializes the lunar phase model with the calculated values.
|
|
578
|
-
"""
|
|
579
|
-
# Initialize moon_phase and sun_phase to None in case of an error
|
|
580
|
-
moon_phase, sun_phase = None, None
|
|
581
|
-
|
|
582
|
-
# Calculate the anti-clockwise degrees between the sun and moon
|
|
583
|
-
moon, sun = self.moon.abs_pos, self.sun.abs_pos
|
|
584
|
-
degrees_between = (moon - sun) % 360
|
|
585
|
-
|
|
586
|
-
# Calculate the moon phase (1-28) based on the degrees between the sun and moon
|
|
587
|
-
step = 360.0 / 28.0
|
|
588
|
-
moon_phase = int(degrees_between // step) + 1
|
|
589
|
-
|
|
590
|
-
# Define the sun phase steps
|
|
591
|
-
sunstep = [
|
|
592
|
-
0, 30, 40, 50, 60, 70, 80, 90, 120, 130, 140, 150, 160, 170, 180,
|
|
593
|
-
210, 220, 230, 240, 250, 260, 270, 300, 310, 320, 330, 340, 350
|
|
594
|
-
]
|
|
595
|
-
|
|
596
|
-
# Calculate the sun phase (1-28) based on the degrees between the sun and moon
|
|
597
|
-
for x in range(len(sunstep)):
|
|
598
|
-
low = sunstep[x]
|
|
599
|
-
high = sunstep[x + 1] if x < len(sunstep) - 1 else 360
|
|
600
|
-
if low <= degrees_between < high:
|
|
601
|
-
sun_phase = x + 1
|
|
602
|
-
break
|
|
603
|
-
|
|
604
|
-
# Create a dictionary with the lunar phase information
|
|
605
|
-
lunar_phase_dictionary = {
|
|
606
|
-
"degrees_between_s_m": degrees_between,
|
|
607
|
-
"moon_phase": moon_phase,
|
|
608
|
-
"sun_phase": sun_phase,
|
|
609
|
-
"moon_emoji": get_moon_emoji_from_phase_int(moon_phase),
|
|
610
|
-
"moon_phase_name": get_moon_phase_name_from_phase_int(moon_phase)
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
# Initialize the lunar phase model with the calculated values
|
|
614
|
-
self.lunar_phase = LunarPhaseModel(**lunar_phase_dictionary)
|
|
615
|
-
|
|
616
|
-
def json(self, dump=False, destination_folder: Union[str, None] = None, indent: Union[int, None] = None) -> str:
|
|
617
|
-
"""
|
|
618
|
-
Dumps the Kerykeion object to a json string foramt,
|
|
619
|
-
if dump=True also dumps to file located in destination
|
|
620
|
-
or the home folder.
|
|
621
|
-
"""
|
|
622
|
-
|
|
623
|
-
KrData = AstrologicalSubjectModel(**self.__dict__)
|
|
624
|
-
json_string = KrData.model_dump_json(exclude_none=True, indent=indent)
|
|
625
|
-
|
|
626
|
-
if dump:
|
|
627
|
-
if destination_folder:
|
|
628
|
-
destination_path = Path(destination_folder)
|
|
629
|
-
json_path = destination_path / f"{self.name}_kerykeion.json"
|
|
630
|
-
|
|
631
|
-
else:
|
|
632
|
-
json_path = self.json_dir / f"{self.name}_kerykeion.json"
|
|
633
|
-
|
|
634
|
-
with open(json_path, "w", encoding="utf-8") as file:
|
|
635
|
-
file.write(json_string)
|
|
636
|
-
logging.info(f"JSON file dumped in {json_path}.")
|
|
637
|
-
|
|
638
|
-
return json_string
|
|
639
|
-
|
|
640
|
-
def model(self) -> AstrologicalSubjectModel:
|
|
641
|
-
"""
|
|
642
|
-
Creates a Pydantic model of the Kerykeion object.
|
|
643
|
-
"""
|
|
644
|
-
|
|
645
|
-
return AstrologicalSubjectModel(**self.__dict__)
|
|
646
|
-
|
|
647
|
-
@cached_property
|
|
648
|
-
def utc_time(self) -> float:
|
|
649
|
-
"""
|
|
650
|
-
Deprecated property, use iso_formatted_utc_datetime instead, will be removed in the future.
|
|
651
|
-
Returns the UTC time as a float.
|
|
652
|
-
"""
|
|
653
|
-
dt = datetime.fromisoformat(self.iso_formatted_utc_datetime)
|
|
654
|
-
|
|
655
|
-
# Extract the hours, minutes, and seconds
|
|
656
|
-
hours = dt.hour
|
|
657
|
-
minutes = dt.minute
|
|
658
|
-
seconds = dt.second + dt.microsecond / 1_000_000
|
|
659
|
-
|
|
660
|
-
# Convert time to float hours
|
|
661
|
-
float_time = hours + minutes / 60 + seconds / 3600
|
|
662
|
-
|
|
663
|
-
return float_time
|
|
664
|
-
|
|
665
|
-
@cached_property
|
|
666
|
-
def local_time(self) -> float:
|
|
667
|
-
"""
|
|
668
|
-
Deprecated property, use iso_formatted_local_datetime instead, will be removed in the future.
|
|
669
|
-
Returns the local time as a float.
|
|
670
|
-
"""
|
|
671
|
-
dt = datetime.fromisoformat(self.iso_formatted_local_datetime)
|
|
672
|
-
|
|
673
|
-
# Extract the hours, minutes, and seconds
|
|
674
|
-
hours = dt.hour
|
|
675
|
-
minutes = dt.minute
|
|
676
|
-
seconds = dt.second + dt.microsecond / 1_000_000
|
|
677
|
-
|
|
678
|
-
# Convert time to float hours
|
|
679
|
-
float_time = hours + minutes / 60 + seconds / 3600
|
|
680
|
-
|
|
681
|
-
return float_time
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
@staticmethod
|
|
685
|
-
def get_from_iso_utc_time(
|
|
686
|
-
name: str,
|
|
687
|
-
iso_utc_time: str,
|
|
688
|
-
city: str = "Greenwich",
|
|
689
|
-
nation: str = "GB",
|
|
690
|
-
tz_str: str = "Etc/GMT",
|
|
691
|
-
online: bool = False,
|
|
692
|
-
lng: Union[int, float] = 0,
|
|
693
|
-
lat: Union[int, float] = 51.5074,
|
|
694
|
-
geonames_username: str = DEFAULT_GEONAMES_USERNAME,
|
|
695
|
-
zodiac_type: ZodiacType = DEFAULT_ZODIAC_TYPE,
|
|
696
|
-
disable_chiron_and_lilith: bool = False,
|
|
697
|
-
sidereal_mode: Union[SiderealMode, None] = None,
|
|
698
|
-
houses_system_identifier: HousesSystemIdentifier = DEFAULT_HOUSES_SYSTEM_IDENTIFIER,
|
|
699
|
-
perspective_type: PerspectiveType = DEFAULT_PERSPECTIVE_TYPE
|
|
700
|
-
|
|
701
|
-
) -> "AstrologicalSubject":
|
|
702
|
-
"""
|
|
703
|
-
Creates an AstrologicalSubject object from an iso formatted UTC time.
|
|
704
|
-
This method is offline by default, set online=True to fetch the timezone and coordinates from geonames.
|
|
705
|
-
|
|
706
|
-
Args:
|
|
707
|
-
- name (str): The name of the subject.
|
|
708
|
-
- iso_utc_time (str): The iso formatted UTC time.
|
|
709
|
-
- city (str, optional): City or location of birth. Defaults to "Greenwich".
|
|
710
|
-
- nation (str, optional): Nation of birth. Defaults to "GB".
|
|
711
|
-
- tz_str (str, optional): Timezone of the birth location. Defaults to "Etc/GMT".
|
|
712
|
-
- online (bool, optional): Sets if you want to use the online mode, which fetches the timezone and coordinates from geonames.
|
|
713
|
-
If you already have the coordinates and timezone, set this to False. Defaults to False.
|
|
714
|
-
- lng (Union[int, float], optional): Longitude of the birth location. Defaults to 0 (Greenwich, London).
|
|
715
|
-
- lat (Union[int, float], optional): Latitude of the birth location. Defaults to 51.5074 (Greenwich, London).
|
|
716
|
-
- geonames_username (str, optional): The username for the geonames API. Note: Change this to your own username to avoid rate limits!
|
|
717
|
-
You can get one for free here: https://www.geonames.org/login
|
|
718
|
-
- zodiac_type (ZodiacType, optional): The zodiac type to use. Defaults to "Tropic".
|
|
719
|
-
- disable_chiron_and_lilith: boolean representing if Chiron and Lilith should be disabled. Default is False.
|
|
720
|
-
Chiron calculation can create some issues with the Swiss Ephemeris when the date is too far in the past.
|
|
721
|
-
- sidereal_mode (SiderealMode, optional): Also known as Ayanamsa.
|
|
722
|
-
The mode to use for the sidereal zodiac, according to the Swiss Ephemeris.
|
|
723
|
-
Defaults to None.
|
|
724
|
-
Available modes are visible in the SiderealMode Literal.
|
|
725
|
-
- houses_system_identifier (HousesSystemIdentifier, optional): The system to use for the calculation of the houses.
|
|
726
|
-
Defaults to "P" (Placidus).
|
|
727
|
-
Available systems are visible in the HousesSystemIdentifier Literal.
|
|
728
|
-
- perspective_type (PerspectiveType, optional): The perspective to use for the calculation of the chart.
|
|
729
|
-
Defaults to "Apparent Geocentric".
|
|
730
|
-
|
|
731
|
-
Returns:
|
|
732
|
-
- AstrologicalSubject: The AstrologicalSubject object.
|
|
733
|
-
"""
|
|
734
|
-
dt = datetime.fromisoformat(iso_utc_time)
|
|
735
|
-
|
|
736
|
-
if online == True:
|
|
737
|
-
if geonames_username == DEFAULT_GEONAMES_USERNAME:
|
|
738
|
-
logging.warning(GEONAMES_DEFAULT_USERNAME_WARNING)
|
|
739
|
-
|
|
740
|
-
geonames = FetchGeonames(
|
|
741
|
-
city,
|
|
742
|
-
nation,
|
|
743
|
-
username=geonames_username,
|
|
744
|
-
)
|
|
745
|
-
|
|
746
|
-
city_data: dict[str, str] = geonames.get_serialized_data()
|
|
747
|
-
lng = float(city_data["lng"])
|
|
748
|
-
lat = float(city_data["lat"])
|
|
749
|
-
|
|
750
|
-
subject = AstrologicalSubject(
|
|
751
|
-
name=name,
|
|
752
|
-
year=dt.year,
|
|
753
|
-
month=dt.month,
|
|
754
|
-
day=dt.day,
|
|
755
|
-
hour=dt.hour,
|
|
756
|
-
minute=dt.minute,
|
|
757
|
-
city=city,
|
|
758
|
-
nation=city,
|
|
759
|
-
lng=lng,
|
|
760
|
-
lat=lat,
|
|
761
|
-
tz_str=tz_str,
|
|
762
|
-
online=False,
|
|
763
|
-
geonames_username=geonames_username,
|
|
764
|
-
zodiac_type=zodiac_type,
|
|
765
|
-
sidereal_mode=sidereal_mode,
|
|
766
|
-
houses_system_identifier=houses_system_identifier,
|
|
767
|
-
perspective_type=perspective_type,
|
|
768
|
-
disable_chiron_and_lilith=disable_chiron_and_lilith
|
|
769
|
-
)
|
|
770
|
-
|
|
771
|
-
return subject
|
|
772
|
-
|
|
773
|
-
if __name__ == "__main__":
|
|
774
|
-
import json
|
|
775
|
-
from kerykeion.utilities import setup_logging
|
|
776
|
-
|
|
777
|
-
setup_logging(level="debug")
|
|
778
|
-
|
|
779
|
-
# With Chiron enabled
|
|
780
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US")
|
|
781
|
-
print(json.loads(johnny.json(dump=True)))
|
|
782
|
-
|
|
783
|
-
print('\n')
|
|
784
|
-
print(johnny.chiron)
|
|
785
|
-
|
|
786
|
-
# With Chiron disabled
|
|
787
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", disable_chiron=True)
|
|
788
|
-
print(json.loads(johnny.json(dump=True)))
|
|
789
|
-
|
|
790
|
-
print('\n')
|
|
791
|
-
print(johnny.chiron)
|
|
792
|
-
|
|
793
|
-
# With Sidereal Zodiac
|
|
794
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", zodiac_type="Sidereal", sidereal_mode="LAHIRI")
|
|
795
|
-
print(johnny.json(dump=True, indent=2))
|
|
796
|
-
|
|
797
|
-
# With Morinus Houses
|
|
798
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", houses_system_identifier="M")
|
|
799
|
-
print(johnny.json(dump=True, indent=2))
|
|
800
|
-
|
|
801
|
-
# With True Geocentric Perspective
|
|
802
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", perspective_type="True Geocentric")
|
|
803
|
-
print(johnny.json(dump=True, indent=2))
|
|
804
|
-
|
|
805
|
-
# With Heliocentric Perspective
|
|
806
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", perspective_type="Heliocentric")
|
|
807
|
-
print(johnny.json(dump=True, indent=2))
|
|
808
|
-
|
|
809
|
-
# With Topocentric Perspective
|
|
810
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", perspective_type="Topocentric")
|
|
811
|
-
|
|
812
|
-
# Test Mean Lilith
|
|
813
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", disable_chiron_and_lilith=True)
|
|
814
|
-
print(johnny.mean_lilith)
|
|
815
|
-
|
|
816
|
-
# Offline mode
|
|
817
|
-
johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", online=False, tz_str="America/New_York", lng=-87.1111, lat=37.7711)
|
|
818
|
-
print(johnny.json(dump=True, indent=2))
|