Relational Charts: Synastry and Composite

Relational charts analyse two people’s charts together rather than in isolation. Ketu provides three modules for this: ketu.charts builds the individual charts, ketu.synastry compares them aspect by aspect, and ketu.composite derives a midpoint chart that represents the relationship itself.

Building Charts with compute_chart

compute_chart is the central function for natal chart calculation. It calculates all 14 body positions, twelve house cusps, the four angles, and the full aspect matrix in a single call, returning a CHART_DTYPE structured array.

compute_chart(jd, lat, lon, system="placidus", aspects=None, polar_fallback="raise")

Parameters

  • jd — Julian Day (float, UTC)

  • lat / lon — geographic latitude and longitude in degrees

  • system — house system (default "placidus")

  • aspects — aspect set spec (None uses the library default — TRADITIONAL, the 7 half-circle aspects, v1.3+)

  • polar_fallback — high-latitude fallback behaviour (see House Systems)

Example — two charts

from ketu.charts import compute_chart

jd_a = 2451545.0          # 2000-01-01 12:00 UTC (J2000), Paris
jd_b = 2451910.0          # 2000-12-31 12:00 UTC, New York

chart_a = compute_chart(jd_a, 48.8566, 2.3522)      # Paris
chart_b = compute_chart(jd_b, 40.7128, -74.0060)    # New York

print(chart_a["asc"])                  # Ascendant of chart A
print(chart_b["body_lons"][0])         # Sun longitude of chart B

CHART_DTYPE Fields

Field

Shape

Description

jd

scalar

Julian Day

lat

scalar

Geographic latitude

lon

scalar

Geographic longitude

system

scalar

House system name

body_lons

[14]

Ecliptic longitudes for bodies 0–13

body_lats

[14]

Ecliptic latitudes for bodies 0–13

body_speeds

[14]

Daily motion in degrees for bodies 0–13

cusps

[12]

House cusp longitudes

asc

scalar

Ascendant longitude

mc

scalar

Midheaven longitude

armc

scalar

ARMC (sidereal time angle)

vertex

scalar

Vertex longitude

aspect_matrix

[14, 14]

Aspect type between each body pair (0 = none)

aspect_orbs

[14, 14]

Orb in degrees for each active aspect

Body index 13 is Chiron (see Chiron).

Sect Helper

from ketu.charts import is_day_chart

# Returns True if the Sun is above the horizon (day chart)
is_day = is_day_chart(jd_a, 48.8566, 2.3522)

This is used internally by Arabic Parts to select sect-aware formulas.

Synastry

Synastry overlays two charts and finds aspects formed between the planets of one person and the planets of the other.

from ketu.synastry import calculate_synastry, SYNASTRY_DTYPE

calculate_synastry(chart_a, chart_b, aspects="classical", orbs="synastry", mode="filtered")

Parameters

  • chart_a, chart_bCHART_DTYPE structured arrays from compute_chart

  • aspects — aspect set: "classical", "traditional", "extended", or a list/mask. calculate_synastry’s own default is "classical" (5 major aspects), pinned for backward-compatible byte stability — this is distinct from the library-wide default of calculate_aspects, which is TRADITIONAL (7 half-circle aspects, v1.3+).

  • orbs — orb set: "synastry" applies the standard synastry orb reduction factor

  • mode"filtered" returns only active aspects; "all" returns every body pair

Example

from ketu.charts import compute_chart
from ketu.synastry import calculate_synastry

jd_a = 2451545.0
jd_b = 2451910.0

chart_a = compute_chart(jd_a, 48.8566, 2.3522)
chart_b = compute_chart(jd_b, 40.7128, -74.0060)

aspects = calculate_synastry(chart_a, chart_b)

for row in aspects:
    print(
        f"Body {row['body_a']} ({row['lon_a']:.1f} deg)"
        f" {row['aspect_type']}"
        f" Body {row['body_b']} ({row['lon_b']:.1f} deg)"
        f"  orb={row['orb']:.2f} deg"
        f"  applying={row['applying']}"
    )

SYNASTRY_DTYPE Fields

Field

Type

Description

body_a

int

Body index from chart A (0–15; 14=ASC, 15=MC)

body_b

int

Body index from chart B (0–15)

lon_a

float64

Ecliptic longitude of body A

lon_b

float64

Ecliptic longitude of body B

aspect_type

int

Aspect type code

orb

float64

Orb in degrees

applying

bool

True if the aspect is applying

orb_limit

float64

Maximum allowed orb for this aspect

Synastry includes ASC and MC from both charts, giving up to 16 points per chart.

Composite Charts

A composite chart is constructed from the midpoints of each pair of planets, houses, and angles between two natal charts. It represents the energy of the relationship rather than either individual.

from ketu.composite import calculate_composite, circular_midpoint

calculate_composite(chart_a, chart_b, system="placidus")

Returns a single CHART_DTYPE structured array. The house system is re-calculated from the composite Ascendant and Midheaven.

from ketu.charts import compute_chart
from ketu.composite import calculate_composite, circular_midpoint

jd_a = 2451545.0
jd_b = 2451910.0

chart_a = compute_chart(jd_a, 48.8566, 2.3522)
chart_b = compute_chart(jd_b, 40.7128, -74.0060)

composite = calculate_composite(chart_a, chart_b)

print(composite["asc"])            # Composite Ascendant
print(composite["body_lons"][0])   # Composite Sun

circular_midpoint

circular_midpoint computes the shortest-arc midpoint between two ecliptic longitudes, handling the 0°/360° wraparound correctly.

from ketu.composite import circular_midpoint

# Midpoint of 350° and 10° crosses the 0°-point: result is 0°
mid = circular_midpoint(350.0, 10.0)
print(mid)   # 0.0

# Standard midpoint
mid2 = circular_midpoint(30.0, 90.0)
print(mid2)  # 60.0

Next Steps