kerykeion 4.8.1__py3-none-any.whl → 4.14.2__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/enums.py CHANGED
@@ -15,6 +15,7 @@ class Planets(Enum):
15
15
  CHIRON = "Chiron"
16
16
  TRUE_NODE = "True_Node"
17
17
  MEAN_NODE = "Mean_Node"
18
+ MEAN_LILITH = "Mean_Lilith"
18
19
 
19
20
 
20
21
  class Aspects(Enum):
@@ -0,0 +1,174 @@
1
+ from kerykeion import AstrologicalSubject
2
+ from kerykeion.astrological_subject import DEFAULT_HOUSES_SYSTEM_IDENTIFIER, DEFAULT_PERSPECTIVE_TYPE, DEFAULT_ZODIAC_TYPE
3
+ from kerykeion.kr_types import EphemerisDictModel
4
+ from kerykeion.kr_types import SiderealMode, HousesSystemIdentifier, PerspectiveType, ZodiacType
5
+ from datetime import datetime, timedelta
6
+ from typing import Literal, Union
7
+ import logging
8
+
9
+
10
+ class EphemerisDataFactory:
11
+ """
12
+ This class is used to generate ephemeris data for a given date range.
13
+
14
+ Parameters:
15
+ - start_datetime: datetime object representing the start date and time.
16
+ - end_datetime: datetime object representing the end date and time.
17
+ - step_type: string representing the step type. It can be "days", "hours", or "minutes". Default is "days".
18
+ - step: integer representing the step value. Default is 1.
19
+ - lat: float representing the latitude. Default is 51.4769 (Greenwich).
20
+ - lng: float representing the longitude. Default is 0.0005 (Greenwich).
21
+ - tz_str: string representing the timezone. Default is "Etc/UTC".
22
+ - is_dst: boolean representing if daylight saving time is active. Default is False.
23
+ - disable_chiron_and_lilith: boolean representing if Chiron and Lilith should be disabled. Default is False.
24
+ - zodiac_type: ZodiacType object representing the zodiac type. Default is DEFAULT_ZODIAC_TYPE.
25
+ - sidereal_mode: SiderealMode object representing the sidereal mode. Default is None.
26
+ - houses_system_identifier: HousesSystemIdentifier object representing the houses system identifier. Default is DEFAULT_HOUSES_SYSTEM_IDENTIFIER.
27
+ - perspective_type: PerspectiveType object representing the perspective type. Default is DEFAULT_PERSPECTIVE_TYPE.
28
+ - max_days: integer representing the maximum number of days.
29
+ Set it to None to disable the check. Default is 730.
30
+ - max_hours: integer representing the maximum number of hours.
31
+ Set it to None to disable the check. Default is 8760.
32
+ - max_minutes: integer representing the maximum number of minutes.
33
+ Set it to None to disable the check. Default is 525600.
34
+
35
+ Raises:
36
+ - ValueError: if the step type is invalid.
37
+ - ValueError: if the number of days, hours, or minutes is greater than the maximum allowed.
38
+ """
39
+
40
+ def __init__(
41
+ self,
42
+ start_datetime: datetime,
43
+ end_datetime: datetime,
44
+ step_type: Literal["days", "hours", "minutes"] = "days",
45
+ step: int = 1,
46
+ lat: float = 51.4769,
47
+ lng: float = 0.0005,
48
+ tz_str: str = "Etc/UTC",
49
+ is_dst: bool = False,
50
+ disable_chiron_and_lilith: bool = False,
51
+ zodiac_type: ZodiacType = DEFAULT_ZODIAC_TYPE,
52
+ sidereal_mode: Union[SiderealMode, None] = None,
53
+ houses_system_identifier: HousesSystemIdentifier = DEFAULT_HOUSES_SYSTEM_IDENTIFIER,
54
+ perspective_type: PerspectiveType = DEFAULT_PERSPECTIVE_TYPE,
55
+ max_days: int = 730,
56
+ max_hours: int = 8760,
57
+ max_minutes: int = 525600,
58
+ ):
59
+ self.start_datetime = start_datetime
60
+ self.end_datetime = end_datetime
61
+ self.step_type = step_type
62
+ self.step = step
63
+ self.lat = lat
64
+ self.lng = lng
65
+ self.tz_str = tz_str
66
+ self.is_dst = is_dst
67
+ self.disable_chiron_and_lilith = disable_chiron_and_lilith
68
+ self.zodiac_type = zodiac_type
69
+ self.sidereal_mode = sidereal_mode
70
+ self.houses_system_identifier = houses_system_identifier
71
+ self.perspective_type = perspective_type
72
+ self.max_days = max_days
73
+ self.max_hours = max_hours
74
+ self.max_minutes = max_minutes
75
+
76
+ self.dates_list = []
77
+ if self.step_type == "days":
78
+ self.dates_list = [self.start_datetime + timedelta(days=i) for i in range((self.end_datetime - self.start_datetime).days)]
79
+ if max_days and (len(self.dates_list) > max_days):
80
+ raise ValueError(f"Too many days: {len(self.dates_list)} > {self.max_days}. To prevent this error, set max_days to a higher value or reduce the date range.")
81
+
82
+ elif self.step_type == "hours":
83
+ self.dates_list = [self.start_datetime + timedelta(hours=i) for i in range((self.end_datetime - self.start_datetime).days * 24)]
84
+ if max_hours and (len(self.dates_list) > max_hours):
85
+ raise ValueError(f"Too many hours: {len(self.dates_list)} > {self.max_hours}. To prevent this error, set max_hours to a higher value or reduce the date range.")
86
+
87
+ elif self.step_type == "minutes":
88
+ self.dates_list = [self.start_datetime + timedelta(minutes=i) for i in range((self.end_datetime - self.start_datetime).days * 24 * 60)]
89
+ if max_minutes and (len(self.dates_list) > max_minutes):
90
+ raise ValueError(f"Too many minutes: {len(self.dates_list)} > {self.max_minutes}. To prevent this error, set max_minutes to a higher value or reduce the date range.")
91
+
92
+ else:
93
+ raise ValueError(f"Invalid step type: {self.step_type}")
94
+
95
+ if not self.dates_list:
96
+ raise ValueError("No dates found. Check the date range and step values.")
97
+
98
+ if len(self.dates_list) > 1000:
99
+ logging.warning(f"Large number of dates: {len(self.dates_list)}. The calculation may take a while.")
100
+
101
+ def get_ephemeris_data(self) -> list:
102
+ """
103
+ Generate ephemeris data for the specified date range.
104
+ The data is structured as a list of dictionaries, where each dictionary contains the date, planets, and houses data.
105
+ Eg. [{"date": "2020-01-01T00:00:00", "planets": [{...}, {...}, ...], "houses": [{...}, {...}, ...]}, ...]
106
+
107
+ Args:
108
+ - as_model: boolean representing if the ephemeris data should be returned as model instances. Default is False.
109
+ - as_dict: boolean representing if the ephemeris data should be returned as dictionaries. Default is False.
110
+
111
+ Returns:
112
+ - list of dictionaries representing the ephemeris data.
113
+ """
114
+ ephemeris_data_list = []
115
+ for date in self.dates_list:
116
+ subject = AstrologicalSubject(
117
+ year=date.year,
118
+ month=date.month,
119
+ day=date.day,
120
+ hour=date.hour,
121
+ minute=date.minute,
122
+ lng=self.lng,
123
+ lat=self.lat,
124
+ tz_str=self.tz_str,
125
+ city="Placeholder",
126
+ nation="Placeholder",
127
+ online=False,
128
+ disable_chiron_and_lilith=self.disable_chiron_and_lilith,
129
+ zodiac_type=self.zodiac_type,
130
+ sidereal_mode=self.sidereal_mode,
131
+ houses_system_identifier=self.houses_system_identifier,
132
+ perspective_type=self.perspective_type,
133
+ is_dst=self.is_dst,
134
+ )
135
+
136
+ ephemeris_data_list.append({"date": date.isoformat(), "planets": subject.planets_list, "houses": subject.houses_list})
137
+
138
+ return ephemeris_data_list
139
+
140
+ def get_ephemeris_data_as_model(self) -> list[EphemerisDictModel]:
141
+ """
142
+ Generate ephemeris data as model instances for the specified date range.
143
+ The data is structured as a list of EphemerisDictModel instances.
144
+
145
+ Returns:
146
+ - list of EphemerisDictModel instances representing the ephemeris data.
147
+ """
148
+ return [EphemerisDictModel(**data) for data in self.get_ephemeris_data()]
149
+
150
+
151
+ if "__main__" == __name__:
152
+ start_date = datetime.fromisoformat("2020-01-01")
153
+ end_date = datetime.fromisoformat("2020-01-03")
154
+
155
+ factory = EphemerisDataFactory(
156
+ start_datetime=start_date,
157
+ end_datetime=end_date,
158
+ step_type="minutes",
159
+ step=1,
160
+ lat=37.9838,
161
+ lng=23.7275,
162
+ tz_str="Europe/Athens",
163
+ is_dst=False,
164
+ max_hours=None,
165
+ max_minutes=None,
166
+ max_days=None,
167
+ )
168
+
169
+ ephemeris_data = factory.get_ephemeris_data_as_model()
170
+ print(ephemeris_data[0])
171
+ print(len(ephemeris_data))
172
+
173
+ for ephe in ephemeris_data:
174
+ print(ephe.planets[0]["abs_pos"])
@@ -79,12 +79,11 @@ class FetchGeonames:
79
79
 
