Skip to content

Commit 489f175

Browse files
committed
Added information about "adaptive" strategy
1 parent eee54da commit 489f175

1 file changed

Lines changed: 23 additions & 5 deletions

File tree

README.md

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ protac = (
8686
)
8787
result = split_protac(protac)
8888
print(result)
89-
# {'SMILES': '...', 'default_pred_n0': 'e3_smiles.linker_smiles.poi_smiles', 'model_name': 'XGBoost'}
89+
# {'SMILES': '...', 'default_pred_n0': 'e3_smiles.linker_smiles.poi_smiles', 'model_name': 'Heuristic', 'heuristic_params': '...', 'n_flags': 0, 'review_reasons': ''}
9090

9191
# --- List of SMILES ---
9292
results = split_protac([protac, protac])
@@ -105,7 +105,7 @@ print(result_df[["PROTAC SMILES", "default_pred_n0", "model_name"]].head())
105105
| Parameter | Type | Default | Description |
106106
|---|---|---|---|
107107
| `protac_smiles` | `str \| list \| DataFrame` | *(required)* | SMILES to split. Single string, list of strings, or DataFrame with a `protac_smiles_col` column. |
108-
| `model` | `str` | `"xgboost"` | Splitting strategy. See [Splitting strategies](#splitting-strategies) for valid values. |
108+
| `model` | `str` | `"adaptive"` | Splitting strategy. See [Splitting strategies](#splitting-strategies) for valid values. |
109109
| `fix_predictions` | `bool` | `True` | Apply cheminformatics post-processing to Transformer predictions before reassembly check. |
110110
| `protac_smiles_col` | `str` | `"SMILES"` | Column name for SMILES when input is a DataFrame; also used as key name in output dicts. |
111111
| `batch_size` | `int` | `1` | Inference batch size (Transformer only). |
@@ -116,15 +116,26 @@ print(result_df[["PROTAC SMILES", "default_pred_n0", "model_name"]].head())
116116
| `betweenness_threshold` | `float` | `0.4` | Betweenness-centrality cut-off for the heuristic. Higher values are more conservative. |
117117
| `use_capacity_weight` | `bool` | `False` | Weight graph edges by bond order when computing betweenness centrality (heuristic only). |
118118
| `betweenness_approx_frac` | `float \| None` | `None` | Fraction of nodes to sample for approximate betweenness centrality. `None` uses exact computation. |
119+
| `adaptive_heuristic_grid` | `list[tuple[float, bool]] \| None` | `None` | `model="adaptive"` only. `(betweenness_threshold, use_capacity_weight)` pairs to try, in order. `None` uses a built-in 6-point grid seeded with the package default first. |
120+
| `adaptive_use_xgboost` | `bool` | `True` | `model="adaptive"` only. Whether the XGBoost stage runs on molecules the heuristic grid left flagged. |
121+
| `adaptive_use_transformer` | `bool` | `False` | `model="adaptive"` only. Whether the Transformer stage runs on molecules still flagged after XGBoost. Off by default (needs the `[transformer]` extra; GPU recommended). |
119122
| `use_transformer` | `bool \| None` | `None` | **Deprecated.** Use `model='transformer'` instead. |
120123
| `use_xgboost` | `bool \| None` | `None` | **Deprecated.** Use `model='xgboost'` instead. |
121124

125+
`model="adaptive"` returns three extra keys beyond the usual `default_pred_n0` / `model_name`: `heuristic_params` (which grid point won, when `model_name == "Heuristic"`, else `None`), `n_flags`, and `review_reasons` — a semicolon-joined list of the [`evaluation.score_split()`](protac_splitter/evaluation.py) plausibility checks that still fired on the winning candidate (empty string if none). Running `model="adaptive"` over a batch of test molecules and looking at which `heuristic_params` wins most often is a good way to pick new defaults for `betweenness_threshold` / `use_capacity_weight`.
126+
127+
```python
128+
result = split_protac(protac, model="adaptive")
129+
print(result["model_name"], result["heuristic_params"], result["n_flags"], result["review_reasons"])
130+
# 'Heuristic' 'betweenness_threshold=0.4,use_capacity_weight=False' 0 ''
131+
```
132+
122133
### Command-line interface 🖥️
123134

124135
After installation the `protac-splitter` command is available:
125136

126137
```bash
127-
# Split a single SMILES with the default XGBoost model
138+
# Split a single SMILES with the default adaptive strategy
128139
protac-splitter --smiles "CC(C)(C)S(=O)(=O)c1cc2c..."
129140

130141
# Use the heuristic algorithm (no model download)
@@ -145,6 +156,12 @@ protac-splitter --smiles "..." --model "transformer->xgboost"
145156
# XGBoost with heuristic fallback
146157
protac-splitter --smiles "..." --model "xgboost->heuristic"
147158

159+
# QC-gated escalation (default): heuristic grid -> XGBoost -> (optionally)
160+
# Transformer, scored by evaluation.score_split; prints which method/params
161+
# won plus the remaining QC flags (if any) -- equivalent to omitting --model
162+
protac-splitter --smiles "..." --model adaptive
163+
protac-splitter --smiles "..." --model adaptive --adaptive-use-transformer
164+
148165
# Batch processing from CSV
149166
protac-splitter --input-csv protacs.csv --smiles-col "SMILES" \
150167
--output-csv results.csv --model xgboost
@@ -172,7 +189,8 @@ PROTAC-Splitter supports multiple strategies, selectable via `--model` (CLI) or
172189

173190
| Value | Description |
174191
|---|---|
175-
| `xgboost` | XGBoost graph edge classifier — default, no GPU required. Model downloaded automatically on first use (~17 MB). |
192+
| `adaptive` *(default)* | QC-gated escalation, not just fallback-on-failure: a small heuristic `(betweenness_threshold, use_capacity_weight)` grid runs first, then XGBoost, then — only with `--adaptive-use-transformer` / `adaptive_use_transformer=True` — the Transformer. Each stage only runs on molecules the previous stage left flagged by [`evaluation.score_split()`](protac_splitter/evaluation.py) (structural validity, fragment size, linker topology, known-ligand similarity), and a later stage only replaces the current best if it scores strictly better. Slower than a single strategy, but reports which method/params won — see [`adaptive_*` arguments](#python-api) above. |
193+
| `xgboost` | XGBoost graph edge classifier — no GPU required. Model downloaded automatically on first use (~17 MB). |
176194
| `heuristic` | Betweenness-centrality graph algorithm — no model download needed. |
177195
| `transformer` | Seq2seq Transformer (requires `[transformer]` extra; GPU recommended). |
178196
| `transformer->xgboost` | Transformer first; XGBoost replaces any failed predictions. |
@@ -183,7 +201,7 @@ PROTAC-Splitter supports multiple strategies, selectable via `--model` (CLI) or
183201
> [!IMPORTANT]
184202
> The above strategies must be passed as a double-quoted string in the CLI (e.g., `--model "transformer->xgboost"`). The `>` operator is a shell redirection operator, so it must be quoted to avoid shell interpretation.
185203
186-
The default strategy is `heuristic->xgboost`, which is the most robust, fastest and accurate for general use.
204+
The default strategy is `adaptive`, which trades speed for a QC-scored search over methods and parameters, generally giving the best-quality split. For higher-throughput batch jobs where a single robust pass is enough, `heuristic->xgboost` is a faster alternative. See [docs/adaptive_splitting.md](docs/adaptive_splitting.md) for the full pipeline reference: every stage, every QC flag it checks, and how each threshold was calibrated.
187205

188206
> [!TIP]
189207
> We recommend increasing the `num_proc` argument to maximize the amount of parallelism when using the default strategy.

0 commit comments

Comments
 (0)