Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure the position contraint in strain calculation works #7

Merged
merged 2 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
posecheck.egg-info/*
.vscode/*
# Distribution / packaging
*.egg-info/
posecheck/__pycache__/*.pyc
*/*/__pycache__/
48 changes: 44 additions & 4 deletions posecheck/utils/strain.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ def calculate_energy(
except Exception:
return np.nan

energy = ff.CalcEnergy()
try:
energy = ff.CalcEnergy()
except:
return np.nan

return energy

Expand Down Expand Up @@ -64,7 +67,7 @@ def relax_constrained(
return np.nan

for i in range(mol.GetNumAtoms()):
ff.UFFAddPositionConstraint(i, maxDispl=maxDispl, forceConstant=1)
ff.UFFAddPositionConstraint(i, maxDispl=maxDispl, forceConstant=1.0e5)


try:
Expand Down Expand Up @@ -102,10 +105,45 @@ def relax_global(mol: Chem.Mol) -> Chem.Mol:
AllChem.EmbedMolecule(mol)

# optimize the molecule
AllChem.UFFOptimizeMolecule(mol)
try:
AllChem.UFFOptimizeMolecule(mol)
except:
return None

# return the molecule
return mol

def relax_global_on_pose(mol: Chem.Mol) -> Chem.Mol:
"""Relax the given pose without position constraints by adding hydrogens and optimizing it
using the UFF force field.

Args:
mol (Chem.Mol): The molecule to relax.

Returns:
Chem.Mol: The relaxed molecule.
"""

# if the molecule is None, return None
if mol is None:
return None

# Incase ring info is not present
Chem.GetSSSR(mol) # SSSR: Smallest Set of Smallest Rings

# make a copy of the molecule
mol = deepcopy(mol)

# add hydrogens
mol = Chem.AddHs(mol, addCoords=True)

# optimize the molecule
try:
AllChem.UFFOptimizeMolecule(mol)
except:
return None

return mol

def calculate_strain_energy(mol: Chem.Mol, maxDispl: float = 0.1, num_confs: int = 50) -> float:
"""Calculate the strain energy of a molecule.
Expand All @@ -127,12 +165,14 @@ def calculate_strain_energy(mol: Chem.Mol, maxDispl: float = 0.1, num_confs: int
locally_relaxed = relax_constrained(mol, maxDispl=maxDispl)
# sample and minimize n conformers
global_relaxed = [relax_global(mol) for i in range(num_confs)]
# alleviate insufficient sampling
global_relaxed.append(relax_global_on_pose(mol))

# calculate the energy of the locally relaxed molecule
local_energy = calculate_energy(locally_relaxed)

# calculate the energy of the globally relaxed molecules and take the minimum
global_energy = min([calculate_energy(mol) for mol in global_relaxed])
global_energy = min([calculate_energy(mol) for mol in global_relaxed if mol is not None])

# calculate the strain energy
strain_energy = local_energy - global_energy
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ datamol
#openbabel

# Data
pandas
pandas==2.0.0
seaborn
matplotlib
numpy
Loading