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.

@@ -64,7 +64,7 @@ from kerykeion.charts.charts_utils import (
64
64
  calculate_quality_points,
65
65
  calculate_synastry_quality_points
66
66
  )
67
- from kerykeion.charts.draw_planets_v2 import draw_planets_v2 as draw_planets
67
+ from kerykeion.charts.draw_planets import draw_planets
68
68
  from kerykeion.utilities import get_houses_list, inline_css_variables_in_svg
69
69
  from kerykeion.settings.config_constants import DEFAULT_ACTIVE_ASPECTS
70
70
  from kerykeion.settings.legacy.legacy_color_settings import DEFAULT_CHART_COLORS
@@ -314,7 +314,6 @@ class KerykeionChartSVG:
314
314
  # Calculate aspects
315
315
  natal_aspects_instance = NatalAspectsFactory.from_subject(
316
316
  self.first_obj,
317
- new_settings_file=self.new_settings_file,
318
317
  active_points=self.active_points,
319
318
  active_aspects=active_aspects,
320
319
  )
@@ -347,7 +346,7 @@ class KerykeionChartSVG:
347
346
  raise KerykeionException("First object must be a CompositeSubjectModel instance.")
348
347
 
349
348
  # Calculate aspects
350
- self.aspects_list = NatalAspectsFactory.from_subject(self.first_obj, new_settings_file=self.new_settings_file, active_points=self.active_points).relevant_aspects
349
+ self.aspects_list = NatalAspectsFactory.from_subject(self.first_obj, active_points=self.active_points).relevant_aspects
351
350
 
352
351
  # Screen size
353
352
  self.height = self._DEFAULT_HEIGHT
@@ -381,7 +380,6 @@ class KerykeionChartSVG:
381
380
  synastry_aspects_instance = SynastryAspectsFactory.from_subjects(
382
381
  self.first_obj,
383
382
  self.second_obj,
384
- new_settings_file=self.new_settings_file,
385
383
  active_points=self.active_points,
386
384
  active_aspects=active_aspects,
387
385
  )
@@ -426,7 +424,6 @@ class KerykeionChartSVG:
426
424
  synastry_aspects_instance = SynastryAspectsFactory.from_subjects(
427
425
  self.first_obj,
428
426
  self.second_obj,
429
- new_settings_file=self.new_settings_file,
430
427
  active_points=self.active_points,
431
428
  active_aspects=active_aspects,
432
429
  )
@@ -467,7 +464,6 @@ class KerykeionChartSVG:
467
464
  synastry_aspects_instance = SynastryAspectsFactory.from_subjects(
468
465
  self.first_obj,
469
466
  self.second_obj,
470
- new_settings_file=self.new_settings_file,
471
467
  active_points=self.active_points,
472
468
  active_aspects=active_aspects,
473
469
  )
@@ -500,7 +496,6 @@ class KerykeionChartSVG:
500
496
  # Calculate aspects
501
497
  natal_aspects_instance = NatalAspectsFactory.from_subject(
502
498
  self.first_obj,
503
- new_settings_file=self.new_settings_file,
504
499
  active_points=self.active_points,
505
500
  active_aspects=active_aspects,
506
501
  )
@@ -5,7 +5,7 @@
5
5
  xmlns:kr="https://www.kerykeion.net/"
6
6
  width="100%"
7
7
  height="100%"
8
- viewBox="85 40 500 500"
8
+ viewBox="90 40 500 500"
9
9
  preserveAspectRatio="xMidYMid"
10
10
  style="background-color: $background_color"
11
11
  >
