Skip to content

Latest commit

 

History

48 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LunaEph

Caution

警告:此仓库完全由 AI 自动生成,未经系统性的人工审查。许多实现存在大量 Bug、错误假设和未经充分验证的近似,请不要使用,也不要依赖这里的任何计算结果。

Warning: This repository was generated entirely by AI and has not received systematic human review. Many implementations contain bugs, incorrect assumptions, and insufficiently validated approximations. Do not use this project or rely on any of its results.

A lightweight, arcsecond-precision astrology engine for ±3000 years.

Pure Python. Zero native C/C++ dependencies. pip install and go.

Covers western tropical, Indian sidereal, and classical medieval techniques — all from a single calculate_chart() call. Built on taiyin-ephemeris-semi-analytic (∼0.2–3.7″ RMS vs DE441) with Vondrák 2011 precession, IAU 2000B nutation, WGS84 ellipsoid, and hybrid atmospheric refraction — hardcoded, no runtime data files.

Quick start

from lunaeph import calculate_chart

chart = calculate_chart(
    2003, 3, 13, 14, 15, 0,          # local date & time
    tz=8.0,                            # UTC+8
    latitude_deg=37.45,                # Dongying, Shandong
    longitude_deg=118.49,
)

# Planets
chart.planet("sun")          # {'name': 'Sun', 'sign': 'Pisces', 'degree': 22, ...}
chart.planets                # ['sun', 'moon', 'mercury', ...]

# Houses
chart.ascendant              # {'sign': 'Leo', 'degree': 5, 'minute': 32}
chart.midheaven              # {'sign': 'Aries', 'degree': 24, 'minute': 31}

# Aspects
chart.aspects_to("moon")     # filter by body
chart.aspects_between("sun", "moon")

# Custom orbs
chart.set_orb(60, 1.0)       # sextile → 1° orb
chart.reset_orb(60)          # back to default

Feature overview

Category What Detail
Planets 10 bodies + lunar nodes + Lilith Sun through Pluto, True/Mean Node, True/Mean Lilith
Houses 8 systems Placidus, Koch, Whole Sign, Equal, Porphyry, Regiomontanus, Campanus, Alcabitius
Aspects 12 angles + custom Conjunction, opposition, trine, square, sextile, quincunx, semisextile, semisquare, sesquiquadrate, quintile, biquintile, decile; applying/separating via true velocity
Signs Tropical + sidereal 12 tropical signs (element/modality/triplicity); 6 ayanamshas (Lahiri, Fagan-Bradley, Raman, Krishnamurti, Yukteswar, True Chitra)
Dignities Essential + accidental Domicile, detriment, exaltation, fall, Dorothean triplicities, Chaldean faces, Ptolemaic & Egyptian terms, sect, combustion, cazimi
Lots Hellenistic / Arabic Parts Fortune, Spirit, Eros, Nemesis, Victory, Courage, Necessity, and more
Relationship Synastry, Composite, Davison Cross-chart aspects + house overlays; midpoint composite; time/space Davison
Predictive Progressions + directions Secondary, Tertiary I & II, Minor; True Solar Arc; Naibod direction
Returns Solar + Lunar Returns Exact Brent root-finding on true ecliptic longitude recurrence
Medieval Almuten, Firdaria, ZR, Profections, Primary Directions Ibn Ezra / Bonatti / Lilly schools; Valens/Brennan ZR; Naibod/Ptolemy keys
Jyotish Nakshatra, Dasha, Vargas, Karakas 27/28 Nakshatras with Ashta Kuta; Vimshottari (5-level) & Yogini Dasha; 16 Vargas (D1–D60); Chara/Sthira/Naisargika Karakas
Jyotish II Ashtakavarga, Arudha, Upagraha, KP Sarvashtakavarga; Jaimini Arudha Padas; 5 Upagrahas; KP sub-lord; Panchadha Maitri
Time utils EoT, sunrise/sunset, syzygy Equation of time; WGS84 ellipsoid + hybrid Bennett/Smart refraction; new/full moon sequence; apparent solar time

Western astrology

Houses & signs

from lunaeph import calculate_chart, HouseSystem

chart = calculate_chart(2003, 3, 13, 14, 15, 0, tz=8.0,
                        latitude_deg=37.45, longitude_deg=118.49,
                        house_system=HouseSystem.KOCH)

