stjames 0.0.63__py3-none-any.whl → 0.0.65__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.

@@ -516,7 +516,7 @@ def add_atom_to_polymer(atom: dict[str, Any], aniso: dict[int, Any], model: dict
516
516
  try:
517
517
  model["polymer"][mol_id]["residues"][res_id] = {
518
518
  "name": name,
519
- "full_name": names.get(name),
519
+ "full_name": names.get(name).upper() if names.get(name) is not None else None, # type: ignore [union-attr]
520
520
  "atoms": {int(atom["id"]): atom_dict_to_atom_dict(atom, aniso)},
521
521
  "number": len(model["polymer"][mol_id]["residues"]) + 1,
522
522
  }
@@ -530,7 +530,7 @@ def add_atom_to_polymer(atom: dict[str, Any], aniso: dict[int, Any], model: dict
530
530
  "name": name,
531
531
  "atoms": {int(atom["id"]): atom_dict_to_atom_dict(atom, aniso)},
532
532
  "number": 1,
533
- "full_name": names.get(name),
533
+ "full_name": names.get(name).upper() if names.get(name) is not None else None, # type: ignore [union-attr]
534
534
  }
535
535
  },
536
536
  }
@@ -547,6 +547,8 @@ def add_atom_to_non_polymer(atom: dict[str, Any], aniso: dict[int, Any], model:
547
547
  :param names: lookup dictionary for full name information
548
548
  """
549
549
  mol_id = make_residue_id(atom)
550
+ if mol_type == "non-polymer":
551
+ mol_type = "non_polymer"
550
552
 
551
553
  try:
552
554
  model[mol_type][mol_id]["atoms"][int(atom["id"])] = atom_dict_to_atom_dict(atom, aniso)
@@ -554,7 +556,7 @@ def add_atom_to_non_polymer(atom: dict[str, Any], aniso: dict[int, Any], model:
554
556
  name = atom["auth_comp_id"]
555
557
  model[mol_type][mol_id] = {
556
558
  "name": name,
557
- "full_name": names.get(name),
559
+ "full_name": names.get(name).upper() if names.get(name) is not None and names.get(name).lower() != "water" else None, # type: ignore [union-attr]
558
560
  "internal_id": atom["label_asym_id"],
559
561
  "polymer": atom["auth_asym_id"],
560
562
  "atoms": {int(atom["id"]): atom_dict_to_atom_dict(atom, aniso)},
@@ -644,7 +646,7 @@ def atom_dict_to_atom_dict(d: dict[str, Any], aniso_dict: dict[int, Any]) -> dic
644
646
  "bvalue": d.get("B_iso_or_equiv"),
645
647
  "charge": d.get(charge, 0) if d.get(charge) != "?" else 0,
646
648
  "alt_loc": d.get("label_alt_id") if d.get("label_alt_id") != "." else None,
647
- "anisotropy": aniso_dict.get(int(d["id"]), [0, 0, 0, 0, 0, 0]),
649
+ "anisotropy": aniso_dict.get(int(d["id"]), None),
648
650
  "is_hetatm": d.get("group_PDB", "ATOM") == "HETATM",
649
651
  }
650
652
 
stjames/molecule.py CHANGED
@@ -34,6 +34,7 @@ class VibrationalMode(Base):
34
34
  reduced_mass: Annotated[float, AfterValidator(round_float(3))] # amu
35
35
  force_constant: Annotated[float, AfterValidator(round_float(3))] # mDyne/Å
36
36
  displacements: Annotated[Vector3DPerAtom, AfterValidator(round_vector3d_per_atom(6))] # Å
37
+ ir_intensity: Annotated[Optional[float], AfterValidator(round_optional_float(3))] = None # km/mol
37
38
 
38
39
 
39
40
  class Molecule(Base):
@@ -68,6 +69,7 @@ class Molecule(Base):
68
69
  thermal_free_energy_corr: Annotated[Optional[float], AfterValidator(round_optional_float(6))] = None
69
70
 
70
71
  smiles: Optional[str] = None
72
+ calculation_index: int | None = None
71
73
 
72
74
  def __len__(self) -> int:
73
75
  return len(self.atoms)
stjames/pdb.py CHANGED
@@ -204,6 +204,12 @@ def fetch_pdb(code: str) -> PDB:
204
204
  return PDB.model_validate(astj.fetch(code, data_dict=True))
205
205
 
206
206
 
207
+ def fetch_pdb_from_mmcif(code: str) -> PDB:
208
+ """Fetch a pdb from the Protein Data Bank."""
209
+ code += ".cif"
210
+ return PDB.model_validate(astj.fetch(code, data_dict=True))
211
+
212
+
207
213
  def pdb_from_pdb_filestring(pdb: str) -> PDB:
208
214
  """Read a PDB from a string."""
209
215
  return PDB.model_validate(pdb_dict_to_data_dict(pdb_string_to_pdb_dict(pdb)))
@@ -12,6 +12,7 @@ from .docking import *
12
12
  from .electronic_properties import *
13
13
  from .fukui import *
14
14
  from .hydrogen_bond_basicity import *
15
+ from .ion_mobility import *
15
16
  from .irc import *
16
17
  from .molecular_dynamics import *
17
18
  from .multistage_opt import *
@@ -34,6 +35,7 @@ WORKFLOW_NAME = Literal[
34
35
  "electronic_properties",
35
36
  "fukui",
36
37
  "hydrogen_bond_basicity",
38
+ "ion_mobility",
37
39
  "irc",
38
40
  "molecular_dynamics",
39
41
  "multistage_opt",
@@ -56,6 +58,7 @@ WORKFLOW_MAPPING: dict[WORKFLOW_NAME, Workflow] = {
56
58
  "electronic_properties": ElectronicPropertiesWorkflow, # type: ignore [dict-item]
57
59
  "fukui": FukuiIndexWorkflow, # type: ignore [dict-item]
58
60
  "hydrogen_bond_basicity": HydrogenBondBasicityWorkflow, # type: ignore [dict-item]
61
+ "ion_mobility": IonMobilityWorkflow, # type: ignore [dict-item]
59
62
  "irc": IRCWorkflow, # type: ignore [dict-item]
60
63
  "molecular_dynamics": MolecularDynamicsWorkflow, # type: ignore [dict-item]
61
64
  "multistage_opt": MultiStageOptWorkflow, # type: ignore [dict-item]
@@ -1,18 +1,39 @@
1
1
  """ADME-Tox property prediction workflow."""
2
2
 
3
- from .workflow import MoleculeWorkflow
3
+ import warnings
4
+ from typing import Self
4
5
 
6
+ from pydantic import model_validator
5
7
 
6
- class ADMETWorkflow(MoleculeWorkflow):
8
+ from ..molecule import Molecule
9
+ from .workflow import MoleculeWorkflow, SMILESWorkflow
10
+
11
+
12
+ class ADMETWorkflow(SMILESWorkflow, MoleculeWorkflow):
7
13
  """
8
14
  A workflow for predicting ADME-Tox properties.
9
15
 
10
16
  Inherited:
11
- :param initial_molecule: Molecule of interest
17
+ :param initial_smiles: SMILES string of molecule (mutually exclusive with initial_molecule)
18
+ :param initial_molecule: Molecule of interest (deprecated)
12
19
  :param mode: Mode for workflow (currently unused)
13
20
 
14
21
  New:
15
22
  :param properties: predicted properties
16
23
  """
17
24
 
25
+ initial_smiles: str = ""
26
+ initial_molecule: Molecule | None = None # type: ignore [assignment] # Deprecated
18
27
  properties: dict[str, float | int] | None = None
28
+
29
+ @model_validator(mode="after")
30
+ def validate_mol_input(self) -> Self:
31
+ """Ensure that only one of initial_molecule or initial_smiles is set."""
32
+
33
+ if not (bool(self.initial_smiles) ^ bool(self.initial_molecule)):
34
+ raise ValueError("Can only set one of initial_molecule should and initial_smiles")
35
+
36
+ if self.initial_molecule is not None:
37
+ warnings.warn(DeprecationWarning("initial_molecule is deprecated. Use initial_smiles instead."))
38
+
39
+ return self
@@ -0,0 +1,36 @@
1
+ """Ion mobility workflow."""
2
+
3
+ from ..types import UUID
4
+ from .workflow import MoleculeWorkflow
5
+
6
+
7
+ class IonMobilityWorkflow(MoleculeWorkflow):
8
+ """
9
+ Workflow for calculating hydrogen bond basicity.
10
+
11
+ Inherited:
12
+ :param initial_molecule: Molecule of interest
13
+ :param mode: Mode for workflow (currently unused)
14
+
15
+ New:
16
+ :param do_csearch: whether to perform a conformational search
17
+ :param do_optimization: whether to perform an optimization
18
+
19
+ Results:
20
+ :param conformer_ccs: the collision cross section (Å**2) per conformer
21
+ :param conformer_ccs_stdev: the uncertainty in the same
22
+ :param conformer_weights: the Boltzmann weights at RT
23
+ :param average_ccs: the Boltzmann-weighted CCS for the ensemble
24
+ :param average_ccs_stdev: the uncertainty in the same
25
+ """
26
+
27
+ do_csearch: bool = True
28
+ do_optimization: bool = True
29
+ conformers: list[UUID] = []
30
+
31
+ conformer_ccs: list[float] = []
32
+ conformer_ccs_stdev: list[float] = []
33
+ boltzmann_weights: list[float] = []
34
+
35
+ average_ccs: float | None = None
36
+ average_ccs_stdev: float | None = None
@@ -0,0 +1,72 @@
1
+ """pKa workflow."""
2
+
3
+ from typing import Annotated, Self
4
+
5
+ from pydantic import AfterValidator, model_validator
6
+
7
+ from ..base import Base, round_float
8
+ from ..types import round_list
9
+ from .workflow import SMILESWorkflow
10
+
11
+
12
+ class MacropKaMicrostate(Base):
13
+ """
14
+ A microstate for pKa calculations.
15
+
16
+ :param smiles: SMILES string for this conformer
17
+ :param energy: free energy of this conformer
18
+ :param charge: the total charge
19
+ """
20
+
21
+ smiles: str
22
+ energy: Annotated[float, AfterValidator(round_float(3))] # free energy
23
+ charge: int
24
+
25
+
26
+ class MacropKaValue(Base):
27
+ """
28
+ Represents a change in pKa.
29
+
30
+ :param initial_charge: the charge of the initial state
31
+ :param final_charge: the charge of the final state
32
+ :param pKa: the pKa for the transition
33
+ """
34
+
35
+ initial_charge: int
36
+ final_charge: int
37
+ pKa: Annotated[float, AfterValidator(round_float(3))]
38
+
39
+
40
+ class MacropKaWorkflow(SMILESWorkflow):
41
+ """
42
+ Workflow for calculating pKa.
43
+
44
+ Inherited:
45
+ :param initial_smiles:
46
+
47
+ New:
48
+ :param temperature: the temperature, in K
49
+ :param min_pH: for precomputed microstate weights
50
+ :param max_pH: for precomputed microstate weights
51
+
52
+ Results:
53
+ :param microstates: microstates
54
+ :param pKa_values: macroscopic pKa values
55
+ :param microstate_weights_by_pH: precompute the % of different microstates
56
+ """
57
+
58
+ temperature: Annotated[float, AfterValidator(round_float(3))] = 298.0
59
+ min_pH: Annotated[float, AfterValidator(round_float(3))] = 0.0
60
+ max_pH: Annotated[float, AfterValidator(round_float(3))] = 14.0
61
+
62
+ microstates: list[MacropKaMicrostate] = []
63
+ pKa_values: list[MacropKaValue] = []
64
+ microstate_weights_by_pH: dict[float, Annotated[list[float], AfterValidator(round_list(6))]] = {}
65
+
66
+ @model_validator(mode="after")
67
+ def check_weights(self) -> Self:
68
+ for weights in self.microstate_weights_by_pH.values():
69
+ if len(weights) != len(self.microstates):
70
+ raise ValueError("Length of microstate weights doesn't match!")
71
+
72
+ return self
stjames/workflows/scan.py CHANGED
@@ -4,7 +4,7 @@ from typing import Annotated
4
4
 
5
5
  import numpy as np
6
6
  from numpy.typing import NDArray
7
- from pydantic import AfterValidator
7
+ from pydantic import AfterValidator, field_validator
8
8
 
9
9
  from ..base import Base, round_optional_float
10
10
  from ..molecule import Molecule
@@ -62,15 +62,33 @@ class ScanWorkflow(MoleculeWorkflow):
62
62
  :param mode: Mode for workflow (currently unused)
63
63
 
64
64
  New:
65
- :param scan_settings: information about what coordinate to scan
65
+ :param scan_settings: what coordinate(s) to scan; if more than one, all will be performed simultaneously and should have the same number of steps
66
+ :param scan_settings_2d: what additional coordinate(s) to scan; makes a grid with `scan_settings`
67
+ :param wavefront propagation: whether to use wavefront propagation (10.1063/5.0009232) for more expensive but smoother scans
66
68
  :param calc_settings: settings for the calculation
67
69
  :param calc_engine: engine to use for the calculation
68
70
  :param scan_points: points along the scan
69
71
  """
70
72
 
71
- scan_settings: ScanSettings
73
+ scan_settings: ScanSettings | list[ScanSettings]
74
+ scan_settings_2d: ScanSettings | list[ScanSettings] = []
72
75
  calc_settings: Settings
73
76
  calc_engine: str
74
77
 
78
+ wavefront_propagation: bool = True
79
+
75
80
  # UUIDs of scan points
76
81
  scan_points: list[UUID | None] = []
82
+
83
+ @field_validator("scan_settings", "scan_settings_2d", mode="after")
84
+ @classmethod
85
+ def validate_scan_settings(cls, val: ScanSettings | list[ScanSettings]) -> list[ScanSettings]:
86
+ """Ensure that scan_settings is a list, and that every list item has the same number of steps."""
87
+ if isinstance(val, ScanSettings):
88
+ val = [val]
89
+
90
+ for ss in val:
91
+ if ss.num != val[0].num:
92
+ raise ValueError("Concerted scan settings must have same number of steps!")
93
+
94
+ return val
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: stjames
3
- Version: 0.0.63
3
+ Version: 0.0.65
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
@@ -13,9 +13,9 @@ stjames/int_settings.py,sha256=5HXp8opt5ZyY1UpmfaK7NVloWVLM5jkG0elEEqpVLUo,896
13
13
  stjames/message.py,sha256=Rq6QqmHZKecWxYH8fVyXmuoCCPZv8YinvgykSeorXSU,216
14
14
  stjames/method.py,sha256=5hBHk2xQLpxZ52LwJ9FHWaqQMdFKnsbQEOxaVe6O4Go,2321
15
15
  stjames/mode.py,sha256=xw46Cc7f3eTS8i35qECi-8DocAlANhayK3w4akD4HBU,496
16
- stjames/molecule.py,sha256=UjJu5nA6IeV8rcO-Tnu3xBiNt2reUm9_3DLLCyxJF0M,14227
16
+ stjames/molecule.py,sha256=R0BalcXdvyhuyffoH11Nml_49qiVl4mD0dcGcLqfQYM,14371
17
17
  stjames/opt_settings.py,sha256=gxXGtjy9l-Q5Wen9eO6T6HHRCuS8rfOofdVQIJj0JcI,550
18
- stjames/pdb.py,sha256=-i0H029NEX-pcyCqdVyq7D62ZDvmUPWK7l83WdoDmpk,25759
18
+ stjames/pdb.py,sha256=YxJgheU37H74cAPjRcYS16Z_-fZo2Yel9V_trluYq9Q,25938
19
19
  stjames/periodic_cell.py,sha256=eV_mArsY_MPEFSrFEsTC-CyCc6V8ITAXdk7yhjjNI7M,1080
20
20
  stjames/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  stjames/scf_settings.py,sha256=WotVgVrayQ_8PUHP39zVtG7iLT9PV41lpzruttFACP8,2356
@@ -27,7 +27,7 @@ stjames/thermochem_settings.py,sha256=ZTLz31v8Ltutde5Nfm0vH5YahWjcfFWfr_R856Kffx
27
27
  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
- stjames/atomium_stjames/mmcif.py,sha256=llbJ65p2B-aZN31-E_ODVDmrVeBoSw9y_Mg5XjyQvTA,26755
30
+ stjames/atomium_stjames/mmcif.py,sha256=B5t_gxvMTG8OblXUWF0dnKgOHhn-8bufOv_a7ccbiqU,27081
31
31
  stjames/atomium_stjames/pdb.py,sha256=C2mEcBDDrnoXD9ZCMIH2uJpjiWPJy6ktXq8IFZsrQKM,22482
32
32
  stjames/atomium_stjames/utilities.py,sha256=-YtM7sRMvMk0wWrC3svWUWH4CGI0NtY77nXsg9tjHfc,4964
33
33
  stjames/data/__init__.py,sha256=O59Ksp7AIqwOELCWymfCx7YeBzwNOGCMlGQi7tNLqiE,24
@@ -37,8 +37,8 @@ stjames/data/isotopes.json,sha256=5ba8QnLrHD_Ypv2xekv2cIRwYrX3MQ19-1FOFtt0RuU,83
37
37
  stjames/data/nist_isotopes.json,sha256=d5DNk1dX0iB1waEYIRR6JMHuA7AuYwSBEgBvb4EKyhM,14300
38
38
  stjames/data/read_nist_isotopes.py,sha256=y10FNjW43QpC45qib7VHsIghEwT7GG5rsNwHdc9osRI,3309
39
39
  stjames/data/symbol_element.json,sha256=vl_buFusTqBd-muYQtMLtTDLy2OtBI6KkBeqkaWRQrg,1186
40
- stjames/workflows/__init__.py,sha256=5KX0IcuYElj8K3qE2c-XY8dL-vPdG87US7ErfZlyK88,2293
41
- stjames/workflows/admet.py,sha256=m8yGWe-UeYK5F7TOeNsQMPTzdWL-aaRSTQsyO7SVa6k,421
40
+ stjames/workflows/__init__.py,sha256=sHKzK6ZtVt8TkaX3JoIrg46SVK9rDi_elA7qCIAqBpE,2410
41
+ stjames/workflows/admet.py,sha256=h8ph6oeRCxU3-_jqRRWPg3RZcheu9JzCHiWqSC9VYKY,1296
42
42
  stjames/workflows/basic_calculation.py,sha256=ZX3KwhfyyCTjc2ougQIL4If7gtwZP9WjqpL45mBquW0,573
43
43
  stjames/workflows/bde.py,sha256=hdTjwma5L9SrU5F5r6dB1ruB_B6buBUtZHf2sanNW2k,9802
44
44
  stjames/workflows/conformer.py,sha256=18aO6ngMBeGAmQkBdLGCCHr398RIYr1v2hD2IT1u4cc,3005
@@ -48,18 +48,20 @@ stjames/workflows/docking.py,sha256=GCW_-JeEZcMXKZ9EQFOxWUYRo0jsbzwIv10aSz8KuaQ,
48
48
  stjames/workflows/electronic_properties.py,sha256=GT3-NC7w-dbcOJ-3AzJ7LgzH6frTbiH2Iyb9BCa-SvY,4112
49
49
  stjames/workflows/fukui.py,sha256=e7CF7Mp2Dt1JTipQx-Sz_37W1urL-iRpjXY-9ItSvhM,1268
50
50
  stjames/workflows/hydrogen_bond_basicity.py,sha256=XDpHEluw6DQ9Zk5g2Je2a81HqIkqPglZ-6f2YZnd4Bc,1159
51
+ stjames/workflows/ion_mobility.py,sha256=e6XSidrud5qSkrAcjzOzgHaf-G09JoP09V76myjdyjc,1097
51
52
  stjames/workflows/irc.py,sha256=ZP7icylW8rgo_Uh7h3bmyumn0ru1IyF-61nP5Jnmq3M,3402
53
+ stjames/workflows/macropka.py,sha256=d3jUKZIUU7ifcMCB6KuTEpP91Pl9sQA0WAmjnODbp6g,2058
52
54
  stjames/workflows/molecular_dynamics.py,sha256=kxugE73Ntzpj-xpJSoQ1EwGzXXdvi_NTyeP4913EVwE,3173
53
55
  stjames/workflows/multistage_opt.py,sha256=pPLAZDztHd37q8cxCUkdq8EzOFyrTzZJHNfDV5auiHs,13638
54
56
  stjames/workflows/pka.py,sha256=j3vBh2YM3nJzJ1XJKPsmYahRCeaU9n3P-G-u9_moaFw,2065
55
57
  stjames/workflows/redox_potential.py,sha256=7S18t9Y3eynSnA3lZbRlvLfdbgeBopdiigLzt1zxg5c,3871
56
- stjames/workflows/scan.py,sha256=vGS1wWMpMSogb63DEED6U6oHsLgV0D2hXVQg2UWWJgs,1913
58
+ stjames/workflows/scan.py,sha256=Lph2VhsxJMpzY-wtmUV7U1TOS7mIwjgkLniaipGDo8I,2899
57
59
  stjames/workflows/solubility.py,sha256=kGfVyPPGDLRpf2j6dSY7woCkfsoXSbUzdSImA4mcMpw,1898
58
60
  stjames/workflows/spin_states.py,sha256=0degmE-frovgoXweshZyjfjqL7nkbaFoO9YoJhvQnaI,4748
59
61
  stjames/workflows/tautomer.py,sha256=7eYKziGPg8Km6lfowTzSkgJfJ4SHUPrAmnTf8Bi-SB0,1164
60
62
  stjames/workflows/workflow.py,sha256=sk2BUz59wdIkT_EyKOnMt5woNrjo3aHVK38cU8x8I7Q,1423
61
- stjames-0.0.63.dist-info/LICENSE,sha256=i7ehYBS-6gGmbTcgU4mgk28pyOx2kScJ0kcx8n7bWLM,1084
62
- stjames-0.0.63.dist-info/METADATA,sha256=PlYrd27UJROPiSqNv6i1XqW-Kbvpk9h5Tcw3PDMqOnc,1672
63
- stjames-0.0.63.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
64
- stjames-0.0.63.dist-info/top_level.txt,sha256=FYCwxl6quhYOAgG-mnPQcCK8vsVM7B8rIUrO-WrQ_PI,8
65
- stjames-0.0.63.dist-info/RECORD,,
63
+ stjames-0.0.65.dist-info/LICENSE,sha256=i7ehYBS-6gGmbTcgU4mgk28pyOx2kScJ0kcx8n7bWLM,1084
64
+ stjames-0.0.65.dist-info/METADATA,sha256=OQsAzZU4ZxSwkHhpyaHaiI-3SvcHB5VS_nDKKlv-3FM,1672
65
+ stjames-0.0.65.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
66
+ stjames-0.0.65.dist-info/top_level.txt,sha256=FYCwxl6quhYOAgG-mnPQcCK8vsVM7B8rIUrO-WrQ_PI,8
67
+ stjames-0.0.65.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (76.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5