Source code for schrodinger.rdkit.alignment
from math import ceil
import numpy
from rdkit.Chem import Conformer
from rdkit.Chem import rdMolTransforms
from rdkit.Chem.rdchem import Mol
from rdkit.Chem.rdCoordGen import AddCoords
from scipy.spatial.transform import Rotation
[docs]def get_height(conformer: Conformer) -> float:
"""
:param conformer: a conformer with nonzero coordinates
:return: the maximum y-axis distance between positions of the conformer
"""
pos = conformer.GetPositions()
return pos[:, 1].max() - pos[:, 1].min()
[docs]def rotate_2D(conformer: Conformer, rot_angle: float):
"""
Rotate a conformer clockwise around the z axis.
:param conformer: a conformer with nonzero coordinates
:param rot_angle: the angle at which to rotate the conformer (clockwise in
around the z axis, in degrees)
"""
rot = Rotation.from_euler(seq='z', angles=rot_angle, degrees=True)
transform_conformer(conformer, rot.as_matrix())
[docs]def align_horizontally(conformer: Conformer):
"""
Rotate the specified conformer to minimize its height.
:param conformer: a conformer with nonzero coordinates
:note: this optimization is performed over a limited number of possible
angles in order to preserve aesthetically-pleasing bond angles
generated for this conformer by `Chem.rdCoordGen`
"""
degrees_per_rotation = 30
max_rotation_count = ceil(90 / degrees_per_rotation) + 1
conf_copy = Conformer(conformer)
min_height = get_height(conf_copy)
min_height_angle = 0
for rotation_count in range(1, max_rotation_count):
rotate_2D(conf_copy, rot_angle=degrees_per_rotation)
height = get_height(conf_copy)
if height < min_height:
min_height = height
min_height_angle = rotation_count * degrees_per_rotation
rotate_2D(conformer, rot_angle=min_height_angle)
[docs]def generate_min_height_coords(mol: Mol):
"""
Clear the existing conformers of the input `Mol` object and generate one
such that its height (greatest y-axis distance between two points) is
minimized to some extent.
:param mol: input RDKit molecule object
"""
AddCoords(mol)
align_horizontally(mol.GetConformer())