import csv
from pathlib import Path
import glmm
from _oracle import TOL_BETA_REL, TOL_LOGLIK_ABS_LMM, TOL_SE_REL, TOL_STDDEV_REL, check_abs, check_rel, load_golden
DATA_PATH = Path(__file__).resolve().parents[3] / "validation" / "data" / "empirical" / "Pastes.csv"
with open(DATA_PATH, newline="") as f:
rows = list(csv.DictReader(f))
data = {
"strength": [float(r["strength"]) for r in rows],
"batch": [r["batch"] for r in rows],
"cask": [r["cask"] for r in rows],
}
fit = glmm.fit(data, "strength ~ (1 | batch/cask)")
print("converged:", fit.converged, " singular:", fit.singular)
fit.summary()
print("loglik (REML crit):", fit.loglik)
print("\noracle cross-check vs goldens/pastes_lmm.json (manifest rung 4):")
g = load_golden("pastes_lmm")
est = g["estimates"]
check_rel("beta[Intercept]", fit.beta[0], est["beta"][0], TOL_BETA_REL)
check_rel("se[Intercept]", fit.se[0], est["se"][0], TOL_SE_REL)
def _key(name):
return frozenset(name.split(":"))
golden_by_group = {_key(v["group"]): v["stddev"][0] for v in est["varcomp"]}
for i, (group_name, _terms) in enumerate(fit.re_groups):
sd, _corr = fit.stddev_corr(i)
check_rel(f"{group_name} stddev", sd[0], golden_by_group[_key(group_name)], TOL_STDDEV_REL)
check_abs("loglik (REML crit)", fit.loglik, est["loglik"], TOL_LOGLIK_ABS_LMM)