Files
Jyotisha/references/open_source_sources/jyotishganit/tests/test_ashtakavarga.py
T
732642856 f83db2fac1 Enhance Jyotish validation and Jaimini modules
- add external validation reports and open-source comparison references

- integrate Jaimini arudha/graha pada, enhanced argala, and additional synastry kutas

- update skill docs and capability matrices

- add smoke tests for open-source integrations
2026-06-10 20:50:52 +08:00

348 lines
11 KiB
Python

"""
Test suite for Ashtakavarga calculations in jyotishganit.
Tests individual Binnna Ashtakavarga charts and Sarvashtakavarga totals
against classical benchmarks from Maharishi Parashara's teachings.
"""
from jyotishganit.components.ashtakavarga import (
BENEFIC_HOUSES,
calculate_ashtakavarga,
calculate_ashtakavarga_for_chart,
calculate_bhinna_ashtakavarga,
create_natal_chart_sign_mapping,
)
from jyotishganit.core.constants import ZODIAC_SIGNS
class TestAshtakavargaConstants:
"""Test Ashtakavarga constant definitions and formulas."""
def test_benefic_houses_defined(self):
"""Verify all planets have benefic house definitions."""
expected_planets = [
"Sun",
"Moon",
"Mars",
"Mercury",
"Jupiter",
"Venus",
"Saturn",
]
assert set(BENEFIC_HOUSES.keys()) == set(expected_planets)
# Lagna should be included in all
for planet_houses in BENEFIC_HOUSES.values():
assert "Lagna" in planet_houses
def test_benefic_house_values(self):
"""Verify house values are within 1-12 range (as houses are numbered)."""
for planet, contributors in BENEFIC_HOUSES.items():
for contributor, houses in contributors.items():
for house_num in houses:
assert 1 <= house_num <= 12, (
f"Invalid house {house_num} for {planet}-{contributor}"
)
def test_classical_totals(self, expected_ashtakavarga_benchmarks):
"""Verify classical total bindu counts for each planet's BAV."""
# These should sum to the classical values from texts
sun_total = expected_ashtakavarga_benchmarks["sun_bav_total"]
moon_total = expected_ashtakavarga_benchmarks["moon_bav_total"]
# Basic sanity checks - totals should be reasonable
assert sun_total > 0 and sun_total <= 400 # Sun has 48 according to texts
assert moon_total > 0 and moon_total <= 400 # Moon has 49 according to texts
class TestBhinnaAshtakavarga:
"""Test individual Bhinna Ashtakavarga calculations."""
def test_calculate_bhinna_ashtakavarga_structure(self):
"""Test basic structure of BAV calculation."""
# Sample natal chart with planets in known positions
natal_chart = {
"Sun": 4, # Leo (natural Sun sign - should be strong)
"Moon": 3, # Cancer
"Mars": 0, # Aries
"Mercury": 2, # Gemini (own sign)
"Jupiter": 8, # Sagittarius
"Venus": 6, # Libra
"Saturn": 10, # Aquarius
"Lagna": 5, # Virgo
}
bav = calculate_bhinna_ashtakavarga("Sun", natal_chart, BENEFIC_HOUSES)
# Should have bindu counts for all 12 signs
assert len(bav) == 12
assert set(bav.keys()) == set(ZODIAC_SIGNS)
# All counts should be non-negative integers
for _sign, bindus in bav.items():
assert isinstance(bindus, int)
assert bindus >= 0
def test_sun_bav_total_benchmark(self, expected_ashtakavarga_benchmarks):
"""Verify Sun's BAV totals match classical texts."""
# Place Sun in its own sign (Leo = 4) for maximum exaltation
natal_chart_sun_in_leo = {
"Sun": 4,
"Moon": 0,
"Mars": 0,
"Mercury": 0,
"Jupiter": 0,
"Venus": 0,
"Saturn": 0,
"Lagna": 0,
}
sun_bav = calculate_bhinna_ashtakavarga(
"Sun", natal_chart_sun_in_leo, BENEFIC_HOUSES
)
# Sum should be 48 according to Parashara
total_bindus = sum(sun_bav.values())
expected_total = expected_ashtakavarga_benchmarks["sun_bav_total"]
# Allow some tolerance due to computational factors
tolerance = 2
assert abs(total_bindus - expected_total) <= tolerance, (
f"Sun BAV total {total_bindus} should be close to {expected_total}"
)
def test_moon_bav_total_benchmark(self, expected_ashtakavarga_benchmarks):
"""Verify Moon's BAV totals match classical texts."""
# Place Moon in Cancer for maximum strength
natal_chart_moon_in_cancer = {
"Sun": 0,
"Moon": 3,
"Mars": 0,
"Mercury": 0,
"Jupiter": 0,
"Venus": 0,
"Saturn": 0,
"Lagna": 0,
}
moon_bav = calculate_bhinna_ashtakavarga(
"Moon", natal_chart_moon_in_cancer, BENEFIC_HOUSES
)
total_bindus = sum(moon_bav.values())
expected_total = expected_ashtakavarga_benchmarks["moon_bav_total"]
tolerance = 2
assert abs(total_bindus - expected_total) <= tolerance, (
f"Moon BAV total {total_bindus} should be close to {expected_total}"
)
def test_bindu_count_consistency(self):
"""Test that bindu counts are consistent for same planetary configuration."""
natal_chart = {
"Sun": 4,
"Moon": 3,
"Mars": 7,
"Mercury": 2,
"Jupiter": 11,
"Venus": 1,
"Saturn": 9,
"Lagna": 0,
}
# Calculate BAV multiple times - should be deterministic
bav1 = calculate_bhinna_ashtakavarga("Sun", natal_chart, BENEFIC_HOUSES)
bav2 = calculate_bhinna_ashtakavarga("Sun", natal_chart, BENEFIC_HOUSES)
assert bav1 == bav2
def test_all_planets_bav_non_empty(self):
"""Verify all planets have non-empty BAV charts."""
natal_chart = {
"Sun": 4,
"Moon": 3,
"Mars": 0,
"Mercury": 2,
"Jupiter": 8,
"Venus": 6,
"Saturn": 10,
"Lagna": 5,
}
planets = ["Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn"]
for planet in planets:
bav = calculate_bhinna_ashtakavarga(planet, natal_chart, BENEFIC_HOUSES)
# Should have all 12 signs
assert len(bav) == 12
# Should have some positive bindus (not all zeros)
assert sum(bav.values()) > 0
class TestSarvashtakavarga:
"""Test Sarvashtakavarga (total) calculations."""
def test_calculate_ashtakavarga_structure(self):
"""Test basic structure of full Ashtakavarga calculation."""
natal_chart = {
"Sun": 4,
"Moon": 3,
"Mars": 0,
"Mercury": 2,
"Jupiter": 8,
"Venus": 6,
"Saturn": 10,
"Lagna": 5,
}
result = calculate_ashtakavarga(natal_chart)
# Should have bhav (individual) and sav (total) sections
assert "bhav" in result
assert "sav" in result
# bhav should have all planets
assert set(result["bhav"].keys()) == {
"Sun",
"Moon",
"Mars",
"Mercury",
"Jupiter",
"Venus",
"Saturn",
}
# sav should have bindu counts for all signs
assert len(result["sav"]) == 12
assert set(result["sav"].keys()) == set(ZODIAC_SIGNS)
def test_sarvashtakavarga_totals(self):
"""Test that SAV totals equal sum of individual BAVs."""
natal_chart = {
"Sun": 4,
"Moon": 3,
"Mars": 0,
"Mercury": 2,
"Jupiter": 8,
"Venus": 6,
"Saturn": 10,
"Lagna": 5,
}
result = calculate_ashtakavarga(natal_chart)
planets = ["Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn"]
# Calculate expected totals by summing individual BAVs
expected_sav = dict.fromkeys(ZODIAC_SIGNS, 0)
for planet in planets:
bav = calculate_bhinna_ashtakavarga(planet, natal_chart, BENEFIC_HOUSES)
for sign, bindus in bav.items():
expected_sav[sign] += bindus
actual_sav = result["sav"]
# Should match exactly
assert expected_sav == actual_sav
def test_sav_bindu_range(self):
"""Test that SAV bindu counts are in reasonable ranges."""
natal_chart = {
"Sun": 0,
"Moon": 1,
"Mars": 2,
"Mercury": 3,
"Jupiter": 4,
"Venus": 5,
"Saturn": 6,
"Lagna": 7,
}
result = calculate_ashtakavarga(natal_chart)
for sign, bindus in result["sav"].items():
# Each sign should have reasonable bindu count
# Range based on accumulated benefic houses across all planets/lagna
assert 15 <= bindus <= 40, (
f"SAV bindus for {sign}: {bindus} seems unreasonable"
)
class TestChartIntegration:
"""Test Ashtakavarga integration with full chart calculations."""
def test_create_natal_chart_sign_mapping(self):
"""Test sign mapping creation from D1 chart."""
# Mock a simple D1 chart
class MockPlanet:
def __init__(self, name, sign):
self.celestial_body = name
self.sign = sign
class MockAscendant:
def __init__(self, sign):
self.sign = sign
class MockD1Chart:
def __init__(self):
self.planets = [
MockPlanet("Sun", "Leo"),
MockPlanet("Moon", "Cancer"),
MockPlanet("Mars", "Aries"),
]
self.ascendant = MockAscendant("Virgo")
d1_chart = MockD1Chart()
ascendant_sign = "Virgo"
sign_mapping = create_natal_chart_sign_mapping(d1_chart, ascendant_sign)
# Should have all planets and Lagna
assert set(sign_mapping.keys()) == {"Sun", "Moon", "Mars", "Lagna"}
# Should map signs correctly to indices
assert sign_mapping["Sun"] == 4 # Leo
assert sign_mapping["Moon"] == 3 # Cancer
assert sign_mapping["Mars"] == 0 # Aries
assert sign_mapping["Lagna"] == 5 # Virgo
def test_full_chart_integration(self, sample_vedic_chart_delhi):
"""Test Ashtakavarga calculation with real D1 chart data."""
chart = sample_vedic_chart_delhi
# Should be able to calculate AV without errors
ascendant_sign = chart.d1_chart.houses[0].sign
av = calculate_ashtakavarga_for_chart(chart.d1_chart, ascendant_sign)
assert hasattr(av, "bhav")
assert hasattr(av, "sav")
# Verify SAV has all signs
assert len(av.sav) == 12
# Verify all planets have BAV charts
expected_planets = {
"Sun",
"Moon",
"Mars",
"Mercury",
"Jupiter",
"Venus",
"Saturn",
}
assert set(av.bhav.keys()) == expected_planets
def test_bindu_counts_numeric(self, sample_vedic_chart_delhi):
"""Verify all bindu counts are numeric and reasonable."""
chart = sample_vedic_chart_delhi
ascendant_sign = chart.d1_chart.houses[0].sign
av = calculate_ashtakavarga_for_chart(chart.d1_chart, ascendant_sign)
# Check SAV bindus
for _sign, bindus in av.sav.items():
assert isinstance(bindus, int)
assert bindus >= 0
# Check individual BAV charts
for _planet, bav in av.bhav.items():
for _sign, bindus in bav.items():
assert isinstance(bindus, int)
assert bindus >= 0