Skip to content

Commit 16c4394

Browse files
committed
Release v0.8.6
- Fix boltz confidence retrieval - Properly handle when model metadata input tokens is null, e.g. msa for AF2 - Some documentation fixes - Add metadata for fold
1 parent 5616f2a commit 16c4394

File tree

4 files changed

+66
-39
lines changed

4 files changed

+66
-39
lines changed

anaconda_build/meta.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package:
22
name: openprotein-python
3-
version: "0.8.5"
3+
version: "0.8.6"
44

55
source:
66
path: ../

openprotein/common/model_metadata.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ class ModelMetadata(BaseModel):
2828
max_sequence_length: int | None = None
2929
dimension: int
3030
output_types: list[str]
31-
input_tokens: list[str]
31+
input_tokens: list[str] | None
3232
output_tokens: list[str] | None = None
3333
token_descriptions: list[list[TokenInfo]]

openprotein/fold/alphafold2.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,8 @@ def fold(
4747
number of times to recycle models
4848
num_models : int
4949
number of models to train - best model will be used
50-
max_msa : Union[str, int]
51-
maximum number of sequences in the msa to use.
52-
relax_max_iterations : int
53-
maximum number of iterations
50+
num_relax : int
51+
maximum number of iterations for relax
5452
5553
Returns
5654
-------
@@ -61,6 +59,7 @@ def fold(
6159
"Inputs to AlphaFold 2 have been updated. 'msa' should be supplied as 'proteins' argument. Support will be dropped in the future."
6260
)
6361
proteins = kwargs["msa"]
62+
assert isinstance(proteins, MSAFuture), "Expected msa to be an MSAFuture"
6463
if "ligands" in kwargs or "dnas" in kwargs or "rnas" in kwargs:
6564
with warnings.catch_warnings():
6665
warnings.simplefilter("always") # Force warning to always show
@@ -73,6 +72,10 @@ def fold(
7372
msa_to_seed: dict[str, Counter] = dict()
7473
for protein in proteins:
7574
if (msa := protein.msa) is not None:
75+
if isinstance(msa, Protein.NullMSA):
76+
raise ValueError(
77+
"AlphaFold 2 expects MSA and does not support single sequence mode"
78+
)
7679
msa_id = msa.id if isinstance(msa, MSAFuture) else msa
7780
if msa_id in msa_to_seed:
7881
seeds = msa_to_seed[msa_id]

openprotein/fold/future.py

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
from openprotein import config
1010
from openprotein.base import APISession
1111
from openprotein.chains import DNA, RNA, Ligand
12-
from openprotein.jobs import Future, MappedFuture
12+
from openprotein.jobs import Future, JobsAPI, MappedFuture
1313
from openprotein.protein import Protein
1414

1515
from . import api
16-
from .schemas import FoldJob
16+
from .schemas import FoldJob, FoldMetadata
1717

1818
if TYPE_CHECKING:
1919
from .boltz import BoltzAffinity, BoltzConfidence
@@ -34,34 +34,39 @@ class FoldResultFuture(MappedFuture, Future):
3434
def __init__(
3535
self,
3636
session: APISession,
37-
job: FoldJob,
37+
job: FoldJob | None = None,
38+
metadata: FoldMetadata | None = None,
3839
sequences: list[bytes] | None = None,
3940
max_workers: int = config.MAX_CONCURRENT_WORKERS,
4041
):
4142
"""
4243
Initialize a FoldResultFuture instance.
4344
44-
Parameters
45-
----------
46-
session : APISession
47-
The API session to use for requests.
48-
job : FoldJob
49-
The fold job associated with this future.
50-
sequences : list[bytes], optional
51-
List of sequences submitted for the fold request. If None, sequences will be fetched.
52-
max_workers : int, optional
53-
Maximum number of concurrent workers. Default is config.MAX_CONCURRENT_WORKERS.
45+
Takes in either a fold job, or the fold job metadata.
46+
47+
:meta private:
5448
"""
55-
super().__init__(session, job, max_workers)
49+
# initialize the fold job metadata
50+
if metadata is None:
51+
if job is None or job.job_id is None:
52+
raise ValueError("Expected fold metadata or job")
53+
metadata = api.fold_get(session, job.job_id)
54+
self._metadata = metadata
55+
if job is None:
56+
jobs_api = getattr(session, "jobs", None)
57+
assert isinstance(jobs_api, JobsAPI)
58+
job = FoldJob.create(jobs_api.get_job(job_id=metadata.job_id))
5659
if sequences is None:
5760
sequences = api.fold_get_sequences(self.session, job_id=job.job_id)
5861
self._sequences = sequences
62+
super().__init__(session, job, max_workers)
5963

6064
@classmethod
6165
def create(
6266
cls: type[Self],
6367
session: APISession,
64-
job: FoldJob,
68+
job: FoldJob | None = None,
69+
metadata: FoldMetadata | None = None,
6570
**kwargs,
6671
) -> "Self | FoldComplexResultFuture":
6772
"""
@@ -81,7 +86,13 @@ def create(
8186
FoldResultFuture or FoldComplexResultFuture
8287
An instance of FoldResultFuture or FoldComplexResultFuture depending on the model.
8388
"""
84-
model_id = api.fold_get(session=session, job_id=job.job_id).model_id
89+
if job is not None:
90+
job_id = job.job_id
91+
elif metadata is not None:
92+
job_id = metadata.job_id
93+
else:
94+
raise ValueError("Expected fold metadata or job")
95+
model_id = api.fold_get(session=session, job_id=job_id).model_id
8596
if model_id.startswith("boltz") or model_id.startswith("alphafold"):
8697
return FoldComplexResultFuture(session=session, job=job, **kwargs)
8798
else:
@@ -101,22 +112,6 @@ def sequences(self) -> list[bytes]:
101112
self._sequences = api.fold_get_sequences(self.session, self.job.job_id)
102113
return self._sequences
103114

104-
@property
105-
def model_id(self) -> str:
106-
"""
107-
Get the model ID used for the fold request.
108-
109-
Returns
110-
-------
111-
str
112-
Model ID.
113-
"""
114-
if self._model_id is None:
115-
self._model_id = api.fold_get(
116-
session=self.session, job_id=self.job.job_id
117-
).model_id
118-
return self._model_id
119-
120115
@property
121116
def id(self):
122117
"""
@@ -129,6 +124,17 @@ def id(self):
129124
"""
130125
return self.job.job_id
131126

127+
128+
@property
129+
def metadata(self) -> FoldMetadata:
130+
"""The fold metadata."""
131+
return self._metadata
132+
133+
@property
134+
def model_id(self) -> str:
135+
"""The fold model used."""
136+
return self._metadata.model_id
137+
132138
def __keys__(self):
133139
"""
134140
Get the list of sequences submitted for the fold request.
@@ -189,7 +195,8 @@ class FoldComplexResultFuture(Future):
189195
def __init__(
190196
self,
191197
session: APISession,
192-
job: FoldJob,
198+
job: FoldJob | None = None,
199+
metadata: FoldMetadata | None = None,
193200
model_id: str | None = None,
194201
proteins: list[Protein] | None = None,
195202
ligands: list[Ligand] | None = None,
@@ -216,6 +223,16 @@ def __init__(
216223
rnas : list[RNA], optional
217224
List of RNAs submitted for fold request.
218225
"""
226+
# initialize the fold job metadata
227+
if metadata is None:
228+
if job is None or job.job_id is None:
229+
raise ValueError("Expected fold metadata or job")
230+
metadata = api.fold_get(session, job.job_id)
231+
self._metadata = metadata
232+
if job is None:
233+
jobs_api = getattr(session, "jobs", None)
234+
assert isinstance(jobs_api, JobsAPI)
235+
job = FoldJob.create(jobs_api.get_job(job_id=metadata.job_id))
219236
super().__init__(session, job)
220237
self._model_id = model_id
221238
self._proteins = proteins
@@ -229,6 +246,11 @@ def __init__(
229246
self._confidence: list["BoltzConfidence"] | None = None
230247
self._affinity: "BoltzAffinity | None" = None
231248

249+
@property
250+
def metadata(self) -> FoldMetadata:
251+
"""The fold metadata."""
252+
return self._metadata
253+
232254
@property
233255
def model_id(self) -> str:
234256
"""
@@ -433,6 +455,8 @@ def confidence(self) -> list["BoltzConfidence"]:
433455
AttributeError
434456
If confidence is not supported for the model.
435457
"""
458+
from .boltz import BoltzConfidence
459+
436460
if self.model_id not in {"boltz-1", "boltz-1x", "boltz-2"}:
437461
raise AttributeError("confidence not supported for non-Boltz model")
438462
if self._confidence is None:

0 commit comments

Comments
 (0)