Skip to content

feat: wire #120's aspect-ratio buckets into recommend_config() - #121

Merged
jc-macdonald merged 1 commit into
mainfrom
feat/116-wire-aspect-ratio-buckets
Aug 24, 2026
Merged

feat: wire #120's aspect-ratio buckets into recommend_config()#121
jc-macdonald merged 1 commit into
mainfrom
feat/116-wire-aspect-ratio-buckets

Conversation

@jc-macdonald

Copy link
Copy Markdown
Collaborator

Summary

Closes the last piece of #116: recommend_config() now actually returns an aspect-ratio-aware recommendation for genomics/ecological-scale data, instead of just warning that the standard buckets don't cover it.

Change

_bucket() now takes n (not just p), routing extreme-aspect-ratio regimes to one of #120's four new buckets:

bucket trigger validated at
wide_extreme p/n > 10 bulk_rnaseq: n=30, p=2000, p/n=66.7
wide_moderate p > 200 or p/n > 2.0 microbiome (p/n=6) + single_cell (p=500)
tall_extreme n/p > 50 ecological: n=3000, p=30, n/p=100
tall_moderate n/p > 15 cultural: n=1000, p=50, n/p=20

Falls back to smallp/trans/large otherwise, unchanged. recommend_config() still warns when it returns one of the four new buckets (each validated at a single example regime, not a dense grid like the original three) -- but now it's a real, empirically better recommendation rather than a warning with nothing behind it.

Also closes a gap in #117's warning: it only checked p/n (the wide direction), never n/p -- the original Option A grid's own tested n/p ceiling (15.0) is much tighter than the p/n one (2.0), so n >> p data was silently extrapolating too.

Two real bugs found while wiring this in

Neither was exercised by #120's own validation script, which called VBPCASimulator.generate() directly rather than round-tripping through recommend_config():

  1. criterion_order/active_criteria were stored as trade-study preset names ("cost_angle", "all"), not the list/dict VBPCA's constructor actually accepts -- VBPCA(**recommend_config(n=30, p=2000)) raised TypeError immediately. Resolved to real values; active_criteria renamed to convergence_criteria (VBPCA's actual kwarg).
  2. rmsstop_window/rmsstop_atol/rmsstop_rtol were three separate keys; VBPCA takes one compound rmsstop=[window, atol, rtol] kwarg.

Found a third issue alongside (same root cause): the shallow dict(_BUCKET_CONFIGS[bucket]) copy left the new buckets' nested list/dict values as shared references across calls -- mutating a returned config would corrupt the module-level bucket for every future caller. Now a deep copy.

Test plan

  • just ci passes, defaults.py at 100% coverage
  • New tests: all four new buckets actually VBPCA(**cfg).fit() without error (regression test for both bugs above), mutation-safety (regression test for the third), bucket routing at each threshold (wide_extreme/wide_moderate/tall_extreme/tall_moderate), boundary values stay in the non-extreme bucket, extreme configs differ from their moderate siblings

🤖 Generated with Claude Code

Extends _bucket() to take both n and p, routing extreme p/n or n/p
regimes to one of four new buckets (wide_moderate/wide_extreme for
p>>n genomics-scale data, tall_moderate/tall_extreme for n>>p
ecological/survey-scale data) derived by #120's NSGA-II search, instead
of falling back to smallp/trans/large (validated only up to p=200,
p/n=2.0) or silently extrapolating past it. recommend_config() still
warns when it returns one of the four -- each is validated at only one
example regime, not a dense grid -- but now returns a real, empirically
better recommendation rather than just a warning.

Also fixes two real bugs found while wiring this in (neither was
exercised by #120's own validation script, which called
VBPCASimulator.generate() directly rather than round-tripping through
recommend_config()):

- criterion_order/active_criteria were stored as trade-study preset
  *names* ("cost_angle", "all"), not the list/dict VBPCA's constructor
  actually accepts -- `VBPCA(**recommend_config(n=30, p=2000))` raised
  TypeError immediately. Resolved to real values at module load, and
  active_criteria renamed to convergence_criteria (VBPCA's actual kwarg
  name) to match.
- rmsstop_window/rmsstop_atol/rmsstop_rtol were three separate keys;
  VBPCA takes one compound `rmsstop=[window, atol, rtol]` kwarg.
- (found alongside, same root cause -- untested round-trip): the
  shallow `dict(_BUCKET_CONFIGS[bucket])` copy left the new buckets'
  nested list/dict values (criterion_order, convergence_criteria,
  rmsstop) as shared references -- mutating a returned config would
  have corrupted the module-level bucket for every future call. Now a
  deep copy.

Also closes the tall-direction gap in #117's extrapolation warning: it
only checked p/n (wide direction), never n/p, despite the original
Option A grid's own tested n/p ceiling (15.0) being much tighter than
naive intuition suggests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jc-macdonald
jc-macdonald merged commit 4cae993 into main Aug 24, 2026
7 checks passed
@jc-macdonald
jc-macdonald deleted the feat/116-wire-aspect-ratio-buckets branch August 24, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant