moira

Moira

Astronomy-First Ephemeris and Astrology Computation Engine

Python MIT License PyPI Native Core Precision: ERFA-Audited Light Box: P0 Receipted Ephemeris: JPL DE4xx AI Visibility: Optimized DOI

Moira is a sovereign, astronomy-first computation engine built for transparent astrological derivation, reproducible chart reduction, and an inspectable calculation chain from physical ephemerides to astrological outputs. Grounded in JPL DE441/DE440 state vectors, IAU 2000A/2006 precession-nutation models, ERFA/SOFA-aligned astrometry, and Gaia DR3-linked stellar catalogs, Moira pairs a zero-dependency Python orchestration and policy layer with a required C++17 numerical extension (_moira_native, compiled via pybind11).

Where conventional astrology libraries return terminal numbers from opaque defaults, Moira operates as a Light Box: computation stages are named and individually toggleable, doctrinal and source variants are explicit parameters rather than silent assumptions, and validation is maintained as version-bound, replayable evidence.


Table of Contents


Why Moira & The Light Box Doctrine

Astronomy is the foundation. Astrology is the purpose. Validation is the proof. Visibility is the doctrine.

Pillar What Moira Guarantees
Sovereign Astronomical Substrate Direct native C++17 SPK/DAF reading of published JPL DE441/DE440/DE430 Chebyshev records and Type-13 Hermite small-body shards. No jplephem, Swiss Ephemeris, or third-party runtime wrapper.
Light Box Inspectability Every major reduction stage—light-time iteration, gravitational deflection, relativistic aberration, IAU 2006 frame bias, P03 precession, IAU 2000A nutation, WGS-84 topocentric parallax, and refraction—is exposed as a typed breakdown or ComputationTruth receipt.
Explicit Doctrinal Policy Competing classical and modern traditions (house polar fallbacks, sect horizon conventions, Egyptian vs. Ptolemaic bounds, BPHS vs. Saravali vs. Jaimini profile lineages, Addey harmonic orbs) are represented by immutable policy objects and source-cited receipts rather than silent defaults.
Zero-Dependency Base Runtime Base moira-astro requires only the Python standard library plus its compiled _moira_native extension. Optional FastAPI transport (moira-astro[server]) and lunar-graze tooling (moira-astro[lunar-graze]) live behind strict feature boundaries.
Audit-Ready Conformance Across 1,251 canonical public calculations in 150 families, 100% of P0 production-user calculations (171 / 171) and 209 total canonical surfaces are governed by 63 exact-source replay contracts under LIGHT_BOX_CURRENT_STATUS.generated.md.

Who It Is For: Developers, ephemeris engineers, historians of astronomy/astrology, and researchers who require a programmable, audit-grade engine for reproducible pipelines and rigorous comparison against primary texts and physical oracles.

What It Is Not: Moira is not a consumer UI application, not a thin wrapper over opaque compiled stacks, and not convenience-first text generation without mathematical traceability.


Requirements and Installation

# Standard engine install (uses a published wheel when available)
pip install moira-astro

# With the FastAPI REST server (FastAPI, Starlette, Uvicorn, Pydantic)
pip install "moira-astro[server]"

# With Lunar Graze support (spiceypy, laspy, requests)
pip install "moira-astro[lunar-graze]"

[!NOTE] This README documents the current main branch (6.10.1). The PyPI badge identifies the latest packaged release; features merged after that release require a source checkout until the next version is published.


Quick Start

Moira initializes cleanly even before a planetary kernel is configured. Kernel-dependent calls (such as m.chart()) raise an explicit MissingEphemerisKernelError with remediation instructions until a kernel is present in kernels/ or ~/.moira/kernels/.

from datetime import datetime, timezone
from moira import HouseSystem, Moira
from moira.facade import planet_reduction_breakdown_at
from moira.houses import house_of
from moira.patterns import find_all_patterns

m = Moira()
dt = datetime(2000, 1, 1, 12, 0, tzinfo=timezone.utc)

# 1. Planetary chart reduction
chart = m.chart(dt)
print(f"Sun:  {chart.planets['Sun'].longitude:.6f} deg ({chart.planets['Sun'].sign})")
print(f"Moon: {chart.planets['Moon'].longitude:.6f} deg ({chart.planets['Moon'].sign})")

# 2. House cusps and placement (Placidus, London)
houses = m.houses(
    dt,
    latitude=51.5074,
    longitude=-0.1278,
    system=HouseSystem.PLACIDUS,
)
sun_house = house_of(chart.planets["Sun"].longitude, houses)
print(f"ASC: {houses.asc:.4f} deg | MC: {houses.mc:.4f} deg | Sun House: {sun_house}")

# 3. Aspect pattern detection
for pattern in find_all_patterns(chart.longitudes()):
    print(f"{pattern.name}: {', '.join(pattern.bodies)}")

# 4. Light Box inspectability: per-stage astrometric breakdown at JD_UT1 2451545.0
breakdown = planet_reduction_breakdown_at("Mars", 2451545.0)
print(f"Mars apparent longitude: {breakdown.final_longitude:.6f} deg")
print(f"Light-time delay (days): {breakdown.light_time_days:.6f}")

The Reduction Pipeline

flowchart TD
    A["JPL Planetary Kernel<br/>Chebyshev state vectors"] --> B["SSB Barycentric Position<br/>km · ICRF"]
    C["Sovereign Star Registry<br/>1,809 named stars"] --> D["Stellar Astrometric Position<br/>proper motion · parallax"]
    B --> E["1 · Light-Time Iteration<br/>body at t − τ  (τ = d/c)"]
    E --> F["2 · Gravitational Deflection<br/>Sun · Jupiter · Saturn"]
    F --> G["3 · Annual Aberration<br/>relativistic · IAU SOFA"]
    G --> H["4 · IAU 2006 Frame Bias<br/>ICRF → Mean Equator J2000"]
    D --> H
    H --> I["5 · IAU 2006 Precession<br/>P03 polynomial series"]
    I --> J["6 · IAU 2000A Nutation<br/>1358 luni-solar + 1056 planetary terms"]
    J --> K["True Equinox and Equator of Date"]
    K --> L["7 · Topocentric Parallax<br/>WGS-84 · optional"]
    K --> N["Ecliptic Projection<br/>True obliquity of date"]
    L --> R["8 · Diurnal Aberration<br/>observer rotation · optional"]
    R --> M["Atmospheric Refraction<br/>sky altitude only · optional"]
    N --> O["Zodiacal Longitude · Latitude · Distance"]
    K --> P["Sidereal Frame · Ayanamsa<br/>optional"]
    K --> Q["House Cusps · 22 Systems<br/>requires lat/lon"]

Worked Example: Mars at 2000-01-01 12:00 UT1

This snapshot is reproduced by planet_reduction_breakdown_at("Mars", 2451545.0, reader) with the admitted DE441 kernel. The input is JD_UT1 2451545.0; it is about 63.829 seconds after the exact J2000.0 TT epoch and is therefore not labelled as exact J2000.0.

Time: JD_UT1 2451545.000000 → JD_TT 2451545.000739 ($\Delta T = +63.829\text{ s}$)

Stage Operation Engine receipt Longitude contribution
0 Geometric geocentric SSB-to-Mars minus SSB-to-Earth; $\lambda = 327.975456^\circ$; distance = 276,697,408.4 km reference
1 Light-time iteration $\tau = 0.010683\text{ days} = 15.383\text{ min}$ $-15.762371^{\prime\prime}$
2 Gravitational deflection Sun, Jupiter, and Saturn $-0.003057^{\prime\prime}$
3 Annual aberration Earth barycentric velocity; relativistic $-14.069158^{\prime\prime}$
4 IAU 2006 frame bias ICRF to dynamical mean J2000 $+0.000300^{\prime\prime}$
5 IAU 2006 precession P03; mean equator/ecliptic of date $+0.006571^{\prime\prime}$
6 IAU 2000A nutation $\Delta\psi = -13.932004^{\prime\prime}$; $\Delta\varepsilon = -5.769413^{\prime\prime}$ $-13.932004^{\prime\prime}$
7–8 Topocentric parallax and diurnal aberration disabled for this geocentric example $0$

Final position: Aquarius 27° 57′ 48″ · $\lambda = 327.963300^\circ$ · $\beta = -1.067779^\circ$ · distance = $1.849688\text{ AU}$ · speed = $+0.775674^\circ/\text{day}$

Total visible reduction from the geometric J2000-ecliptic reference to the final true-of-date ecliptic longitude: $-43.759719\text{ arcseconds}$.

The stage contributions above come from the typed reduction receipt. They should not be reconstructed by subtracting unrelated coordinate frames or by treating apparent=False as “no frame transformation.”

Pipeline Controls

Selected correction policies can be toggled via planet_at(). The table below shows the measurable effect of disabling each exposed policy in this JD_UT1 = 2451545.0 Mars snapshot.

Parameter Default Effect on snapshot longitude Function
apparent=True True Full pipeline active planet_at()
apparent=False — Omits light-time, deflection, and aberration while retaining the declared ecliptic-of-date frame and nutation policy. $\Delta = \mathbf{+29.835\text{ arcsec}}$ planet_at()
aberration=False — Aberration stage skipped. $\Delta = \mathbf{+14.069\text{ arcsec}}$ planet_at()
grav_deflection=False — Deflection stage skipped. $\Delta = \mathbf{+0.003\text{ arcsec}}$ planet_at()
nutation=False — Nutation skipped; mean equinox used. $\Delta = \mathbf{+13.932\text{ arcsec}}$ planet_at()
observer_lat/lon None When supplied together, adds WGS-84 topocentric parallax and observer-rotation diurnal aberration; the effect is body-, location-, and epoch-dependent. planet_at()
refraction=True True Applies the declared pressure, temperature, and humidity model to geometric sky altitude. sky_position_at()
delta_t_policy None Controls UT → TT conversion branch (IERS tables, polynomial, hybrid physical). both

What Moira Computes

Positions and Celestial Catalogs

Chart Architecture and Traditional Western

Predictive and Time-Lord Techniques

Vedic / Jyotish Suite

Admitted Vedic surfaces name their governing classical source, modern lineage, or source-scoped witness (including Brihat Parashara Hora Shastra [BPHS], Brihat Jataka, Saravali, Phaladeepika, Uttara Kalamrita, Jataka Parijata, Jaimini Upadesa Sutras, and the named 1879 Agastya- and 2024 Bogamuni-attributed Pancha Pakshi witnesses). Where sources disagree or a modern composition is required, Moira exposes the policy or qualification instead of presenting one silent universal rule.

Expand Pancha Pakshi Source-Scoped Boundary Contract (Madras 1879 & Bogamuni 2024) - **Madras 1879 Fixed-Clock Schedule & Directed Relationship Profile:** An explicitly named Agastya-attributed Madras 1879 aksara/query-or-name-initial fixed-clock schedule and directed relationship profile, with exact rational timing, source locators, declared omissions, and no implicit or universal default. - **Standalone Astronomical Paksha:** Evaluates apparent geocentric Moon-minus-Sun longitude in the true ecliptic of date and maps `[0, 180)` Shukla/waxing to the profile's source-attested Purva label and `[180, 360)` Krishna/waning to Amara. It accepts no location and never selects a schedule, materializes a clock, supplies paksha to another operation, or infers natal identity. - **Local-Solar Context, Fixed-Clock, and Solar-Proportional Policies:** An explicit modern local-solar context policy derives topocentric day/night and local-mean-solar weekday for an aware instant and location while requiring the caller to supply Purva or Amara. A separate modern fixed-clock policy anchors the selected schedule at sunrise or sunset, treats one nazhigai as exactly 1,440 SI seconds on reader-bound TT, and publishes half-open UT1 cell intervals plus their unclipped relation to the astronomical half end (returning `unmaterialized_solar_half_tail` when a long solar half outlasts the fixed span). A distinct modern solar-proportional policy maps nominal offset fractions across the complete governing day or night half on reader-bound TT (25 half-open TT/UT1 cells with exact boundary closure; status is always `selected`). The 1879 witness is not credited with that proportional rule. - **Stage 2I First-Samam EAT Seed Lookup:** Exposes the selected 1879 generator's first-samam EAT seed from explicit profile Paksha, day/night half, and weekday without materializing the schedule or promoting that seed into a whole-day eating bird, Padu, authority, Adhikara/Bharana, condition, score, or forecast. All 28 cells are bound to the 1879 leaves and corroborated by the 1934 Uromarisi publication. - **Bogamuni 2024 Nakshatra & Padu Profiles:** Preserves the 54-cell Purva/Amara-by-nakshatra bird table (where the Amara verse governs and the malformed adjacent commentary duplicating Shravana and omitting Revati is retained as rejected conflict evidence). The fixed modern `bogamuni_2024_apparent_lahiri_natal_moon_identity_v1` composition evaluates apparent geocentric Sun and Moon positions on one reader-bound TT epoch, applies Lahiri true ayanamsa, assigns the Moon to one of 27 equal half-open nakshatras, and returns the selected source-table bird with every intermediate visible. A separate `bogamuni_chennai_2024_padu_bird_mapping` profile preserves the 14-cell Purva/Amara-by-weekday Padu-bird lookup without day/night axis or schedule/forecast routing.

Phenomena, Visibility, and Locational Astronomy


REST API Server (moira_server)

Moira includes an optional FastAPI transport layer (moira_server) that exposes 531 OpenAPI operations (527 versioned /v1 routes plus 4 operational endpoints) with strict Pydantic request/response validation and embedded provenance receipts.

pip install "moira-astro[server]"
uvicorn --factory moira_server:create_app

For latency-sensitive deployments, opt in to a bounded per-worker startup warmup before accepting computational traffic:

$env:MOIRA_SERVER_PREWARM = "1"
uvicorn --factory moira_server:create_app

Kernel Setup and Small-Body Archives

Planetary Kernels (JPL SPK)

Moira requires a JPL DE-series SPK planetary kernel for planetary calculations. All kernel reading is performed by Moira’s native C++17 SPK/DAF reader (_moira_native) with zero jplephem fallback. Ordinary ephemeris calculations are strictly local and never make outbound network requests.

Kernel File Size Date range Notes Direct JPL Download
DE441 de441.bsp ~3.1 GB ~13,200 BCE – ~17,200 CE Full historical/deep-time target; maximum date coverage Download DE441
DE440 de440.bsp ~114 MiB 1550 BCE – 2650 CE Recommended modern-range kernel for most users Download DE440
DE430 de430.bsp ~114 MiB 1550 BCE – 2650 CE Widely deployed predecessor to DE440 Download DE430

Place your .bsp file in kernels/ (relative to the repository root) or ~/.moira/kernels/, or configure a custom path in Python:

from moira import Moira
from moira.spk_reader import set_kernel_path

set_kernel_path("/path/to/de440.bsp")
m = Moira()
print(m.is_kernel_available(), m.available_kernels)

Kernel Manager GUI, CLI, and Custom DAF Writer

# CLI: list kernel status or download missing planetary kernels
moira-download-kernels --list
moira-download-kernels --yes

# Tkinter GUI: browse, download with progress bar, and activate kernels
moira-kernel-manager

# Tkinter GUI: build custom Type-13 SPK kernels from JPL Horizons
moira-daf-writer