@@ -1,3 +1,43 @@
1
+ """
2
+ Composite Subject Factory Module
3
+
4
+ This module provides functionality for creating composite astrological charts from two
5
+ individual astrological subjects. A composite chart represents the relationship between
6
+ two people by calculating midpoint positions between corresponding planetary placements
7
+ and house cusps.
8
+
9
+ The module implements the midpoint composite technique, which is the most commonly used
10
+ method for relationship astrology. This technique creates a single chart that symbolizes
11
+ the energy and dynamics of the relationship itself, rather than comparing individual charts.
12
+
13
+ Key Features:
14
+ - Midpoint calculation for all planetary positions
15
+ - Midpoint calculation for house cusp positions
16
+ - Proper handling of zodiacal boundary crossings (0°/360°)
17
+ - Validation of compatible astrological settings between subjects
18
+ - Lunar phase calculation for composite charts
19
+ - Support for all standard astrological points and house systems
20
+
21
+ Classes:
22
+ CompositeSubjectFactory: Main factory class for creating composite charts
23
+
24
+ Dependencies:
25
+ - AstrologicalSubjectFactory: For working with individual astrological subjects
26
+ - Various kr_types modules: For type definitions and models
27
+ - utilities module: For astrological calculations and helper functions
28
+
29
+ Example Usage:
30
+ >>> from kerykeion import AstrologicalSubjectFactory, CompositeSubjectFactory
31
+ >>> person1 = AstrologicalSubjectFactory.from_birth_data(...)
32
+ >>> person2 = AstrologicalSubjectFactory.from_birth_data(...)
33
+ >>> composite = CompositeSubjectFactory(person1, person2)
34
+ >>> composite_chart = composite.get_midpoint_composite_subject_model()
35
+
36
+ Author: Giacomo Battaglia
37
+ Copyright: (C) 2025 Kerykeion Project
38
+ License: AGPL-3.0
39
+ """
40
+
1
41
  from typing import Union
2
42
 
3
43
  # Fix the circular import by changing this import
@@ -17,15 +57,48 @@ from kerykeion.utilities import (
17
57
 
18
58
  class CompositeSubjectFactory:
19
59
  """
20
- Factory class to create a Composite Subject Model from two Astrological Subjects
21
- Currently, the only available method for creating composite charts is the midpoint method.
22
- The composite houses and planets are calculated based on the midpoint of the corresponding points of the two subjects.
23
- The house are then reordered to match the original house system of the first subject.
24
-
25
- Args:
26
- first_subject (AstrologicalSubject): First astrological subject
27
- second_subject (AstrologicalSubject): Second astrological subject
28
- chart_name (str): Name of the composite chart. If None, it will be automatically generated.
60
+ Factory class to create composite astrological charts from two astrological subjects.
61
+
62
+ A composite chart represents the relationship between two people by calculating the midpoint
63
+ between corresponding planetary positions and house cusps. This creates a single chart
64
+ that symbolizes the energy of the relationship itself.
65
+
66
+ Currently supports the midpoint method for composite chart calculation, where:
67
+ - Planetary positions are calculated as the circular mean of corresponding planets
68
+ - House cusps are calculated as the circular mean of corresponding houses
69
+ - Houses are reordered to maintain consistency with the original house system
70
+ - Only common active points between both subjects are included
71
+
72
+ The resulting composite chart maintains the zodiac type, sidereal mode, houses system,
73
+ and perspective type of the input subjects (which must be identical between subjects).
74
+
75
+ Attributes:
76
+ model (CompositeSubjectModel | None): The generated composite subject model
77
+ first_subject (AstrologicalSubjectModel): First astrological subject
78
+ second_subject (AstrologicalSubjectModel): Second astrological subject
79
+ name (str): Name of the composite chart
80
+ composite_chart_type (CompositeChartType): Type of composite chart (currently "Midpoint")
81
+ zodiac_type (ZodiacType): Zodiac system used (Tropical or Sidereal)
82
+ sidereal_mode (SiderealMode | None): Sidereal calculation mode if applicable
83
+ houses_system_identifier (HousesSystemIdentifier): House system identifier
84
+ houses_system_name (str): Human-readable house system name
85
+ perspective_type (PerspectiveType): Astrological perspective type
86
+ houses_names_list (list[Houses]): List of house names
87
+ active_points (list[AstrologicalPoint]): Common active planetary points
88
+
89
+ Example:
90
+ >>> first_person = AstrologicalSubjectFactory.from_birth_data(
91
+ ... "John", 1990, 1, 1, 12, 0, "New York", "US"
92
+ ... )
93
+ >>> second_person = AstrologicalSubjectFactory.from_birth_data(
94
+ ... "Jane", 1992, 6, 15, 14, 30, "Los Angeles", "US"
95
+ ... )
96
+ >>> composite = CompositeSubjectFactory(first_person, second_person)
97
+ >>> composite_model = composite.get_midpoint_composite_subject_model()
98
+
99
+ Raises:
100
+ KerykeionException: When subjects have incompatible settings (different zodiac types,
101
+ sidereal modes, house systems, or perspective types)
29
102
  """
30
103
 
31
104
  model: Union[CompositeSubjectModel, None]
@@ -47,6 +120,27 @@ class CompositeSubjectFactory:
47
120
  second_subject: AstrologicalSubjectModel,
48
121
  chart_name: Union[str, None] = None
49
122
  ):
