Skip to content

Commit

Permalink
Merge pull request #35 from pnnl/develop
Browse files Browse the repository at this point in the history
Update to rdkit md default
  • Loading branch information
jessbade authored Apr 30, 2024
2 parents e828c62 + d8fd694 commit ba0fc28
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 88 deletions.
18 changes: 9 additions & 9 deletions isicle/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def __init__(self, **kwargs):
self.__dict__.update(dict.fromkeys(self._defaults, self._default_value))
self.__dict__.update(kwargs)

def _is_embedded(self):
def _is_embedded(self, mol):
"""
Check if molecule has embedded 3D coordinates.
Expand All @@ -311,7 +311,7 @@ def _is_embedded(self):
"""

try:
self.mol.GetConformers()
mol.GetConformer().Is3D()
return True
except:
return False
Expand Down Expand Up @@ -386,17 +386,17 @@ def _forcefield_selector(forcefield, mw):
# Embed molecule 3D coordinates
if embed is True:
# Attempt embedding
try:
Chem.AllChem.EmbedMolecule(mol)

# Use random coordinates
except:
Chem.AllChem.EmbedMolecule(mol, useRandomCoords=True)
res = Chem.AllChem.EmbedMolecule(mol)
if res == -1:
# Use random coordinates
res = Chem.AllChem.EmbedMolecule(mol, useRandomCoords=True)
if res == -1:
raise ValueError("Embedding failure.")

