rowan-python 3.1.1__py3-none-any.whl → 3.1.2__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 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 (
@@ -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) -> dict | None:
61
- """
62
- The constructed RBFE perturbation graph as a dict, or None if not yet computed.
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.1
3
+ Version: 3.1.2
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.204
14
+ Requires-Dist: stjames>=0.0.208
15
15
  Description-Content-Type: text/markdown
16
16
 
17
17
  # Rowan Python Library
@@ -1,4 +1,4 @@
1
- rowan/__init__.py,sha256=tyL1rh1lEZ1u9-E5Li3z20ymEFzO032ALyrATc-6zMw,1234
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
@@ -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=LcVu3nFGZ5NTSdeojb-DeRfwEDh3gBTRkVF_jOrzVtQ,5893
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=uxC3Rr63U6GjNa9u2Hurahu48l4rYEz5RQX4hV0D250,13456
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.1.dist-info/METADATA,sha256=BJ6RevJYUsM7A5ivp7ahR7S9CUG91fcVqRJXEFP89QM,2052
53
- rowan_python-3.1.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
54
- rowan_python-3.1.1.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
55
- rowan_python-3.1.1.dist-info/RECORD,,
52
+ rowan_python-3.1.2.dist-info/METADATA,sha256=poPK5z_485P_QgH_M-RVS8GkqGUhlojTCR5BlZW-iC0,2052
53
+ rowan_python-3.1.2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
54
+ rowan_python-3.1.2.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
55
+ rowan_python-3.1.2.dist-info/RECORD,,