Small-Body Catalogs (Asteroids and Comets)

Verify an extracted small-body catalog release or archive before use:

.\.venv\Scripts\python.exe -m moira.small_body_catalog_release verify C:\path\to\catalog-release
.\.venv\Scripts\python.exe -m moira.small_body_catalog_release verify-archive C:\path\to\catalog-release.zip

Data Inventory

Layer Source Bundled Note
IAU 2000A/2006 nutation and precession tables IAU Yes 2,414 terms (1358 luni-solar + 1056 planetary terms); native C++ (_moira_native)
DE-series planetary kernel JPL No de430 (~114 MiB), de440 (~114 MiB), or de441 (~3.1 GB); download separately
Named star registry Sovereign (star_registry.csv + JSON provenance) Yes 1,809 stars; license-independent
Deep-sky coordinate-anchor catalog Moira selection; SIMBAD coordinates/identities; NASA Exoplanet Archive host confirmation Yes 60 non-Solar-System anchors; per-artifact SHA-256 and source receipt included
Canonical small-body identity registries Moira release catalogs with JPL identity lineage Yes 11,223 asteroid and 497 comet identities; names and disambiguation only, with no positional vectors implied
Wheel asteroid ephemeris JPL Horizons (Moira Type-13 packaging) Yes Catalog moira-asteroids-wheel 2026.08.14.1; 25 named bodies including Chiron; one Type-13 shard
Full position-capable asteroid ephemeris JPL Horizons No 11,223 selected asteroids; 449 Type-13 shards in release 2026.10.10.1; adaptive apsidal sampling for 59 audited bodies; public archive, manifest-discovered
Asteroid-family membership catalog Proper25 + retained NASA PDS exclusions Yes 342 families; 200,726 unique numbered asteroids; 221,095 many-to-many membership rows; no positional ephemeris implied
Numbered periodic comet catalog JPL Horizons No 497 comets (1P–516P); 20 Type-13 shards in release 2026.10.10.1; adaptive apsidal sampling for all admitted bodies; public archive, manifest-discovered

Native C++ Performance

Moira’s required numerical extension (_moira_native) is implemented in C++17 with pybind11. Published wheels install the compiled binary directly; source builds compile it via CMake during installation.


Validation Evidence and Light Box Conformance

Moira is validated across a three-layer corpus—Astronomy (IAU ERFA/SOFA, JPL Horizons, NASA, IERS), Astrology (named primary texts, source-owned fixtures, doctrine-grounded invariants, and bounded secondary comparisons), and Experimental/Sovereign domains—governed by three gates:

  1. Gate of Source — Inputs and reference tables are tied to an independent primary authority.
  2. Gate of Flow — The computational derivation is explicit and inspectable.
  3. Gate of Validation — Outputs satisfy a product-appropriate external authority, source-owned golden, independent invariant, or replayable release contract.

Light Box Conformance Program (GAP-007)

Beyond narrative validation ledgers, Moira enforces machine-checked Light Box Conformance across the entire public calculation denominator (moira.facade.__all__ + FastAPI OpenAPI):

Validation / Conformance Ledger Scope and Verification Authority
LIGHT_BOX_CURRENT_STATUS.generated.md Machine-generated exact-release conformance status (1,251 canonical calculations, 171/171 P0 partial/receipted, 63 passed replay contracts).
LIGHT_BOX_ASSURANCE_MATRIX.generated.md Per-surface, per-evidence-class matrix (authority, doctrine_source, invariant, regression, native_parity, release).
LIGHT_BOX_CONFORMANCE_PROGRAM.md Seven-stage Light Box conformance architecture and release-gate protocol.
RELEASE_VALIDATION_6.10.0.md Integrated 6.10 release validation receipt covering Kalachakra Dasha, Chara/Argala profiles, Yoga extensions, and 2026.10.10.1 small-body catalogs.
VALIDATION_ASTRONOMY.md Product-specific IAU ERFA/SOFA, JPL Horizons, NASA, IERS, and invariant evidence with named tolerances and qualifications.
PLANETARY_REDUCTION_PIPELINE.md Major-body route identity, reader-bound time and context ownership, reduction stages, and target/time/frame-matched Horizons contracts.
VALIDATION_ASTROLOGY.md Primary texts, source-owned goldens, doctrine tables, invariants, and bounded Swiss/Astro.com corroboration where applicable.
VALIDATION_EXPERIMENTAL.md Dated subsystem evidence and explicit partial-status boundaries for sovereign and modern products.

