fix(benchmark): pass the ayanamsa to the Arudha and Chara Dasha compares
run_arudha_compare.py and run_chara_dasha_compare.py still set PyJHora to Lahiri while the engine default is Raman (pre_work_error_ledger 2026-11-04). Both now take --ayanamsa / --node-mode, set both on PyJHora, and refuse a local baseline built with other settings (baseline_settings_error, as in run_pyjhora_compare.py). run_chara_dasha_compare.py imported jaimini from benchmarks/scripts (parents[2]); it now uses the repo scripts/. Raman rerun on the 19 fixed samples: A10 vs independent formula 114/114 fields, vs PyJHora 18/19 (one Scorpio/Aquarius co-lord case); Chara Dasha KN Rao sign sequence 228/228, durations 212/228. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
This commit is contained in:
@@ -9,6 +9,7 @@ Compares local Jyotish skill A10 canonical output against an independent local f
|
||||
and PyJHora's bhava_arudhas_from_planet_positions() sign output.
|
||||
Samples are fictional/public smoke cases only.
|
||||
"""
|
||||
import argparse
|
||||
import csv
|
||||
import json
|
||||
import sys
|
||||
@@ -86,7 +87,7 @@ def patch_swisseph_for_pyjhora():
|
||||
swe.houses_ex = houses_ex
|
||||
|
||||
|
||||
def pyjhora_a10_sign(sample):
|
||||
def pyjhora_a10_sign(sample, *, ayanamsa='lahiri', node_mode='mean'):
|
||||
if str(PYJHORA_COMPAT) not in sys.path:
|
||||
sys.path.insert(0, str(PYJHORA_COMPAT))
|
||||
if str(PYJHORA_SITE) not in sys.path:
|
||||
@@ -95,8 +96,12 @@ def pyjhora_a10_sign(sample):
|
||||
from jhora import utils, const
|
||||
from jhora.panchanga import drik
|
||||
from jhora.horoscope.chart import charts, arudhas
|
||||
const._DEFAULT_AYANAMSA_MODE = 'LAHIRI'
|
||||
drik.set_ayanamsa_mode('LAHIRI')
|
||||
# Same ayanamsa and node mode as the local baseline (pre_work_error_ledger 2026-11-04:
|
||||
# this was hard-coded to Lahiri while the engine default had become Raman).
|
||||
const._DEFAULT_AYANAMSA_MODE = ayanamsa.upper()
|
||||
drik.set_ayanamsa_mode(ayanamsa.upper())
|
||||
const.set_node_mode(node_mode == 'true')
|
||||
drik.set_planet_list(set_rahu_ketu_as_true_nodes=(node_mode == 'true'))
|
||||
b = sample['birth']
|
||||
jd = utils.julian_day_number((b['year'], b['month'], b['day']), (b['hour'], b['minute'], 0))
|
||||
place = drik.Place(sample['label'], b['lat'], b['lon'], b['tz'])
|
||||
@@ -165,15 +170,24 @@ def write_report(rows):
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description='Compare the local A10 against an independent formula and PyJHora.')
|
||||
parser.add_argument('--ayanamsa', choices=['lahiri', 'raman'], default='lahiri', help='Ayanamsa for PyJHora; the local baseline must have been built with the same one.')
|
||||
parser.add_argument('--node-mode', choices=['mean', 'true'], default='mean', help='Node mode for PyJHora; must match the local baseline.')
|
||||
args = parser.parse_args(argv)
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
from run_pyjhora_compare import baseline_settings_error
|
||||
samples = json.loads(DATA.read_text())
|
||||
rows = []
|
||||
for sample in samples:
|
||||
sid = sample['id']
|
||||
canon = local_canonical(sid)
|
||||
settings_error = baseline_settings_error(canon, ayanamsa=args.ayanamsa, node_mode=args.node_mode)
|
||||
if settings_error:
|
||||
parser.error(f'{sid}: {settings_error}; rebuild with run_skill_baseline.py')
|
||||
local_a10 = canon['advanced']['A10_Karma_Pada']
|
||||
indep = independent_a10_from_canonical(canon)
|
||||
pyj_sign = pyjhora_a10_sign(sample)
|
||||
pyj_sign = pyjhora_a10_sign(sample, ayanamsa=args.ayanamsa, node_mode=args.node_mode)
|
||||
for field in ['sign', 'source_sign', 'source_lord_sign', 'distance_from_source', 'exception_applied']:
|
||||
compare(rows, sid, 'independent_formula', field, local_a10.get(field), indep.get(field))
|
||||
compare(rows, sid, 'independent_formula', 'source_lord', SIGN_LORDS[local_a10['source_sign']], indep['source_lord'])
|
||||
|
||||
@@ -10,6 +10,7 @@ PyJHora's KN Rao Chara Dasha over fictional/public smoke samples. This script is
|
||||
intended to identify whether the local module is production-grade or only a
|
||||
placeholder workflow component.
|
||||
"""
|
||||
import argparse
|
||||
import csv
|
||||
import json
|
||||
import sys
|
||||
@@ -23,7 +24,7 @@ OUT = ROOT / 'outputs'
|
||||
CANON = OUT / 'canonical'
|
||||
REPORT = OUT / 'jyotish_benchmark_round7_chara_dasha_compare.md'
|
||||
MATRIX = OUT / 'chara_dasha_comparison_matrix.csv'
|
||||
SKILL_SCRIPTS = Path(__file__).resolve().parents[2] / 'scripts'
|
||||
SKILL_SCRIPTS = Path(__file__).resolve().parents[3] / 'scripts' # repo scripts/ (parents[2] was benchmarks/)
|
||||
PYJHORA_SITE = Path(__import__('os').environ.get('PYJHORA_SITE', ''))
|
||||
PYJHORA_COMPAT = ROOT / 'scripts/pyjhora_compat'
|
||||
|
||||
@@ -71,7 +72,7 @@ def local_chara(sample, c):
|
||||
return [{'order': x['order'], 'sign': x['sign'], 'duration_years': float(x['duration_years'])} for x in d['dasha_sequence']]
|
||||
|
||||
|
||||
def pyjhora_chara(sample):
|
||||
def pyjhora_chara(sample, *, ayanamsa='lahiri', node_mode='mean'):
|
||||
if str(PYJHORA_COMPAT) not in sys.path:
|
||||
sys.path.insert(0, str(PYJHORA_COMPAT))
|
||||
if str(PYJHORA_SITE) not in sys.path:
|
||||
@@ -80,8 +81,11 @@ def pyjhora_chara(sample):
|
||||
from jhora import const
|
||||
from jhora.panchanga import drik
|
||||
from jhora.horoscope.dhasa.raasi import chara
|
||||
const._DEFAULT_AYANAMSA_MODE = 'LAHIRI'
|
||||
drik.set_ayanamsa_mode('LAHIRI')
|
||||
# Same ayanamsa and node mode as the local baseline (pre_work_error_ledger 2026-11-04).
|
||||
const._DEFAULT_AYANAMSA_MODE = ayanamsa.upper()
|
||||
drik.set_ayanamsa_mode(ayanamsa.upper())
|
||||
const.set_node_mode(node_mode == 'true')
|
||||
drik.set_planet_list(set_rahu_ketu_as_true_nodes=(node_mode == 'true'))
|
||||
b = sample['birth']
|
||||
dob = (b['year'], b['month'], b['day'])
|
||||
tob = (b['hour'], b['minute'], 0)
|
||||
@@ -161,15 +165,24 @@ def write_report(rows, per_sample):
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description='Compare the local Chara Dasha against PyJHora KN Rao.')
|
||||
parser.add_argument('--ayanamsa', choices=['lahiri', 'raman'], default='lahiri', help='Ayanamsa for PyJHora; the local baseline must have been built with the same one.')
|
||||
parser.add_argument('--node-mode', choices=['mean', 'true'], default='mean', help='Node mode for PyJHora; must match the local baseline.')
|
||||
args = parser.parse_args(argv)
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
from run_pyjhora_compare import baseline_settings_error
|
||||
samples = json.loads(DATA.read_text())
|
||||
rows = []
|
||||
per_sample = []
|
||||
for sample in samples:
|
||||
sid = sample['id']
|
||||
c = canon(sid)
|
||||
settings_error = baseline_settings_error(c, ayanamsa=args.ayanamsa, node_mode=args.node_mode)
|
||||
if settings_error:
|
||||
parser.error(f'{sid}: {settings_error}; rebuild with run_skill_baseline.py')
|
||||
local = local_chara(sample, c)
|
||||
pyj = pyjhora_chara(sample)
|
||||
pyj = pyjhora_chara(sample, ayanamsa=args.ayanamsa, node_mode=args.node_mode)
|
||||
sign_match = 0
|
||||
duration_match = 0
|
||||
for i in range(12):
|
||||
|
||||
@@ -107,3 +107,30 @@ def test_fixed_samples_include_the_public_rodden_aa_backtest_figures():
|
||||
for figure in ["steve_jobs", "barack_obama", "elizabeth_taylor", "marilyn_monroe", "judy_garland", "edith_piaf", "frida_kahlo", "george_w_bush", "zinedine_zidane"]:
|
||||
assert figure in ids
|
||||
assert all(sample.get("privacy") in {"fictional_or_public_test", "public_rodden_aa"} for sample in samples)
|
||||
|
||||
|
||||
def test_arudha_and_chara_compares_take_the_ayanamsa_and_refuse_a_mismatched_baseline(monkeypatch, tmp_path):
|
||||
# Data audit wave 2 (2026-11-04): both scripts still hard-coded Lahiri on the PyJHora side.
|
||||
import json
|
||||
|
||||
from benchmarks.jyotish.scripts import run_arudha_compare as arudha
|
||||
from benchmarks.jyotish.scripts import run_chara_dasha_compare as chara
|
||||
|
||||
for module in (arudha, chara):
|
||||
source = Path(module.__file__).read_text()
|
||||
assert "set_ayanamsa_mode('LAHIRI')" not in source
|
||||
assert "drik.set_ayanamsa_mode(ayanamsa.upper())" in source
|
||||
canon = tmp_path / module.__name__
|
||||
canon.mkdir()
|
||||
sample = json.loads(module.DATA.read_text())[0]
|
||||
(canon / f"{sample['id']}.canonical.json").write_text(json.dumps({"parameters": {"ayanamsa": "raman", "node_mode": "mean"}}))
|
||||
monkeypatch.setattr(module, "CANON", canon)
|
||||
monkeypatch.setattr(module, "DATA", canon / "samples.json")
|
||||
(canon / "samples.json").write_text(json.dumps([sample]))
|
||||
try:
|
||||
module.main(["--ayanamsa", "lahiri"])
|
||||
except SystemExit as exc:
|
||||
assert exc.code == 2
|
||||
else:
|
||||
raise AssertionError(f"{module.__name__} compared a raman baseline under lahiri")
|
||||
assert chara.SKILL_SCRIPTS == ROOT / "scripts"
|
||||
|
||||
Reference in New Issue
Block a user