Source code for schrodinger.ui.sketcher_extensions
from schrodinger.forcefield import OPLSVersion
from schrodinger.structutils import minimize
from schrodinger.thirdparty import rdkit_adapter
CONSTRAINT_FORCE_CONSTANT = 200.0
COORDINATES_LIMIT = 10000000.0
[docs]def get_2D_structure(sketcher):
"""
:param sketcher: given sketcher instance
:return: extracted Structure object with sketcher-generated 2D coordinates
"""
rdmol = sketcher.getRDKitStructure()
return rdkit_adapter.from_rdkit(rdmol)
[docs]def get_3D_structure(sketcher):
"""
:param sketcher: given sketcher instance
:return: extracted Structure object with sketcher-generated 3D coordinates
:raises RuntimeError: if 3D coordinates are not available
"""
rdmol = sketcher.getRDKitStructure()
if rdmol.GetNumConformers() < 2:
raise RuntimeError("No 3D coordinates available")
# 3D coordinates should be in the second conformer
st = rdkit_adapter.from_rdkit(rdmol, conformer=1)
# mmffld minization has a hard time with many atoms overlapping
# at the same position; update atoms with invalid coordinates
# to the 2D coordinates generated by the sketcher, and freeze all others
fixed_atom_indices = []
st_2d = get_2D_structure(sketcher)
for atom in st.atom:
if any(c > COORDINATES_LIMIT for c in (atom.x, atom.y, atom.z)):
atom.xyz = st_2d.atom[atom.index].xyz
else:
fixed_atom_indices.append(atom.index)
if len(fixed_atom_indices) == st.atom_total:
return st
minimizer = minimize.Minimizer(ffld_version=OPLSVersion.F16,
struct=st,
honor_pbc=False,
nonbonded_cutoff=10.0)
for index in fixed_atom_indices:
minimizer.addPosRestraint(index,
force_constant=CONSTRAINT_FORCE_CONSTANT)
minimizer.minimize()
return st
[docs]def set_structure(sketcher, st):
"""
:param sketcher: given sketcher instance
:param st: Structure to set into the sketcher
"""
rdmol = rdkit_adapter.to_rdkit(st, implicitH=True, sanitize=False)
sketcher.clearStructure()
sketcher.setStructure(rdmol)