99from openprotein import config
1010from openprotein .base import APISession
1111from openprotein .chains import DNA , RNA , Ligand
12- from openprotein .jobs import Future , MappedFuture
12+ from openprotein .jobs import Future , JobsAPI , MappedFuture
1313from openprotein .protein import Protein
1414
1515from . import api
16- from .schemas import FoldJob
16+ from .schemas import FoldJob , FoldMetadata
1717
1818if 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