Architecture¶
Overview¶
vedic-calc follows a layered architecture with strict dependency boundaries. Every module above the core layer is a pure-function consumer of sidereal longitudes — it never touches the Swiss Ephemeris directly.
┌─────────────────────────────────────────────────────────────────────┐
│ Public API │
│ │
│ Chart calculate_chart() render_south_indian() render_svg()│
│ calculate_divisional_chart() calculate_aspects() │
│ calculate_combustion() calculate_planet_states() │
│ analyze_houses() calculate_transit_chart() │
│ calculate_special_lagnas() calculate_upagrahas() │
│ calculate_sahams() calculate_sade_sati() │
│ calculate_chandrashtama() calculate_functional_nature()│
│ calculate_chalit_chart() calculate_sudarshana_chakra()│
│ calculate_event_timeline() │
│ │
│ Dasha calculate_dasha() get_current_dasha() │
│ calculate_yogini_dasha() calculate_ashtottari_dasha()│
│ calculate_narayana_dasha() │
│ (levels=4: sookshmadasha, levels=5: pranadasha) │
│ │
│ Panchanga calculate_panchanga() get_festivals() │
│ get_anandadi_yoga() calculate_panchanga_transitions()│
│ │
│ Yoga/Dosha detect_yogas() detect_doshas() │
│ score_yogas() score_doshas() │
│ │
│ Strength calculate_shadbala() calculate_ashtakavarga() │
│ │
│ Compatibility calculate_compatibility() calculate_porutham() │
│ calculate_avakhada() calculate_papasamyam() │
│ │
│ Muhurta calculate_muhurta() find_muhurta_windows() │
│ get_disha_shool() │
│ │
│ Prashna cast_prashna_chart() evaluate_prashna() │
│ detect_tajika_yogas() │
│ │
│ Jaimini calculate_chara_karakas() calculate_arudha_padas() │
│ │
│ Varshaphal calculate_varshaphal() │
│ calculate_panchavargeeya_bala() │
│ │
│ KP System calculate_kp_chart() get_kp_sublord() │
│ get_kp_significators() get_kp_house_significators() │
│ │
│ Numerology calculate_numerology() │
├─────────────────────────────────────────────────────────────────────┤
│ Calculation Layer │
│ │
│ chart/ calculator renderer houses aspects combustion │
│ states transits divisional upagrahas special_lagnas │
│ sahams sade_sati chandrashtama functional chalit │
│ relationships sudarshana timeline │
│ │
│ dasha/ calculator yogini ashtottari narayana │
│ panchanga/ calculator festivals transitions │
│ muhurta/ calculator solver │
│ prashna/ chart tajika evaluator │
│ jaimini/ karakas arudha │
│ kp/ calculator houses sublords significators │
│ compatibility/ calculator porutham avakhada constants │
│ papasamyam │
│ strength/ ashtakavarga shadbala │
│ dosha/ calculator scorer │
│ yoga/ calculator scorer │
│ varshaphal/ calculator │
│ numerology/ calculator │
├─────────────────────────────────────────────────────────────────────┤
│ Core Layer │
│ types.py │ constants.py │ ephemeris.py │ helpers.py │
│ search.py │
├─────────────────────────────────────────────────────────────────────┤
│ Swiss Ephemeris (pyswisseph) │
│ (NASA JPL ephemeris data) │
└─────────────────────────────────────────────────────────────────────┘
Key Boundary: ephemeris.py¶
The single most important design decision: only ephemeris.py imports pyswisseph. Everything else works with plain floats (longitudes in degrees).
This gives us:
- Testability -- mock
ephemeris.pyto test all chart logic without the Swiss Ephemeris - Swappability -- could replace pyswisseph with another engine (REST API, WASM, etc.)
- Simplicity -- pyswisseph has a complex C-style API; we expose clean Python functions
What ephemeris.py provides¶
| Function | Input | Output |
|---|---|---|
_to_julian_day() |
year, month, day, hour | Julian Day float |
get_ayanamsa() |
Julian Day, mode | degrees (float) |
get_planet_longitude() |
Julian Day, planet, ayanamsa | (longitude, is_retrograde) |
get_ascendant() |
Julian Day, lat, lon, ayanamsa | longitude (float) |
get_sunrise_sunset() |
Julian Day, lat, lon | (sunrise_jd, sunset_jd) |
jd_to_datetime() |
Julian Day, timezone_offset | Python datetime |
Data Flow¶
Birth Chart¶
Birth Details (date, time, lat/lon, timezone)
│
▼
Convert to UT → Julian Day
│
▼
┌───────────────────────────┐
│ Swiss Ephemeris │
│ (tropical longitudes) │
└──────────┬────────────────┘
│ - ayanamsa
▼
Sidereal longitudes (floats)
│
├── longitude / 30 → Sign
├── longitude / 13.33 → Nakshatra + Pada
├── ascendant sign → 12 Houses (Whole Sign)
└── daily speed < 0 → Retrograde flag
│
▼
BirthChart (Pydantic model, frozen, JSON-serializable)
Dasha (Planetary Periods)¶
BirthChart
│
├── Moon's nakshatra lord → Starting mahadasha planet
├── Moon's degree in nakshatra / 13.333 → Elapsed fraction
│
▼
Vimsottari sequence (rotated to start from birth lord)
│
├── 9 mahadashas (first one partial)
├── 81 antardashas (proportional subdivision)
└── 729 pratyantardashas (one more level)
│
▼
list[DashaPeriod] (flat, chronological, with level field)
Additional dasha systems follow similar flows but use different period sequences: - Yogini Dasha -- 8 yogini deities, 36-year total cycle, nakshatra-based start - Ashtottari Dasha -- 8 planets (no Ketu), 108-year cycle, used when Rahu is in a kendra/trikona - Narayana Dasha -- sign-based (not planet-based), starts from lagna sign, duration depends on sign lord position
Panchanga¶
Date + Location
│
├── get_sunrise_sunset() → Sunrise JD
├── get_planet_longitude(MOON) at sunrise → Moon sidereal lon
├── get_planet_longitude(SUN) at sunrise → Sun sidereal lon
│
▼
Five computations:
├── (Moon - Sun) % 360 / 12 → Tithi (1-30)
├── Moon lon / 13.333 → Nakshatra (1-27)
├── (Moon + Sun) % 360 / 13.333 → Yoga (1-27)
├── (Moon - Sun) % 360 / 6 → Karana (1-60)
└── datetime.weekday() → Vara
│
▼
PanchangaInfo (Pydantic model)
Chart Rendering¶
BirthChart
│
├── Map planets to their signs
├── Map houses to grid positions
│
▼
ASCII (South/North Indian style)
or
SVG (South/North Indian style)
Muhurta (Electional Timing)¶
Activity + Date Range + Location
│
├── For each day:
│ ├── calculate_panchanga() → tithi, nakshatra, yoga, karana, vara
│ ├── calculate_muhurta() → Rahu Kalam, Yamagandam, Abhijit
│ │
│ ▼
│ 5-Layer Filter:
│ ├── Tithi: skip Rikta tithis (4, 9, 14); score good tithis +20
│ ├── Vara: match weekday to activity; score +15
│ ├── Nakshatra: match to activity; score +20
│ ├── Yoga: skip Vyatipata, Vaidhriti; score +10
│ └── Karana: skip Vishti/Bhadra; score +10
│ │
│ ▼ (optional, if natal Moon provided)
│ Personal Overlays:
│ ├── Chandrabala (transit Moon sign from natal) → +15
│ └── Tarabala (transit Moon nak from natal) → +10
│
▼
MuhurtaSearchResult (windows sorted by score, 0-100)
Prashna (Horary Astrology)¶
Question Moment (date, time, location)
│
▼
calculate_chart() → BirthChart (for the question moment)
│
├── Classify question → query house (career=10th, marriage=7th, etc.)
├── Identify query house lord + lagna lord
├── Calculate planetary dignity (exalted, debilitated, etc.)
│
▼
Tajika Yoga Detection (degree-based aspects, NOT Parashari sign-based):
├── Ithasala: faster planet applying to slower → favorable
├── Easarapha: faster separating from slower → unfavorable
├── Induvara: no aspect between significators → matter fails
├── Kamboola: Moon transfers light → success via intermediary
└── Nakta: heavier receives from lighter → partial success
│
▼
PrashnaVerdict (verdict: favorable / unfavorable / mixed + reasoning)
Strength Assessment¶
BirthChart
│
├── Shadbala (6-fold strength):
│ ├── Sthana Bala → positional (sign, house, exaltation, etc.)
│ ├── Dig Bala → directional (Sun strong in 10th, etc.)
│ ├── Kala Bala → temporal (day/night, hora, year lord, etc.)
│ ├── Cheshta Bala → motional (speed, retrograde bonus)
│ ├── Naisargika → natural (Sun=60, Moon=51.43, etc.)
│ └── Drik Bala → aspectual (benefic/malefic aspect balance)
│ │
│ ▼
│ ShadbalaResult per planet (total in rupas, is_strong flag)
│
├── Ashtakavarga (8-source transit strength):
│ ├── For each planet: 12 signs × 8 contributors → benefic dots
│ ├── Sarvashtakavarga: sum across all planets per sign
│ │
│ ▼
│ AshtakavargaResult (per-planet tables + sarva table)
Compatibility¶
Chart A + Chart B
│
├── Ashtakoot (North Indian, 8 factors, max 36 points):
│ ├── Varna (1) ├── Vasya (2) ├── Tara (3) ├── Yoni (4)
│ ├── Graha Maitri (5) ├── Gana (6) ├── Bhakoot (7)
│ └── Nadi (8)
│ │
│ ▼
│ Total score / 36, compatibility level, Mangal Dosha check
│
├── Porutham (South Indian, 10 factors):
│ ├── Dina ├── Gana ├── Mahendra ├── Stree Dirgha
│ ├── Yoni ├── Rasi ├── Rasiyathipathi ├── Vasya
│ ├── Rajju └── Vedha
│ │
│ ▼
│ PoruthamResult (factor-by-factor pass/fail + overall assessment)
Varshaphal (Solar Return)¶
BirthChart + Target Year
│
├── Find exact Sun return moment (same sidereal longitude as birth)
├── Cast chart for that moment at current location
├── Calculate Muntha (progressed ascendant: birth lagna + years elapsed)
├── Detect Tajika yogas in the annual chart
│
▼
VarshaphalResult (annual chart + Muntha + Tajika yogas)
KP System (Krishnamurti Paddhati)¶
Birth Details
│
├── Calculate Placidus house cusps (not Whole Sign)
├── For each cusp and planet longitude:
│ ├── Sign lord (standard)
│ ├── Star lord (nakshatra lord)
│ └── Sub lord (KP sublord from unequal subdivision table)
│
▼
KPChartResult (cusps with 3-level lordship + planets with sub-lords)
Module Responsibilities¶
Core Layer¶
core/constants.py¶
All enumerations and lookup tables. Data sourced from BPHS, Surya Siddhanta, Muhurta Chintamani, and standard panchanga practice.
Planet-- 9 Navagraha (Sun through Ketu)Sign-- 12 Rashis (Aries through Pisces)Nakshatra-- 27 lunar mansionsAyanamsa-- precession correction modes (Lahiri, Raman, KP, True Chitrapaksha)- Chart tables: sign lords, nakshatra lords, exaltation/debilitation degrees, moolatrikona
- Vimsottari tables: dasha years, dasha order, nakshatra-to-lord mapping
- Yogini/Ashtottari tables: period sequences and durations
- Panchanga tables: tithi names, yoga names, karana names, vara names
- Muhurta tables: Rahu Kalam slots, Yamagandam slots, Gulika Kalam slots, Choghadiya sequences
- Muhurta rules: good tithis/nakshatras/varas per activity, bad tithis/yogas/karanas
- Tajika tables: aspect orbs (conjunction, opposition, trine, square, sextile)
- Compatibility tables: Ashtakoot scoring tables, yoni pairs, gana compatibility
- Porutham tables: 10 South Indian compatibility factors
- Shadbala tables: dig bala, naisargika bala, kala bala weights
- Ashtakavarga tables: benefic-point maps for each planet
- KP tables: sublord division table (249 sub-divisions of the zodiac)
- Rendering tables: planet abbreviations, sign abbreviations, grid positions
core/types.py¶
Pydantic models for all data structures. All frozen (immutable), JSON-serializable.
| Model | Purpose |
|---|---|
NakshatraInfo |
Nakshatra + pada + lord |
PlanetPosition |
Longitude, sign, degree, nakshatra, retrograde flag |
HousePosition |
House number, sign, lord |
BirthChart |
Complete chart: planets, houses, ascendant, metadata |
DashaPeriod |
Planetary period with start/end dates and level |
PanchangaInfo |
Daily five-element calendar + sunrise/sunset |
DivisionalChart |
Varga chart with remapped sign placements |
AspectInfo |
Planetary aspect with type, orb, and strength |
CombustionStatus |
Planet's combustion state relative to the Sun |
PlanetState |
Dignity, combustion, retrograde, dispositor chain |
TransitChart |
Current sky positions relative to a natal chart |
HouseAnalysis |
House lord, occupants, aspects, strength assessment |
YogaResult |
Detected yoga with name, type, involved planets |
DoshaResult |
Detected dosha with severity and remedies |
MuhurtaInfo |
Daily Rahu Kalam, Yamagandam, Abhijit, Choghadiya |
MuhurtaWindow |
Scored auspicious window with panchanga breakdown |
MuhurtaSearchResult |
Ranked list of muhurta windows for an activity |
UpagrahaPosition |
Sub-planet (Dhuma, Vyatipata, etc.) position |
SpecialLagna |
Hora Lagna, Ghati Lagna, etc. with longitude |
CharaKaraka |
Jaimini variable significator (planet + karaka role) |
ArudhaPada |
Arudha pada for a house (sign placement) |
AshtakavargaResult |
Per-planet and sarva bindus per sign |
ShadbalaResult |
Six-fold strength breakdown per planet (in rupas) |
PoruthamFactor |
Single South Indian compatibility factor result |
PoruthamResult |
All 10 factors + overall compatibility assessment |
SahamPosition |
Arabic part (lot) position and sign |
FestivalInfo |
Festival name, date, type, and panchanga basis |
TajikaYoga |
Tajika aspect yoga (name, planets, significance) |
PrashnaVerdict |
Horary verdict with query house, yogas, reasoning |
MunthaInfo |
Progressed ascendant for varshaphal |
VarshaphalResult |
Solar return chart + Muntha + annual Tajika yogas |
KPSublordInfo |
Star lord + sub lord for a longitude |
KPHouseCusp |
Placidus cusp with sign/star/sub lords |
KPPlanetInfo |
Planet with KP-style lordship chain |
KPChartResult |
Full KP chart with cusps and planet sub-lords |
NumerologyResult |
Name/birth numbers with Chaldean analysis |
SadeSatiResult |
Sade Sati status, phase, and period dates |
ChandrashtamaResult |
Chandrashtama active flag and window times |
AvakhadaInfo |
Birth summary (Varna, Vasya, Yoni, Gana, Nadi) |
DishaShoolInfo |
Inauspicious travel direction for the day |
AnandadiYogaInfo |
Anandadi yoga from tithi-vara combination |
PlanetRelationshipResult |
Natural, temporal, compound relationships |
FunctionalNature |
Functional benefic/malefic status per planet |
ChalitChart |
Bhava Chalit house cusps and planet placements |
TransitionMoment |
Exact datetime of a panchanga element change |
PanchangaTransitions |
All transition times within a day |
ScoredYogaResult |
Yoga with strength score (0-100) |
ScoredDoshaResult |
Dosha with severity score (0-100) |
TimelineEvent |
Single event in a chronological timeline |
EventTimeline |
Merged, sorted list of life events |
KPSignificatorDetail |
4-level KP significators for a planet |
KPHouseSignificators |
Significator planets for a KP house |
SudarshanaChakra |
3-ring house overlay from Lagna/Moon/Sun |
PapasamyamResult |
Malefic balance comparison for two charts |
PanchavargeeaBala |
5-fold Varshaphal strength assessment |
core/ephemeris.py¶
Thin wrapper around pyswisseph. Only module that imports swisseph. All other modules receive plain floats (degrees) and Python datetimes.
core/helpers.py¶
Shared utilities used across multiple modules. Includes sign_distance(), planet_house(), degree normalization, and other common calculations.
core/search.py¶
Bisection search utilities for astronomical transitions. Given a function that changes value between two Julian Days, finds the exact transition moment to a configurable precision.
Chart Module (chart/)¶
chart/calculator.py¶
Main birth chart entry point. Pure functions that transform longitudes into structured astrology data.
calculate_chart()-- public API, returnsBirthChartlongitude_to_sign()-- 45.0 degrees to Tauruslongitude_to_nakshatra_info()-- 45.0 degrees to Rohini pada 2build_houses()-- Whole Sign houses from ascendant
chart/renderer.py¶
Visual chart rendering. No external dependencies.
render_south_indian()-- ASCII art, signs in fixed positions (standard South Indian grid)render_north_indian()-- ASCII art, houses in fixed positions (diamond layout)render_svg()-- SVG markup for web/mobile display
chart/divisional.py¶
Divisional chart (varga) computation. Takes a BirthChart and divides each planet's longitude by the varga factor to produce a remapped chart.
calculate_divisional_chart()-- supports D-1 through D-60 (Rasi, Hora, Drekkana, Chaturthamsa, Saptamsa, Navamsa, Dashamsa, Dwadashamsa, Shodashamsa, Vimshamsa, Chaturvimshamsa, Saptavimshamsa, Trimshamsa, Khavedamsa, Akshavedamsa, Shastiamsha)
chart/aspects.py¶
Planetary aspect (drishti) calculation. Vedic aspects are sign-based, not degree-based (unlike Western astrology). Every planet aspects the 7th house from it; Mars also aspects 4th and 8th; Jupiter also aspects 5th and 9th; Saturn also aspects 3rd and 10th.
calculate_aspects()-- returns list ofAspectInfofor all active aspects in a chart
chart/combustion.py¶
Combustion detection. A planet is combust when it is too close to the Sun (within specific orb limits that vary per planet). Combust planets lose strength.
calculate_combustion()-- returnsCombustionStatusfor each planet
chart/states.py¶
Planetary dignity and state assessment. Evaluates each planet's condition: own sign, exaltation, debilitation, moolatrikona, friend/enemy sign, retrograde status, combustion, and dispositor chain.
calculate_planet_states()-- returnsPlanetStatefor each planet
chart/houses.py¶
House-level analysis. For each house, identifies the lord, occupants, aspecting planets, and produces a qualitative strength assessment.
analyze_houses()-- returnsHouseAnalysisfor all 12 houses
chart/transits.py¶
Transit chart computation. Calculates current planetary positions and overlays them on a natal chart to identify active transits.
calculate_transit_chart()-- returnsTransitChartwith transit-to-natal relationships
chart/special_lagnas.py¶
Special ascendant calculations used in Jaimini and advanced Parashari analysis.
calculate_special_lagnas()-- computes Hora Lagna, Ghati Lagna, Bhava Lagna, Sree Lagna, Vighati Lagna
chart/upagrahas.py¶
Sub-planet (upagraha) calculations. These are mathematically derived shadow points, not physical bodies. Includes Dhuma, Vyatipata, Parivesha, Chapa (Indrachapa), and Upaketu.
calculate_upagrahas()-- returns positions of all 5 standard upagrahas
chart/sahams.py¶
Arabic parts (sahams/lots). Mathematical points calculated from the longitudes of three chart factors (typically ascendant, planet A, planet B). Used in Tajika and Varshaphal.
calculate_sahams()-- returns common sahams (Punya, Vidya, Yasas, Mitra, Mahatmya, Asha, Samartha, Bhratri, Gaurava, Pitri, Rajya, Matri, Putra, Jeeva, Karma, Roga, Kali, Sastra, Bandhu, Mrityu, Paradesa)
chart/sade_sati.py¶
Sade Sati detection and period calculation. Identifies when Saturn transits through the 12th, 1st, and 2nd signs from the natal Moon.
calculate_sade_sati()-- returnsSadeSatiResult
chart/chandrashtama.py¶
Chandrashtama window detection. Identifies when the Moon transits the 8th sign from the natal Moon (inauspicious ~2.5 day window).
calculate_chandrashtama()-- returnsChandrashtamaResult
chart/relationships.py¶
Panchadha Maitri (5-fold planet relationships). Computes natural, temporal, and compound relationships between all planet pairs.
- Returns
PlanetRelationshipResult
chart/functional.py¶
Functional nature of planets per ascendant. Classifies each planet as functional benefic, malefic, or neutral based on the houses it rules from the ascendant sign.
calculate_functional_nature()-- returnsFunctionalNatureper planet
chart/chalit.py¶
Bhava Chalit chart with equal-house cusps. Redistributes planets into bhavas based on mid-cusp boundaries (can differ from Whole Sign placement).
calculate_chalit_chart()-- returnsChalitChart
chart/sudarshana.py¶
3-ring Sudarshana Chakra from Lagna, Moon, and Sun. Overlays three reference frames for combined house analysis.
calculate_sudarshana_chakra()-- returnsSudarshanaChakra
chart/timeline.py¶
Chronological event timeline. Merges dasha periods, Sade Sati windows, Saturn/Jupiter returns, and other timed events into a single sorted timeline.
calculate_event_timeline()-- returnsEventTimeline
Dasha Module (dasha/)¶
dasha/calculator.py¶
Vimsottari Dasha -- the most widely used planetary period system. 120-year cycle based on the Moon's nakshatra at birth.
calculate_dasha()-- full dasha timeline (mahadasha + antardasha + pratyantardasha)get_current_dasha()-- active periods for a specific date
dasha/yogini.py¶
Yogini Dasha -- 36-year cycle based on 8 yogini deities. Shorter cycle makes it useful for timing events in shorter lifespans or for confirmation alongside Vimsottari.
calculate_yogini_dasha()-- full Yogini period timeline
dasha/ashtottari.py¶
Ashtottari Dasha -- 108-year cycle using 8 planets (excludes Ketu). Traditionally used when Rahu occupies a kendra or trikona from the lagna lord.
calculate_ashtottari_dasha()-- full Ashtottari period timeline
dasha/narayana.py¶
Narayana Dasha -- Jaimini's sign-based dasha system. Unlike planet-based dashas, periods are ruled by signs (not planets), and the sequence depends on whether the lagna is odd or even.
calculate_narayana_dasha()-- sign-based period timeline
Panchanga Module (panchanga/)¶
panchanga/calculator.py¶
Daily Vedic calendar (panchanga) computation. The five limbs: Tithi, Nakshatra, Yoga, Karana, Vara. All computed at the sunrise moment for the given location.
calculate_panchanga()-- computes all five panchanga elements for a date/location
panchanga/festivals.py¶
Hindu festival detection based on panchanga data. Maps specific tithi + month combinations to festival names (e.g., Chaitra Shukla 9 = Rama Navami).
get_festivals()-- returns festivals for a given date/panchanga
panchanga/transitions.py¶
Exact panchanga element transition times. Uses bisection search to find the precise moment each tithi, nakshatra, yoga, and karana changes within a day.
calculate_panchanga_transitions()-- returnsPanchangaTransitions
Muhurta Module (muhurta/)¶
muhurta/calculator.py¶
Daily muhurta (electional timing) calculations. Computes inauspicious windows and auspicious periods from sunrise/sunset.
calculate_muhurta()-- returns Rahu Kalam, Yamagandam, Gulika Kalam, Abhijit Muhurta, Choghadiya (day + night), Hora lord
muhurta/solver.py¶
Muhurta constraint solver. Given an activity, date range, and location, iterates each day, applies a 5-layer panchanga filter, optionally applies personal overlays (Chandrabala, Tarabala), and returns scored/ranked auspicious windows.
find_muhurta_windows()-- returnsMuhurtaSearchResultwith top-N windows
Prashna Module (prashna/)¶
prashna/chart.py¶
Prashna (horary) chart casting. A Prashna chart is structurally identical to a birth chart -- the only difference is that it represents the moment a question is asked, not the moment of birth.
cast_prashna_chart()-- thin wrapper aroundcalculate_chart()for the question moment
prashna/tajika.py¶
Tajika yoga detection for Prashna and Varshaphal. Tajika yogas use degree-based aspects with specific orbs (unlike Parashari sign-based aspects). Implements the 5 most critical verdict-determining yogas.
detect_tajika_yogas()-- detects Ithasala, Easarapha, Induvara, Kamboola, Nakta
prashna/evaluator.py¶
Prashna verdict engine. Combines the query house, house lord dignity, and detected Tajika yogas into a favorable/unfavorable/mixed verdict with reasoning.
evaluate_prashna()-- returnsPrashnaVerdict
Jaimini Module (jaimini/)¶
jaimini/karakas.py¶
Chara Karaka (variable significator) calculation. In Jaimini's system, the 7 karakas (Atmakaraka through Darakaraka) are assigned to planets based on their degree within their sign -- the planet with the highest degree becomes Atmakaraka (soul significator).
calculate_chara_karakas()-- returns 7 karakas sorted by degree
jaimini/arudha.py¶
Arudha Pada calculation. The Arudha (image/projection) of a house is found by counting the same distance from the house lord as the lord is from the house. Arudha Lagna (AL) is the most important -- it represents how the world perceives the native.
calculate_arudha_padas()-- returns Arudha Pada for all 12 houses
Compatibility Module (compatibility/)¶
compatibility/calculator.py¶
Ashtakoot (North Indian) compatibility scoring. Compares Moon positions of two charts across 8 factors totaling 36 points. Also checks Mangal Dosha (Mars affliction) for both charts.
calculate_compatibility()-- returns factor-by-factor scores + total + Mangal Dosha status
compatibility/porutham.py¶
Porutham (South Indian) compatibility analysis. Uses 10 factors (vs. North Indian 8). Includes Rajju (longevity compatibility) and Vedha (obstruction check), which are unique to the South Indian system.
calculate_porutham()-- returnsPoruthamResultwith 10 factor pass/fail
compatibility/avakhada.py¶
Avakhada birth summary table. Computes the traditional birth profile (Varna, Vasya, Yoni, Gana, Nadi, etc.) from the Moon's nakshatra -- used as input for compatibility scoring.
calculate_avakhada()-- returnsAvakhadaInfo
compatibility/papasamyam.py¶
Malefic balance (Papasamyam) compatibility check. Compares the malefic influence on the 1st, 7th, and 8th houses of both charts to ensure the affliction is balanced.
calculate_papasamyam()-- returnsPapasamyamResult
Strength Module (strength/)¶
strength/shadbala.py¶
Shadbala (6-fold strength) computation. Quantifies planetary strength in rupas (units) across 6 dimensions: positional, directional, temporal, motional, natural, and aspectual. A planet needs at least 1 rupa to be considered strong.
calculate_shadbala()-- returnsShadbalaResultper planet
strength/ashtakavarga.py¶
Ashtakavarga (8-source) benefic-point system. For each planet, each of the 8 contributors (7 planets + ascendant) either contributes a benefic point (bindu) or not in each of the 12 signs. Signs with more bindus are stronger for that planet's transit.
calculate_ashtakavarga()-- returns per-planet and sarvashtakavarga tables
Yoga Module (yoga/)¶
yoga/calculator.py¶
Yoga (planetary combination) detection. Scans a chart for classical yogas -- specific planetary configurations that indicate life patterns. Implements ~20 major yogas from BPHS, Phaladeepika, and Saravali, including:
- Pancha Mahapurusha (Ruchaka, Bhadra, Hamsa, Malavya, Shasha)
- Wealth yogas (Dhana, Lakshmi)
- Wisdom yogas (Budhaditya, Saraswati, Gajakesari)
- Affliction yogas (Kemadruma, Shakata, Daridra)
- Moon-based yogas (Sunapha, Anapha, Durudhara, Chandra-Mangal)
- Sun-based yogas (Veshi, Voshi, Ubhayachari)
- Raja and Viparita Raja yogas
Function: detect_yogas() -- returns list of YogaResult
yoga/scorer.py¶
Probabilistic yoga strength scoring (0-100). Evaluates how strongly a detected yoga manifests based on planetary strength, house lordship, and aspects.
score_yogas()-- returns list ofScoredYogaResult
Dosha Module (dosha/)¶
dosha/calculator.py¶
Dosha (affliction) detection. Identifies chart-level doshas that indicate specific life challenges. Each dosha includes severity (mild/moderate/severe) and traditional remedial measures.
- Mangal Dosha (Kuja Dosha) -- Mars in 1st, 2nd, 4th, 7th, 8th, or 12th house
- Kaal Sarpa Dosha -- all planets hemmed between Rahu and Ketu
- Pitru Dosha -- Sun afflicted by Rahu/Saturn (ancestor karma)
- Grahan Dosha -- luminaries conjunct Rahu/Ketu (eclipse yoga)
Function: detect_doshas() -- returns list of DoshaResult
dosha/scorer.py¶
Probabilistic dosha severity scoring (0-100). Evaluates actual impact of a detected dosha based on cancellation conditions, planetary strength, and mitigating factors.
score_doshas()-- returns list ofScoredDoshaResult
Varshaphal Module (varshaphal/)¶
varshaphal/calculator.py¶
Varshaphal (Solar Return / Annual Horoscopy). Casts a chart for the exact moment the Sun returns to its natal sidereal longitude each year. Includes Muntha (progressed ascendant) and applies Tajika yogas for annual predictions.
calculate_varshaphal()-- returnsVarshaphalResult
KP System Module (kp/)¶
kp/calculator.py¶
Krishnamurti Paddhati chart calculation. KP uses Placidus house cusps (not Whole Sign) and a unique sublord system that subdivides each nakshatra unequally based on Vimsottari dasha proportions.
calculate_kp_chart()-- returnsKPChartResult
kp/houses.py¶
Placidus house cusp calculation for KP. Computes the 12 house cusps using the Placidus system via the Swiss Ephemeris.
kp/sublords.py¶
KP sublord lookup. Each degree of the zodiac maps to a sign lord, star lord (nakshatra lord), and sub lord. The sub lord is determined by dividing the nakshatra's 13.333 degrees into unequal parts proportional to Vimsottari dasha years.
get_kp_sublord()-- returnsKPSublordInfofor a given longitude
kp/significators.py¶
KP 4-level significators per planet and house. Determines planet-to-house signification through occupancy, lordship, star-lordship, and sub-lordship chains.
get_kp_significators()-- returnsKPSignificatorDetailper planetget_kp_house_significators()-- returnsKPHouseSignificatorsper house
Numerology Module (numerology/)¶
numerology/calculator.py¶
Vedic numerology (Chaldean system). Computes the psychic number (birth day), destiny number (full birth date), and name number (Chaldean letter-to-number mapping). Includes compatibility between numbers and basic interpretation.
calculate_numerology()-- returnsNumerologyResult
Design Decisions¶
Why Pydantic?¶
- Immutability --
frozen=Trueprevents accidental mutation - Validation --
Field(ge=1, le=12)catches invalid house numbers - Serialization --
.model_dump_json()for API responses, storage - Type safety -- full IDE autocomplete and type checking
Why Whole Sign houses?¶
Whole Sign is the traditional house system in Vedic astrology (Parashari method). The ascendant's sign = 1st house, next sign = 2nd house, etc. Simple, unambiguous, and the most commonly used system in Jyotish. (The KP module uses Placidus cusps separately, as required by that system.)
Why Lahiri ayanamsa as default?¶
Lahiri (Chitrapaksha) is the official ayanamsa of the Indian government, adopted by the Calendar Reform Committee in 1956. It's the most widely used ayanamsa in India and the de facto standard for Vedic astrology.
Why IntEnum for planets/signs?¶
Integer enums allow both human-readable code (Planet.JUPITER) and mathematical operations when needed. They also serialize cleanly to JSON.
Why flat list for dashas?¶
A flat list[DashaPeriod] (instead of nested trees) is simpler to serialize, filter, and iterate. The level field on each period distinguishes mahadasha/antardasha/pratyantardasha. To find "all antardashas within Jupiter mahadasha", filter by date range. This applies to all four dasha systems.
Why sunrise-based panchanga?¶
The Vedic "day" (ahoratra) begins at sunrise, not midnight. All panchanga elements are computed at the sunrise moment for the given location, following traditional practice.
Why Tajika aspects are separate from Parashari aspects?¶
Parashari aspects (in chart/aspects.py) are sign-based: "Mars in Aries aspects Libra" (7th sign). Tajika aspects (in prashna/tajika.py) are degree-based with specific orbs: "Mars at 15 Aries applies to Jupiter at 18 Libra within 8 degree orb." They serve different analytical traditions -- Parashari for natal analysis, Tajika for Prashna and Varshaphal.
Why both Ashtakoot and Porutham?¶
North Indian and South Indian traditions use different compatibility frameworks. Ashtakoot (8 factors, max 36 points) is dominant in North India. Porutham (10 factors, pass/fail) is dominant in Tamil Nadu, Kerala, and Karnataka. Both are provided because the user base spans all of India.