80
80
  params = {
81
81
  "q": city_name,
82
- "contry": country_code,
82
+ "country": country_code,
83
83
  "username": self.username,
84
84
  "maxRows": 1,
85
85
  "style": "SHORT",
86
- "featureClass": "A",
87
- "featureClass": "P",
86
+ "featureClass": ["A", "P"],
88
87
  }
89
88
 
90
89
  prepared_request = Request("GET", self.base_url, params=params).prepare()
@@ -6,20 +6,15 @@ class ChartTemplateDictionary(TypedDict):
6
6
  degreeRing: str
7
7
  first_circle: str
8
8
  second_circle: str
9
- c3: str
10
- c3style: str
9
+ third_circle: str
11
10
  makeAspects: str
12
11
  makeAspectGrid: str
13
- makePatterns: str
14
12
  chart_height: float
15
13
  chart_width: float
16
- circleX: str
17
- circleY: str
18
- svgWidth: str
19
- svgHeight: str
20
14
  viewbox: str
21
15
  stringTitle: str
22
16
  stringName: str
17
+ bottomLeft0: str
23
18
  bottomLeft1: str
24
19
  bottomLeft2: str
25
20
  bottomLeft3: str
@@ -41,7 +36,7 @@ class ChartTemplateDictionary(TypedDict):
41
36
  # Background color of the chart
42
37
  paper_color_1: str
43
38
 
44
- # Planets colors, from 1 to 15 (0 is the Sun)
39
+ # Planets colors, from 0 to 16 (0 is the Sun)
45
40
  planets_color_0: str
46
41
  planets_color_1: str
47
42
  planets_color_2: str
@@ -58,6 +53,7 @@ class ChartTemplateDictionary(TypedDict):
58
53
  planets_color_13: str
59
54
  planets_color_14: str
60
55
  planets_color_15: str
56
+ planets_color_16: str
61
57
 
62
58
  # Zodiac colors, from 0 to 11 (0 is Aries)
63
59
  zodiac_color_0: str
@@ -86,7 +82,6 @@ class ChartTemplateDictionary(TypedDict):
86
82
  orb_color_150: str
87
83
  orb_color_180: str
88
84
 
89
- cfgZoom: str
90
85
  cfgRotate: str
91
86
  cfgTranslate: str
92
87
  makeZodiac: str
@@ -1,68 +1,101 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """
3
- This is part of Kerykeion (C) 2024 Giacomo Battaglia
3
+ This is part of Kerykeion (C) 2024 Giacomo Battaglia
4
4
  """
5
-
6
-
7
5
  from typing import Literal
8
6
 
9
- # Zodiac Types:
7
+
10
8
  ZodiacType = Literal["Tropic", "Sidereal"]
