"""
Functions for computing medchem properties.
To add a new property to be calculated simply add another tuple to the
properties list. To remove a property, remove its tuple from the properties
list.
Copyright Schrodinger, LLC. All rights reserved
"""
# Contributors: Dave Giesen, January 2010
import schrodinger.application.canvas.utils as canvasutils
import schrodinger.structutils.analyze as analyze
import schrodinger.structutils.smiles as smiles
from schrodinger.infra import canvas
_version = 0.10
# Some of these calculations need a canvas license.
canvas_license = canvasutils.get_license(canvasutils.LICENSE_SHARED)
################################################################################
# Property Function calculation routines
# Each property calculation function should accept as arguments in
# this order:
# The structure object
# The program abbreviation
# The property name
# The ChmMol object
# *args (so any future additional arguments are ignored)
# Any additional argument needed for any new properties added to the
# list should be added at the end of the list just before *args
#
# This argument structure allows all routines to be called in a consistent
# manner, meaning very little needs to be changed (only the properties list)
# in order to add, subtract or edit the properties calculated.
#
# Each routine should return the property value and the key used to store
# that property value in the structure.property dictionary
[docs]def compute_title(structure, program, name, *args):
"""
Returns the title of the structure.
:type structure: schrodinger.structure.Structure object
:param structure: structure object to run the calculation on
:type program: str
:param program: abbreviation of the program running this calculation, for
purposes of creating the key to store the calculation in
`structure.property['r_"program"_"name"']`
:type name: str
:param name: name of the property when storing the calculation in
`structure.property['r_"program"_"name"]`
:rtype: str, str
:return: Title of the structure, structure.property key
"""
propname = '_'.join(['s', program, name])
structure.property[propname] = structure.title
return structure.title, propname
[docs]def compute_mw(structure, program, name, *args):
"""
Returns the molecular weight of the structure.
:type structure: schrodinger.structure.Structure object
:param structure: structure object to run the calculation on
:type program: str
:param program: abbreviation of the program running this calculation, for
purposes of creating the key to store the calculation in
`structure.property['r_"program"_"name"']`
:type name: str
:param name: name of the property when storing the calculation in
`structure.property['r_"program"_"name"]`
:rtype: float, str
:return: Molecular weight of the structure, structure.property key
"""
propname = '_'.join(['r', program, name])
structure.property[propname] = structure.total_weight
return structure.total_weight, propname
[docs]def compute_alogp(structure, program, name, mol, *args):
"""
Returns the ALogP of the structure and stores it in structure.property
:type structure: schrodinger.structure.Structure object
:param structure: structure object to run the calculation on
:type program: str
:param program: abbreviation of the program running this calculation, for
purposes of creating the key to store the calculation in
`structure.property['r_"program"_"name"']`
:type name: str
:param name: name of the property when storing the calculation in
`structure.property['r_"program"_"name"]`
:type mol: ChmMol object
:param structure: ChmMol object to run the calculation on
:rtype: float, str
:return: ALogP of the structure, structure.property key
"""
logp_calc = canvas.ChmAtomTyperAlogP()
alogp = logp_calc.calculateScalar(mol)
propname = '_'.join(['r', program, name])
structure.property[propname] = alogp
return alogp, propname
[docs]def compute_polar_surf_area(structure, program, name, mol, *args):
"""
Returns the polar surface area of the structure and stores it in
structure.property
:type structure: schrodinger.structure.Structure object
:param structure: structure object to store the calculation on
:type mol: ChmMol object
:param structure: ChmMol object to run the calculation on
:type program: str
:param program: abbreviation of the program running this calculation, for
purposes of creating the key to store the calculation in
`structure.property['r_"program"_"name"']`
:type name: str
:param name: name of the property when storing the calculation in
`structure.property['r_"program"_"name"']`
:rtype: int, str
:return: Polar Surface Area of the structure, structure.property key
"""
polar_calc = canvas.ChmAtomTyperPSA()
psa = polar_calc.calculateScalar(mol)
propname = '_'.join(['r', program, name])
structure.property[propname] = psa
return psa, propname
[docs]def compute_num_rot_bonds(structure, program, name, *args):
"""
Returns the number of rotatable bonds in the structure and stores it in
structure.property
:type structure: schrodinger.structure.Structure object
:param structure: structure object to run the calculation on
:type program: str
:param program: abbreviation of the program running this calculation, for
purposes of creating the key to store the calculation in
`structure.property['i_"program"_"name"']`
:type name: str
:param name: name of the property when storing the calculation in
`structure.property['i_"program"_"name"']`
:rtype: float, str
:return: Number of Rotatable Bonds in the structure, structure.property key
"""
num_rot_bonds = analyze.get_num_rotatable_bonds(structure)
propname = '_'.join(['i', program, name])
structure.property[propname] = num_rot_bonds
return num_rot_bonds, propname
[docs]def compute_num_hbond_donors(structure, program, name, mol, *args):
"""
Returns the number of HBond donors in the structure and stores it in
structure.property
:type structure: schrodinger.structure.Structure object
:param structure: structure object to store the calculation on
:type mol: ChmMol object
:param structure: ChmMol object to run the calculation on
:type program: str
:param program: abbreviation of the program running this calculation, for
purposes of creating the key to store the calculation in
`structure.property['i_"program"_"name"']`
:type name: str
:param name: name of the property when storing the calculation in
`structure.property['i_"program"_"name"']`
:rtype: int, str
:return: number of Hbond donors in the structure, structure.property key
"""
# H-bond donors and acceptors code from EV95528
hbond_calc = canvas.ChmHbond()
hbond_calc.assignDonors(mol)
donors = 0
for i in range(mol.getAtomCount()):
if hbond_calc.isDonor(i):
donors += 1
propname = '_'.join(['i', program, name])
structure.property[propname] = donors
return donors, propname
[docs]def compute_num_hbond_acceptors(structure, program, name, mol, *args):
"""
Returns the number of HBond acceptors in the structure and stores it in
structure.property
:type structure: schrodinger.structure.Structure object
:param structure: structure object to store the calculation on
:type mol: ChmMol object
:param structure: ChmMol object to run the calculation on
:type program: str
:param program: abbreviation of the program running this calculation, for
purposes of creating the key to store the calculation in
`structure.property['i_"program"_"name"']`
:type name: str
:param name: name of the property when storing the calculation in
`structure.property['i_"program"_"name"']`
:rtype: int, str
:return: number of Hbond acceptors in the structure, structure.property key
"""
# H-bond donors and acceptors code from EV95528
hbond_calc = canvas.ChmHbond()
hbond_calc.assignAcceptors(mol)
accepts = 0
for i in range(mol.getAtomCount()):
if hbond_calc.isAcceptor(i):
accepts += 1
propname = '_'.join(['i', program, name])
structure.property[propname] = accepts
return accepts, propname
[docs]def compute_smiles(structure, program, name, *args):
"""
Returns the SMILES string for the structure and stores it in
structure.property
:type structure: schrodinger.structure.Structure object
:param structure: structure object to run the calculation on
:type program: str
:param program: abbreviation of the program running this calculation, for
purposes of creating the key to store the calculation in
`structure.property['s_"program"_"name"']`
:type name: str
:param name: name of the property when storing the calculation in
`structure.property['s_"program"_"name"]`
:rtype: str, str
:return: SMILES string for the structure, structure.property key
"""
smiles_calc = smiles.SmilesGenerator()
my_smiley = smiles_calc.getSmiles(structure)
propname = '_'.join(['s', program, name])
structure.property[propname] = my_smiley
return my_smiley, propname
#
# End of property calculation functions
################################################################################
# properties is a list of tuples. Each tuple contains the name of a property to
# calculate and the function to do the calculation. The first two properties
# are a bit different, as they use properties already calculated for the
# structure, so do not store any data on the structure object.
#
# To add a new property or modify an existing one, simply add another tuple or
# modify an existing tuple. If adding a property, a function to calculate that
# property must be added. No other change should be necessary, although see the
# comments in the compute_medchem_properties function about function parameters.
#properties = [('Title', compute_title),
properties = [('Molecular Weight', compute_mw), ('ALogP', compute_alogp),
('Polar Surface Area', compute_polar_surf_area),
('Rotatable Bonds', compute_num_rot_bonds),
('Hbond Donors', compute_num_hbond_donors),
('Hbond Acceptors', compute_num_hbond_acceptors),
('SMILES', compute_smiles)]
[docs]def compute_medchem_properties(structure, program="mpc"):
"""
Calculates the medchem molecular properties for the structure
:type structure: schrodinger.structure.Structure class object
:param structure: structure to compute properties of
:type program: str
:param program: Abbreviation of the program running this calculation, so
that the result of the calculation is stored properly in the
structure.property dictionary, which uses keys of the form
"type_program_property".
:rtype: list
:return: A list of results, each member of the list is a tuple of the form
(diplay property name, property value, key), where key is the key used to
store the property value in the structure.property dictionary
"""
results = []
# Create a ChmMol object for easy canvas calculations.
# Code was adapted from structure.py, the canvas API,
# and reading canvas.py
adaptor = canvas.ChmMmctAdaptor()
mol = adaptor.create(structure.handle, canvas.ChmMmctAdaptor.NoStereo)
# mol is now a pointer that can be used by ChmHbond
for name, func in properties:
# Each property calculation function should accept as arguments in
# this order:
# The structure object
# The program abbreviation
# The property name
# The ChmMol object
# *args
# Any additional argument needed for any new properties added to the
# list should be added at the end of the list just before *args
uname = name.replace(" ", "_")
value, key = func(structure, program, uname, mol)
results.append((name, value, key))
return results