Three distinct audiences, each with different needs, different workflows, and different reasons to choose Moira over the alternatives.
Building production applications
Moira's MIT license and layered import surfaces make it a practical foundation for applications that need astronomical computation without AGPL licensing constraints.
from moira.facade import Moira, HouseSystem
from datetime import datetime, timezone
# Initialize once; kernel auto-detected
m = Moira()
def calculate_chart(birth_dt: datetime, lat: float, lon: float) -> dict:
chart = m.chart(birth_dt)
houses = m.houses(birth_dt, latitude=lat, longitude=lon,
system=HouseSystem.PLACIDUS)
aspects = m.aspects(chart)
return {
"planets": {
name: {"longitude": p.longitude, "speed": p.speed}
for name, p in chart.planets.items()
},
"asc": houses.asc,
"mc": houses.mc,
"aspects": [
{"body1": a.body1, "aspect": str(a.aspect), "orb": a.orb}
for a in aspects
],
}Reproducible astronomical studies
Moira's transparent reduction pipeline, documented residuals, and physical ΔT model make it suitable for academic research where reproducibility and methodology transparency are required.
from moira.facade import Moira, delta_t, delta_t_breakdown
from moira.classical import star_at
from moira.stars import star_light_time_split
from datetime import datetime, timezone
m = Moira(kernel_path="/data/de441.bsp")
jd_tt = 2451545.0 # J2000.0
# Inspect ΔT with full breakdown
dt_val = delta_t(jd_tt)
breakdown = delta_t_breakdown(jd_tt)
print(f"ΔT = {dt_val:.6f}s ±{breakdown.uncertainty_1sigma:.4f}s")
# Gaia DR3 stellar positions with light-time split
observed, true_pos = star_light_time_split("Arcturus", jd_tt)
print(f"Observed: {observed.longitude:.6f}°")
print(f"True: {true_pos.longitude:.6f}°")
print(f"Δ = {abs(observed.longitude - true_pos.longitude)*3600:.4f} arcsec")Professional astrological work
Moira provides broad Western, Hellenistic, Medieval, and Vedic computation surfaces, from primary directions to Vimshottari Dasha, in a single library.
from moira.vedic import vimshottari
from moira.classical import firdaria, zodiacal_releasing
from moira.predictive import synastry_aspects, composite_chart
# Vimshottari Dasha with sub-periods
periods = vimshottari(
chart.planets["Moon"].longitude,
chart.jd_ut,
levels=3,
)
for period in periods[:3]:
print(f"{period.planet:10s} {period.start_jd:.5f} → {period.end_jd:.5f}")
for sub in period.sub[:2]:
print(f" {sub.planet:10s} {sub.start_jd:.5f}")
# Synastry between two charts
chart_b = m.chart(partner_dt)
synastry = synastry_aspects(chart, chart_b)
for a in synastry[:5]:
print(f"{a.body1} {a.aspect} {a.body2} — orb {a.orb:.2f}°")Install Moira, download a JPL kernel, and compute your first chart in under five minutes.