kerykeion 5.0.0a10__py3-none-any.whl → 5.0.0a11__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.

@@ -1,6 +1,44 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """
3
- This is part of Kerykeion (C) 2025 Giacomo Battaglia
3
+ Relationship Score Factory Module
4
+
5
+ This module calculates relationship scores between two astrological subjects using the
6
+ Ciro Discepolo method. It analyzes synastry aspects to generate numerical compatibility
7
+ scores with descriptive categories.
8
+
9
+ Key Features:
10
+ - Point-based scoring system using synastry aspects
11
+ - Configurable major/minor aspect filtering
12
+ - Orbital precision weighting
13
+ - Categorical score descriptions
14
+
15
+ Score Categories:
16
+ - 0-5: Minimal relationship
17
+ - 5-10: Medium relationship
18
+ - 10-15: Important relationship
19
+ - 15-20: Very important relationship
20
+ - 20-30: Exceptional relationship
21
+ - 30+: Rare exceptional relationship
22
+
23
+ Classes:
24
+ RelationshipScoreFactory: Main factory for calculating relationship scores
25
+
26
+ Example:
27
+ >>> from kerykeion import AstrologicalSubjectFactory
28
+ >>> from kerykeion.relationship_score_factory import RelationshipScoreFactory
29
+ >>>
30
+ >>> person1 = AstrologicalSubjectFactory.from_birth_data("John", 1990, 5, 15, 12, 0, "New York", "US")
31
+ >>> person2 = AstrologicalSubjectFactory.from_birth_data("Jane", 1988, 8, 22, 14, 30, "London", "GB")
32
+ >>> factory = RelationshipScoreFactory(person1, person2)
33
+ >>> score = factory.get_relationship_score()
34
+ >>> print(f"Score: {score.score_value} ({score.score_description})")
35
+
36
+ Reference:
37
+ Ciro Discepolo Method: http://www.cirodiscepolo.it/Articoli/Discepoloele.htm
38
+
39
+ Author: Giacomo Battaglia
40
+ Copyright: (C) 2025 Kerykeion Project
41
+ License: AGPL-3.0
4
42
  """
5
43
 
6
44
  from kerykeion import AstrologicalSubjectFactory
@@ -22,21 +60,26 @@ VENUS_MARS_ASPECT_POINTS = 4
22
60
 
23
61
  class RelationshipScoreFactory:
24
62
  """
25
- Calculates the relevance of the relationship between two subjects using the Ciro Discepolo method.
63
+ Calculates relationship scores between two subjects using the Ciro Discepolo method.
26
64
 
27
- Results:
28
- - 0 to 5: Minimal relationship
29
- - 5 to 10: Medium relationship
30
- - 10 to 15: Important relationship
31
- - 15 to 20: Very important relationship
32
- - 20 to 35: Exceptional relationship
33
- - 30 and above: Rare Exceptional relationship
65
+ The scoring system evaluates synastry aspects between planetary positions to generate
66
+ numerical compatibility scores with categorical descriptions.
34
67
 
35
- Documentation: http://www.cirodiscepolo.it/Articoli/Discepoloele.htm
68
+ Score Ranges:
69
+ - 0-5: Minimal relationship
70
+ - 5-10: Medium relationship
71
+ - 10-15: Important relationship
72
+ - 15-20: Very important relationship
73
+ - 20-30: Exceptional relationship
74
+ - 30+: Rare exceptional relationship
36
75
 
37
76
  Args:
38
- first_subject (AstrologicalSubjectModel): First subject instance
39
- second_subject (AstrologicalSubjectModel): Second subject instance
77
+ first_subject (AstrologicalSubjectModel): First astrological subject
78
+ second_subject (AstrologicalSubjectModel): Second astrological subject
79
+ use_only_major_aspects (bool, optional): Filter to major aspects only. Defaults to True.
80
+
81
+ Reference:
82
+ http://www.cirodiscepolo.it/Articoli/Discepoloele.htm
40
83
  """
41
84
 
42
85
  SCORE_MAPPING = [
@@ -68,7 +111,10 @@ class RelationshipScoreFactory:
68
111
 
69
112
  def _evaluate_destiny_sign(self):
70
113
  """
71
- Evaluates if the subjects share the same sun sign quality and adds points if true.
114
+ Checks if subjects share the same sun sign quality and adds points.
115
+
116
+ Adds 5 points if both subjects have sun signs with matching quality
117
+ (cardinal, fixed, or mutable).
72
118
  """
73
119
  if self.first_subject.sun["quality"] == self.second_subject.sun["quality"]: # type: ignore
74
120
  self.is_destiny_sign = True
@@ -77,11 +123,11 @@ class RelationshipScoreFactory:
77
123
 
78
124
  def _evaluate_aspect(self, aspect, points):
79
125
  """
80
- Evaluates an aspect and adds points to the score.
126
+ Processes an aspect and adds points to the total score.
81
127
 
82
128
  Args:
83
- aspect (dict): Aspect information.
84
- points (int): Points to add.
129
+ aspect (dict): Aspect data containing planetary positions and geometry
130
+ points (int): Points to add to the total score
85
131
  """
86
132
  if self.use_only_major_aspects and aspect["aspect"] not in self.MAJOR_ASPECTS:
87
133
  return
@@ -99,12 +145,12 @@ class RelationshipScoreFactory:
99
145
 
100
146
  def _evaluate_sun_sun_main_aspect(self, aspect):
101
147
  """
102
- Evaluates Sun-Sun main aspects and adds points accordingly:
103
- - 8 points for conjunction/opposition/square
104
- - 11 points if the aspect's orbit is <= 2 degrees
148
+ Evaluates Sun-Sun conjunction, opposition, or square aspects.
149
+
150
+ Adds 8 points for standard orbs, 11 points for tight orbs (≤2°).
105
151
 
106
152
  Args:
107
- aspect (dict): Aspect information.
153
+ aspect (dict): Aspect data
108
154
  """
109
155
  if aspect["p1_name"] == "Sun" and aspect["p2_name"] == "Sun" and aspect["aspect"] in {"conjunction", "opposition", "square"}:
110
156
  points = MAJOR_ASPECT_POINTS_HIGH_PRECISION if aspect["orbit"] <= HIGH_PRECISION_ORBIT_THRESHOLD else MAJOR_ASPECT_POINTS_STANDARD
@@ -112,12 +158,12 @@ class RelationshipScoreFactory:
112
158
 
113
159
  def _evaluate_sun_moon_conjunction(self, aspect):
114
160
  """
115
- Evaluates Sun-Moon conjunctions and adds points accordingly:
116
- - 8 points for conjunction
117
- - 11 points if the aspect's orbit is <= 2 degrees
161
+ Evaluates Sun-Moon conjunction aspects.
162
+
163
+ Adds 8 points for standard orbs, 11 points for tight orbs (≤2°).
118
164
 
119
165
  Args:
120
- aspect (dict): Aspect information.
166
+ aspect (dict): Aspect data
121
167
  """
122
168
  if {aspect["p1_name"], aspect["p2_name"]} == {"Moon", "Sun"} and aspect["aspect"] == "conjunction":
123
169
  points = MAJOR_ASPECT_POINTS_HIGH_PRECISION if aspect["orbit"] <= HIGH_PRECISION_ORBIT_THRESHOLD else MAJOR_ASPECT_POINTS_STANDARD
@@ -125,11 +171,12 @@ class RelationshipScoreFactory:
125
171
 
126
172
  def _evaluate_sun_sun_other_aspects(self, aspect):
127
173
  """
128
- Evaluates Sun-Sun aspects that are not conjunctions and adds points accordingly:
129
- - 4 points for other aspects
174
+ Evaluates Sun-Sun aspects other than conjunction, opposition, or square.
175
+
176
+ Adds 4 points for any qualifying aspect.
130
177
 
131
178
  Args:
132
- aspect (dict): Aspect information.
179
+ aspect (dict): Aspect data
133
180
  """
134
181
  if aspect["p1_name"] == "Sun" and aspect["p2_name"] == "Sun" and aspect["aspect"] not in {"conjunction", "opposition", "square"}:
135
182
  points = MINOR_ASPECT_POINTS
@@ -137,11 +184,12 @@ class RelationshipScoreFactory:
137
184
 
138
185
  def _evaluate_sun_moon_other_aspects(self, aspect):
139
186
  """
140
- Evaluates Sun-Moon aspects that are not conjunctions and adds points accordingly:
141
- - 4 points for other aspects
187
+ Evaluates Sun-Moon aspects other than conjunctions.
188
+
189
+ Adds 4 points for any qualifying aspect.
142
190
 
143
191
  Args:
144
- aspect (dict): Aspect information.
192
+ aspect (dict): Aspect data
145
193
  """
146
194
  if {aspect["p1_name"], aspect["p2_name"]} == {"Moon", "Sun"} and aspect["aspect"] != "conjunction":
147
195
  points = MINOR_ASPECT_POINTS
@@ -149,11 +197,12 @@ class RelationshipScoreFactory:
149
197
 
150
198
  def _evaluate_sun_ascendant_aspect(self, aspect):
151
199
  """
152
- Evaluates Sun-Ascendant aspects and adds points accordingly:
153
- - 4 points for any aspect
200
+ Evaluates Sun-Ascendant aspects.
201
+
202
+ Adds 4 points for any aspect between Sun and Ascendant.
154
203
 
155
204
  Args:
156
- aspect (dict): Aspect information.
205
+ aspect (dict): Aspect data
157
206
  """
158
207
  if {aspect["p1_name"], aspect["p2_name"]} == {"Sun", "Ascendant"}:
159
208
  points = SUN_ASCENDANT_ASPECT_POINTS
@@ -161,11 +210,12 @@ class RelationshipScoreFactory:
161
210
 
162
211
  def _evaluate_moon_ascendant_aspect(self, aspect):
163
212
  """
164
- Evaluates Moon-Ascendant aspects and adds points accordingly:
165
- - 4 points for any aspect
213
+ Evaluates Moon-Ascendant aspects.
214
+
215
+ Adds 4 points for any aspect between Moon and Ascendant.
166
216
 
167
217
  Args:
168
- aspect (dict): Aspect information.
218
+ aspect (dict): Aspect data
169
219
  """
170
220
  if {aspect["p1_name"], aspect["p2_name"]} == {"Moon", "Ascendant"}:
171
221
  points = MOON_ASCENDANT_ASPECT_POINTS
@@ -173,11 +223,12 @@ class RelationshipScoreFactory:
173
223
 
174
224
  def _evaluate_venus_mars_aspect(self, aspect):
175
225
  """
176
- Evaluates Venus-Mars aspects and adds points accordingly:
177
- - 4 points for any aspect
226
+ Evaluates Venus-Mars aspects.
227
+
228
+ Adds 4 points for any aspect between Venus and Mars.
178
229
 
179
230
  Args:
180
- aspect (dict): Aspect information.
231
+ aspect (dict): Aspect data
181
232
  """
182
233
  if {aspect["p1_name"], aspect["p2_name"]} == {"Venus", "Mars"}:
183
234
  points = VENUS_MARS_ASPECT_POINTS
@@ -185,7 +236,9 @@ class RelationshipScoreFactory:
185
236
 
186
237
  def _evaluate_relationship_score_description(self):
187
238
  """
188
- Evaluates the relationship score description based on the total score.
239
+ Determines the categorical description based on the numerical score.
240
+
241
+ Maps the total score to predefined description ranges.
189
242
  """
190
243
  for description, threshold in self.SCORE_MAPPING:
191
244
  if self.score_value < threshold:
@@ -194,10 +247,11 @@ class RelationshipScoreFactory:
194
247
 
195
248
  def get_relationship_score(self):
196
249
  """
197
- Calculates the relationship score based on synastry aspects.
250
+ Calculates the complete relationship score using all evaluation methods.
198
251
 
199
252
  Returns:
200
- RelationshipScoreModel: The calculated relationship score.
253
+ RelationshipScoreModel: Score object containing numerical value, description,
254
+ destiny sign status, contributing aspects, and subject data.
201
255
  """
202
256
  self._evaluate_destiny_sign()
203
257
 
kerykeion/report.py CHANGED
@@ -14,6 +14,12 @@ class Report:
14
14
  houses_table: str
15
15
 
16
16
  def __init__(self, instance: AstrologicalSubjectModel):
17
+ """
18
+ Initialize a new Report instance.
19
+
20
+ Args:
21
+ instance: The astrological subject model to create a report for.
22
+ """
17
23
  self.instance = instance
18
24
 
19
25
  self.get_report_title()
@@ -22,6 +28,7 @@ class Report:
22
28
  self.get_houses_table()
23
29
 
24
30
  def get_report_title(self) -> None:
31
+ """Generate the report title based on the subject's name."""
25
32
  self.report_title = f"\n+- Kerykeion report for {self.instance.name} -+"
26
33
 
27
34
  def get_data_table(self) -> None:
@@ -0,0 +1,293 @@
1
+ """
2
+ Transits Time Range Factory Module
3
+
4
+ This module provides the TransitsTimeRangeFactory class for calculating astrological
5
+ transits over specified time periods. It compares ephemeris data points (planetary
6
+ positions at different times) with a natal chart to identify when celestial bodies
7
+ form specific angular relationships (aspects).
8
+
9
+ Key Features:
10
+ - Time-series transit calculations
11
+ - Configurable celestial points and aspect types
12
+ - Structured output models for data analysis
13
+ - Integration with ephemeris data generation
14
+ - Batch processing of multiple time points
15
+
16
+ The module generates comprehensive transit data by analyzing the angular relationships
17
+ between transiting celestial bodies and natal chart positions, creating timestamped
18
+ records of when specific geometric configurations occur.
19
+
20
+ Classes:
21
+ TransitsTimeRangeFactory: Main factory class for generating transit data
22
+
23
+ Dependencies:
24
+ - kerykeion.AstrologicalSubjectFactory: For creating astrological subjects
25
+ - kerykeion.aspects.SynastryAspectsFactory: For calculating angular relationships
26
+ - kerykeion.ephemeris_data_factory: For generating time-series planetary positions
27
+ - kerykeion.kr_types: For type definitions and model structures
28
+ - datetime: For date/time handling
29
+
30
+ Example:
31
+ Basic usage for calculating 30-day transits:
32
+
33
+ >>> from datetime import datetime, timedelta
34
+ >>> from kerykeion import AstrologicalSubjectFactory
35
+ >>> from kerykeion.ephemeris_data_factory import EphemerisDataFactory
36
+ >>> from kerykeion.transits_time_range_factory import TransitsTimeRangeFactory
37
+ >>>
38
+ >>> # Create natal chart
39
+ >>> person = AstrologicalSubjectFactory.from_birth_data(
40
+ ... "Subject", 1990, 1, 1, 12, 0, "New York", "US"
41
+ ... )
42
+ >>>
43
+ >>> # Generate ephemeris data
44
+ >>> start = datetime.now()
45
+ >>> end = start + timedelta(days=30)
46
+ >>> ephemeris_factory = EphemerisDataFactory(start, end)
47
+ >>> ephemeris_data = ephemeris_factory.get_ephemeris_data_as_astrological_subjects()
48
+ >>>
49
+ >>> # Calculate transits
50
+ >>> transit_factory = TransitsTimeRangeFactory(person, ephemeris_data)
51
+ >>> results = transit_factory.get_transit_moments()
52
+
53
+ Author: Giacomo Battaglia
54
+ Copyright: (C) 2025 Kerykeion Project
55
+ License: AGPL-3.0
56
+ """
57
+
58
+ from typing import Union, List
59
+ from datetime import datetime, timedelta
60
+ from kerykeion.kr_types.kr_models import AstrologicalSubjectModel
61
+ from kerykeion.astrological_subject_factory import AstrologicalSubjectFactory
62
+ from kerykeion.aspects import SynastryAspectsFactory
63
+ from kerykeion.ephemeris_data_factory import EphemerisDataFactory
64
+ from kerykeion.kr_types.kr_literals import AstrologicalPoint
65
+ from kerykeion.kr_types.kr_models import ActiveAspect, TransitMomentModel, TransitsTimeRangeModel
66
+ from kerykeion.kr_types.settings_models import KerykeionSettingsModel
67
+ from kerykeion.settings.config_constants import DEFAULT_ACTIVE_POINTS, DEFAULT_ACTIVE_ASPECTS
68
+ from pathlib import Path
69
+
70
+
71
+ class TransitsTimeRangeFactory:
72
+ """
73
+ Factory class for calculating astrological transits over time periods.
74
+
75
+ This class analyzes the angular relationships (aspects) between transiting
76
+ celestial bodies and natal chart positions across multiple time points,
77
+ generating structured transit data for astrological analysis.
78
+
79
+ The factory compares ephemeris data points (representing planetary positions
80
+ at different moments) with a natal chart to identify when specific geometric
81
+ configurations occur between transiting and natal celestial bodies.
82
+
83
+ Args:
84
+ natal_chart (AstrologicalSubjectModel): The natal chart used as the reference
85
+ point for transit calculations. All transiting positions are compared
86
+ against this chart's planetary positions.
87
+ ephemeris_data_points (List[AstrologicalSubjectModel]): A list of astrological
88
+ subject models representing different moments in time, typically generated
89
+ by EphemerisDataFactory. Each point contains planetary positions for
90
+ a specific date/time.
91
+ active_points (List[AstrologicalPoint], optional): List of celestial bodies
92
+ to include in aspect calculations (e.g., Sun, Moon, planets, asteroids).
93
+ Defaults to DEFAULT_ACTIVE_POINTS.
94
+ active_aspects (List[ActiveAspect], optional): List of aspect types to
95
+ calculate (e.g., conjunction, opposition, trine, square, sextile).
96
+ Defaults to DEFAULT_ACTIVE_ASPECTS.
97
+ settings_file (Union[Path, KerykeionSettingsModel, dict, None], optional):
98
+ Configuration settings for calculations. Can be a file path, settings
99
+ model, dictionary, or None for defaults. Defaults to None.
100
+
101
+ Attributes:
102
+ natal_chart: The reference natal chart for transit calculations.
103
+ ephemeris_data_points: Time-series planetary position data.
104
+ active_points: Celestial bodies included in calculations.
105
+ active_aspects: Aspect types considered for analysis.
106
+ settings_file: Configuration settings for the calculations.
107
+
108
+ Examples:
109
+ Basic transit calculation:
110
+
111
+ >>> natal_chart = AstrologicalSubjectFactory.from_birth_data(...)
112
+ >>> ephemeris_data = ephemeris_factory.get_ephemeris_data_as_astrological_subjects()
113
+ >>> factory = TransitsTimeRangeFactory(natal_chart, ephemeris_data)
114
+ >>> transits = factory.get_transit_moments()
115
+
116
+ Custom configuration:
117
+
118
+ >>> from kerykeion.kr_types import AstrologicalPoint, ActiveAspect
119
+ >>> custom_points = [AstrologicalPoint.SUN, AstrologicalPoint.MOON]
120
+ >>> custom_aspects = [ActiveAspect.CONJUNCTION, ActiveAspect.OPPOSITION]
121
+ >>> factory = TransitsTimeRangeFactory(
122
+ ... natal_chart, ephemeris_data,
123
+ ... active_points=custom_points,
124
+ ... active_aspects=custom_aspects
125
+ ... )
126
+
127
+ Note:
128
+ - Calculation time scales with the number of ephemeris data points
129
+ - More active points and aspects increase computational requirements
130
+ - The natal chart's coordinate system should match the ephemeris data
131
+ """
132
+
133
+ def __init__(
134
+ self,
135
+ natal_chart: AstrologicalSubjectModel,
136
+ ephemeris_data_points: List[AstrologicalSubjectModel],
137
+ active_points: List[AstrologicalPoint] = DEFAULT_ACTIVE_POINTS,
138
+ active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
139
+ settings_file: Union[Path, KerykeionSettingsModel, dict, None] = None,
140
+ ):
141
+ """
142
+ Initialize the TransitsTimeRangeFactory with calculation parameters.
143
+
144
+ Sets up the factory with all necessary data and configuration for calculating
145
+ transits across the specified time period. The natal chart serves as the
146
+ reference point, while ephemeris data points provide the transiting positions
147
+ for comparison.
148
+
149
+ Args:
150
+ natal_chart (AstrologicalSubjectModel): Reference natal chart containing
151
+ the baseline planetary positions for transit calculations.
152
+ ephemeris_data_points (List[AstrologicalSubjectModel]): Time-ordered list
153
+ of planetary positions representing different moments in time.
154
+ Typically generated by EphemerisDataFactory.
155
+ active_points (List[AstrologicalPoint], optional): Celestial bodies to
156
+ include in aspect calculations. Determines which planets/points are
157
+ analyzed for aspects. Defaults to DEFAULT_ACTIVE_POINTS.
158
+ active_aspects (List[ActiveAspect], optional): Types of angular relationships
159
+ to calculate between natal and transiting positions. Defaults to
160
+ DEFAULT_ACTIVE_ASPECTS.
161
+ settings_file (Union[Path, KerykeionSettingsModel, dict, None], optional):
162
+ Configuration settings for orb tolerances, calculation methods, and
163
+ other parameters. Defaults to None (uses system defaults).
164
+
165
+ Note:
166
+ - All ephemeris data points should use the same coordinate system as the natal chart
167
+ - The order of ephemeris_data_points determines the chronological sequence
168
+ - Settings affect orb tolerances and calculation precision
169
+ """
170
+ self.natal_chart = natal_chart
171
+ self.ephemeris_data_points = ephemeris_data_points
172
+ self.active_points = active_points
173
+ self.active_aspects = active_aspects
174
+ self.settings_file = settings_file
175
+
176
+ def get_transit_moments(self) -> TransitsTimeRangeModel:
177
+ """
178
+ Calculate and generate transit data for all configured time points.
179
+
180
+ This method processes each ephemeris data point to identify angular relationships
181
+ (aspects) between transiting celestial bodies and natal chart positions. It
182
+ creates a comprehensive model containing all transit moments with their
183
+ corresponding aspects and timestamps.
184
+
185
+ The calculation process:
186
+ 1. Iterates through each ephemeris data point chronologically
187
+ 2. Compares transiting planetary positions with natal chart positions
188
+ 3. Identifies aspects that fall within the configured orb tolerances
189
+ 4. Creates timestamped transit moment records
190
+ 5. Compiles all data into a structured model for analysis
191
+
192
+ Returns:
193
+ TransitsTimeRangeModel: A comprehensive model containing:
194
+ - dates (List[str]): ISO-formatted datetime strings for all data points
195
+ - subject (AstrologicalSubjectModel): The natal chart used as reference
196
+ - transits (List[TransitMomentModel]): Chronological list of transit moments,
197
+ each containing:
198
+ * date (str): ISO-formatted timestamp for the transit moment
199
+ * aspects (List[RelevantAspect]): All aspects formed at this moment
200
+ between transiting and natal positions
201
+
202
+ Examples:
203
+ Basic usage:
204
+
205
+ >>> factory = TransitsTimeRangeFactory(natal_chart, ephemeris_data)
206
+ >>> results = factory.get_transit_moments()
207
+ >>>
208
+ >>> # Access specific data
209
+ >>> all_dates = results.dates
210
+ >>> first_transit = results.transits[0]
211
+ >>> aspects_at_first_moment = first_transit.aspects
212
+
213
+ Processing results:
214
+
215
+ >>> results = factory.get_transit_moments()
216
+ >>> for transit_moment in results.transits:
217
+ ... print(f"Date: {transit_moment.date}")
218
+ ... for aspect in transit_moment.aspects:
219
+ ... print(f" {aspect.p1_name} {aspect.aspect} {aspect.p2_name}")
220
+
221
+ Performance Notes:
222
+ - Calculation time is proportional to: number of time points × active points × active aspects
223
+ - Large datasets may require significant processing time
224
+ - Memory usage scales with the number of aspects found
225
+ - Consider filtering active_points and active_aspects for better performance
226
+
227
+ See Also:
228
+ TransitMomentModel: Individual transit moment structure
229
+ TransitsTimeRangeModel: Complete transit dataset structure
230
+ SynastryAspectsFactory: Underlying aspect calculation engine
231
+ """
232
+ transit_moments = []
233
+
234
+ for ephemeris_point in self.ephemeris_data_points:
235
+ # Calculate aspects between transit positions and natal chart
236
+ aspects = SynastryAspectsFactory.from_subjects(
237
+ ephemeris_point,
238
+ self.natal_chart,
239
+ active_points=self.active_points,
240
+ active_aspects=self.active_aspects,
241
+ ).relevant_aspects
242
+
243
+ # Create a transit moment for this point in time
244
+ transit_moments.append(
245
+ TransitMomentModel(
246
+ date=ephemeris_point.iso_formatted_utc_datetime,
247
+ aspects=aspects,
248
+ )
249
+ )
250
+
251
+ # Create and return the complete transits model
252
+ return TransitsTimeRangeModel(
253
+ dates=[point.iso_formatted_utc_datetime for point in self.ephemeris_data_points],
254
+ subject=self.natal_chart,
255
+ transits=transit_moments
256
+ )
257
+
258
+
259
+ if __name__ == "__main__":
260
+ # Create a natal chart for the subject
261
+ person = AstrologicalSubjectFactory.from_birth_data(
262
+ "Johnny Depp", 1963, 6, 9, 20, 15, "Owensboro", "US"
263
+ )
264
+
265
+ # Define the time period for transit calculation
266
+ start_date = datetime.now()
267
+ end_date = datetime.now() + timedelta(days=30)
268
+
269
+ # Create ephemeris data for the specified time period
270
+ ephemeris_factory = EphemerisDataFactory(
271
+ start_datetime=start_date,
272
+ end_datetime=end_date,
273
+ step_type="days",
274
+ step=1,
275
+ lat=person.lat,
276
+ lng=person.lng,
277
+ tz_str=person.tz_str,
278
+ )
279
+
280
+ ephemeris_data_points = ephemeris_factory.get_ephemeris_data_as_astrological_subjects()
281
+
282
+ # Calculate transits for the subject
283
+ transit_factory = TransitsTimeRangeFactory(
284
+ natal_chart=person,
285
+ ephemeris_data_points=ephemeris_data_points,
286
+ )
287
+
288
+ transit_results = transit_factory.get_transit_moments()
289
+
290
+ # Print example data
291
+ print(transit_results.model_dump()["dates"][2])
292
+ print(transit_results.model_dump()["transits"][2]['date'])
293
+ print(transit_results.model_dump()["transits"][2]['aspects'][0])