# Optimize according to supplied forcefield
if forcefield is not None:
# Check if embedded
if self._is_embedded():
if self._is_embedded(mol):
# Forcefield selection
if "mmff94s" in forcefield.lower():
_forcefield_selector(forcefield, mol)(
Expand Down
6 changes: 4 additions & 2 deletions isicle/md.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ def set_geometry(self, geom):
self.geom = geom
self.basename = self.geom.basename

def configure(self, method: str = "distance", numConfs: int = 10, **kwargs):
def configure(self, method: str = "etkdgv3", numConfs: int = 10, **kwargs):
"""
Set conformer generation parameters.
Parameters
Expand Down Expand Up @@ -600,12 +600,14 @@ def _configure_etkdg2(self):
"""
self.params = rdDistGeom.ETKDGv2()

def _configure_etkdg3(self):
def _configure_etkdg3(self, variant=True):
"""
Set parameters for ETKDG conformer generation, based on work by Riniker and Landrum.
Version 3: Updated sampling small rings AND macrocycles
"""
self.params = rdDistGeom.ETKDGv3()
if variant is True:
self.params.useSmallRingTorsions = True

def _configure_etkdg3_variant(self):
"""
Expand Down
151 changes: 74 additions & 77 deletions tests/test_conformers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,140 +26,137 @@ def random_energies():

@pytest.fixture()
def conformers():
x = [isicle.geometry.load(localfile('resources/geom_test.mol'))
for i in range(30)]
x = [isicle.geometry.load(localfile("resources/geom_test.mol")) for i in range(30)]
return isicle.conformers.ConformationalEnsemble(x)


@pytest.mark.parametrize('func,expected',
[('boltzmann', isicle.conformers.boltzmann),
('simple', isicle.conformers.simple_average),
('lowest', isicle.conformers.lowest_energy),
('threshold', isicle.conformers.threshold)])
@pytest.mark.parametrize(
"func,expected",
[
("boltzmann", isicle.conformers.boltzmann),
("simple", isicle.conformers.simple_average),
("lowest", isicle.conformers.lowest_energy),
("threshold", isicle.conformers.energy_threshold),
],
)
def test__function_selector(func, expected):
# Check correct class is yielded
assert isicle.conformers._function_selector(func) == expected


@pytest.mark.parametrize('func',
[('boltzman'),
('smple'),
('lowest-energy'),
('thresh')])
@pytest.mark.parametrize(
"func", [("boltzman"), ("smple"), ("lowest-energy"), ("thresh")]
)
def test__function_selector_fail(func):
# Check unsupported selections
with pytest.raises(ValueError):
isicle.conformers._function_selector(func)


@pytest.mark.parametrize('func,expected',
[(isicle.conformers.boltzmann, True),
(isicle.conformers.simple_average, False),
(isicle.conformers.lowest_energy, True),
(isicle.conformers.threshold, True)])
@pytest.mark.parametrize(
"func,expected",
[
(isicle.conformers.boltzmann, True),
(isicle.conformers.simple_average, False),
(isicle.conformers.lowest_energy, True),
(isicle.conformers.energy_threshold, True),
],
)
def test__energy_based(func, expected):
assert isicle.conformers._energy_based(func) is expected


def test_reduce(random_values, random_energies):
result = isicle.conformers.reduce(random_values,
func='boltzmann',
energy=random_energies,
index=None)
result = isicle.conformers.reduce(
random_values, func="boltzmann", energy=random_energies, index=None
)

assert abs(result['mean'] - 670.505) < 1E-3
assert abs(result['std'] - 26.566) < 1E-3
assert result['n'] == 30
assert abs(result["mean"] - 670.505) < 1e-3
assert abs(result["std"] - 26.566) < 1e-3
assert result["n"] == 30


@pytest.mark.parametrize('index',
[(None)])
@pytest.mark.parametrize("index", [(None)])
def test_boltzmann(random_values, random_energies, index):
result = isicle.conformers.boltzmann(random_values,
random_energies,
index=index)
result = isicle.conformers.boltzmann(random_values, random_energies, index=index)

assert abs(result['mean'] - 670.505) < 1E-3
assert abs(result['std'] - 26.566) < 1E-3
assert result['n'] == 30
assert abs(result["mean"] - 670.505) < 1e-3
assert abs(result["std"] - 26.566) < 1e-3
assert result["n"] == 30


@pytest.mark.parametrize('index',
[(None)])
@pytest.mark.parametrize("index", [(None)])
def test_simple_average(random_values, index):
result = isicle.conformers.simple_average(random_values,
index=index)
result = isicle.conformers.simple_average(random_values, index=index)

assert abs(result['mean'] - 451.660) < 1E-3
assert abs(result['std'] - 276.717) < 1E-3
assert result['n'] == 30
assert abs(result["mean"] - 451.660) < 1e-3
assert abs(result["std"] - 276.717) < 1e-3
assert result["n"] == 30


@pytest.mark.parametrize('index',
[(None)])
@pytest.mark.parametrize("index", [(None)])
def test_lowest_energy(random_values, random_energies, index):
result = isicle.conformers.lowest_energy(random_values,
random_energies,
index=index)
result = isicle.conformers.lowest_energy(
random_values, random_energies, index=index
)

assert abs(result['value'] - 667.237) < 1E-3
assert abs(result['energy'] - 0.016) < 1E-3
assert abs(result["value"] - 667.237) < 1e-3
assert abs(result["energy"] - 0.016) < 1e-3


@pytest.mark.parametrize('index',
[(None)])
@pytest.mark.parametrize("index", [(None)])
def test_threshold(random_values, random_energies, index):
result = isicle.conformers.threshold(random_values,
random_energies,
threshold=0.5,
index=index)

assert abs(result['mean'] - 414.716) < 1E-3
assert abs(result['std'] - 289.999) < 1E-3
assert result['n'] == 15


@pytest.mark.parametrize('objects',
[([Geometry(), Geometry(), Geometry()]),
([XYZGeometry(), XYZGeometry(), Geometry()])])
result = isicle.conformers.energy_threshold(
random_values, random_energies, threshold=0.5, index=index
)

assert abs(result["mean"] - 414.716) < 1e-3
assert abs(result["std"] - 289.999) < 1e-3
assert result["n"] == 15


@pytest.mark.parametrize(
"objects",
[
([Geometry(), Geometry(), Geometry()]),
([XYZGeometry(), XYZGeometry(), Geometry()]),
],
)
def test_build_conformational_ensemble(objects):
isicle.conformers.build_conformational_ensemble(objects)


@pytest.mark.parametrize('objects',
[([Geometry(), 'abc', Geometry()]),
([XYZGeometry(), Geometry(), list()])])
@pytest.mark.parametrize(
"objects",
[([Geometry(), "abc", Geometry()]), ([XYZGeometry(), Geometry(), list()])],
)
def test_build_conformational_ensemble_fail(objects):
with pytest.raises(TypeError):
isicle.conformers.build_conformational_ensemble(objects)


class TestConformationalEnsemble:

@pytest.mark.parametrize('index',
[(False)])
@pytest.mark.parametrize("index", [(False)])
def test_reduce(self, conformers, random_values, random_energies, index):
# Set values
for c, v, e in zip(conformers, random_values, random_energies):
c.global_properties = {'dummy': v, 'energy': {'energy': [e]}}
c.global_properties = {"dummy": v, "energy": {"energy": [e]}}

# Reduce attribute
result = conformers.reduce('dummy', func='boltzmann')
result = conformers.reduce("dummy", func="boltzmann")

# Verify result
assert abs(result['mean'] - 670.505) < 1E-3
assert abs(result['std'] - 26.566) < 1E-3
assert result['n'] == 30
assert abs(result["mean"] - 670.505) < 1e-3
assert abs(result["std"] - 26.566) < 1e-3
assert result["n"] == 30

def test__apply_method(self, conformers):
result = conformers._apply_method('get_natoms')
result = conformers._apply_method("get_natoms")
assert all(x == 2 for x in result)

def test__apply_function(self, conformers):
result = conformers._apply_function(isicle.qm.dft,
program='NWChem',
fmt='xyz')
result = conformers._apply_function(isicle.qm.dft, program="NWChem", fmt="xyz")

def test_apply(self, conformers):
result = conformers.apply(method='get_natoms')
result = conformers.apply(method="get_natoms")
assert all(x == 2 for x in result)

0 comments on commit ba0fc28

Please sign in to comment.