for i in range(1, 13):
    cusp = chart.house_cusp(i)
    print(f"House {i:2d}: {cusp['sign_abbrev']:>3s} {cusp['degree']:2d}°{cusp['minute']:02d}'")

# Custom orbs
chart.set_orb(72, 2.0)   # quintile → 2°
chart.set_orb(100, 1.5)  # custom angle → 1.5°

Relationship charts

# Dongying native (2003-03-13) × a friend (2002-12-01)
a = calculate_chart(2003, 3, 13, 14, 15, 0, tz=8.0,
                    latitude_deg=37.45, longitude_deg=118.49)
b = calculate_chart(2002, 12, 1, 8, 30, 0, tz=8.0,
                    latitude_deg=36.0, longitude_deg=120.0)

syn = a.synastry_with(b)                # cross-chart aspects + house placements
comp = a.composite_with(b)              # midpoint composite
dav = a.davison_with(b, mode="spherical")  # Davison time/space chart

# Synastry cross-aspects (planet-to-planet only, top 5)
for entry in syn["cross_aspects"][:5]:
    print(f"{entry['chart_a_body']:8s}─{entry['chart_b_body']:8s}  "
          f"{entry['aspect']:14s}  {entry['orb_deg']:.2f}°  "
          f"{'A' if entry.get('applying') else 'S'}")
#  sun     ─moon      quincunx        1.14°  A
#  sun     ─mercury   square          4.29°  S
#  sun     ─mars      biquintile      1.37°  S
#  sun     ─saturn    square          4.69°  A
#  sun     ─neptune   semisquare      1.42°  A

Progressions & returns

chart = calculate_chart(2003, 3, 13, 14, 15, 0, tz=8.0,
                        latitude_deg=37.45, longitude_deg=118.49)

prog  = chart.secondary_progression(years=20.0)  # 1 day = 1 year (age 20)
tert  = chart.tertiary_progression(years=20.0)   # Tertiary I
sa    = chart.solar_arc(years=20.0)              # True Solar Arc
sr23  = chart.solar_return(2023)                 # Solar Return for 2023
lr    = chart.lunar_return(2023, 3)              # Lunar Return for Mar 2023

Classical techniques

# Almuten Figuris (Victor of the Chart)
alm = chart.almuten_figuris()             # → 'venus', score 33

# Firdaria (Persian time-lord periods)
from lunaeph import get_current_firdaria
fird = chart.firdaria(age=33.5)           # active major & minor periods

# Zodiacal Releasing (Valens)
zr = chart.zodiacal_releasing(lot="spirit", age=33.5)

# Annual / Monthly / Daily Profections
prof = chart.profection(age=33.5)

# Primary Directions (Naibod key)
from lunaeph import calc_primary_directions
dirs = chart.primary_directions(key="naibod")

# Arabic Lots
from lunaeph import calculate_lots
lots = calculate_lots(asc_deg, sun_deg, moon_deg, ...)

Indian / Vedic (Jyotish)

Nakshatras & compatibility

from lunaeph import calc_nakshatra_chart, calc_nakshatra_compatibility, get_nakshatra_info

# Planetary placements in the standard 27-Nakshatra system.  Pass
# system="28" to additionally report overlapping Abhijit membership; it does
# not replace the primary 27-Nakshatra placement.
nak = chart.nakshatra_chart(ayanamsha_mode="lahiri", system="27")
# → {'sun': {'nakshatra': 'Purva Bhadrapada', 'pada': 3, ...}, ...}

# Ashta Kuta compatibility
score = chart_a.nakshatra_compatibility(chart_b, ayanamsha_mode="lahiri")
# → {'total': 24.5, 'varna': 1, 'vashya': 2, 'tara': 3, ...}

# Single nakshatra info
info = get_nakshatra_info("Rohini")
# → {'lord': 'moon', 'deity': 'Brahma', 'gana': 'Manushya', ...}

Dasha systems

# Vimshottari Dasha (120-year, 5-level recursive)
dasha = chart.vimshottari_dasha(age=20.35, ayanamsha_mode="lahiri")
# → maha, antara, pratyantara, sookshma, prana breakdown

# Yogini Dasha (36-year cycle)
from lunaeph import calc_yogini_dasha
yog = chart.yogini_dasha(age_years=20.35)

