pranamanam's picture Jingjie00's picture
Upload Staplebridge files (#1)
bb6d2aa
Raw
History Blame Contribute Delete
2 kB
from __future__ import annotations
from dataclasses import dataclass, field, asdict
from typing import Any, Optional
@dataclass
class LeadExample:
example_id: str
linear_sequence: str
target_id: Optional[str] = None
target_context: Optional[dict[str, Any]] = None
protected_positions: list[int] = field(default_factory=list)
preferred_property_direction: dict[str, str] = field(default_factory=dict)
thresholds: dict[str, float] = field(default_factory=dict)
known_active_motif_positions: Optional[list[int]] = None
def to_dict(self) -> dict[str, Any]:
return asdict(self)
@dataclass
class BuildingBlock:
"""Stapling building block.
The geometry / motif fields drive CP-Composer-style feasibility:
- `motif`: sequence-level pattern; for K↔D/E lactam stapling this is
{"i_aa": ["K"], "j_aa": ["D","E"], "spacings": [3, 4]}.
- `ca_window`: allowed Cα(i)-Cα(j) distance window in Å.
`chemistry_class` is now restricted to {"stapled"} (head_to_tail /
disulfide / bicycle were removed; the previous hydrocarbon i,i+4 / i,i+7
blocks were also removed because they fall outside CP-Composer's scope).
"""
block_id: str
name: str
chemistry_class: str
synthetic_accessibility_score: float
cost_score: float
spps_score: float
motif: Optional[dict[str, Any]] = None
ca_window: tuple[float, float] = (4.0, 6.5)
def to_dict(self) -> dict[str, Any]:
d = asdict(self)
d["ca_window"] = list(self.ca_window)
return d
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "BuildingBlock":
d = dict(d)
if "ca_window" in d and isinstance(d["ca_window"], list):
d["ca_window"] = tuple(d["ca_window"])
# tolerate legacy catalogs by dropping retired fields
for legacy in ("allowed_anchor_spacings", "compatible_residue_types", "token_substitution"):
d.pop(legacy, None)
return cls(**d)