Repository navigation
test: proline Boman edge cases + ZwitterAMP trap end-to-end scorer divergence - #29
Merged
Merged
Conversation
…ce tests
Proline edge cases (test_boman_scorer.py):
- test_all_proline_returns_zero: P has Boman potential 0.0 → boman_index("PPPPPPPP")=0.0;
matches G (both are conformational residues with no side-chain charge contribution)
- test_proline_same_as_glycine_in_boman: G and P share the same Boman table entry (0.0)
- test_all_proline_boman_activity_is_midpoint: boman_index=0 → tanh(0)=0 → score=0.5
ZwitterAMP trap (test_pipeline_filters.py):
- KDKDKDKD is designed to fool the Boman scorer: K and D each have Boman potential +2.465
(highest table value), so boman_index=2.465 → boman_activity≈0.92. But net charge=0
(K and D cancel) and no hydrophobicity, so activity_likeness≈0.19. Disagreement≈0.73.
- test_zwitteramp_trap_scorer_divergence: pins actual computed values (act<0.25, bom>0.85,
dis>0.60) to verify the two scoring systems diverge as expected on this false positive
- test_zwitteramp_trap_blocked_by_pipeline: full run_ranking_pipeline integration test
confirms selected=False for KDKDKDKD against the default pipeline.yaml gate (max_dis=0.40)
- test_all_proline_pipeline_scores_and_disagreement: PPPPPPPP has dis≈0.33, which passes
pipeline.yaml gate (0.40) but would fail phase3.yaml gate (0.30); both config thresholds
tested explicitly against live computed values
Why this matters for synthesis: these tests document that the two independent scorers serve
as cross-check, not just redundancy — a sequence that is systematically biased in one scoring
paradigm (all-polar, no-net-charge) still gets caught by the other scorer and by disagreement.
…ertions - test_pipeline_filters.py: move compute_features, activity_likeness_score, boman_activity_score, model_disagreement to module-level imports (good practice even though PLC0415 is not enabled in this project's ruff config); remove redundant dis>0.40 / dis>0.30 assertions that were logically implied by dis>0.60 - test_boman_scorer.py: replace test_proline_same_as_glycine_in_boman (compared two computed values against each other — would survive an equal-but-wrong implementation) with test_proline_boman_index_is_zero_like_glycine asserting both against pytest.approx(0.0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two gaps closed before synthesis ordering:
1. Proline edge case (3 tests in
test_boman_scorer.py)Proline (P) has Boman potential 0.0 — identical to glycine (G). This means:
boman_index("PPPPPPPP") = 0.0boman_activity("PPPPPPPP") ≈ 0.5(neutral midpoint)No test previously covered this. A future edit to the
_BOMAN_POTENTIALStable that accidentally gave proline a non-zero value would corrupt scores on proline-containing candidates (common in hairpin-forming AMP variants) without any test catching it.2. ZwitterAMP trap — end-to-end scorer divergence (3 tests in
test_pipeline_filters.py)KDKDKDKD is a sequence designed to fool the Boman scorer in the worst possible way:
boman_index = 2.465→boman_activity ≈ 0.92activity_likeness ≈ 0.19(correctly identifies this as non-AMP)Without the disagreement gate, this sequence could pass individual scorer thresholds and be nominated for a $10k synthesis slot. The three new tests verify:
run_ranking_pipeline()call marks itselected: falsewith the default configPPPPPPPPcorrectly straddles the two config gates (passes pipeline 0.40, fails phase3 0.30)Test plan
pytest tests/test_boman_scorer.py tests/test_pipeline_filters.py— 61 passed