# Convenience: current active period
from lunaeph import get_current_dasha
active = get_current_dasha(chart, age=20.35)

Divisional charts (Vargas)

# All 16 Vargas (D1 Rashi through D60 Shashtiamsha)
from lunaeph import calculate_divisional_charts
vargas = chart.divisional_charts(ayanamsha_mode="lahiri")
# → D1, D2 Hora, D3 Drekkana, D4, D7, D9 Navamsha, D10, D12, D16,
#   D20, D24, D27 Bhamsha, D30 Trimshamsha, D40, D45, D60

More Jyotish tools

# Jaimini Chara Karakas (7 or 8 planet scheme)
k = chart.jaimini_chara_karakas(scheme="8_karaka")

# Ashtakavarga (Sarvashtakavarga, max 337 bindus)
av = chart.ashtakavarga()        # → bhinnashtakavarga per planet + sarva totals

# Arudha Padas (A1–A12, including Upapada/UL)
ap = chart.arudha_padas()        # → {'A1': ..., 'upapada': ...}

# Sade Sati (Saturn 7.5-year transit)
chart.sade_sati("Capricorn")     # is Saturn transiting over natal Moon?

# Upagrahas (5 shadow planets)
chart.upagrahas()                # → Dhuma, Vyatipata, Parivesha, Indrachapa, Upaketu

# KP system
chart.kp_sublord(planet="moon")  # → star-lord + sub-lord

# All three karaka systems
from lunaeph import calc_all_karakas
all_k = chart.karakas()          # → Naisargika, Sthira, Chara

Time & calendar utilities

Equation of time

from lunaeph import equation_of_time_minutes, apparent_solar_time_minutes
from lunaeph._time import calendar_to_jd

jd = calendar_to_jd(2024, 11, 3, 12, 0, 0.0)
eot = equation_of_time_minutes(jd)          # → +16.48 min (sundial ahead of clock)
ast = apparent_solar_time_minutes(jd, lon_deg=116.4)  # → minutes since midnight

Sunrise, sunset & twilight

from lunaeph import sun_times

times = sun_times(2003, 3, 13, lon_deg=118.49, lat_deg=37.45, tz=8.0)
# → {'rise': JD, 'transit': JD, 'set': JD,
#     'civil_dawn': JD, 'civil_dusk': JD,
#     'nautical_dawn': JD, 'nautical_dusk': JD,
#     'astron_dawn': JD, 'astron_dusk': JD}
# Uses WGS84 ellipsoid + hybrid Bennett/Smart refraction model.
# Also accepts height_m, pressure_mbar, temperature_c for precision.

New & full moons

from lunaeph import new_moons_between, full_moons_between, calendar_to_jd, jd_to_calendar

jd1 = calendar_to_jd(2003, 1, 1)
jd2 = calendar_to_jd(2004, 1, 1)

for jd in new_moons_between(jd1, jd2):    # 12–13 per year
    y, m, d, h, mi, s = jd_to_calendar(jd)
    print(f"New moon: {y}-{m:02d}-{d:02d} {h:02d}:{mi:02d} UT")
# Accuracy: < 5 minutes vs USNO across −3000 to +3000.

Astronomy

Correction Model
Planetary ephemeris taiyin semi-analytic (~0.2–3.7″ RMS vs DE441)
Precession Vondrák 2011
Nutation IAU 2000B (77 lunisolar + planetary terms)
ΔT Stephenson & Morrison (2004/2015) spline + annual Catmull-Rom table
Light-time single-pass iteration
Stellar aberration special-relativistic velocity form
Solar deflection GR deflection vector
Atmospheric refraction Hybrid Bennett + Smart, scaled by P/T
Earth shape WGS84 ellipsoid (a=6378137 m, 1/f=298.257223563)

All models are hardcoded — no runtime data files, same philosophy as taiyin.

Installation

pip install lunaeph

Depends on taiyin-ephemeris-semi-analytic>=0.2.0.

License

Apache 2.0.

Acknowledgements

  • 寿星天文历 (sxwnl) by 许剑伟 — https://github.com/sxwnl/sxwnl
    The Equation of Time, sunrise/sunset/twilight, and syzygy sequence algorithms are adapted from this project. See NOTICE for the full copyright notice.

About

A lightweight, arcsecond-precision astrology engine for ±3000 years — western, vedic, classical. Pure Python, zero native deps.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages