f83db2fac1
- 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
348 lines
11 KiB
Python
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
|