Skip to content

Commit c42ef5b

Browse files
damborik22claude
andcommitted
Fix ruff lint and formatting across bindmaster/, examples/, tests/
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 859fc79 commit c42ef5b

17 files changed

Lines changed: 201 additions & 190 deletions

bindmaster/scoring/unified.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import json
1515
from dataclasses import asdict, dataclass, field
1616
from enum import Enum
17-
from typing import Optional
1817

1918

2019
class ToolOrigin(str, Enum):
@@ -49,33 +48,33 @@ class BinderScore:
4948
binder_length: int
5049

5150
# --- Structural confidence ---
52-
plddt_binder: Optional[float] = None
53-
iptm: Optional[float] = None
54-
ptm: Optional[float] = None
55-
ipae: Optional[float] = None
56-
pae_interaction: Optional[float] = None
51+
plddt_binder: float | None = None
52+
iptm: float | None = None
53+
ptm: float | None = None
54+
ipae: float | None = None
55+
pae_interaction: float | None = None
5756

5857
# --- Geometry ---
59-
binder_rmsd: Optional[float] = None
60-
complex_rmsd: Optional[float] = None
58+
binder_rmsd: float | None = None
59+
complex_rmsd: float | None = None
6160

6261
# --- Filter pass/fail (PXDesign-style booleans) ---
63-
passes_af2ig_easy: Optional[bool] = None
64-
passes_af2ig_strict: Optional[bool] = None
65-
passes_protenix_basic: Optional[bool] = None
66-
passes_protenix_strict: Optional[bool] = None
62+
passes_af2ig_easy: bool | None = None
63+
passes_af2ig_strict: bool | None = None
64+
passes_protenix_basic: bool | None = None
65+
passes_protenix_strict: bool | None = None
6766

6867
# --- Ligand-specific (RFDiffusionAA only) ---
69-
ligand_ccd_code: Optional[str] = None
70-
ligand_contact_residues: Optional[int] = None
68+
ligand_ccd_code: str | None = None
69+
ligand_contact_residues: int | None = None
7170

7271
# --- Computed composite ---
73-
composite_score: Optional[float] = field(default=None, init=False)
72+
composite_score: float | None = field(default=None, init=False)
7473

7574
def __post_init__(self):
7675
self.composite_score = self._compute_composite()
7776

78-
def _compute_composite(self) -> Optional[float]:
77+
def _compute_composite(self) -> float | None:
7978
"""Compute composite score from available metrics."""
8079
terms = {}
8180

bindmaster/tools/base.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from abc import ABC, abstractmethod
99
from dataclasses import dataclass
1010
from pathlib import Path
11-
from typing import Optional
1211

1312

1413
@dataclass
@@ -24,9 +23,9 @@ class ToolResult:
2423
output_dir: Path
2524
pdb_paths: list[Path]
2625
log_path: Path
27-
error_message: Optional[str] = None
28-
raw_scores: Optional[dict] = None # Tool-specific scores, unmodified
29-
metadata: Optional[dict] = None # Any additional tool-specific info
26+
error_message: str | None = None
27+
raw_scores: dict | None = None # Tool-specific scores, unmodified
28+
metadata: dict | None = None # Any additional tool-specific info
3029

3130

3231
class ToolAdapter(ABC):

bindmaster/tools/pxdesign/config.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,27 @@
55
from __future__ import annotations
66

77
import hashlib
8-
from dataclasses import dataclass, field
8+
from dataclasses import dataclass
99
from pathlib import Path
10-
from typing import Optional, Union
1110

1211
import yaml
1312

1413

1514
@dataclass
1615
class ChainConfig:
1716
"""Configuration for a single target chain."""
18-
crop: Optional[list[str]] = None
19-
hotspots: Optional[list[int]] = None
20-
msa: Optional[Path] = None
17+
18+
crop: list[str] | None = None
19+
hotspots: list[int] | None = None
20+
msa: Path | None = None
2121

2222

2323
@dataclass
2424
class PXDesignTargetConfig:
2525
"""Target structure configuration."""
26+
2627
file: Path
27-
chains: dict[str, Union[ChainConfig, str]]
28+
chains: dict[str, ChainConfig | str]
2829

