stjames 0.0.76__py3-none-any.whl → 0.0.78__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.
Potentially problematic release.
This version of stjames might be problematic. Click here for more details.
- stjames/atomium_stjames/pdb.py +56 -10
- stjames/molecule.py +99 -10
- stjames/workflows/hydrogen_bond_basicity.py +19 -3
- stjames/workflows/multistage_opt.py +72 -1
- stjames/workflows/protein_cofolding.py +12 -1
- stjames/workflows/workflow.py +1 -0
- {stjames-0.0.76.dist-info → stjames-0.0.78.dist-info}/METADATA +2 -1
- {stjames-0.0.76.dist-info → stjames-0.0.78.dist-info}/RECORD +11 -11
- {stjames-0.0.76.dist-info → stjames-0.0.78.dist-info}/WHEEL +1 -1
- {stjames-0.0.76.dist-info → stjames-0.0.78.dist-info}/licenses/LICENSE +0 -0
- {stjames-0.0.76.dist-info → stjames-0.0.78.dist-info}/top_level.txt +0 -0
stjames/atomium_stjames/pdb.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import re
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from itertools import chain, groupby
|
|
6
|
-
from typing import Any, Callable
|
|
6
|
+
from typing import Any, Callable, TypedDict
|
|
7
7
|
|
|
8
8
|
from .data import CODES
|
|
9
9
|
from .mmcif import add_secondary_structure_to_polymers
|
|
@@ -476,15 +476,17 @@ def add_atom_to_polymer(line: str, model: dict[Any, Any], chain_id: str, res_id:
|
|
|
476
476
|
:param str res_id: the molecule ID to add to.
|
|
477
477
|
:param dict aniso_dict: lookup dictionary for anisotropy information."""
|
|
478
478
|
|
|
479
|
+
atom = atom_line_to_dict(line, aniso_dict)
|
|
480
|
+
|
|
479
481
|
try:
|
|
480
|
-
model["polymer"][chain_id]["residues"][res_id]["atoms"][int(line[6:11])] =
|
|
482
|
+
model["polymer"][chain_id]["residues"][res_id]["atoms"][int(line[6:11])] = atom
|
|
481
483
|
except Exception:
|
|
482
484
|
name = line[17:20].strip()
|
|
483
485
|
try:
|
|
484
486
|
model["polymer"][chain_id]["residues"][res_id] = {
|
|
485
487
|
"name": name,
|
|
486
488
|
"full_name": full_names.get(name),
|
|
487
|
-
"atoms": {int(line[6:11]):
|
|
489
|
+
"atoms": {int(line[6:11]): atom},
|
|
488
490
|
"number": len(model["polymer"][chain_id]["residues"]) + 1,
|
|
489
491
|
}
|
|
490
492
|
except Exception:
|
|
@@ -495,7 +497,7 @@ def add_atom_to_polymer(line: str, model: dict[Any, Any], chain_id: str, res_id:
|
|
|
495
497
|
"residues": {
|
|
496
498
|
res_id: {
|
|
497
499
|
"name": line[17:20].strip(),
|
|
498
|
-
"atoms": {int(line[6:11]):
|
|
500
|
+
"atoms": {int(line[6:11]): atom},
|
|
499
501
|
"number": 1,
|
|
500
502
|
"full_name": None,
|
|
501
503
|
}
|
|
@@ -511,10 +513,11 @@ def add_atom_to_non_polymer(line: str, model: dict[Any, Any], res_id: str, aniso
|
|
|
511
513
|
:param dict model: the model to update.
|
|
512
514
|
:param str res_id: the molecule ID to add to.
|
|
513
515
|
:param dict aniso_dict: lookup dictionary for anisotropy information."""
|
|
516
|
+
atom = atom_line_to_dict(line, aniso_dict)
|
|
514
517
|
|
|
515
518
|
key = "water" if line[17:20] in ["HOH", "DOD"] else "non_polymer"
|
|
516
519
|
try:
|
|
517
|
-
model[key][res_id]["atoms"][int(line[6:11])] =
|
|
520
|
+
model[key][res_id]["atoms"][int(line[6:11])] = atom
|
|
518
521
|
except Exception:
|
|
519
522
|
name = line[17:20].strip()
|
|
520
523
|
model[key][res_id] = {
|
|
@@ -522,18 +525,55 @@ def add_atom_to_non_polymer(line: str, model: dict[Any, Any], res_id: str, aniso
|
|
|
522
525
|
"full_name": full_names.get(name),
|
|
523
526
|
"internal_id": line[21],
|
|
524
527
|
"polymer": line[21],
|
|
525
|
-
"atoms": {int(line[6:11]):
|
|
528
|
+
"atoms": {int(line[6:11]): atom},
|
|
526
529
|
}
|
|
527
530
|
|
|
528
531
|
|
|
529
|
-
def
|
|
530
|
-
|
|
532
|
+
def guess_element_from_name(atom_name: str) -> str | None:
|
|
533
|
+
atom_name = atom_name.strip()
|
|
534
|
+
if not atom_name:
|
|
535
|
+
return None
|
|
536
|
+
|
|
537
|
+
# Case 1: Atom name starts with a digit (e.g. '1HG1') → element is second character
|
|
538
|
+
if atom_name[0].isdigit() and len(atom_name) > 1:
|
|
539
|
+
return atom_name[1].upper()
|
|
540
|
+
|
|
541
|
+
# # Case 2: Atom name starts with a letter
|
|
542
|
+
# if len(atom_name) >= 2 and atom_name[:2].isalpha():
|
|
543
|
+
# possible = atom_name[:2].strip().capitalize()
|
|
544
|
+
# # Check for common two-letter elements
|
|
545
|
+
# if possible in {"Cl", "Br", "Fe", "Mg", "Zn", "Ca", "Na", "Cu", "Mn", "Co", "Ni"}:
|
|
546
|
+
# return possible
|
|
547
|
+
# Fallback to first letter
|
|
548
|
+
return atom_name[0].upper()
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
class AtomDict(TypedDict, total=False):
|
|
552
|
+
"""A dictionary representing an atom in a PDB file."""
|
|
553
|
+
|
|
554
|
+
occupancy: float | None
|
|
555
|
+
bvalue: float | None
|
|
556
|
+
charge: int | None
|
|
557
|
+
anisotropy: float | None
|
|
558
|
+
is_hetatm: bool | None
|
|
559
|
+
name: str | None
|
|
560
|
+
alt_loc: str | None
|
|
561
|
+
x: float
|
|
562
|
+
y: float
|
|
563
|
+
z: float
|
|
564
|
+
element: str | None
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def atom_line_to_dict(line: str, aniso_dict: dict[Any, Any]) -> AtomDict:
|
|
568
|
+
"""
|
|
569
|
+
Converts an ATOM or HETATM record to an atom dictionary.
|
|
531
570
|
|
|
532
571
|
:param str line: the record to convert.
|
|
533
572
|
:param dict aniso_dict: the anisotropy dictionary to use.
|
|
534
|
-
:
|
|
573
|
+
:return: atom dictionary
|
|
574
|
+
"""
|
|
535
575
|
|
|
536
|
-
a = {"occupancy": 1, "bvalue": None, "charge": 0, "anisotropy": aniso_dict.get(int(line[6:11].strip()), None)}
|
|
576
|
+
a: AtomDict = {"occupancy": 1, "bvalue": None, "charge": 0, "anisotropy": aniso_dict.get(int(line[6:11].strip()), None)}
|
|
537
577
|
a["is_hetatm"] = line[:6] == "HETATM"
|
|
538
578
|
a["name"] = line[12:16].strip() or None
|
|
539
579
|
a["alt_loc"] = line[16].strip() or None
|
|
@@ -545,6 +585,11 @@ def atom_line_to_dict(line: str, aniso_dict: dict[Any, Any]) -> dict[str, Any]:
|
|
|
545
585
|
if line[60:66].strip():
|
|
546
586
|
a["bvalue"] = float(line[60:66].strip())
|
|
547
587
|
a["element"] = line[76:78].strip() or None
|
|
588
|
+
if not a["element"]:
|
|
589
|
+
if not a["name"]:
|
|
590
|
+
raise ValueError("Cannot guess element from empty name.")
|
|
591
|
+
assert isinstance(a["name"], str)
|
|
592
|
+
a["element"] = guess_element_from_name(a["name"])
|
|
548
593
|
if line[78:80].strip():
|
|
549
594
|
try:
|
|
550
595
|
a["charge"] = int(line[78:80].strip())
|
|
@@ -561,6 +606,7 @@ def atom_line_to_dict(line: str, aniso_dict: dict[Any, Any]) -> dict[str, Any]:
|
|
|
561
606
|
a["occupancy"] = None
|
|
562
607
|
if a["name"] == a["element"]:
|
|
563
608
|
a["name"] = None
|
|
609
|
+
|
|
564
610
|
return a
|
|
565
611
|
|
|
566
612
|
|
stjames/molecule.py
CHANGED
|
@@ -2,6 +2,7 @@ import re
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Annotated, Any, Iterable, Optional, Self, Sequence, TypeAlias, TypedDict, TypeVar
|
|
4
4
|
|
|
5
|
+
import numpy as np
|
|
5
6
|
import pydantic
|
|
6
7
|
from pydantic import AfterValidator, NonNegativeInt, PositiveInt, ValidationError
|
|
7
8
|
from rdkit import Chem
|
|
@@ -75,15 +76,41 @@ class Molecule(Base):
|
|
|
75
76
|
def __len__(self) -> int:
|
|
76
77
|
return len(self.atoms)
|
|
77
78
|
|
|
78
|
-
def distance(self,
|
|
79
|
+
def distance(self, i: PositiveInt, j: PositiveInt) -> float:
|
|
79
80
|
r"""
|
|
80
|
-
|
|
81
|
+
Calculate the distance between atoms.
|
|
81
82
|
|
|
82
83
|
>>> mol = Molecule.from_xyz("H 0 1 0\nH 0 0 1")
|
|
83
84
|
>>> mol.distance(1, 2)
|
|
84
85
|
1.4142135623730951
|
|
85
86
|
"""
|
|
86
|
-
return sum((q2 - q1) ** 2 for q1, q2 in zip(self.atoms[
|
|
87
|
+
return sum((q2 - q1) ** 2 for q1, q2 in zip(self.atoms[i - 1].position, self.atoms[j - 1].position)) ** 0.5 # type: ignore [no-any-return,unused-ignore]
|
|
88
|
+
|
|
89
|
+
def angle(self, i: PositiveInt, j: PositiveInt, k: PositiveInt, degrees: bool = True) -> float:
|
|
90
|
+
r"""
|
|
91
|
+
Calculate the angle between three atoms.
|
|
92
|
+
|
|
93
|
+
>>> Molecule.from_xyz("H 0 0 0\nO 0 0 1\nH 0 1 1").angle(1, 2, 3)
|
|
94
|
+
90.0
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
return angle(self.coordinates[i - 1], self.coordinates[j - 1], self.coordinates[k - 1], degrees=degrees)
|
|
98
|
+
|
|
99
|
+
def dihedral(self, i: int, j: int, k: int, l: int, degrees: bool = True, positive_domain: bool = True) -> float:
|
|
100
|
+
r"""
|
|
101
|
+
Calculate the dihedral angle between four atoms.
|
|
102
|
+
|
|
103
|
+
>>> Molecule.from_xyz("H 0 0 0\nO 0 0 1\nO 0 1 1\nH 1 1 1").dihedral(1, 2, 3, 4)
|
|
104
|
+
270.0
|
|
105
|
+
"""
|
|
106
|
+
return dihedral(
|
|
107
|
+
self.coordinates[i - 1],
|
|
108
|
+
self.coordinates[j - 1],
|
|
109
|
+
self.coordinates[k - 1],
|
|
110
|
+
self.coordinates[l - 1],
|
|
111
|
+
degrees=degrees,
|
|
112
|
+
positive_domain=positive_domain,
|
|
113
|
+
)
|
|
87
114
|
|
|
88
115
|
@property
|
|
89
116
|
def coordinates(self) -> Vector3DPerAtom:
|
|
@@ -345,19 +372,17 @@ class Molecule(Base):
|
|
|
345
372
|
return cls(atoms=atoms, cell=cell, charge=charge, multiplicity=multiplicity, energy=energy, gradient=gradients)
|
|
346
373
|
|
|
347
374
|
@classmethod
|
|
348
|
-
def from_rdkit(cls: type[Self], rdkm: RdkitMol, cid: int = 0) -> Self:
|
|
375
|
+
def from_rdkit(cls: type[Self], rdkm: RdkitMol, cid: int = 0, multiplicity: int = 1) -> Self:
|
|
349
376
|
if len(rdkm.GetConformers()) == 0:
|
|
350
377
|
rdkm = _embed_rdkit_mol(rdkm)
|
|
351
378
|
|
|
352
|
-
atoms = []
|
|
353
379
|
atomic_numbers = [atom.GetAtomicNum() for atom in rdkm.GetAtoms()] # type: ignore [no-untyped-call, unused-ignore]
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
380
|
+
atoms = [
|
|
381
|
+
Atom(atomic_number=atom, position=xyz) # keep open
|
|
382
|
+
for atom, xyz in zip(atomic_numbers, rdkm.GetConformers()[cid].GetPositions(), strict=True)
|
|
383
|
+
]
|
|
358
384
|
|
|
359
385
|
charge = Chem.GetFormalCharge(rdkm)
|
|
360
|
-
multiplicity = 1
|
|
361
386
|
|
|
362
387
|
return cls(atoms=atoms, charge=charge, multiplicity=multiplicity)
|
|
363
388
|
|
|
@@ -447,3 +472,67 @@ def parse_extxyz_comment_line(line: str) -> EXTXYZMetadata:
|
|
|
447
472
|
prop_dict[key] = value # type: ignore [literal-required]
|
|
448
473
|
|
|
449
474
|
return prop_dict
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def angle(p0: Sequence[float], p1: Sequence[float], p2: Sequence[float], degrees: bool = True) -> float:
|
|
478
|
+
"""
|
|
479
|
+
Angle between three points.
|
|
480
|
+
|
|
481
|
+
:param i, j, k: positions of points
|
|
482
|
+
:param degrees: whether to return in degrees
|
|
483
|
+
:return: angle in radians or degrees
|
|
484
|
+
"""
|
|
485
|
+
a0, a1, a2 = map(np.asarray, (p0, p1, p2))
|
|
486
|
+
u = a1 - a0
|
|
487
|
+
v = a1 - a2
|
|
488
|
+
|
|
489
|
+
nu = np.linalg.norm(u)
|
|
490
|
+
nv = np.linalg.norm(v)
|
|
491
|
+
cos_theta = np.dot(u, v) / (nu * nv)
|
|
492
|
+
cos_theta = np.clip(cos_theta, -1.0, 1.0)
|
|
493
|
+
|
|
494
|
+
ang = np.arccos(cos_theta)
|
|
495
|
+
if degrees:
|
|
496
|
+
return float(np.degrees(ang))
|
|
497
|
+
return float(ang)
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def dihedral(p0: Sequence[float], p1: Sequence[float], p2: Sequence[float], p3: Sequence[float], degrees: bool = True, positive_domain: bool = True) -> float:
|
|
501
|
+
"""
|
|
502
|
+
Dihedral angle between four points.
|
|
503
|
+
|
|
504
|
+
:param p0, p1, p2, p3: points
|
|
505
|
+
:param degrees: whether to return in degrees
|
|
506
|
+
:param positive_domain: (0, 360] if True else (-180, 180]
|
|
507
|
+
:return: angle in degrees or radians (or nan if collinearities detected)
|
|
508
|
+
|
|
509
|
+
>>> a = [0, 0, 0]
|
|
510
|
+
>>> b = [0, 0, 1]
|
|
511
|
+
>>> c = [0, 1, 1]
|
|
512
|
+
>>> d1 = [0, 1, 2]
|
|
513
|
+
>>> d2 = [0.5, 1, 1.5]
|
|
514
|
+
>>> dihedral(a, b, c, d1)
|
|
515
|
+
180.0
|
|
516
|
+
>>> dihedral(a, b, c, d2, positive_domain=False)
|
|
517
|
+
-135.0
|
|
518
|
+
"""
|
|
519
|
+
a0, a1, a2, a3 = map(np.asarray, (p0, p1, p2, p3))
|
|
520
|
+
b0 = a1 - a0
|
|
521
|
+
b1 = a2 - a1
|
|
522
|
+
b2 = a3 - a2
|
|
523
|
+
|
|
524
|
+
b1 = b1 / np.linalg.norm(b1)
|
|
525
|
+
|
|
526
|
+
v = b1 * np.dot(b0, b1) - b0
|
|
527
|
+
w = b2 - b1 * np.dot(b2, b1)
|
|
528
|
+
|
|
529
|
+
x = np.dot(v, w)
|
|
530
|
+
y = np.dot(np.cross(b1, v), w)
|
|
531
|
+
ang = np.arctan2(y, x)
|
|
532
|
+
|
|
533
|
+
if positive_domain and ang < 0:
|
|
534
|
+
ang += 2 * np.pi
|
|
535
|
+
|
|
536
|
+
if degrees:
|
|
537
|
+
return float(np.degrees(ang))
|
|
538
|
+
return float(ang)
|
|
@@ -7,10 +7,10 @@ from .workflow import MoleculeWorkflow
|
|
|
7
7
|
|
|
8
8
|
class HydrogenBondAcceptorSite(Base):
|
|
9
9
|
"""
|
|
10
|
-
A hydrogen
|
|
10
|
+
A hydrogen-bond-acceptor site.
|
|
11
11
|
|
|
12
12
|
:param atom_idx: index of the atom
|
|
13
|
-
:param pkbhx: Hydrogen
|
|
13
|
+
:param pkbhx: Hydrogen-bond basicity
|
|
14
14
|
:param position: position of the atom
|
|
15
15
|
:param name: name of the atom
|
|
16
16
|
"""
|
|
@@ -21,9 +21,23 @@ class HydrogenBondAcceptorSite(Base):
|
|
|
21
21
|
name: str | None = None
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
class HydrogenBondDonorSite(Base):
|
|
25
|
+
"""
|
|
26
|
+
A hydrogen-bond-donor site.
|
|
27
|
+
|
|
28
|
+
:param atom_idx: index of the atom
|
|
29
|
+
:param pk_alpha: Hydrogen-bond acidity
|
|
30
|
+
:param position: position of the atom
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
atom_idx: int # zero-indexed
|
|
34
|
+
pk_alpha: float
|
|
35
|
+
position: tuple[float, float, float]
|
|
36
|
+
|
|
37
|
+
|
|
24
38
|
class HydrogenBondBasicityWorkflow(MoleculeWorkflow):
|
|
25
39
|
"""
|
|
26
|
-
Workflow for calculating hydrogen
|
|
40
|
+
Workflow for calculating hydrogen-bond basicity and acidity.
|
|
27
41
|
|
|
28
42
|
Inherited:
|
|
29
43
|
:param initial_molecule: Molecule of interest
|
|
@@ -36,6 +50,7 @@ class HydrogenBondBasicityWorkflow(MoleculeWorkflow):
|
|
|
36
50
|
Results:
|
|
37
51
|
:param optimization: UUID of optimization
|
|
38
52
|
:param hba_sites: hydrogen-bond-acceptor sites
|
|
53
|
+
:param hbd_sites: hydrogen-bond-donor sites
|
|
39
54
|
"""
|
|
40
55
|
|
|
41
56
|
do_csearch: bool = True
|
|
@@ -43,3 +58,4 @@ class HydrogenBondBasicityWorkflow(MoleculeWorkflow):
|
|
|
43
58
|
|
|
44
59
|
optimization: UUID | None = None
|
|
45
60
|
hba_sites: list[HydrogenBondAcceptorSite] = [] # noqa: RUF012
|
|
61
|
+
hbd_sites: list[HydrogenBondDonorSite] = [] # noqa: RUF012
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
"""Multi-stage optimization workflow."""
|
|
2
2
|
|
|
3
|
+
import re
|
|
3
4
|
from typing import Self, Sequence
|
|
4
5
|
|
|
6
|
+
import more_itertools as mit
|
|
5
7
|
from pydantic import BaseModel, Field, model_validator
|
|
6
8
|
|
|
9
|
+
from stjames.correction import Correction
|
|
10
|
+
|
|
7
11
|
from ..constraint import Constraint
|
|
8
12
|
from ..method import XTB_METHODS, Method
|
|
9
13
|
from ..mode import Mode
|
|
10
14
|
from ..opt_settings import OptimizationSettings
|
|
11
15
|
from ..settings import Settings
|
|
12
|
-
from ..solvent import Solvent, SolventSettings
|
|
16
|
+
from ..solvent import Solvent, SolventModel, SolventSettings
|
|
13
17
|
from ..task import Task
|
|
14
18
|
from ..types import UUID
|
|
15
19
|
from .workflow import MoleculeWorkflow
|
|
@@ -264,6 +268,73 @@ class MultiStageOptMixin(BaseModel):
|
|
|
264
268
|
return self
|
|
265
269
|
|
|
266
270
|
|
|
271
|
+
def mso_settings_from_method_string(
|
|
272
|
+
methods: str,
|
|
273
|
+
solvent: Solvent | None = None,
|
|
274
|
+
use_solvent_for_opt: bool = False,
|
|
275
|
+
constraints: list[Constraint] | None = None,
|
|
276
|
+
transition_state: bool = False,
|
|
277
|
+
frequencies: bool = False,
|
|
278
|
+
) -> MultiStageOptSettings:
|
|
279
|
+
"""
|
|
280
|
+
Helper function to construct multi-stage opt settings objects from a method string.
|
|
281
|
+
|
|
282
|
+
>>> mso_settings_from_method_string("r2SCAN-3c/CPCM(Water)//B3LYP-D3/6-31G(d)/ALPB(Water)//GFN2-xTB/CPCM(Water)//GFN0-xTB").level_of_theory
|
|
283
|
+
'r2scan_3c/cpcm(water)//b3lyp-d3/6-31g(d)/alpb(water)//gfn2_xtb/cpcm(water)//gfn0_xtb'
|
|
284
|
+
"""
|
|
285
|
+
solvent_models = "|".join(model.name for model in SolventModel)
|
|
286
|
+
|
|
287
|
+
pattern = rf"""
|
|
288
|
+
(?P<method>[^/()]+) # Method + optional corrections
|
|
289
|
+
(?:/(?P<basis_set>(?!{solvent_models})[^/]+?))? # Optional basis_set, not starting with solvent model name
|
|
290
|
+
(?:/(?P<solvent_model>{solvent_models}) # Optional solvent model
|
|
291
|
+
\((?P<solvent>[^()]+)\))? # Solvent name in parentheses
|
|
292
|
+
(?:\/\/|$) # End or separator
|
|
293
|
+
"""
|
|
294
|
+
constraints = constraints or []
|
|
295
|
+
opt_settings = OptimizationSettings(constraints=constraints, transition_state=transition_state)
|
|
296
|
+
OPT = [Task.OPTIMIZE if not transition_state else Task.OPTIMIZE_TS]
|
|
297
|
+
|
|
298
|
+
valid_corrections = {c.name.lower() for c in Correction} # Python3.11 hack
|
|
299
|
+
|
|
300
|
+
def process(match: re.Match[str]) -> Settings:
|
|
301
|
+
data = match.groupdict()
|
|
302
|
+
|
|
303
|
+
method, corrections = mit.partition(lambda x: x.lower() in valid_corrections, data["method"].split("-"))
|
|
304
|
+
solvent_settings = SolventSettings(solvent=data["solvent"], model=data["solvent_model"]) if data["solvent"] else None
|
|
305
|
+
|
|
306
|
+
return Settings(
|
|
307
|
+
method="-".join(method),
|
|
308
|
+
basis_set=data["basis_set"],
|
|
309
|
+
tasks=OPT,
|
|
310
|
+
solvent_settings=solvent_settings,
|
|
311
|
+
opt_settings=opt_settings,
|
|
312
|
+
corrections=list(corrections),
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
optimization_settings = [process(match) for match in re.finditer(pattern, methods, re.VERBOSE | re.IGNORECASE)]
|
|
316
|
+
if len(optimization_settings) > 1:
|
|
317
|
+
sp_settings = optimization_settings.pop(0)
|
|
318
|
+
sp_settings.tasks = [Task.ENERGY]
|
|
319
|
+
else:
|
|
320
|
+
sp_settings = None
|
|
321
|
+
|
|
322
|
+
optimization_settings = optimization_settings[::-1]
|
|
323
|
+
if frequencies:
|
|
324
|
+
optimization_settings[-1].tasks.append(Task.FREQUENCIES)
|
|
325
|
+
|
|
326
|
+
return MultiStageOptSettings(
|
|
327
|
+
mode=Mode.MANUAL,
|
|
328
|
+
optimization_settings=optimization_settings,
|
|
329
|
+
singlepoint_settings=sp_settings,
|
|
330
|
+
solvent=solvent,
|
|
331
|
+
xtb_preopt=False,
|
|
332
|
+
constraints=constraints,
|
|
333
|
+
transition_state=transition_state,
|
|
334
|
+
frequencies=frequencies,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
267
338
|
def build_mso_settings(
|
|
268
339
|
sp_method: Method,
|
|
269
340
|
sp_basis_set: str | None,
|
|
@@ -12,6 +12,7 @@ class CofoldingModel(LowercaseStrEnum):
|
|
|
12
12
|
|
|
13
13
|
CHAI_1R = "chai_1r"
|
|
14
14
|
BOLTZ_1 = "boltz_1"
|
|
15
|
+
BOLTZ_2 = "boltz_2"
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class CofoldingScores(BaseModel):
|
|
@@ -20,6 +21,15 @@ class CofoldingScores(BaseModel):
|
|
|
20
21
|
iptm: float # interface predicted template modeling score
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
class AffinityScore(BaseModel):
|
|
25
|
+
pred_value: float
|
|
26
|
+
probability_binary: float
|
|
27
|
+
pred_value1: float
|
|
28
|
+
probability_binary1: float
|
|
29
|
+
pred_value2: float
|
|
30
|
+
probability_binary2: float
|
|
31
|
+
|
|
32
|
+
|
|
23
33
|
class ProteinCofoldingWorkflow(FASTAWorkflow):
|
|
24
34
|
"""
|
|
25
35
|
A workflow for predicting structures. Especially protein structures.
|
|
@@ -38,4 +48,5 @@ class ProteinCofoldingWorkflow(FASTAWorkflow):
|
|
|
38
48
|
use_templates_server: bool = False
|
|
39
49
|
predicted_structure_uuid: UUID | None = None
|
|
40
50
|
scores: CofoldingScores | None = None
|
|
41
|
-
model: CofoldingModel = CofoldingModel.
|
|
51
|
+
model: CofoldingModel = CofoldingModel.BOLTZ_2
|
|
52
|
+
affinity_score: AffinityScore | None = None
|
stjames/workflows/workflow.py
CHANGED
|
@@ -32,6 +32,7 @@ class FASTAWorkflow(Workflow):
|
|
|
32
32
|
|
|
33
33
|
initial_protein_sequences: list[str]
|
|
34
34
|
initial_smiles_list: list[str] | None = None
|
|
35
|
+
ligand_binding_affinity_index: int | None = None
|
|
35
36
|
|
|
36
37
|
def __repr__(self) -> str:
|
|
37
38
|
return f"<{type(self).__name__} {self.initial_protein_sequences} {self.initial_smiles_list}>"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stjames
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.78
|
|
4
4
|
Summary: standardized JSON atom/molecule encoding scheme
|
|
5
5
|
Author-email: Corin Wagen <corin@rowansci.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/rowansci/stjames
|
|
@@ -12,6 +12,7 @@ Requires-Dist: pydantic>=2.4
|
|
|
12
12
|
Requires-Dist: numpy
|
|
13
13
|
Requires-Dist: requests
|
|
14
14
|
Requires-Dist: rdkit
|
|
15
|
+
Requires-Dist: more-itertools
|
|
15
16
|
Dynamic: license-file
|
|
16
17
|
|
|
17
18
|
# stjames
|
|
@@ -13,7 +13,7 @@ stjames/int_settings.py,sha256=5HXp8opt5ZyY1UpmfaK7NVloWVLM5jkG0elEEqpVLUo,896
|
|
|
13
13
|
stjames/message.py,sha256=Rq6QqmHZKecWxYH8fVyXmuoCCPZv8YinvgykSeorXSU,216
|
|
14
14
|
stjames/method.py,sha256=k7WtNvD_0OyXWWDjukmVXFFYfIO-Wg4vY1W58o99-gQ,2821
|
|
15
15
|
stjames/mode.py,sha256=xw46Cc7f3eTS8i35qECi-8DocAlANhayK3w4akD4HBU,496
|
|
16
|
-
stjames/molecule.py,sha256=
|
|
16
|
+
stjames/molecule.py,sha256=l4S6prH1xflnZtbwidSF2THsiHaSJtRiy1rmUbH366Q,20631
|
|
17
17
|
stjames/opt_settings.py,sha256=LEwGXUEKq5TfU5rr60Z4QQBhCqiw1Ch5w0M_lXawWo8,642
|
|
18
18
|
stjames/pdb.py,sha256=_pIdJCMhIzS4t2HWQa_susDWjZEl0oLn4Njb1QoKvKw,26460
|
|
19
19
|
stjames/periodic_cell.py,sha256=eV_mArsY_MPEFSrFEsTC-CyCc6V8ITAXdk7yhjjNI7M,1080
|
|
@@ -28,7 +28,7 @@ stjames/types.py,sha256=rs2CdpkruIfU-PS98rjr9HAJNFGdZDB_zl-u3wa5rAs,4092
|
|
|
28
28
|
stjames/atomium_stjames/__init__.py,sha256=gZkzC7i9D_fmWUTN55gtygITo3-qvJUda5CXLR0jyCQ,306
|
|
29
29
|
stjames/atomium_stjames/data.py,sha256=-hzwBpTHq5JetsOVyopUJswKnKAkMtJ_XkONxjXVupU,5675
|
|
30
30
|
stjames/atomium_stjames/mmcif.py,sha256=em1fNt6577OaUjL7Pctru7aJp3ceZ9kEnj5w6BRWdVs,27090
|
|
31
|
-
stjames/atomium_stjames/pdb.py,sha256=
|
|
31
|
+
stjames/atomium_stjames/pdb.py,sha256=hoEV1xmbkYkXW8A6YX5uspvSRvGlhzM1o_BiikQ6DiU,23734
|
|
32
32
|
stjames/atomium_stjames/utilities.py,sha256=-YtM7sRMvMk0wWrC3svWUWH4CGI0NtY77nXsg9tjHfc,4964
|
|
33
33
|
stjames/data/__init__.py,sha256=O59Ksp7AIqwOELCWymfCx7YeBzwNOGCMlGQi7tNLqiE,24
|
|
34
34
|
stjames/data/bragg_radii.json,sha256=hhbn-xyZNSdmnULIjN2Cvq-_BGIZIqG243Ls_mey61w,1350
|
|
@@ -47,22 +47,22 @@ stjames/workflows/descriptors.py,sha256=T4tc7xdtBdxESGO86KR323jPQ2pgwxBqgV0khA6M
|
|
|
47
47
|
stjames/workflows/docking.py,sha256=GCW_-JeEZcMXKZ9EQFOxWUYRo0jsbzwIv10aSz8KuaQ,3027
|
|
48
48
|
stjames/workflows/electronic_properties.py,sha256=GT3-NC7w-dbcOJ-3AzJ7LgzH6frTbiH2Iyb9BCa-SvY,4112
|
|
49
49
|
stjames/workflows/fukui.py,sha256=T6TDg-lcE-sfTDVpa3KFBenLe7PGUO2QrQ2jNuw_iiU,1756
|
|
50
|
-
stjames/workflows/hydrogen_bond_basicity.py,sha256=
|
|
50
|
+
stjames/workflows/hydrogen_bond_basicity.py,sha256=q9eXty68ZyCmrB6G_8bfeOT8Ui_IQquRPu6z-3rNreQ,1589
|
|
51
51
|
stjames/workflows/ion_mobility.py,sha256=e6XSidrud5qSkrAcjzOzgHaf-G09JoP09V76myjdyjc,1097
|
|
52
52
|
stjames/workflows/irc.py,sha256=ZP7icylW8rgo_Uh7h3bmyumn0ru1IyF-61nP5Jnmq3M,3402
|
|
53
53
|
stjames/workflows/macropka.py,sha256=KRIyk4gsSYL3eqyzCDndStGLwjWSo60cgCAzvAoD1Nk,3754
|
|
54
54
|
stjames/workflows/molecular_dynamics.py,sha256=kxugE73Ntzpj-xpJSoQ1EwGzXXdvi_NTyeP4913EVwE,3173
|
|
55
|
-
stjames/workflows/multistage_opt.py,sha256=
|
|
55
|
+
stjames/workflows/multistage_opt.py,sha256=P8rxMUhKXMmDi7Id95IOTEmM0xN1ErsKcDJfgY08vjc,16538
|
|
56
56
|
stjames/workflows/pka.py,sha256=j3vBh2YM3nJzJ1XJKPsmYahRCeaU9n3P-G-u9_moaFw,2065
|
|
57
|
-
stjames/workflows/protein_cofolding.py,sha256=
|
|
57
|
+
stjames/workflows/protein_cofolding.py,sha256=y4egDFTVEmUPN4gVeivgO83IA3CG6AVbRtvU5Ng3iuE,1454
|
|
58
58
|
stjames/workflows/redox_potential.py,sha256=7S18t9Y3eynSnA3lZbRlvLfdbgeBopdiigLzt1zxg5c,3871
|
|
59
59
|
stjames/workflows/scan.py,sha256=DXQBpa2t2PowAtOwmdgpxaSLq--fEShljzAGSb8Nf5U,2993
|
|
60
60
|
stjames/workflows/solubility.py,sha256=kGfVyPPGDLRpf2j6dSY7woCkfsoXSbUzdSImA4mcMpw,1898
|
|
61
61
|
stjames/workflows/spin_states.py,sha256=0degmE-frovgoXweshZyjfjqL7nkbaFoO9YoJhvQnaI,4748
|
|
62
62
|
stjames/workflows/tautomer.py,sha256=7eYKziGPg8Km6lfowTzSkgJfJ4SHUPrAmnTf8Bi-SB0,1164
|
|
63
|
-
stjames/workflows/workflow.py,sha256=
|
|
64
|
-
stjames-0.0.
|
|
65
|
-
stjames-0.0.
|
|
66
|
-
stjames-0.0.
|
|
67
|
-
stjames-0.0.
|
|
68
|
-
stjames-0.0.
|
|
63
|
+
stjames/workflows/workflow.py,sha256=OE05pt2ZOd8TzTOlBngXCVg9wv_553ZR60VNRPlq0f8,1953
|
|
64
|
+
stjames-0.0.78.dist-info/licenses/LICENSE,sha256=i7ehYBS-6gGmbTcgU4mgk28pyOx2kScJ0kcx8n7bWLM,1084
|
|
65
|
+
stjames-0.0.78.dist-info/METADATA,sha256=F9H_rYG2dPbIsXty-Du4PnKs64_-k1f1VRt69dqZU9U,1724
|
|
66
|
+
stjames-0.0.78.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
67
|
+
stjames-0.0.78.dist-info/top_level.txt,sha256=FYCwxl6quhYOAgG-mnPQcCK8vsVM7B8rIUrO-WrQ_PI,8
|
|
68
|
+
stjames-0.0.78.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|