Skip to content

Commit eaa273a

Browse files
committed
handle for clashing embedding and minimisation
1 parent b323715 commit eaa273a

File tree

4 files changed

+49
-34
lines changed

4 files changed

+49
-34
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.poetry]
22
name = "jazzy"
3-
version = "0.1.1"
4-
description = "Jazzy"
3+
version = "0.1.2"
4+
description = "Jazzy allows calculating a set of atomic/molecular descriptors including the Gibbs free energy of hydration (kJ/mol), its polar/apolar components, and the hydrogen-bond strength of donor and acceptor atoms."
55
authors = ["Gian Marco Ghiandoni <[email protected]>", "Eike Caldeweyher <[email protected]>"]
66
license = "Apache-2.0"
77
readme = "README.rst"

src/jazzy/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
MINIMISATION_METHOD = None
55
ROUNDING_DIGITS = 4
66
ANNOTATION_FONT_SCALE = 0.7
7+
EMBEDDING_TYPES = ("2D", "3D")
78

89

910
class Config(object):

src/jazzy/core.py

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from rdkit.Chem import rdMolDescriptors
1818
from rdkit.Chem.rdchem import Mol
1919

20+
from jazzy.config import EMBEDDING_TYPES
2021
from jazzy.config import ROUNDING_DIGITS
2122
from jazzy.exception import EmbeddingError
2223
from jazzy.exception import KallistoError
@@ -47,10 +48,6 @@ def rdkit_molecule_from_smiles(
4748
Returns:
4849
An RDKit molecule (rdkit.Chem.rdchem.Mol) or None if the process fails
4950
50-
Raises:
51-
ValueError: If 'minimisation_method' does not correspond to one of the
52-
available methods.
53-
5451
"""
5552
# create molecule, add hydrogens
5653
m = Chem.MolFromSmiles(smiles)
@@ -66,29 +63,19 @@ def rdkit_molecule_from_smiles(
6663
return None
6764

6865
# energy minimisation
69-
valid_methods = [None, "MMFF94", "MMFF94s", "UFF"]
70-
if minimisation_method is not None:
71-
if minimisation_method not in valid_methods:
72-
raise ValueError(f"Select a valid minimisation method {valid_methods}")
73-
if minimisation_method == valid_methods[1]:
74-
AllChem.MMFFOptimizeMolecule(mh)
75-
if minimisation_method == valid_methods[2]:
76-
AllChem.MMFFOptimizeMolecule(mh, mmffVariant="MMFF94s")
77-
if minimisation_method == valid_methods[3]:
78-
AllChem.UFFOptimizeMolecule(mh)
66+
_minimise_molecule(mh, minimisation_method, **kwargs)
7967
return mh
8068

8169

82-
def _embed_molecule(rdkit_molecule: Chem.rdchem.Mol, **kwargs) -> None:
70+
def _embed_molecule(rdkit_molecule: Mol, **kwargs) -> None:
8371
"""Molecule embedding using either the 2D or 3D method."""
8472
embedding_type = kwargs.get("embedding_type", "3D")
8573
embedding_seed = kwargs.get("embedding_seed", 11)
86-
valid_types = ["2D", "3D"]
87-
if embedding_type not in valid_types:
88-
raise ValueError(f"Select a valid embedding type {valid_types}")
89-
if embedding_type == valid_types[0]:
74+
if embedding_type not in EMBEDDING_TYPES:
75+
raise ValueError(f"Select a valid embedding type {EMBEDDING_TYPES}")
76+
if embedding_type == EMBEDDING_TYPES[0]:
9077
AllChem.Compute2DCoords(rdkit_molecule, sampleSeed=embedding_seed)
91-
if embedding_type == valid_types[1]:
78+
if embedding_type == EMBEDDING_TYPES[1]:
9279
params = (
9380
rdDistGeom.ETDG()
9481
) # ETDG over others as it seems produce fewer failures
@@ -105,7 +92,26 @@ def _embed_molecule(rdkit_molecule: Chem.rdchem.Mol, **kwargs) -> None:
10592
raise EmbeddingError(error_msg)
10693

10794

108-
def get_covalent_atom_idxs(rdkit_molecule: Chem.rdchem.Mol) -> list:
95+
def _minimise_molecule(rdkit_molecule: Mol, minimisation_method: str, **kwargs) -> None:
96+
"""Minimise the energy of a molecule. Only works for 3D molecules."""
97+
valid_methods = (None, "MMFF94", "MMFF94s", "UFF")
98+
if not minimisation_method:
99+
return
100+
embedding_type = kwargs.get("embedding_type", "3D")
101+
if embedding_type == EMBEDDING_TYPES[0]:
102+
logger.warning("Energy minimisation is not supported for 2D molecules.")
103+
return
104+
if minimisation_method == valid_methods[1]:
105+
AllChem.MMFFOptimizeMolecule(rdkit_molecule)
106+
elif minimisation_method == valid_methods[2]:
107+
AllChem.MMFFOptimizeMolecule(rdkit_molecule, mmffVariant="MMFF94s")
108+
elif minimisation_method == valid_methods[3]:
109+
AllChem.UFFOptimizeMolecule(rdkit_molecule)
110+
else:
111+
raise ValueError(f"Select a valid minimisation method {valid_methods}")
112+
113+
114+
def get_covalent_atom_idxs(rdkit_molecule: Mol) -> list:
109115
"""Get covalent indices for atom_idx.
110116
111117
Creates a list of lists, where indices are atom indices and the content
@@ -120,7 +126,7 @@ def get_covalent_atom_idxs(rdkit_molecule: Chem.rdchem.Mol) -> list:
120126
return atoms_and_idxs
121127

122128

123-
def get_all_neighbours(rdkit_molecule: Chem.rdchem.Mol, molecule_covalent_nbrs: list):
129+
def get_all_neighbours(rdkit_molecule: Mol, molecule_covalent_nbrs: list):
124130
"""Get all alpha, beta, and gamma neighbours.
125131
126132
Create dictionaries for covalent bonding partner (alpha), all nearest
@@ -147,7 +153,7 @@ def get_all_neighbours(rdkit_molecule: Chem.rdchem.Mol, molecule_covalent_nbrs:
147153
return alpha, beta, gamma
148154

149155

150-
def kallisto_molecule_from_rdkit_molecule(rdkit_molecule: Chem.rdchem.Mol) -> Molecule:
156+
def kallisto_molecule_from_rdkit_molecule(rdkit_molecule: Mol) -> Molecule:
151157
"""Create a kallisto molecule from RDKit molecule.
152158
153159
Args:
@@ -215,7 +221,7 @@ def get_charges_from_kallisto_molecule(
215221

216222

217223
def calculate_polar_strength_map(
218-
rdkit_molecule: Chem.rdchem.Mol,
224+
rdkit_molecule: Mol,
219225
kallisto_molecule: Molecule,
220226
atoms_and_nbrs: list,
221227
charges: list,
@@ -442,7 +448,7 @@ def _calculate_q_delta(q_alpha, q_beta, q_gamma, t):
442448

443449

444450
def calculate_delta_apolar(
445-
rdkit_molecule: Chem.rdchem.Mol,
451+
rdkit_molecule: Mol,
446452
mol_map: dict,
447453
g0: float,
448454
gs: float,
@@ -633,7 +639,7 @@ def interaction_strength(idx: int, mol_map: dict, acceptor_exp: float) -> float:
633639

634640

635641
def calculate_delta_interaction(
636-
rdkit_molecule: Chem.rdchem.Mol,
642+
rdkit_molecule: Mol,
637643
mol_map: dict,
638644
atoms_and_nbrs: list,
639645
gi: float,

tests/test_rdkit.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Test cases for the rdkit methods."""
22
import pytest
3+
from rdkit.Chem.rdchem import Mol
34

45
from jazzy.core import get_all_neighbours
56
from jazzy.core import get_covalent_atom_idxs
@@ -62,25 +63,32 @@ def test_minimisation_works_for_valid_method() -> None:
6263

6364
def test_invalid_minimisation_method() -> None:
6465
"""It exits with a ValueError when an invalid method is entered."""
65-
with pytest.raises(Exception):
66+
with pytest.raises(ValueError):
6667
smiles = "CC"
6768
minimisation_method = "MMFF95"
68-
m = rdkit_molecule_from_smiles(
69+
rdkit_molecule_from_smiles(
6970
smiles=smiles,
7071
minimisation_method=minimisation_method,
7172
)
72-
assert m is None
7373

7474

7575
def test_invalid_embedding_type() -> None:
7676
"""It exits with a ValueError when an invalid method is entered."""
77-
with pytest.raises(Exception):
77+
with pytest.raises(ValueError):
7878
smiles = "CC"
79-
m = rdkit_molecule_from_smiles(
79+
rdkit_molecule_from_smiles(
8080
smiles=smiles,
8181
embedding_type="4d",
8282
)
83-
assert m is None
83+
84+
85+
def test_warning_2d_embedding_with_minimisation() -> None:
86+
"""It ignores the clash between 2D embedding and energy minimisation."""
87+
smiles = "CC"
88+
m = rdkit_molecule_from_smiles(
89+
smiles=smiles, embedding_type="2D", minimisation_method="MMFF94"
90+
)
91+
assert isinstance(m, Mol)
8492

8593

8694
def test_embedding_fails_with_fewer_iterations() -> None:

0 commit comments

Comments
 (0)