2930
def __post_init__(self):
3031
if not Path(self.file).exists():
@@ -37,6 +38,7 @@ class PXDesignConfig:
3738
Complete PXDesign run configuration.
3839
Generates a YAML file that pxdesign CLI consumes.
3940
"""
41+
4042
target: PXDesignTargetConfig
4143
binder_length: int
4244
n_samples: int = 1000
@@ -48,7 +50,7 @@ class PXDesignConfig:
4850
# BindMaster-specific (not written to YAML)
4951
gpu_device: int = 0
5052
conda_env: str = "bindmaster_pxdesign"
51-
task_name: Optional[str] = None
53+
task_name: str | None = None
5254

5355
def get_task_name(self) -> str:
5456
if self.task_name:
@@ -75,7 +77,7 @@ def to_yaml(self, output_path: Path) -> Path:
7577
"target": {
7678
"file": str(self.target.file),
7779
"chains": {},
78-
}
80+
},
7981
}
8082

8183
for chain_id, chain_cfg in self.target.chains.items():
@@ -99,9 +101,12 @@ def to_yaml(self, output_path: Path) -> Path:
99101
def to_cli_args(self) -> list[str]:
100102
"""Generate the `pxdesign pipeline` CLI argument list."""
101103
args = [
102-
"--preset", self.preset,
103-
"--N_sample", str(self.n_samples),
104-
"--dtype", self.dtype,
104+
"--preset",
105+
self.preset,
106+
"--N_sample",
107+
str(self.n_samples),
108+
"--dtype",
109+
self.dtype,
105110
]
106111
if self.use_fast_ln:
107112
args += ["--use_fast_ln", "True"]

bindmaster/tools/pxdesign/msa_manager.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import time
1111
from pathlib import Path
1212

13-
from bindmaster.tools.pxdesign.config import PXDesignConfig, ChainConfig
13+
from bindmaster.tools.pxdesign.config import ChainConfig, PXDesignConfig
1414

1515

1616
class MSAManager:
@@ -28,10 +28,7 @@ def is_cached(self, config: PXDesignConfig) -> bool:
2828
cache_path = self.cache_dir / key
2929
if not cache_path.exists():
3030
return False
31-
for chain_id in config.target.chains:
32-
if not (cache_path / chain_id).exists():
33-
return False
34-
return True
31+
return all((cache_path / chain_id).exists() for chain_id in config.target.chains)
3532

3633
def get_msa_paths(self, config: PXDesignConfig) -> dict[str, Path]:
3734
key = self.cache_key(config)
@@ -41,8 +38,7 @@ def get_msa_paths(self, config: PXDesignConfig) -> dict[str, Path]:
4138
chain_msa = cache_path / chain_id
4239
if not chain_msa.exists():
4340
raise FileNotFoundError(
44-
f"MSA not cached for chain {chain_id} "
45-
f"(target_hash={key}). Run compute_msa() first."
41+
f"MSA not cached for chain {chain_id} (target_hash={key}). Run compute_msa() first."
4642
)
4743
paths[chain_id] = chain_msa
4844
return paths
@@ -68,8 +64,17 @@ def compute_msa(
6864

6965
t0 = time.time()
7066
proc = subprocess.run(
71-
["conda", "run", "-n", conda_env, "--no-capture-output",
72-
"pxdesign", "prepare-msa", "--yaml", str(tmp_yaml)],
67+
[
68+
"conda",
69+
"run",
70+
"-n",
71+
conda_env,
72+
"--no-capture-output",
73+
"pxdesign",
74+
"prepare-msa",
75+
"--yaml",
76+
str(tmp_yaml),
77+
],
7378
capture_output=True,
7479
text=True,
7580
)

bindmaster/tools/pxdesign/results_parser.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import csv
88
from pathlib import Path
99

10-
1110
COLUMN_MAP = {
1211
"af2_ipTM": "af2_iptm",
1312
"af2_ipAE": "af2_ipae",
@@ -89,10 +88,7 @@ def get_passing_designs(
8988
}.get(filter_name)
9089

9190
if not filter_key:
92-
raise ValueError(
93-
f"Unknown filter '{filter_name}'. "
94-
f"Choose from: AF2-IG-easy, AF2-IG, Protenix-basic, Protenix"
95-
)
91+
raise ValueError(f"Unknown filter '{filter_name}'. Choose from: AF2-IG-easy, AF2-IG, Protenix-basic, Protenix")
9692

9793
return [r for r in records if r.get(filter_key) is True]
9894

@@ -112,13 +108,21 @@ def summarize_run(summary_csv: Path) -> dict:
112108

113109
print(f"\n[pxdesign] Run summary ({summary_csv.parent.name}):")
114110
print(f" Total designs: {n_total:>6}")
115-
print(f" AF2-IG easy pass: {summary['passes_af2ig_easy']:>6} "
116-
f"({100*summary['passes_af2ig_easy']/max(n_total,1):.1f}%)")
117-
print(f" AF2-IG strict pass: {summary['passes_af2ig_strict']:>6} "
118-
f"({100*summary['passes_af2ig_strict']/max(n_total,1):.1f}%)")
119-
print(f" Protenix basic: {summary['passes_protenix_basic']:>6} "
120-
f"({100*summary['passes_protenix_basic']/max(n_total,1):.1f}%)")
121-
print(f" Protenix strict: {summary['passes_protenix_strict']:>6} "
122-
f"({100*summary['passes_protenix_strict']/max(n_total,1):.1f}%)")
111+
print(
112+
f" AF2-IG easy pass: {summary['passes_af2ig_easy']:>6} "
113+
f"({100 * summary['passes_af2ig_easy'] / max(n_total, 1):.1f}%)"
114+
)
115+
print(
116+
f" AF2-IG strict pass: {summary['passes_af2ig_strict']:>6} "
117+
f"({100 * summary['passes_af2ig_strict'] / max(n_total, 1):.1f}%)"
118+
)
119+
print(
120+
f" Protenix basic: {summary['passes_protenix_basic']:>6} "
121+
f"({100 * summary['passes_protenix_basic'] / max(n_total, 1):.1f}%)"
122+
)
123+
print(
124+
f" Protenix strict: {summary['passes_protenix_strict']:>6} "
125+
f"({100 * summary['passes_protenix_strict'] / max(n_total, 1):.1f}%)"
126+
)
123127

124128
return summary

0 commit comments

Comments
 (0)