Aspects Module #
The AspectsFactory provides a unified interface for calculating angular relationships between planets. It handles both single-chart analysis (natal, return) and dual-chart analysis (synastry, transits).
Looking for
synastry/? There is nosynastrysubmodule: synastry isAspectsFactory.dual_chart_aspects()plusHouseComparisonFactoryandRelationshipScoreFactory. The v5SynastryAspectsclass was removed in v6; importing it raises a migration error pointing atdual_chart_aspectsand the migration guide.
What Are Aspects? #
Aspects are specific angular relationships between planets in a chart. They represent how planetary energies interact:
- Harmonious aspects (trines 120°, sextiles 60°) indicate ease and flow between planetary energies
- Challenging aspects (squares 90°, oppositions 180°) indicate tension, conflict, or dynamic growth opportunities
- Neutral/Mixed (conjunctions 0°) blend energies intensely, for better or worse depending on the planets involved
Aspects are fundamental to astrological interpretation, a chart without aspect analysis is like a musical score without chords.
Factory Methods #
1. single_chart_aspects #
Calculates aspects within a single astrological subject.
from kerykeion import AstrologicalSubjectFactory, AspectsFactory
# Create subject
subject = AstrologicalSubjectFactory.from_birth_data(
"Alice", 1990, 6, 15, 12, 0,
lng=-0.1276, lat=51.5074, tz_str="Europe/London", online=False,
)
# Calculate aspects
aspects_data = AspectsFactory.single_chart_aspects(subject)
print(f"Total Aspects: {len(aspects_data.aspects)}")
for aspect in aspects_data.aspects[:5]: # Show first 5
print(f"{aspect.p1_name} {aspect.aspect} {aspect.p2_name} (orb: {aspect.orbit:.2f}°)")
Expected Output:
Total Aspects: 34
Moon sextile Venus (orb: 3.93°)
Moon trine Jupiter (orb: 1.08°)
Moon sextile Neptune (orb: 1.08°)
Moon trine Pluto (orb: 0.60°)
Moon trine Chiron (orb: 1.25°)
Note: Orb values are always non-negative (absolute deviation from exact aspect). To determine whether an aspect is applying or separating, check the
aspect_movementfield ("Applying","Separating", or"Static").
2. dual_chart_aspects #
Calculates aspects between two different subjects (Synastry/Transits).
# Create second subject
subject_b = AstrologicalSubjectFactory.from_birth_data(
"Bob", 1992, 8, 20, 14, 30,
lng=-74.006, lat=40.7128, tz_str="America/New_York", online=False,
)
# Calculate synastry
synastry = AspectsFactory.dual_chart_aspects(subject, subject_b)
print(f"Synastry Aspects: {len(synastry.aspects)}")
Expected Output:
Synastry Aspects: 67
Additional Parameters for dual_chart_aspects:
| Parameter | Type | Default | Description |
|---|---|---|---|
first_subject_is_fixed |
bool |
False |
Treat first subject as stationary (natal). |
second_subject_is_fixed |
bool |
False |
Treat second subject as stationary. |
These parameters affect aspect movement calculation (applying/separating).
Deprecated compatibility aliases #
natal_aspects(subject, *, active_points=None, active_aspects=None, axis_orb_limit=None) delegates to single_chart_aspects(), while
synastry_aspects(first_subject, second_subject, *, active_points=None, active_aspects=None, axis_orb_limit=None) delegates to dual_chart_aspects().
Both aliases emit DeprecationWarning and are scheduled for removal in 7.0.0;
new code should call the corresponding primary method directly.
Configuration #
Supported Aspects #
Kerykeion calculates both major and minor aspects. Orbs can be customized.
| Aspect | Angle | Default Orb | Active by Default | Type |
|---|---|---|---|---|
| Conjunction | 0° | 6° | Yes | Major |
| Opposition | 180° | 6° | Yes | Major |
| Trine | 120° | 6° | Yes | Major |
| Square | 90° | 6° | Yes | Major |
| Sextile | 60° | 5° | Yes | Major |
| Quintile | 72° | 2° | No | Minor |
| Semi-sextile | 30° | 2° | No | Minor |
| Semi-square | 45° | 2° | No | Minor |
| Sesquiquadrate | 135° | 2° | No | Minor |
| Biquintile | 144° | 2° | No | Minor |
| Quincunx | 150° | 2° | No | Minor |
The orb values shown above are the base orbs from
DEFAULT_ACTIVE_ASPECTS/ALL_ACTIVE_ASPECTS.AspectsFactoryapplies no luminary widening unless a per-point adjustment table is supplied;ChartDataFactorynatal, synastry, and composite entry points resolveNoneto the Sun/Moon +1.5° preset. TheDEFAULT_ACTIVE_ASPECTSpreset includes only the five major aspects (conjunction, sextile, square, trine, opposition). To enable all 11 aspects, passactive_aspects=ALL_ACTIVE_ASPECTSfromkerykeion.settings.config_constants.
Filtering Options #
You can refine calculations by specifying which points or aspects to include.
By Points (active_points) #
Limit calculation to specific planets (e.g., only personal planets).
personal_planets = ["Sun", "Moon", "Mercury", "Venus", "Mars"]
aspects = AspectsFactory.single_chart_aspects(subject, active_points=personal_planets)
By Aspect Types (active_aspects) #
Define exactly which aspects to check and their specific orbs.
# Only look for exact major aspects (tight orbs)
custom_aspects = [
{"name": "conjunction", "orb": 3},
{"name": "opposition", "orb": 3},
{"name": "trine", "orb": 3},
{"name": "square", "orb": 3},
]
tight_aspects = AspectsFactory.single_chart_aspects(subject, active_aspects=custom_aspects)
Axis Orbs (axis_orb_limit) #
Apply stricter orbs when angles (Ascendant, MC) are involved. The value must be a finite positive number when provided.
# Standard orb for planets, but strict 2° orb for Angles
aspects = AspectsFactory.single_chart_aspects(subject, axis_orb_limit=2.0)
Per-point Orbs (point_orb_adjustments) #
Widen or tighten the orb for specific points (for example, give the luminaries a
larger orb). point_orb_adjustments maps a point name to a finite additive
adjustment in degrees, and point_orb_adjustment_strategy controls how the
two endpoints’ adjustments combine. NaN and infinite adjustments are rejected
before calculation.
| Strategy | Combination |
|---|---|
"max_explicit" (default) |
The larger of the adjustments that are actually configured. |
"min_explicit" |
The smaller of the configured adjustments — a negative one still tightens the pair. |
"sum" |
Both adjustments added together. |
"none" |
No adjustment; the base orb stands. |
Only explicitly configured points take part: an unconfigured endpoint is
absent from the comparison rather than counted as 0.0.
# Add 1.5° to aspects involving the Sun or Moon.
aspects = AspectsFactory.single_chart_aspects(
subject,
point_orb_adjustments={"Sun": 1.5, "Moon": 1.5},
)
A built-in preset, DEFAULT_NATAL_POINT_ORB_ADJUSTMENTS (luminary widening), is
available in kerykeion.settings.config_constants.
Aspect-keyed adjustments #
A point’s entry can also vary by aspect: instead of a single number, pass a
mapping of aspect name → adjustment, with "*" as the default for aspects not
listed. number and {"*": number} are equivalent.
aspects = AspectsFactory.single_chart_aspects(
subject,
point_orb_adjustments={
"Sun": {"*": 1.5, "conjunction": 3.0}, # 3.0° for Sun conjunctions, 1.5° otherwise
"Ascendant": {"conjunction": -3.0}, # configured ONLY for conjunctions
},
)
Without a "*" key, the point is unconfigured for the aspects it does not
list — not treated as 0.0. That preserves the explicit-only rule per aspect:
in the example above, a Mars–Ascendant trine resolves exactly as if the
Ascendant were absent from the table, so another point’s negative adjustment
still tightens the pair. Unknown aspect names log a warning (they can never
match) but do not raise, mirroring how active_aspects treats unknown names.
Return Data Structure #
The factory returns a SingleChartAspectsModel (for single charts) or DualChartAspectsModel (for dual charts) containing a list of AspectModel objects.
Key AspectModel Attributes:
p1_name,p2_name: Names of the two points involved.aspect: Name of the aspect (e.g.,"conjunction").orbit: The exact orb (absolute deviation from exact aspect, always non-negative).aspect_degrees: The theoretical angle (e.g., 120 for trine).aspect_movement:"Applying","Separating", or"Static".
Declination Aspects #
In addition to ecliptic (longitude) aspects, AspectsFactory supports declination-based aspects. Two points form a parallel when their declinations are within orb degrees of each other (both north or both south). A contra-parallel occurs when their declinations are equal in magnitude but opposite in sign.
single_chart_declination_aspects #
from kerykeion import AstrologicalSubjectFactory, AspectsFactory
subject = AstrologicalSubjectFactory.from_birth_data(
"Alice", 1990, 6, 15, 12, 0,
lng=-0.1276, lat=51.5074, tz_str="Europe/London", online=False
)
dec_aspects = AspectsFactory.single_chart_declination_aspects(subject, orb=1.0)
for asp in dec_aspects:
print(f"{asp.p1_name} {asp.aspect} {asp.p2_name} (orb: {asp.orbit:.2f})")
| Parameter | Type | Default | Description |
|---|---|---|---|
subject |
Subject | – | The astrological subject |
orb |
float | 1.0 | Finite, non-negative maximum orb in degrees |
active_points |
List or None | None | Points to include (defaults to subject’s list) |
dual_chart_declination_aspects #
subject_a = AstrologicalSubjectFactory.from_birth_data(
"Alice", 1990, 6, 15, 12, 0,
lng=-0.1276, lat=51.5074, tz_str="Europe/London", online=False
)
subject_b = AstrologicalSubjectFactory.from_birth_data(
"Bob", 1992, 8, 20, 14, 30,
lng=-74.0060, lat=40.7128, tz_str="America/New_York", online=False
)
dec_synastry = AspectsFactory.dual_chart_declination_aspects(subject_a, subject_b, orb=1.0)
Returns List[AspectModel] with aspect="parallel" or aspect="contra-parallel".
Its orb parameter has the same finite, non-negative contract as the
single-chart method.
Aspect Utilities #
Import from: kerykeion.aspects.utils
calculate_aspect_movement #
Determines if an aspect is Applying (orb decreasing) or Separating (orb increasing).
from kerykeion.aspects.utils import calculate_aspect_movement
movement = calculate_aspect_movement(
point_one_abs_pos=120.0,
point_two_abs_pos=122.0,
aspect_degrees=0, # Conjunction
point_one_speed=1.0, # Moving forward
point_two_speed=0.5 # Moving slower forward
)
# Returns "Applying" (Point one at 120° is behind point two at 122° and catching up due to higher speed)
Expected Output:
Applying
get_aspect_from_two_points #
Low-level function to check if two points form an aspect.
get_aspect_from_two_points(aspects_settings, point_one, point_two, extra_orb=0.0)
extra_orb accepts either a number, applied to every aspect’s base orb, or a
mapping of aspect name → adjustment (missing names get 0.0; the caller
resolves any "*" wildcard before building the mapping). The effective orb is
clamped to >= 0.0.
from kerykeion.aspects.utils import get_aspect_from_two_points
aspect = get_aspect_from_two_points(
[{"name": "trine", "degree": 120, "orb": 8}],
0.0,
120.5,
)
print(aspect["verdict"], aspect["name"], round(aspect["orbit"], 2))
Expected Output:
True trine 0.5
verdict is False when no configured aspect matches; orbit always reports
the distance from exactness.
get_active_points_list #
Extracts active celestial points from a subject based on configuration.
from kerykeion.aspects.utils import get_active_points_list
from kerykeion.settings import DEFAULT_CELESTIAL_POINTS_SETTINGS
points = get_active_points_list(
subject,
active_points=["Sun", "Moon", "Mercury"],
celestial_points=DEFAULT_CELESTIAL_POINTS_SETTINGS, # keyword-only; defaults to this
)
planet_id_decoder #
Converts a planet name to its Swiss Ephemeris ID.
from kerykeion.aspects.utils import planet_id_decoder
from kerykeion.settings import DEFAULT_CELESTIAL_POINTS_SETTINGS
swe_id = planet_id_decoder(DEFAULT_CELESTIAL_POINTS_SETTINGS, "Jupiter")
# Returns 5