Skip to content

Commit 0b7956f

Browse files
committed
fix: address code review issues from PR #47 — charge model consistency, imports, defaults
- presynth_check.py: move selectivity_proxy imports to module level (was deferred; deferred imports are justified only to break circular dependencies, which do not exist here). Use physchem.net_charge_at_ph74() for consistency with compute_features() so the selectivity_proxy value is identical in both the feature dict and QC report. The old _net_charge_at_ph() included terminal groups/Cys/Tyr producing a ~0.2 offset that would give divergent cytotox verdicts for the same sequence. - SynthQC.selectivity_proxy default changed from 1.0 to 0.0 (conservative: assume cytotoxic until check_sequence() fills the field; 1.0 = safe default is misleading for a risk field) - physchem.py docstring: "optimum: +3 to +7" → "+2 to +7" (code awards full score starting at charge=2.0; the prior text contradicted the implementation and the test) - test_selectivity_proxy.py: add boundary test (selectivity_proxy=0.50 exactly must NOT trigger cytotox_risk since predicate is strict <0.5) - Makefile: update echo to "1081-test suite" → "1082-test suite" (38 new tests total)
1 parent a7fd2c0 commit 0b7956f

4 files changed

Lines changed: 23 additions & 9 deletions

File tree

‎Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ lint:
2020
$(RUFF) check src tests scripts
2121

2222
ci: lint test
23-
@echo "CI passed: lint + 1044-test suite green"
23+
@echo "CI passed: lint + 1081-test suite green"
2424

2525
bench-leakage:
2626
PYTHONPATH=src $(PYTHON) -m openamp_foundry.cli bench leakage \

‎src/openamp_foundry/features/physchem.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def selectivity_proxy(charge: float, gravy: float) -> float:
145145
Based on Dathe & Wieprecht (1999) Biochim Biophys Acta 1462:71-87 (GRAVY/cytotox
146146
correlation) and Shai (2002) Biochim Biophys Acta 1462:55-70 (charge selectivity).
147147
148-
Selectivity optimum: net charge +3 to +7, GRAVY ≤ 0.5.
148+
Selectivity optimum: net charge +2 to +7, GRAVY ≤ 0.5.
149149
150150
- Charge < +2: insufficient electrostatic attraction to anionic bacterial membranes
151151
(phosphatidylglycerol, cardiolipin) → reduced bacterial killing, not cytotoxic.

‎src/openamp_foundry/qc/presynth_check.py‎

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import re
99
from dataclasses import dataclass, field
1010

11+
from openamp_foundry.features.physchem import net_charge_at_ph74 as _charge_at_ph74
12+
from openamp_foundry.features.physchem import selectivity_proxy as _sel_proxy
13+
from openamp_foundry.scoring.boman import gravy_score as _gravy
14+
1115

1216
# Trypsin cleaves after K or R (except when followed by P).
1317
_TRYPSIN_RE = re.compile(r"[KR](?!P)(?=.)")
@@ -124,8 +128,9 @@ class SynthQC:
124128
mu_h: float = 0.0
125129
hemolysis_start_conc: str = "" # suggested starting concentration for hemolysis assay
126130

127-
# Mammalian cytotoxicity risk (selectivity proxy < 0.5)
128-
selectivity_proxy: float = 1.0
131+
# Mammalian cytotoxicity risk (selectivity proxy < 0.5).
132+
# Default 0.0 = maximally conservative (assume cytotoxic until check_sequence() fills this).
133+
selectivity_proxy: float = 0.0
129134
cytotox_risk: bool = False
130135

131136
# C-terminal modification
@@ -261,12 +266,14 @@ def check_sequence(candidate_id: str, seq: str, mu_h: float = 0.0) -> SynthQC:
261266
qc.hemolysis_start_conc = f"Start at MIC; μH={mu_h:.2f} low risk"
262267

263268
# Selectivity proxy (cytotoxicity risk).
264-
# Computed from net charge and GRAVY to detect sequences likely to fail mammalian
265-
# cytotoxicity assays. Flagged when proxy < 0.5 (high charge OR high hydrophobicity).
269+
# Uses the same net_charge_at_ph74 model as compute_features() to guarantee that the
270+
# selectivity_proxy value here matches the one stored in the candidate feature dict
271+
# (side-chain only: K, R, H at pH 7.4 with pKa 6.5; D, E). The presynth_check
272+
# _net_charge_at_ph() model includes terminal groups/Cys/Tyr, which produces a
273+
# systematic offset (~0.2) and would cause divergent cytotox verdicts for the same
274+
# sequence when comparing feature dicts to QC reports.
266275
# Literature: Dathe & Wieprecht (1999) BBA; Shai (2002) BBA; Chen et al. (2005) JBC.
267-
from openamp_foundry.features.physchem import selectivity_proxy as _sel_proxy
268-
from openamp_foundry.scoring.boman import gravy_score as _gravy
269-
qc.selectivity_proxy = _sel_proxy(qc.charge_ph74, _gravy(seq))
276+
qc.selectivity_proxy = _sel_proxy(_charge_at_ph74(seq), _gravy(seq))
270277
qc.cytotox_risk = qc.selectivity_proxy < 0.5
271278

272279
# C-terminal amidation recommendation.

‎tests/test_selectivity_proxy.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ def test_very_hydrophobic_no_charge_is_zero(self):
109109
def test_return_type_is_float(self):
110110
assert isinstance(selectivity_proxy(5.0, 0.1), float)
111111

112+
def test_exact_threshold_boundary_is_not_flagged(self):
113+
# selectivity_proxy(1.0, 0.75) = 0.6 × 0.5 + 0.4 × 0.5 = 0.50 exactly.
114+
# The predicate is strict `< 0.5`, so 0.50 must NOT trigger HIGH_CYTOTOX_RISK.
115+
p = selectivity_proxy(1.0, 0.75)
116+
assert p == pytest.approx(0.50, abs=1e-4)
117+
assert not (p < 0.5), "Boundary value 0.50 must NOT trigger cytotox risk (predicate is strict <)"
118+
112119
def test_output_clipped_to_unit_interval(self):
113120
# Cannot exceed 1.0 or go below 0.0 for any input
114121
for charge in [-5, 0, 5, 15]:

0 commit comments

Comments
 (0)