123
+ """
124
+ Initialize the composite subject factory with two astrological subjects.
125
+
126
+ Validates that both subjects have compatible settings and extracts common
127
+ active points for composite chart calculation.
128
+
129
+ Args:
130
+ first_subject (AstrologicalSubjectModel): First astrological subject for the composite
131
+ second_subject (AstrologicalSubjectModel): Second astrological subject for the composite
132
+ chart_name (str | None, optional): Custom name for the composite chart.
133
+ If None, generates name from subject names.
134
+ Defaults to None.
135
+
136
+ Raises:
137
+ KerykeionException: If subjects have different zodiac types, sidereal modes,
138
+ house systems, house system names, or perspective types.
139
+
140
+ Note:
141
+ Both subjects must have identical astrological calculation settings to ensure
142
+ meaningful composite chart calculations.
143
+ """
50
144
  self.model: Union[CompositeSubjectModel, None] = None
51
145
  self.composite_chart_type = "Midpoint"
52
146
 
@@ -102,30 +196,114 @@ class CompositeSubjectFactory:
102
196
  self.houses_names_list = self.first_subject.houses_names_list
103
197
 
104
198
  def __str__(self):
199
+ """
200
+ Return string representation of the composite subject.
201
+
202
+ Returns:
203
+ str: Human-readable string describing the composite chart.
204
+ """
105
205
  return f"Composite Chart Data for {self.name}"
106
206
 
107
207
  def __repr__(self):
208
+ """
209
+ Return detailed string representation of the composite subject.
210
+
211
+ Returns:
212
+ str: Detailed string representation for debugging purposes.
213
+ """
108
214
  return f"Composite Chart Data for {self.name}"
109
215
 
110
216
  def __eq__(self, other):
217
+ """
218
+ Check equality with another composite subject.
219
+
220
+ Args:
221
+ other (CompositeSubjectFactory): Another composite subject to compare with.
222
+
223
+ Returns:
224
+ bool: True if both subjects and chart name are identical.
225
+ """
111
226
  return self.first_subject == other.first_subject and self.second_subject == other.second_subject and self.name == other.chart_name
112
227
 
113
228
  def __ne__(self, other):
229
+ """
230
+ Check inequality with another composite subject.
231
+
232
+ Args:
233
+ other (CompositeSubjectFactory): Another composite subject to compare with.
234
+
235
+ Returns:
236
+ bool: True if subjects or chart name are different.
237
+ """
114
238
  return not self.__eq__(other)
115
239
 
116
240
  def __hash__(self):
241
+ """
242
+ Generate hash for the composite subject.
243
+
244
+ Returns:
245
+ int: Hash value based on both subjects and chart name.
246
+ """
117
247
  return hash((self.first_subject, self.second_subject, self.name))
118
248
 
119
249
  def __copy__(self):
250
+ """
251
+ Create a shallow copy of the composite subject.
252
+
253
+ Returns:
254
+ CompositeSubjectFactory: New instance with the same subjects and name.
255
+ """
120
256
  return CompositeSubjectFactory(self.first_subject, self.second_subject, self.name)
121
257
 
122
258
  def __setitem__(self, key, value):
259
+ """
260
+ Set an attribute using dictionary-style access.
261
+
262
+ Args:
263
+ key (str): Attribute name to set.
264
+ value: Value to assign to the attribute.
265
+ """
123
266
  setattr(self, key, value)
124
267
 
125
268
  def __getitem__(self, key):
