boltz-vsynthes 0.0.10__py3-none-any.whl → 0.0.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- boltz/data/crop/affinity.py +1 -1
- boltz/data/crop/boltz.py +1 -1
- boltz/data/parse/pdb.py +18 -29
- boltz/data/parse/pdb_download.py +18 -28
- boltz/data/tokenize/boltz2.py +1 -1
- boltz/main.py +25 -62
- boltz/model/layers/pairformer.py +2 -2
- boltz/model/models/boltz2.py +1 -1
- boltz/utils/sdf_to_pre_affinity_npz.py +35 -0
- {boltz_vsynthes-0.0.10.dist-info → boltz_vsynthes-0.0.12.dist-info}/METADATA +7 -7
- {boltz_vsynthes-0.0.10.dist-info → boltz_vsynthes-0.0.12.dist-info}/RECORD +15 -14
- {boltz_vsynthes-0.0.10.dist-info → boltz_vsynthes-0.0.12.dist-info}/entry_points.txt +1 -0
- {boltz_vsynthes-0.0.10.dist-info → boltz_vsynthes-0.0.12.dist-info}/WHEEL +0 -0
- {boltz_vsynthes-0.0.10.dist-info → boltz_vsynthes-0.0.12.dist-info}/licenses/LICENSE +0 -0
- {boltz_vsynthes-0.0.10.dist-info → boltz_vsynthes-0.0.12.dist-info}/top_level.txt +0 -0
boltz/data/crop/affinity.py
CHANGED
@@ -105,7 +105,7 @@ class AffinityCropper(Cropper):
|
|
105
105
|
new_tokens = chain_tokens
|
106
106
|
else:
|
107
107
|
# First limit to the maximum set of tokens, with the
|
108
|
-
#
|
108
|
+
# neighborhood on both sides to handle edges. This
|
109
109
|
# is mostly for efficiency with the while loop below.
|
110
110
|
min_idx = token["res_idx"] - self.neighborhood_size
|
111
111
|
max_idx = token["res_idx"] + self.neighborhood_size
|
boltz/data/crop/boltz.py
CHANGED
@@ -245,7 +245,7 @@ class BoltzCropper(Cropper):
|
|
245
245
|
new_tokens = chain_tokens
|
246
246
|
else:
|
247
247
|
# First limit to the maximum set of tokens, with the
|
248
|
-
#
|
248
|
+
# neighborhood on both sides to handle edges. This
|
249
249
|
# is mostly for efficiency with the while loop below.
|
250
250
|
min_idx = token["res_idx"] - neighborhood_size
|
251
251
|
max_idx = token["res_idx"] + neighborhood_size
|
boltz/data/parse/pdb.py
CHANGED
@@ -8,9 +8,6 @@ from Bio.PDB.Polypeptide import PPBuilder
|
|
8
8
|
from Bio.Data.IUPACData import protein_letters_3to1
|
9
9
|
from rdkit import Chem
|
10
10
|
from rdkit.Chem.rdchem import Mol
|
11
|
-
from Bio.SeqUtils import seq1
|
12
|
-
from collections import defaultdict
|
13
|
-
|
14
11
|
|
15
12
|
from boltz.data.types import Target
|
16
13
|
from boltz.data.parse.schema import parse_boltz_schema
|
@@ -41,35 +38,27 @@ def parse_pdb(
|
|
41
38
|
Dictionary containing sequences and bonds.
|
42
39
|
"""
|
43
40
|
# Read PDB file
|
44
|
-
|
45
|
-
|
41
|
+
parser = PDBParser(QUIET=True)
|
42
|
+
structure = parser.get_structure("protein", str(pdb_path))
|
43
|
+
ppb = PPBuilder()
|
46
44
|
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
45
|
+
# Convert to yaml format
|
46
|
+
sequences = []
|
47
|
+
for model in structure:
|
48
|
+
for chain in model:
|
49
|
+
for pp in ppb.build_peptides(chain):
|
50
|
+
seq = str(pp.get_sequence())
|
51
|
+
if seq: # Only add if sequence is not empty
|
52
|
+
sequences.append({
|
53
|
+
"protein": {
|
54
|
+
"id": chain.id,
|
55
|
+
"sequence": seq,
|
56
|
+
"modifications": [],
|
57
|
+
}
|
58
|
+
})
|
60
59
|
|
61
|
-
# Convert to yaml-style list
|
62
|
-
for chain_id, aa_list in sequence_by_chain.items():
|
63
|
-
sequences.append({
|
64
|
-
"protein": {
|
65
|
-
"id": chain_id,
|
66
|
-
"sequence": ''.join(aa_list),
|
67
|
-
"modifications": [],
|
68
|
-
}
|
69
|
-
})
|
70
|
-
print(sequences)
|
71
60
|
return {
|
72
61
|
"sequences": sequences,
|
73
62
|
"bonds": [],
|
74
63
|
"version": 1,
|
75
|
-
}
|
64
|
+
}
|
boltz/data/parse/pdb_download.py
CHANGED
@@ -8,8 +8,6 @@ from Bio.PDB.PDBParser import PDBParser
|
|
8
8
|
from Bio.PDB.Polypeptide import PPBuilder
|
9
9
|
from rdkit import Chem
|
10
10
|
from rdkit.Chem.rdchem import Mol
|
11
|
-
from Bio.SeqUtils import seq1
|
12
|
-
from collections import defaultdict
|
13
11
|
|
14
12
|
from boltz.data.types import Target
|
15
13
|
from boltz.data.parse.schema import parse_boltz_schema
|
@@ -81,33 +79,25 @@ def parse_pdb_id(
|
|
81
79
|
# Download PDB file
|
82
80
|
pdb_path = download_pdb(pdb_id, cache_dir)
|
83
81
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
with open(pdb_path) as f:
|
89
|
-
for line in f:
|
90
|
-
if line.startswith("SEQRES"):
|
91
|
-
parts = line.split()
|
92
|
-
chain_id = parts[2]
|
93
|
-
residues = parts[4:]
|
94
|
-
for res in residues:
|
95
|
-
try:
|
96
|
-
aa = seq1(res)
|
97
|
-
except KeyError:
|
98
|
-
aa = 'X'
|
99
|
-
sequence_by_chain[chain_id].append(aa)
|
82
|
+
# Read PDB file
|
83
|
+
parser = PDBParser(QUIET=True)
|
84
|
+
structure = parser.get_structure("protein", str(pdb_path))
|
85
|
+
ppb = PPBuilder()
|
100
86
|
|
101
|
-
# Convert to yaml
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
87
|
+
# Convert to yaml format
|
88
|
+
sequences = []
|
89
|
+
for model in structure:
|
90
|
+
for chain in model:
|
91
|
+
for pp in ppb.build_peptides(chain):
|
92
|
+
seq = str(pp.get_sequence())
|
93
|
+
if seq: # Only add if sequence is not empty
|
94
|
+
sequences.append({
|
95
|
+
"protein": {
|
96
|
+
"id": chain.id,
|
97
|
+
"sequence": seq,
|
98
|
+
"modifications": [],
|
99
|
+
}
|
100
|
+
})
|
111
101
|
|
112
102
|
return {
|
113
103
|
"sequences": sequences,
|
boltz/data/tokenize/boltz2.py
CHANGED
@@ -133,7 +133,7 @@ def tokenize_structure( # noqa: C901, PLR0915
|
|
133
133
|
chains = struct.chains[struct.mask]
|
134
134
|
|
135
135
|
# Ensemble atom id start in coords table.
|
136
|
-
# For cropper and other operations,
|
136
|
+
# For cropper and other operations, hardcoded to 0th conformer.
|
137
137
|
offset = struct.ensemble[0]["atom_coord_idx"]
|
138
138
|
|
139
139
|
for chain in chains:
|
boltz/main.py
CHANGED
@@ -9,7 +9,7 @@ from dataclasses import asdict, dataclass
|
|
9
9
|
from functools import partial
|
10
10
|
from multiprocessing import Pool
|
11
11
|
from pathlib import Path
|
12
|
-
from typing import Literal, Optional
|
12
|
+
from typing import Literal, Optional
|
13
13
|
|
14
14
|
import click
|
15
15
|
import torch
|
@@ -18,8 +18,6 @@ from pytorch_lightning.strategies import DDPStrategy
|
|
18
18
|
from pytorch_lightning.utilities import rank_zero_only
|
19
19
|
from rdkit import Chem
|
20
20
|
from tqdm import tqdm
|
21
|
-
import time
|
22
|
-
from datetime import datetime
|
23
21
|
|
24
22
|
from boltz.data import const
|
25
23
|
from boltz.data.module.inference import BoltzInferenceDataModule
|
@@ -205,21 +203,22 @@ def download_boltz2(cache: Path) -> None:
|
|
205
203
|
The cache directory.
|
206
204
|
|
207
205
|
"""
|
208
|
-
# Use /tmp if possible for faster local disk I/O
|
209
|
-
if str(cache).startswith("/home") or str(cache).startswith("/mnt"):
|
210
|
-
cache = Path("/tmp/boltz_cache")
|
211
|
-
cache.mkdir(parents=True, exist_ok=True)
|
212
|
-
|
213
206
|
# Download CCD
|
214
207
|
mols = cache / "mols"
|
215
208
|
tar_mols = cache / "mols.tar"
|
216
|
-
if not
|
209
|
+
if not tar_mols.exists():
|
217
210
|
click.echo(
|
218
|
-
f"Downloading
|
211
|
+
f"Downloading the CCD data to {tar_mols}. "
|
219
212
|
"This may take a bit of time. You may change the cache directory "
|
220
213
|
"with the --cache flag."
|
221
214
|
)
|
222
215
|
urllib.request.urlretrieve(MOL_URL, str(tar_mols)) # noqa: S310
|
216
|
+
if not mols.exists():
|
217
|
+
click.echo(
|
218
|
+
f"Extracting the CCD data to {mols}. "
|
219
|
+
"This may take a bit of time. You may change the cache directory "
|
220
|
+
"with the --cache flag."
|
221
|
+
)
|
223
222
|
with tarfile.open(str(tar_mols), "r") as tar:
|
224
223
|
tar.extractall(cache) # noqa: S202
|
225
224
|
|
@@ -984,7 +983,6 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
984
983
|
torch.set_grad_enabled(False)
|
985
984
|
|
986
985
|
# Ignore matmul precision warning
|
987
|
-
# torch.set_float32_matmul_precision('medium')
|
988
986
|
torch.set_float32_matmul_precision("highest")
|
989
987
|
|
990
988
|
# Set rdkit pickle logic
|
@@ -1031,16 +1029,14 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1031
1029
|
msg = f"Method {method} not supported. Supported: {method_names}"
|
1032
1030
|
raise ValueError(msg)
|
1033
1031
|
|
1034
|
-
#
|
1035
|
-
t_process_inputs = time.time()
|
1032
|
+
# Process inputs
|
1036
1033
|
ccd_path = cache / "ccd.pkl"
|
1037
1034
|
mol_dir = cache / "mols"
|
1038
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Starting process_inputs...")
|
1039
1035
|
process_inputs(
|
1040
1036
|
data=data,
|
1041
1037
|
out_dir=out_dir,
|
1042
|
-
ccd_path=
|
1043
|
-
mol_dir=
|
1038
|
+
ccd_path=ccd_path,
|
1039
|
+
mol_dir=mol_dir,
|
1044
1040
|
use_msa_server=use_msa_server,
|
1045
1041
|
msa_server_url=msa_server_url,
|
1046
1042
|
msa_pairing_strategy=msa_pairing_strategy,
|
@@ -1048,27 +1044,18 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1048
1044
|
preprocessing_threads=preprocessing_threads,
|
1049
1045
|
max_msa_seqs=max_msa_seqs,
|
1050
1046
|
)
|
1051
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] process_inputs finished in {time.time() - t_process_inputs:.2f} seconds")
|
1052
1047
|
|
1053
|
-
#
|
1054
|
-
t_manifest = time.time()
|
1055
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Loading manifest...")
|
1048
|
+
# Load manifest
|
1056
1049
|
manifest = Manifest.load(out_dir / "processed" / "manifest.json")
|
1057
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Manifest loaded in {time.time() - t_manifest:.2f} seconds")
|
1058
1050
|
|
1059
|
-
#
|
1060
|
-
t_filter = time.time()
|
1061
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Filtering out existing predictions...")
|
1051
|
+
# Filter out existing predictions
|
1062
1052
|
filtered_manifest = filter_inputs_structure(
|
1063
1053
|
manifest=manifest,
|
1064
1054
|
outdir=out_dir,
|
1065
1055
|
override=override,
|
1066
1056
|
)
|
1067
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Filtering finished in {time.time() - t_filter:.2f} seconds")
|
1068
1057
|
|
1069
|
-
#
|
1070
|
-
t_processed = time.time()
|
1071
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Loading processed data...")
|
1058
|
+
# Load processed data
|
1072
1059
|
processed_dir = out_dir / "processed"
|
1073
1060
|
processed = BoltzProcessedInput(
|
1074
1061
|
manifest=filtered_manifest,
|
@@ -1088,22 +1075,8 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1088
1075
|
(processed_dir / "mols") if (processed_dir / "mols").exists() else None
|
1089
1076
|
),
|
1090
1077
|
)
|
1091
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Processed data loaded in {time.time() - t_processed:.2f} seconds")
|
1092
1078
|
|
1093
|
-
#
|
1094
|
-
t_writer = time.time()
|
1095
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Creating prediction writer...")
|
1096
|
-
pred_writer = BoltzWriter(
|
1097
|
-
data_dir=processed.targets_dir,
|
1098
|
-
output_dir=out_dir / "predictions",
|
1099
|
-
output_format=output_format,
|
1100
|
-
boltz2=model == "boltz2",
|
1101
|
-
)
|
1102
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Prediction writer created in {time.time() - t_writer:.2f} seconds")
|
1103
|
-
|
1104
|
-
# 6. Before and after set up trainer
|
1105
|
-
t_trainer = time.time()
|
1106
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Setting up trainer...")
|
1079
|
+
# Set up trainer
|
1107
1080
|
strategy = "auto"
|
1108
1081
|
if (isinstance(devices, int) and devices > 1) or (
|
1109
1082
|
isinstance(devices, list) and len(devices) > 1
|
@@ -1156,16 +1129,13 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1156
1129
|
devices=devices,
|
1157
1130
|
precision=32 if model == "boltz1" else "bf16-mixed",
|
1158
1131
|
)
|
1159
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Trainer set up in {time.time() - t_trainer:.2f} seconds")
|
1160
1132
|
|
1161
1133
|
if filtered_manifest.records:
|
1162
1134
|
msg = f"Running structure prediction for {len(filtered_manifest.records)} input"
|
1163
1135
|
msg += "s." if len(filtered_manifest.records) > 1 else "."
|
1164
1136
|
click.echo(msg)
|
1165
1137
|
|
1166
|
-
#
|
1167
|
-
t_datamodule = time.time()
|
1168
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Creating data module...")
|
1138
|
+
# Create data module
|
1169
1139
|
if model == "boltz2":
|
1170
1140
|
data_module = Boltz2InferenceDataModule(
|
1171
1141
|
manifest=processed.manifest,
|
@@ -1186,16 +1156,14 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1186
1156
|
num_workers=num_workers,
|
1187
1157
|
constraints_dir=processed.constraints_dir,
|
1188
1158
|
)
|
1189
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Data module created in {time.time() - t_datamodule:.2f} seconds")
|
1190
1159
|
|
1191
|
-
#
|
1192
|
-
t_model = time.time()
|
1193
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Loading model...")
|
1160
|
+
# Load model
|
1194
1161
|
if checkpoint is None:
|
1195
1162
|
if model == "boltz2":
|
1196
1163
|
checkpoint = cache / "boltz2_conf.ckpt"
|
1197
1164
|
else:
|
1198
1165
|
checkpoint = cache / "boltz1_conf.ckpt"
|
1166
|
+
|
1199
1167
|
predict_args = {
|
1200
1168
|
"recycling_steps": recycling_steps,
|
1201
1169
|
"sampling_steps": sampling_steps,
|
@@ -1205,17 +1173,17 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1205
1173
|
"write_full_pae": write_full_pae,
|
1206
1174
|
"write_full_pde": write_full_pde,
|
1207
1175
|
}
|
1176
|
+
|
1208
1177
|
steering_args = BoltzSteeringParams()
|
1209
1178
|
steering_args.fk_steering = use_potentials
|
1210
1179
|
steering_args.guidance_update = use_potentials
|
1180
|
+
|
1211
1181
|
model_cls = Boltz2 if model == "boltz2" else Boltz1
|
1212
|
-
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
1213
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Using device: {device}")
|
1214
1182
|
model_module = model_cls.load_from_checkpoint(
|
1215
1183
|
checkpoint,
|
1216
1184
|
strict=True,
|
1217
1185
|
predict_args=predict_args,
|
1218
|
-
map_location=
|
1186
|
+
map_location="cpu",
|
1219
1187
|
diffusion_process_args=asdict(diffusion_params),
|
1220
1188
|
ema=False,
|
1221
1189
|
use_kernels=not no_kernels,
|
@@ -1224,17 +1192,13 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1224
1192
|
steering_args=asdict(steering_args),
|
1225
1193
|
)
|
1226
1194
|
model_module.eval()
|
1227
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Model loaded in {time.time() - t_model:.2f} seconds")
|
1228
1195
|
|
1229
|
-
#
|
1230
|
-
t_predict = time.time()
|
1231
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Computing structure predictions...")
|
1196
|
+
# Compute structure predictions
|
1232
1197
|
trainer.predict(
|
1233
1198
|
model_module,
|
1234
1199
|
datamodule=data_module,
|
1235
1200
|
return_predictions=False,
|
1236
1201
|
)
|
1237
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Structure predictions computed in {time.time() - t_predict:.2f} seconds")
|
1238
1202
|
|
1239
1203
|
# Check if affinity predictions are needed
|
1240
1204
|
if any(r.affinity for r in manifest.records):
|
@@ -1287,13 +1251,11 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1287
1251
|
if affinity_checkpoint is None:
|
1288
1252
|
affinity_checkpoint = cache / "boltz2_aff.ckpt"
|
1289
1253
|
|
1290
|
-
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
1291
|
-
print(f"[{datetime.now().strftime('%H:%M:%S')}] Using device: {device}")
|
1292
1254
|
model_module = Boltz2.load_from_checkpoint(
|
1293
1255
|
affinity_checkpoint,
|
1294
1256
|
strict=True,
|
1295
1257
|
predict_args=predict_affinity_args,
|
1296
|
-
map_location=
|
1258
|
+
map_location="cpu",
|
1297
1259
|
diffusion_process_args=asdict(diffusion_params),
|
1298
1260
|
ema=False,
|
1299
1261
|
pairformer_args=asdict(pairformer_args),
|
@@ -1310,5 +1272,6 @@ def predict( # noqa: C901, PLR0915, PLR0912
|
|
1310
1272
|
return_predictions=False,
|
1311
1273
|
)
|
1312
1274
|
|
1275
|
+
|
1313
1276
|
if __name__ == "__main__":
|
1314
1277
|
cli()
|
boltz/model/layers/pairformer.py
CHANGED
@@ -325,13 +325,13 @@ class PairformerNoSeqModule(nn.Module):
|
|
325
325
|
z,
|
326
326
|
pair_mask,
|
327
327
|
chunk_size_tri_attn,
|
328
|
-
use_kernels
|
328
|
+
use_kernels,
|
329
329
|
)
|
330
330
|
else:
|
331
331
|
z = layer(
|
332
332
|
z,
|
333
333
|
pair_mask,
|
334
334
|
chunk_size_tri_attn,
|
335
|
-
use_kernels
|
335
|
+
use_kernels,
|
336
336
|
)
|
337
337
|
return z
|
boltz/model/models/boltz2.py
CHANGED
@@ -593,7 +593,7 @@ class Boltz2(LightningModule):
|
|
593
593
|
pred_distogram_logits=(
|
594
594
|
dict_out["pdistogram"][
|
595
595
|
:, :, :, 0
|
596
|
-
].detach() # TODO only
|
596
|
+
].detach() # TODO only implemented for 1 distogram
|
597
597
|
),
|
598
598
|
multiplicity=diffusion_samples,
|
599
599
|
run_sequentially=run_confidence_sequentially,
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
boltz-sdf-to-pre-affinity: Convert a docked SDF file (protein-ligand complex) to Boltz pre_affinity_[ligand_id].npz format.
|
4
|
+
|
5
|
+
Usage:
|
6
|
+
boltz-sdf-to-pre-affinity --sdf docked_pose.sdf --ligand_id ligand1 --output pre_affinity_ligand1.npz
|
7
|
+
|
8
|
+
This command is available after installing boltz with pip.
|
9
|
+
"""
|
10
|
+
import argparse
|
11
|
+
from pathlib import Path
|
12
|
+
|
13
|
+
from boltz.data.parse.sdf import parse_sdf
|
14
|
+
from boltz.data.types import StructureV2
|
15
|
+
|
16
|
+
|
17
|
+
def main():
|
18
|
+
parser = argparse.ArgumentParser(description="Convert SDF to Boltz pre_affinity_*.npz format.")
|
19
|
+
parser.add_argument('--sdf', type=str, required=True, help='Input SDF file (protein-ligand complex)')
|
20
|
+
parser.add_argument('--ligand_id', type=str, required=True, help='Ligand ID (used in output filename)')
|
21
|
+
parser.add_argument('--output', type=str, required=True, help='Output .npz file path')
|
22
|
+
args = parser.parse_args()
|
23
|
+
|
24
|
+
sdf_path = Path(args.sdf)
|
25
|
+
output_path = Path(args.output)
|
26
|
+
|
27
|
+
# Parse the SDF file to StructureV2
|
28
|
+
structure: StructureV2 = parse_sdf(sdf_path)
|
29
|
+
|
30
|
+
# Save as pre_affinity_[ligand_id].npz
|
31
|
+
structure.dump(output_path)
|
32
|
+
print(f"Saved: {output_path}")
|
33
|
+
|
34
|
+
if __name__ == "__main__":
|
35
|
+
main()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: boltz-vsynthes
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.12
|
4
4
|
Summary: Boltz for VSYNTHES
|
5
5
|
Requires-Python: <3.13,>=3.10
|
6
6
|
Description-Content-Type: text/markdown
|
@@ -43,8 +43,8 @@ Dynamic: license-file
|
|
43
43
|
<img src="docs/boltz2_title.png" width="300"/>
|
44
44
|
<img src="https://model-gateway.boltz.bio/a.png?x-pxid=bce1627f-f326-4bff-8a97-45c6c3bc929d" />
|
45
45
|
|
46
|
-
[Boltz-1](https://doi.org/10.1101/2024.11.19.624167) | [Boltz-2](https://
|
47
|
-
[Slack](https://join.slack.com/t/boltz-community/shared_invite/zt-
|
46
|
+
[Boltz-1](https://doi.org/10.1101/2024.11.19.624167) | [Boltz-2](https://doi.org/10.1101/2025.06.14.659707) |
|
47
|
+
[Slack](https://join.slack.com/t/boltz-community/shared_invite/zt-37uc4m8t2-gbbph6ka704ORcDCHLlFKg) <br> <br>
|
48
48
|
</div>
|
49
49
|
|
50
50
|
|
@@ -56,7 +56,7 @@ Dynamic: license-file
|
|
56
56
|
|
57
57
|
Boltz is a family of models for biomolecular interaction prediction. Boltz-1 was the first fully open source model to approach AlphaFold3 accuracy. Our latest work Boltz-2 is a new biomolecular foundation model that goes beyond AlphaFold3 and Boltz-1 by jointly modeling complex structures and binding affinities, a critical component towards accurate molecular design. Boltz-2 is the first deep learning model to approach the accuracy of physics-based free-energy perturbation (FEP) methods, while running 1000x faster — making accurate in silico screening practical for early-stage drug discovery.
|
58
58
|
|
59
|
-
All the code and weights are provided under MIT license, making them freely available for both academic and commercial uses. For more information about the model, see the [Boltz-1](https://doi.org/10.1101/2024.11.19.624167) and [Boltz-2](https://
|
59
|
+
All the code and weights are provided under MIT license, making them freely available for both academic and commercial uses. For more information about the model, see the [Boltz-1](https://doi.org/10.1101/2024.11.19.624167) and [Boltz-2](https://doi.org/10.1101/2025.06.14.659707) technical reports. To discuss updates, tools and applications join our [Slack channel](https://join.slack.com/t/boltz-community/shared_invite/zt-37uc4m8t2-gbbph6ka704ORcDCHLlFKg).
|
60
60
|
|
61
61
|
## Installation
|
62
62
|
|
@@ -108,7 +108,7 @@ If you're interested in retraining the model, currently for Boltz-1 but soon for
|
|
108
108
|
|
109
109
|
## Contributing
|
110
110
|
|
111
|
-
We welcome external contributions and are eager to engage with the community. Connect with us on our [Slack channel](https://join.slack.com/t/boltz-community/shared_invite/zt-
|
111
|
+
We welcome external contributions and are eager to engage with the community. Connect with us on our [Slack channel](https://join.slack.com/t/boltz-community/shared_invite/zt-37uc4m8t2-gbbph6ka704ORcDCHLlFKg) to discuss advancements, share insights, and foster collaboration around Boltz-2.
|
112
112
|
|
113
113
|
Boltz also runs on Tenstorrent hardware thanks to a [fork](https://github.com/moritztng/tt-boltz) by Moritz Thüning.
|
114
114
|
|
@@ -126,8 +126,8 @@ If you use this code or the models in your research, please cite the following p
|
|
126
126
|
author = {Passaro, Saro and Corso, Gabriele and Wohlwend, Jeremy and Reveiz, Mateo and Thaler, Stephan and Somnath, Vignesh Ram and Getz, Noah and Portnoi, Tally and Roy, Julien and Stark, Hannes and Kwabi-Addo, David and Beaini, Dominique and Jaakkola, Tommi and Barzilay, Regina},
|
127
127
|
title = {Boltz-2: Towards Accurate and Efficient Binding Affinity Prediction},
|
128
128
|
year = {2025},
|
129
|
-
doi = {},
|
130
|
-
journal = {}
|
129
|
+
doi = {10.1101/2025.06.14.659707},
|
130
|
+
journal = {bioRxiv}
|
131
131
|
}
|
132
132
|
|
133
133
|
@article{wohlwend2024boltz1,
|
@@ -1,13 +1,13 @@
|
|
1
1
|
boltz/__init__.py,sha256=F_-so3S40iZrSZ89Ge4TS6aZqwWyZXq_H4AXGDlbA_g,187
|
2
|
-
boltz/main.py,sha256=
|
2
|
+
boltz/main.py,sha256=zBLxa6T8hxcBs7gj1BnWfgJSx6uki8iV-QgClvoaiSA,39951
|
3
3
|
boltz/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
boltz/data/const.py,sha256=1M-88Z6HkfKY6MkNtqcj3b9P-oX9xEXluh3qM_u8dNU,26779
|
5
5
|
boltz/data/mol.py,sha256=maOpPHEGX1VVXCIFY6pQNGF7gUBZPAfgSvuPf2QO1yc,34268
|
6
6
|
boltz/data/pad.py,sha256=O4CGOOc5TwFuuWeP7hKjMIIsljdfLj-VJtXQeVXFx8s,2066
|
7
7
|
boltz/data/types.py,sha256=4w9brpOCQe16AyByNrxz7pjIzrgzFNihtik3aaHvKaE,21965
|
8
8
|
boltz/data/crop/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
boltz/data/crop/affinity.py,sha256=
|
10
|
-
boltz/data/crop/boltz.py,sha256=
|
9
|
+
boltz/data/crop/affinity.py,sha256=NqGtvI83iOtWGDmAVwTpXyIzxeSSAHDauGCrmxqvsYs,5732
|
10
|
+
boltz/data/crop/boltz.py,sha256=bloP9vk6cmKIZ4zZoO04IXhbouSIEFvKbxBUoLEDQHE,9840
|
11
11
|
boltz/data/crop/cropper.py,sha256=BGDgFwNVUPyBZvcqnJwPyH_IfZ1NAYCZ_KMwbQf4HK4,1145
|
12
12
|
boltz/data/feature/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
boltz/data/feature/featurizer.py,sha256=yYWsgW3VAH9GOgfitZPt__gsB2bcxrzcvUQjKVeRYhc,44574
|
@@ -38,8 +38,8 @@ boltz/data/parse/csv.py,sha256=Hcq8rJW2njczahEr8jfd_o-zxLaNSgJ3YIoC9srIqpw,2518
|
|
38
38
|
boltz/data/parse/fasta.py,sha256=taI4s_CqPtyF0XaLJAsVAJHCL0GXm2g1g8Qeccdxikk,3906
|
39
39
|
boltz/data/parse/mmcif.py,sha256=25kEXCkx-OuaawAs7cdz0fxdRu5_CCO0AV00u84PrjQ,36822
|
40
40
|
boltz/data/parse/mmcif_with_constraints.py,sha256=WHYZckSqUwu-Nb9vmVmxHmC7uxwVrF7AVUeVKsc5wGQ,51473
|
41
|
-
boltz/data/parse/pdb.py,sha256=
|
42
|
-
boltz/data/parse/pdb_download.py,sha256=
|
41
|
+
boltz/data/parse/pdb.py,sha256=iybk4p2UgUy_ABGprDq_xxyPSdm1HAZsGTM0lhxVEwM,1654
|
42
|
+
boltz/data/parse/pdb_download.py,sha256=wge-scX-lOatX0q83W1wOsaql99rYp-6uGWSHEc995M,2718
|
43
43
|
boltz/data/parse/schema.py,sha256=kNu28U2_MGiecwWNlcxgaDH3WOcO0P-q2LdoSPSb66w,63826
|
44
44
|
boltz/data/parse/sdf.py,sha256=fs3MQVClDcCzxJaeVYiDuoh-fUrYc8Tcd5Bz8ws3FKI,2052
|
45
45
|
boltz/data/parse/yaml.py,sha256=GRFRMtDD4PQ4PIpA_S1jj0vRaEu2LlZd_g4rN1zUrNo,1505
|
@@ -50,7 +50,7 @@ boltz/data/sample/random.py,sha256=jmennDNfkuq2UByn55wrQTwNPCOBuu6_jBJT4VraL28,1
|
|
50
50
|
boltz/data/sample/sampler.py,sha256=LXV4FLQPdMC_ja4MjPj0kicErr8UXSWrKehPBF5zOxQ,1095
|
51
51
|
boltz/data/tokenize/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
52
52
|
boltz/data/tokenize/boltz.py,sha256=h4rb2Jm9u5SP0xWygg4zE2kJ_RySRvYYDwvwlKqsSa0,6643
|
53
|
-
boltz/data/tokenize/boltz2.py,sha256=
|
53
|
+
boltz/data/tokenize/boltz2.py,sha256=to7E9pJOlC7yVMpgKTNZvH2jSMEEot_hAFrKXzW2bTI,12822
|
54
54
|
boltz/data/tokenize/tokenizer.py,sha256=9okkO89A1RvQd5tcW9VLIKZCSvvUALosy2itdN1mDIE,484
|
55
55
|
boltz/data/write/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
56
56
|
boltz/data/write/mmcif.py,sha256=zHwe4ulietjCVz5JMzl4_bu4liqwwcUKlgr9orVVd2Q,12177
|
@@ -66,7 +66,7 @@ boltz/model/layers/dropout.py,sha256=kUr8_a84CtyYryQO1_VK44jGAD51qV4HTUQWXMV9xCc
|
|
66
66
|
boltz/model/layers/initialize.py,sha256=KnK9tUfGvCWkdwbcLvJYoL-Wmlo9YcIcKBtdrXaUG30,2463
|
67
67
|
boltz/model/layers/outer_product_mean.py,sha256=AZoWhbaZHvVCmKSRWJ8Jw7xaCiN232VBjFsMclk_SR8,3151
|
68
68
|
boltz/model/layers/pair_averaging.py,sha256=XXZipyOlxZv4QR4Uk2cIUe8Ow_Xpr45eECqsWouNAVs,4332
|
69
|
-
boltz/model/layers/pairformer.py,sha256=
|
69
|
+
boltz/model/layers/pairformer.py,sha256=Oh8mOXOBgjSbFXuc4kjqnOkYb5ZtIRLZTYX5TXi_CyI,10302
|
70
70
|
boltz/model/layers/relative.py,sha256=fLOwADG5VDDdH2Gqis-L6Lw8hnWGxCPjfV6t8kYeEIc,1875
|
71
71
|
boltz/model/layers/transition.py,sha256=zFClGmqmaUVUIFSd4W4pVY17lvin2NpvaZMKuec4zzc,2290
|
72
72
|
boltz/model/layers/triangular_mult.py,sha256=uQahL0rwZ04xPK95UOWjHlB48VypDBSaIXKVDmWCzJw,5996
|
@@ -85,7 +85,7 @@ boltz/model/loss/distogramv2.py,sha256=dFgMGwpdLK4-skHJwvpERG10KfF3ZUN1T9_hUj-iW
|
|
85
85
|
boltz/model/loss/validation.py,sha256=gYpbag9mulg5HJPXjOUFaMV9XSYX_s2bIQ0iYjiAow0,33501
|
86
86
|
boltz/model/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
87
87
|
boltz/model/models/boltz1.py,sha256=x-x0b3VAXiAkPUBePnF56k1aYEPNgX1M6GtNCYVdCso,51718
|
88
|
-
boltz/model/models/boltz2.py,sha256=
|
88
|
+
boltz/model/models/boltz2.py,sha256=3XOWjUWaSJquw8Xdp7JItDUnVDyoC0qtx3q4MFQrd38,51523
|
89
89
|
boltz/model/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
90
90
|
boltz/model/modules/affinity.py,sha256=FktI2wrkDqsjGHJOuvzVrZK78MOPjU65QN0l6sB1QPQ,7041
|
91
91
|
boltz/model/modules/confidence.py,sha256=sXGymZiiMtfXPkUvHpa2KCCvNY79D8jXXEx9Gz2rNFs,17475
|
@@ -108,10 +108,11 @@ boltz/model/potentials/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
108
108
|
boltz/model/potentials/potentials.py,sha256=vev8Vjfs-ML1hyrdv_R8DynG4wSFahJ6nzPWp7CYQqw,17507
|
109
109
|
boltz/model/potentials/schedules.py,sha256=m7XJjfuF9uTX3bR9VisXv1rvzJjxiD8PobXRpcBBu1c,968
|
110
110
|
boltz/utils/sdf_splitter.py,sha256=ZHn_syOcmm-fDnJ3YEGyGv_vYz2IRzUW7vbbMSU2JBY,2108
|
111
|
+
boltz/utils/sdf_to_pre_affinity_npz.py,sha256=ev0s2pS8NoB-_3BkSjRKk3GMnqjOxTRCH-r9avKYGOg,1212
|
111
112
|
boltz/utils/yaml_generator.py,sha256=ermWIG-BE6nNWHFvpEwpk92N9J-YATpGXZGLvD1I2oQ,4012
|
112
|
-
boltz_vsynthes-0.0.
|
113
|
-
boltz_vsynthes-0.0.
|
114
|
-
boltz_vsynthes-0.0.
|
115
|
-
boltz_vsynthes-0.0.
|
116
|
-
boltz_vsynthes-0.0.
|
117
|
-
boltz_vsynthes-0.0.
|
113
|
+
boltz_vsynthes-0.0.12.dist-info/licenses/LICENSE,sha256=8GZ_1eZsUeG6jdqgJJxtciWzADfgLEV4LY8sKUOsJhc,1102
|
114
|
+
boltz_vsynthes-0.0.12.dist-info/METADATA,sha256=XPcHZExavOK9oz8BaZnp31f-acFOXbCKwmDORbDxaP8,7235
|
115
|
+
boltz_vsynthes-0.0.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
116
|
+
boltz_vsynthes-0.0.12.dist-info/entry_points.txt,sha256=WlXNdHTJF1ahGN-H1QpgMbZm_5SobXY05eiuT8buycw,212
|
117
|
+
boltz_vsynthes-0.0.12.dist-info/top_level.txt,sha256=MgU3Jfb-ctWm07YGMts68PMjSh9v26D0gfG3dFRmVFA,6
|
118
|
+
boltz_vsynthes-0.0.12.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|