Repository navigation
feat: windowed mu_h (Eisenberg window=11) + anionic guard — AUROC 0.8047→0.8348 - #70
Merged
Merged
Conversation
Two scoring improvements that raise the retrospective AUROC meaningfully
before synthesis:
1. Windowed hydrophobic moment (window=11, Eisenberg standard):
- `max_windowed_hydrophobic_moment()` added to physchem.py
- `max_hydrophobic_moment` feature added to compute_features() output
- activity_likeness_score() uses max(mu_h, max_mu_h), so long-sequence
AMPs get credit for their best helical segment (magainin-2: 1.51×,
cecropin-A: 2.90× improvement vs full-seq)
- Short sequences (≤11 AA) are unaffected: windowed == full-seq
2. Anionic charge guard:
- charge_density_ph74 < 0.0 returns 0.0 immediately
- Prevents anionic peptides (electrostatically repelled by bacterial
membranes) receiving spurious partial credit
- Corrects EEIEIEIEIEIEIEE getting 0.42 (should be 0.0)
- Fixed Python eager-eval bug: dict.get(key, features["fallback"])
evaluates the fallback even when key is present; replaced with
explicit `if key in features` conditional
AUROC: pipeline 0.8047→0.8348, phase3 0.7846→0.8126
Regression sentinel: ≥0.79 (was ≥0.75)
Config-identity sentinel: <0.82 (sits between phase3=0.8126, pipeline=0.8348)
Tests: 1223 passing (+23 new for windowed mu_h and anionic guard)
Docs: METHODS.md formula and AUROC table updated; DISCOVERY_PREDICTION.md
and CHANGELOG.md updated
…_h ordering Code review (PR #70) found two MEDIUM issues: 1. max_windowed_hydrophobic_moment is NOT guaranteed >= hydrophobic_moment. For non-amphipathic/uniform sequences longer than the window, the fixed- window value (normalised by window=11) can be LESS than the full-sequence average (normalised by len). The scorer handles this correctly via max(hydrophobic_moment, max_hydrophobic_moment), but the docstring and test comment implied the wrong invariant. - Corrected docstring to document the [0, ∞) range and the non-invariant - Renamed test to _for_known_amps and added note - Added test_windowed_can_be_less_than_full_for_uniform_sequences as an explicit counterexample (12-A uniform sequence) 2. Test comment erroneously stated the windowed value is <= 1.0. The Eisenberg scale can produce values > 1.0 for tightly packed hydrophobic windows; clamping happens in the scorer (clamp01). Removed the incorrect upper-bound claim from the comment. Also fixed LOW: stale weight coefficient in amphipathicity bonus comment (0.15 → 0.14, matching activity.py line 79).
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 scoring improvements that raise the retrospective AUROC from 0.8047 → 0.8348 (pipeline) and 0.7846 → 0.8126 (phase3 synthesis gate) before wet-lab synthesis.
1. Windowed Hydrophobic Moment (PR #70a)
For sequences > 11 residues, the full-sequence μH is diluted by non-helical termini and linker regions. The Eisenberg (1984) standard uses a window of 11 residues to capture the most amphipathic helical segment.
max_windowed_hydrophobic_moment(sequence, window=11)tofeatures/physchem.pymax_hydrophobic_momentkey tocompute_features()outputactivity_likeness_score()now usesmax(hydrophobic_moment, max_hydrophobic_moment)2. Anionic Charge Guard (PR #70b)
Anionic peptides (charge_density_ph74 < 0.0) are electrostatically repelled by bacterial membranes (phosphatidylglycerol, cardiolipin) and cannot operate via the canonical cationic AMP mechanism. Previously, EEIEIEIEIEIEIEE received 0.42 — now correctly 0.0.
charge_density_ph74 < 0.0dict.get(key, features["fallback"])evaluates the fallback argument before calling.get(), raisingKeyErrorwhencharge_densityis absent. Replaced with explicitif "charge_density_ph74" in featuresconditional.Results
Sentinel updates
>= 0.79(was>= 0.75)< 0.82— sits between phase3=0.8126 and pipeline=0.8348, so a silent config fallback is detectableTest plan
uv run pytest tests/ -q)TestMaxWindowedHydrophobicMoment— 8 tests: short seq == full, long seq >= full, magainin-2 >1.2× improvement, single residue, custom window, nonnegTestComputeFeaturesMaxMuH— 5 tests: key present, type, nonneg, max >= full, short seq == fullTestAnionicGuard— 6 tests: anionic → 0, ph74 field priority, polyglutamate → 0, zero not blocked, small negative blocked, positive not blockedTestMaxWindowedMuHInActivity— 3 tests: max used when higher, backward compat, missing both keysphase3.yaml AUROC=0.8126 >= 0.79 ✓,< 0.82 ✓μH_eff = max(hydrophobic_moment, max_hydrophobic_moment)and anionic guard note🤖 Generated with Claude Code