269
+ """
270
+ Get an attribute using dictionary-style access.
271
+
272
+ Args:
273
+ key (str): Attribute name to retrieve.
274
+
275
+ Returns:
276
+ Any: Value of the requested attribute.
277
+
278
+ Raises:
279
+ AttributeError: If the attribute doesn't exist.
280
+ """
126
281
  return getattr(self, key)
127
282
 
128
283
  def _calculate_midpoint_composite_points_and_houses(self):
284
+ """
285
+ Calculate midpoint positions for all planets and house cusps in the composite chart.
286
+
287
+ This method implements the midpoint composite technique by:
288
+ 1. Computing circular means of house cusp positions from both subjects
289
+ 2. Sorting house positions to maintain proper house order
290
+ 3. Creating composite house cusps with calculated positions
291
+ 4. Computing circular means of planetary positions for common active points
292
+ 5. Assigning planets to their appropriate houses in the composite chart
293
+
294
+ The circular mean calculation ensures proper handling of zodiacal positions
295
+ around the 360-degree boundary (e.g., when one position is at 350° and
296
+ another at 10°, the midpoint is correctly calculated as 0°).
297
+
298
+ Side Effects:
299
+ - Updates instance attributes with calculated house cusp positions
300
+ - Updates instance attributes with calculated planetary positions
301
+ - Sets house assignments for each planetary position
302
+
303
+ Note:
304
+ This is an internal method called by get_midpoint_composite_subject_model().
305
+ Only planets that exist in both subjects' active_points are included.
306
+ """
129
307
  # Houses
130
308
  house_degree_list_ut = []
131
309
  for house in self.first_subject.houses_names_list:
@@ -165,12 +343,53 @@ class CompositeSubjectFactory:
165
343
  self[planet_lower]["house"] = get_planet_house(self[planet_lower]['abs_pos'], house_degree_list_ut)
166
344
 
167
345
  def _calculate_composite_lunar_phase(self):
346
+ """
347
+ Calculate the lunar phase for the composite chart based on Sun-Moon midpoints.
348
+
349
+ Uses the composite positions of the Sun and Moon to determine the lunar phase
350
+ angle, representing the relationship's emotional and instinctual dynamics.
351
+
352
+ Side Effects:
353
+ Sets the lunar_phase attribute with the calculated phase information.
354
+
355
+ Note:
356
+ This method should be called after _calculate_midpoint_composite_points_and_houses()
357
+ to ensure Sun and Moon composite positions are available.
358
+ """
168
359
  self.lunar_phase = calculate_moon_phase(
169
360
  self['moon'].abs_pos,
170
361
  self['sun'].abs_pos
171
362
  )
172
363
 
173
364
  def get_midpoint_composite_subject_model(self):
365
+ """
366
+ Generate the complete composite chart model using the midpoint technique.
367
+
368
+ This is the main public method for creating a composite chart. It orchestrates
369
+ the calculation of all composite positions and creates a complete CompositeSubjectModel
370
+ containing all necessary astrological data for the relationship chart.
371
+
372
+ The process includes:
373
+ 1. Calculating midpoint positions for all planets and house cusps
374
+ 2. Computing the composite lunar phase
375
+ 3. Assembling all data into a comprehensive model
376
+
377
+ Returns:
378
+ CompositeSubjectModel: Complete composite chart data model containing:
379
+ - All calculated planetary positions and their house placements
380
+ - House cusp positions maintaining proper house system order
381
+ - Lunar phase information for the composite chart
382
+ - All metadata from the original subjects (names, chart type, etc.)
383
+
384
+ Example:
385
+ >>> composite = CompositeSubjectFactory(person1, person2, "Our Relationship")
386
+ >>> model = composite.get_midpoint_composite_subject_model()
387
+ >>> print(f"Composite Sun at {model.sun.abs_pos}° in House {model.sun.house}")
388
+
389
+ Note:
390
+ This method performs all calculations internally and returns a complete,
391
+ ready-to-use composite chart model suitable for analysis or chart drawing.
392
+ """
174
393
  self._calculate_midpoint_composite_points_and_houses()
175
394
  self._calculate_composite_lunar_phase()
176
395