kerykeion 5.0.0a9__py3-none-any.whl → 5.1.8__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 +50 -9
- kerykeion/aspects/__init__.py +5 -2
- kerykeion/aspects/aspects_factory.py +568 -0
- kerykeion/aspects/aspects_utils.py +78 -11
- kerykeion/astrological_subject_factory.py +1032 -275
- kerykeion/backword.py +820 -0
- kerykeion/chart_data_factory.py +552 -0
- kerykeion/charts/chart_drawer.py +2661 -0
- kerykeion/charts/charts_utils.py +652 -399
- kerykeion/charts/draw_planets.py +603 -353
- kerykeion/charts/templates/aspect_grid_only.xml +326 -198
- kerykeion/charts/templates/chart.xml +306 -256
- kerykeion/charts/templates/wheel_only.xml +330 -200
- kerykeion/charts/themes/black-and-white.css +148 -0
- kerykeion/charts/themes/classic.css +11 -0
- kerykeion/charts/themes/dark-high-contrast.css +11 -0
- kerykeion/charts/themes/dark.css +11 -0
- kerykeion/charts/themes/light.css +11 -0
- kerykeion/charts/themes/strawberry.css +10 -0
- kerykeion/composite_subject_factory.py +232 -13
- kerykeion/ephemeris_data_factory.py +443 -0
- kerykeion/fetch_geonames.py +78 -21
- kerykeion/house_comparison/__init__.py +4 -1
- kerykeion/house_comparison/house_comparison_factory.py +52 -19
- kerykeion/house_comparison/house_comparison_utils.py +37 -9
- 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 -160
- kerykeion/kr_types/kr_models.py +14 -291
- kerykeion/kr_types/settings_models.py +15 -167
- kerykeion/planetary_return_factory.py +545 -40
- kerykeion/relationship_score_factory.py +137 -63
- kerykeion/report.py +749 -64
- 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 +88 -12
- kerykeion/settings/kerykeion_settings.py +32 -75
- 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 +289 -204
- kerykeion-5.1.8.dist-info/METADATA +1793 -0
- kerykeion-5.1.8.dist-info/RECORD +63 -0
- kerykeion/aspects/natal_aspects.py +0 -181
- kerykeion/aspects/synastry_aspects.py +0 -141
- kerykeion/aspects/transits_time_range.py +0 -41
- kerykeion/charts/draw_planets_v2.py +0 -649
- kerykeion/charts/draw_planets_v3.py +0 -679
- kerykeion/charts/kerykeion_chart_svg.py +0 -2038
- kerykeion/enums.py +0 -57
- kerykeion/ephemeris_data.py +0 -238
- kerykeion/house_comparison/house_comparison_models.py +0 -38
- kerykeion/kr_types/chart_types.py +0 -106
- kerykeion/settings/kr.config.json +0 -1304
- kerykeion/settings/legacy/__init__.py +0 -0
- kerykeion/settings/legacy/legacy_celestial_points_settings.py +0 -299
- kerykeion/settings/legacy/legacy_chart_aspects_settings.py +0 -71
- kerykeion/settings/legacy/legacy_color_settings.py +0 -42
- kerykeion/transits_time_range.py +0 -128
- kerykeion-5.0.0a9.dist-info/METADATA +0 -636
- kerykeion-5.0.0a9.dist-info/RECORD +0 -55
- kerykeion-5.0.0a9.dist-info/entry_points.txt +0 -2
- {kerykeion-5.0.0a9.dist-info → kerykeion-5.1.8.dist-info}/WHEEL +0 -0
- {kerykeion-5.0.0a9.dist-info → kerykeion-5.1.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Chart Data Factory Module
|
|
4
|
+
|
|
5
|
+
This module provides factory classes for creating comprehensive chart data models that include
|
|
6
|
+
all the pure data from astrological charts, including subjects, aspects, house comparisons,
|
|
7
|
+
and other analytical data without the visual rendering components.
|
|
8
|
+
|
|
9
|
+
This is designed to be the "pure data" counterpart to ChartDrawer, providing structured
|
|
10
|
+
access to all chart information for API consumption, data analysis, or other programmatic uses.
|
|
11
|
+
|
|
12
|
+
Key Features:
|
|
13
|
+
- Comprehensive chart data including subjects and aspects
|
|
14
|
+
- House comparison analysis for dual charts
|
|
15
|
+
- Element and quality distributions
|
|
16
|
+
- Relationship scoring for synastry charts
|
|
17
|
+
- Flexible point and aspect filtering
|
|
18
|
+
- Support for all chart types (Natal, Transit, Synastry, Composite, Return)
|
|
19
|
+
|
|
20
|
+
Classes:
|
|
21
|
+
ElementDistributionModel: Model for element distribution analysis
|
|
22
|
+
QualityDistributionModel: Model for quality distribution analysis
|
|
23
|
+
SingleChartDataModel: Model for single-subject chart data
|
|
24
|
+
DualChartDataModel: Model for dual-subject chart data
|
|
25
|
+
ChartDataFactory: Factory for creating chart data models
|
|
26
|
+
|
|
27
|
+
Author: Giacomo Battaglia
|
|
28
|
+
Copyright: (C) 2025 Kerykeion Project
|
|
29
|
+
License: AGPL-3.0
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from typing import Mapping, Union, Optional, List, Literal, cast
|
|
33
|
+
|
|
34
|
+
from kerykeion.aspects import AspectsFactory
|
|
35
|
+
from kerykeion.house_comparison.house_comparison_factory import HouseComparisonFactory
|
|
36
|
+
from kerykeion.relationship_score_factory import RelationshipScoreFactory
|
|
37
|
+
from kerykeion.schemas import (
|
|
38
|
+
KerykeionException,
|
|
39
|
+
ChartType,
|
|
40
|
+
ActiveAspect
|
|
41
|
+
)
|
|
42
|
+
from kerykeion.schemas.kr_models import (
|
|
43
|
+
AstrologicalSubjectModel,
|
|
44
|
+
CompositeSubjectModel,
|
|
45
|
+
PlanetReturnModel,
|
|
46
|
+
SingleChartAspectsModel,
|
|
47
|
+
DualChartAspectsModel,
|
|
48
|
+
ElementDistributionModel,
|
|
49
|
+
QualityDistributionModel,
|
|
50
|
+
SingleChartDataModel,
|
|
51
|
+
DualChartDataModel,
|
|
52
|
+
ChartDataModel
|
|
53
|
+
)
|
|
54
|
+
from kerykeion.schemas.settings_models import KerykeionSettingsCelestialPointModel
|
|
55
|
+
from kerykeion.schemas.kr_literals import (
|
|
56
|
+
AstrologicalPoint,
|
|
57
|
+
)
|
|
58
|
+
from kerykeion.utilities import find_common_active_points, distribute_percentages_to_100
|
|
59
|
+
from kerykeion.settings.config_constants import DEFAULT_ACTIVE_ASPECTS
|
|
60
|
+
from kerykeion.settings.chart_defaults import DEFAULT_CELESTIAL_POINTS_SETTINGS
|
|
61
|
+
from kerykeion.charts.charts_utils import (
|
|
62
|
+
ElementQualityDistributionMethod,
|
|
63
|
+
calculate_element_points,
|
|
64
|
+
calculate_quality_points,
|
|
65
|
+
calculate_synastry_element_points,
|
|
66
|
+
calculate_synastry_quality_points,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class ChartDataFactory:
|
|
72
|
+
"""
|
|
73
|
+
Factory class for creating comprehensive chart data models.
|
|
74
|
+
|
|
75
|
+
This factory creates ChartDataModel instances containing all the pure data
|
|
76
|
+
from astrological charts, including subjects, aspects, house comparisons,
|
|
77
|
+
and analytical metrics. It provides the structured data equivalent of
|
|
78
|
+
ChartDrawer's visual output.
|
|
79
|
+
|
|
80
|
+
The factory handles all chart types and automatically includes relevant
|
|
81
|
+
analyses based on chart type (e.g., house comparison for dual charts,
|
|
82
|
+
relationship scoring for synastry charts).
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
>>> # Create natal chart data
|
|
86
|
+
>>> john = AstrologicalSubjectFactory.from_birth_data("John", 1990, 1, 1, 12, 0, "London", "GB")
|
|
87
|
+
>>> natal_data = ChartDataFactory.create_chart_data("Natal", john)
|
|
88
|
+
>>> print(f"Elements: Fire {natal_data.element_distribution.fire_percentage}%")
|
|
89
|
+
>>>
|
|
90
|
+
>>> # Create synastry chart data
|
|
91
|
+
>>> jane = AstrologicalSubjectFactory.from_birth_data("Jane", 1992, 6, 15, 14, 30, "Paris", "FR")
|
|
92
|
+
>>> synastry_data = ChartDataFactory.create_chart_data("Synastry", john, jane)
|
|
93
|
+
>>> print(f"Relationship score: {synastry_data.relationship_score.score_value}")
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def create_chart_data(
|
|
98
|
+
chart_type: ChartType,
|
|
99
|
+
first_subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
|
|
100
|
+
second_subject: Optional[Union[AstrologicalSubjectModel, PlanetReturnModel]] = None,
|
|
101
|
+
active_points: Optional[List[AstrologicalPoint]] = None,
|
|
102
|
+
active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
|
|
103
|
+
include_house_comparison: bool = True,
|
|
104
|
+
include_relationship_score: bool = True,
|
|
105
|
+
*,
|
|
106
|
+
axis_orb_limit: Optional[float] = None,
|
|
107
|
+
distribution_method: ElementQualityDistributionMethod = "weighted",
|
|
108
|
+
custom_distribution_weights: Optional[Mapping[str, float]] = None,
|
|
109
|
+
) -> ChartDataModel:
|
|
110
|
+
"""
|
|
111
|
+
Create comprehensive chart data for the specified chart type.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
chart_type: Type of chart to create data for
|
|
115
|
+
first_subject: Primary astrological subject
|
|
116
|
+
second_subject: Secondary subject (required for dual charts)
|
|
117
|
+
active_points: Points to include in calculations (defaults to first_subject.active_points)
|
|
118
|
+
active_aspects: Aspect types and orbs to use
|
|
119
|
+
include_house_comparison: Whether to include house comparison for dual charts
|
|
120
|
+
include_relationship_score: Whether to include relationship scoring for synastry
|
|
121
|
+
axis_orb_limit: Optional orb threshold for chart axes (applies only to single chart aspects)
|
|
122
|
+
distribution_method: Strategy for element/modality weighting ("pure_count" or "weighted")
|
|
123
|
+
custom_distribution_weights: Optional overrides for the distribution weights
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
ChartDataModel: Comprehensive chart data model
|
|
127
|
+
|
|
128
|
+
Raises:
|
|
129
|
+
KerykeionException: If chart type requirements are not met
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
# Validate chart type requirements
|
|
133
|
+
if chart_type in ["Transit", "Synastry", "DualReturnChart"] and not second_subject:
|
|
134
|
+
raise KerykeionException(f"Second subject is required for {chart_type} charts.")
|
|
135
|
+
|
|
136
|
+
if chart_type == "Composite" and not isinstance(first_subject, CompositeSubjectModel):
|
|
137
|
+
raise KerykeionException("First subject must be a CompositeSubjectModel for Composite charts.")
|
|
138
|
+
|
|
139
|
+
if chart_type == "Return" and not isinstance(second_subject, PlanetReturnModel):
|
|
140
|
+
raise KerykeionException("Second subject must be a PlanetReturnModel for Return charts.")
|
|
141
|
+
|
|
142
|
+
if chart_type == "SingleReturnChart" and not isinstance(first_subject, PlanetReturnModel):
|
|
143
|
+
raise KerykeionException("First subject must be a PlanetReturnModel for SingleReturnChart charts.")
|
|
144
|
+
|
|
145
|
+
# Determine active points
|
|
146
|
+
if not active_points:
|
|
147
|
+
effective_active_points = first_subject.active_points
|
|
148
|
+
else:
|
|
149
|
+
effective_active_points = find_common_active_points(
|
|
150
|
+
active_points,
|
|
151
|
+
first_subject.active_points
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# For dual charts, further filter by second subject's active points
|
|
155
|
+
if second_subject:
|
|
156
|
+
effective_active_points = find_common_active_points(
|
|
157
|
+
effective_active_points,
|
|
158
|
+
second_subject.active_points
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Calculate aspects based on chart type
|
|
162
|
+
aspects_model: Union[SingleChartAspectsModel, DualChartAspectsModel]
|
|
163
|
+
if chart_type in ["Natal", "Composite", "SingleReturnChart"]:
|
|
164
|
+
# Single chart aspects
|
|
165
|
+
aspects_model = AspectsFactory.single_chart_aspects(
|
|
166
|
+
first_subject,
|
|
167
|
+
active_points=effective_active_points,
|
|
168
|
+
active_aspects=active_aspects,
|
|
169
|
+
axis_orb_limit=axis_orb_limit,
|
|
170
|
+
)
|
|
171
|
+
else:
|
|
172
|
+
# Dual chart aspects - second_subject is guaranteed to exist here due to validation above
|
|
173
|
+
if second_subject is None:
|
|
174
|
+
raise KerykeionException(f"Second subject is required for {chart_type} charts.")
|
|
175
|
+
aspects_model = AspectsFactory.dual_chart_aspects(
|
|
176
|
+
first_subject,
|
|
177
|
+
second_subject,
|
|
178
|
+
active_points=effective_active_points,
|
|
179
|
+
active_aspects=active_aspects,
|
|
180
|
+
axis_orb_limit=axis_orb_limit,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# Calculate house comparison for dual charts
|
|
184
|
+
house_comparison = None
|
|
185
|
+
if second_subject and include_house_comparison and chart_type in ["Transit", "Synastry", "DualReturnChart"]:
|
|
186
|
+
if isinstance(first_subject, AstrologicalSubjectModel) and isinstance(second_subject, (AstrologicalSubjectModel, PlanetReturnModel)):
|
|
187
|
+
house_comparison_factory = HouseComparisonFactory(
|
|
188
|
+
first_subject,
|
|
189
|
+
second_subject,
|
|
190
|
+
active_points=effective_active_points
|
|
191
|
+
)
|
|
192
|
+
house_comparison = house_comparison_factory.get_house_comparison()
|
|
193
|
+
|
|
194
|
+
# Calculate relationship score for synastry
|
|
195
|
+
relationship_score = None
|
|
196
|
+
if chart_type == "Synastry" and include_relationship_score and second_subject:
|
|
197
|
+
if isinstance(first_subject, AstrologicalSubjectModel) and isinstance(second_subject, AstrologicalSubjectModel):
|
|
198
|
+
relationship_score_factory = RelationshipScoreFactory(
|
|
199
|
+
first_subject,
|
|
200
|
+
second_subject,
|
|
201
|
+
axis_orb_limit=axis_orb_limit,
|
|
202
|
+
)
|
|
203
|
+
relationship_score = relationship_score_factory.get_relationship_score()
|
|
204
|
+
|
|
205
|
+
# Calculate element and quality distributions
|
|
206
|
+
available_planets_setting_dicts: list[dict[str, object]] = []
|
|
207
|
+
for body in DEFAULT_CELESTIAL_POINTS_SETTINGS:
|
|
208
|
+
if body["name"] in effective_active_points:
|
|
209
|
+
body_dict = dict(body)
|
|
210
|
+
body_dict["is_active"] = True
|
|
211
|
+
available_planets_setting_dicts.append(body_dict)
|
|
212
|
+
|
|
213
|
+
# Convert to models for type safety
|
|
214
|
+
available_planets_setting: list[KerykeionSettingsCelestialPointModel] = [
|
|
215
|
+
KerykeionSettingsCelestialPointModel(**body) for body in available_planets_setting_dicts # type: ignore
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
celestial_points_names = [body.name.lower() for body in available_planets_setting]
|
|
219
|
+
|
|
220
|
+
if chart_type == "Synastry" and second_subject:
|
|
221
|
+
# Calculate combined element/quality points for synastry
|
|
222
|
+
# Type narrowing: ensure both subjects are AstrologicalSubjectModel for synastry
|
|
223
|
+
if isinstance(first_subject, AstrologicalSubjectModel) and isinstance(second_subject, AstrologicalSubjectModel):
|
|
224
|
+
element_totals = calculate_synastry_element_points(
|
|
225
|
+
available_planets_setting,
|
|
226
|
+
celestial_points_names,
|
|
227
|
+
first_subject,
|
|
228
|
+
second_subject,
|
|
229
|
+
method=distribution_method,
|
|
230
|
+
custom_weights=custom_distribution_weights,
|
|
231
|
+
)
|
|
232
|
+
quality_totals = calculate_synastry_quality_points(
|
|
233
|
+
available_planets_setting,
|
|
234
|
+
celestial_points_names,
|
|
235
|
+
first_subject,
|
|
236
|
+
second_subject,
|
|
237
|
+
method=distribution_method,
|
|
238
|
+
custom_weights=custom_distribution_weights,
|
|
239
|
+
)
|
|
240
|
+
else:
|
|
241
|
+
# Fallback to single chart calculation for incompatible types
|
|
242
|
+
element_totals = calculate_element_points(
|
|
243
|
+
available_planets_setting,
|
|
244
|
+
celestial_points_names,
|
|
245
|
+
first_subject,
|
|
246
|
+
method=distribution_method,
|
|
247
|
+
custom_weights=custom_distribution_weights,
|
|
248
|
+
)
|
|
249
|
+
quality_totals = calculate_quality_points(
|
|
250
|
+
available_planets_setting,
|
|
251
|
+
celestial_points_names,
|
|
252
|
+
first_subject,
|
|
253
|
+
method=distribution_method,
|
|
254
|
+
custom_weights=custom_distribution_weights,
|
|
255
|
+
)
|
|
256
|
+
else:
|
|
257
|
+
# Calculate element/quality points for single chart
|
|
258
|
+
element_totals = calculate_element_points(
|
|
259
|
+
available_planets_setting,
|
|
260
|
+
celestial_points_names,
|
|
261
|
+
first_subject,
|
|
262
|
+
method=distribution_method,
|
|
263
|
+
custom_weights=custom_distribution_weights,
|
|
264
|
+
)
|
|
265
|
+
quality_totals = calculate_quality_points(
|
|
266
|
+
available_planets_setting,
|
|
267
|
+
celestial_points_names,
|
|
268
|
+
first_subject,
|
|
269
|
+
method=distribution_method,
|
|
270
|
+
custom_weights=custom_distribution_weights,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
# Calculate percentages
|
|
274
|
+
total_elements = element_totals["fire"] + element_totals["water"] + element_totals["earth"] + element_totals["air"]
|
|
275
|
+
element_percentages = distribute_percentages_to_100(element_totals) if total_elements > 0 else {"fire": 0, "earth": 0, "air": 0, "water": 0}
|
|
276
|
+
element_distribution = ElementDistributionModel(
|
|
277
|
+
fire=element_totals["fire"],
|
|
278
|
+
earth=element_totals["earth"],
|
|
279
|
+
air=element_totals["air"],
|
|
280
|
+
water=element_totals["water"],
|
|
281
|
+
fire_percentage=element_percentages["fire"],
|
|
282
|
+
earth_percentage=element_percentages["earth"],
|
|
283
|
+
air_percentage=element_percentages["air"],
|
|
284
|
+
water_percentage=element_percentages["water"],
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
total_qualities = quality_totals["cardinal"] + quality_totals["fixed"] + quality_totals["mutable"]
|
|
288
|
+
quality_percentages = distribute_percentages_to_100(quality_totals) if total_qualities > 0 else {"cardinal": 0, "fixed": 0, "mutable": 0}
|
|
289
|
+
quality_distribution = QualityDistributionModel(
|
|
290
|
+
cardinal=quality_totals["cardinal"],
|
|
291
|
+
fixed=quality_totals["fixed"],
|
|
292
|
+
mutable=quality_totals["mutable"],
|
|
293
|
+
cardinal_percentage=quality_percentages["cardinal"],
|
|
294
|
+
fixed_percentage=quality_percentages["fixed"],
|
|
295
|
+
mutable_percentage=quality_percentages["mutable"],
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# Create and return the appropriate chart data model
|
|
299
|
+
if chart_type in ["Natal", "Composite", "SingleReturnChart"]:
|
|
300
|
+
# Single chart data model - cast types since they're already validated
|
|
301
|
+
return SingleChartDataModel(
|
|
302
|
+
chart_type=cast(Literal["Natal", "Composite", "SingleReturnChart"], chart_type),
|
|
303
|
+
subject=first_subject,
|
|
304
|
+
aspects=cast(SingleChartAspectsModel, aspects_model).aspects,
|
|
305
|
+
element_distribution=element_distribution,
|
|
306
|
+
quality_distribution=quality_distribution,
|
|
307
|
+
active_points=effective_active_points,
|
|
308
|
+
active_aspects=active_aspects,
|
|
309
|
+
)
|
|
310
|
+
else:
|
|
311
|
+
# Dual chart data model - cast types since they're already validated
|
|
312
|
+
if second_subject is None:
|
|
313
|
+
raise KerykeionException(f"Second subject is required for {chart_type} charts.")
|
|
314
|
+
return DualChartDataModel(
|
|
315
|
+
chart_type=cast(Literal["Transit", "Synastry", "DualReturnChart"], chart_type),
|
|
316
|
+
first_subject=first_subject,
|
|
317
|
+
second_subject=second_subject,
|
|
318
|
+
aspects=cast(DualChartAspectsModel, aspects_model).aspects,
|
|
319
|
+
house_comparison=house_comparison,
|
|
320
|
+
relationship_score=relationship_score,
|
|
321
|
+
element_distribution=element_distribution,
|
|
322
|
+
quality_distribution=quality_distribution,
|
|
323
|
+
active_points=effective_active_points,
|
|
324
|
+
active_aspects=active_aspects,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
@staticmethod
|
|
328
|
+
def create_natal_chart_data(
|
|
329
|
+
subject: Union[AstrologicalSubjectModel, CompositeSubjectModel, PlanetReturnModel],
|
|
330
|
+
active_points: Optional[List[AstrologicalPoint]] = None,
|
|
331
|
+
active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
|
|
332
|
+
*,
|
|
333
|
+
distribution_method: ElementQualityDistributionMethod = "weighted",
|
|
334
|
+
custom_distribution_weights: Optional[Mapping[str, float]] = None,
|
|
335
|
+
) -> ChartDataModel:
|
|
336
|
+
"""
|
|
337
|
+
Convenience method for creating natal chart data.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
subject: Astrological subject
|
|
341
|
+
active_points: Points to include in calculations
|
|
342
|
+
active_aspects: Aspect types and orbs to use
|
|
343
|
+
distribution_method: Strategy for element/modality weighting
|
|
344
|
+
custom_distribution_weights: Optional overrides for distribution weights
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
ChartDataModel: Natal chart data
|
|
348
|
+
"""
|
|
349
|
+
return ChartDataFactory.create_chart_data(
|
|
350
|
+
first_subject=subject,
|
|
351
|
+
chart_type="Natal",
|
|
352
|
+
active_points=active_points,
|
|
353
|
+
active_aspects=active_aspects,
|
|
354
|
+
distribution_method=distribution_method,
|
|
355
|
+
custom_distribution_weights=custom_distribution_weights,
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
@staticmethod
|
|
359
|
+
def create_synastry_chart_data(
|
|
360
|
+
first_subject: AstrologicalSubjectModel,
|
|
361
|
+
second_subject: AstrologicalSubjectModel,
|
|
362
|
+
active_points: Optional[List[AstrologicalPoint]] = None,
|
|
363
|
+
active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
|
|
364
|
+
include_house_comparison: bool = True,
|
|
365
|
+
include_relationship_score: bool = True,
|
|
366
|
+
*,
|
|
367
|
+
distribution_method: ElementQualityDistributionMethod = "weighted",
|
|
368
|
+
custom_distribution_weights: Optional[Mapping[str, float]] = None,
|
|
369
|
+
) -> ChartDataModel:
|
|
370
|
+
"""
|
|
371
|
+
Convenience method for creating synastry chart data.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
first_subject: First astrological subject
|
|
375
|
+
second_subject: Second astrological subject
|
|
376
|
+
active_points: Points to include in calculations
|
|
377
|
+
active_aspects: Aspect types and orbs to use
|
|
378
|
+
include_house_comparison: Whether to include house comparison
|
|
379
|
+
include_relationship_score: Whether to include relationship scoring
|
|
380
|
+
distribution_method: Strategy for element/modality weighting
|
|
381
|
+
custom_distribution_weights: Optional overrides for distribution weights
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
ChartDataModel: Synastry chart data
|
|
385
|
+
"""
|
|
386
|
+
return ChartDataFactory.create_chart_data(
|
|
387
|
+
first_subject=first_subject,
|
|
388
|
+
chart_type="Synastry",
|
|
389
|
+
second_subject=second_subject,
|
|
390
|
+
active_points=active_points,
|
|
391
|
+
active_aspects=active_aspects,
|
|
392
|
+
include_house_comparison=include_house_comparison,
|
|
393
|
+
include_relationship_score=include_relationship_score,
|
|
394
|
+
distribution_method=distribution_method,
|
|
395
|
+
custom_distribution_weights=custom_distribution_weights,
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
@staticmethod
|
|
399
|
+
def create_transit_chart_data(
|
|
400
|
+
natal_subject: AstrologicalSubjectModel,
|
|
401
|
+
transit_subject: AstrologicalSubjectModel,
|
|
402
|
+
active_points: Optional[List[AstrologicalPoint]] = None,
|
|
403
|
+
active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
|
|
404
|
+
include_house_comparison: bool = True,
|
|
405
|
+
*,
|
|
406
|
+
distribution_method: ElementQualityDistributionMethod = "weighted",
|
|
407
|
+
custom_distribution_weights: Optional[Mapping[str, float]] = None,
|
|
408
|
+
) -> ChartDataModel:
|
|
409
|
+
"""
|
|
410
|
+
Convenience method for creating transit chart data.
|
|
411
|
+
|
|
412
|
+
Args:
|
|
413
|
+
natal_subject: Natal astrological subject
|
|
414
|
+
transit_subject: Transit astrological subject
|
|
415
|
+
active_points: Points to include in calculations
|
|
416
|
+
active_aspects: Aspect types and orbs to use
|
|
417
|
+
include_house_comparison: Whether to include house comparison
|
|
418
|
+
distribution_method: Strategy for element/modality weighting
|
|
419
|
+
custom_distribution_weights: Optional overrides for distribution weights
|
|
420
|
+
|
|
421
|
+
Returns:
|
|
422
|
+
ChartDataModel: Transit chart data
|
|
423
|
+
"""
|
|
424
|
+
return ChartDataFactory.create_chart_data(
|
|
425
|
+
first_subject=natal_subject,
|
|
426
|
+
chart_type="Transit",
|
|
427
|
+
second_subject=transit_subject,
|
|
428
|
+
active_points=active_points,
|
|
429
|
+
active_aspects=active_aspects,
|
|
430
|
+
include_house_comparison=include_house_comparison,
|
|
431
|
+
distribution_method=distribution_method,
|
|
432
|
+
custom_distribution_weights=custom_distribution_weights,
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
@staticmethod
|
|
436
|
+
def create_composite_chart_data(
|
|
437
|
+
composite_subject: CompositeSubjectModel,
|
|
438
|
+
active_points: Optional[List[AstrologicalPoint]] = None,
|
|
439
|
+
active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
|
|
440
|
+
*,
|
|
441
|
+
distribution_method: ElementQualityDistributionMethod = "weighted",
|
|
442
|
+
custom_distribution_weights: Optional[Mapping[str, float]] = None,
|
|
443
|
+
) -> ChartDataModel:
|
|
444
|
+
"""
|
|
445
|
+
Convenience method for creating composite chart data.
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
composite_subject: Composite astrological subject
|
|
449
|
+
active_points: Points to include in calculations
|
|
450
|
+
active_aspects: Aspect types and orbs to use
|
|
451
|
+
distribution_method: Strategy for element/modality weighting
|
|
452
|
+
custom_distribution_weights: Optional overrides for distribution weights
|
|
453
|
+
|
|
454
|
+
Returns:
|
|
455
|
+
ChartDataModel: Composite chart data
|
|
456
|
+
"""
|
|
457
|
+
return ChartDataFactory.create_chart_data(
|
|
458
|
+
first_subject=composite_subject,
|
|
459
|
+
chart_type="Composite",
|
|
460
|
+
active_points=active_points,
|
|
461
|
+
active_aspects=active_aspects,
|
|
462
|
+
distribution_method=distribution_method,
|
|
463
|
+
custom_distribution_weights=custom_distribution_weights,
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
@staticmethod
|
|
467
|
+
def create_return_chart_data(
|
|
468
|
+
natal_subject: AstrologicalSubjectModel,
|
|
469
|
+
return_subject: PlanetReturnModel,
|
|
470
|
+
active_points: Optional[List[AstrologicalPoint]] = None,
|
|
471
|
+
active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
|
|
472
|
+
include_house_comparison: bool = True,
|
|
473
|
+
*,
|
|
474
|
+
distribution_method: ElementQualityDistributionMethod = "weighted",
|
|
475
|
+
custom_distribution_weights: Optional[Mapping[str, float]] = None,
|
|
476
|
+
) -> ChartDataModel:
|
|
477
|
+
"""
|
|
478
|
+
Convenience method for creating planetary return chart data.
|
|
479
|
+
|
|
480
|
+
Args:
|
|
481
|
+
natal_subject: Natal astrological subject
|
|
482
|
+
return_subject: Planetary return subject
|
|
483
|
+
active_points: Points to include in calculations
|
|
484
|
+
active_aspects: Aspect types and orbs to use
|
|
485
|
+
include_house_comparison: Whether to include house comparison
|
|
486
|
+
distribution_method: Strategy for element/modality weighting
|
|
487
|
+
custom_distribution_weights: Optional overrides for distribution weights
|
|
488
|
+
|
|
489
|
+
Returns:
|
|
490
|
+
ChartDataModel: Return chart data
|
|
491
|
+
"""
|
|
492
|
+
return ChartDataFactory.create_chart_data(
|
|
493
|
+
first_subject=natal_subject,
|
|
494
|
+
chart_type="DualReturnChart",
|
|
495
|
+
second_subject=return_subject,
|
|
496
|
+
active_points=active_points,
|
|
497
|
+
active_aspects=active_aspects,
|
|
498
|
+
include_house_comparison=include_house_comparison,
|
|
499
|
+
distribution_method=distribution_method,
|
|
500
|
+
custom_distribution_weights=custom_distribution_weights,
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
@staticmethod
|
|
504
|
+
def create_single_wheel_return_chart_data(
|
|
505
|
+
return_subject: PlanetReturnModel,
|
|
506
|
+
active_points: Optional[List[AstrologicalPoint]] = None,
|
|
507
|
+
active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
|
|
508
|
+
*,
|
|
509
|
+
distribution_method: ElementQualityDistributionMethod = "weighted",
|
|
510
|
+
custom_distribution_weights: Optional[Mapping[str, float]] = None,
|
|
511
|
+
) -> ChartDataModel:
|
|
512
|
+
"""
|
|
513
|
+
Convenience method for creating single wheel planetary return chart data.
|
|
514
|
+
|
|
515
|
+
Args:
|
|
516
|
+
return_subject: Planetary return subject
|
|
517
|
+
active_points: Points to include in calculations
|
|
518
|
+
active_aspects: Aspect types and orbs to use
|
|
519
|
+
distribution_method: Strategy for element/modality weighting
|
|
520
|
+
custom_distribution_weights: Optional overrides for distribution weights
|
|
521
|
+
|
|
522
|
+
Returns:
|
|
523
|
+
ChartDataModel: Single wheel return chart data
|
|
524
|
+
"""
|
|
525
|
+
return ChartDataFactory.create_chart_data(
|
|
526
|
+
first_subject=return_subject,
|
|
527
|
+
chart_type="SingleReturnChart",
|
|
528
|
+
active_points=active_points,
|
|
529
|
+
active_aspects=active_aspects,
|
|
530
|
+
distribution_method=distribution_method,
|
|
531
|
+
custom_distribution_weights=custom_distribution_weights,
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
if __name__ == "__main__":
|
|
536
|
+
# Example usage
|
|
537
|
+
from kerykeion.astrological_subject_factory import AstrologicalSubjectFactory
|
|
538
|
+
|
|
539
|
+
# Create a natal chart data
|
|
540
|
+
subject = AstrologicalSubjectFactory.from_current_time(name="Test Subject")
|
|
541
|
+
natal_data = ChartDataFactory.create_natal_chart_data(subject)
|
|
542
|
+
|
|
543
|
+
print(f"Chart Type: {natal_data.chart_type}")
|
|
544
|
+
print(f"Active Points: {len(natal_data.active_points)}")
|
|
545
|
+
print(f"Aspects: {len(natal_data.aspects)}")
|
|
546
|
+
print(f"Fire: {natal_data.element_distribution.fire_percentage}%")
|
|
547
|
+
print(f"Earth: {natal_data.element_distribution.earth_percentage}%")
|
|
548
|
+
print(f"Air: {natal_data.element_distribution.air_percentage}%")
|
|
549
|
+
print(f"Water: {natal_data.element_distribution.water_percentage}%")
|
|
550
|
+
|
|
551
|
+
print("\n---\n")
|
|
552
|
+
print(natal_data.model_dump_json(indent=4))
|