rowan-python 3.0.6__py3-none-any.whl → 3.0.7__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.
@@ -84,6 +84,7 @@ from .multistage_optimization import (
84
84
  )
85
85
  from .nmr import NMRPeak, NMRResult, submit_nmr_workflow
86
86
  from .pka import pKaMicrostate, pKaResult, submit_pka_workflow
87
+ from .pocket_detection import Pocket, PocketDetectionResult, submit_pocket_detection_workflow
87
88
  from .pose_analysis_md import PoseAnalysisMDResult, submit_pose_analysis_md_workflow
88
89
  from .protein_binder_design import (
89
90
  ProteinBinder,
@@ -3,6 +3,7 @@
3
3
  from dataclasses import dataclass
4
4
 
5
5
  import stjames
6
+ from stjames import ENGINE_METHODS, Engine, Method
6
7
 
7
8
  from ..folder import Folder
8
9
  from ..types import MoleculeInput
@@ -155,6 +156,7 @@ def submit_electronic_properties_workflow(
155
156
  :param webhook_url: URL that Rowan will POST to when the workflow completes.
156
157
  :param is_draft: If True, submit the workflow as a draft without starting execution.
157
158
  :returns: Workflow object representing the submitted workflow.
159
+ :raises ValueError: If the method is not supported by the psi4 engine.
158
160
  :raises requests.HTTPError: if the request to the API fails.
159
161
  """
160
162
  if folder and folder_uuid:
@@ -164,7 +166,15 @@ def submit_electronic_properties_workflow(
164
166
  initial_molecule = molecule_to_dict(initial_molecule)
165
167
 
166
168
  if isinstance(method, str):
167
- method = stjames.Method(method)
169
+ method = Method(method)
170
+
171
+ supported_methods = ENGINE_METHODS[Engine.PSI4]
172
+ if method not in supported_methods:
173
+ supported_names = sorted(m.value for m in supported_methods)
174
+ raise ValueError(
175
+ f"Method '{method.value}' is not supported by the psi4 engine. "
176
+ f"Supported methods: {', '.join(supported_names)}"
177
+ )
168
178
 
169
179
  settings = stjames.Settings(method=method, basis_set=basis_set)
170
180
 
rowan/workflows/pka.py CHANGED
@@ -188,7 +188,16 @@ def submit_pka_workflow(
188
188
  if method in _PKA_WATER_ONLY_METHODS and solvent != "water":
189
189
  raise ValueError(f"{method} only supports water as solvent.")
190
190
 
191
- protonate_elements = protonate_elements or [7]
191
+ if method == "chemprop_nevolianis2025" and protonate_elements:
192
+ raise ValueError(
193
+ "chemprop_nevolianis2025 was only trained on deprotonation data; "
194
+ "protonation is disabled. Leave `protonate_elements` unset or pass []."
195
+ )
196
+
197
+ if method == "chemprop_nevolianis2025":
198
+ protonate_elements = []
199
+ else:
200
+ protonate_elements = protonate_elements or [7]
192
201
  deprotonate_elements = deprotonate_elements or [7, 8, 16]
193
202
 
194
203
  workflow = stjames.pKaWorkflow(
@@ -0,0 +1,112 @@
1
+ """Pocket detection workflow - detect potential binding sites on a protein."""
2
+
3
+ from dataclasses import dataclass
4
+
5
+ import stjames
6
+
7
+ from ..folder import Folder
8
+ from ..protein import Protein
9
+ from ..utils import api_client
10
+ from .base import Workflow, WorkflowResult, register_result
11
+
12
+
13
+ @dataclass(frozen=True, slots=True)
14
+ class Pocket:
15
+ """
16
+ A detected binding pocket.
17
+
18
+ :param sphere_centers: centers of detected spheres, in Å
19
+ :param sphere_radii: radii of detected spheres, in Å
20
+ :param volume: pocket volume, in ų
21
+ :param score: druggability/quality score; larger is better
22
+ :param pocket_center: center of axis-aligned bounding box, in Å
23
+ :param pocket_sides: side lengths of axis-aligned bounding box, in Å
24
+ :param residue_numbers: residue numbers lining the pocket
25
+ """
26
+
27
+ sphere_centers: tuple[tuple[float, float, float], ...]
28
+ sphere_radii: tuple[float, ...]
29
+ volume: float
30
+ score: float
31
+ pocket_center: tuple[float, float, float]
32
+ pocket_sides: tuple[float, float, float]
33
+ residue_numbers: tuple[int, ...]
34
+
35
+
36
+ @register_result("pocket_detection")
37
+ class PocketDetectionResult(WorkflowResult):
38
+ """Result from a pocket-detection workflow."""
39
+
40
+ _stjames_class = stjames.PocketDetectionWorkflow
41
+
42
+ def __repr__(self) -> str:
43
+ return f"<PocketDetectionResult pockets={len(self.pockets)}>"
44
+
45
+ @property
46
+ def pockets(self) -> list[Pocket]:
47
+ """Detected pockets, in the order returned by the backend."""
48
+ raw = getattr(self._workflow, "pockets", []) or []
49
+ return [
50
+ Pocket(
51
+ sphere_centers=tuple(tuple(c) for c in p.sphere_centers),
52
+ sphere_radii=tuple(p.sphere_radii),
53
+ volume=p.volume,
54
+ score=p.score,
55
+ pocket_center=tuple(p.pocket_center),
56
+ pocket_sides=tuple(p.pocket_sides),
57
+ residue_numbers=tuple(p.residue_numbers),
58
+ )
59
+ for p in raw
60
+ ]
61
+
62
+
63
+ def submit_pocket_detection_workflow(
64
+ protein: str | Protein,
65
+ merge_distance: float = 1.75,
66
+ name: str = "Pocket Detection Workflow",
67
+ folder_uuid: str | None = None,
68
+ folder: Folder | None = None,
69
+ max_credits: int | None = None,
70
+ webhook_url: str | None = None,
71
+ is_draft: bool = False,
72
+ ) -> Workflow:
73
+ """
74
+ Submits a pocket-detection workflow to the API.
75
+
76
+ :param protein: protein to analyze. Can be a UUID or a Protein object.
77
+ :param merge_distance: distance for merging pocket spheres, in Å
78
+ :param name: name of the workflow
79
+ :param folder_uuid: UUID of the folder to place the workflow in
80
+ :param folder: Folder object to store the workflow in
81
+ :param max_credits: maximum number of credits to use for the workflow
82
+ :param webhook_url: URL that Rowan will POST to when the workflow completes
83
+ :param is_draft: if True, submit the workflow as a draft without starting execution
84
+ :returns: Workflow object representing the submitted workflow
85
+ :raises requests.HTTPError: if the request to the API fails
86
+ """
87
+ if folder and folder_uuid:
88
+ raise ValueError("Provide either `folder` or `folder_uuid`, not both.")
89
+ if folder:
90
+ folder_uuid = folder.uuid
91
+ if isinstance(protein, Protein):
92
+ protein = protein.uuid
93
+
94
+ workflow = stjames.PocketDetectionWorkflow(
95
+ protein=protein,
96
+ merge_distance=merge_distance,
97
+ )
98
+
99
+ data = {
100
+ "workflow_type": "pocket_detection",
101
+ "workflow_data": workflow.model_dump(mode="json"),
102
+ "name": name,
103
+ "folder_uuid": folder_uuid,
104
+ "max_credits": max_credits,
105
+ "webhook_url": webhook_url,
106
+ "is_draft": is_draft,
107
+ }
108
+
109
+ with api_client() as client:
110
+ response = client.post("/workflow", json=data)
111
+ response.raise_for_status()
112
+ return Workflow(**response.json())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rowan-python
3
- Version: 3.0.6
3
+ Version: 3.0.7
4
4
  Summary: Rowan Python Library
5
5
  Project-URL: Homepage, https://github.com/rowansci/rowan-client
6
6
  Project-URL: Bug Tracker, https://github.com/rowansci/rowan-client/issues
@@ -12,7 +12,7 @@ rowan/user.py,sha256=Tnwz1-u_92ACt1xATQegtMj3FcosFsAG4m-4YuAkiyg,5955
12
12
  rowan/utils.py,sha256=c1s6Ze-OqLtfvrD23OV60otskejmj-CD88nNf8_nFcw,3636
13
13
  rowan/rowan_rdkit/__init__.py,sha256=EATX2VRzywzKxqkpCUMTf7RNQLkWsfi5VcCNDW6EIiw,503
14
14
  rowan/rowan_rdkit/chem_utils.py,sha256=ZWdLziT59Qr5JzjvV789CAyRq0m5JIawsOP4RxUbQQA,35529
15
- rowan/workflows/__init__.py,sha256=o2fN6V10mWt82QPr1UlbkyHzc2vtoIbkoiFZF2PgYow,4257
15
+ rowan/workflows/__init__.py,sha256=UTkqcsqtANh9TtaYXwOSYmTOvzR9ucQ_xhDupAFHROI,4351
16
16
  rowan/workflows/admet.py,sha256=0_wIwXXLfHF-3kgGx_1EM1ljjaYHLeEijJ-GbMYxpL8,2904
17
17
  rowan/workflows/analogue_docking.py,sha256=LJpbbaug0tZ9Cg-m0b7EgGH5hJ5894fHOC16Wefx7mE,9206
18
18
  rowan/workflows/base.py,sha256=eLGyzTc9NpXBGC-FRjsaUwKP6RluWrz0ipDZ4jDY_jc,30103
@@ -24,7 +24,7 @@ rowan/workflows/constants.py,sha256=el8jWE9gnGTLNWn5_n_V0H362vIRneOqgy7BOQ8CScg,
24
24
  rowan/workflows/descriptors.py,sha256=rGrNca6kA4SzX5BAOjP6rE91MOLTvCWSYKF_LW2Z0y4,2963
25
25
  rowan/workflows/docking.py,sha256=wmE7QJu1uDHBDynTT1XesXXAZtpB6xLjZUKsHOQyCcU,7386
26
26
  rowan/workflows/double_ended_ts_search.py,sha256=abBblMkshhbzq5UTwIf-ovNFxY8Ltp2O-bGu_plkI58,7806
27
- rowan/workflows/electronic_properties.py,sha256=AVVtpIIO82GRETHbemCLI8tqM7QHmr7XrGbrQ_YB5w4,7108
27
+ rowan/workflows/electronic_properties.py,sha256=2L0BUvhx0iT0k4gQf7hbceCpatznT2xui7rs6lpME7k,7564
28
28
  rowan/workflows/fukui.py,sha256=wLimH3QmorSpvkovRPlI91VuxHG4J91F2EcLYqg3eP0,5112
29
29
  rowan/workflows/hydrogen_bond_donor_acceptor_strength.py,sha256=WWiEK_GlumIEgTTOaqw-Y5gPDkRkaePWcIjTdIocrPc,4916
30
30
  rowan/workflows/interaction_energy_decomposition.py,sha256=Kjwkb-pviFSFIIZNjMb9i8nAkdKrbjFftmG_lkYtE40,6120
@@ -35,7 +35,8 @@ rowan/workflows/membrane_permeability.py,sha256=oIDmB8qF_K_Kesv7o_FiljAk4dpptEeO
35
35
  rowan/workflows/msa.py,sha256=V3B1SyWPR8MT306hh9W-T9JTpi_E-XgAIeF9yRQZ7tI,5075
36
36
  rowan/workflows/multistage_optimization.py,sha256=HFVx8mnHxG97pDYyL6eOhNGmESqTxaKNgUdwrFpFUJ0,6456
37
37
  rowan/workflows/nmr.py,sha256=hergJdsiawKj7iV-jHxDOS03n_EnZcaCIt_ZTl34-JY,5183
38
- rowan/workflows/pka.py,sha256=Gh-rMrqZyHbpIpX2LaEiBzlqE4paIE58paSkHEQCoEU,8334
38
+ rowan/workflows/pka.py,sha256=TCFSE5HI5JLPslKdbUvJe4IxrVaLExrI_3PnDfXtxTw,8691
39
+ rowan/workflows/pocket_detection.py,sha256=aGHY0puxekp4c4nsNYHcvKCe1fsetygL04BcSvNFvE8,3864
39
40
  rowan/workflows/pose_analysis_md.py,sha256=UvotLhWv0_VAkKteZboOutDry7l-Zt1K6_SBx3EXqgM,9530
40
41
  rowan/workflows/protein_binder_design.py,sha256=J-9NSbRLdHb6JQRhY_vq43HlHCDCiQqrkOZUCAF-2dk,8604
41
42
  rowan/workflows/protein_cofolding.py,sha256=1R29XjAVjWHyelGG-mylP2GIamZbLCQKaaaFsCAnYgI,13012
@@ -49,7 +50,7 @@ rowan/workflows/solvent_dependent_conformers.py,sha256=ovvnhCE4xlkpdhccLHEq7oBJR
49
50
  rowan/workflows/spin_states.py,sha256=GZgBJPO6_ds9el4b7wbigIZ5213Z9DwXhokczJ5NDhs,7122
50
51
  rowan/workflows/strain.py,sha256=r0tlZoUlAslAiF7dPTpa9WlQFUAKyVjZ19zASjSS8Hs,6339
51
52
  rowan/workflows/tautomer_search.py,sha256=aqwXoj0ffWsb5gbvzfz_bpx5ifIfR_K07fbdWhU62Ko,5820
52
- rowan_python-3.0.6.dist-info/METADATA,sha256=8c_sKx6JPCz0nVzsM_rX7N3bBjHz8_DxM58wZSFwLcs,1600
53
- rowan_python-3.0.6.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
54
- rowan_python-3.0.6.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
55
- rowan_python-3.0.6.dist-info/RECORD,,
53
+ rowan_python-3.0.7.dist-info/METADATA,sha256=-sirW_Q74BeqsjNRR4wAWYoV8ebpuNLzc6-8FrgOKRs,1600
54
+ rowan_python-3.0.7.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
55
+ rowan_python-3.0.7.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
56
+ rowan_python-3.0.7.dist-info/RECORD,,