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).

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, "London", "GB")

# 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: 24
Sun conjunction Mercury (orb: 3.45°)
Sun square Mars (orb: 2.18°)
Sun trine Jupiter (orb: 4.67°)
Sun sextile Ascendant (orb: 1.23°)
Moon opposition Saturn (orb: 5.89°)

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, "New York", "US")

# Calculate synastry
synastry = AspectsFactory.dual_chart_aspects(subject, subject_b)

print(f"Synastry Aspects: {len(synastry.aspects)}")

Expected Output:

Synastry Aspects: 31

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).

Configuration #

Supported Aspects #

Kerykeion calculates both major and minor aspects. Orbs can be customized.

Aspect Angle Default Orb Active by Default Type
Conjunction 10° Yes Major
Opposition 180° 10° Yes Major
Trine 120° Yes Major
Sextile 60° Yes Major
Square 90° Yes Major
Quintile 72° Yes 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 defaults from ALL_ACTIVE_ASPECTS. The DEFAULT_ACTIVE_ASPECTS preset includes only the first 6 aspects (Conjunction through Quintile). 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.

# Standard orb for planets, but strict 2° orb for Angles
aspects = AspectsFactory.single_chart_aspects(subject, axis_orb_limit=2.0)

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".

Aspect Utilities #

Import from: kerykeion.aspects.aspects_utils

calculate_aspect_movement #

Determines if an aspect is Applying (orb decreasing) or Separating (orb increasing).

from kerykeion.aspects.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.

from kerykeion.aspects.aspects_utils import get_aspect_from_two_points

aspect = get_aspect_from_two_points(
    [{"name": "trine", "degree": 120, "orb": 8}],
    0.0,
    120.5,
)
# Returns dict with aspect details if found, else verdict=False

get_active_points_list #

Extracts active celestial points from a subject based on configuration.

from kerykeion.aspects.aspects_utils import get_active_points_list

points = get_active_points_list(
    subject=subject,
    active_points=["Sun", "Moon", "Mercury"],
    celestial_points=settings.celestial_points  # keyword-only
)

planet_id_decoder #

Converts a planet name to its Swiss Ephemeris ID.

from kerykeion.aspects.aspects_utils import planet_id_decoder

swe_id = planet_id_decoder(planets_settings, "Jupiter")
# Returns 5

Need this in production? Use the Astrologer API for hosted calculations, charts, and AI interpretations - no server setup required. Learn more →