Architecture
Cette page décrit l’architecture interne de Ketu v1.3.
Structure des modules
ketu/
├── __init__.py # Public re-exports: bodies, aspects, signs, HOUSES_DTYPE,
│ # HighLatitudeError, HOUSE_SYSTEMS, calculate_houses,
│ # house_of, __version__
├── core.py # Fundamental data structures: bodies (14), aspects, signs
├── calculations.py # High-level API: long, lat, dist_au, body_sign,
│ # is_retrograde, positions, body_name, body_properties
├── display.py # CLI display: print_positions, print_aspects, main
├── aspect_windows.py # Aspect timing: AspectMoment, AspectWindow,
│ # find_aspect_window, find_aspects_timeline
├── transits.py # Transit calculations: NatalPosition, TransitAspect,
│ # get_natal_positions, find_transits_to_position
│
├── aspects/ # Configurable aspect sets (New in v1.1)
│ └── __init__.py # CLASSICAL, TRADITIONAL, EXTENDED, AspectSetSpec,
│ # resolve_aspect_set, calculate_aspects, get_aspect, get_orb
│
├── houses/ # House system calculations (New in v1.1/v1.2)
│ └── __init__.py # calculate_houses, house_of, HOUSES_DTYPE, SYSTEMS,
│ # HighLatitudeError, register (6 systems)
│
├── charts/ # Full natal chart (New in v1.2)
│ └── __init__.py # compute_chart, is_day_chart, CHART_DTYPE
│
├── synastry/ # Inter-chart aspects (New in v1.2)
│ └── __init__.py # calculate_synastry, SYNASTRY_DTYPE
│
├── composite/ # Midpoint composite charts (New in v1.2)
│ └── __init__.py # calculate_composite, circular_midpoint
│
├── returns/ # Solar and lunar returns (New in v1.2)
│ └── __init__.py # solar_return, lunar_return
│
├── parts/ # Arabic Parts / Hermetic Lots (New in v1.2)
│ └── __init__.py # PARTS, calculate_part, calculate_all_parts,
│ # register, get_part, PartSpec
│
├── cache/ # High-performance ephemeris cache
│ └── ephemeris_cache.py # Monthly pre-computed positions (O(1) lookups)
│
├── data/ # Embedded coefficient data (New in v1.3)
│ └── chiron_coeffs.npz # Chebyshev polynomial coefficients for Chiron,
│ # 1900–2100, seg=32 days, degree=10
│
└── ephemeris/ # Low-level astronomical calculations (pure NumPy)
├── __init__.py # Ephemeris package API
├── time.py # Time conversions: utc_to_julian, local_to_utc,
│ # sidereal time, Delta T
├── orbital.py # Orbital mechanics: Kepler solver, orbital elements,
│ # perturbations (re-export hub; elements in _elements.py)
├── _elements.py # ORBITAL_ELEMENTS + Lilith constants (extracted in v1.2)
├── _perturbations.py # apply_perturbations strategy (extracted in v1.2)
├── coordinates.py # Coordinate transformations: ecliptic↔equatorial,
│ # heliocentric↔geocentric, nutation, aberration
├── planets.py # Planetary position dispatch: BODY_STRATEGIES dict,
│ # calc_planet_position, get_body_position, body_properties
└── chiron.py # Chiron Chebyshev evaluator (New in v1.3): private helpers
# _load_chiron_data, _chiron_scalar, _chiron_vec
Dépendances Runtime
Ketu est une bibliothèque Pure NumPy au runtime. La seule dépendance runtime est NumPy.
pyswisseph est utilisé uniquement dans l’outil de build hors-ligne (tools/gen_chiron_coeffs.py) pour générer les Coefficients de Chebyshev de Chiron. Il n’est jamais importé au runtime, ce qui maintient l’isolation AGPL.
Composants principaux
Structures de données (core.py)
Définit les tableaux structurés fondamentaux :
bodies: tableau structuré à 14 éléments (name,id,orb,speed). Index 13 = Chiron (Nouveau en v1.3).aspects: tableau à 14 éléments (name,value,coef) pour tous les angles d’aspects supportés.signs: liste des 12 noms de signes du zodiaque.
Calculs (calculations.py)
API de haut niveau encapsulant les fonctions d’éphéméride avec Cache LRU :
positions()— toutes les longitudes planétaireslong/lat/dist_au()— composantes de position d’un corps uniquebody_sign()— signe zodiacal + décomposition en degrésis_retrograde()— détection de rétrogradationbody_name()— identifiant de corps vers chaîne de caractères
Aspects (ketu/aspects/)
Détection d’aspects configurable (Nouveau en v1.1) :
CLASSICAL / TRADITIONAL / EXTENDED— masques booléens pour les ensembles prédéfiniscalculate_aspects(jdate, l_bodies, aspects=None)— accepte toutAspectSetSpecget_aspect(jdate, body1, body2)— paire uniqueget_orb(body1, body2, asp)— orbe pour la paire + aspect
Systèmes de maisons (ketu/houses/)
Six systèmes de maisons (Nouveau en v1.1/v1.2) :
Placidus, Koch, Porphyre, Signe entier, Égal, Regiomontanus
calculate_houses(jd, lat, lon, system, polar_fallback)→HOUSES_DTYPEhouse_of(planet_lon, cusps)— affectation de maison vectoriséeregister— étendre avec des systèmes personnalisésHighLatitudeError— levée lorsque Placidus/Koch échouent près des pôles
Thèmes (ketu/charts/)
Thème natal complet (Nouveau en v1.2) :
compute_chart(jd, lat, lon, system, aspects, polar_fallback)→CHART_DTYPEis_day_chart(jd, lat, lon)— aide secte (Soleil au-dessus de l’horizon)CHART_DTYPE— tableau structuré unifié : 14 positions de corps, 12 cuspides, angles, matrice d’aspects 14×14
Thèmes relationnels (ketu/synastry/, ketu/composite/)
Analyse inter-thèmes (Nouveau en v1.2) :
calculate_synastry(chart_a, chart_b, aspects, orbs, mode)→SYNASTRY_DTYPEcalculate_composite(chart_a, chart_b, system)→CHART_DTYPEcircular_midpoint(lon_a, lon_b)— utilitaire de point médian par arc minimal
Thèmes prédictifs (ketu/returns/)
Révolutions solaires et lunaires (Nouveau en v1.2) :
solar_return(natal_jd, …, target_year)— retour exact du Soleil à la position natalelunar_return(natal_jd, …, target_jd)— prochain retour de la Lune après la date cibleLes deux retournent
CHART_DTYPEpour le thème de retourSupportent la délocalisation via les paramètres
return_lat/return_lon
Parts arabes (ketu/parts/)
Lots hermétiques (Nouveau en v1.2) :
Registre
PARTS:fortune,spirit,marriagecalculate_part(part_name, chart)— sensible à la secte pour Fortune/Spiritcalculate_all_parts(chart, parts=None)→dict[str, float]Parts personnalisées via
register(name, day_formula, night_formula, description)
Package Ephemeris
Conversions de temps (ephemeris/time.py)
Conversions UTC ↔ Jour Julien
Calculs d’équation du temps
Calculs de temps sidéral
Corrections Delta T pour les dates historiques
Utilise des formules purement mathématiques — aucune dépendance externe.
Mécanique orbitale (ephemeris/orbital.py)
Hub de ré-export déléguant vers :
_elements.py:ORBITAL_ELEMENTS+ constantes Lilith (extraites en v1.2 pour éliminer le risque d’import circulaire)_perturbations.py: stratégieapply_perturbations
Fonctions principales :
Solveur de Kepler (Newton-Raphson)
Position à partir des éléments orbitaux
Perturbations planétaires majeures
Transformations de coordonnées (ephemeris/coordinates.py)
Coordonnées écliptiques ↔ équatoriales
Positions héliocentriques ↔ géocentriques
Coordonnées rectangulaires ↔ sphériques
Corrections de nutation + aberration (appliquées dans les fonctions body-vec)
Calculs planétaires (ephemeris/planets.py)
Dispatch basé sur la stratégie (refactorisé en v1.2) :
BODY_STRATEGIES— dictionnaire associant body_id → fonction de calcul ; stratégie Chiron ajoutée à l’index 13 (v1.3)calc_planet_position(jday, body)— dispatch via le dictionnaire de stratégiesget_body_position / get_body_position_vectorized— points d’entrée scalaire et batchbody_properties(jd, body)— vecteur complet à 6 composantes (lon, lat, dist, vitesses), mis en Cache LRU
Évaluateur Chiron (ephemeris/chiron.py)
Nouveau en v1.3. Helpers privés — ne font pas partie de l’API publique :
_load_chiron_data()— chargeketu/data/chiron_coeffs.npzviaimportlib.resources_chiron_scalar(jd)— évalue le polynôme de Chebyshev pour un Jour Julien unique_chiron_vec(jd_array)— évaluation batch vectorisée
Coefficients : 2283 segments, largeur 32 jours, degré 10, trois quantités (lon, lat, dist). Erreur max : 0,001214° sur 1900–2100.
Principes de conception
Séparation des préoccupations
ephemeris/: calculs astronomiques purs (sans interprétation astrologique)calculations.py: couche d’interprétation astrologiquedisplay.py: interface utilisateur uniquementSous-paquets : chaque domaine fonctionnel est autonome
Vectorisation en premier
Toutes les fonctions principales supportent entrées scalaires et tableaux via broadcasting NumPy.
Pas d’état global
Toutes les fonctions sont pures — mêmes entrées produisent toujours mêmes sorties. Le Cache LRU est le seul état partagé (effaçable via body_properties.cache_clear()).
Runtime Pure NumPy
Seul NumPy est importé au runtime. pyswisseph est une dépendance test/build uniquement (isolation AGPL).
Couverture de tests à 100%
Toutes les branches sont couvertes par la suite de tests (1373+ tests). La porte fail_under=100 est appliquée en CI via pytest-cov.
Flux de données
Flux de calcul de position
from ketu.calculations import long
long(jd, body)
|
v
ephemeris/planets.py — body_properties(jd, body)
|
v
BODY_STRATEGIES[body](jd) ← strategy dispatch
|
body < 13: calc_planet_position (orbital mechanics)
body == 13: _chiron_vec / _chiron_scalar (Chebyshev)
|
v
Returns: [lon, lat, dist, lon_speed, lat_speed, dist_speed]
Flux de calcul de thème
from ketu.charts import compute_chart
compute_chart(jd, lat, lon, system)
|
v
1. get_body_position_vectorized → body_lons[14], body_lats[14], body_speeds[14]
2. calculate_houses(jd, lat, lon, system) → cusps[12], asc, mc, armc, vertex
3. calculate_aspects(jd, ...) → aspect_matrix[14,14], aspect_orbs[14,14]
|
v
Returns: scalar CHART_DTYPE array
Stratégie de test
Tests unitaires
Fonctions individuelles dans
ephemeris/Calculs isolés
Cas limites et conditions aux limites
Tests d’intégration
Calcul complet de thème
Détection d’aspects
Conversions de temps
Épingles de précision Chiron (longitudes de référence couvrant 1900–2100)
Portes de qualité (CI)
pytest : 1373+ tests, tous doivent passer
Couverture : 100% (
fail_under=100, zéro pragma,exclude_linespour les branches mortes prouvées)mypy strict : zéro erreur dans tous les sous-paquets
numpydoc : toutes les docstrings publiques validées
doctests : 56+ exemples inline vérifiés via
pytest --doctest-modules ketu/