Skip to content

feat: panel diversity analysis, QC tests, optimal synthesis recommend… - #17

Merged
cschanhniem merged 2 commits into
mainfrom
feat/diversity-qc
Jun 27, 2026
Merged

cschanhniem merged 2 commits into
mainfrom
feat/diversity-qc

Conversation

@cschanhniem

Copy link
Copy Markdown
Collaborator

…ation

Panel diversity analysis (src/openamp_foundry/analysis/diversity.py):

  • Levenshtein-based pairwise similarity matrix (pure Python, no dependencies)
  • Single-linkage clustering at configurable similarity threshold (default 0.60)
  • Greedy minimal diverse panel: 1 candidate per structural cluster
  • Optimal cluster representatives: best ensemble per cluster, tie-break by no-Met then lowest μH — separates rank-based selection from score-optimal
  • Family-level structural warnings: detect when ALL members of a family share a structural liability (e.g. all SEED-005 have ≥4 trypsin sites, all SEED-005 have μH > 0.65 → entire family has hemolytic risk)

Key finding for synthesis planning:

  • 16-candidate panel → only 4 structural clusters
  • 14 of 16 candidates are structurally redundant (>60% similar to earlier)
  • Optimal 4-candidate panel: VAR_009 (SEED-005), VAR_016 (SEED-003), VAR_084 (SEED-002), VAR_011 (SEED-004) — covers all 4 scaffolds

Tests (80 new, 445 total):

  • tests/test_diversity.py: 40 tests covering all diversity module functions
  • tests/test_presynth_qc.py: 40 tests for presynth_check.py (MW, pI, charge, oxidation, trypsin/chymotrypsin sites, deamidation, aggregation, UV, hemolysis stratification, difficulty, panel batch function)

CLI + Makefile:

  • New subcommand: diversity-check --panel-csv --similarity-threshold --n-per-cluster --out
  • New Makefile target: make diversity → outputs/diversity_report.md

…ation

Panel diversity analysis (src/openamp_foundry/analysis/diversity.py):
- Levenshtein-based pairwise similarity matrix (pure Python, no dependencies)
- Single-linkage clustering at configurable similarity threshold (default 0.60)
- Greedy minimal diverse panel: 1 candidate per structural cluster
- Optimal cluster representatives: best ensemble per cluster, tie-break by
  no-Met then lowest μH — separates rank-based selection from score-optimal
- Family-level structural warnings: detect when ALL members of a family
  share a structural liability (e.g. all SEED-005 have ≥4 trypsin sites,
  all SEED-005 have μH > 0.65 → entire family has hemolytic risk)

Key finding for synthesis planning:
- 16-candidate panel → only 4 structural clusters
- 14 of 16 candidates are structurally redundant (>60% similar to earlier)
- Optimal 4-candidate panel: VAR_009 (SEED-005), VAR_016 (SEED-003),
  VAR_084 (SEED-002), VAR_011 (SEED-004) — covers all 4 scaffolds

Tests (80 new, 445 total):
- tests/test_diversity.py: 40 tests covering all diversity module functions
- tests/test_presynth_qc.py: 40 tests for presynth_check.py (MW, pI, charge,
  oxidation, trypsin/chymotrypsin sites, deamidation, aggregation, UV,
  hemolysis stratification, difficulty, panel batch function)

CLI + Makefile:
- New subcommand: diversity-check --panel-csv --similarity-threshold --n-per-cluster --out
- New Makefile target: make diversity → outputs/diversity_report.md
…ak tests

CRITICAL:
- evaluate.py: Fix random_recall_at_k formula (was inflating EF by n_positives/k
  when k < n_positives). Correct: E[recall@k] = min(1.0, k/n_candidates).
  Add 2 regression tests: k < n_positives case + real benchmark scale (k=8, n=88).

HIGH:
- presynth_check.py: Remove dead inner loop in _net_charge_at_ph (for _ in seq: pass
  did nothing; charge calculation was correct but code was misleading)
- test_physchem_amphipathicity.py: Add directional assertion to
  test_alternating_hydrophobic_polar_has_higher_moment (was only checking isinstance)

MEDIUM:
- scoring/activity.py: Rebalance weights (0.28+0.32+0.20 + 0.10 + 0.15 = 1.05 max).
  Scale base terms to 0.24+0.27+0.17=0.68 so ceiling is 0.93 with all bonuses.
- test_benchmark_evaluate.py: Strengthen test_expected_random_recall with exact
  expected value check (0.4); remove redundant 'or' in disclaimer test.

LOW:
- presynth_check.py: Document that _TRYPSIN_RE (?=.) and m.start() < len-1 are
  complementary guards (both kept intentionally for defence in depth)
- presynth_check.py: Raise descriptive KeyError when panel CSV missing columns
- cli.py: Remove unused is_first variable in diversity-check handler
@cschanhniem
cschanhniem merged commit c70a23c into main Jun 27, 2026
2 of 3 checks passed
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