Skip to content

Commit 5d175eb

Browse files
Jammy2211Jammy2211claude
authored
fix: populate NUTS samples_info keys under test-mode bypass (#1260)
`PYAUTO_TEST_MODE=2` skips the sampler in `_fit_bypass_test_mode`, producing a samples_info stub with only `total_iterations`, `time`, and `log_evidence`. Tutorial and downstream code that reads NUTS diagnostics (`ess_min`, `num_samples`, `mean_acceptance`, `n_divergent`, `n_logl_evals`) crashed with `KeyError`. Add a `_test_mode_samples_info()` hook on `AbstractSearch`, merged into the bypass `samples_info`. Override in `BlackJAXNUTS` to return the diagnostic keys with NaN/0 placeholders — bypass mode never ran the sampler, so honest empties propagate to the tutorial print. Fixes the `autofit_workspace/scripts/searches/mcmc.py` smoke test. Co-authored-by: Jammy2211 <JNightingale2211@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7646624 commit 5d175eb

2 files changed

Lines changed: 34 additions & 5 deletions

File tree

autofit/non_linear/search/abstract_search.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -858,14 +858,16 @@ def _fit_bypass_test_mode(
858858
# (grid search log_evidences, subhalo Bayesian model comparison,
859859
# scrape aggregator assertions) doesn't crash on None. SamplesPDF
860860
# reads log_evidence from samples_info.
861+
samples_info = {
862+
"total_iterations": 1,
863+
"time": 0.0,
864+
"log_evidence": log_likelihood,
865+
}
866+
samples_info.update(self._test_mode_samples_info())
861867
samples = SamplesPDF(
862868
model=model,
863869
sample_list=sample_list,
864-
samples_info={
865-
"total_iterations": 1,
866-
"time": 0.0,
867-
"log_evidence": log_likelihood,
868-
},
870+
samples_info=samples_info,
869871
)
870872

871873
samples_summary = samples.summary()
@@ -888,6 +890,19 @@ def _fit_bypass_test_mode(
888890

889891
return result
890892

893+
def _test_mode_samples_info(self) -> dict:
894+
"""
895+
Sampler-specific keys to merge into ``samples_info`` when the
896+
sampler is bypassed via ``PYAUTO_TEST_MODE=2`` or ``=3``.
897+
898+
Override in subclasses to add the diagnostic keys that the real
899+
run would populate (e.g. NUTS ESS, MCMC autocorrelations) so that
900+
tutorial scripts and downstream code can access those keys
901+
without ``KeyError``. Use NaN/0 placeholders — the bypass did not
902+
actually sample.
903+
"""
904+
return {}
905+
891906
@staticmethod
892907
def _build_fake_samples(model, parameter_vector, log_likelihood):
893908
"""

autofit/non_linear/search/mcmc/blackjax/nuts/search.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,20 @@ def output_search_internal(self, search_internal):
378378
with open(self.backend_filename, "wb") as f:
379379
pickle.dump(search_internal, f)
380380

381+
def _test_mode_samples_info(self) -> dict:
382+
return {
383+
"num_warmup": int(self.num_warmup),
384+
"num_samples": 0,
385+
"num_chains": int(self.num_chains),
386+
"ess_min": float("nan"),
387+
"ess_per_param": [],
388+
"mean_acceptance": float("nan"),
389+
"n_divergent": 0,
390+
"n_logl_evals": 0,
391+
"total_walkers": int(self.num_chains),
392+
"total_steps": 0,
393+
}
394+
381395
def samples_info_from(self, search_internal=None):
382396
search_internal = search_internal if search_internal is not None else self.backend
383397

0 commit comments

Comments
 (0)