Try Astrologer API

Subscribe to support and grow the project.

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 no synastry submodule: synastry is AspectsFactory.dual_chart_aspects() plus HouseComparisonFactory and RelationshipScoreFactory. The v5 SynastryAspects class was removed in v6; importing it raises a migration error pointing at dual_chart_aspects and 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_movement field ("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 Yes Major
Opposition 180° Yes Major
Trine 120° Yes Major
Square 90° Yes Major
Sextile 60° Yes Major
Quintile 72° No Minor
Semi-sextile 30° No Minor
Semi-square 45° No Minor
Sesquiquadrate 135° No Minor
Biquintile 144° No Minor
Quincunx 150° No Minor

The orb values shown above are the base orbs from DEFAULT_ACTIVE_ASPECTS / ALL_ACTIVE_ASPECTS. AspectsFactory applies no luminary widening unless a per-point adjustment table is supplied; ChartDataFactory natal, synastry, and composite entry points resolve None to the Sun/Moon +1.5° preset. The DEFAULT_ACTIVE_ASPECTS preset includes only the five major aspects (conjunction, sextile, square, trine, opposition). To enable all 11 aspects, pass active_aspects=ALL_ACTIVE_ASPECTS from kerykeion.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