rowan-python 3.1.1__py3-none-any.whl → 3.1.3__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 +1 -0
- rowan/molecule.py +13 -2
- rowan/workflows/rbfe_graph.py +32 -8
- rowan/workflows/relative_binding_free_energy_perturbation.py +11 -1
- {rowan_python-3.1.1.dist-info → rowan_python-3.1.3.dist-info}/METADATA +2 -2
- {rowan_python-3.1.1.dist-info → rowan_python-3.1.3.dist-info}/RECORD +8 -8
- {rowan_python-3.1.1.dist-info → rowan_python-3.1.3.dist-info}/WHEEL +0 -0
- {rowan_python-3.1.1.dist-info → rowan_python-3.1.3.dist-info}/licenses/LICENSE +0 -0
rowan/__init__.py
CHANGED
|
@@ -24,6 +24,7 @@ from stjames import (
|
|
|
24
24
|
SolventSettings,
|
|
25
25
|
Task,
|
|
26
26
|
)
|
|
27
|
+
from stjames.workflows.relative_binding_free_energy_perturbation import RBFEGraph, RBFEGraphEdge
|
|
27
28
|
from stjames.excited_state_settings import TDDFTSettings
|
|
28
29
|
from stjames.pbc_dft_settings import PBCDFTSmearing
|
|
29
30
|
from stjames.engine_compatibility import (
|
rowan/molecule.py
CHANGED
|
@@ -280,7 +280,8 @@ def load_named_ligands(path: Path | str) -> dict[str, Molecule]:
|
|
|
280
280
|
Molecule names are read from the title field of each record. Use this when
|
|
281
281
|
ligand identity needs to be preserved - for example, building a ligand dict
|
|
282
282
|
for an RBFE workflow where names are used as keys throughout submission and
|
|
283
|
-
results.
|
|
283
|
+
results. Every record must therefore have a unique name; duplicates raise
|
|
284
|
+
rather than silently collapsing into one ligand.
|
|
284
285
|
|
|
285
286
|
Supported formats (all carry per-molecule name fields):
|
|
286
287
|
- SDF / MOL (``.sdf``, ``.mol``) - name from the title line
|
|
@@ -288,7 +289,8 @@ def load_named_ligands(path: Path | str) -> dict[str, Molecule]:
|
|
|
288
289
|
|
|
289
290
|
:param path: Path to an SDF, MOL, or MOL2 file.
|
|
290
291
|
:returns: Dict mapping ligand name to Molecule, in file order.
|
|
291
|
-
:raises ValueError: If no valid molecules are found
|
|
292
|
+
:raises ValueError: If no valid molecules are found, the format is
|
|
293
|
+
unsupported, or two records share a name.
|
|
292
294
|
"""
|
|
293
295
|
path = Path(path)
|
|
294
296
|
suffix = path.suffix.lower()
|
|
@@ -311,4 +313,13 @@ def load_named_ligands(path: Path | str) -> dict[str, Molecule]:
|
|
|
311
313
|
if not pairs:
|
|
312
314
|
raise ValueError(f"No valid molecules found in {path}")
|
|
313
315
|
|
|
316
|
+
# require every record to have a unique name rather than dropping data
|
|
317
|
+
names = [name for name, _ in pairs]
|
|
318
|
+
duplicates = sorted({name for name in names if names.count(name) > 1})
|
|
319
|
+
if duplicates:
|
|
320
|
+
raise ValueError(
|
|
321
|
+
f"Ligand names must be unique, but {path} repeats: {', '.join(duplicates)}. "
|
|
322
|
+
"Rename the duplicate records before loading."
|
|
323
|
+
)
|
|
324
|
+
|
|
314
325
|
return {name: Molecule(_stjames=stjames.Molecule.from_rdkit(rdkm)) for name, rdkm in pairs}
|
rowan/workflows/rbfe_graph.py
CHANGED
|
@@ -4,6 +4,7 @@ from dataclasses import dataclass
|
|
|
4
4
|
from typing import Literal
|
|
5
5
|
|
|
6
6
|
import stjames
|
|
7
|
+
from stjames.workflows.relative_binding_free_energy_perturbation import RBFEGraph
|
|
7
8
|
|
|
8
9
|
from ..folder import Folder
|
|
9
10
|
from ..molecule import Molecule
|
|
@@ -57,13 +58,9 @@ class RelativeBindingFreeEnergyGraphResult(WorkflowResult):
|
|
|
57
58
|
return {k: Molecule.from_stjames(v) for k, v in self._workflow.ligands.items()}
|
|
58
59
|
|
|
59
60
|
@property
|
|
60
|
-
def graph(self) ->
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
Pass directly to ``submit_rbfe_perturbation_workflow(graph=...)``.
|
|
65
|
-
"""
|
|
66
|
-
return g.model_dump(mode="json") if (g := self._workflow.graph) else None
|
|
61
|
+
def graph(self) -> RBFEGraph | None:
|
|
62
|
+
"""The constructed RBFE graph, or None if not yet computed."""
|
|
63
|
+
return self._workflow.graph
|
|
67
64
|
|
|
68
65
|
@property
|
|
69
66
|
def edges(self) -> list[RelativeBindingFreeEnergyGraphEdge]:
|
|
@@ -99,6 +96,7 @@ def submit_relative_binding_free_energy_graph_workflow(
|
|
|
99
96
|
greedy_scoring: Literal["best", "jaccard", "dummy_atoms"] = "best",
|
|
100
97
|
greedy_k_min_cut: int = 3,
|
|
101
98
|
refine_cutoff: float | None = None,
|
|
99
|
+
seed_graph: RBFEGraph | None = None,
|
|
102
100
|
name: str = "RBFE Graph",
|
|
103
101
|
folder_uuid: str | None = None,
|
|
104
102
|
folder: Folder | None = None,
|
|
@@ -119,6 +117,9 @@ def submit_relative_binding_free_energy_graph_workflow(
|
|
|
119
117
|
``"best"``, ``"jaccard"``, or ``"dummy_atoms"``.
|
|
120
118
|
:param greedy_k_min_cut: Target edge-connectivity for greedy augmentation. Must be > 0.
|
|
121
119
|
:param refine_cutoff: Optional MCS similarity cutoff for graph refinement.
|
|
120
|
+
:param seed_graph: RBFE graph from a prior run to extend, as returned by a
|
|
121
|
+
completed result's ``graph``. Its existing edges (and any computed results)
|
|
122
|
+
are preserved, and only edges for newly added ligands are built.
|
|
122
123
|
:param name: Name of the workflow.
|
|
123
124
|
:param folder_uuid: UUID of the folder to place the workflow in.
|
|
124
125
|
:param folder: Folder object to store the workflow in.
|
|
@@ -126,7 +127,8 @@ def submit_relative_binding_free_energy_graph_workflow(
|
|
|
126
127
|
:param webhook_url: URL that Rowan will POST to when the workflow completes.
|
|
127
128
|
:param is_draft: If True, submit the workflow as a draft without starting execution.
|
|
128
129
|
:returns: Workflow object representing the submitted workflow.
|
|
129
|
-
:raises ValueError: If both folder and folder_uuid are provided
|
|
130
|
+
:raises ValueError: If both folder and folder_uuid are provided, if any ligand has
|
|
131
|
+
no defined charge, or if the ligands do not all share the same formal charge.
|
|
130
132
|
:raises requests.HTTPError: if the request to the API fails.
|
|
131
133
|
"""
|
|
132
134
|
if folder and folder_uuid:
|
|
@@ -138,6 +140,27 @@ def submit_relative_binding_free_energy_graph_workflow(
|
|
|
138
140
|
require_coordinates(ligand)
|
|
139
141
|
ligands_dict = {k: molecule_to_dict(v) for k, v in ligands.items()}
|
|
140
142
|
|
|
143
|
+
charges = {name: mol.get("charge") for name, mol in ligands_dict.items()}
|
|
144
|
+
missing_charge = sorted(name for name, charge in charges.items() if charge is None)
|
|
145
|
+
if missing_charge:
|
|
146
|
+
raise ValueError(
|
|
147
|
+
"Cannot verify charge consistency: no charge found for ligand(s) "
|
|
148
|
+
f"{', '.join(missing_charge)}. Provide ligands with a defined formal charge."
|
|
149
|
+
)
|
|
150
|
+
distinct_charges = {charge for charge in charges.values() if charge is not None}
|
|
151
|
+
if len(distinct_charges) > 1:
|
|
152
|
+
groups = {
|
|
153
|
+
charge: sorted(name for name, c in charges.items() if c == charge)
|
|
154
|
+
for charge in sorted(distinct_charges)
|
|
155
|
+
}
|
|
156
|
+
summary = "; ".join(
|
|
157
|
+
f"charge {charge}: {', '.join(names)}" for charge, names in groups.items()
|
|
158
|
+
)
|
|
159
|
+
raise ValueError(
|
|
160
|
+
"All RBFE ligands must share the same formal charge - charge-changing "
|
|
161
|
+
f"perturbations are not supported. Found multiple charge states ({summary})."
|
|
162
|
+
)
|
|
163
|
+
|
|
141
164
|
workflow = stjames.RBFEGraphWorkflow(
|
|
142
165
|
ligands=ligands_dict,
|
|
143
166
|
mode=mode,
|
|
@@ -145,6 +168,7 @@ def submit_relative_binding_free_energy_graph_workflow(
|
|
|
145
168
|
greedy_scoring=greedy_scoring,
|
|
146
169
|
greedy_k_min_cut=greedy_k_min_cut,
|
|
147
170
|
refine_cutoff=refine_cutoff,
|
|
171
|
+
seed_graph=seed_graph,
|
|
148
172
|
)
|
|
149
173
|
|
|
150
174
|
data = {
|
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
from typing import Literal
|
|
6
6
|
|
|
7
7
|
import stjames
|
|
8
|
-
from stjames.workflows.relative_binding_free_energy_perturbation import TMDRBFESettings
|
|
8
|
+
from stjames.workflows.relative_binding_free_energy_perturbation import RBFEGraph, TMDRBFESettings
|
|
9
9
|
|
|
10
10
|
from ..folder import Folder
|
|
11
11
|
from ..molecule import Molecule
|
|
@@ -86,6 +86,16 @@ class RelativeBindingFreeEnergyPerturbationResult(WorkflowResult):
|
|
|
86
86
|
"""Ligand molecules keyed by identifier."""
|
|
87
87
|
return {k: Molecule.from_stjames(v) for k, v in self._workflow.ligands.items()}
|
|
88
88
|
|
|
89
|
+
@property
|
|
90
|
+
def protein(self) -> Protein:
|
|
91
|
+
"""Prepared protein structure used as the simulation target."""
|
|
92
|
+
return Protein(uuid=str(self._workflow.protein))
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def graph(self) -> RBFEGraph | None:
|
|
96
|
+
"""The RBFE graph with per-edge results, or None if not constructed."""
|
|
97
|
+
return self._workflow.graph
|
|
98
|
+
|
|
89
99
|
@property
|
|
90
100
|
def edges(self) -> list[RelativeBindingFreeEnergyGraphEdge]:
|
|
91
101
|
"""Graph edges with per-edge FEP results."""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rowan-python
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.3
|
|
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
|
|
@@ -11,7 +11,7 @@ Requires-Dist: httpx
|
|
|
11
11
|
Requires-Dist: nest-asyncio
|
|
12
12
|
Requires-Dist: rdkit
|
|
13
13
|
Requires-Dist: setuptools
|
|
14
|
-
Requires-Dist: stjames>=0.0.
|
|
14
|
+
Requires-Dist: stjames>=0.0.208
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
|
|
17
17
|
# Rowan Python Library
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
rowan/__init__.py,sha256=
|
|
1
|
+
rowan/__init__.py,sha256=UhyjCkQh7YDTtemmetfelGD1d36WSJ6oaWct7CP2eyQ,1331
|
|
2
2
|
rowan/api_keys.py,sha256=TvG5l5MmQ3Qt8Z3Y7jCA_lcrwEHuI7xHy-KLbIdQ8_A,4793
|
|
3
3
|
rowan/calculation.py,sha256=lZZ52DxPsuJWCTzFZXjhauHK6dV0KCUwzoxtmoxSY48,3442
|
|
4
4
|
rowan/config.py,sha256=TejQKSxnzNKKTNL9-2bCLq6RvAh54oVA5Ivl1p_ZT8Q,20899
|
|
5
5
|
rowan/constants.py,sha256=emCH4m9OL2Hm5E-6mJGM_FgzrK_JrZT-FiKJ6pMNQ4Y,84
|
|
6
6
|
rowan/folder.py,sha256=eyKdZjHR-LsNK0yS8iedb0vPi3OB10gluuA1-Ee_JCg,9202
|
|
7
|
-
rowan/molecule.py,sha256=
|
|
7
|
+
rowan/molecule.py,sha256=LyneBgSbNS7ByQ2sI8hcRLOXwljZMZQtALgAYcqX2tM,10844
|
|
8
8
|
rowan/project.py,sha256=RtxYE9jv3Yz6fH5I56iDGRG5EbwlOHiSK-HF1uxc0d4,4582
|
|
9
9
|
rowan/protein.py,sha256=hfDqk_LgU8o39Zg2kHHWf8EqPcQOnT3Mo43Ik1gAO68,14856
|
|
10
10
|
rowan/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -40,16 +40,16 @@ rowan/workflows/pose_analysis_md.py,sha256=XJIfvn-H7GA6lVtw9uKjlgznVSSsr9bJiDt_P
|
|
|
40
40
|
rowan/workflows/protein_binder_design.py,sha256=pgywTQDuXHplZYka-61_S6CC4WTPDCwJrbupp825eC4,9281
|
|
41
41
|
rowan/workflows/protein_cofolding.py,sha256=CV13VUHC0NLDDaS1-GGTQ3RySkzEE30xzu1_4oPu6lo,16239
|
|
42
42
|
rowan/workflows/protein_md.py,sha256=41S-GIHP91ahW5mIVxjAkpZbxept98IgausM5JoeckA,9276
|
|
43
|
-
rowan/workflows/rbfe_graph.py,sha256=
|
|
43
|
+
rowan/workflows/rbfe_graph.py,sha256=7UJA3ZBbvtaB9l1KQi9279Pc89moVnBHO-XJpxEr5uQ,7238
|
|
44
44
|
rowan/workflows/redox_potential.py,sha256=bBeT1K9XGVpjCFZeeuv7Vtr3EYHN2okJ4LqYc3gMV04,5427
|
|
45
|
-
rowan/workflows/relative_binding_free_energy_perturbation.py,sha256=
|
|
45
|
+
rowan/workflows/relative_binding_free_energy_perturbation.py,sha256=vi5Qj5aDAERtjcHDsgzI6vRV_BZJnJ8boOj5aG6GXzo,13817
|
|
46
46
|
rowan/workflows/scan.py,sha256=R5Y6Md3ohPoFVJ4NYvx3_k3JNwMnVw1CDsNPD9S8sr4,7518
|
|
47
47
|
rowan/workflows/solubility.py,sha256=ulZwdG8JRl0RCwWPatYUZGMhlAZeb6wqjVbvzQYFKmE,8555
|
|
48
48
|
rowan/workflows/solvent_dependent_conformers.py,sha256=Z2xESmcM8WcTsR2TSTUa--RrhrQ-5ri_WagD9wJeVwc,6812
|
|
49
49
|
rowan/workflows/spin_states.py,sha256=rjkgie2-XVNIN7O6P93yn6EPv9Ogjy8iTj3ufZIsUgY,9331
|
|
50
50
|
rowan/workflows/strain.py,sha256=kCW_BlX__sdQG1JVbFZuB-57rkpnxa_JCw3h4uKdGDk,6425
|
|
51
51
|
rowan/workflows/tautomer_search.py,sha256=mbRl0ZJ7wibueRF8c8_idhXJ1rtwg7LBt--5QwQ_Cck,5767
|
|
52
|
-
rowan_python-3.1.
|
|
53
|
-
rowan_python-3.1.
|
|
54
|
-
rowan_python-3.1.
|
|
55
|
-
rowan_python-3.1.
|
|
52
|
+
rowan_python-3.1.3.dist-info/METADATA,sha256=mv9y4fxN9Ds7WCnd2W-vZL-LdLCNkp_1XxWipE5Q2Yg,2052
|
|
53
|
+
rowan_python-3.1.3.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
54
|
+
rowan_python-3.1.3.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
|
|
55
|
+
rowan_python-3.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|