9
+ """Literal type for Zodiac Types"""
10
+
11
+
12
+ Sign = Literal["Ari", "Tau", "Gem", "Can", "Leo", "Vir", "Lib", "Sco", "Sag", "Cap", "Aqu", "Pis"]
13
+ """Literal type for Zodiac Signs"""
14
+
15
+
16
+ SignNumbers = Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
17
+ """Literal type for Zodiac Sign Numbers, the signs are numbered in order starting from Aries (0) to Pisces (11)"""
18
+
19
+
20
+ Houses = Literal["First_House", "Second_House", "Third_House", "Fourth_House", "Fifth_House", "Sixth_House", "Seventh_House", "Eighth_House", "Ninth_House", "Tenth_House", "Eleventh_House", "Twelfth_House"]
21
+ """Literal type for Houses"""
22
+
23
+
24
+ HouseNumbers = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
25
+ """Literal type for House Numbers, starting from the First House (1) to the Twelfth House (12)"""
26
+
27
+
28
+ Planet = Literal["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", "Mean_Node", "True_Node", "Chiron", "Mean_Lilith"]
29
+ """Literal type for Planets"""
11
30
 
12
- # Sings:
13
- Sign = Literal[
14
- "Ari", "Tau", "Gem", "Can", "Leo", "Vir", "Lib", "Sco", "Sag", "Cap", "Aqu", "Pis"
15
- ]
16
-
17
- Houses = Literal[
18
- "First_House",
19
- "Second_House",
20
- "Third_House",
21
- "Fourth_House",
22
- "Fifth_House",
23
- "Sixth_House",
24
- "Seventh_House",
25
- "Eighth_House",
26
- "Ninth_House",
27
- "Tenth_House",
28
- "Eleventh_House",
29
- "Twelfth_House",
30
- ]
31
-
32
- Planet = Literal[
33
- "Sun",
34
- "Moon",
35
- "Mercury",
36
- "Venus",
37
- "Mars",
38
- "Jupiter",
39
- "Saturn",
40
- "Uranus",
41
- "Neptune",
42
- "Pluto",
43
- "Mean_Node",
44
- "True_Node",
45
- "Chiron",
46
- ]
47
31
 
48
32
  Element = Literal["Air", "Fire", "Earth", "Water"]
33
+ """Literal type for Elements"""
34
+
35
+
36
+ Quality = Literal["Cardinal", "Fixed", "Mutable"]
37
+ """Literal type for Qualities"""
49
38
 
50
- Quality = Literal[
51
- "Cardinal",
52
- "Fixed",
53
- "Mutable",
54
- ]
55
39
 
56
40
  ChartType = Literal["Natal", "ExternalNatal", "Synastry", "Transit"]
41
+ """Literal type for Chart Types"""
42
+
43
+
44
+ PointType = Literal["Planet", "House"]
45
+ """Literal type for Point Types"""
46
+
57
47
 
58
48
  LunarPhaseEmoji = Literal["🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"]
