rowan-python 1.1.12__py3-none-any.whl → 2.0.0__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.
- rowan/__init__.py +4 -6
- rowan/folder.py +193 -71
- rowan/protein.py +196 -44
- rowan/rowan_rdkit/chem_utils.py +162 -116
- rowan/user.py +137 -0
- rowan/utils.py +15 -0
- rowan/workflow.py +957 -109
- {rowan_python-1.1.12.dist-info → rowan_python-2.0.0.dist-info}/METADATA +1 -1
- rowan_python-2.0.0.dist-info/RECORD +14 -0
- rowan/calculation.py +0 -14
- rowan/client.py +0 -55
- rowan/protein_cofolding.py +0 -36
- rowan_python-1.1.12.dist-info/RECORD +0 -16
- {rowan_python-1.1.12.dist-info → rowan_python-2.0.0.dist-info}/WHEEL +0 -0
- {rowan_python-1.1.12.dist-info → rowan_python-2.0.0.dist-info}/licenses/LICENSE +0 -0
rowan/__init__.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# ruff: noqa
|
|
2
2
|
|
|
3
3
|
from . import utils
|
|
4
|
-
from .client import compute
|
|
5
4
|
|
|
6
5
|
from . import constants
|
|
7
6
|
|
|
8
|
-
from .folder import
|
|
9
|
-
from .workflow import
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
12
|
-
from .protein_cofolding import *
|
|
7
|
+
from .folder import *
|
|
8
|
+
from .workflow import *
|
|
9
|
+
from .protein import *
|
|
10
|
+
from .user import *
|
rowan/folder.py
CHANGED
|
@@ -1,90 +1,212 @@
|
|
|
1
|
-
from
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Any, Self
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
+
from pydantic import BaseModel
|
|
4
5
|
|
|
5
6
|
from .utils import api_client
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
class Folder:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return response.json()
|
|
9
|
+
class Folder(BaseModel):
|
|
10
|
+
"""
|
|
11
|
+
A class representing a folder in the Rowan API.
|
|
12
|
+
|
|
13
|
+
:ivar uuid: The UUID of the folder.
|
|
14
|
+
:ivar name: The name of the folder.
|
|
15
|
+
:ivar parent_uuid: The UUID of the parent folder.
|
|
16
|
+
:ivar notes: Folder notes.
|
|
17
|
+
:ivar starred: Whether the folder is starred.
|
|
18
|
+
:ivar public: Whether the folder is public.
|
|
19
|
+
:ivar created_at: The date and time the folder was created.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
uuid: str
|
|
23
|
+
name: str | None = None
|
|
24
|
+
parent_uuid: str | None = None
|
|
25
|
+
notes: str = ""
|
|
26
|
+
starred: bool = False
|
|
27
|
+
public: bool = False
|
|
28
|
+
created_at: datetime | None = None
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
def __repr__(self) -> str:
|
|
31
|
+
return f"<Folder name='{self.name}' created_at='{self.created_at}' uuid='{self.uuid}'>"
|
|
32
|
+
|
|
33
|
+
def fetch_latest(self, in_place: bool = False) -> Self:
|
|
34
|
+
"""
|
|
35
|
+
Fetch the latest folder data from the API.
|
|
36
|
+
|
|
37
|
+
This method refreshes the folder object with the latest data from the API.
|
|
38
|
+
|
|
39
|
+
:param in_place: Whether to update the current instance in-place.
|
|
40
|
+
:return: The updated instance (self).
|
|
41
|
+
:raises HTTPError: If the API request fails.
|
|
42
|
+
"""
|
|
32
43
|
with api_client() as client:
|
|
33
|
-
response = client.get(f"/folder/{uuid}")
|
|
44
|
+
response = client.get(f"/folder/{self.uuid}")
|
|
34
45
|
response.raise_for_status()
|
|
35
|
-
|
|
46
|
+
data = response.json()
|
|
47
|
+
|
|
48
|
+
if not in_place:
|
|
49
|
+
return self.__class__.model_validate(data)
|
|
50
|
+
|
|
51
|
+
updated_folder = self.model_validate(data)
|
|
52
|
+
|
|
53
|
+
# Update current instance with new data using class-level model_fields
|
|
54
|
+
for field_name in self.__class__.model_fields:
|
|
55
|
+
setattr(self, field_name, getattr(updated_folder, field_name))
|
|
56
|
+
|
|
57
|
+
self.model_rebuild()
|
|
58
|
+
|
|
59
|
+
return self
|
|
36
60
|
|
|
37
|
-
@classmethod
|
|
38
61
|
def update(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
self,
|
|
63
|
+
name: str | None = None,
|
|
64
|
+
parent_uuid: str | None = None,
|
|
65
|
+
notes: str | None = None,
|
|
66
|
+
starred: bool | None = None,
|
|
67
|
+
public: bool | None = None,
|
|
68
|
+
) -> Self:
|
|
69
|
+
"""
|
|
70
|
+
Update a folder.
|
|
71
|
+
|
|
72
|
+
:param name: The new name of the folder.
|
|
73
|
+
:param parent_uuid: The UUID of the new parent folder.
|
|
74
|
+
:param notes: A description of the folder.
|
|
75
|
+
:param starred: Whether the folder is starred.
|
|
76
|
+
:param public: Whether the folder is public.
|
|
77
|
+
|
|
78
|
+
:return: The updated folder object.
|
|
79
|
+
"""
|
|
80
|
+
payload = {
|
|
81
|
+
"name": name if name is not None else self.name,
|
|
82
|
+
"parent_uuid": parent_uuid if parent_uuid is not None else self.parent_uuid,
|
|
83
|
+
"notes": notes if notes is not None else self.notes,
|
|
84
|
+
"starred": starred if starred is not None else self.starred,
|
|
85
|
+
"public": public if public is not None else self.public,
|
|
55
86
|
}
|
|
56
87
|
|
|
57
88
|
with api_client() as client:
|
|
58
|
-
response = client.post(f"/folder/{uuid}", json=
|
|
89
|
+
response = client.post(f"/folder/{self.uuid}", json=payload)
|
|
59
90
|
response.raise_for_status()
|
|
60
|
-
|
|
91
|
+
updated_data = response.json()
|
|
61
92
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
93
|
+
self.name = updated_data.get("name")
|
|
94
|
+
self.parent_uuid = updated_data.get("parent_uuid")
|
|
95
|
+
self.notes = updated_data.get("notes")
|
|
96
|
+
self.starred = updated_data.get("starred")
|
|
97
|
+
self.public = updated_data.get("public")
|
|
98
|
+
return self
|
|
67
99
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
parent_uuid: Optional[stjames.UUID] = None,
|
|
72
|
-
name_contains: Optional[str] = None,
|
|
73
|
-
public: Optional[bool] = None,
|
|
74
|
-
starred: Optional[bool] = None,
|
|
75
|
-
page: int = 0,
|
|
76
|
-
size: int = 10,
|
|
77
|
-
) -> dict[str, Any]:
|
|
78
|
-
params = {
|
|
79
|
-
"page": page,
|
|
80
|
-
"size": size,
|
|
81
|
-
"parent_uuid": parent_uuid,
|
|
82
|
-
"name_contains": name_contains,
|
|
83
|
-
"public": public,
|
|
84
|
-
"starred": starred,
|
|
85
|
-
}
|
|
100
|
+
def delete(self) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Delete the folder and all its contents.
|
|
86
103
|
|
|
104
|
+
This is a destructive action, it will delete all the folders and
|
|
105
|
+
workflows that are inside this folder.
|
|
106
|
+
|
|
107
|
+
:raises requests.HTTPError: if the request to the API fails.
|
|
108
|
+
"""
|
|
87
109
|
with api_client() as client:
|
|
88
|
-
response = client.
|
|
110
|
+
response = client.delete(f"/folder/{self.uuid}")
|
|
89
111
|
response.raise_for_status()
|
|
90
|
-
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def retrieve_folder(uuid: str) -> Folder:
|
|
115
|
+
"""
|
|
116
|
+
Retrieves a folder from the API by UUID. Folder UUID can be found in the folder's URL.
|
|
117
|
+
|
|
118
|
+
:param uuid: The UUID of the folder to retrieve.
|
|
119
|
+
:return: A Folder object representing the retrieved folder.
|
|
120
|
+
:raises HTTPError: If the API request fails.
|
|
121
|
+
"""
|
|
122
|
+
with api_client() as client:
|
|
123
|
+
response = client.get(f"/folder/{uuid}")
|
|
124
|
+
response.raise_for_status()
|
|
125
|
+
return Folder(**response.json())
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def home_folder() -> Folder:
|
|
129
|
+
"""
|
|
130
|
+
Retrieves the home folder from the API.
|
|
131
|
+
|
|
132
|
+
:return: A Folder object representing the home folder.
|
|
133
|
+
:raises HTTPError: If the API request fails.
|
|
134
|
+
"""
|
|
135
|
+
with api_client() as client:
|
|
136
|
+
response = client.get("/user/me/root_folders")
|
|
137
|
+
response.raise_for_status()
|
|
138
|
+
return Folder(**response.json()["user_root"])
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def list_folders(
|
|
142
|
+
parent_uuid: str | None = None,
|
|
143
|
+
name_contains: str | None = None,
|
|
144
|
+
public: bool | None = None,
|
|
145
|
+
starred: bool | None = None,
|
|
146
|
+
page: int = 0,
|
|
147
|
+
size: int = 10,
|
|
148
|
+
) -> list[Folder]:
|
|
149
|
+
"""
|
|
150
|
+
Retrieve a list of folders based on the specified criteria.
|
|
151
|
+
|
|
152
|
+
:param parent_uuid: UUID of the parent folder to filter by.
|
|
153
|
+
:param name_contains: Substring to search for in folder names.
|
|
154
|
+
:param public: Filter folders by their public status.
|
|
155
|
+
:param starred: Filter folders by their starred status.
|
|
156
|
+
:param page: Pagination parameter to specify the page number.
|
|
157
|
+
:param size: Pagination parameter to specify the number of items per page.
|
|
158
|
+
:return: A list of Folder objects that match the search criteria.
|
|
159
|
+
:raises requests.HTTPError: if the request to the API fails.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
params: dict[str, Any] = {
|
|
163
|
+
"page": page,
|
|
164
|
+
"size": size,
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if parent_uuid is not None:
|
|
168
|
+
params["parent_uuid"] = parent_uuid
|
|
169
|
+
if name_contains is not None:
|
|
170
|
+
params["name_contains"] = name_contains
|
|
171
|
+
if public is not None:
|
|
172
|
+
params["public"] = public
|
|
173
|
+
if starred is not None:
|
|
174
|
+
params["starred"] = starred
|
|
175
|
+
|
|
176
|
+
with api_client() as client:
|
|
177
|
+
response = client.get("/folder", params=params)
|
|
178
|
+
response.raise_for_status()
|
|
179
|
+
items = response.json()["folders"]
|
|
180
|
+
|
|
181
|
+
return [Folder(**item) for item in items]
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def create_folder(
|
|
185
|
+
name: str,
|
|
186
|
+
parent_uuid: str | None = None,
|
|
187
|
+
notes: str = "",
|
|
188
|
+
starred: bool = False,
|
|
189
|
+
public: bool = False,
|
|
190
|
+
) -> Folder:
|
|
191
|
+
"""
|
|
192
|
+
Create a new folder.
|
|
193
|
+
|
|
194
|
+
:param name: The name of the folder.
|
|
195
|
+
:param parent_uuid: The UUID of the parent folder.
|
|
196
|
+
:param notes: A description of the folder.
|
|
197
|
+
:param starred: Whether the folder is starred.
|
|
198
|
+
:param public: Whether the folder is public.
|
|
199
|
+
:return: The newly created folder.
|
|
200
|
+
"""
|
|
201
|
+
data = {
|
|
202
|
+
"name": name,
|
|
203
|
+
"parent_uuid": parent_uuid,
|
|
204
|
+
"notes": notes,
|
|
205
|
+
"starred": starred,
|
|
206
|
+
"public": public,
|
|
207
|
+
}
|
|
208
|
+
with api_client() as client:
|
|
209
|
+
response = client.post("/folder", json=data)
|
|
210
|
+
response.raise_for_status()
|
|
211
|
+
folder_data = response.json()
|
|
212
|
+
return Folder(**folder_data)
|
rowan/protein.py
CHANGED
|
@@ -1,63 +1,215 @@
|
|
|
1
|
-
from
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, Self
|
|
2
4
|
|
|
3
|
-
import
|
|
5
|
+
from pydantic import BaseModel
|
|
4
6
|
|
|
5
7
|
from .utils import api_client
|
|
6
8
|
|
|
7
9
|
|
|
8
|
-
class Protein:
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
class Protein(BaseModel):
|
|
11
|
+
"""
|
|
12
|
+
A Rowan protein.
|
|
13
|
+
|
|
14
|
+
Data is not loaded by default to avoid unnecessary downloads that could impact performance.
|
|
15
|
+
Call `load_data()` to fetch and attach the protein data to this `Protein` object.
|
|
16
|
+
|
|
17
|
+
:ivar uuid: The UUID of the protein
|
|
18
|
+
:ivar created_at: The creation date of the protein
|
|
19
|
+
:ivar used_in_workflow: Whether the protein is used in a workflow
|
|
20
|
+
:ivar ancestor_uuid: The UUID of the ancestor protein
|
|
21
|
+
:ivar sanitized: Whether the protein is sanitized
|
|
22
|
+
:ivar name: The name of the protein
|
|
23
|
+
:ivar data: The data of the protein
|
|
24
|
+
:ivar public: Whether the protein is public
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
uuid: str
|
|
28
|
+
created_at: datetime | None = None
|
|
29
|
+
used_in_workflow: bool | None = None
|
|
30
|
+
ancestor_uuid: str | None = None
|
|
31
|
+
sanitized: int | None = None
|
|
32
|
+
name: str | None = None
|
|
33
|
+
data: dict | None = None
|
|
34
|
+
public: bool | None = None
|
|
35
|
+
pocket: list[list[float]] | None = None
|
|
36
|
+
|
|
37
|
+
def __repr__(self):
|
|
38
|
+
return f"<Protein name='{self.name}' created_at='{self.created_at}' uuid='{self.uuid}'>"
|
|
39
|
+
|
|
40
|
+
def refresh(self, in_place: bool = True) -> Self:
|
|
41
|
+
"""
|
|
42
|
+
Loads protein data
|
|
43
|
+
|
|
44
|
+
:return: protein with loaded data
|
|
45
|
+
"""
|
|
11
46
|
with api_client() as client:
|
|
12
|
-
response = client.get(f"/protein/{uuid}")
|
|
47
|
+
response = client.get(f"/protein/{self.uuid}")
|
|
13
48
|
response.raise_for_status()
|
|
14
|
-
|
|
49
|
+
protein_data = response.json()
|
|
50
|
+
if not in_place:
|
|
51
|
+
return self.__class__.model_validate(protein_data)
|
|
52
|
+
|
|
53
|
+
self.name = protein_data.get("name")
|
|
54
|
+
self.data = protein_data.get("data")
|
|
55
|
+
self.public = protein_data.get("public")
|
|
56
|
+
self.pocket = protein_data.get("pocket")
|
|
57
|
+
self.sanitized = protein_data.get("sanitized")
|
|
58
|
+
self.used_in_workflow = protein_data.get("used_in_workflow")
|
|
59
|
+
return self
|
|
15
60
|
|
|
16
|
-
@classmethod
|
|
17
61
|
def update(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
new_data = {}
|
|
28
|
-
new_data["name"] = name if name is not None else old_data["name"]
|
|
29
|
-
new_data["data"] = data if data is not None else old_data["data"]
|
|
30
|
-
new_data["public"] = public if public is not None else old_data["public"]
|
|
31
|
-
new_data["pocket"] = pocket if pocket is not None else old_data["pocket"]
|
|
62
|
+
self,
|
|
63
|
+
name: str | None = None,
|
|
64
|
+
data: dict | None = None,
|
|
65
|
+
public: bool | None = None,
|
|
66
|
+
pocket: list[list[float]] | None = None,
|
|
67
|
+
) -> Self:
|
|
68
|
+
# Use current values unless new ones are passed in
|
|
69
|
+
"""
|
|
70
|
+
Updates protein data
|
|
32
71
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
72
|
+
:param name: The new name of the protein
|
|
73
|
+
:param data: The new data of the protein
|
|
74
|
+
:param public: Whether the protein is public
|
|
75
|
+
:param pocket: The new pocket of the protein
|
|
76
|
+
:return: The updated protein object
|
|
77
|
+
"""
|
|
78
|
+
updated_payload = {
|
|
79
|
+
"name": name if name is not None else self.name,
|
|
80
|
+
"data": data if data is not None else self.data,
|
|
81
|
+
"public": public if public is not None else self.public,
|
|
82
|
+
"pocket": pocket if pocket is not None else self.pocket,
|
|
83
|
+
}
|
|
37
84
|
|
|
38
|
-
@classmethod
|
|
39
|
-
def delete(cls, uuid: stjames.UUID) -> None:
|
|
40
85
|
with api_client() as client:
|
|
41
|
-
response = client.
|
|
86
|
+
response = client.post(f"/protein/{self.uuid}", json=updated_payload)
|
|
42
87
|
response.raise_for_status()
|
|
88
|
+
updated_data = response.json()
|
|
43
89
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
size: int = 20,
|
|
51
|
-
):
|
|
52
|
-
params: dict[str, Any] = {"page": page, "size": size}
|
|
90
|
+
# Update attributes
|
|
91
|
+
self.name = updated_data.get("name")
|
|
92
|
+
self.data = updated_data.get("data")
|
|
93
|
+
self.public = updated_data.get("public")
|
|
94
|
+
self.pocket = updated_data.get("pocket")
|
|
95
|
+
return self
|
|
53
96
|
|
|
54
|
-
|
|
55
|
-
|
|
97
|
+
def delete(self) -> None:
|
|
98
|
+
"""
|
|
99
|
+
Deletes a protein
|
|
56
100
|
|
|
57
|
-
if
|
|
58
|
-
|
|
101
|
+
:raises requests.HTTPError: if the request to the API fails
|
|
102
|
+
"""
|
|
103
|
+
with api_client() as client:
|
|
104
|
+
response = client.delete(f"/protein/{self.uuid}")
|
|
105
|
+
response.raise_for_status()
|
|
59
106
|
|
|
107
|
+
def sanitize(self) -> None:
|
|
108
|
+
"""
|
|
109
|
+
Sanitizes a protein
|
|
110
|
+
|
|
111
|
+
:raises requests.HTTPError: if the request to the API fails
|
|
112
|
+
"""
|
|
60
113
|
with api_client() as client:
|
|
61
|
-
response = client.
|
|
114
|
+
response = client.post(f"/protein/sanitize/{self.uuid}")
|
|
62
115
|
response.raise_for_status()
|
|
63
|
-
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def retrieve_protein(uuid: str) -> Protein:
|
|
119
|
+
"""
|
|
120
|
+
Retrieves a protein from the API using its UUID.
|
|
121
|
+
|
|
122
|
+
:param uuid: The UUID of the protein to retrieve.
|
|
123
|
+
:return: A Protein object representing the retrieved protein.
|
|
124
|
+
:raises requests.HTTPError: if the request to the API fails.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
with api_client() as client:
|
|
128
|
+
response = client.get(f"/protein/{uuid}")
|
|
129
|
+
response.raise_for_status()
|
|
130
|
+
protein_data = response.json()
|
|
131
|
+
|
|
132
|
+
return Protein(**protein_data)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def list_proteins(
|
|
136
|
+
ancestor_uuid: str | None = None,
|
|
137
|
+
name_contains: str | None = None,
|
|
138
|
+
page: int = 0,
|
|
139
|
+
size: int = 20,
|
|
140
|
+
) -> list[Protein]:
|
|
141
|
+
"""
|
|
142
|
+
List proteins
|
|
143
|
+
|
|
144
|
+
:param ancestor_uuid: The UUID of the ancestor protein to filter by
|
|
145
|
+
:param name_contains: Substring to search for in protein names
|
|
146
|
+
:param page: The page number to retrieve
|
|
147
|
+
:param size: The number of items per page
|
|
148
|
+
:return: A list of Protein objects that match the search criteria
|
|
149
|
+
:raises requests.HTTPError: if the request to the API fails
|
|
150
|
+
"""
|
|
151
|
+
params: dict[str, Any] = {"page": page, "size": size}
|
|
152
|
+
if ancestor_uuid is not None:
|
|
153
|
+
params["ancestor_uuid"] = ancestor_uuid
|
|
154
|
+
if name_contains is not None:
|
|
155
|
+
params["name_contains"] = name_contains
|
|
156
|
+
|
|
157
|
+
with api_client() as client:
|
|
158
|
+
response = client.get("/protein", params=params)
|
|
159
|
+
response.raise_for_status()
|
|
160
|
+
results = response.json()["proteins"]
|
|
161
|
+
|
|
162
|
+
return [Protein(**item) for item in results]
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def upload_protein(name: str, file_path: Path) -> Protein:
|
|
166
|
+
"""
|
|
167
|
+
Uploads a protein from a PDB file to the API.
|
|
168
|
+
|
|
169
|
+
:param name: The name of the protein to create
|
|
170
|
+
:param file_path: The path to the PDB file to upload
|
|
171
|
+
:return: A Protein object representing the uploaded protein
|
|
172
|
+
:raises requests.HTTPError: if the request to the API fails
|
|
173
|
+
"""
|
|
174
|
+
with api_client() as client:
|
|
175
|
+
# Step 1: Read the file and post it to the conversion endpoint.
|
|
176
|
+
conversion_payload = {"name": name, "text": file_path.read_text()}
|
|
177
|
+
conversion_response = client.post("/convert/pdb_file_to_protein", json=conversion_payload)
|
|
178
|
+
conversion_response.raise_for_status() # Ensure the request was successful
|
|
179
|
+
|
|
180
|
+
# Extract the JSON data from the conversion response.
|
|
181
|
+
protein_data = conversion_response.json()
|
|
182
|
+
|
|
183
|
+
# Step 2: Use the converted data to create the final protein object.
|
|
184
|
+
creation_payload = {"name": name, "protein_data": protein_data, "ancestor_uuid": None}
|
|
185
|
+
final_response = client.post("/protein", json=creation_payload)
|
|
186
|
+
final_response.raise_for_status()
|
|
187
|
+
|
|
188
|
+
# Deserialize the final JSON response into a Protein object and return it.
|
|
189
|
+
return Protein(**final_response.json())
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def create_protein_from_pdb_id(name: str, code: str) -> Protein:
|
|
193
|
+
"""
|
|
194
|
+
Creates a protein from a PDB ID.
|
|
195
|
+
|
|
196
|
+
:param name: The name of the protein to create
|
|
197
|
+
:param code: The PDB ID of the protein to create
|
|
198
|
+
:return: A Protein object representing the created protein
|
|
199
|
+
:raises requests.HTTPError: if the request to the API fails
|
|
200
|
+
"""
|
|
201
|
+
with api_client() as client:
|
|
202
|
+
# Step 1: Read the file and post it to the conversion endpoint.
|
|
203
|
+
conversion_response = client.post(f"/convert/pdb_id_to_protein?pdb_id={code}")
|
|
204
|
+
conversion_response.raise_for_status() # Ensure the request was successful
|
|
205
|
+
|
|
206
|
+
# Extract the JSON data from the conversion response.
|
|
207
|
+
protein_data = conversion_response.json()
|
|
208
|
+
|
|
209
|
+
# Step 2: Use the converted data to create the final protein object.
|
|
210
|
+
creation_payload = {"name": name, "protein_data": protein_data, "ancestor_uuid": None}
|
|
211
|
+
final_response = client.post("/protein", json=creation_payload)
|
|
212
|
+
final_response.raise_for_status()
|
|
213
|
+
|
|
214
|
+
# Deserialize the final JSON response into a Protein object and return it.
|
|
215
|
+
return Protein(**final_response.json())
|