openprotein-python 0.8.2__1-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.
- openprotein/__init__.py +164 -0
- openprotein/_version.py +48 -0
- openprotein/align/__init__.py +8 -0
- openprotein/align/align.py +395 -0
- openprotein/align/api.py +428 -0
- openprotein/align/future.py +55 -0
- openprotein/align/msa.py +129 -0
- openprotein/align/schemas.py +165 -0
- openprotein/base.py +181 -0
- openprotein/chains.py +88 -0
- openprotein/common/__init__.py +5 -0
- openprotein/common/features.py +7 -0
- openprotein/common/model_metadata.py +33 -0
- openprotein/common/reduction.py +8 -0
- openprotein/config.py +9 -0
- openprotein/csv.py +31 -0
- openprotein/data/__init__.py +9 -0
- openprotein/data/api.py +218 -0
- openprotein/data/assaydataset.py +178 -0
- openprotein/data/data.py +93 -0
- openprotein/data/schemas.py +27 -0
- openprotein/design/__init__.py +16 -0
- openprotein/design/api.py +259 -0
- openprotein/design/design.py +125 -0
- openprotein/design/future.py +146 -0
- openprotein/design/schemas.py +607 -0
- openprotein/embeddings/__init__.py +27 -0
- openprotein/embeddings/api.py +619 -0
- openprotein/embeddings/embeddings.py +151 -0
- openprotein/embeddings/esm.py +33 -0
- openprotein/embeddings/future.py +146 -0
- openprotein/embeddings/models.py +421 -0
- openprotein/embeddings/openprotein.py +21 -0
- openprotein/embeddings/poet.py +446 -0
- openprotein/embeddings/poet2.py +505 -0
- openprotein/embeddings/schemas.py +78 -0
- openprotein/errors.py +76 -0
- openprotein/fasta.py +92 -0
- openprotein/fold/__init__.py +21 -0
- openprotein/fold/alphafold2.py +131 -0
- openprotein/fold/api.py +287 -0
- openprotein/fold/boltz.py +691 -0
- openprotein/fold/esmfold.py +54 -0
- openprotein/fold/fold.py +107 -0
- openprotein/fold/future.py +509 -0
- openprotein/fold/models.py +139 -0
- openprotein/fold/schemas.py +39 -0
- openprotein/jobs/__init__.py +9 -0
- openprotein/jobs/api.py +71 -0
- openprotein/jobs/futures.py +746 -0
- openprotein/jobs/jobs.py +69 -0
- openprotein/jobs/schemas.py +135 -0
- openprotein/models/__init__.py +4 -0
- openprotein/models/base.py +63 -0
- openprotein/models/foundation/rfdiffusion.py +283 -0
- openprotein/models/models.py +33 -0
- openprotein/predictor/__init__.py +25 -0
- openprotein/predictor/api.py +384 -0
- openprotein/predictor/models.py +374 -0
- openprotein/predictor/prediction.py +79 -0
- openprotein/predictor/predictor.py +242 -0
- openprotein/predictor/schemas.py +113 -0
- openprotein/predictor/validate.py +40 -0
- openprotein/prompt/__init__.py +9 -0
- openprotein/prompt/api.py +505 -0
- openprotein/prompt/models.py +142 -0
- openprotein/prompt/prompt.py +130 -0
- openprotein/prompt/schemas.py +49 -0
- openprotein/protein.py +587 -0
- openprotein/svd/__init__.py +9 -0
- openprotein/svd/api.py +206 -0
- openprotein/svd/models.py +288 -0
- openprotein/svd/schemas.py +31 -0
- openprotein/svd/svd.py +134 -0
- openprotein/umap/__init__.py +9 -0
- openprotein/umap/api.py +259 -0
- openprotein/umap/models.py +211 -0
- openprotein/umap/schemas.py +35 -0
- openprotein/umap/umap.py +175 -0
- openprotein/utils/uuid.py +29 -0
- openprotein_python-0.8.2.dist-info/METADATA +176 -0
- openprotein_python-0.8.2.dist-info/RECORD +84 -0
- openprotein_python-0.8.2.dist-info/WHEEL +4 -0
- openprotein_python-0.8.2.dist-info/licenses/LICENSE.txt +30 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Community-based ESMFold model."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
|
|
5
|
+
from openprotein.base import APISession
|
|
6
|
+
from openprotein.common import ModelMetadata
|
|
7
|
+
|
|
8
|
+
from . import api
|
|
9
|
+
from .future import FoldResultFuture
|
|
10
|
+
from .models import FoldModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ESMFoldModel(FoldModel):
|
|
14
|
+
"""
|
|
15
|
+
Class providing inference endpoints for Facebook's ESMFold structure prediction models.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
model_id: str = "esmfold"
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
session: APISession,
|
|
23
|
+
model_id: str,
|
|
24
|
+
metadata: ModelMetadata | None = None,
|
|
25
|
+
):
|
|
26
|
+
super().__init__(session=session, model_id=model_id, metadata=metadata)
|
|
27
|
+
|
|
28
|
+
def fold(
|
|
29
|
+
self, sequences: Sequence[bytes | str], num_recycles: int | None = None
|
|
30
|
+
) -> FoldResultFuture:
|
|
31
|
+
"""
|
|
32
|
+
Fold sequences using this model.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
sequences : Sequence[bytes | str]
|
|
37
|
+
sequences to fold
|
|
38
|
+
num_recycles : int | None
|
|
39
|
+
number of times to recycle models
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
FoldResultFuture
|
|
43
|
+
"""
|
|
44
|
+
result = FoldResultFuture.create(
|
|
45
|
+
session=self.session,
|
|
46
|
+
job=api.fold_models_post(
|
|
47
|
+
session=self.session,
|
|
48
|
+
model_id=self.model_id,
|
|
49
|
+
sequences=sequences,
|
|
50
|
+
num_recycles=num_recycles,
|
|
51
|
+
),
|
|
52
|
+
)
|
|
53
|
+
assert isinstance(result, FoldResultFuture)
|
|
54
|
+
return result
|
openprotein/fold/fold.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Fold API interface for making structure prediction requests."""
|
|
2
|
+
|
|
3
|
+
from openprotein.base import APISession
|
|
4
|
+
|
|
5
|
+
from . import api
|
|
6
|
+
from .alphafold2 import AlphaFold2Model
|
|
7
|
+
from .boltz import Boltz1Model, Boltz1xModel, Boltz2Model
|
|
8
|
+
from .esmfold import ESMFoldModel
|
|
9
|
+
from .future import FoldComplexResultFuture, FoldResultFuture
|
|
10
|
+
from .models import (
|
|
11
|
+
FoldModel,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FoldAPI:
|
|
16
|
+
"""
|
|
17
|
+
Fold API provides a high level interface for making protein structure predictions.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
#: Boltz-2 model
|
|
21
|
+
boltz2: Boltz2Model
|
|
22
|
+
boltz_2: Boltz2Model
|
|
23
|
+
#: Boltz-1x model
|
|
24
|
+
boltz1x: Boltz1xModel
|
|
25
|
+
boltz_1x: Boltz1xModel
|
|
26
|
+
#: Boltz-1 model
|
|
27
|
+
boltz1: Boltz1Model
|
|
28
|
+
boltz_1: Boltz1Model
|
|
29
|
+
af2: AlphaFold2Model
|
|
30
|
+
#: AlphaFold-2 model
|
|
31
|
+
alphafold2: AlphaFold2Model
|
|
32
|
+
#: ESMFold model
|
|
33
|
+
esmfold: ESMFoldModel
|
|
34
|
+
|
|
35
|
+
def __init__(self, session: APISession):
|
|
36
|
+
self.session = session
|
|
37
|
+
self._load_models()
|
|
38
|
+
|
|
39
|
+
def _load_models(self):
|
|
40
|
+
# Dynamically add model instances as attributes - precludes any drift
|
|
41
|
+
models = self.list_models()
|
|
42
|
+
for model in models:
|
|
43
|
+
model_name = model.id.replace("-", "_") # hyphens out
|
|
44
|
+
setattr(self, model_name, model)
|
|
45
|
+
# Setup aliases safely
|
|
46
|
+
if getattr(self, "alphafold2", None):
|
|
47
|
+
self.af2 = self.alphafold2
|
|
48
|
+
if getattr(self, "boltz_1", None):
|
|
49
|
+
self.boltz1 = self.boltz_1
|
|
50
|
+
if getattr(self, "boltz_1x", None):
|
|
51
|
+
self.boltz1x = self.boltz_1x
|
|
52
|
+
if getattr(self, "boltz_2", None):
|
|
53
|
+
self.boltz2 = self.boltz_2
|
|
54
|
+
|
|
55
|
+
def list_models(self) -> list[FoldModel]:
|
|
56
|
+
"""list models available for creating folds of your sequences"""
|
|
57
|
+
models = []
|
|
58
|
+
for model_id in api.fold_models_list_get(self.session):
|
|
59
|
+
models.append(
|
|
60
|
+
FoldModel.create(
|
|
61
|
+
session=self.session, model_id=model_id, default=FoldModel
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
return models
|
|
65
|
+
|
|
66
|
+
def get_model(self, model_id: str) -> FoldModel:
|
|
67
|
+
"""
|
|
68
|
+
Get model by model_id.
|
|
69
|
+
|
|
70
|
+
FoldModel allows all the usual job manipulation: \
|
|
71
|
+
e.g. making POST and GET requests for this model specifically.
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
model_id : str
|
|
77
|
+
the model identifier
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
FoldModel
|
|
82
|
+
The model
|
|
83
|
+
|
|
84
|
+
Raises
|
|
85
|
+
------
|
|
86
|
+
HTTPError
|
|
87
|
+
If the GET request does not succeed.
|
|
88
|
+
"""
|
|
89
|
+
return FoldModel.create(
|
|
90
|
+
session=self.session, model_id=model_id, default=FoldModel
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def get_results(self, job) -> FoldResultFuture | FoldComplexResultFuture:
|
|
94
|
+
"""
|
|
95
|
+
Retrieves the results of a fold job.
|
|
96
|
+
|
|
97
|
+
Parameters
|
|
98
|
+
----------
|
|
99
|
+
job : Job
|
|
100
|
+
The fold job whose results are to be retrieved.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
FoldResultFuture
|
|
105
|
+
An instance of FoldResultFuture
|
|
106
|
+
"""
|
|
107
|
+
return FoldResultFuture.create(job=job, session=self.session)
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
"""Fold prediction results represented as futures."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Literal
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from pydantic.type_adapter import TypeAdapter
|
|
7
|
+
from typing_extensions import Self
|
|
8
|
+
|
|
9
|
+
from openprotein import config
|
|
10
|
+
from openprotein.base import APISession
|
|
11
|
+
from openprotein.chains import DNA, RNA, Ligand
|
|
12
|
+
from openprotein.jobs import Future, MappedFuture
|
|
13
|
+
from openprotein.protein import Protein
|
|
14
|
+
|
|
15
|
+
from . import api
|
|
16
|
+
from .schemas import FoldJob
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from .boltz import BoltzAffinity, BoltzConfidence
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class FoldResultFuture(MappedFuture, Future):
|
|
23
|
+
"""
|
|
24
|
+
Fold results represented as a future.
|
|
25
|
+
|
|
26
|
+
Attributes
|
|
27
|
+
----------
|
|
28
|
+
job : FoldJob
|
|
29
|
+
The fold job associated with this future.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
job: FoldJob
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
session: APISession,
|
|
37
|
+
job: FoldJob,
|
|
38
|
+
sequences: list[bytes] | None = None,
|
|
39
|
+
max_workers: int = config.MAX_CONCURRENT_WORKERS,
|
|
40
|
+
):
|
|
41
|
+
"""
|
|
42
|
+
Initialize a FoldResultFuture instance.
|
|
43
|
+
|
|
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.
|
|
54
|
+
"""
|
|
55
|
+
super().__init__(session, job, max_workers)
|
|
56
|
+
if sequences is None:
|
|
57
|
+
sequences = api.fold_get_sequences(self.session, job_id=job.job_id)
|
|
58
|
+
self._sequences = sequences
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def create(
|
|
62
|
+
cls: type[Self],
|
|
63
|
+
session: APISession,
|
|
64
|
+
job: FoldJob,
|
|
65
|
+
**kwargs,
|
|
66
|
+
) -> "Self | FoldComplexResultFuture":
|
|
67
|
+
"""
|
|
68
|
+
Factory method to create a FoldResultFuture or FoldComplexResultFuture.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
session : APISession
|
|
73
|
+
The API session to use for requests.
|
|
74
|
+
job : FoldJob
|
|
75
|
+
The fold job associated with this future.
|
|
76
|
+
**kwargs
|
|
77
|
+
Additional keyword arguments.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
FoldResultFuture or FoldComplexResultFuture
|
|
82
|
+
An instance of FoldResultFuture or FoldComplexResultFuture depending on the model.
|
|
83
|
+
"""
|
|
84
|
+
model_id = api.fold_get(session=session, job_id=job.job_id).model_id
|
|
85
|
+
if model_id.startswith("boltz") or model_id.startswith("alphafold"):
|
|
86
|
+
return FoldComplexResultFuture(session=session, job=job, **kwargs)
|
|
87
|
+
else:
|
|
88
|
+
return cls(session=session, job=job, **kwargs)
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def sequences(self) -> list[bytes]:
|
|
92
|
+
"""
|
|
93
|
+
Get the sequences submitted for the fold request.
|
|
94
|
+
|
|
95
|
+
Returns
|
|
96
|
+
-------
|
|
97
|
+
list[bytes]
|
|
98
|
+
List of sequences.
|
|
99
|
+
"""
|
|
100
|
+
if self._sequences is None:
|
|
101
|
+
self._sequences = api.fold_get_sequences(self.session, self.job.job_id)
|
|
102
|
+
return self._sequences
|
|
103
|
+
|
|
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
|
+
|
|
120
|
+
@property
|
|
121
|
+
def id(self):
|
|
122
|
+
"""
|
|
123
|
+
Get the ID of the fold request.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
str
|
|
128
|
+
Fold job ID.
|
|
129
|
+
"""
|
|
130
|
+
return self.job.job_id
|
|
131
|
+
|
|
132
|
+
def __keys__(self):
|
|
133
|
+
"""
|
|
134
|
+
Get the list of sequences submitted for the fold request.
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
list of bytes
|
|
139
|
+
List of sequences.
|
|
140
|
+
"""
|
|
141
|
+
return self.sequences
|
|
142
|
+
|
|
143
|
+
def get(self, verbose=False) -> list[tuple[str, bytes]]:
|
|
144
|
+
"""
|
|
145
|
+
Retrieve the fold results as a list of tuples mapping sequence to PDB-encoded string.
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
verbose : bool, optional
|
|
150
|
+
If True, print verbose output. Default is False.
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
list[tuple[str, str]]
|
|
155
|
+
List of tuples mapping sequence to PDB-encoded string.
|
|
156
|
+
"""
|
|
157
|
+
return super().get(verbose=verbose)
|
|
158
|
+
|
|
159
|
+
def get_item(self, sequence: bytes) -> bytes:
|
|
160
|
+
"""
|
|
161
|
+
Get fold results for a specified sequence.
|
|
162
|
+
|
|
163
|
+
Parameters
|
|
164
|
+
----------
|
|
165
|
+
sequence : bytes
|
|
166
|
+
Sequence to fetch results for.
|
|
167
|
+
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
170
|
+
bytes
|
|
171
|
+
Fold result for the specified sequence.
|
|
172
|
+
"""
|
|
173
|
+
data = api.fold_get_sequence_result(self.session, self.job.job_id, sequence)
|
|
174
|
+
return data
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class FoldComplexResultFuture(Future):
|
|
178
|
+
"""
|
|
179
|
+
Future for manipulating results of a fold complex request.
|
|
180
|
+
|
|
181
|
+
Attributes
|
|
182
|
+
----------
|
|
183
|
+
job : FoldJob
|
|
184
|
+
The fold job associated with this future.
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
job: FoldJob
|
|
188
|
+
|
|
189
|
+
def __init__(
|
|
190
|
+
self,
|
|
191
|
+
session: APISession,
|
|
192
|
+
job: FoldJob,
|
|
193
|
+
model_id: str | None = None,
|
|
194
|
+
proteins: list[Protein] | None = None,
|
|
195
|
+
ligands: list[Ligand] | None = None,
|
|
196
|
+
dnas: list[DNA] | None = None,
|
|
197
|
+
rnas: list[RNA] | None = None,
|
|
198
|
+
):
|
|
199
|
+
"""
|
|
200
|
+
Initialize a FoldComplexResultFuture instance.
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
session : APISession
|
|
205
|
+
The API session to use for requests.
|
|
206
|
+
job : FoldJob
|
|
207
|
+
The fold job associated with this future.
|
|
208
|
+
model_id : str, optional
|
|
209
|
+
Model ID used for the fold request.
|
|
210
|
+
proteins : list[Protein], optional
|
|
211
|
+
List of proteins submitted for fold request.
|
|
212
|
+
ligands : list[Ligand], optional
|
|
213
|
+
List of ligands submitted for fold request.
|
|
214
|
+
dnas : list[DNA], optional
|
|
215
|
+
List of DNAs submitted for fold request.
|
|
216
|
+
rnas : list[RNA], optional
|
|
217
|
+
List of RNAs submitted for fold request.
|
|
218
|
+
"""
|
|
219
|
+
super().__init__(session, job)
|
|
220
|
+
self._model_id = model_id
|
|
221
|
+
self._proteins = proteins
|
|
222
|
+
self._ligands = ligands
|
|
223
|
+
self._dnas = dnas
|
|
224
|
+
self._rnas = rnas
|
|
225
|
+
self._initialized = not (proteins == ligands == dnas == rnas == None)
|
|
226
|
+
self._pae: np.ndarray | None = None
|
|
227
|
+
self._pde: np.ndarray | None = None
|
|
228
|
+
self._plddt: np.ndarray | None = None
|
|
229
|
+
self._confidence: list["BoltzConfidence"] | None = None
|
|
230
|
+
self._affinity: "BoltzAffinity | None" = None
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def model_id(self) -> str:
|
|
234
|
+
"""
|
|
235
|
+
Get the model ID used for the fold request.
|
|
236
|
+
|
|
237
|
+
Returns
|
|
238
|
+
-------
|
|
239
|
+
str
|
|
240
|
+
Model ID.
|
|
241
|
+
"""
|
|
242
|
+
if self._model_id is None:
|
|
243
|
+
self._model_id = api.fold_get(
|
|
244
|
+
session=self.session, job_id=self.job.job_id
|
|
245
|
+
).model_id
|
|
246
|
+
return self._model_id
|
|
247
|
+
|
|
248
|
+
def __get_chains(self):
|
|
249
|
+
"""
|
|
250
|
+
Internal method to initialize chain objects (proteins, dnas, rnas, ligands)
|
|
251
|
+
from the fold job arguments.
|
|
252
|
+
"""
|
|
253
|
+
args = api.fold_get(session=self.session, job_id=self.job.job_id).args
|
|
254
|
+
assert args is not None and "sequences" in args
|
|
255
|
+
for chain in args["sequences"]:
|
|
256
|
+
assert isinstance(chain, dict)
|
|
257
|
+
for chain_type, chain_info in chain:
|
|
258
|
+
if chain_type == "protein":
|
|
259
|
+
self._proteins = self._proteins or []
|
|
260
|
+
protein = Protein(sequence=chain_info["sequence"])
|
|
261
|
+
protein.chain_id = chain_info.get("id")
|
|
262
|
+
protein.msa = chain_info.get("msa_id")
|
|
263
|
+
self._proteins.append(protein)
|
|
264
|
+
elif chain_type == "dna":
|
|
265
|
+
self._dnas = self._dnas or []
|
|
266
|
+
dna = DNA(sequence=chain_info["sequence"])
|
|
267
|
+
dna.chain_id = chain_info.get("id")
|
|
268
|
+
self._dnas.append(dna)
|
|
269
|
+
elif chain_type == "rna":
|
|
270
|
+
self._rnas = self._rnas or []
|
|
271
|
+
rna = RNA(sequence=chain_info["sequence"])
|
|
272
|
+
rna.chain_id = chain_info.get("id")
|
|
273
|
+
self._rnas.append(rna)
|
|
274
|
+
elif chain_type == "ligand":
|
|
275
|
+
self._ligands = self._ligands or []
|
|
276
|
+
ligand = Ligand(
|
|
277
|
+
chain_id=chain_info.get("id"),
|
|
278
|
+
ccd=chain_info.get("ccd"),
|
|
279
|
+
smiles=chain_info.get("smiles"),
|
|
280
|
+
)
|
|
281
|
+
self._ligands.append(ligand)
|
|
282
|
+
else:
|
|
283
|
+
pass
|
|
284
|
+
self._initialized = True
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def proteins(self) -> list[Protein] | None:
|
|
288
|
+
"""
|
|
289
|
+
Get the proteins submitted for the fold request.
|
|
290
|
+
|
|
291
|
+
Returns
|
|
292
|
+
-------
|
|
293
|
+
list[Protein] or None
|
|
294
|
+
List of Protein objects or None.
|
|
295
|
+
"""
|
|
296
|
+
if not self._initialized:
|
|
297
|
+
self.__get_chains()
|
|
298
|
+
return self._proteins
|
|
299
|
+
|
|
300
|
+
@property
|
|
301
|
+
def dnas(self) -> list[DNA] | None:
|
|
302
|
+
"""
|
|
303
|
+
Get the DNAs submitted for the fold request.
|
|
304
|
+
|
|
305
|
+
Returns
|
|
306
|
+
-------
|
|
307
|
+
list[DNA] or None
|
|
308
|
+
List of DNA objects or None.
|
|
309
|
+
"""
|
|
310
|
+
if not self._initialized:
|
|
311
|
+
self.__get_chains()
|
|
312
|
+
return self._dnas
|
|
313
|
+
|
|
314
|
+
@property
|
|
315
|
+
def rnas(self) -> list[RNA] | None:
|
|
316
|
+
"""
|
|
317
|
+
Get the RNAs submitted for the fold request.
|
|
318
|
+
|
|
319
|
+
Returns
|
|
320
|
+
-------
|
|
321
|
+
list[RNA] or None
|
|
322
|
+
List of RNA objects or None.
|
|
323
|
+
"""
|
|
324
|
+
if not self._initialized:
|
|
325
|
+
self.__get_chains()
|
|
326
|
+
return self._rnas
|
|
327
|
+
|
|
328
|
+
@property
|
|
329
|
+
def ligands(self) -> list[Ligand] | None:
|
|
330
|
+
"""
|
|
331
|
+
Get the ligands submitted for the fold request.
|
|
332
|
+
|
|
333
|
+
Returns
|
|
334
|
+
-------
|
|
335
|
+
list[Ligand] or None
|
|
336
|
+
List of Ligand objects or None.
|
|
337
|
+
"""
|
|
338
|
+
if not self._initialized:
|
|
339
|
+
self.__get_chains()
|
|
340
|
+
return self._ligands
|
|
341
|
+
|
|
342
|
+
@property
|
|
343
|
+
def pae(self) -> np.ndarray:
|
|
344
|
+
"""
|
|
345
|
+
Get the Predicted Aligned Error (PAE) matrix.
|
|
346
|
+
|
|
347
|
+
Returns
|
|
348
|
+
-------
|
|
349
|
+
np.ndarray
|
|
350
|
+
PAE matrix.
|
|
351
|
+
|
|
352
|
+
Raises
|
|
353
|
+
------
|
|
354
|
+
AttributeError
|
|
355
|
+
If PAE is not supported for the model.
|
|
356
|
+
"""
|
|
357
|
+
if self.model_id not in {"boltz-1", "boltz-1x", "boltz-2"}:
|
|
358
|
+
raise AttributeError("pae not supported for non-Boltz model")
|
|
359
|
+
if self._pae is None:
|
|
360
|
+
pae = api.fold_get_complex_extra_result(
|
|
361
|
+
session=self.session, job_id=self.job.job_id, key="pae"
|
|
362
|
+
)
|
|
363
|
+
assert isinstance(pae, np.ndarray)
|
|
364
|
+
self._pae = pae
|
|
365
|
+
return self._pae
|
|
366
|
+
|
|
367
|
+
@property
|
|
368
|
+
def pde(self) -> np.ndarray:
|
|
369
|
+
"""
|
|
370
|
+
Get the Predicted Distance Error (PDE) matrix.
|
|
371
|
+
|
|
372
|
+
Returns
|
|
373
|
+
-------
|
|
374
|
+
np.ndarray
|
|
375
|
+
PDE matrix.
|
|
376
|
+
|
|
377
|
+
Raises
|
|
378
|
+
------
|
|
379
|
+
AttributeError
|
|
380
|
+
If PDE is not supported for the model.
|
|
381
|
+
"""
|
|
382
|
+
if self.model_id not in {"boltz-1", "boltz-1x", "boltz-2"}:
|
|
383
|
+
raise AttributeError("pde not supported for non-Boltz model")
|
|
384
|
+
if self._pde is None:
|
|
385
|
+
pde = api.fold_get_complex_extra_result(
|
|
386
|
+
session=self.session, job_id=self.job.job_id, key="pde"
|
|
387
|
+
)
|
|
388
|
+
assert isinstance(pde, np.ndarray)
|
|
389
|
+
self._pde = pde
|
|
390
|
+
return self._pde
|
|
391
|
+
|
|
392
|
+
@property
|
|
393
|
+
def plddt(self) -> np.ndarray:
|
|
394
|
+
"""
|
|
395
|
+
Get the Predicted Local Distance Difference Test (pLDDT) scores.
|
|
396
|
+
|
|
397
|
+
Returns
|
|
398
|
+
-------
|
|
399
|
+
np.ndarray
|
|
400
|
+
pLDDT scores.
|
|
401
|
+
|
|
402
|
+
Raises
|
|
403
|
+
------
|
|
404
|
+
AttributeError
|
|
405
|
+
If pLDDT is not supported for the model.
|
|
406
|
+
"""
|
|
407
|
+
if self.model_id not in {"boltz-1", "boltz-1x", "boltz-2"}:
|
|
408
|
+
raise AttributeError("plddt not supported for non-Boltz model")
|
|
409
|
+
if self._plddt is None:
|
|
410
|
+
plddt = api.fold_get_complex_extra_result(
|
|
411
|
+
session=self.session, job_id=self.job.job_id, key="plddt"
|
|
412
|
+
)
|
|
413
|
+
assert isinstance(plddt, np.ndarray)
|
|
414
|
+
self._plddt = plddt
|
|
415
|
+
return self._plddt
|
|
416
|
+
|
|
417
|
+
@property
|
|
418
|
+
def confidence(self) -> list["BoltzConfidence"]:
|
|
419
|
+
"""
|
|
420
|
+
Retrieve the confidences of the structure prediction.
|
|
421
|
+
|
|
422
|
+
Note
|
|
423
|
+
----
|
|
424
|
+
This is only currently supported for Boltz models.
|
|
425
|
+
|
|
426
|
+
Returns
|
|
427
|
+
-------
|
|
428
|
+
list[BoltzConfidence]
|
|
429
|
+
List of BoltzConfidence objects.
|
|
430
|
+
|
|
431
|
+
Raises
|
|
432
|
+
------
|
|
433
|
+
AttributeError
|
|
434
|
+
If confidence is not supported for the model.
|
|
435
|
+
"""
|
|
436
|
+
if self.model_id not in {"boltz-1", "boltz-1x", "boltz-2"}:
|
|
437
|
+
raise AttributeError("confidence not supported for non-Boltz model")
|
|
438
|
+
if self._confidence is None:
|
|
439
|
+
confidence = api.fold_get_complex_extra_result(
|
|
440
|
+
session=self.session, job_id=self.job.job_id, key="confidence"
|
|
441
|
+
)
|
|
442
|
+
assert isinstance(confidence, list)
|
|
443
|
+
self._confidence = TypeAdapter(list[BoltzConfidence]).validate_python(
|
|
444
|
+
confidence
|
|
445
|
+
)
|
|
446
|
+
return self._confidence
|
|
447
|
+
|
|
448
|
+
@property
|
|
449
|
+
def affinity(self) -> "BoltzAffinity":
|
|
450
|
+
"""
|
|
451
|
+
Retrieve the predicted binding affinities.
|
|
452
|
+
|
|
453
|
+
Note
|
|
454
|
+
----
|
|
455
|
+
This is only currently supported for Boltz models.
|
|
456
|
+
|
|
457
|
+
Returns
|
|
458
|
+
-------
|
|
459
|
+
BoltzAffinity
|
|
460
|
+
BoltzAffinity object containing the predicted affinities.
|
|
461
|
+
|
|
462
|
+
Raises
|
|
463
|
+
------
|
|
464
|
+
AttributeError
|
|
465
|
+
If affinity is not supported for the model.
|
|
466
|
+
"""
|
|
467
|
+
if self.model_id not in {"boltz-1", "boltz-1x", "boltz-2"}:
|
|
468
|
+
raise AttributeError("affinity not supported for non-Boltz model")
|
|
469
|
+
if self._affinity is None:
|
|
470
|
+
affinity = api.fold_get_complex_extra_result(
|
|
471
|
+
session=self.session, job_id=self.job.job_id, key="affinity"
|
|
472
|
+
)
|
|
473
|
+
assert isinstance(affinity, dict)
|
|
474
|
+
self._affinity = BoltzAffinity.parse_obj_with_models(affinity)
|
|
475
|
+
return self._affinity
|
|
476
|
+
|
|
477
|
+
@property
|
|
478
|
+
def id(self):
|
|
479
|
+
"""
|
|
480
|
+
Get the ID of the fold request.
|
|
481
|
+
|
|
482
|
+
Returns
|
|
483
|
+
-------
|
|
484
|
+
str
|
|
485
|
+
Fold job ID.
|
|
486
|
+
"""
|
|
487
|
+
return self.job.job_id
|
|
488
|
+
|
|
489
|
+
def get(self, format: Literal["pdb", "mmcif"] = "mmcif", verbose=False) -> bytes:
|
|
490
|
+
"""
|
|
491
|
+
Retrieve the fold results as a single bytestring.
|
|
492
|
+
|
|
493
|
+
Defaults to mmCIF for complexes. Additional predicted properties like plddt and pae should be accessed from their respective properties, i.e. `.plddt` and `.pae`.
|
|
494
|
+
|
|
495
|
+
Parameters
|
|
496
|
+
----------
|
|
497
|
+
format : {'pdb', 'mmcif'}, optional
|
|
498
|
+
Output format. Default is 'mmcif'.
|
|
499
|
+
verbose : bool, optional
|
|
500
|
+
If True, print verbose output. Default is False.
|
|
501
|
+
|
|
502
|
+
Returns
|
|
503
|
+
-------
|
|
504
|
+
bytes
|
|
505
|
+
Fold result as a bytestring.
|
|
506
|
+
"""
|
|
507
|
+
return api.fold_get_complex_result(
|
|
508
|
+
session=self.session, job_id=self.id, format=format
|
|
509
|
+
)
|