59
- LunarPhaseName = Literal[
60
- "New Moon",
61
- "Waxing Crescent",
62
- "First Quarter",
63
- "Waxing Gibbous",
64
- "Full Moon",
65
- "Waning Gibbous",
66
- "Last Quarter",
67
- "Waning Crescent"
68
- ]
49
+ """Literal type for Lunar Phases Emoji"""
50
+
51
+
52
+ LunarPhaseName = Literal["New Moon", "Waxing Crescent", "First Quarter", "Waxing Gibbous", "Full Moon", "Waning Gibbous", "Last Quarter", "Waning Crescent"]
53
+ """Literal type for Lunar Phases Name"""
54
+
55
+
56
+ SiderealMode = Literal["FAGAN_BRADLEY", "LAHIRI", "DELUCE", "RAMAN", "USHASHASHI", "KRISHNAMURTI", "DJWHAL_KHUL", "YUKTESHWAR", "JN_BHASIN", "BABYL_KUGLER1", "BABYL_KUGLER2", "BABYL_KUGLER3", "BABYL_HUBER", "BABYL_ETPSC", "ALDEBARAN_15TAU", "HIPPARCHOS", "SASSANIAN", "J2000", "J1900", "B1950"]
57
+ """Literal type for Sidereal Modes, as known as Ayanamsa"""
58
+
59
+
60
+ HousesSystemIdentifier = Literal["A", "B", "C", "D", "F", "H", "I", "i", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y"]
61
+ """
62
+ Literal type for Houses Systems:
63
+
64
+ A = equal
65
+ B = Alcabitius
66
+ C = Campanus
67
+ D = equal (MC)
68
+ F = Carter poli-equ.
69
+ H = horizon/azimut
70
+ I = Sunshine
71
+ i = Sunshine/alt.
72
+ K = Koch
73
+ L = Pullen SD
74
+ M = Morinus
75
+ N = equal/1=Aries
76
+ O = Porphyry
77
+ P = Placidus
78
+ Q = Pullen SR
79
+ R = Regiomontanus
80
+ S = Sripati
81
+ T = Polich/Page
82
+ U = Krusinski-Pisa-Goelzer
83
+ V = equal/Vehlow
84
+ W = equal/whole sign
85
+ X = axial rotation system/Meridian houses
86
+ Y = APC houses
87
+
88
+ Usually the standard is Placidus (P)
89
+ """
90
+
91
+
92
+ PerspectiveType = Literal["Apparent Geocentric", "Heliocentric", "Topocentric", "True Geocentric"]
93
+ """
94
+ Literal type for perspective types.
95
+ - "Apparent Geocentric": Earth-centered, apparent positions.
96
+ - "Heliocentric": Sun-centered.
97
+ - "Topocentric": Observer's location on Earth's surface.
98
+ - "True Geocentric": Earth-centered, true positions.
99
+
100
+ Usually the standard is "Apparent Geocentric"
101
+ """
@@ -4,42 +4,31 @@
4
4
  """
5
5
 
6
6
 
7
- from typing import Literal, Union, Optional
7
+ from typing import Union, Optional
8
8
  from pydantic import BaseModel
9
9
 
10
- from kerykeion.kr_types import LunarPhaseEmoji, LunarPhaseName, Planet, Houses, Quality, Element, Sign, ZodiacType
11
-
12
-
13
- class LunarPhaseModel(BaseModel):
14
- degrees_between_s_m: Union[float, int]
15
- moon_phase: int
16
- sun_phase: int
17
- moon_emoji: LunarPhaseEmoji
18
- moon_phase_name: LunarPhaseName
19
-
20
- def __str__(self):
21
- return (
22
- super()
23
- .model_dump(
24
- exclude_none=True,
25
- exclude_unset=True,
26
- exclude_defaults=True,
27
- by_alias=False,
28
- )
29
- .__str__()
30
- )
31
-
32
- def __repr__(self):
33
- return (
34
- super()
35
- .model_dump(
36
- exclude_none=True,
37
- exclude_unset=True,
38
- exclude_defaults=True,
39
- by_alias=False,
40
- )
41
- .__str__()
42
- )
10
+ from kerykeion.kr_types import (
11
+ LunarPhaseEmoji,
12
+ LunarPhaseName,
13
+ Planet,
14
+ Houses,
15
+ Quality,
16
+ Element,
17
+ Sign,
18
+ ZodiacType,
19
+ SignNumbers,
20
+ HouseNumbers,
21
+ PointType,
22
+ SiderealMode,
23
+ HousesSystemIdentifier,
24
+ Houses,
25
+ )
26
+
27
+
28
+ class SubscriptableBaseModel(BaseModel):
29
+ """
30
+ Pydantic BaseModel with subscriptable support, so you can access the fields as if they were a dictionary.
31
+ """
43
32
 
44
33
  def __getitem__(self, key):
45
34
  return getattr(self, key)
@@ -54,7 +43,15 @@ class LunarPhaseModel(BaseModel):
54
43
  return getattr(self, key, default)
55
44
 
56
45
 
57
- class KerykeionPointModel(BaseModel):
46
+ class LunarPhaseModel(SubscriptableBaseModel):
47
+ degrees_between_s_m: Union[float, int]
48
+ moon_phase: int
49
+ sun_phase: int
50
+ moon_emoji: LunarPhaseEmoji
51
+ moon_phase_name: LunarPhaseName
52
+
53
+
54
+ class KerykeionPointModel(SubscriptableBaseModel):
58
55
  """
59
56
  Kerykeion Point Model
60
57
  """
@@ -63,52 +60,16 @@ class KerykeionPointModel(BaseModel):
63
60
  quality: Quality
64
61
  element: Element
65
62
  sign: Sign
66
- sign_num: Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
63
+ sign_num: SignNumbers
67
64
  position: float
68
65
  abs_pos: float
69
66
  emoji: str
70
- point_type: Literal["Planet", "House"]
71
- house: Optional[Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]] = None
67
+ point_type: PointType
68
+ house: Optional[Houses] = None
72
69
  retrograde: Optional[bool] = None
73
70
 
74
- def __str__(self):
75
- return (
76
- super()
77
- .model_dump(
78
- exclude_none=True,
79
- exclude_unset=True,
80
- exclude_defaults=True,
81
- by_alias=False,
82
- )
83
- .__str__()
84
- )
85
-
86
- def __repr__(self):
87
- return (
88
- super()
89
- .model_dump(
90
- exclude_none=True,
91
- exclude_unset=True,
92
- exclude_defaults=True,
93
- by_alias=False,
94
- )
95
- .__str__()
96
- )
97
-
98
- def __getitem__(self, key):
99
- return getattr(self, key)
100
-
101
- def __setitem__(self, key, value):
102
- setattr(self, key, value)
103
-
104
- def __delitem__(self, key):
105
- delattr(self, key)
106
-
107
- def get(self, key, default):
108
- return getattr(self, key, default)
109
-
110
71
 
111
- class AstrologicalSubjectModel(BaseModel):
72
+ class AstrologicalSubjectModel(SubscriptableBaseModel):
112
73
  # Data
113
74
  name: str
114
75
  year: int
@@ -122,10 +83,19 @@ class AstrologicalSubjectModel(BaseModel):
122
83
  lat: float
123
84
  tz_str: str
124
85
  zodiac_type: ZodiacType
125
- local_time: float
126
- utc_time: float
86
+ sidereal_mode: Union[SiderealMode, None]
87
+ houses_system_identifier: HousesSystemIdentifier
88
+ houses_system_name: str
89
+ perspective_type: str
90
+ iso_formatted_local_datetime: str
91
+ iso_formatted_utc_datetime: str
127
92
  julian_day: float
128
93
 
94
+ # Deprecated properties -->
95
+ utc_time: float
96
+ local_time: float
97
+ # <-- Deprecated properties
98
+
129
99
  # Planets
130
100
  sun: KerykeionPointModel
131
101
  moon: KerykeionPointModel
@@ -137,7 +107,10 @@ class AstrologicalSubjectModel(BaseModel):
137
107
  uranus: KerykeionPointModel
138
108
  neptune: KerykeionPointModel
139
109
  pluto: KerykeionPointModel
110
+
111
+ # Optional Planets:
140
112
  chiron: Union[KerykeionPointModel, None]
113
+ mean_lilith: Union[KerykeionPointModel, None]
141
114
 
142
115
  # Houses
143
116
  first_house: KerykeionPointModel
@@ -160,23 +133,28 @@ class AstrologicalSubjectModel(BaseModel):
160
133
  # Lunar Phase
161
134
  lunar_phase: LunarPhaseModel
162
135
 
163
-
164
- if __name__ == "__main__":
165
- from kerykeion.utilities import setup_logging
166
-
167
- setup_logging(level="debug")
168
-
169
- sun = KerykeionPointModel(
170
- name="Sun",
171
- element="Air",
172
- quality="Fixed",
173
- sign="Aqu",
174
- sign_num=1,
175
- position=0,
176
- abs_pos=12.123123,
177
- emoji="♈",
178
- point_type="Planet",
179
- )
180
-
181
- print(sun.model_dump_json())
182
- print(sun)
136
+ # Lists
137
+ # houses_list: list[KerykeionPointModel]
138
+ # planets_list: list[KerykeionPointModel]
139
+ # planets_degrees_ut: list[float]
140
+ # houses_degree_ut: list[float]
141
+
142
+
143
+ class EphemerisDictModel(SubscriptableBaseModel):
144
+ date: str
145
+ planets: list[KerykeionPointModel]
146
+ houses: list[KerykeionPointModel]
147
+
148
+
149
+ class AspectModel(SubscriptableBaseModel):
150
+ p1_name: str
151
+ p1_abs_pos: float
152
+ p2_name: str
153
+ p2_abs_pos: float
154
+ aspect: str
155
+ orbit: float
156
+ aspect_degrees: int
157
+ aid: int
158
+ diff: float
159
+ p1: int
160
+ p2: int