AI and LLM Visibility

Moira is structured for high-integrity discovery and collaboration with AI coding and research agents:


Project Documentation and Artifact Governance

The canonical documentation tree lives in wiki/. The flat moira.wiki/ Git wiki mirror is synchronized from wiki/ and should not be edited by hand in isolation. Website-publishable documents are governed by website_docs/publication_sources.json.

Refresh affected generated artifacts in dependency order using the project .venv (.\.venv\Scripts\python.exe) before pushing:

  1. scripts/generate_hellenistic_inventory.py when admitted Hellenistic families change.
  2. scripts/sync_rest_api_reference.py after server route changes.
  3. scripts/generate_lightbox_calculation_inventory.py, scripts/generate_lightbox_conformance_manifest.py, scripts/generate_lightbox_family_register.py, scripts/generate_lightbox_family_assessment.py, scripts/replay_lightbox_receipts.py, scripts/generate_lightbox_assurance_matrix.py, and scripts/generate_lightbox_public_status.py when public calculation surfaces or admissions change.
  4. scripts/sync_git_wiki.py after canonical documentation changes.
  5. scripts/build_website_docs_bundle.py after public exports, route references, or allowlisted documents change.

Before publishing, run the consistency, release-identity, and generated-artifact gates defined in Release Hardening (scripts/check_doc_consistency.py and scripts/check_release_identity.py).

Document Contents
CHANGELOG.md Versioned release history and current unreleased boundary.
RELEASE_NOTES_6.10.1.md Published 6.10.1 release notes, Light Box conformance summary, and Natal Discovery scope.
COMPATIBILITY_NOTES_6.10.1.md 6.10.1 public contract compatibility notes and migration boundaries.
API_REFERENCE.md Canonical Python engine and facade reference (moira and moira.facade).
REST_API_REFERENCE.md Generated FastAPI OpenAPI route inventory (531 operations) and transport contracts.
01_LIGHT_BOX_DOCTRINE.md Transparency and visible derivation as foundational design constraints.
BEYOND_SWISS_EPHEMERIS.md Capabilities enabled by sovereign catalogs, explicit policy, and modern Python/C++17.
WHY_MOIRA_DOES_NOT_COMPRESS_DEXX.md How Moira reads published JPL SPK records versus how Swiss Ephemeris reads packed .se1 files.
MIGRATING_FROM_SWISS_EPHEMERIS.md Contract-first porting guide for Swiss flags, bodies, time scales, units, houses, REST, and dual-run verification.
HOUSE_SYSTEM_DIVERGENCE.md House-system derivation and discretionary divergence from conventional Swiss-facing behavior.
PHYSICAL_HELIACAL_VISIBILITY_CAPABILITY_MATRIX.generated.md Current physical-visibility admission, evidence classes, tolerances, and closed exclusions.
PHYSICAL_HELIACAL_VISIBILITY_API_INVENTORY.generated.md Generated Python/facade/REST/OpenAPI inventory for the opt-in physical visibility contract.
CONSTITUTIONAL_PROCESS.md The Subsystem Constitutional Process — Moira’s development and governance protocol.
MOIRA_ROADMAP.md Living implementation roadmap and improvement register.

License

MIT (c) 2026 TheDaniel166. See PROVENANCE.md for license and Swiss-lineage provenance clarity.